aboutsummaryrefslogtreecommitdiffstats
path: root/commands
diff options
context:
space:
mode:
Diffstat (limited to 'commands')
-rw-r--r--commands/select/select.go125
-rw-r--r--commands/select/select_test.go109
2 files changed, 234 insertions, 0 deletions
diff --git a/commands/select/select.go b/commands/select/select.go
new file mode 100644
index 00000000..5d6cee7f
--- /dev/null
+++ b/commands/select/select.go
@@ -0,0 +1,125 @@
+package _select
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path"
+
+ "github.com/MichaelMure/git-bug/bug"
+ "github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/repository"
+ "github.com/MichaelMure/git-bug/util/git"
+ "github.com/pkg/errors"
+)
+
+const selectFile = "select"
+
+var ErrNoValidId = errors.New("you must provide a bug id")
+
+// ResolveBug first try to resolve a bug using the first argument of the command
+// line. If it fails, it fallback to the select mechanism.
+//
+// Returns:
+// - the bug if any
+// - the new list of command line arguments with the bug prefix removed if it
+// has been used
+// - an error if the process failed
+func ResolveBug(repo *cache.RepoCache, args []string) (*cache.BugCache, []string, error) {
+ if len(args) > 0 {
+ b, err := repo.ResolveBugPrefix(args[0])
+
+ if err == nil {
+ return b, args[1:], nil
+ }
+
+ if err != bug.ErrBugNotExist {
+ return nil, nil, err
+ }
+ }
+
+ // first arg is not a valid bug prefix
+
+ b, err := selected(repo)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ if b != nil {
+ return b, args, nil
+ }
+
+ return nil, nil, ErrNoValidId
+}
+
+// Select will select a bug for future use
+func Select(repo *cache.RepoCache, id string) error {
+ selectPath := selectFilePath(repo.Repository())
+
+ f, err := os.OpenFile(selectPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ return err
+ }
+
+ _, err = f.WriteString(id)
+ if err != nil {
+ return err
+ }
+
+ return f.Close()
+}
+
+// Clear will clear the selected bug, if any
+func Clear(repo *cache.RepoCache) error {
+ selectPath := selectFilePath(repo.Repository())
+
+ return os.Remove(selectPath)
+}
+
+func selected(repo *cache.RepoCache) (*cache.BugCache, error) {
+ selectPath := selectFilePath(repo.Repository())
+
+ f, err := os.Open(selectPath)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return nil, nil
+ } else {
+ return nil, err
+ }
+ }
+
+ buf, err := ioutil.ReadAll(io.LimitReader(f, 100))
+ if err != nil {
+ return nil, err
+ }
+ if len(buf) == 100 {
+ return nil, fmt.Errorf("the select file should be < 100 bytes")
+ }
+
+ h := git.Hash(buf)
+ if !h.IsValid() {
+ err = os.Remove(selectPath)
+ if err != nil {
+ return nil, errors.Wrap(err, "error while removing invalid select file")
+ }
+
+ return nil, fmt.Errorf("select file in invalid, removing it")
+ }
+
+ b, err := repo.ResolveBug(string(h))
+ if err != nil {
+ return nil, err
+ }
+
+ err = f.Close()
+ if err != nil {
+ return nil, err
+ }
+
+ return b, nil
+}
+
+func selectFilePath(repo repository.Repo) string {
+ return path.Join(repo.GetPath(), ".git", "git-bug", selectFile)
+}
diff --git a/commands/select/select_test.go b/commands/select/select_test.go
new file mode 100644
index 00000000..5a34d71e
--- /dev/null
+++ b/commands/select/select_test.go
@@ -0,0 +1,109 @@
+package _select
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "testing"
+
+ "github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/repository"
+)
+
+func TestSelect(t *testing.T) {
+ repo, err := cache.NewRepoCache(createRepo())
+ checkErr(t, err)
+
+ _, _, err = ResolveBug(repo, []string{})
+ if err != ErrNoValidId {
+ t.Fatal("expected no valid id error, got", err)
+ }
+
+ err = Select(repo, "invalid")
+ checkErr(t, err)
+
+ _, _, err = ResolveBug(repo, []string{})
+ if err == nil {
+ t.Fatal("expected invalid bug error")
+ }
+
+ // generate a bunch of bugs
+ for i := 0; i < 10; i++ {
+ _, err := repo.NewBug("title", "message")
+ checkErr(t, err)
+ }
+
+ // two more for testing
+ b1, err := repo.NewBug("title", "message")
+ checkErr(t, err)
+ b2, err := repo.NewBug("title", "message")
+ checkErr(t, err)
+
+ err = Select(repo, b1.Id())
+ checkErr(t, err)
+
+ // normal select without args
+ b3, _, err := ResolveBug(repo, []string{})
+ checkErr(t, err)
+ if b3.Id() != b1.Id() {
+ t.Fatal("incorrect bug returned")
+ }
+
+ // override selection with same id
+ b4, _, err := ResolveBug(repo, []string{b1.Id()})
+ checkErr(t, err)
+ if b4.Id() != b1.Id() {
+ t.Fatal("incorrect bug returned")
+ }
+
+ // override selection with a prefix
+ b5, _, err := ResolveBug(repo, []string{b1.HumanId()})
+ checkErr(t, err)
+ if b5.Id() != b1.Id() {
+ t.Fatal("incorrect bug returned")
+ }
+
+ // args that shouldn't override
+ b6, _, err := ResolveBug(repo, []string{"arg"})
+ checkErr(t, err)
+ if b6.Id() != b1.Id() {
+ t.Fatal("incorrect bug returned")
+ }
+
+ // override with a different id
+ b7, _, err := ResolveBug(repo, []string{b2.Id()})
+ checkErr(t, err)
+ if b7.Id() != b2.Id() {
+ t.Fatal("incorrect bug returned")
+ }
+
+ err = Clear(repo)
+ checkErr(t, err)
+
+ _, _, err = ResolveBug(repo, []string{})
+ if err == nil {
+ t.Fatal("expected invalid bug error")
+ }
+}
+
+func createRepo() *repository.GitRepo {
+ dir, err := ioutil.TempDir("", "")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println("Creating repo:", dir)
+
+ repo, err := repository.InitGitRepo(dir)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ return repo
+}
+
+func checkErr(t testing.TB, err error) {
+ if err != nil {
+ t.Fatal(err)
+ }
+}