cache: provide sorted (id, creation, edit) list of bugs

Michael Muré created

Change summary

cache/bug_excerpt.go      |  4 +-
cache/repo_cache.go       | 55 +++++++++++++++++++++++++++++++++++++++-
commands/ls.go            | 24 ++++++++--------
graphql/resolvers/repo.go |  6 ---
termui/bug_table.go       | 36 ++++++++------------------
5 files changed, 79 insertions(+), 46 deletions(-)

Detailed changes

cache/bug_excerpt.go 🔗

@@ -42,7 +42,7 @@ func init() {
  * Sorting
  */
 
-type BugsByCreationTime []*BugExcerpt
+type BugsByCreationTime []BugExcerpt
 
 func (b BugsByCreationTime) Len() int {
 	return len(b)
@@ -70,7 +70,7 @@ func (b BugsByCreationTime) Swap(i, j int) {
 	b[i], b[j] = b[j], b[i]
 }
 
-type BugsByEditTime []*BugExcerpt
+type BugsByEditTime []BugExcerpt
 
 func (b BugsByEditTime) Len() int {
 	return len(b)

cache/repo_cache.go 🔗

@@ -8,6 +8,7 @@ import (
 	"io/ioutil"
 	"os"
 	"path"
+	"sort"
 	"strconv"
 	"strings"
 
@@ -203,8 +204,58 @@ func (c *RepoCache) ResolveBugPrefix(prefix string) (*BugCache, error) {
 	return cached, nil
 }
 
-func (c *RepoCache) AllBugIds() ([]string, error) {
-	return bug.ListLocalIds(c.repo)
+func (c *RepoCache) AllBugOrderById() []string {
+	result := make([]string, len(c.excerpts))
+
+	i := 0
+	for key := range c.excerpts {
+		result[i] = key
+		i++
+	}
+
+	sort.Strings(result)
+
+	return result
+}
+
+func (c *RepoCache) AllBugsOrderByEdit() []string {
+	excerpts := make([]BugExcerpt, len(c.excerpts))
+
+	i := 0
+	for _, val := range c.excerpts {
+		excerpts[i] = val
+		i++
+	}
+
+	sort.Sort(BugsByEditTime(excerpts))
+
+	result := make([]string, len(excerpts))
+
+	for i, val := range excerpts {
+		result[i] = val.Id
+	}
+
+	return result
+}
+
+func (c *RepoCache) AllBugsOrderByCreation() []string {
+	excerpts := make([]BugExcerpt, len(c.excerpts))
+
+	i := 0
+	for _, val := range c.excerpts {
+		excerpts[i] = val
+		i++
+	}
+
+	sort.Sort(BugsByCreationTime(excerpts))
+
+	result := make([]string, len(excerpts))
+
+	for i, val := range excerpts {
+		result[i] = val.Id
+	}
+
+	return result
 }
 
 // ClearAllBugs clear all bugs kept in memory

commands/ls.go 🔗

@@ -4,26 +4,26 @@ import (
 	"fmt"
 
 	"github.com/MichaelMure/git-bug/bug"
+	"github.com/MichaelMure/git-bug/cache"
 	"github.com/MichaelMure/git-bug/util"
 	"github.com/spf13/cobra"
 )
 
 func runLsBug(cmd *cobra.Command, args []string) error {
-	//backend, err := cache.NewRepoCache(repo)
-	//if err != nil {
-	//	return err
-	//}
-
-	// Todo: read bugs from backend
+	backend, err := cache.NewRepoCache(repo)
+	if err != nil {
+		return err
+	}
 
-	bugs := bug.ReadAllLocalBugs(repo)
+	allIds := backend.AllBugsOrderByCreation()
 
-	for b := range bugs {
-		if b.Err != nil {
-			return b.Err
+	for _, id := range allIds {
+		b, err := backend.ResolveBug(id)
+		if err != nil {
+			return err
 		}
 
-		snapshot := b.Bug.Compile()
+		snapshot := b.Snapshot()
 
 		var author bug.Person
 
@@ -37,7 +37,7 @@ func runLsBug(cmd *cobra.Command, args []string) error {
 		authorFmt := fmt.Sprintf("%-15.15s", author.Name)
 
 		fmt.Printf("%s %s\t%s\t%s\t%s\n",
-			util.Cyan(b.Bug.HumanId()),
+			util.Cyan(b.HumanId()),
 			util.Yellow(snapshot.Status),
 			titleFmt,
 			util.Magenta(authorFmt),

graphql/resolvers/repo.go 🔗

@@ -19,11 +19,7 @@ func (repoResolver) AllBugs(ctx context.Context, obj *models.Repository, after *
 	}
 
 	// Simply pass a []string with the ids to the pagination algorithm
-	source, err := obj.Repo.AllBugIds()
-
-	if err != nil {
-		return models.BugConnection{}, err
-	}
+	source := obj.Repo.AllBugOrderById()
 
 	// The edger create a custom edge holding just the id
 	edger := func(id string, offset int) connections.Edge {

termui/bug_table.go 🔗

@@ -212,22 +212,17 @@ func (bt *bugTable) disable(g *gocui.Gui) error {
 }
 
 func (bt *bugTable) paginate(max int) error {
-	allIds, err := bt.repo.AllBugIds()
-	if err != nil {
-		return err
-	}
+	bt.allIds = bt.repo.AllBugsOrderByCreation()
 
-	bt.allIds = allIds
-
-	return bt.doPaginate(allIds, max)
+	return bt.doPaginate(max)
 }
 
-func (bt *bugTable) doPaginate(allIds []string, max int) error {
+func (bt *bugTable) doPaginate(max int) error {
 	// clamp the cursor
 	bt.pageCursor = maxInt(bt.pageCursor, 0)
-	bt.pageCursor = minInt(bt.pageCursor, len(allIds))
+	bt.pageCursor = minInt(bt.pageCursor, len(bt.allIds))
 
-	nb := minInt(len(allIds)-bt.pageCursor, max)
+	nb := minInt(len(bt.allIds)-bt.pageCursor, max)
 
 	if nb < 0 {
 		bt.bugs = []*cache.BugCache{}
@@ -235,7 +230,7 @@ func (bt *bugTable) doPaginate(allIds []string, max int) error {
 	}
 
 	// slice the data
-	ids := allIds[bt.pageCursor : bt.pageCursor+nb]
+	ids := bt.allIds[bt.pageCursor : bt.pageCursor+nb]
 
 	bt.bugs = make([]*cache.BugCache, len(ids))
 
@@ -360,34 +355,25 @@ func (bt *bugTable) cursorClamp(v *gocui.View) error {
 func (bt *bugTable) nextPage(g *gocui.Gui, v *gocui.View) error {
 	_, max := v.Size()
 
-	allIds, err := bt.repo.AllBugIds()
-	if err != nil {
-		return err
-	}
-
-	bt.allIds = allIds
+	bt.allIds = bt.repo.AllBugsOrderByCreation()
 
-	if bt.pageCursor+max >= len(allIds) {
+	if bt.pageCursor+max >= len(bt.allIds) {
 		return nil
 	}
 
 	bt.pageCursor += max
 
-	return bt.doPaginate(allIds, max)
+	return bt.doPaginate(max)
 }
 
 func (bt *bugTable) previousPage(g *gocui.Gui, v *gocui.View) error {
 	_, max := v.Size()
-	allIds, err := bt.repo.AllBugIds()
-	if err != nil {
-		return err
-	}
 
-	bt.allIds = allIds
+	bt.allIds = bt.repo.AllBugsOrderByCreation()
 
 	bt.pageCursor = maxInt(0, bt.pageCursor-max)
 
-	return bt.doPaginate(allIds, max)
+	return bt.doPaginate(max)
 }
 
 func (bt *bugTable) newBug(g *gocui.Gui, v *gocui.View) error {