bug_cache.go

  1package cache
  2
  3import (
  4	"fmt"
  5	"time"
  6
  7	"github.com/MichaelMure/git-bug/bug"
  8	"github.com/MichaelMure/git-bug/entity"
  9	"github.com/MichaelMure/git-bug/util/git"
 10)
 11
 12var ErrNoMatchingOp = fmt.Errorf("no matching operation found")
 13
 14// BugCache is a wrapper around a Bug. It provide multiple functions:
 15//
 16// 1. Provide a higher level API to use than the raw API from Bug.
 17// 2. Maintain an up to date Snapshot available.
 18type BugCache struct {
 19	repoCache *RepoCache
 20	bug       *bug.WithSnapshot
 21}
 22
 23func NewBugCache(repoCache *RepoCache, b *bug.Bug) *BugCache {
 24	return &BugCache{
 25		repoCache: repoCache,
 26		bug:       &bug.WithSnapshot{Bug: b},
 27	}
 28}
 29
 30func (c *BugCache) Snapshot() *bug.Snapshot {
 31	return c.bug.Snapshot()
 32}
 33
 34func (c *BugCache) Id() entity.Id {
 35	return c.bug.Id()
 36}
 37
 38func (c *BugCache) notifyUpdated() error {
 39	return c.repoCache.bugUpdated(c.bug.Id())
 40}
 41
 42// ResolveOperationWithMetadata will find an operation that has the matching metadata
 43func (c *BugCache) ResolveOperationWithMetadata(key string, value string) (entity.Id, error) {
 44	// preallocate but empty
 45	matching := make([]entity.Id, 0, 5)
 46
 47	it := bug.NewOperationIterator(c.bug)
 48	for it.Next() {
 49		op := it.Value()
 50		opValue, ok := op.GetMetadata(key)
 51		if ok && value == opValue {
 52			matching = append(matching, op.Id())
 53		}
 54	}
 55
 56	if len(matching) == 0 {
 57		return "", ErrNoMatchingOp
 58	}
 59
 60	if len(matching) > 1 {
 61		return "", bug.NewErrMultipleMatchOp(matching)
 62	}
 63
 64	return matching[0], nil
 65}
 66
 67func (c *BugCache) AddComment(message string) (*bug.AddCommentOperation, error) {
 68	return c.AddCommentWithFiles(message, nil)
 69}
 70
 71func (c *BugCache) OpAddComment(message string) (*bug.AddCommentOperation, error) {
 72	return c.Op
 73}
 74
 75func (c *BugCache) AddCommentWithFiles(message string, files []git.Hash) (*bug.AddCommentOperation, error) {
 76	author, err := c.repoCache.GetUserIdentity()
 77	if err != nil {
 78		return nil, err
 79	}
 80
 81	return c.AddCommentRaw(author, time.Now().Unix(), message, files, nil)
 82}
 83
 84func (c *BugCache) OpAddCommentWithFiles(message string, files []git.Hash) (*bug.AddCommentOperation, error) {
 85	return c.Op
 86}
 87
 88func (c *BugCache) AddCommentRaw(author *IdentityCache, unixTime int64, message string, files []git.Hash, metadata map[string]string) (*bug.AddCommentOperation, error) {
 89	op, err := bug.AddCommentWithFiles(c.bug, author.Identity, unixTime, message, files)
 90	if err != nil {
 91		return nil, err
 92	}
 93
 94	for key, value := range metadata {
 95		op.SetMetadata(key, value)
 96	}
 97
 98	return op, c.notifyUpdated()
 99}
