diff options
author | amine <hilalyamine@gmail.com> | 2019-10-31 15:46:09 +0100 |
---|---|---|
committer | amine <hilalyamine@gmail.com> | 2019-10-31 15:46:09 +0100 |
commit | ab935674a26f2eef5d8014c615b9b5bc1f402135 (patch) | |
tree | 0a1283552ec54460fc3bef464ac26d61fc034066 /repository/git.go | |
parent | 11b4a1beb7e1ab8809515a5ce21e8708fba7f300 (diff) | |
download | git-bug-ab935674a26f2eef5d8014c615b9b5bc1f402135.tar.gz |
repository: config interface and implementation rework
Diffstat (limited to 'repository/git.go')
-rw-r--r-- | repository/git.go | 175 |
1 files changed, 27 insertions, 148 deletions
diff --git a/repository/git.go b/repository/git.go index 93016cd9..5ca81c14 100644 --- a/repository/git.go +++ b/repository/git.go @@ -8,7 +8,6 @@ import ( "os/exec" "path" "regexp" - "strconv" "strings" "github.com/blang/semver" @@ -33,16 +32,26 @@ type GitRepo struct { editClock *lamport.Persisted } +// LocalConfig . +func (repo *GitRepo) LocalConfig() Config { + return NewGitConfig(repo, false) +} + +// GlobalConfig . +func (repo *GitRepo) GlobalConfig() Config { + return NewGitConfig(repo, true) +} + // Run the given git command with the given I/O reader/writers, returning an error if it fails. func (repo *GitRepo) runGitCommandWithIO(stdin io.Reader, stdout, stderr io.Writer, args ...string) error { - repopath:=repo.Path - if repopath==".git" { + repopath := repo.Path + if repopath == ".git" { // seeduvax> trangely the git command sometimes fail for very unknown // reason wihtout this replacement. // observed with rev-list command when git-bug is called from git // hook script, even the same command with same args runs perfectly - // when called directly from the same hook script. - repopath="" + // when called directly from the same hook script. + repopath = "" } // fmt.Printf("[%s] Running git %s\n", repopath, strings.Join(args, " ")) @@ -125,7 +134,7 @@ func NewGitRepo(path string, witnesser Witnesser) (*GitRepo, error) { // InitGitRepo create a new empty git repo at the given path func InitGitRepo(path string) (*GitRepo, error) { - repo := &GitRepo{Path: path+"/.git"} + repo := &GitRepo{Path: path + "/.git"} err := repo.createClocks() if err != nil { return nil, err @@ -197,149 +206,10 @@ func (repo *GitRepo) GetRemotes() (map[string]string, error) { return remotes, nil } -// StoreConfig store a single key/value pair in the config of the repo -func (repo *GitRepo) StoreConfig(key string, value string) error { - _, err := repo.runGitCommand("config", "--replace-all", key, value) - - return err -} - -// ReadConfigs read all key/value pair matching the key prefix -func (repo *GitRepo) ReadConfigs(keyPrefix string) (map[string]string, error) { - stdout, err := repo.runGitCommand("config", "--get-regexp", keyPrefix) - - // / \ - // / ! \ - // ------- - // - // There can be a legitimate error here, but I see no portable way to - // distinguish them from the git error that say "no matching value exist" - if err != nil { - return nil, nil - } - - lines := strings.Split(stdout, "\n") - - result := make(map[string]string, len(lines)) - - for _, line := range lines { - if strings.TrimSpace(line) == "" { - continue - } - - parts := strings.Fields(line) - if len(parts) != 2 { - return nil, fmt.Errorf("bad git config: %s", line) - } - - result[parts[0]] = parts[1] - } - - return result, nil -} - -func (repo *GitRepo) ReadConfigBool(key string) (bool, error) { - val, err := repo.ReadConfigString(key) - if err != nil { - return false, err - } - - return strconv.ParseBool(val) -} - -func (repo *GitRepo) ReadConfigString(key string) (string, error) { - stdout, err := repo.runGitCommand("config", "--get-all", key) - - // / \ - // / ! \ - // ------- - // - // There can be a legitimate error here, but I see no portable way to - // distinguish them from the git error that say "no matching value exist" - if err != nil { - return "", ErrNoConfigEntry - } - - lines := strings.Split(stdout, "\n") - - if len(lines) == 0 { - return "", ErrNoConfigEntry - } - if len(lines) > 1 { - return "", ErrMultipleConfigEntry - } - - return lines[0], nil -} - -func (repo *GitRepo) rmSection(keyPrefix string) error { - _, err := repo.runGitCommand("config", "--remove-section", keyPrefix) - return err -} - -func (repo *GitRepo) unsetAll(keyPrefix string) error { - _, err := repo.runGitCommand("config", "--unset-all", keyPrefix) - return err -} - -// return keyPrefix section -// example: sectionFromKey(a.b.c.d) return a.b.c -func sectionFromKey(keyPrefix string) string { - s := strings.Split(keyPrefix, ".") - if len(s) == 1 { - return keyPrefix - } - - return strings.Join(s[:len(s)-1], ".") -} - -// rmConfigs with git version lesser than 2.18 -func (repo *GitRepo) rmConfigsGitVersionLT218(keyPrefix string) error { - // try to remove key/value pair by key - err := repo.unsetAll(keyPrefix) - if err != nil { - return repo.rmSection(keyPrefix) - } - - m, err := repo.ReadConfigs(sectionFromKey(keyPrefix)) - if err != nil { - return err - } - - // if section doesn't have any left key/value remove the section - if len(m) == 0 { - return repo.rmSection(sectionFromKey(keyPrefix)) - } - - return nil -} - -// RmConfigs remove all key/value pair matching the key prefix -func (repo *GitRepo) RmConfigs(keyPrefix string) error { - // starting from git 2.18.0 sections are automatically deleted when the last existing - // key/value is removed. Before 2.18.0 we should remove the section - // see https://github.com/git/git/blob/master/Documentation/RelNotes/2.18.0.txt#L379 - lt218, err := repo.gitVersionLT218() - if err != nil { - return errors.Wrap(err, "getting git version") - } - - if lt218 { - return repo.rmConfigsGitVersionLT218(keyPrefix) - } - - err = repo.unsetAll(keyPrefix) - if err != nil { - return repo.rmSection(keyPrefix) - } - - return nil -} - -func (repo *GitRepo) gitVersionLT218() (bool, error) { +func (repo *GitRepo) GitVersion() (*semver.Version, error) { versionOut, err := repo.runGitCommand("version") if err != nil { - return false, err + return nil, err } // extract the version and truncate potential bad parts @@ -348,11 +218,20 @@ func (repo *GitRepo) gitVersionLT218() (bool, error) { extracted := r.FindString(versionOut) if extracted == "" { - return false, fmt.Errorf("unreadable git version %s", versionOut) + return nil, fmt.Errorf("unreadable git version %s", versionOut) } version, err := semver.Make(extracted) if err != nil { + return nil, err + } + + return &version, nil +} + +func (repo *GitRepo) gitVersionLT218() (bool, error) { + version, err := repo.GitVersion() + if err != nil { return false, err } |