From d171e11028f5993137a5f83beb7fe002bed866f5 Mon Sep 17 00:00:00 2001 From: Michael Muré Date: Fri, 26 Jun 2020 19:25:17 +0200 Subject: repository: partial impl of a go-git backed Repo --- repository/gogit_config.go | 175 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 repository/gogit_config.go (limited to 'repository/gogit_config.go') diff --git a/repository/gogit_config.go b/repository/gogit_config.go new file mode 100644 index 00000000..0f91b092 --- /dev/null +++ b/repository/gogit_config.go @@ -0,0 +1,175 @@ +package repository + +import ( + "fmt" + "strconv" + "strings" + "time" + + gogit "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/format/config" +) + +var _ Config = &goGitConfig{} + +type goGitConfig struct { + repo *gogit.Repository +} + +func newGoGitConfig(repo *gogit.Repository) *goGitConfig { + return &goGitConfig{repo: repo} +} + +func (ggc *goGitConfig) StoreString(key, value string) error { + cfg, err := ggc.repo.Config() + if err != nil { + return err + } + + split := strings.Split(key, ".") + + switch { + case len(split) <= 1: + return fmt.Errorf("invalid key") + case len(split) == 2: + cfg.Raw.Section(split[0]).SetOption(split[1], value) + default: + section := split[0] + subsection := strings.Join(split[1:len(split)-2], ".") + option := split[len(split)-1] + cfg.Raw.Section(section).Subsection(subsection).SetOption(option, value) + } + + return ggc.repo.SetConfig(cfg) +} + +func (ggc *goGitConfig) StoreTimestamp(key string, value time.Time) error { + return ggc.StoreString(key, strconv.Itoa(int(value.Unix()))) +} + +func (ggc *goGitConfig) StoreBool(key string, value bool) error { + return ggc.StoreString(key, strconv.FormatBool(value)) +} + +func (ggc *goGitConfig) ReadAll(keyPrefix string) (map[string]string, error) { + cfg, err := ggc.repo.Config() + if err != nil { + return nil, err + } + + split := strings.Split(keyPrefix, ".") + + var opts config.Options + + switch { + case len(split) < 1: + return nil, fmt.Errorf("invalid key prefix") + case len(split) == 1: + opts = cfg.Raw.Section(split[0]).Options + default: + section := split[0] + subsection := strings.Join(split[1:len(split)-1], ".") + opts = cfg.Raw.Section(section).Subsection(subsection).Options + } + + if len(opts) == 0 { + return nil, fmt.Errorf("invalid section") + } + + if keyPrefix[len(keyPrefix)-1:] != "." { + keyPrefix += "." + } + + result := make(map[string]string, len(opts)) + for _, opt := range opts { + result[keyPrefix+opt.Key] = opt.Value + } + + return result, nil +} + +func (ggc *goGitConfig) ReadBool(key string) (bool, error) { + val, err := ggc.ReadString(key) + if err != nil { + return false, err + } + + return strconv.ParseBool(val) +} + +func (ggc *goGitConfig) ReadString(key string) (string, error) { + cfg, err := ggc.repo.Config() + if err != nil { + return "", err + } + + split := strings.Split(key, ".") + + // TODO: return ErrNoConfigEntry and ErrMultipleConfigEntry + // Can use forked go-git: https://github.com/go-git/go-git/pull/112 + + switch { + case len(split) <= 1: + return "", fmt.Errorf("invalid key") + case len(split) == 2: + return cfg.Raw.Section(split[0]).Option(split[1]), nil + default: + section := split[0] + subsection := strings.Join(split[1:len(split)-2], ".") + option := split[len(split)-1] + return cfg.Raw.Section(section).Subsection(subsection).Option(option), nil + } +} + +func (ggc *goGitConfig) ReadTimestamp(key string) (time.Time, error) { + value, err := ggc.ReadString(key) + if err != nil { + return time.Time{}, err + } + return ParseTimestamp(value) +} + +func (ggc *goGitConfig) RemoveAll(keyPrefix string) error { + cfg, err := ggc.repo.Config() + if err != nil { + return err + } + + split := strings.Split(keyPrefix, ".") + + // missing in go-git + hasOption := func(options config.Options, key string) bool { + for _, option := range options { + if option.IsKey(key) { + return true + } + } + return false + } + + switch { + case len(split) < 1: + return fmt.Errorf("invalid key prefix") + case len(split) == 1: + if len(cfg.Raw.Section(split[0]).Options) > 0 { + cfg.Raw.RemoveSection(split[0]) + } else { + return fmt.Errorf("invalid key prefix") + } + default: + section := split[0] + rest := strings.Join(split[1:], ".") + + if cfg.Raw.Section(section).HasSubsection(rest) { + cfg.Raw.RemoveSubsection(section, rest) + } else { + if hasOption(cfg.Raw.Section(section).Options, rest) { + cfg.Raw.Section(section).RemoveOption(rest) + } else { + return fmt.Errorf("invalid key prefix") + } + } + } + + return ggc.repo.SetConfig(cfg) +} -- cgit From 9c1087e18d2b4f7d5d9f0e98136933d05ce13827 Mon Sep 17 00:00:00 2001 From: Michael Muré Date: Sun, 30 Aug 2020 11:56:34 +0200 Subject: repository: fix a todo in the gogit repo --- repository/gogit_config.go | 51 ++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 20 deletions(-) (limited to 'repository/gogit_config.go') diff --git a/repository/gogit_config.go b/repository/gogit_config.go index 0f91b092..000658a8 100644 --- a/repository/gogit_config.go +++ b/repository/gogit_config.go @@ -105,19 +105,40 @@ func (ggc *goGitConfig) ReadString(key string) (string, error) { split := strings.Split(key, ".") - // TODO: return ErrNoConfigEntry and ErrMultipleConfigEntry - // Can use forked go-git: https://github.com/go-git/go-git/pull/112 + if len(split) <= 1 { + return "", fmt.Errorf("invalid key") + } + + sectionName := split[0] + if !cfg.Raw.HasSection(sectionName) { + return "", ErrNoConfigEntry + } + section := cfg.Raw.Section(sectionName) switch { - case len(split) <= 1: - return "", fmt.Errorf("invalid key") case len(split) == 2: - return cfg.Raw.Section(split[0]).Option(split[1]), nil + optionName := split[1] + if !section.HasOption(optionName) { + return "", ErrNoConfigEntry + } + if len(section.OptionAll(optionName)) > 1 { + return "", ErrMultipleConfigEntry + } + return section.Option(optionName), nil default: - section := split[0] - subsection := strings.Join(split[1:len(split)-2], ".") - option := split[len(split)-1] - return cfg.Raw.Section(section).Subsection(subsection).Option(option), nil + subsectionName := strings.Join(split[1:len(split)-2], ".") + optionName := split[len(split)-1] + if !section.HasSubsection(subsectionName) { + return "", ErrNoConfigEntry + } + subsection := section.Subsection(subsectionName) + if !subsection.HasOption(optionName) { + return "", ErrNoConfigEntry + } + if len(subsection.OptionAll(optionName)) > 1 { + return "", ErrMultipleConfigEntry + } + return subsection.Option(optionName), nil } } @@ -137,16 +158,6 @@ func (ggc *goGitConfig) RemoveAll(keyPrefix string) error { split := strings.Split(keyPrefix, ".") - // missing in go-git - hasOption := func(options config.Options, key string) bool { - for _, option := range options { - if option.IsKey(key) { - return true - } - } - return false - } - switch { case len(split) < 1: return fmt.Errorf("invalid key prefix") @@ -163,7 +174,7 @@ func (ggc *goGitConfig) RemoveAll(keyPrefix string) error { if cfg.Raw.Section(section).HasSubsection(rest) { cfg.Raw.RemoveSubsection(section, rest) } else { - if hasOption(cfg.Raw.Section(section).Options, rest) { + if cfg.Raw.Section(section).HasOption(rest) { cfg.Raw.Section(section).RemoveOption(rest) } else { return fmt.Errorf("invalid key prefix") -- cgit From 4f172432b1fb983c57aa258a93e24cbb36c8e1fb Mon Sep 17 00:00:00 2001 From: Michael Muré Date: Sun, 27 Sep 2020 19:25:37 +0200 Subject: repo: fix manu bugs in go-git config --- repository/gogit_config.go | 90 +++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 32 deletions(-) (limited to 'repository/gogit_config.go') diff --git a/repository/gogit_config.go b/repository/gogit_config.go index 000658a8..80b0a215 100644 --- a/repository/gogit_config.go +++ b/repository/gogit_config.go @@ -7,7 +7,6 @@ import ( "time" gogit "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing/format/config" ) var _ Config = &goGitConfig{} @@ -35,7 +34,7 @@ func (ggc *goGitConfig) StoreString(key, value string) error { cfg.Raw.Section(split[0]).SetOption(split[1], value) default: section := split[0] - subsection := strings.Join(split[1:len(split)-2], ".") + subsection := strings.Join(split[1:len(split)-1], ".") option := split[len(split)-1] cfg.Raw.Section(section).Subsection(subsection).SetOption(option, value) } @@ -58,33 +57,52 @@ func (ggc *goGitConfig) ReadAll(keyPrefix string) (map[string]string, error) { } split := strings.Split(keyPrefix, ".") - - var opts config.Options + result := make(map[string]string) switch { - case len(split) < 1: - return nil, fmt.Errorf("invalid key prefix") + case keyPrefix == "": + for _, section := range cfg.Raw.Sections { + for _, option := range section.Options { + result[fmt.Sprintf("%s.%s", section.Name, option.Key)] = option.Value + } + for _, subsection := range section.Subsections { + for _, option := range subsection.Options { + result[fmt.Sprintf("%s.%s.%s", section.Name, subsection.Name, option.Key)] = option.Value + } + } + } case len(split) == 1: - opts = cfg.Raw.Section(split[0]).Options + if !cfg.Raw.HasSection(split[0]) { + return nil, fmt.Errorf("invalid section") + } + section := cfg.Raw.Section(split[0]) + for _, option := range section.Options { + result[fmt.Sprintf("%s.%s", section.Name, option.Key)] = option.Value + } + for _, subsection := range section.Subsections { + for _, option := range subsection.Options { + result[fmt.Sprintf("%s.%s.%s", section.Name, subsection.Name, option.Key)] = option.Value + } + } default: - section := split[0] - subsection := strings.Join(split[1:len(split)-1], ".") - opts = cfg.Raw.Section(section).Subsection(subsection).Options + if !cfg.Raw.HasSection(split[0]) { + return nil, fmt.Errorf("invalid section") + } + section := cfg.Raw.Section(split[0]) + rest := strings.Join(split[1:], ".") + for _, subsection := range section.Subsections { + if strings.HasPrefix(subsection.Name, rest) { + for _, option := range subsection.Options { + result[fmt.Sprintf("%s.%s.%s", section.Name, subsection.Name, option.Key)] = option.Value + } + } + } } - if len(opts) == 0 { + if len(result) == 0 { return nil, fmt.Errorf("invalid section") } - if keyPrefix[len(keyPrefix)-1:] != "." { - keyPrefix += "." - } - - result := make(map[string]string, len(opts)) - for _, opt := range opts { - result[keyPrefix+opt.Key] = opt.Value - } - return result, nil } @@ -159,26 +177,34 @@ func (ggc *goGitConfig) RemoveAll(keyPrefix string) error { split := strings.Split(keyPrefix, ".") switch { - case len(split) < 1: - return fmt.Errorf("invalid key prefix") + case keyPrefix == "": + cfg.Raw.Sections = nil + // warning: this does not actually remove everything as go-git config hold + // some entries in multiple places (cfg.User ...) case len(split) == 1: - if len(cfg.Raw.Section(split[0]).Options) > 0 { + if cfg.Raw.HasSection(split[0]) { cfg.Raw.RemoveSection(split[0]) } else { return fmt.Errorf("invalid key prefix") } default: - section := split[0] + if !cfg.Raw.HasSection(split[0]) { + return fmt.Errorf("invalid key prefix") + } + section := cfg.Raw.Section(split[0]) rest := strings.Join(split[1:], ".") - if cfg.Raw.Section(section).HasSubsection(rest) { - cfg.Raw.RemoveSubsection(section, rest) - } else { - if cfg.Raw.Section(section).HasOption(rest) { - cfg.Raw.Section(section).RemoveOption(rest) - } else { - return fmt.Errorf("invalid key prefix") - } + ok := false + if section.HasSubsection(rest) { + section.RemoveSubsection(rest) + ok = true + } + if section.HasOption(rest) { + section.RemoveOption(rest) + ok = true + } + if !ok { + return fmt.Errorf("invalid key prefix") } } -- cgit From eb88f0e4463ea1aef5494314fa2a9607aaa262dd Mon Sep 17 00:00:00 2001 From: Michael Muré Date: Sun, 27 Sep 2020 20:31:09 +0200 Subject: repo: more config related bug fixes --- repository/gogit_config.go | 113 +++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 45 deletions(-) (limited to 'repository/gogit_config.go') diff --git a/repository/gogit_config.go b/repository/gogit_config.go index 80b0a215..7812de76 100644 --- a/repository/gogit_config.go +++ b/repository/gogit_config.go @@ -7,51 +7,40 @@ import ( "time" gogit "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/config" ) var _ Config = &goGitConfig{} type goGitConfig struct { - repo *gogit.Repository + ConfigRead + ConfigWrite } -func newGoGitConfig(repo *gogit.Repository) *goGitConfig { - return &goGitConfig{repo: repo} +func newGoGitLocalConfig(repo *gogit.Repository) *goGitConfig { + return &goGitConfig{ + ConfigRead: &goGitConfigReader{getConfig: repo.Config}, + ConfigWrite: &goGitConfigWriter{repo: repo}, + } } -func (ggc *goGitConfig) StoreString(key, value string) error { - cfg, err := ggc.repo.Config() - if err != nil { - return err +func newGoGitGlobalConfig(repo *gogit.Repository) *goGitConfig { + return &goGitConfig{ + ConfigRead: &goGitConfigReader{getConfig: func() (*config.Config, error) { + return config.LoadConfig(config.GlobalScope) + }}, + ConfigWrite: &configPanicWriter{}, } - - split := strings.Split(key, ".") - - switch { - case len(split) <= 1: - return fmt.Errorf("invalid key") - case len(split) == 2: - cfg.Raw.Section(split[0]).SetOption(split[1], value) - default: - section := split[0] - subsection := strings.Join(split[1:len(split)-1], ".") - option := split[len(split)-1] - cfg.Raw.Section(section).Subsection(subsection).SetOption(option, value) - } - - return ggc.repo.SetConfig(cfg) } -func (ggc *goGitConfig) StoreTimestamp(key string, value time.Time) error { - return ggc.StoreString(key, strconv.Itoa(int(value.Unix()))) -} +var _ ConfigRead = &goGitConfigReader{} -func (ggc *goGitConfig) StoreBool(key string, value bool) error { - return ggc.StoreString(key, strconv.FormatBool(value)) +type goGitConfigReader struct { + getConfig func() (*config.Config, error) } -func (ggc *goGitConfig) ReadAll(keyPrefix string) (map[string]string, error) { - cfg, err := ggc.repo.Config() +func (cr *goGitConfigReader) ReadAll(keyPrefix string) (map[string]string, error) { + cfg, err := cr.getConfig() if err != nil { return nil, err } @@ -73,7 +62,7 @@ func (ggc *goGitConfig) ReadAll(keyPrefix string) (map[string]string, error) { } case len(split) == 1: if !cfg.Raw.HasSection(split[0]) { - return nil, fmt.Errorf("invalid section") + return nil, nil } section := cfg.Raw.Section(split[0]) for _, option := range section.Options { @@ -86,7 +75,7 @@ func (ggc *goGitConfig) ReadAll(keyPrefix string) (map[string]string, error) { } default: if !cfg.Raw.HasSection(split[0]) { - return nil, fmt.Errorf("invalid section") + return nil, nil } section := cfg.Raw.Section(split[0]) rest := strings.Join(split[1:], ".") @@ -99,15 +88,11 @@ func (ggc *goGitConfig) ReadAll(keyPrefix string) (map[string]string, error) { } } - if len(result) == 0 { - return nil, fmt.Errorf("invalid section") - } - return result, nil } -func (ggc *goGitConfig) ReadBool(key string) (bool, error) { - val, err := ggc.ReadString(key) +func (cr *goGitConfigReader) ReadBool(key string) (bool, error) { + val, err := cr.ReadString(key) if err != nil { return false, err } @@ -115,8 +100,8 @@ func (ggc *goGitConfig) ReadBool(key string) (bool, error) { return strconv.ParseBool(val) } -func (ggc *goGitConfig) ReadString(key string) (string, error) { - cfg, err := ggc.repo.Config() +func (cr *goGitConfigReader) ReadString(key string) (string, error) { + cfg, err := cr.getConfig() if err != nil { return "", err } @@ -160,16 +145,54 @@ func (ggc *goGitConfig) ReadString(key string) (string, error) { } } -func (ggc *goGitConfig) ReadTimestamp(key string) (time.Time, error) { - value, err := ggc.ReadString(key) +func (cr *goGitConfigReader) ReadTimestamp(key string) (time.Time, error) { + value, err := cr.ReadString(key) if err != nil { return time.Time{}, err } return ParseTimestamp(value) } -func (ggc *goGitConfig) RemoveAll(keyPrefix string) error { - cfg, err := ggc.repo.Config() +var _ ConfigWrite = &goGitConfigWriter{} + +// Only works for the local config as go-git only support that +type goGitConfigWriter struct { + repo *gogit.Repository +} + +func (cw *goGitConfigWriter) StoreString(key, value string) error { + cfg, err := cw.repo.Config() + if err != nil { + return err + } + + split := strings.Split(key, ".") + + switch { + case len(split) <= 1: + return fmt.Errorf("invalid key") + case len(split) == 2: + cfg.Raw.Section(split[0]).SetOption(split[1], value) + default: + section := split[0] + subsection := strings.Join(split[1:len(split)-1], ".") + option := split[len(split)-1] + cfg.Raw.Section(section).Subsection(subsection).SetOption(option, value) + } + + return cw.repo.SetConfig(cfg) +} + +func (cw *goGitConfigWriter) StoreTimestamp(key string, value time.Time) error { + return cw.StoreString(key, strconv.Itoa(int(value.Unix()))) +} + +func (cw *goGitConfigWriter) StoreBool(key string, value bool) error { + return cw.StoreString(key, strconv.FormatBool(value)) +} + +func (cw *goGitConfigWriter) RemoveAll(keyPrefix string) error { + cfg, err := cw.repo.Config() if err != nil { return err } @@ -208,5 +231,5 @@ func (ggc *goGitConfig) RemoveAll(keyPrefix string) error { } } - return ggc.repo.SetConfig(cfg) + return cw.repo.SetConfig(cfg) } -- cgit