select.go

  1package _select
  2
  3import (
  4	"fmt"
  5	"io"
  6	"io/ioutil"
  7	"os"
  8	"path"
  9
 10	"github.com/MichaelMure/git-bug/bug"
 11	"github.com/MichaelMure/git-bug/cache"
 12	"github.com/MichaelMure/git-bug/repository"
 13	"github.com/MichaelMure/git-bug/util/git"
 14	"github.com/pkg/errors"
 15)
 16
 17const selectFile = "select"
 18
 19var ErrNoValidId = errors.New("you must provide a bug id")
 20
 21// ResolveBug first try to resolve a bug using the first argument of the command
 22// line. If it fails, it fallback to the select mechanism.
 23//
 24// Returns:
 25// - the bug if any
 26// - the new list of command line arguments with the bug prefix removed if it
 27//   has been used
 28// - an error if the process failed
 29func ResolveBug(repo *cache.RepoCache, args []string) (*cache.BugCache, []string, error) {
 30	if len(args) > 0 {
 31		b, err := repo.ResolveBugPrefix(args[0])
 32
 33		if err == nil {
 34			return b, args[1:], nil
 35		}
 36
 37		if err != bug.ErrBugNotExist {
 38			return nil, nil, err
 39		}
 40	}
 41
 42	// first arg is not a valid bug prefix
 43
 44	b, err := selected(repo)
 45	if err != nil {
 46		return nil, nil, err
 47	}
 48
 49	if b != nil {
 50		return b, args, nil
 51	}
 52
 53	return nil, nil, ErrNoValidId
 54}
 55
 56// Select will select a bug for future use
 57func Select(repo *cache.RepoCache, id string) error {
 58	selectPath := selectFilePath(repo.Repository())
 59
 60	f, err := os.OpenFile(selectPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
 61	if err != nil {
 62		return err
 63	}
 64
 65	_, err = f.WriteString(id)
 66	if err != nil {
 67		return err
 68	}
 69
 70	return f.Close()
 71}
 72
 73// Clear will clear the selected bug, if any
 74func Clear(repo *cache.RepoCache) error {
 75	selectPath := selectFilePath(repo.Repository())
 76
 77	return os.Remove(selectPath)
 78}
 79
 80func selected(repo *cache.RepoCache) (*cache.BugCache, error) {
 81	selectPath := selectFilePath(repo.Repository())
 82
 83	f, err := os.Open(selectPath)
 84	if err != nil {
 85		if os.IsNotExist(err) {
 86			return nil, nil
 87		} else {
 88			return nil, err
 89		}
 90	}
 91
 92	buf, err := ioutil.ReadAll(io.LimitReader(f, 100))
 93	if err != nil {
 94		return nil, err
 95	}
 96	if len(buf) == 100 {
 97		return nil, fmt.Errorf("the select file should be < 100 bytes")
 98	}
 99
100	h := git.Hash(buf)
101	if !h.IsValid() {
102		err = os.Remove(selectPath)
103		if err != nil {
104			return nil, errors.Wrap(err, "error while removing invalid select file")
105		}
106
107		return nil, fmt.Errorf("select file in invalid, removing it")
108	}
109
110	b, err := repo.ResolveBug(string(h))
111	if err != nil {
112		return nil, err
113	}
114
115	err = f.Close()
116	if err != nil {
117		return nil, err
118	}
119
120	return b, nil
121}
122
123func selectFilePath(repo repository.Repo) string {
124	return path.Join(repo.GetPath(), ".git", "git-bug", selectFile)
125}