diff options
author | Michael Muré <batolettre@gmail.com> | 2018-09-18 12:49:16 +0200 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2018-09-18 12:49:16 +0200 |
commit | 0d5998eb67f9bbf146e15a127a2d6a89aa14eab9 (patch) | |
tree | 1f9a61040bc5f84ef2b78199a9adf922b7f0441f /commands | |
parent | 5eaf9e83e7cd56b8bb4915193d13adfb60575b21 (diff) | |
download | git-bug-0d5998eb67f9bbf146e15a127a2d6a89aa14eab9.tar.gz |
commands: add a package to handle implicit bug selection
Diffstat (limited to 'commands')
-rw-r--r-- | commands/select/select.go | 125 | ||||
-rw-r--r-- | commands/select/select_test.go | 109 |
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) + } +} |