1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
package _select
import (
"fmt"
"io"
"io/ioutil"
"os"
"github.com/pkg/errors"
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/entity"
)
const selectFile = "select"
var ErrNoValidId = errors.New("you must provide a bug id or use the \"select\" command first")
// 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) {
// At first, try to use the first argument as a bug prefix
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, we can safely use the preselected bug if any
b, err := selected(repo)
// selected bug is invalid
if err == bug.ErrBugNotExist {
// we clear the selected bug
err = Clear(repo)
if err != nil {
return nil, nil, err
}
return nil, nil, ErrNoValidId
}
// another error when reading the bug
if err != nil {
return nil, nil, err
}
// bug is successfully retrieved
if b != nil {
return b, args, nil
}
// no selected bug and no valid first argument
return nil, nil, ErrNoValidId
}
// Select will select a bug for future use
func Select(repo *cache.RepoCache, id entity.Id) error {
f, err := repo.LocalStorage().OpenFile(selectFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return err
}
_, err = f.Write([]byte(id.String()))
if err != nil {
return err
}
return f.Close()
}
// Clear will clear the selected bug, if any
func Clear(repo *cache.RepoCache) error {
return repo.LocalStorage().Remove(selectFile)
}
func selected(repo *cache.RepoCache) (*cache.BugCache, error) {
f, err := repo.LocalStorage().Open(selectFile)
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")
}
id := entity.Id(buf)
if err := id.Validate(); err != nil {
err = repo.LocalStorage().Remove(selectFile)
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(id)
if err != nil {
return nil, err
}
err = f.Close()
if err != nil {
return nil, err
}
return b, nil
}
|