| | package driver |
| |
|
| | import ( |
| | "encoding/json" |
| | "fmt" |
| | "net/url" |
| | "os" |
| | "path/filepath" |
| | ) |
| |
|
| | |
| | type settings struct { |
| | |
| | Configs []namedConfig `json:"configs"` |
| | } |
| |
|
| | |
| | type namedConfig struct { |
| | Name string `json:"name"` |
| | config |
| | } |
| |
|
| | |
| | func settingsFileName() (string, error) { |
| | |
| | dir, err := os.UserConfigDir() |
| | if err != nil { |
| | return "", err |
| | } |
| | return filepath.Join(dir, "pprof", "settings.json"), nil |
| | } |
| |
|
| | |
| | func readSettings(fname string) (*settings, error) { |
| | data, err := os.ReadFile(fname) |
| | if err != nil { |
| | if os.IsNotExist(err) { |
| | return &settings{}, nil |
| | } |
| | return nil, fmt.Errorf("could not read settings: %w", err) |
| | } |
| | settings := &settings{} |
| | if err := json.Unmarshal(data, settings); err != nil { |
| | return nil, fmt.Errorf("could not parse settings: %w", err) |
| | } |
| | for i := range settings.Configs { |
| | settings.Configs[i].resetTransient() |
| | } |
| | return settings, nil |
| | } |
| |
|
| | |
| | func writeSettings(fname string, settings *settings) error { |
| | data, err := json.MarshalIndent(settings, "", " ") |
| | if err != nil { |
| | return fmt.Errorf("could not encode settings: %w", err) |
| | } |
| |
|
| | |
| | |
| | |
| | if err := os.MkdirAll(filepath.Dir(fname), 0700); err != nil { |
| | return fmt.Errorf("failed to create settings directory: %w", err) |
| | } |
| |
|
| | if err := os.WriteFile(fname, data, 0644); err != nil { |
| | return fmt.Errorf("failed to write settings: %w", err) |
| | } |
| | return nil |
| | } |
| |
|
| | |
| | type configMenuEntry struct { |
| | Name string |
| | URL string |
| | Current bool |
| | UserConfig bool |
| | } |
| |
|
| | |
| | func configMenu(fname string, u url.URL) []configMenuEntry { |
| | |
| | configs := []namedConfig{{Name: "Default", config: defaultConfig()}} |
| | if settings, err := readSettings(fname); err == nil { |
| | |
| | configs = append(configs, settings.Configs...) |
| | } |
| |
|
| | |
| | result := make([]configMenuEntry, len(configs)) |
| | lastMatch := -1 |
| | for i, cfg := range configs { |
| | dst, changed := cfg.config.makeURL(u) |
| | if !changed { |
| | lastMatch = i |
| | } |
| | |
| | rel := &url.URL{RawQuery: dst.RawQuery, ForceQuery: true} |
| | result[i] = configMenuEntry{ |
| | Name: cfg.Name, |
| | URL: rel.String(), |
| | UserConfig: (i != 0), |
| | } |
| | } |
| | |
| | if lastMatch >= 0 { |
| | result[lastMatch].Current = true |
| | } |
| | return result |
| | } |
| |
|
| | |
| | func editSettings(fname string, fn func(s *settings) error) error { |
| | settings, err := readSettings(fname) |
| | if err != nil { |
| | return err |
| | } |
| | if err := fn(settings); err != nil { |
| | return err |
| | } |
| | return writeSettings(fname, settings) |
| | } |
| |
|
| | |
| | func setConfig(fname string, request url.URL) error { |
| | q := request.Query() |
| | name := q.Get("config") |
| | if name == "" { |
| | return fmt.Errorf("invalid config name") |
| | } |
| | cfg := currentConfig() |
| | if err := cfg.applyURL(q); err != nil { |
| | return err |
| | } |
| | return editSettings(fname, func(s *settings) error { |
| | for i, c := range s.Configs { |
| | if c.Name == name { |
| | s.Configs[i].config = cfg |
| | return nil |
| | } |
| | } |
| | s.Configs = append(s.Configs, namedConfig{Name: name, config: cfg}) |
| | return nil |
| | }) |
| | } |
| |
|
| | |
| | func removeConfig(fname, config string) error { |
| | return editSettings(fname, func(s *settings) error { |
| | for i, c := range s.Configs { |
| | if c.Name == config { |
| | s.Configs = append(s.Configs[:i], s.Configs[i+1:]...) |
| | return nil |
| | } |
| | } |
| | return fmt.Errorf("config %s not found", config) |
| | }) |
| | } |
| |
|