aboutsummaryrefslogtreecommitdiffstats
path: root/repository
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2020-12-08 14:42:13 +0100
committerMichael Muré <batolettre@gmail.com>2020-12-08 14:42:13 +0100
commitc884d557bf5e0ebdbe6e3b20535af24c2e97d29f (patch)
tree3bb95fcf0d6a2a19e6915cdcc1da4d70bc448bb4 /repository
parent71e1303234ef227851998f08c98c7c69670c9966 (diff)
downloadgit-bug-c884d557bf5e0ebdbe6e3b20535af24c2e97d29f.tar.gz
repo: move bleve there
Diffstat (limited to 'repository')
-rw-r--r--repository/git.go86
-rw-r--r--repository/gogit.go76
-rw-r--r--repository/mock_repo.go47
-rw-r--r--repository/repo.go14
4 files changed, 215 insertions, 8 deletions
diff --git a/repository/git.go b/repository/git.go
index 2348f5d5..993e6cc6 100644
--- a/repository/git.go
+++ b/repository/git.go
@@ -9,6 +9,7 @@ import (
"strings"
"sync"
+ "github.com/blevesearch/bleve"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/osfs"
@@ -30,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
@@ -45,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,
}
@@ -84,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)
@@ -100,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)
@@ -113,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)
@@ -183,6 +201,58 @@ 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)
diff --git a/repository/gogit.go b/repository/gogit.go
index 741982aa..74fe3fc5 100644
--- a/repository/gogit.go
+++ b/repository/gogit.go
@@ -12,6 +12,7 @@ import (
"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"
@@ -33,6 +34,9 @@ type GoGitRepo struct {
clocksMutex sync.Mutex
clocks map[string]lamport.Clock
+ indexesMutex sync.Mutex
+ indexes map[string]bleve.Index
+
keyring Keyring
localStorage billy.Filesystem
}
@@ -58,6 +62,7 @@ func OpenGoGitRepo(path string, clockLoaders []ClockLoader) (*GoGitRepo, error)
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")),
}
@@ -97,6 +102,7 @@ func InitGoGitRepo(path string) (*GoGitRepo, error) {
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
@@ -118,6 +124,7 @@ func InitBareGoGitRepo(path string) (*GoGitRepo, error) {
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
@@ -179,6 +186,17 @@ func isGitDir(path string) (bool, error) {
return true, nil
}
+func (repo *GoGitRepo) 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 *GoGitRepo) LocalConfig() Config {
return newGoGitLocalConfig(repo.r)
@@ -274,6 +292,64 @@ 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)
diff --git a/repository/mock_repo.go b/repository/mock_repo.go
index 02e5010f..8a1724ef 100644
--- a/repository/mock_repo.go
+++ b/repository/mock_repo.go
@@ -7,6 +7,7 @@ import (
"sync"
"github.com/99designs/keyring"
+ "github.com/blevesearch/bleve"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/memfs"
@@ -22,16 +23,20 @@ type mockRepoForTest struct {
*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(),
}
@@ -126,6 +131,48 @@ 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 {
diff --git a/repository/repo.go b/repository/repo.go
index d8fe44e6..eb9296d4 100644
--- a/repository/repo.go
+++ b/repository/repo.go
@@ -4,6 +4,7 @@ package repository
import (
"errors"
+ "github.com/blevesearch/bleve"
"github.com/go-git/go-billy/v5"
"github.com/MichaelMure/git-bug/util/lamport"
@@ -23,6 +24,9 @@ type Repo interface {
RepoCommon
RepoData
RepoStorage
+ RepoBleve
+
+ Close() error
}
type RepoCommonStorage interface {
@@ -69,11 +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