diff options
Diffstat (limited to 'cache/repo_cache.go')
-rw-r--r-- | cache/repo_cache.go | 133 |
1 files changed, 104 insertions, 29 deletions
diff --git a/cache/repo_cache.go b/cache/repo_cache.go index e58165d2..c73dbe9f 100644 --- a/cache/repo_cache.go +++ b/cache/repo_cache.go @@ -1,8 +1,12 @@ package cache import ( + "bytes" + "encoding/gob" "fmt" "io" + "os" + "path" "strings" "github.com/MichaelMure/git-bug/bug" @@ -11,39 +15,110 @@ import ( "github.com/MichaelMure/git-bug/util" ) -type RepoCacher interface { - Repository() repository.Repo - ResolveBug(id string) (BugCacher, error) - ResolveBugPrefix(prefix string) (BugCacher, error) - AllBugIds() ([]string, error) - ClearAllBugs() - - // Mutations - NewBug(title string, message string) (BugCacher, error) - NewBugWithFiles(title string, message string, files []util.Hash) (BugCacher, error) - Fetch(remote string) (string, error) - MergeAll(remote string) <-chan bug.MergeResult - Pull(remote string, out io.Writer) error - Push(remote string) (string, error) -} - type RepoCache struct { - repo repository.Repo - bugs map[string]BugCacher + repo repository.Repo + excerpts map[string]BugExcerpt + bugs map[string]*BugCache } -func NewRepoCache(r repository.Repo) RepoCacher { - return &RepoCache{ +func NewRepoCache(r repository.Repo) (*RepoCache, error) { + c := &RepoCache{ repo: r, - bugs: make(map[string]BugCacher), + bugs: make(map[string]*BugCache), + } + + err := c.loadExcerpts() + + if err == nil { + return c, nil } + + c.buildAllExcerpt() + + return c, c.writeExcerpts() } func (c *RepoCache) Repository() repository.Repo { return c.repo } -func (c *RepoCache) ResolveBug(id string) (BugCacher, error) { +// 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 string) error { + b, ok := c.bugs[id] + if !ok { + panic("missing bug in the cache") + } + + c.excerpts[id] = NewBugExcerpt(b.bug, b.Snapshot()) + + return c.writeExcerpts() +} + +// loadExcerpts will try to read from the disk the bug excerpt file +func (c *RepoCache) loadExcerpts() error { + excerptsPath := repoExcerptsFilePath(c.repo) + + f, err := os.Open(excerptsPath) + if err != nil { + return err + } + + decoder := gob.NewDecoder(f) + + var excerpts map[string]BugExcerpt + + err = decoder.Decode(&excerpts) + if err != nil { + return err + } + + c.excerpts = excerpts + return nil +} + +// writeExcerpts will serialize on disk the BugExcerpt array +func (c *RepoCache) writeExcerpts() error { + var data bytes.Buffer + + encoder := gob.NewEncoder(&data) + + err := encoder.Encode(c.excerpts) + if err != nil { + return err + } + + excerptsPath := repoExcerptsFilePath(c.repo) + + f, err := os.Create(excerptsPath) + if err != nil { + return err + } + + _, err = f.Write(data.Bytes()) + if err != nil { + return err + } + + return f.Close() +} + +func repoExcerptsFilePath(repo repository.Repo) string { + return path.Join(repo.GetPath(), ".git", "git-bug", excerptsFile) +} + +func (c *RepoCache) buildAllExcerpt() { + c.excerpts = make(map[string]BugExcerpt) + + allBugs := bug.ReadAllLocalBugs(c.repo) + + for b := range allBugs { + snap := b.Bug.Compile() + c.excerpts[b.Bug.Id()] = NewBugExcerpt(b.Bug, &snap) + } +} + +func (c *RepoCache) ResolveBug(id string) (*BugCache, error) { cached, ok := c.bugs[id] if ok { return cached, nil @@ -54,13 +129,13 @@ func (c *RepoCache) ResolveBug(id string) (BugCacher, error) { return nil, err } - cached = NewBugCache(c.repo, b) + cached = NewBugCache(c, b) c.bugs[id] = cached return cached, nil } -func (c *RepoCache) ResolveBugPrefix(prefix string) (BugCacher, error) { +func (c *RepoCache) ResolveBugPrefix(prefix string) (*BugCache, error) { // preallocate but empty matching := make([]string, 0, 5) @@ -87,7 +162,7 @@ func (c *RepoCache) ResolveBugPrefix(prefix string) (BugCacher, error) { return nil, err } - cached := NewBugCache(c.repo, b) + cached := NewBugCache(c, b) c.bugs[b.Id()] = cached return cached, nil @@ -98,14 +173,14 @@ func (c *RepoCache) AllBugIds() ([]string, error) { } func (c *RepoCache) ClearAllBugs() { - c.bugs = make(map[string]BugCacher) + c.bugs = make(map[string]*BugCache) } -func (c *RepoCache) NewBug(title string, message string) (BugCacher, error) { +func (c *RepoCache) NewBug(title string, message string) (*BugCache, error) { return c.NewBugWithFiles(title, message, nil) } -func (c *RepoCache) NewBugWithFiles(title string, message string, files []util.Hash) (BugCacher, error) { +func (c *RepoCache) NewBugWithFiles(title string, message string, files []util.Hash) (*BugCache, error) { author, err := bug.GetUser(c.repo) if err != nil { return nil, err @@ -121,7 +196,7 @@ func (c *RepoCache) NewBugWithFiles(title string, message string, files []util.H return nil, err } - cached := NewBugCache(c.repo, b) + cached := NewBugCache(c, b) c.bugs[b.Id()] = cached return cached, nil |