diff options
-rw-r--r-- | cache/repo_cache.go | 12 | ||||
-rw-r--r-- | repository/git.go | 35 | ||||
-rw-r--r-- | repository/git_test.go | 51 | ||||
-rw-r--r-- | repository/mock_repo.go | 21 | ||||
-rw-r--r-- | repository/repo.go | 14 |
5 files changed, 133 insertions, 0 deletions
diff --git a/cache/repo_cache.go b/cache/repo_cache.go index 01e5a4a9..dc1889b2 100644 --- a/cache/repo_cache.go +++ b/cache/repo_cache.go @@ -37,6 +37,8 @@ func (e ErrInvalidCacheFormat) Error() string { return e.message } +var _ repository.RepoCommon = &RepoCache{} + // RepoCache is a cache for a Repository. This cache has multiple functions: // // 1. After being loaded, a Bug is kept in memory in the cache, allowing for fast @@ -127,6 +129,16 @@ func (c *RepoCache) ReadConfigs(keyPrefix string) (map[string]string, error) { return c.repo.ReadConfigs(keyPrefix) } +// ReadConfigBool read a single boolean value from the config +func (c *RepoCache) ReadConfigBool(key string) (bool, error) { + return c.repo.ReadConfigBool(key) +} + +// ReadConfigBool read a single string value from the config +func (c *RepoCache) ReadConfigString(key string) (string, error) { + return c.repo.ReadConfigString(key) +} + // RmConfigs remove all key/value pair matching the key prefix func (c *RepoCache) RmConfigs(keyPrefix string) error { return c.repo.RmConfigs(keyPrefix) diff --git a/repository/git.go b/repository/git.go index c982f820..4d6ca19a 100644 --- a/repository/git.go +++ b/repository/git.go @@ -8,6 +8,7 @@ import ( "io" "os/exec" "path" + "strconv" "strings" "github.com/MichaelMure/git-bug/util/git" @@ -202,6 +203,40 @@ func (repo *GitRepo) ReadConfigs(keyPrefix string) (map[string]string, error) { 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 +} + // RmConfigs remove all key/value pair matching the key prefix func (repo *GitRepo) RmConfigs(keyPrefix string) error { _, err := repo.runGitCommand("config", "--unset-all", keyPrefix) diff --git a/repository/git_test.go b/repository/git_test.go new file mode 100644 index 00000000..32634cfb --- /dev/null +++ b/repository/git_test.go @@ -0,0 +1,51 @@ +// Package repository contains helper methods for working with the Git repo. +package repository + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestConfig(t *testing.T) { + repo := CreateTestRepo(false) + defer CleanupTestRepos(t, repo) + + err := repo.StoreConfig("section.key", "value") + assert.NoError(t, err) + + val, err := repo.ReadConfigString("section.key") + assert.Equal(t, "value", val) + + err = repo.StoreConfig("section.true", "true") + assert.NoError(t, err) + + val2, err := repo.ReadConfigBool("section.true") + assert.Equal(t, true, val2) + + configs, err := repo.ReadConfigs("section") + assert.NoError(t, err) + assert.Equal(t, configs, map[string]string{ + "section.key": "value", + "section.true": "true", + }) + + err = repo.RmConfigs("section.true") + assert.NoError(t, err) + + configs, err = repo.ReadConfigs("section") + assert.NoError(t, err) + + assert.Equal(t, configs, map[string]string{ + "section.key": "value", + }) + + _, err = repo.ReadConfigBool("section.true") + assert.Equal(t, ErrNoConfigEntry, err) + + err = repo.RmConfigs("section.key") + assert.NoError(t, err) + + _, err = repo.ReadConfigString("section.key") + assert.Equal(t, ErrNoConfigEntry, err) +} diff --git a/repository/mock_repo.go b/repository/mock_repo.go index 97a4504f..14f5e7b5 100644 --- a/repository/mock_repo.go +++ b/repository/mock_repo.go @@ -3,6 +3,7 @@ package repository import ( "crypto/sha1" "fmt" + "strconv" "strings" "github.com/MichaelMure/git-bug/util/git" @@ -75,6 +76,26 @@ func (r *mockRepoForTest) ReadConfigs(keyPrefix string) (map[string]string, erro return result, nil } +func (r *mockRepoForTest) ReadConfigBool(key string) (bool, error) { + // unlike git, the mock can only store one value for the same key + val, ok := r.config[key] + if !ok { + return false, ErrNoConfigEntry + } + + return strconv.ParseBool(val) +} + +func (r *mockRepoForTest) ReadConfigString(key string) (string, error) { + // unlike git, the mock can only store one value for the same key + val, ok := r.config[key] + if !ok { + return "", ErrNoConfigEntry + } + + return val, nil +} + func (r *mockRepoForTest) RmConfigs(keyPrefix string) error { for key := range r.config { if strings.HasPrefix(key, keyPrefix) { diff --git a/repository/repo.go b/repository/repo.go index 8a66c320..f3c2de6d 100644 --- a/repository/repo.go +++ b/repository/repo.go @@ -3,12 +3,16 @@ package repository import ( "bytes" + "errors" "strings" "github.com/MichaelMure/git-bug/util/git" "github.com/MichaelMure/git-bug/util/lamport" ) +var ErrNoConfigEntry = errors.New("no config entry for the given key") +var ErrMultipleConfigEntry = errors.New("multiple config entry for the given key") + // RepoCommon represent the common function the we want all the repo to implement type RepoCommon interface { // GetPath returns the path to the repo. @@ -29,6 +33,16 @@ type RepoCommon interface { // ReadConfigs read all key/value pair matching the key prefix ReadConfigs(keyPrefix string) (map[string]string, error) + // ReadConfigBool read a single boolean value from the config + // Return ErrNoConfigEntry or ErrMultipleConfigEntry if there is zero or more than one entry + // for this key + ReadConfigBool(key string) (bool, error) + + // ReadConfigBool read a single string value from the config + // Return ErrNoConfigEntry or ErrMultipleConfigEntry if there is zero or more than one entry + // for this key + ReadConfigString(key string) (string, error) + // RmConfigs remove all key/value pair matching the key prefix RmConfigs(keyPrefix string) error } |