aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bug/bug.go2
-rw-r--r--bug/bug_actions.go (renamed from bug/remote_actions.go)40
-rw-r--r--bug/operations/add_comment.go5
-rw-r--r--bug/operations/create.go8
-rw-r--r--bug/operations/label_change.go64
-rw-r--r--bug/operations/set_status.go10
-rw-r--r--bug/operations/set_title.go5
-rw-r--r--commands/close.go8
-rw-r--r--commands/comment.go8
-rw-r--r--commands/label.go70
-rw-r--r--commands/new.go16
-rw-r--r--commands/open.go8
-rw-r--r--commands/pull.go22
-rw-r--r--repository/git.go52
-rw-r--r--repository/mock_repo.go17
-rw-r--r--repository/repo.go4
16 files changed, 220 insertions, 119 deletions
diff --git a/bug/bug.go b/bug/bug.go
index 0b9a4da3..713d6edc 100644
--- a/bug/bug.go
+++ b/bug/bug.go
@@ -41,7 +41,7 @@ func NewBug() *Bug {
// Find an existing Bug matching a prefix
func FindLocalBug(repo repository.Repo, prefix string) (*Bug, error) {
- ids, err := repo.ListRefs(bugsRefPattern)
+ ids, err := repo.ListIds(bugsRefPattern)
if err != nil {
return nil, err
diff --git a/bug/remote_actions.go b/bug/bug_actions.go
index 2070ba21..85123e1c 100644
--- a/bug/remote_actions.go
+++ b/bug/bug_actions.go
@@ -3,13 +3,14 @@ package bug
import (
"fmt"
"github.com/MichaelMure/git-bug/repository"
+ "io"
"strings"
)
-const MsgNew = "new"
-const MsgInvalid = "invalid data"
-const MsgUpdated = "updated"
-const MsgNothing = "nothing to do"
+const MsgMergeNew = "new"
+const MsgMergeInvalid = "invalid data"
+const MsgMergeUpdated = "updated"
+const MsgMergeNothing = "nothing to do"
func Fetch(repo repository.Repo, remote string) error {
remoteRefSpec := fmt.Sprintf(bugsRemoteRefPattern, remote)
@@ -22,6 +23,27 @@ func Push(repo repository.Repo, remote string) error {
return repo.PushRefs(remote, bugsRefPattern+"*")
}
+func Pull(repo repository.Repo, out io.Writer, remote string) error {
+ fmt.Fprintf(out, "Fetching remote ...\n")
+
+ if err := Fetch(repo, remote); err != nil {
+ return err
+ }
+
+ fmt.Fprintf(out, "\nMerging data ...\n")
+
+ for merge := range MergeAll(repo, remote) {
+ if merge.Err != nil {
+ return merge.Err
+ }
+
+ if merge.Status != MsgMergeNothing {
+ fmt.Fprintf(out, "%s: %s\n", merge.HumanId, merge.Status)
+ }
+ }
+ return nil
+}
+
type MergeResult struct {
Err error
@@ -73,7 +95,7 @@ func MergeAll(repo repository.Repo, remote string) <-chan MergeResult {
// Check for error in remote data
if !remoteBug.IsValid() {
- out <- newMergeStatus(id, MsgInvalid)
+ out <- newMergeStatus(id, MsgMergeInvalid)
continue
}
@@ -89,7 +111,7 @@ func MergeAll(repo repository.Repo, remote string) <-chan MergeResult {
return
}
- out <- newMergeStatus(id, MsgNew)
+ out <- newMergeStatus(id, MsgMergeNew)
continue
}
@@ -108,12 +130,14 @@ func MergeAll(repo repository.Repo, remote string) <-chan MergeResult {
}
if updated {
- out <- newMergeStatus(id, MsgUpdated)
+ out <- newMergeStatus(id, MsgMergeUpdated)
} else {
- out <- newMergeStatus(id, MsgNothing)
+ out <- newMergeStatus(id, MsgMergeNothing)
}
}
}()
return out
}
+
+
diff --git a/bug/operations/add_comment.go b/bug/operations/add_comment.go
index 9ee8dc64..66725915 100644
--- a/bug/operations/add_comment.go
+++ b/bug/operations/add_comment.go
@@ -31,3 +31,8 @@ func (op AddCommentOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
return snapshot
}
+
+func Comment(b *bug.Bug, author bug.Person, message string) {
+ addCommentOp := NewAddCommentOp(author, message)
+ b.Append(addCommentOp)
+}
diff --git a/bug/operations/create.go b/bug/operations/create.go
index 72eba843..0fd1225e 100644
--- a/bug/operations/create.go
+++ b/bug/operations/create.go
@@ -33,3 +33,11 @@ func (op CreateOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
}
return snapshot
}
+
+func Create(author bug.Person, title, message string) (*bug.Bug, error) {
+ newBug := bug.NewBug()
+ createOp := NewCreateOp(author, title, message)
+ newBug.Append(createOp)
+
+ return newBug, nil
+}
diff --git a/bug/operations/label_change.go b/bug/operations/label_change.go
index ca07f6f5..b9bf86c8 100644
--- a/bug/operations/label_change.go
+++ b/bug/operations/label_change.go
@@ -1,7 +1,9 @@
package operations
import (
+ "fmt"
"github.com/MichaelMure/git-bug/bug"
+ "io"
"sort"
)
@@ -54,3 +56,65 @@ AddLoop:
return snapshot
}
+
+func ChangeLabels(out io.Writer, b *bug.Bug, author bug.Person, add, remove []string) error {
+ var added, removed []bug.Label
+
+ snap := b.Compile()
+
+ for _, str := range add {
+ label := bug.Label(str)
+
+ // check for duplicate
+ if labelExist(added, label) {
+ fmt.Fprintf(out, "label \"%s\" is a duplicate\n", str)
+ continue
+ }
+
+ // check that the label doesn't already exist
+ if labelExist(snap.Labels, label) {
+ fmt.Fprintf(out, "label \"%s\" is already set on this bug\n", str)
+ continue
+ }
+
+ added = append(added, label)
+ }
+
+ for _, str := range remove {
+ label := bug.Label(str)
+
+ // check for duplicate
+ if labelExist(removed, label) {
+ fmt.Fprintf(out, "label \"%s\" is a duplicate\n", str)
+ continue
+ }
+
+ // check that the label actually exist
+ if !labelExist(snap.Labels, label) {
+ fmt.Fprintf(out, "label \"%s\" doesn't exist on this bug\n", str)
+ continue
+ }
+
+ removed = append(removed, label)
+ }
+
+ if len(added) == 0 && len(removed) == 0 {
+ return fmt.Errorf("no label added or removed")
+ }
+
+ labelOp := NewLabelChangeOperation(author, added, removed)
+
+ b.Append(labelOp)
+
+ return nil
+}
+
+func labelExist(labels []bug.Label, label bug.Label) bool {
+ for _, l := range labels {
+ if l == label {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/bug/operations/set_status.go b/bug/operations/set_status.go
index 7c718cd6..b62409dc 100644
--- a/bug/operations/set_status.go
+++ b/bug/operations/set_status.go
@@ -25,3 +25,13 @@ func (op SetStatusOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
return snapshot
}
+
+func Open(b *bug.Bug, author bug.Person) {
+ op := NewSetStatusOp(author, bug.OpenStatus)
+ b.Append(op)
+}
+
+func Close(b *bug.Bug, author bug.Person) {
+ op := NewSetStatusOp(author, bug.ClosedStatus)
+ b.Append(op)
+}
diff --git a/bug/operations/set_title.go b/bug/operations/set_title.go
index ef934db1..295db282 100644
--- a/bug/operations/set_title.go
+++ b/bug/operations/set_title.go
@@ -25,3 +25,8 @@ func (op SetTitleOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
return snapshot
}
+
+func SetTitle(b *bug.Bug, author bug.Person, title string) {
+ setTitleOp := NewSetTitleOp(author, title)
+ b.Append(setTitleOp)
+}
diff --git a/commands/close.go b/commands/close.go
index 58446d71..f57519ea 100644
--- a/commands/close.go
+++ b/commands/close.go
@@ -28,13 +28,9 @@ func runCloseBug(cmd *cobra.Command, args []string) error {
return err
}
- op := operations.NewSetStatusOp(author, bug.ClosedStatus)
+ operations.Close(b, author)
- b.Append(op)
-
- err = b.Commit(repo)
-
- return err
+ return b.Commit(repo)
}
var closeCmd = &cobra.Command{
diff --git a/commands/comment.go b/commands/comment.go
index 252fb7e4..ebbeaa77 100644
--- a/commands/comment.go
+++ b/commands/comment.go
@@ -49,13 +49,9 @@ func runComment(cmd *cobra.Command, args []string) error {
return err
}
- addCommentOp := operations.NewAddCommentOp(author, commentMessage)
+ operations.Comment(b, author, commentMessage)
- b.Append(addCommentOp)
-
- err = b.Commit(repo)
-
- return err
+ return b.Commit(repo)
}
var commentCmd = &cobra.Command{
diff --git a/commands/label.go b/commands/label.go
index e1679972..ee6ed25f 100644
--- a/commands/label.go
+++ b/commands/label.go
@@ -2,10 +2,10 @@ package commands
import (
"errors"
- "fmt"
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/bug/operations"
"github.com/spf13/cobra"
+ "os"
)
var labelRemove bool
@@ -21,6 +21,14 @@ func runLabel(cmd *cobra.Command, args []string) error {
prefix := args[0]
+ var add, remove []string
+
+ if labelRemove {
+ remove = args[1:]
+ } else {
+ add = args[1:]
+ }
+
b, err := bug.FindLocalBug(repo, prefix)
if err != nil {
return err
@@ -31,65 +39,13 @@ func runLabel(cmd *cobra.Command, args []string) error {
return err
}
- var added, removed []bug.Label
-
- snap := b.Compile()
-
- for _, arg := range args[1:] {
- label := bug.Label(arg)
-
- if labelRemove {
- // check for duplicate
- if labelExist(removed, label) {
- fmt.Printf("label \"%s\" is a duplicate\n", arg)
- continue
- }
-
- // check that the label actually exist
- if !labelExist(snap.Labels, label) {
- fmt.Printf("label \"%s\" doesn't exist on this bug\n", arg)
- continue
- }
-
- removed = append(removed, label)
- } else {
- // check for duplicate
- if labelExist(added, label) {
- fmt.Printf("label \"%s\" is a duplicate\n", arg)
- continue
- }
-
- // check that the label doesn't already exist
- if labelExist(snap.Labels, label) {
- fmt.Printf("label \"%s\" is already set on this bug\n", arg)
- continue
- }
-
- added = append(added, label)
- }
- }
-
- if len(added) == 0 && len(removed) == 0 {
- return errors.New("no label added or removed")
- }
-
- labelOp := operations.NewLabelChangeOperation(author, added, removed)
-
- b.Append(labelOp)
+ err = operations.ChangeLabels(os.Stdout, b, author, add, remove)
- err = b.Commit(repo)
-
- return err
-}
-
-func labelExist(labels []bug.Label, label bug.Label) bool {
- for _, l := range labels {
- if l == label {
- return true
- }
+ if err != nil {
+ return err
}
- return false
+ return b.Commit(repo)
}
var labelCmd = &cobra.Command{
diff --git a/commands/new.go b/commands/new.go
index 9844e121..4168453e 100644
--- a/commands/new.go
+++ b/commands/new.go
@@ -44,18 +44,20 @@ func runNewBug(cmd *cobra.Command, args []string) error {
return err
}
- newBug := bug.NewBug()
-
- createOp := operations.NewCreateOp(author, title, newMessage)
-
- newBug.Append(createOp)
+ newBug, err := operations.Create(author, title, newMessage)
+ if err != nil {
+ return err
+ }
err = newBug.Commit(repo)
- fmt.Printf("%s created\n", newBug.HumanId())
+ if err != nil {
+ return err
+ }
- return err
+ fmt.Printf("%s created\n", newBug.HumanId())
+ return nil
}
var newCmd = &cobra.Command{
diff --git a/commands/open.go b/commands/open.go
index 7fa59b49..c99578cf 100644
--- a/commands/open.go
+++ b/commands/open.go
@@ -28,13 +28,9 @@ func runOpenBug(cmd *cobra.Command, args []string) error {
return err
}
- op := operations.NewSetStatusOp(author, bug.OpenStatus)
+ operations.Open(b, author)
- b.Append(op)
-
- err = b.Commit(repo)
-
- return err
+ return b.Commit(repo)
}
var openCmd = &cobra.Command{
diff --git a/commands/pull.go b/commands/pull.go
index ac6a3732..52b3ecd8 100644
--- a/commands/pull.go
+++ b/commands/pull.go
@@ -2,9 +2,9 @@ package commands
import (
"errors"
- "fmt"
"github.com/MichaelMure/git-bug/bug"
"github.com/spf13/cobra"
+ "os"
)
func runPull(cmd *cobra.Command, args []string) error {
@@ -17,25 +17,7 @@ func runPull(cmd *cobra.Command, args []string) error {
remote = args[0]
}
- fmt.Printf("Fetching remote ...\n\n")
-
- if err := bug.Fetch(repo, remote); err != nil {
- return err
- }
-
- fmt.Printf("\nMerging data ...\n\n")
-
- for merge := range bug.MergeAll(repo, remote) {
- if merge.Err != nil {
- return merge.Err
- }
-
- if merge.Status != bug.MsgNothing {
- fmt.Printf("%s: %s\n", merge.HumanId, merge.Status)
- }
- }
-
- return nil
+ return bug.Pull(repo, os.Stdout, remote)
}
// showCmd defines the "push" subcommand.
diff --git a/repository/git.go b/repository/git.go
index c6bc5009..17b2096f 100644
--- a/repository/git.go
+++ b/repository/git.go
@@ -3,7 +3,6 @@ package repository
import (
"bytes"
- "crypto/sha1"
"fmt"
"github.com/MichaelMure/git-bug/util"
"io"
@@ -19,7 +18,7 @@ type GitRepo struct {
// Run the given git command with the given I/O reader/writers, returning an error if it fails.
func (repo *GitRepo) runGitCommandWithIO(stdin io.Reader, stdout, stderr io.Writer, args ...string) error {
- fmt.Println("Running git", strings.Join(args, " "))
+ //fmt.Println("Running git", strings.Join(args, " "))
cmd := exec.Command("git", args...)
cmd.Dir = repo.Path
@@ -74,17 +73,29 @@ func NewGitRepo(path string) (*GitRepo, error) {
return nil, err
}
+func InitGitRepo(path string) (*GitRepo, error) {
+ repo := &GitRepo{Path: path}
+ _, err := repo.runGitCommand("init", path)
+ if err != nil {
+ return nil, err
+ }
+ return repo, nil
+}
+
+func InitBareGitRepo(path string) (*GitRepo, error) {
+ repo := &GitRepo{Path: path}
+ _, err := repo.runGitCommand("init", "--bare", path)
+ if err != nil {
+ return nil, err
+ }
+ return repo, nil
+}
+
// GetPath returns the path to the repo.
func (repo *GitRepo) GetPath() string {
return repo.Path
}
-// GetRepoStateHash returns a hash which embodies the entire current state of a repository.
-func (repo *GitRepo) GetRepoStateHash() (string, error) {
- stateSummary, err := repo.runGitCommand("show-ref")
- return fmt.Sprintf("%x", sha1.Sum([]byte(stateSummary))), err
-}
-
// GetUserName returns the name the the user has used to configure git
func (repo *GitRepo) GetUserName() (string, error) {
return repo.runGitCommand("config", "user.name")
@@ -189,6 +200,24 @@ func (repo *GitRepo) UpdateRef(ref string, hash util.Hash) error {
// ListRefs will return a list of Git ref matching the given refspec
func (repo *GitRepo) ListRefs(refspec string) ([]string, error) {
+ stdout, err := repo.runGitCommand("for-each-ref", "--format=%(refname)", refspec)
+
+ if err != nil {
+ return nil, err
+ }
+
+ splitted := strings.Split(stdout, "\n")
+
+ if len(splitted) == 1 && splitted[0] == "" {
+ return []string{}, nil
+ }
+
+ return splitted, nil
+}
+
+// ListIds will return a list of Git ref matching the given refspec,
+// stripped to only the last part of the ref
+func (repo *GitRepo) ListIds(refspec string) ([]string, error) {
// the format option will strip the ref name to keep only the last part (ie, the bug id)
stdout, err := repo.runGitCommand("for-each-ref", "--format=%(refname:lstrip=-1)", refspec)
@@ -274,3 +303,10 @@ func (repo *GitRepo) GetTreeHash(commit util.Hash) (util.Hash, error) {
return util.Hash(stdout), nil
}
+
+// Add a new remote to the repository
+func (repo *GitRepo) AddRemote(name string, url string) error {
+ _, err := repo.runGitCommand("remote", "add", name, url)
+
+ return err
+}
diff --git a/repository/mock_repo.go b/repository/mock_repo.go
index 4bd25738..f8653c64 100644
--- a/repository/mock_repo.go
+++ b/repository/mock_repo.go
@@ -3,6 +3,8 @@ package repository
import (
"crypto/sha1"
"fmt"
+ "strings"
+
"github.com/MichaelMure/git-bug/util"
)
@@ -134,6 +136,21 @@ func (r *mockRepoForTest) ListRefs(refspec string) ([]string, error) {
return keys, nil
}
+// ListIds will return a list of Git ref matching the given refspec,
+// stripped to only the last part of the ref
+func (r *mockRepoForTest) ListIds(refspec string) ([]string, error) {
+ keys := make([]string, len(r.refs))
+
+ i := 0
+ for k := range r.refs {
+ splitted := strings.Split(k, "/")
+ keys[i] = splitted[len(splitted)-1]
+ i++
+ }
+
+ return keys, nil
+}
+
func (r *mockRepoForTest) ListCommits(ref string) ([]util.Hash, error) {
var hashes []util.Hash
diff --git a/repository/repo.go b/repository/repo.go
index 6ab7be91..38d8a6cb 100644
--- a/repository/repo.go
+++ b/repository/repo.go
@@ -48,6 +48,10 @@ type Repo interface {
// ListRefs will return a list of Git ref matching the given refspec
ListRefs(refspec string) ([]string, error)
+ // ListIds will return a list of Git ref matching the given refspec,
+ // stripped to only the last part of the ref
+ ListIds(refspec string) ([]string, error)
+
// RefExist will check if a reference exist in Git
RefExist(ref string) (bool, error)