aboutsummaryrefslogtreecommitdiffstats
path: root/bug
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2022-07-31 14:38:32 +0200
committerMichael Muré <batolettre@gmail.com>2022-07-31 14:38:32 +0200
commitd179b8b7ec7815ccac73e00f35f5cfbdc4ddbe2e (patch)
treed3faa7217cb287c7b20f2769f5c5808373aca63b /bug
parent3d454d9dc8ba2409046c0938618a70864e6eb8ef (diff)
downloadgit-bug-d179b8b7ec7815ccac73e00f35f5cfbdc4ddbe2e.tar.gz
bug: fix an issue where Id would be used, then changed due to metadata
Diffstat (limited to 'bug')
-rw-r--r--bug/bug.go6
-rw-r--r--bug/interface.go14
-rw-r--r--bug/op_add_comment.go19
-rw-r--r--bug/op_create.go26
-rw-r--r--bug/op_edit_comment.go27
-rw-r--r--bug/op_label_change.go35
-rw-r--r--bug/op_set_metadata.go2
-rw-r--r--bug/op_set_status.go16
-rw-r--r--bug/op_set_title.go18
-rw-r--r--bug/operation_test.go2
-rw-r--r--bug/with_snapshot.go9
11 files changed, 88 insertions, 86 deletions
diff --git a/bug/bug.go b/bug/bug.go
index d4f4ac2e..dce30f76 100644
--- a/bug/bug.go
+++ b/bug/bug.go
@@ -140,14 +140,14 @@ func (bug *Bug) Operations() []Operation {
}
// Compile a bug in a easily usable snapshot
-func (bug *Bug) Compile() Snapshot {
- snap := Snapshot{
+func (bug *Bug) Compile() *Snapshot {
+ snap := &Snapshot{
id: bug.Id(),
Status: OpenStatus,
}
for _, op := range bug.Operations() {
- op.Apply(&snap)
+ op.Apply(snap)
snap.Operations = append(snap.Operations, op)
}
diff --git a/bug/interface.go b/bug/interface.go
index 27a84dc5..2ae31fd1 100644
--- a/bug/interface.go
+++ b/bug/interface.go
@@ -7,22 +7,22 @@ import (
)
type Interface interface {
- // Id return the Bug identifier
+ // Id returns the Bug identifier
Id() entity.Id
- // Validate check if the Bug data is valid
+ // Validate checks if the Bug data is valid
Validate() error
// Append an operation into the staging area, to be committed later
Append(op Operation)
- // Operations return the ordered operations
+ // Operations returns the ordered operations
Operations() []Operation
- // NeedCommit indicate that the in-memory state changed and need to be commit in the repository
+ // NeedCommit indicates that the in-memory state changed and need to be commit in the repository
NeedCommit() bool
- // Commit write the staging area in Git and move the operations to the packs
+ // Commit writes the staging area in Git and move the operations to the packs
Commit(repo repository.ClockedRepo) error
// FirstOp lookup for the very first operation of the bug.
@@ -33,8 +33,8 @@ type Interface interface {
// For a valid Bug, should never be nil
LastOp() Operation
- // Compile a bug in a easily usable snapshot
- Compile() Snapshot
+ // Compile a bug in an easily usable snapshot
+ Compile() *Snapshot
// CreateLamportTime return the Lamport time of creation
CreateLamportTime() lamport.Time
diff --git a/bug/op_add_comment.go b/bug/op_add_comment.go
index b11afe34..eddd585a 100644
--- a/bug/op_add_comment.go
+++ b/bug/op_add_comment.go
@@ -79,16 +79,15 @@ type AddCommentTimelineItem struct {
// IsAuthored is a sign post method for gqlgen
func (a *AddCommentTimelineItem) IsAuthored() {}
-// Convenience function to apply the operation
-func AddComment(b Interface, author identity.Interface, unixTime int64, message string) (*AddCommentOperation, error) {
- return AddCommentWithFiles(b, author, unixTime, message, nil)
-}
-
-func AddCommentWithFiles(b Interface, author identity.Interface, unixTime int64, message string, files []repository.Hash) (*AddCommentOperation, error) {
- addCommentOp := NewAddCommentOp(author, unixTime, message, files)
- if err := addCommentOp.Validate(); err != nil {
+// AddComment is a convenience function to add a comment to a bug
+func AddComment(b Interface, author identity.Interface, unixTime int64, message string, files []repository.Hash, metadata map[string]string) (*AddCommentOperation, error) {
+ op := NewAddCommentOp(author, unixTime, message, files)
+ for key, val := range metadata {
+ op.SetMetadata(key, val)
+ }
+ if err := op.Validate(); err != nil {
return nil, err
}
- b.Append(addCommentOp)
- return addCommentOp, nil
+ b.Append(op)
+ return op, nil
}
diff --git a/bug/op_create.go b/bug/op_create.go
index ed2fd994..ca4f3d8a 100644
--- a/bug/op_create.go
+++ b/bug/op_create.go
@@ -97,20 +97,16 @@ type CreateTimelineItem struct {
// IsAuthored is a sign post method for gqlgen
func (c *CreateTimelineItem) IsAuthored() {}
-// Convenience function to apply the operation
-func Create(author identity.Interface, unixTime int64, title, message string) (*Bug, *CreateOperation, error) {
- return CreateWithFiles(author, unixTime, title, message, nil)
-}
-
-func CreateWithFiles(author identity.Interface, unixTime int64, title, message string, files []repository.Hash) (*Bug, *CreateOperation, error) {
- newBug := NewBug()
- createOp := NewCreateOp(author, unixTime, title, message, files)
-
- if err := createOp.Validate(); err != nil {
- return nil, createOp, err
+// Create is a convenience function to create a bug
+func Create(author identity.Interface, unixTime int64, title, message string, files []repository.Hash, metadata map[string]string) (*Bug, *CreateOperation, error) {
+ b := NewBug()
+ op := NewCreateOp(author, unixTime, title, message, files)
+ for key, val := range metadata {
+ op.SetMetadata(key, val)
}
-
- newBug.Append(createOp)
-
- return newBug, createOp, nil
+ if err := op.Validate(); err != nil {
+ return nil, op, err
+ }
+ b.Append(op)
+ return b, op, nil
}
diff --git a/bug/op_edit_comment.go b/bug/op_edit_comment.go
index 36c31663..70a362de 100644
--- a/bug/op_edit_comment.go
+++ b/bug/op_edit_comment.go
@@ -110,27 +110,20 @@ func NewEditCommentOp(author identity.Interface, unixTime int64, target entity.I
}
// EditComment is a convenience function to apply the operation
-func EditComment(b Interface, author identity.Interface, unixTime int64, target entity.Id, message string) (*EditCommentOperation, error) {
- return EditCommentWithFiles(b, author, unixTime, target, message, nil)
-}
-
-func EditCommentWithFiles(b Interface, author identity.Interface, unixTime int64, target entity.Id, message string, files []repository.Hash) (*EditCommentOperation, error) {
- editCommentOp := NewEditCommentOp(author, unixTime, target, message, files)
- if err := editCommentOp.Validate(); err != nil {
+func EditComment(b Interface, author identity.Interface, unixTime int64, target entity.Id, message string, files []repository.Hash, metadata map[string]string) (*EditCommentOperation, error) {
+ op := NewEditCommentOp(author, unixTime, target, message, files)
+ for key, val := range metadata {
+ op.SetMetadata(key, val)
+ }
+ if err := op.Validate(); err != nil {
return nil, err
}
- b.Append(editCommentOp)
- return editCommentOp, nil
+ b.Append(op)
+ return op, nil
}
// EditCreateComment is a convenience function to edit the body of a bug (the first comment)
-func EditCreateComment(b Interface, author identity.Interface, unixTime int64, message string) (*EditCommentOperation, error) {
- createOp := b.FirstOp().(*CreateOperation)
- return EditComment(b, author, unixTime, createOp.Id(), message)
-}
-
-// EditCreateCommentWithFiles is a convenience function to edit the body of a bug (the first comment)
-func EditCreateCommentWithFiles(b Interface, author identity.Interface, unixTime int64, message string, files []repository.Hash) (*EditCommentOperation, error) {
+func EditCreateComment(b Interface, author identity.Interface, unixTime int64, message string, files []repository.Hash, metadata map[string]string) (*EditCommentOperation, error) {
createOp := b.FirstOp().(*CreateOperation)
- return EditCommentWithFiles(b, author, unixTime, createOp.Id(), message, files)
+ return EditComment(b, author, unixTime, createOp.Id(), message, files, metadata)
}
diff --git a/bug/op_label_change.go b/bug/op_label_change.go
index 77caa7dd..8bcc7853 100644
--- a/bug/op_label_change.go
+++ b/bug/op_label_change.go
@@ -25,7 +25,7 @@ func (op *LabelChangeOperation) Id() entity.Id {
return dag.IdOperation(op, &op.OpBase)
}
-// Apply apply the operation
+// Apply applies the operation
func (op *LabelChangeOperation) Apply(snapshot *Snapshot) {
snapshot.addActor(op.Author())
@@ -113,10 +113,10 @@ func (l LabelChangeTimelineItem) Id() entity.Id {
}
// IsAuthored is a sign post method for gqlgen
-func (l *LabelChangeTimelineItem) IsAuthored() {}
+func (l LabelChangeTimelineItem) IsAuthored() {}
-// ChangeLabels is a convenience function to apply the operation
-func ChangeLabels(b Interface, author identity.Interface, unixTime int64, add, remove []string) ([]LabelChangeResult, *LabelChangeOperation, error) {
+// ChangeLabels is a convenience function to change labels on a bug
+func ChangeLabels(b Interface, author identity.Interface, unixTime int64, add, remove []string, metadata map[string]string) ([]LabelChangeResult, *LabelChangeOperation, error) {
var added, removed []Label
var results []LabelChangeResult
@@ -164,23 +164,25 @@ func ChangeLabels(b Interface, author identity.Interface, unixTime int64, add, r
return results, nil, fmt.Errorf("no label added or removed")
}
- labelOp := NewLabelChangeOperation(author, unixTime, added, removed)
-
- if err := labelOp.Validate(); err != nil {
+ op := NewLabelChangeOperation(author, unixTime, added, removed)
+ for key, val := range metadata {
+ op.SetMetadata(key, val)
+ }
+ if err := op.Validate(); err != nil {
return nil, nil, err
}
- b.Append(labelOp)
+ b.Append(op)
- return results, labelOp, nil
+ return results, op, nil
}
// ForceChangeLabels is a convenience function to apply the operation
// The difference with ChangeLabels is that no checks of deduplications are done. You are entirely
-// responsible of what you are doing. In the general case, you want to use ChangeLabels instead.
+// responsible for what you are doing. In the general case, you want to use ChangeLabels instead.
// The intended use of this function is to allow importers to create legal but unexpected label changes,
// like removing a label with no information of when it was added before.
-func ForceChangeLabels(b Interface, author identity.Interface, unixTime int64, add, remove []string) (*LabelChangeOperation, error) {
+func ForceChangeLabels(b Interface, author identity.Interface, unixTime int64, add, remove []string, metadata map[string]string) (*LabelChangeOperation, error) {
added := make([]Label, len(add))
for i, str := range add {
added[i] = Label(str)
@@ -191,15 +193,18 @@ func ForceChangeLabels(b Interface, author identity.Interface, unixTime int64, a
removed[i] = Label(str)
}
- labelOp := NewLabelChangeOperation(author, unixTime, added, removed)
+ op := NewLabelChangeOperation(author, unixTime, added, removed)
- if err := labelOp.Validate(); err != nil {
+ for key, val := range metadata {
+ op.SetMetadata(key, val)
+ }
+ if err := op.Validate(); err != nil {
return nil, err
}
- b.Append(labelOp)
+ b.Append(op)
- return labelOp, nil
+ return op, nil
}
func labelExist(labels []Label, label Label) bool {
diff --git a/bug/op_set_metadata.go b/bug/op_set_metadata.go
index 962eaa6c..08e1887b 100644
--- a/bug/op_set_metadata.go
+++ b/bug/op_set_metadata.go
@@ -10,7 +10,7 @@ func NewSetMetadataOp(author identity.Interface, unixTime int64, target entity.I
return dag.NewSetMetadataOp[*Snapshot](SetMetadataOp, author, unixTime, target, newMetadata)
}
-// Convenience function to apply the operation
+// SetMetadata is a convenience function to add metadata on another operation
func SetMetadata(b Interface, author identity.Interface, unixTime int64, target entity.Id, newMetadata map[string]string) (*dag.SetMetadataOperation[*Snapshot], error) {
op := NewSetMetadataOp(author, unixTime, target, newMetadata)
if err := op.Validate(); err != nil {
diff --git a/bug/op_set_status.go b/bug/op_set_status.go
index 33afd795..ff8df75d 100644
--- a/bug/op_set_status.go
+++ b/bug/op_set_status.go
@@ -66,11 +66,14 @@ func (s SetStatusTimelineItem) Id() entity.Id {
}
// IsAuthored is a sign post method for gqlgen
-func (s *SetStatusTimelineItem) IsAuthored() {}
+func (s SetStatusTimelineItem) IsAuthored() {}
-// Convenience function to apply the operation
-func Open(b Interface, author identity.Interface, unixTime int64) (*SetStatusOperation, error) {
+// Open is a convenience function to change a bugs state to Open
+func Open(b Interface, author identity.Interface, unixTime int64, metadata map[string]string) (*SetStatusOperation, error) {
op := NewSetStatusOp(author, unixTime, OpenStatus)
+ for key, value := range metadata {
+ op.SetMetadata(key, value)
+ }
if err := op.Validate(); err != nil {
return nil, err
}
@@ -78,9 +81,12 @@ func Open(b Interface, author identity.Interface, unixTime int64) (*SetStatusOpe
return op, nil
}
-// Convenience function to apply the operation
-func Close(b Interface, author identity.Interface, unixTime int64) (*SetStatusOperation, error) {
+// Close is a convenience function to change a bugs state to Close
+func Close(b Interface, author identity.Interface, unixTime int64, metadata map[string]string) (*SetStatusOperation, error) {
op := NewSetStatusOp(author, unixTime, ClosedStatus)
+ for key, value := range metadata {
+ op.SetMetadata(key, value)
+ }
if err := op.Validate(); err != nil {
return nil, err
}
diff --git a/bug/op_set_title.go b/bug/op_set_title.go
index 7f078795..d26a60fa 100644
--- a/bug/op_set_title.go
+++ b/bug/op_set_title.go
@@ -80,10 +80,10 @@ func (s SetTitleTimelineItem) Id() entity.Id {
}
// IsAuthored is a sign post method for gqlgen
-func (s *SetTitleTimelineItem) IsAuthored() {}
+func (s SetTitleTimelineItem) IsAuthored() {}
-// Convenience function to apply the operation
-func SetTitle(b Interface, author identity.Interface, unixTime int64, title string) (*SetTitleOperation, error) {
+// SetTitle is a convenience function to change a bugs title
+func SetTitle(b Interface, author identity.Interface, unixTime int64, title string, metadata map[string]string) (*SetTitleOperation, error) {
var lastTitleOp *SetTitleOperation
for _, op := range b.Operations() {
switch op := op.(type) {
@@ -99,12 +99,14 @@ func SetTitle(b Interface, author identity.Interface, unixTime int64, title stri
was = b.FirstOp().(*CreateOperation).Title
}
- setTitleOp := NewSetTitleOp(author, unixTime, title, was)
-
- if err := setTitleOp.Validate(); err != nil {
+ op := NewSetTitleOp(author, unixTime, title, was)
+ for key, value := range metadata {
+ op.SetMetadata(key, value)
+ }
+ if err := op.Validate(); err != nil {
return nil, err
}
- b.Append(setTitleOp)
- return setTitleOp, nil
+ b.Append(op)
+ return op, nil
}
diff --git a/bug/operation_test.go b/bug/operation_test.go
index d95ffff2..3cfc85c4 100644
--- a/bug/operation_test.go
+++ b/bug/operation_test.go
@@ -104,7 +104,7 @@ func TestID(t *testing.T) {
err = rene.Commit(repo)
require.NoError(t, err)
- b, op, err := Create(rene, time.Now().Unix(), "title", "message")
+ b, op, err := Create(rene, time.Now().Unix(), "title", "message", nil, nil)
require.NoError(t, err)
id1 := op.Id()
diff --git a/bug/with_snapshot.go b/bug/with_snapshot.go
index 9b706d61..0474cac7 100644
--- a/bug/with_snapshot.go
+++ b/bug/with_snapshot.go
@@ -1,6 +1,8 @@
package bug
-import "github.com/MichaelMure/git-bug/repository"
+import (
+ "github.com/MichaelMure/git-bug/repository"
+)
var _ Interface = &WithSnapshot{}
@@ -10,11 +12,10 @@ type WithSnapshot struct {
snap *Snapshot
}
-// Snapshot return the current snapshot
-func (b *WithSnapshot) Snapshot() *Snapshot {
+func (b *WithSnapshot) Compile() *Snapshot {
if b.snap == nil {
snap := b.Bug.Compile()
- b.snap = &snap
+ b.snap = snap
}
return b.snap
}