aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2019-05-27 21:18:46 +0200
committerMichael Muré <batolettre@gmail.com>2019-05-27 21:39:55 +0200
commitd564e37b317a2d59a9694d80b03b40e5d36f741f (patch)
treeba6bcdca38286372293b65f3c0b087cf95c066a1
parentc7abac388aadd274d4f23f996a15f8bba90f2a92 (diff)
downloadgit-bug-d564e37b317a2d59a9694d80b03b40e5d36f741f.tar.gz
repository: add ReadConfigBool and ReadConfigString functions
-rw-r--r--cache/repo_cache.go12
-rw-r--r--repository/git.go35
-rw-r--r--repository/git_test.go51
-rw-r--r--repository/mock_repo.go21
-rw-r--r--repository/repo.go14
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
}