aboutsummaryrefslogtreecommitdiffstats
path: root/repository
diff options
context:
space:
mode:
Diffstat (limited to 'repository')
-rw-r--r--repository/git.go132
-rw-r--r--repository/git_testing.go6
-rw-r--r--repository/gogit.go227
-rw-r--r--repository/gogit_config.go6
-rw-r--r--repository/gogit_test.go6
-rw-r--r--repository/gogit_testing.go6
-rw-r--r--repository/keyring.go4
-rw-r--r--repository/mock_repo.go84
-rw-r--r--repository/repo.go36
-rw-r--r--repository/repo_testing.go28
10 files changed, 403 insertions, 132 deletions
diff --git a/repository/git.go b/repository/git.go
index 504cdd89..bc9d8772 100644
--- a/repository/git.go
+++ b/repository/git.go
@@ -4,10 +4,15 @@ package repository
import (
"bytes"
"fmt"
- "path"
+ "os"
+ "path/filepath"
"strings"
"sync"
+ "github.com/blevesearch/bleve"
+ "github.com/go-git/go-billy/v5"
+ "github.com/go-git/go-billy/v5/osfs"
+
"github.com/MichaelMure/git-bug/util/lamport"
)
@@ -26,12 +31,15 @@ type GitRepo struct {
clocksMutex sync.Mutex
clocks map[string]lamport.Clock
+ indexesMutex sync.Mutex
+ indexes map[string]bleve.Index
+
keyring Keyring
}
-// NewGitRepo determines if the given working directory is inside of a git repository,
+// OpenGitRepo determines if the given working directory is inside of a git repository,
// and returns the corresponding GitRepo instance if it is.
-func NewGitRepo(path string, clockLoaders []ClockLoader) (*GitRepo, error) {
+func OpenGitRepo(path string, clockLoaders []ClockLoader) (*GitRepo, error) {
k, err := defaultKeyring()
if err != nil {
return nil, err
@@ -41,6 +49,7 @@ func NewGitRepo(path string, clockLoaders []ClockLoader) (*GitRepo, error) {
gitCli: gitCli{path: path},
path: path,
clocks: make(map[string]lamport.Clock),
+ indexes: make(map[string]bleve.Index),
keyring: k,
}
@@ -80,9 +89,10 @@ func NewGitRepo(path string, clockLoaders []ClockLoader) (*GitRepo, error) {
// InitGitRepo create a new empty git repo at the given path
func InitGitRepo(path string) (*GitRepo, error) {
repo := &GitRepo{
- gitCli: gitCli{path: path},
- path: path + "/.git",
- clocks: make(map[string]lamport.Clock),
+ gitCli: gitCli{path: path},
+ path: path + "/.git",
+ clocks: make(map[string]lamport.Clock),
+ indexes: make(map[string]bleve.Index),
}
_, err := repo.runGitCommand("init", path)
@@ -96,9 +106,10 @@ func InitGitRepo(path string) (*GitRepo, error) {
// InitBareGitRepo create a new --bare empty git repo at the given path
func InitBareGitRepo(path string) (*GitRepo, error) {
repo := &GitRepo{
- gitCli: gitCli{path: path},
- path: path,
- clocks: make(map[string]lamport.Clock),
+ gitCli: gitCli{path: path},
+ path: path,
+ clocks: make(map[string]lamport.Clock),
+ indexes: make(map[string]bleve.Index),
}
_, err := repo.runGitCommand("init", "--bare", path)
@@ -109,6 +120,17 @@ func InitBareGitRepo(path string) (*GitRepo, error) {
return repo, nil
}
+func (repo *GitRepo) Close() error {
+ var firstErr error
+ for _, index := range repo.indexes {
+ err := index.Close()
+ if err != nil && firstErr == nil {
+ firstErr = err
+ }
+ }
+ return firstErr
+}
+
// LocalConfig give access to the repository scoped configuration
func (repo *GitRepo) LocalConfig() Config {
return newGitConfig(repo.gitCli, false)
@@ -174,6 +196,63 @@ func (repo *GitRepo) GetRemotes() (map[string]string, error) {
return remotes, nil
}
+// LocalStorage return a billy.Filesystem giving access to $RepoPath/.git/git-bug
+func (repo *GitRepo) LocalStorage() billy.Filesystem {
+ return osfs.New(repo.path)
+}
+
+// GetBleveIndex return a bleve.Index that can be used to index documents
+func (repo *GitRepo) GetBleveIndex(name string) (bleve.Index, error) {
+ repo.indexesMutex.Lock()
+ defer repo.indexesMutex.Unlock()
+
+ if index, ok := repo.indexes[name]; ok {
+ return index, nil
+ }
+
+ path := filepath.Join(repo.path, "indexes", name)
+
+ index, err := bleve.Open(path)
+ if err == nil {
+ repo.indexes[name] = index
+ return index, nil
+ }
+
+ err = os.MkdirAll(path, os.ModeDir)
+ if err != nil {
+ return nil, err
+ }
+
+ mapping := bleve.NewIndexMapping()
+ mapping.DefaultAnalyzer = "en"
+
+ index, err = bleve.New(path, mapping)
+ if err != nil {
+ return nil, err
+ }
+
+ repo.indexes[name] = index
+
+ return index, nil
+}
+
+// ClearBleveIndex will wipe the given index
+func (repo *GitRepo) ClearBleveIndex(name string) error {
+ repo.indexesMutex.Lock()
+ defer repo.indexesMutex.Unlock()
+
+ path := filepath.Join(repo.path, "indexes", name)
+
+ err := os.RemoveAll(path)
+ if err != nil {
+ return err
+ }
+
+ delete(repo.indexes, name)
+
+ return nil
+}
+
// FetchRefs fetch git refs from a remote
func (repo *GitRepo) FetchRefs(remote, refSpec string) (string, error) {
stdout, err := repo.runGitCommand("fetch", remote, refSpec)
@@ -358,6 +437,9 @@ func (repo *GitRepo) GetTreeHash(commit Hash) (Hash, error) {
// GetOrCreateClock return a Lamport clock stored in the Repo.
// If the clock doesn't exist, it's created.
func (repo *GitRepo) GetOrCreateClock(name string) (lamport.Clock, error) {
+ repo.clocksMutex.Lock()
+ defer repo.clocksMutex.Unlock()
+
c, err := repo.getClock(name)
if err == nil {
return c, nil
@@ -366,12 +448,7 @@ func (repo *GitRepo) GetOrCreateClock(name string) (lamport.Clock, error) {
return nil, err
}
- repo.clocksMutex.Lock()
- defer repo.clocksMutex.Unlock()
-
- p := path.Join(repo.path, clockPath, name+"-clock")
-
- c, err = lamport.NewPersistedClock(p)
+ c, err = lamport.NewPersistedClock(repo.LocalStorage(), name+"-clock")
if err != nil {
return nil, err
}
@@ -381,16 +458,11 @@ func (repo *GitRepo) GetOrCreateClock(name string) (lamport.Clock, error) {
}
func (repo *GitRepo) getClock(name string) (lamport.Clock, error) {
- repo.clocksMutex.Lock()
- defer repo.clocksMutex.Unlock()
-
if c, ok := repo.clocks[name]; ok {
return c, nil
}
- p := path.Join(repo.path, clockPath, name+"-clock")
-
- c, err := lamport.LoadPersistedClock(p)
+ c, err := lamport.LoadPersistedClock(repo.LocalStorage(), name+"-clock")
if err == nil {
repo.clocks[name] = c
return c, nil
@@ -408,3 +480,21 @@ func (repo *GitRepo) AddRemote(name string, url string) error {
return err
}
+
+// GetLocalRemote return the URL to use to add this repo as a local remote
+func (repo *GitRepo) GetLocalRemote() string {
+ return repo.path
+}
+
+// EraseFromDisk delete this repository entirely from the disk
+func (repo *GitRepo) EraseFromDisk() error {
+ err := repo.Close()
+ if err != nil {
+ return err
+ }
+
+ path := filepath.Clean(strings.TrimSuffix(repo.path, string(filepath.Separator)+".git"))
+
+ // fmt.Println("Cleaning repo:", path)
+ return os.RemoveAll(path)
+}
diff --git a/repository/git_testing.go b/repository/git_testing.go
index 874cc86c..2168d53e 100644
--- a/repository/git_testing.go
+++ b/repository/git_testing.go
@@ -48,14 +48,12 @@ func SetupReposAndRemote() (repoA, repoB, remote TestedRepo) {
repoB = CreateGoGitTestRepo(false)
remote = CreateGoGitTestRepo(true)
- remoteAddr := "file://" + remote.GetPath()
-
- err := repoA.AddRemote("origin", remoteAddr)
+ err := repoA.AddRemote("origin", remote.GetLocalRemote())
if err != nil {
log.Fatal(err)
}
- err = repoB.AddRemote("origin", remoteAddr)
+ err = repoB.AddRemote("origin", remote.GetLocalRemote())
if err != nil {
log.Fatal(err)
}
diff --git a/repository/gogit.go b/repository/gogit.go
index c59409d4..bdac259d 100644
--- a/repository/gogit.go
+++ b/repository/gogit.go
@@ -6,13 +6,15 @@ import (
"io/ioutil"
"os"
"os/exec"
- stdpath "path"
"path/filepath"
"sort"
"strings"
"sync"
"time"
+ "github.com/blevesearch/bleve"
+ "github.com/go-git/go-billy/v5"
+ "github.com/go-git/go-billy/v5/osfs"
gogit "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
@@ -23,6 +25,7 @@ import (
)
var _ ClockedRepo = &GoGitRepo{}
+var _ TestedRepo = &GoGitRepo{}
type GoGitRepo struct {
r *gogit.Repository
@@ -31,10 +34,15 @@ type GoGitRepo struct {
clocksMutex sync.Mutex
clocks map[string]lamport.Clock
- keyring Keyring
+ indexesMutex sync.Mutex
+ indexes map[string]bleve.Index
+
+ keyring Keyring
+ localStorage billy.Filesystem
}
-func NewGoGitRepo(path string, clockLoaders []ClockLoader) (*GoGitRepo, error) {
+// OpenGoGitRepo open an already existing repo at the given path
+func OpenGoGitRepo(path string, clockLoaders []ClockLoader) (*GoGitRepo, error) {
path, err := detectGitPath(path)
if err != nil {
return nil, err
@@ -51,10 +59,12 @@ func NewGoGitRepo(path string, clockLoaders []ClockLoader) (*GoGitRepo, error) {
}
repo := &GoGitRepo{
- r: r,
- path: path,
- clocks: make(map[string]lamport.Clock),
- keyring: k,
+ r: r,
+ path: path,
+ clocks: make(map[string]lamport.Clock),
+ indexes: make(map[string]bleve.Index),
+ keyring: k,
+ localStorage: osfs.New(filepath.Join(path, "git-bug")),
}
for _, loader := range clockLoaders {
@@ -76,6 +86,50 @@ func NewGoGitRepo(path string, clockLoaders []ClockLoader) (*GoGitRepo, error) {
return repo, nil
}
+// InitGoGitRepo create a new empty git repo at the given path
+func InitGoGitRepo(path string) (*GoGitRepo, error) {
+ r, err := gogit.PlainInit(path, false)
+ if err != nil {
+ return nil, err
+ }
+
+ k, err := defaultKeyring()
+ if err != nil {
+ return nil, err
+ }
+
+ return &GoGitRepo{
+ r: r,
+ path: filepath.Join(path, ".git"),
+ clocks: make(map[string]lamport.Clock),
+ indexes: make(map[string]bleve.Index),
+ keyring: k,
+ localStorage: osfs.New(filepath.Join(path, ".git", "git-bug")),
+ }, nil
+}
+
+// InitBareGoGitRepo create a new --bare empty git repo at the given path
+func InitBareGoGitRepo(path string) (*GoGitRepo, error) {
+ r, err := gogit.PlainInit(path, true)
+ if err != nil {
+ return nil, err
+ }
+
+ k, err := defaultKeyring()
+ if err != nil {
+ return nil, err
+ }
+
+ return &GoGitRepo{
+ r: r,
+ path: path,
+ clocks: make(map[string]lamport.Clock),
+ indexes: make(map[string]bleve.Index),
+ keyring: k,
+ localStorage: osfs.New(filepath.Join(path, "git-bug")),
+ }, nil
+}
+
func detectGitPath(path string) (string, error) {
// normalize the path
path, err := filepath.Abs(path)
@@ -84,12 +138,12 @@ func detectGitPath(path string) (string, error) {
}
for {
- fi, err := os.Stat(stdpath.Join(path, ".git"))
+ fi, err := os.Stat(filepath.Join(path, ".git"))
if err == nil {
if !fi.IsDir() {
return "", fmt.Errorf(".git exist but is not a directory")
}
- return stdpath.Join(path, ".git"), nil
+ return filepath.Join(path, ".git"), nil
}
if !os.IsNotExist(err) {
// unknown error
@@ -117,7 +171,7 @@ func isGitDir(path string) (bool, error) {
markers := []string{"HEAD", "objects", "refs"}
for _, marker := range markers {
- _, err := os.Stat(stdpath.Join(path, marker))
+ _, err := os.Stat(filepath.Join(path, marker))
if err == nil {
continue
}
@@ -132,44 +186,15 @@ func isGitDir(path string) (bool, error) {
return true, nil
}
-// InitGoGitRepo create a new empty git repo at the given path
-func InitGoGitRepo(path string) (*GoGitRepo, error) {
- r, err := gogit.PlainInit(path, false)
- if err != nil {
- return nil, err
- }
-
- k, err := defaultKeyring()
- if err != nil {
- return nil, err
- }
-
- return &GoGitRepo{
- r: r,
- path: path + "/.git",
- clocks: make(map[string]lamport.Clock),
- keyring: k,
- }, nil
-}
-
-// InitBareGoGitRepo create a new --bare empty git repo at the given path
-func InitBareGoGitRepo(path string) (*GoGitRepo, error) {
- r, err := gogit.PlainInit(path, true)
- if err != nil {
- return nil, err
- }
-
- k, err := defaultKeyring()
- if err != nil {
- return nil, err
+func (repo *GoGitRepo) Close() error {
+ var firstErr error
+ for _, index := range repo.indexes {
+ err := index.Close()
+ if err != nil && firstErr == nil {
+ firstErr = err
+ }
}
-
- return &GoGitRepo{
- r: r,
- path: path,
- clocks: make(map[string]lamport.Clock),
- keyring: k,
- }, nil
+ return firstErr
}
// LocalConfig give access to the repository scoped configuration
@@ -179,10 +204,7 @@ func (repo *GoGitRepo) LocalConfig() Config {
// GlobalConfig give access to the global scoped configuration
func (repo *GoGitRepo) GlobalConfig() Config {
- // TODO: replace that with go-git native implementation once it's supported
- // see: https://github.com/go-git/go-git
- // see: https://github.com/src-d/go-git/issues/760
- return newGoGitGlobalConfig(repo.r)
+ return newGoGitGlobalConfig()
}
// AnyConfig give access to a merged local/global configuration
@@ -195,11 +217,6 @@ func (repo *GoGitRepo) Keyring() Keyring {
return repo.keyring
}
-// GetPath returns the path to the repo.
-func (repo *GoGitRepo) GetPath() string {
- return repo.path
-}
-
// GetUserName returns the name the the user has used to configure git
func (repo *GoGitRepo) GetUserName() (string, error) {
return repo.AnyConfig().ReadString("user.name")
@@ -270,6 +287,69 @@ func (repo *GoGitRepo) GetRemotes() (map[string]string, error) {
return result, nil
}
+// LocalStorage return a billy.Filesystem giving access to $RepoPath/.git/git-bug
+func (repo *GoGitRepo) LocalStorage() billy.Filesystem {
+ return repo.localStorage
+}
+
+// GetBleveIndex return a bleve.Index that can be used to index documents
+func (repo *GoGitRepo) GetBleveIndex(name string) (bleve.Index, error) {
+ repo.indexesMutex.Lock()
+ defer repo.indexesMutex.Unlock()
+
+ if index, ok := repo.indexes[name]; ok {
+ return index, nil
+ }
+
+ path := filepath.Join(repo.path, "git-bug", "indexes", name)
+
+ index, err := bleve.Open(path)
+ if err == nil {
+ repo.indexes[name] = index
+ return index, nil
+ }
+
+ err = os.MkdirAll(path, os.ModePerm)
+ if err != nil {
+ return nil, err
+ }
+
+ mapping := bleve.NewIndexMapping()
+ mapping.DefaultAnalyzer = "en"
+
+ index, err = bleve.New(path, mapping)
+ if err != nil {
+ return nil, err
+ }
+
+ repo.indexes[name] = index
+
+ return index, nil
+}
+
+// ClearBleveIndex will wipe the given index
+func (repo *GoGitRepo) ClearBleveIndex(name string) error {
+ repo.indexesMutex.Lock()
+ defer repo.indexesMutex.Unlock()
+
+ path := filepath.Join(repo.path, "indexes", name)
+
+ err := os.RemoveAll(path)
+ if err != nil {
+ return err
+ }
+
+ if index, ok := repo.indexes[name]; ok {
+ err = index.Close()
+ if err != nil {
+ return err
+ }
+ delete(repo.indexes, name)
+ }
+
+ return nil
+}
+
// FetchRefs fetch git refs from a remote
func (repo *GoGitRepo) FetchRefs(remote string, refSpec string) (string, error) {
buf := bytes.NewBuffer(nil)
@@ -600,6 +680,9 @@ func (repo *GoGitRepo) ListCommits(ref string) ([]Hash, error) {
// GetOrCreateClock return a Lamport clock stored in the Repo.
// If the clock doesn't exist, it's created.
func (repo *GoGitRepo) GetOrCreateClock(name string) (lamport.Clock, error) {
+ repo.clocksMutex.Lock()
+ defer repo.clocksMutex.Unlock()
+
c, err := repo.getClock(name)
if err == nil {
return c, nil
@@ -608,12 +691,7 @@ func (repo *GoGitRepo) GetOrCreateClock(name string) (lamport.Clock, error) {
return nil, err
}
- repo.clocksMutex.Lock()
- defer repo.clocksMutex.Unlock()
-
- p := stdpath.Join(repo.path, clockPath, name+"-clock")
-
- c, err = lamport.NewPersistedClock(p)
+ c, err = lamport.NewPersistedClock(repo.localStorage, name+"-clock")
if err != nil {
return nil, err
}
@@ -623,16 +701,11 @@ func (repo *GoGitRepo) GetOrCreateClock(name string) (lamport.Clock, error) {
}
func (repo *GoGitRepo) getClock(name string) (lamport.Clock, error) {
- repo.clocksMutex.Lock()
- defer repo.clocksMutex.Unlock()
-
if c, ok := repo.clocks[name]; ok {
return c, nil
}
- p := stdpath.Join(repo.path, clockPath, name+"-clock")
-
- c, err := lamport.LoadPersistedClock(p)
+ c, err := lamport.LoadPersistedClock(repo.localStorage, name+"-clock")
if err == nil {
repo.clocks[name] = c
return c, nil
@@ -653,3 +726,21 @@ func (repo *GoGitRepo) AddRemote(name string, url string) error {
return err
}
+
+// GetLocalRemote return the URL to use to add this repo as a local remote
+func (repo *GoGitRepo) GetLocalRemote() string {
+ return repo.path
+}
+
+// EraseFromDisk delete this repository entirely from the disk
+func (repo *GoGitRepo) EraseFromDisk() error {
+ err := repo.Close()
+ if err != nil {
+ return err
+ }
+
+ path := filepath.Clean(strings.TrimSuffix(repo.path, string(filepath.Separator)+".git"))
+
+ // fmt.Println("Cleaning repo:", path)
+ return os.RemoveAll(path)
+}
diff --git a/repository/gogit_config.go b/repository/gogit_config.go
index 2f9a4cc3..ba61adca 100644
--- a/repository/gogit_config.go
+++ b/repository/gogit_config.go
@@ -24,7 +24,11 @@ func newGoGitLocalConfig(repo *gogit.Repository) *goGitConfig {
}
}
-func newGoGitGlobalConfig(repo *gogit.Repository) *goGitConfig {
+func newGoGitGlobalConfig() *goGitConfig {
+ // TODO: replace that with go-git native implementation once it's supported
+ // see: https://github.com/go-git/go-git
+ // see: https://github.com/src-d/go-git/issues/760
+
return &goGitConfig{
ConfigRead: &goGitConfigReader{getConfig: func() (*config.Config, error) {
return config.LoadConfig(config.GlobalScope)
diff --git a/repository/gogit_test.go b/repository/gogit_test.go
index fba990d3..a2bb49b9 100644
--- a/repository/gogit_test.go
+++ b/repository/gogit_test.go
@@ -19,7 +19,7 @@ func TestNewGoGitRepo(t *testing.T) {
_, err = InitGoGitRepo(plainRoot)
require.NoError(t, err)
- plainGitDir := path.Join(plainRoot, ".git")
+ plainGitDir := filepath.Join(plainRoot, ".git")
// Bare
bareRoot, err := ioutil.TempDir("", "")
@@ -52,13 +52,13 @@ func TestNewGoGitRepo(t *testing.T) {
}
for i, tc := range tests {
- r, err := NewGoGitRepo(tc.inPath, nil)
+ r, err := OpenGoGitRepo(tc.inPath, nil)
if tc.err {
require.Error(t, err, i)
} else {
require.NoError(t, err, i)
- assert.Equal(t, filepath.ToSlash(tc.outPath), filepath.ToSlash(r.GetPath()), i)
+ assert.Equal(t, filepath.ToSlash(tc.outPath), filepath.ToSlash(r.path), i)
}
}
}
diff --git a/repository/gogit_testing.go b/repository/gogit_testing.go
index f20ff6be..a8bff41e 100644
--- a/repository/gogit_testing.go
+++ b/repository/gogit_testing.go
@@ -42,14 +42,12 @@ func SetupGoGitReposAndRemote() (repoA, repoB, remote TestedRepo) {
repoB = CreateGoGitTestRepo(false)
remote = CreateGoGitTestRepo(true)
- remoteAddr := "file://" + remote.GetPath()
-
- err := repoA.AddRemote("origin", remoteAddr)
+ err := repoA.AddRemote("origin", remote.GetLocalRemote())
if err != nil {
log.Fatal(err)
}
- err = repoB.AddRemote("origin", remoteAddr)
+ err = repoB.AddRemote("origin", remote.GetLocalRemote())
if err != nil {
log.Fatal(err)
}
diff --git a/repository/keyring.go b/repository/keyring.go
index f690b0b3..4cb3c9ff 100644
--- a/repository/keyring.go
+++ b/repository/keyring.go
@@ -2,7 +2,7 @@ package repository
import (
"os"
- "path"
+ "path/filepath"
"github.com/99designs/keyring"
)
@@ -38,7 +38,7 @@ func defaultKeyring() (Keyring, error) {
ServiceName: "git-bug",
// Fallback encrypted file
- FileDir: path.Join(ucd, "git-bug", "keyring"),
+ FileDir: filepath.Join(ucd, "git-bug", "keyring"),
// As we write the file in the user's config directory, this file should already be protected by the OS against
// other user's access. We actually don't terribly need to protect it further and a password prompt across all
// UI's would be a pain. Therefore we use here a constant password so the file will be unreadable by generic file
diff --git a/repository/mock_repo.go b/repository/mock_repo.go
index 628939aa..8a1724ef 100644
--- a/repository/mock_repo.go
+++ b/repository/mock_repo.go
@@ -4,8 +4,12 @@ import (
"crypto/sha1"
"fmt"
"strings"
+ "sync"
"github.com/99designs/keyring"
+ "github.com/blevesearch/bleve"
+ "github.com/go-git/go-billy/v5"
+ "github.com/go-git/go-billy/v5/memfs"
"github.com/MichaelMure/git-bug/util/lamport"
)
@@ -18,15 +22,21 @@ type mockRepoForTest struct {
*mockRepoConfig
*mockRepoKeyring
*mockRepoCommon
+ *mockRepoStorage
+ *mockRepoBleve
*mockRepoData
*mockRepoClock
}
+func (m *mockRepoForTest) Close() error { return nil }
+
func NewMockRepoForTest() *mockRepoForTest {
return &mockRepoForTest{
mockRepoConfig: NewMockRepoConfig(),
mockRepoKeyring: NewMockRepoKeyring(),
mockRepoCommon: NewMockRepoCommon(),
+ mockRepoStorage: NewMockRepoStorage(),
+ mockRepoBleve: newMockRepoBleve(),
mockRepoData: NewMockRepoData(),
mockRepoClock: NewMockRepoClock(),
}
@@ -86,11 +96,6 @@ func NewMockRepoCommon() *mockRepoCommon {
return &mockRepoCommon{}
}
-// GetPath returns the path to the repo.
-func (r *mockRepoCommon) GetPath() string {
- return "~/mockRepo/"
-}
-
func (r *mockRepoCommon) GetUserName() (string, error) {
return "René Descartes", nil
}
@@ -112,6 +117,62 @@ func (r *mockRepoCommon) GetRemotes() (map[string]string, error) {
}, nil
}
+var _ RepoStorage = &mockRepoStorage{}
+
+type mockRepoStorage struct {
+ localFs billy.Filesystem
+}
+
+func NewMockRepoStorage() *mockRepoStorage {
+ return &mockRepoStorage{localFs: memfs.New()}
+}
+
+func (m *mockRepoStorage) LocalStorage() billy.Filesystem {
+ return m.localFs
+}
+
+var _ RepoBleve = &mockRepoBleve{}
+
+type mockRepoBleve struct {
+ indexesMutex sync.Mutex
+ indexes map[string]bleve.Index
+}
+
+func newMockRepoBleve() *mockRepoBleve {
+ return &mockRepoBleve{
+ indexes: make(map[string]bleve.Index),
+ }
+}
+
+func (m *mockRepoBleve) GetBleveIndex(name string) (bleve.Index, error) {
+ m.indexesMutex.Lock()
+ defer m.indexesMutex.Unlock()
+
+ if index, ok := m.indexes[name]; ok {
+ return index, nil
+ }
+
+ mapping := bleve.NewIndexMapping()
+ mapping.DefaultAnalyzer = "en"
+
+ index, err := bleve.NewMemOnly(mapping)
+ if err != nil {
+ return nil, err
+ }
+
+ m.indexes[name] = index
+
+ return index, nil
+}
+
+func (m *mockRepoBleve) ClearBleveIndex(name string) error {
+ m.indexesMutex.Lock()
+ defer m.indexesMutex.Unlock()
+
+ delete(m.indexes, name)
+ return nil
+}
+
var _ RepoData = &mockRepoData{}
type commit struct {
@@ -314,7 +375,17 @@ func (r *mockRepoData) AddRemote(name string, url string) error {
panic("implement me")
}
+func (m mockRepoForTest) GetLocalRemote() string {
+ panic("implement me")
+}
+
+func (m mockRepoForTest) EraseFromDisk() error {
+ // nothing to do
+ return nil
+}
+
type mockRepoClock struct {
+ mu sync.Mutex
clocks map[string]lamport.Clock
}
@@ -325,6 +396,9 @@ func NewMockRepoClock() *mockRepoClock {
}
func (r *mockRepoClock) GetOrCreateClock(name string) (lamport.Clock, error) {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+
if c, ok := r.clocks[name]; ok {
return c, nil
}
diff --git a/repository/repo.go b/repository/repo.go
index 4b45a1c5..eb9296d4 100644
--- a/repository/repo.go
+++ b/repository/repo.go
@@ -4,6 +4,9 @@ package repository
import (
"errors"
+ "github.com/blevesearch/bleve"
+ "github.com/go-git/go-billy/v5"
+
"github.com/MichaelMure/git-bug/util/lamport"
)
@@ -20,6 +23,15 @@ type Repo interface {
RepoKeyring
RepoCommon
RepoData
+ RepoStorage
+ RepoBleve
+
+ Close() error
+}
+
+type RepoCommonStorage interface {
+ RepoCommon
+ RepoStorage
}
// ClockedRepo is a Repo that also has Lamport clocks
@@ -48,9 +60,6 @@ type RepoKeyring interface {
// RepoCommon represent the common function the we want all the repo to implement
type RepoCommon interface {
- // GetPath returns the path to the repo.
- GetPath() string
-
// GetUserName returns the name the the user has used to configure git
GetUserName() (string, error)
@@ -64,6 +73,21 @@ type RepoCommon interface {
GetRemotes() (map[string]string, error)
}
+// RepoStorage give access to the filesystem
+type RepoStorage interface {
+ // LocalStorage return a billy.Filesystem giving access to $RepoPath/.git/git-bug
+ LocalStorage() billy.Filesystem
+}
+
+// RepoBleve give access to Bleve to implement full-text search indexes.
+type RepoBleve interface {
+ // GetBleveIndex return a bleve.Index that can be used to index documents
+ GetBleveIndex(name string) (bleve.Index, error)
+
+ // ClearBleveIndex will wipe the given index
+ ClearBleveIndex(name string) error
+}
+
// RepoData give access to the git data storage
type RepoData interface {
// FetchRefs fetch git refs from a remote
@@ -145,4 +169,10 @@ type TestedRepo interface {
type repoTest interface {
// AddRemote add a new remote to the repository
AddRemote(name string, url string) error
+
+ // GetLocalRemote return the URL to use to add this repo as a local remote
+ GetLocalRemote() string
+
+ // EraseFromDisk delete this repository entirely from the disk
+ EraseFromDisk() error
}
diff --git a/repository/repo_testing.go b/repository/repo_testing.go
index 41b3609e..c0e1fa79 100644
--- a/repository/repo_testing.go
+++ b/repository/repo_testing.go
@@ -3,8 +3,6 @@ package repository
import (
"log"
"math/rand"
- "os"
- "strings"
"testing"
"github.com/stretchr/testify/require"
@@ -15,25 +13,13 @@ import (
func CleanupTestRepos(repos ...Repo) {
var firstErr error
for _, repo := range repos {
- path := repo.GetPath()
- if strings.HasSuffix(path, "/.git") {
- // for a normal repository (not --bare), we want to remove everything
- // including the parent directory where files are checked out
- path = strings.TrimSuffix(path, "/.git")
-
- // Testing non-bare repo should also check path is
- // only .git (i.e. ./.git), but doing so, we should
- // try to remove the current directory and hav some
- // trouble. In the present case, this case should not
- // occur.
- // TODO consider warning or error when path == ".git"
- }
- // fmt.Println("Cleaning repo:", path)
- err := os.RemoveAll(path)
- if err != nil {
- log.Println(err)
- if firstErr == nil {
- firstErr = err
+ if repo, ok := repo.(TestedRepo); ok {
+ err := repo.EraseFromDisk()
+ if err != nil {
+ log.Println(err)
+ if firstErr == nil {
+ firstErr = err
+ }
}
}
}