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)
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)
76
77 return os.Remove(selectPath)
78}
79
80func selected(repo *cache.RepoCache) (*cache.BugCache, error) {
81 selectPath := selectFilePath(repo)
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.RepoCommon) string {
124 return path.Join(repo.GetPath(), ".git", "git-bug", selectFile)
125}