aboutsummaryrefslogtreecommitdiffstats
path: root/cache
diff options
context:
space:
mode:
authorMike Goldin <mike.goldin@protonmail.ch>2020-10-01 08:16:31 -0400
committerMike Goldin <mike.goldin@protonmail.ch>2020-11-17 08:09:51 -0500
commit0a827af60acc0e37a4c25b4ffc059b4bb020b77c (patch)
tree0b473b8a8badf9214d239eeba9a5ae171d9cfc6f /cache
parentb285c57dc62caac2c1f09e74eeece406b0e7cc00 (diff)
downloadgit-bug-0a827af60acc0e37a4c25b4ffc059b4bb020b77c.tar.gz
Create a search cache index when git-bug starts up if none exists
Diffstat (limited to 'cache')
-rw-r--r--cache/repo_cache.go36
-rw-r--r--cache/repo_cache_bug.go67
2 files changed, 102 insertions, 1 deletions
diff --git a/cache/repo_cache.go b/cache/repo_cache.go
index 4fc88015..632469e4 100644
--- a/cache/repo_cache.go
+++ b/cache/repo_cache.go
@@ -15,6 +15,7 @@ import (
"github.com/MichaelMure/git-bug/identity"
"github.com/MichaelMure/git-bug/repository"
"github.com/MichaelMure/git-bug/util/process"
+ "github.com/blevesearch/bleve"
)
// 1: original format
@@ -56,6 +57,8 @@ type RepoCache struct {
muBug sync.RWMutex
// excerpt of bugs data for all bugs
bugExcerpts map[entity.Id]*BugExcerpt
+ // searchable cache of all bugs
+ searchCache bleve.Index
// bug loaded in memory
bugs map[entity.Id]*BugCache
// loadedBugs is an LRU cache that records which bugs the cache has loaded in
@@ -116,6 +119,7 @@ func (c *RepoCache) load() error {
if err != nil {
return err
}
+
return c.loadIdentityCache()
}
@@ -166,6 +170,11 @@ func (c *RepoCache) Close() error {
c.bugs = make(map[entity.Id]*BugCache)
c.bugExcerpts = nil
+ if c.searchCache != nil {
+ c.searchCache.Close()
+ c.searchCache = nil
+ }
+
lockPath := repoLockFilePath(c.repo)
return os.Remove(lockPath)
}
@@ -198,6 +207,11 @@ func (c *RepoCache) buildCache() error {
allBugs := bug.ReadAllLocal(c.repo)
+ err := c.ensureBleveIndex()
+ if err != nil {
+ return fmt.Errorf("Unable to create or open search cache. Error: %v", err)
+ }
+
for b := range allBugs {
if b.Err != nil {
return b.Err
@@ -205,9 +219,31 @@ func (c *RepoCache) buildCache() error {
snap := b.Bug.Compile()
c.bugExcerpts[b.Bug.Id()] = NewBugExcerpt(b.Bug, &snap)
+
+ if err := c.addBugToSearchIndex(&snap); err != nil {
+ return err
+ }
}
_, _ = fmt.Fprintln(os.Stderr, "Done.")
+
+ return nil
+}
+
+func (c *RepoCache) addBugToSearchIndex(snap *bug.Snapshot) error {
+ searchableBug := struct {
+ Text []string
+ }{}
+
+ for _, comment := range snap.Comments {
+ searchableBug.Text = append(searchableBug.Text, comment.Message)
+ }
+
+ err := c.searchCache.Index(snap.Id().String(), searchableBug)
+ if err != nil {
+ return err
+ }
+
return nil
}
diff --git a/cache/repo_cache_bug.go b/cache/repo_cache_bug.go
index 0c583e0d..dd833b46 100644
--- a/cache/repo_cache_bug.go
+++ b/cache/repo_cache_bug.go
@@ -14,9 +14,13 @@ import (
"github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/query"
"github.com/MichaelMure/git-bug/repository"
+ "github.com/blevesearch/bleve"
)
-const bugCacheFile = "bug-cache"
+const (
+ bugCacheFile = "bug-cache"
+ searchCacheDir = "search-cache"
+)
var errBugNotInCache = errors.New("bug missing from cache")
@@ -24,6 +28,10 @@ func bugCacheFilePath(repo repository.Repo) string {
return path.Join(repo.GetPath(), "git-bug", bugCacheFile)
}
+func searchCacheDirPath(repo repository.Repo) string {
+ return path.Join(repo.GetPath(), "git-bug", searchCacheDir)
+}
+
// bugUpdated is a callback to trigger when the excerpt of a bug changed,
// that is each time a bug is updated
func (c *RepoCache) bugUpdated(id entity.Id) error {
@@ -43,6 +51,10 @@ func (c *RepoCache) bugUpdated(id entity.Id) error {
c.bugExcerpts[id] = NewBugExcerpt(b.bug, b.Snapshot())
c.muBug.Unlock()
+ if err := c.addBugToSearchIndex(b.Snapshot()); err != nil {
+ return err
+ }
+
// we only need to write the bug cache
return c.writeBugCache()
}
@@ -73,10 +85,52 @@ func (c *RepoCache) loadBugCache() error {
return fmt.Errorf("unknown cache format version %v", aux.Version)
}
+ err = c.ensureBleveIndex()
+ if err != nil {
+ return fmt.Errorf("Unable to create or open search cache. Error: %v", err)
+ }
+ count, err := c.searchCache.DocCount()
+ if err != nil {
+ return err
+ }
+ if count != uint64(len(c.bugExcerpts)) {
+ return fmt.Errorf("count mismatch between bleve and bug excerpts")
+ }
+
c.bugExcerpts = aux.Excerpts
return nil
}
+func (c *RepoCache) ensureBleveIndex() error {
+ blevePath := searchCacheDirPath(c.repo)
+
+ // Try to open the bleve index. If there is _any_ error, whether it be that
+ // the bleve index does not exist or is corrupt, handle that by nuking the
+ // bleve index and recreating it.
+ bleveIndex, err := bleve.Open(blevePath)
+ if err != nil {
+ // If the index does not exist, we don't care. We're going to create it
+ // next.
+ _ = os.RemoveAll(blevePath)
+
+ mapping := bleve.NewIndexMapping()
+ dir := searchCacheDirPath(c.repo)
+
+ bleveIndex, err := bleve.New(dir, mapping)
+ if err != nil {
+ return err
+ }
+
+ c.searchCache = bleveIndex
+
+ return nil
+ }
+
+ c.searchCache = bleveIndex
+
+ return nil
+}
+
// write will serialize on disk the bug cache file
func (c *RepoCache) writeBugCache() error {
c.muBug.RLock()
@@ -256,6 +310,17 @@ func (c *RepoCache) QueryBugs(q *query.Query) []entity.Id {
var filtered []*BugExcerpt
+ //if q.Search != nil {
+ // booleanQuery := bleve.NewBooleanQuery()
+ // for _, term := range q.Search {
+ // query := bleve.NewMatchQuery(term)
+ // booleanQuery.AddMust(query)
+ // }
+
+ // search := bleve.NewSearchRequest(booleanQuery)
+ // searchResults, _ := c.searchCache.Search(search)
+ //}
+
for _, excerpt := range c.bugExcerpts {
if matcher.Match(excerpt, c) {
filtered = append(filtered, excerpt)