cache: refactor to handle bug changes during Pull

Michael Muré created

Change summary

bug/bug.go          |  6 +-----
bug/bug_actions.go  | 43 +++++++++++++++++++++++--------------------
cache/repo_cache.go | 38 ++++++++++++++++++++++++++++++++++++--
commands/pull.go    |  2 +-
termui/bug_table.go |  2 +-
5 files changed, 62 insertions(+), 29 deletions(-)

Detailed changes

bug/bug.go 🔗

@@ -571,12 +571,8 @@ func (bug *Bug) Id() string {
 
 // HumanId return the Bug identifier truncated for human consumption
 func (bug *Bug) HumanId() string {
-	return formatHumanId(bug.Id())
-}
-
-func formatHumanId(id string) string {
 	format := fmt.Sprintf("%%.%ds", humanIdLength)
-	return fmt.Sprintf(format, id)
+	return fmt.Sprintf(format, bug.Id())
 }
 
 // CreateLamportTime return the Lamport time of creation

bug/bug_actions.go 🔗

@@ -45,29 +45,32 @@ func Pull(repo repository.Repo, remote string) error {
 }
 
 type MergeResult struct {
+	// Err is set when a terminal error occur in the process
 	Err error
 
-	Id      string
-	HumanId string
-	Status  string
+	Id     string
+	Status string
+	Bug    *Bug
 }
 
-func newMergeError(id string, err error) MergeResult {
+func newMergeError(err error, id string) MergeResult {
 	return MergeResult{
-		Id:      id,
-		HumanId: formatHumanId(id),
-		Status:  err.Error(),
+		Err: err,
+		Id:  id,
 	}
 }
 
-func newMergeStatus(id string, status string) MergeResult {
+func newMergeStatus(status string, id string, bug *Bug) MergeResult {
 	return MergeResult{
-		Id:      id,
-		HumanId: formatHumanId(id),
-		Status:  status,
+		Id:     id,
+		Status: status,
+
+		// Bug is not set for an invalid merge result
+		Bug: bug,
 	}
 }
 
+// MergeAll will merge all the available remote bug
 func MergeAll(repo repository.Repo, remote string) <-chan MergeResult {
 	out := make(chan MergeResult)
 
@@ -89,13 +92,13 @@ func MergeAll(repo repository.Repo, remote string) <-chan MergeResult {
 			remoteBug, err := readBug(repo, remoteRef)
 
 			if err != nil {
-				out <- newMergeError(id, err)
+				out <- newMergeError(err, id)
 				continue
 			}
 
 			// Check for error in remote data
 			if !remoteBug.IsValid() {
-				out <- newMergeStatus(id, MsgMergeInvalid)
+				out <- newMergeStatus(MsgMergeInvalid, id, nil)
 				continue
 			}
 
@@ -103,7 +106,7 @@ func MergeAll(repo repository.Repo, remote string) <-chan MergeResult {
 			localExist, err := repo.RefExist(localRef)
 
 			if err != nil {
-				out <- newMergeError(id, err)
+				out <- newMergeError(err, id)
 				continue
 			}
 
@@ -112,32 +115,32 @@ func MergeAll(repo repository.Repo, remote string) <-chan MergeResult {
 				err := repo.CopyRef(remoteRef, localRef)
 
 				if err != nil {
-					out <- newMergeError(id, err)
+					out <- newMergeError(err, id)
 					return
 				}
 
-				out <- newMergeStatus(id, MsgMergeNew)
+				out <- newMergeStatus(MsgMergeNew, id, remoteBug)
 				continue
 			}
 
 			localBug, err := readBug(repo, localRef)
 
 			if err != nil {
-				out <- newMergeError(id, err)
+				out <- newMergeError(err, id)
 				return
 			}
 
 			updated, err := localBug.Merge(repo, remoteBug)
 
 			if err != nil {
-				out <- newMergeError(id, err)
+				out <- newMergeError(err, id)
 				return
 			}
 
 			if updated {
-				out <- newMergeStatus(id, MsgMergeUpdated)
+				out <- newMergeStatus(MsgMergeUpdated, id, localBug)
 			} else {
-				out <- newMergeStatus(id, MsgMergeNothing)
+				out <- newMergeStatus(MsgMergeNothing, id, localBug)
 			}
 		}
 	}()

cache/repo_cache.go 🔗

@@ -261,9 +261,43 @@ func (c *RepoCache) Fetch(remote string) (string, error) {
 	return bug.Fetch(c.repo, remote)
 }
 
+// MergeAll will merge all the available remote bug
 func (c *RepoCache) MergeAll(remote string) <-chan bug.MergeResult {
-	// Todo: update the cache properly
-	return bug.MergeAll(c.repo, remote)
+	out := make(chan bug.MergeResult)
+
+	// Intercept merge results to update the cache properly
+	go func() {
+		defer close(out)
+
+		results := bug.MergeAll(c.repo, remote)
+		for result := range results {
+			if result.Err != nil {
+				continue
+			}
+
+			id := result.Id
+
+			switch result.Status {
+			case bug.MsgMergeNew, bug.MsgMergeUpdated:
+				b := result.Bug
+				snap := b.Compile()
+				c.excerpts[id] = NewBugExcerpt(b, &snap)
+
+			default:
+			}
+
+			out <- result
+		}
+
+		err := c.writeExcerpts()
+
+		// No easy way out here ..
+		if err != nil {
+			panic(err)
+		}
+	}()
+
+	return out
 }
 
 // Push update a remote with the local changes

commands/pull.go 🔗

@@ -42,7 +42,7 @@ func runPull(cmd *cobra.Command, args []string) error {
 		}
 
 		if merge.Status != bug.MsgMergeNothing {
-			fmt.Printf("%s: %s\n", merge.HumanId, merge.Status)
+			fmt.Printf("%s: %s\n", merge.Bug.HumanId(), merge.Status)
 		}
 	}
 

termui/bug_table.go 🔗

@@ -417,7 +417,7 @@ func (bt *bugTable) pull(g *gocui.Gui, v *gocui.View) error {
 				})
 			} else {
 				fmt.Fprintf(&buffer, "%s%s: %s",
-					beginLine, util.Cyan(merge.HumanId), merge.Status,
+					beginLine, util.Cyan(merge.Bug.HumanId()), merge.Status,
 				)
 
 				beginLine = "\n"