100
101func (c *BugCache) OpAddCommentRaw(author *IdentityCache, unixTime int64, message string, files []git.Hash, metadata map[string]string) (*bug.AddCommentOperation, error) {
102	op, err := bug.OpAddCommentWithFiles(author.Identity, unixTime, message, files)
103	if err != nil {
104		return nil, err
105	}
106
107	for key, value := range metadata {
108		op.SetMetadata(key, value)
109	}
110}
111
112func (c *BugCache) ChangeLabels(added []string, removed []string) ([]bug.LabelChangeResult, *bug.LabelChangeOperation, error) {
113	author, err := c.repoCache.GetUserIdentity()
114	if err != nil {
115		return nil, nil, err
116	}
117
118	return c.ChangeLabelsRaw(author, time.Now().Unix(), added, removed, nil)
119}
120
121func (c *BugCache) ChangeLabelsRaw(author *IdentityCache, unixTime int64, added []string, removed []string, metadata map[string]string) ([]bug.LabelChangeResult, *bug.LabelChangeOperation, error) {
122	changes, op, err := bug.ChangeLabels(c.bug, author.Identity, unixTime, added, removed)
123	if err != nil {
124		return changes, nil, err
125	}
126
127	for key, value := range metadata {
128		op.SetMetadata(key, value)
129	}
130
131	err = c.notifyUpdated()
132	if err != nil {
133		return nil, nil, err
134	}
135
136	return changes, op, nil
137}
138
139func (c *BugCache) ForceChangeLabels(added []string, removed []string) (*bug.LabelChangeOperation, error) {
140	author, err := c.repoCache.GetUserIdentity()
141	if err != nil {
142		return nil, err
143	}
144
145	return c.ForceChangeLabelsRaw(author, time.Now().Unix(), added, removed, nil)
146}
147
148func (c *BugCache) ForceChangeLabelsRaw(author *IdentityCache, unixTime int64, added []string, removed []string, metadata map[string]string) (*bug.LabelChangeOperation, error) {
149	op, err := bug.ForceChangeLabels(c.bug, author.Identity, unixTime, added, removed)
150	if err != nil {
151		return nil, err
152	}
153
154	for key, value := range metadata {
155		op.SetMetadata(key, value)
156	}
157
158	err = c.notifyUpdated()
159	if err != nil {
160		return nil, err
161	}
162
163	return op, nil
164}
165
166func (c *BugCache) Open() (*bug.SetStatusOperation, error) {
167	author, err := c.repoCache.GetUserIdentity()
168	if err != nil {
169		return nil, err
170	}
171
172	return c.OpenRaw(author, time.Now().Unix(), nil)
173}
174
175func (c *BugCache) OpenRaw(author *IdentityCache, unixTime int64, metadata map[string]string) (*bug.SetStatusOperation, error) {
176	op, err := bug.Open(c.bug, author.Identity, unixTime)
177	if err != nil {
178		return nil, err
179	}
180
181	for key, value := range metadata {
182		op.SetMetadata(key, value)
183	}
184
185	return op, c.notifyUpdated()
186}
187
188func (c *BugCache) Close() (*bug.SetStatusOperation, error) {
189	author, err := c.repoCache.GetUserIdentity()
190	if err != nil {
191		return nil, err
192	}
193
194	return c.CloseRaw(author, time.Now().Unix(), nil)
195}
196
197func (c *BugCache) CloseRaw(author *IdentityCache, unixTime int64, metadata map[string]string) (*bug.SetStatusOperation, error) {
198	op, err := bug.Close(c.bug, author.Identity, unixTime)
199	if err != nil {
200		return nil, err
201	}
202
203	for key, value := range metadata {
204		op.SetMetadata(key, value)
205	}
206
207	return op, c.notifyUpdated()
208}
209
210func (c *BugCache) SetTitle(title string) (*bug.SetTitleOperation, error) {
211	author, err := c.repoCache.GetUserIdentity()
212	if err != nil {
213		return nil, err
214	}
215
216	return c.SetTitleRaw(author, time.Now().Unix(), title, nil)
217}
218
219func (c *BugCache) SetTitleRaw(author *IdentityCache, unixTime int64, title string, metadata map[string]string) (*bug.SetTitleOperation, error) {
220	op, err := bug.SetTitle(c.bug, author.Identity, unixTime, title)
221	if err != nil {
222		return nil, err
223	}
224
225	for key, value := range metadata {
226		op.SetMetadata(key, value)
227	}
228
229	return op, c.notifyUpdated()
230}
231
232func (c *BugCache) EditComment(target entity.Id, message string) (*bug.EditCommentOperation, error) {
233	author, err := c.repoCache.GetUserIdentity()
234	if err != nil {
235		return nil, err
236	}
237
238	return c.EditCommentRaw(author, time.Now().Unix(), target, message, nil)
239}
240
241func (c *BugCache) EditCommentRaw(author *IdentityCache, unixTime int64, target entity.Id, message string, metadata map[string]string) (*bug.EditCommentOperation, error) {
242	op, err := bug.EditComment(c.bug, author.Identity, unixTime, target, message)
243	if err != nil {
244		return nil, err
245	}
246
247	for key, value := range metadata {
248		op.SetMetadata(key, value)
249	}
250
251	return op, c.notifyUpdated()
252}
253
254func (c *BugCache) SetMetadata(target entity.Id, newMetadata map[string]string) (*bug.SetMetadataOperation, error) {
255	author, err := c.repoCache.GetUserIdentity()
256	if err != nil {
257		return nil, err
258	}
259
260	return c.SetMetadataRaw(author, time.Now().Unix(), target, newMetadata)
261}
262
263func (c *BugCache) SetMetadataRaw(author *IdentityCache, unixTime int64, target entity.Id, newMetadata map[string]string) (*bug.SetMetadataOperation, error) {
264	op, err := bug.SetMetadata(c.bug, author.Identity, unixTime, target, newMetadata)
265	if err != nil {
266		return nil, err
267	}
268
269	return op, c.notifyUpdated()
270}
271
272func (c *BugCache) Commit() error {
273	err := c.bug.Commit(c.repoCache.repo)
274	if err != nil {
275		return err
276	}
277	return c.notifyUpdated()
278}
279
280func (c *BugCache) CommitAsNeeded() error {
281	err := c.bug.CommitAsNeeded(c.repoCache.repo)
282	if err != nil {
283		return err
284	}
285	return c.notifyUpdated()
286}
287
288func (c *BugCache) NeedCommit() bool {
289	return c.bug.NeedCommit()
290}