aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bug/bug_actions.go92
-rw-r--r--cache/repo_cache.go60
-rw-r--r--commands/pull.go11
-rw-r--r--entity/doc.go8
-rw-r--r--entity/interface.go8
-rw-r--r--entity/merge.go68
-rw-r--r--identity/identity_actions.go93
-rw-r--r--termui/bug_table.go12
8 files changed, 169 insertions, 183 deletions
diff --git a/bug/bug_actions.go b/bug/bug_actions.go
index f214716d..b26d080f 100644
--- a/bug/bug_actions.go
+++ b/bug/bug_actions.go
@@ -4,6 +4,7 @@ import (
"fmt"
"strings"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/repository"
"github.com/pkg/errors"
)
@@ -34,7 +35,7 @@ func Pull(repo repository.ClockedRepo, remote string) error {
if merge.Err != nil {
return merge.Err
}
- if merge.Status == MergeStatusInvalid {
+ if merge.Status == entity.MergeStatusInvalid {
return errors.Errorf("merge failure: %s", merge.Reason)
}
}
@@ -49,8 +50,8 @@ func Pull(repo repository.ClockedRepo, remote string) error {
// - if the local bug has new commits but the remote don't, nothing is changed
// - if both local and remote bug have new commits (that is, we have a concurrent edition),
// new local commits are rewritten at the head of the remote history (that is, a rebase)
-func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
- out := make(chan MergeResult)
+func MergeAll(repo repository.ClockedRepo, remote string) <-chan entity.MergeResult {
+ out := make(chan entity.MergeResult)
go func() {
defer close(out)
@@ -59,7 +60,7 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
remoteRefs, err := repo.ListRefs(remoteRefSpec)
if err != nil {
- out <- MergeResult{Err: err}
+ out <- entity.MergeResult{Err: err}
return
}
@@ -70,13 +71,13 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
remoteBug, err := readBug(repo, remoteRef)
if err != nil {
- out <- newMergeInvalidStatus(id, errors.Wrap(err, "remote bug is not readable").Error())
+ out <- entity.NewMergeInvalidStatus(id, errors.Wrap(err, "remote bug is not readable").Error())
continue
}
// Check for error in remote data
if err := remoteBug.Validate(); err != nil {
- out <- newMergeInvalidStatus(id, errors.Wrap(err, "remote bug is invalid").Error())
+ out <- entity.NewMergeInvalidStatus(id, errors.Wrap(err, "remote bug is invalid").Error())
continue
}
@@ -84,7 +85,7 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
localExist, err := repo.RefExist(localRef)
if err != nil {
- out <- newMergeError(err, id)
+ out <- entity.NewMergeError(err, id)
continue
}
@@ -93,100 +94,35 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
err := repo.CopyRef(remoteRef, localRef)
if err != nil {
- out <- newMergeError(err, id)
+ out <- entity.NewMergeError(err, id)
return
}
- out <- newMergeStatus(MergeStatusNew, id, remoteBug)
+ out <- entity.NewMergeStatus(entity.MergeStatusNew, id, remoteBug)
continue
}
localBug, err := readBug(repo, localRef)
if err != nil {
- out <- newMergeError(errors.Wrap(err, "local bug is not readable"), id)
+ out <- entity.NewMergeError(errors.Wrap(err, "local bug is not readable"), id)
return
}
updated, err := localBug.Merge(repo, remoteBug)
if err != nil {
- out <- newMergeInvalidStatus(id, errors.Wrap(err, "merge failed").Error())
+ out <- entity.NewMergeInvalidStatus(id, errors.Wrap(err, "merge failed").Error())
return
}
if updated {
- out <- newMergeStatus(MergeStatusUpdated, id, localBug)
+ out <- entity.NewMergeStatus(entity.MergeStatusUpdated, id, localBug)
} else {
- out <- newMergeStatus(MergeStatusNothing, id, localBug)
+ out <- entity.NewMergeStatus(entity.MergeStatusNothing, id, localBug)
}
}
}()
return out
}
-
-// MergeStatus represent the result of a merge operation of a bug
-type MergeStatus int
-
-const (
- _ MergeStatus = iota
- MergeStatusNew
- MergeStatusInvalid
- MergeStatusUpdated
- MergeStatusNothing
-)
-
-type MergeResult struct {
- // Err is set when a terminal error occur in the process
- Err error
-
- Id string
- Status MergeStatus
-
- // Only set for invalid status
- Reason string
-
- // Not set for invalid status
- Bug *Bug
-}
-
-func (mr MergeResult) String() string {
- switch mr.Status {
- case MergeStatusNew:
- return "new"
- case MergeStatusInvalid:
- return fmt.Sprintf("invalid data: %s", mr.Reason)
- case MergeStatusUpdated:
- return "updated"
- case MergeStatusNothing:
- return "nothing to do"
- default:
- panic("unknown merge status")
- }
-}
-
-func newMergeError(err error, id string) MergeResult {
- return MergeResult{
- Err: err,
- Id: id,
- }
-}
-
-func newMergeStatus(status MergeStatus, id string, bug *Bug) MergeResult {
- return MergeResult{
- Id: id,
- Status: status,
-
- // Bug is not set for an invalid merge result
- Bug: bug,
- }
-}
-
-func newMergeInvalidStatus(id string, reason string) MergeResult {
- return MergeResult{
- Id: id,
- Status: MergeStatusInvalid,
- Reason: reason,
- }
-}
diff --git a/cache/repo_cache.go b/cache/repo_cache.go
index bec733e3..fce473f4 100644
--- a/cache/repo_cache.go
+++ b/cache/repo_cache.go
@@ -14,6 +14,7 @@ import (
"time"
"github.com/MichaelMure/git-bug/bug"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/identity"
"github.com/MichaelMure/git-bug/repository"
"github.com/MichaelMure/git-bug/util/git"
@@ -593,23 +594,31 @@ func (c *RepoCache) NewBugRaw(author *IdentityCache, unixTime int64, title strin
return cached, nil
}
-// Fetch retrieve update from a remote
-// This does not change the local bugs state
+// Fetch retrieve updates from a remote
+// This does not change the local bugs or identities state
func (c *RepoCache) Fetch(remote string) (string, error) {
- return bug.Fetch(c.repo, remote)
-}
+ stdout1, err := identity.Fetch(c.repo, remote)
+ if err != nil {
+ return stdout1, err
+ }
+
+ stdout2, err := bug.Fetch(c.repo, remote)
+ if err != nil {
+ return stdout2, err
+ }
-// MergeAll will merge all the available remote bug
-func (c *RepoCache) MergeAll(remote string) <-chan bug.MergeResult {
- // TODO: add identities
+ return stdout1 + stdout2, nil
+}
- out := make(chan bug.MergeResult)
+// MergeAll will merge all the available remote bug and identities
+func (c *RepoCache) MergeAll(remote string) <-chan entity.MergeResult {
+ out := make(chan entity.MergeResult)
// Intercept merge results to update the cache properly
go func() {
defer close(out)
- results := bug.MergeAll(c.repo, remote)
+ results := identity.MergeAll(c.repo, remote)
for result := range results {
out <- result
@@ -617,13 +626,26 @@ func (c *RepoCache) MergeAll(remote string) <-chan bug.MergeResult {
continue
}
- id := result.Id
+ switch result.Status {
+ case entity.MergeStatusNew, entity.MergeStatusUpdated:
+ i := result.Entity.(*identity.Identity)
+ c.identitiesExcerpts[result.Id] = NewIdentityExcerpt(i)
+ }
+ }
+
+ results = bug.MergeAll(c.repo, remote)
+ for result := range results {
+ out <- result
+
+ if result.Err != nil {
+ continue
+ }
switch result.Status {
- case bug.MergeStatusNew, bug.MergeStatusUpdated:
- b := result.Bug
+ case entity.MergeStatusNew, entity.MergeStatusUpdated:
+ b := result.Entity.(*bug.Bug)
snap := b.Compile()
- c.bugExcerpts[id] = NewBugExcerpt(b, &snap)
+ c.bugExcerpts[result.Id] = NewBugExcerpt(b, &snap)
}
}
@@ -640,7 +662,17 @@ func (c *RepoCache) MergeAll(remote string) <-chan bug.MergeResult {
// Push update a remote with the local changes
func (c *RepoCache) Push(remote string) (string, error) {
- return bug.Push(c.repo, remote)
+ stdout1, err := identity.Push(c.repo, remote)
+ if err != nil {
+ return stdout1, err
+ }
+
+ stdout2, err := bug.Push(c.repo, remote)
+ if err != nil {
+ return stdout2, err
+ }
+
+ return stdout1 + stdout2, nil
}
func repoLockFilePath(repo repository.Repo) string {
diff --git a/commands/pull.go b/commands/pull.go
index d2d75f3f..5df10dca 100644
--- a/commands/pull.go
+++ b/commands/pull.go
@@ -6,6 +6,7 @@ import (
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/util/interrupt"
"github.com/spf13/cobra"
)
@@ -38,13 +39,13 @@ func runPull(cmd *cobra.Command, args []string) error {
fmt.Println("Merging data ...")
- for merge := range backend.MergeAll(remote) {
- if merge.Err != nil {
- fmt.Println(merge.Err)
+ for result := range backend.MergeAll(remote) {
+ if result.Err != nil {
+ fmt.Println(result.Err)
}
- if merge.Status != bug.MergeStatusNothing {
- fmt.Printf("%s: %s\n", bug.FormatHumanID(merge.Id), merge)
+ if result.Status != entity.MergeStatusNothing {
+ fmt.Printf("%s: %s\n", bug.FormatHumanID(result.Id), result)
}
}
diff --git a/entity/doc.go b/entity/doc.go
new file mode 100644
index 00000000..4682d545
--- /dev/null
+++ b/entity/doc.go
@@ -0,0 +1,8 @@
+// Package entity contains the base common code to define an entity stored
+// in a chain of git objects, supporting actions like Push, Pull and Merge.
+package entity
+
+// TODO: Bug and Identity are very similar, right ? I expect that this package
+// will eventually hold the common code to define an entity and the related
+// helpers, errors and so on. When this work is done, it will become easier
+// to add new entities, for example to support pull requests.
diff --git a/entity/interface.go b/entity/interface.go
new file mode 100644
index 00000000..62b92a58
--- /dev/null
+++ b/entity/interface.go
@@ -0,0 +1,8 @@
+package entity
+
+type Interface interface {
+ // Id return the Entity identifier
+ Id() string
+ // HumanId return the Entity identifier truncated for human consumption
+ HumanId() string
+}
diff --git a/entity/merge.go b/entity/merge.go
new file mode 100644
index 00000000..544f2168
--- /dev/null
+++ b/entity/merge.go
@@ -0,0 +1,68 @@
+package entity
+
+import "fmt"
+
+// MergeStatus represent the result of a merge operation of an entity
+type MergeStatus int
+
+const (
+ _ MergeStatus = iota
+ MergeStatusNew
+ MergeStatusInvalid
+ MergeStatusUpdated
+ MergeStatusNothing
+)
+
+type MergeResult struct {
+ // Err is set when a terminal error occur in the process
+ Err error
+
+ Id string
+ Status MergeStatus
+
+ // Only set for invalid status
+ Reason string
+
+ // Not set for invalid status
+ Entity Interface
+}
+
+func (mr MergeResult) String() string {
+ switch mr.Status {
+ case MergeStatusNew:
+ return "new"
+ case MergeStatusInvalid:
+ return fmt.Sprintf("invalid data: %s", mr.Reason)
+ case MergeStatusUpdated:
+ return "updated"
+ case MergeStatusNothing:
+ return "nothing to do"
+ default:
+ panic("unknown merge status")
+ }
+}
+
+func NewMergeError(err error, id string) MergeResult {
+ return MergeResult{
+ Err: err,
+ Id: id,
+ }
+}
+
+func NewMergeStatus(status MergeStatus, id string, entity Interface) MergeResult {
+ return MergeResult{
+ Id: id,
+ Status: status,
+
+ // Entity is not set for an invalid merge result
+ Entity: entity,
+ }
+}
+
+func NewMergeInvalidStatus(id string, reason string) MergeResult {
+ return MergeResult{
+ Id: id,
+ Status: MergeStatusInvalid,
+ Reason: reason,
+ }
+}
diff --git a/identity/identity_actions.go b/identity/identity_actions.go
index 53997eef..38d83b19 100644
--- a/identity/identity_actions.go
+++ b/identity/identity_actions.go
@@ -4,6 +4,7 @@ import (
"fmt"
"strings"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/repository"
"github.com/pkg/errors"
)
@@ -34,7 +35,7 @@ func Pull(repo repository.ClockedRepo, remote string) error {
if merge.Err != nil {
return merge.Err
}
- if merge.Status == MergeStatusInvalid {
+ if merge.Status == entity.MergeStatusInvalid {
return errors.Errorf("merge failure: %s", merge.Reason)
}
}
@@ -43,8 +44,8 @@ func Pull(repo repository.ClockedRepo, remote string) error {
}
// MergeAll will merge all the available remote identity
-func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
- out := make(chan MergeResult)
+func MergeAll(repo repository.ClockedRepo, remote string) <-chan entity.MergeResult {
+ out := make(chan entity.MergeResult)
go func() {
defer close(out)
@@ -53,7 +54,7 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
remoteRefs, err := repo.ListRefs(remoteRefSpec)
if err != nil {
- out <- MergeResult{Err: err}
+ out <- entity.MergeResult{Err: err}
return
}
@@ -64,13 +65,13 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
remoteIdentity, err := read(repo, remoteRef)
if err != nil {
- out <- newMergeInvalidStatus(id, errors.Wrap(err, "remote identity is not readable").Error())
+ out <- entity.NewMergeInvalidStatus(id, errors.Wrap(err, "remote identity is not readable").Error())
continue
}
// Check for error in remote data
if err := remoteIdentity.Validate(); err != nil {
- out <- newMergeInvalidStatus(id, errors.Wrap(err, "remote identity is invalid").Error())
+ out <- entity.NewMergeInvalidStatus(id, errors.Wrap(err, "remote identity is invalid").Error())
continue
}
@@ -78,7 +79,7 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
localExist, err := repo.RefExist(localRef)
if err != nil {
- out <- newMergeError(err, id)
+ out <- entity.NewMergeError(err, id)
continue
}
@@ -87,101 +88,35 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
err := repo.CopyRef(remoteRef, localRef)
if err != nil {
- out <- newMergeError(err, id)
+ out <- entity.NewMergeError(err, id)
return
}
- out <- newMergeStatus(MergeStatusNew, id, remoteIdentity)
+ out <- entity.NewMergeStatus(entity.MergeStatusNew, id, remoteIdentity)
continue
}
localIdentity, err := read(repo, localRef)
if err != nil {
- out <- newMergeError(errors.Wrap(err, "local identity is not readable"), id)
+ out <- entity.NewMergeError(errors.Wrap(err, "local identity is not readable"), id)
return
}
updated, err := localIdentity.Merge(repo, remoteIdentity)
if err != nil {
- out <- newMergeInvalidStatus(id, errors.Wrap(err, "merge failed").Error())
+ out <- entity.NewMergeInvalidStatus(id, errors.Wrap(err, "merge failed").Error())
return
}
if updated {
- out <- newMergeStatus(MergeStatusUpdated, id, localIdentity)
+ out <- entity.NewMergeStatus(entity.MergeStatusUpdated, id, localIdentity)
} else {
- out <- newMergeStatus(MergeStatusNothing, id, localIdentity)
+ out <- entity.NewMergeStatus(entity.MergeStatusNothing, id, localIdentity)
}
}
}()
return out
}
-
-// MergeStatus represent the result of a merge operation of a bug
-type MergeStatus int
-
-const (
- _ MergeStatus = iota
- MergeStatusNew
- MergeStatusInvalid
- MergeStatusUpdated
- MergeStatusNothing
-)
-
-// Todo: share a generalized MergeResult with the bug package ?
-type MergeResult struct {
- // Err is set when a terminal error occur in the process
- Err error
-
- Id string
- Status MergeStatus
-
- // Only set for invalid status
- Reason string
-
- // Not set for invalid status
- Identity *Identity
-}
-
-func (mr MergeResult) String() string {
- switch mr.Status {
- case MergeStatusNew:
- return "new"
- case MergeStatusInvalid:
- return fmt.Sprintf("invalid data: %s", mr.Reason)
- case MergeStatusUpdated:
- return "updated"
- case MergeStatusNothing:
- return "nothing to do"
- default:
- panic("unknown merge status")
- }
-}
-
-func newMergeError(err error, id string) MergeResult {
- return MergeResult{
- Err: err,
- Id: id,
- }
-}
-
-func newMergeStatus(status MergeStatus, id string, identity *Identity) MergeResult {
- return MergeResult{
- Id: id,
- Status: status,
-
- // Identity is not set for an invalid merge result
- Identity: identity,
- }
-}
-
-func newMergeInvalidStatus(id string, reason string) MergeResult {
- return MergeResult{
- Id: id,
- Status: MergeStatusInvalid,
- Reason: reason,
- }
-}
diff --git a/termui/bug_table.go b/termui/bug_table.go
index 69634151..50991f2e 100644
--- a/termui/bug_table.go
+++ b/termui/bug_table.go
@@ -4,8 +4,8 @@ import (
"bytes"
"fmt"
- "github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/util/colors"
"github.com/MichaelMure/git-bug/util/text"
"github.com/MichaelMure/gocui"
@@ -435,8 +435,6 @@ func (bt *bugTable) openBug(g *gocui.Gui, v *gocui.View) error {
}
func (bt *bugTable) pull(g *gocui.Gui, v *gocui.View) error {
- // Note: this is very hacky
-
ui.msgPopup.Activate("Pull from remote "+defaultRemote, "...")
go func() {
@@ -457,19 +455,19 @@ func (bt *bugTable) pull(g *gocui.Gui, v *gocui.View) error {
var buffer bytes.Buffer
beginLine := ""
- for merge := range bt.repo.MergeAll(defaultRemote) {
- if merge.Status == bug.MergeStatusNothing {
+ for result := range bt.repo.MergeAll(defaultRemote) {
+ if result.Status == entity.MergeStatusNothing {
continue
}
- if merge.Err != nil {
+ if result.Err != nil {
g.Update(func(gui *gocui.Gui) error {
ui.msgPopup.Activate(msgPopupErrorTitle, err.Error())
return nil
})
} else {
_, _ = fmt.Fprintf(&buffer, "%s%s: %s",
- beginLine, colors.Cyan(merge.Bug.HumanId()), merge,
+ beginLine, colors.Cyan(result.Entity.HumanId()), result,
)
beginLine = "\n"