diff options
-rw-r--r-- | Gopkg.lock | 9 | ||||
-rw-r--r-- | bug/bug.go | 4 | ||||
-rw-r--r-- | bug/bug_actions_test.go (renamed from tests/bug_actions_test.go) | 143 | ||||
-rw-r--r-- | bug/bug_test.go (renamed from tests/bug_test.go) | 57 | ||||
-rw-r--r-- | bug/op_add_comment.go (renamed from operations/add_comment.go) | 27 | ||||
-rw-r--r-- | bug/op_create.go (renamed from operations/create.go) | 27 | ||||
-rw-r--r-- | bug/op_create_test.go (renamed from operations/create_test.go) | 11 | ||||
-rw-r--r-- | bug/op_label_change.go (renamed from operations/label_change.go) | 35 | ||||
-rw-r--r-- | bug/op_set_status.go | 63 | ||||
-rw-r--r-- | bug/op_set_title.go (renamed from operations/set_title.go) | 27 | ||||
-rw-r--r-- | bug/operation.go | 28 | ||||
-rw-r--r-- | bug/operation_iterator_test.go (renamed from tests/operation_iterator_test.go) | 20 | ||||
-rw-r--r-- | bug/operation_pack.go | 53 | ||||
-rw-r--r-- | bug/operation_pack_test.go (renamed from tests/operation_pack_test.go) | 19 | ||||
-rw-r--r-- | bug/operation_test.go (renamed from operations/operations_test.go) | 32 | ||||
-rw-r--r-- | cache/bug_cache.go | 15 | ||||
-rw-r--r-- | cache/repo_cache.go | 3 | ||||
-rw-r--r-- | graphql/gqlgen.yml | 10 | ||||
-rw-r--r-- | graphql/graph/gen_graph.go | 103 | ||||
-rw-r--r-- | graphql/resolvers/operations.go | 23 | ||||
-rw-r--r-- | misc/random_bugs/create_random_bugs.go | 17 | ||||
-rw-r--r-- | operations/operations.go | 17 | ||||
-rw-r--r-- | operations/set_status.go | 60 | ||||
-rw-r--r-- | termui/show_bug.go | 22 | ||||
-rw-r--r-- | tests/read_bugs_test.go | 26 | ||||
-rw-r--r-- | vendor/github.com/go-test/deep/.gitignore | 2 | ||||
-rw-r--r-- | vendor/github.com/go-test/deep/.travis.yml | 13 | ||||
-rw-r--r-- | vendor/github.com/go-test/deep/CHANGES.md | 9 | ||||
-rw-r--r-- | vendor/github.com/go-test/deep/LICENSE | 21 | ||||
-rw-r--r-- | vendor/github.com/go-test/deep/README.md | 51 | ||||
-rw-r--r-- | vendor/github.com/go-test/deep/deep.go | 352 |
31 files changed, 881 insertions, 418 deletions
@@ -66,6 +66,14 @@ version = "v1.7.0" [[projects]] + digest = "1:7f89e0c888fb99c61055c646f5678aae645b0b0a1443d9b2dcd9964d850827ce" + name = "github.com/go-test/deep" + packages = ["."] + pruneopts = "UT" + revision = "6592d9cc0a499ad2d5f574fde80a2b5c5cc3b4f5" + version = "v1.0.1" + +[[projects]] digest = "1:97df918963298c287643883209a2c3f642e6593379f97ab400c2a2e219ab647d" name = "github.com/golang/protobuf" packages = ["proto"] @@ -385,6 +393,7 @@ "github.com/cheekybits/genny/generic", "github.com/dustin/go-humanize", "github.com/fatih/color", + "github.com/go-test/deep", "github.com/gorilla/mux", "github.com/icrowley/fake", "github.com/jroimartin/gocui", @@ -300,7 +300,7 @@ func (bug *Bug) Validate() error { // The very first Op should be a CreateOp firstOp := bug.FirstOp() - if firstOp == nil || firstOp.OpType() != CreateOp { + if firstOp == nil || firstOp.base().OperationType != CreateOp { return fmt.Errorf("first operation should be a Create op") } @@ -308,7 +308,7 @@ func (bug *Bug) Validate() error { it := NewOperationIterator(bug) createCount := 0 for it.Next() { - if it.Value().OpType() == CreateOp { + if it.Value().base().OperationType == CreateOp { createCount++ } } diff --git a/tests/bug_actions_test.go b/bug/bug_actions_test.go index 50333cd2..44409296 100644 --- a/tests/bug_actions_test.go +++ b/bug/bug_actions_test.go @@ -1,14 +1,11 @@ -package tests +package bug import ( + "github.com/MichaelMure/git-bug/repository" "io/ioutil" "log" "os" "testing" - - "github.com/MichaelMure/git-bug/bug" - "github.com/MichaelMure/git-bug/operations" - "github.com/MichaelMure/git-bug/repository" ) func createRepo(bare bool) *repository.GitRepo { @@ -71,37 +68,37 @@ func TestPushPull(t *testing.T) { repoA, repoB, remote := setupRepos(t) defer cleanupRepos(repoA, repoB, remote) - bug1, err := operations.Create(rene, unix, "bug1", "message") + bug1, err := Create(rene, unix, "bug1", "message") checkErr(t, err) err = bug1.Commit(repoA) checkErr(t, err) // A --> remote --> B - _, err = bug.Push(repoA, "origin") + _, err = Push(repoA, "origin") checkErr(t, err) - err = bug.Pull(repoB, "origin") + err = Pull(repoB, "origin") checkErr(t, err) - bugs := allBugs(t, bug.ReadAllLocalBugs(repoB)) + bugs := allBugs(t, ReadAllLocalBugs(repoB)) if len(bugs) != 1 { t.Fatal("Unexpected number of bugs") } // B --> remote --> A - bug2, err := operations.Create(rene, unix, "bug2", "message") + bug2, err := Create(rene, unix, "bug2", "message") checkErr(t, err) err = bug2.Commit(repoB) checkErr(t, err) - _, err = bug.Push(repoB, "origin") + _, err = Push(repoB, "origin") checkErr(t, err) - err = bug.Pull(repoA, "origin") + err = Pull(repoA, "origin") checkErr(t, err) - bugs = allBugs(t, bug.ReadAllLocalBugs(repoA)) + bugs = allBugs(t, ReadAllLocalBugs(repoA)) if len(bugs) != 2 { t.Fatal("Unexpected number of bugs") @@ -114,8 +111,8 @@ func checkErr(t testing.TB, err error) { } } -func allBugs(t testing.TB, bugs <-chan bug.StreamedBug) []*bug.Bug { - var result []*bug.Bug +func allBugs(t testing.TB, bugs <-chan StreamedBug) []*Bug { + var result []*Bug for streamed := range bugs { if streamed.Err != nil { t.Fatal(streamed.Err) @@ -139,43 +136,43 @@ func _RebaseTheirs(t testing.TB) { repoA, repoB, remote := setupRepos(t) defer cleanupRepos(repoA, repoB, remote) - bug1, err := operations.Create(rene, unix, "bug1", "message") + bug1, err := Create(rene, unix, "bug1", "message") checkErr(t, err) err = bug1.Commit(repoA) checkErr(t, err) // A --> remote - _, err = bug.Push(repoA, "origin") + _, err = Push(repoA, "origin") checkErr(t, err) // remote --> B - err = bug.Pull(repoB, "origin") + err = Pull(repoB, "origin") checkErr(t, err) - bug2, err := bug.ReadLocalBug(repoB, bug1.Id()) + bug2, err := ReadLocalBug(repoB, bug1.Id()) checkErr(t, err) - operations.Comment(bug2, rene, unix, "message2") - operations.Comment(bug2, rene, unix, "message3") - operations.Comment(bug2, rene, unix, "message4") + AddComment(bug2, rene, unix, "message2") + AddComment(bug2, rene, unix, "message3") + AddComment(bug2, rene, unix, "message4") err = bug2.Commit(repoB) checkErr(t, err) // B --> remote - _, err = bug.Push(repoB, "origin") + _, err = Push(repoB, "origin") checkErr(t, err) // remote --> A - err = bug.Pull(repoA, "origin") + err = Pull(repoA, "origin") checkErr(t, err) - bugs := allBugs(t, bug.ReadAllLocalBugs(repoB)) + bugs := allBugs(t, ReadAllLocalBugs(repoB)) if len(bugs) != 1 { t.Fatal("Unexpected number of bugs") } - bug3, err := bug.ReadLocalBug(repoA, bug1.Id()) + bug3, err := ReadLocalBug(repoA, bug1.Id()) checkErr(t, err) if nbOps(bug3) != 4 { @@ -197,48 +194,48 @@ func _RebaseOurs(t testing.TB) { repoA, repoB, remote := setupRepos(t) defer cleanupRepos(repoA, repoB, remote) - bug1, err := operations.Create(rene, unix, "bug1", "message") + bug1, err := Create(rene, unix, "bug1", "message") checkErr(t, err) err = bug1.Commit(repoA) checkErr(t, err) // A --> remote - _, err = bug.Push(repoA, "origin") + _, err = Push(repoA, "origin") checkErr(t, err) // remote --> B - err = bug.Pull(repoB, "origin") + err = Pull(repoB, "origin") checkErr(t, err) - operations.Comment(bug1, rene, unix, "message2") - operations.Comment(bug1, rene, unix, "message3") - operations.Comment(bug1, rene, unix, "message4") + AddComment(bug1, rene, unix, "message2") + AddComment(bug1, rene, unix, "message3") + AddComment(bug1, rene, unix, "message4") err = bug1.Commit(repoA) checkErr(t, err) - operations.Comment(bug1, rene, unix, "message5") - operations.Comment(bug1, rene, unix, "message6") - operations.Comment(bug1, rene, unix, "message7") + AddComment(bug1, rene, unix, "message5") + AddComment(bug1, rene, unix, "message6") + AddComment(bug1, rene, unix, "message7") err = bug1.Commit(repoA) checkErr(t, err) - operations.Comment(bug1, rene, unix, "message8") - operations.Comment(bug1, rene, unix, "message9") - operations.Comment(bug1, rene, unix, "message10") + AddComment(bug1, rene, unix, "message8") + AddComment(bug1, rene, unix, "message9") + AddComment(bug1, rene, unix, "message10") err = bug1.Commit(repoA) checkErr(t, err) // remote --> A - err = bug.Pull(repoA, "origin") + err = Pull(repoA, "origin") checkErr(t, err) - bugs := allBugs(t, bug.ReadAllLocalBugs(repoA)) + bugs := allBugs(t, ReadAllLocalBugs(repoA)) if len(bugs) != 1 { t.Fatal("Unexpected number of bugs") } - bug2, err := bug.ReadLocalBug(repoA, bug1.Id()) + bug2, err := ReadLocalBug(repoA, bug1.Id()) checkErr(t, err) if nbOps(bug2) != 10 { @@ -246,8 +243,8 @@ func _RebaseOurs(t testing.TB) { } } -func nbOps(b *bug.Bug) int { - it := bug.NewOperationIterator(b) +func nbOps(b *Bug) int { + it := NewOperationIterator(b) counter := 0 for it.Next() { counter++ @@ -269,73 +266,73 @@ func _RebaseConflict(t testing.TB) { repoA, repoB, remote := setupRepos(t) defer cleanupRepos(repoA, repoB, remote) - bug1, err := operations.Create(rene, unix, "bug1", "message") + bug1, err := Create(rene, unix, "bug1", "message") checkErr(t, err) err = bug1.Commit(repoA) checkErr(t, err) // A --> remote - _, err = bug.Push(repoA, "origin") + _, err = Push(repoA, "origin") checkErr(t, err) // remote --> B - err = bug.Pull(repoB, "origin") + err = Pull(repoB, "origin") checkErr(t, err) - operations.Comment(bug1, rene, unix, "message2") - operations.Comment(bug1, rene, unix, "message3") - operations.Comment(bug1, rene, unix, "message4") + AddComment(bug1, rene, unix, "message2") + AddComment(bug1, rene, unix, "message3") + AddComment(bug1, rene, unix, "message4") err = bug1.Commit(repoA) checkErr(t, err) - operations.Comment(bug1, rene, unix, "message5") - operations.Comment(bug1, rene, unix, "message6") - operations.Comment(bug1, rene, unix, "message7") + AddComment(bug1, rene, unix, "message5") + AddComment(bug1, rene, unix, "message6") + AddComment(bug1, rene, unix, "message7") err = bug1.Commit(repoA) checkErr(t, err) - operations.Comment(bug1, rene, unix, "message8") - operations.Comment(bug1, rene, unix, "message9") - operations.Comment(bug1, rene, unix, "message10") + AddComment(bug1, rene, unix, "message8") + AddComment(bug1, rene, unix, "message9") + AddComment(bug1, rene, unix, "message10") err = bug1.Commit(repoA) checkErr(t, err) - bug2, err := bug.ReadLocalBug(repoB, bug1.Id()) + bug2, err := ReadLocalBug(repoB, bug1.Id()) checkErr(t, err) - operations.Comment(bug2, rene, unix, "message11") - operations.Comment(bug2, rene, unix, "message12") - operations.Comment(bug2, rene, unix, "message13") + AddComment(bug2, rene, unix, "message11") + AddComment(bug2, rene, unix, "message12") + AddComment(bug2, rene, unix, "message13") err = bug2.Commit(repoB) checkErr(t, err) - operations.Comment(bug2, rene, unix, "message14") - operations.Comment(bug2, rene, unix, "message15") - operations.Comment(bug2, rene, unix, "message16") + AddComment(bug2, rene, unix, "message14") + AddComment(bug2, rene, unix, "message15") + AddComment(bug2, rene, unix, "message16") err = bug2.Commit(repoB) checkErr(t, err) - operations.Comment(bug2, rene, unix, "message17") - operations.Comment(bug2, rene, unix, "message18") - operations.Comment(bug2, rene, unix, "message19") + AddComment(bug2, rene, unix, "message17") + AddComment(bug2, rene, unix, "message18") + AddComment(bug2, rene, unix, "message19") err = bug2.Commit(repoB) checkErr(t, err) // A --> remote - _, err = bug.Push(repoA, "origin") + _, err = Push(repoA, "origin") checkErr(t, err) // remote --> B - err = bug.Pull(repoB, "origin") + err = Pull(repoB, "origin") checkErr(t, err) - bugs := allBugs(t, bug.ReadAllLocalBugs(repoB)) + bugs := allBugs(t, ReadAllLocalBugs(repoB)) if len(bugs) != 1 { t.Fatal("Unexpected number of bugs") } - bug3, err := bug.ReadLocalBug(repoB, bug1.Id()) + bug3, err := ReadLocalBug(repoB, bug1.Id()) checkErr(t, err) if nbOps(bug3) != 19 { @@ -343,20 +340,20 @@ func _RebaseConflict(t testing.TB) { } // B --> remote - _, err = bug.Push(repoB, "origin") + _, err = Push(repoB, "origin") checkErr(t, err) // remote --> A - err = bug.Pull(repoA, "origin") + err = Pull(repoA, "origin") checkErr(t, err) - bugs = allBugs(t, bug.ReadAllLocalBugs(repoA)) + bugs = allBugs(t, ReadAllLocalBugs(repoA)) if len(bugs) != 1 { t.Fatal("Unexpected number of bugs") } - bug4, err := bug.ReadLocalBug(repoA, bug1.Id()) + bug4, err := ReadLocalBug(repoA, bug1.Id()) checkErr(t, err) if nbOps(bug4) != 19 { diff --git a/tests/bug_test.go b/bug/bug_test.go index 02336974..d85db6d2 100644 --- a/tests/bug_test.go +++ b/bug/bug_test.go @@ -1,8 +1,8 @@ -package tests +package bug import ( - "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/repository" + "github.com/go-test/deep" "testing" ) @@ -10,7 +10,7 @@ import ( func TestBugId(t *testing.T) { mockRepo := repository.NewMockRepoForTest() - bug1 := bug.NewBug() + bug1 := NewBug() bug1.Append(createOp) @@ -26,7 +26,7 @@ func TestBugId(t *testing.T) { func TestBugValidity(t *testing.T) { mockRepo := repository.NewMockRepoForTest() - bug1 := bug.NewBug() + bug1 := NewBug() if bug1.Validate() == nil { t.Fatal("Empty bug should be invalid") @@ -55,27 +55,28 @@ func TestBugValidity(t *testing.T) { } } -//func TestBugSerialisation(t *testing.T) { -// bug1, err := bug.NewBug() -// if err != nil { -// t.Error(err) -// } -// -// bug1.Append(createOp) -// bug1.Append(setTitleOp) -// bug1.Append(setTitleOp) -// bug1.Append(addCommentOp) -// -// repo := repository.NewMockRepoForTest() -// -// bug1.Commit(repo) -// -// bug2, err := bug.ReadBug(repo, bug.BugsRefPattern+bug1.Id()) -// if err != nil { -// t.Error(err) -// } -// -// if !reflect.DeepEqual(bug1, bug2) { -// t.Fatalf("%v different than %v", bug1, bug2) -// } -//} +func TestBugSerialisation(t *testing.T) { + bug1 := NewBug() + + bug1.Append(createOp) + bug1.Append(setTitleOp) + bug1.Append(setTitleOp) + bug1.Append(addCommentOp) + + repo := repository.NewMockRepoForTest() + + bug1.Commit(repo) + + bug2, err := ReadLocalBug(repo, bug1.Id()) + if err != nil { + t.Error(err) + } + + // ignore some fields + bug2.packs[0].commitHash = bug1.packs[0].commitHash + + deep.CompareUnexportedFields = true + if diff := deep.Equal(bug1, bug2); diff != nil { + t.Fatal(diff) + } +} diff --git a/operations/add_comment.go b/bug/op_add_comment.go index 56a2c606..0a3a5a37 100644 --- a/operations/add_comment.go +++ b/bug/op_add_comment.go @@ -1,26 +1,29 @@ -package operations +package bug import ( "fmt" - "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/util/git" "github.com/MichaelMure/git-bug/util/text" ) // AddCommentOperation will add a new comment in the bug -var _ bug.Operation = AddCommentOperation{} +var _ Operation = AddCommentOperation{} type AddCommentOperation struct { - *bug.OpBase + *OpBase Message string `json:"message"` // TODO: change for a map[string]util.hash to store the filename ? Files []git.Hash `json:"files"` } -func (op AddCommentOperation) Apply(snapshot bug.Snapshot) bug.Snapshot { - comment := bug.Comment{ +func (op AddCommentOperation) base() *OpBase { + return op.OpBase +} + +func (op AddCommentOperation) Apply(snapshot Snapshot) Snapshot { + comment := Comment{ Message: op.Message, Author: op.Author, Files: op.Files, @@ -37,7 +40,7 @@ func (op AddCommentOperation) GetFiles() []git.Hash { } func (op AddCommentOperation) Validate() error { - if err := bug.OpBaseValidate(op, bug.AddCommentOp); err != nil { + if err := opBaseValidate(op, AddCommentOp); err != nil { return err } @@ -52,20 +55,20 @@ func (op AddCommentOperation) Validate() error { return nil } -func NewAddCommentOp(author bug.Person, unixTime int64, message string, files []git.Hash) AddCommentOperation { +func NewAddCommentOp(author Person, unixTime int64, message string, files []git.Hash) AddCommentOperation { return AddCommentOperation{ - OpBase: bug.NewOpBase(bug.AddCommentOp, author, unixTime), + OpBase: newOpBase(AddCommentOp, author, unixTime), Message: message, Files: files, } } // Convenience function to apply the operation -func Comment(b bug.Interface, author bug.Person, unixTime int64, message string) error { - return CommentWithFiles(b, author, unixTime, message, nil) +func AddComment(b Interface, author Person, unixTime int64, message string) error { + return AddCommentWithFiles(b, author, unixTime, message, nil) } -func CommentWithFiles(b bug.Interface, author bug.Person, unixTime int64, message string, files []git.Hash) error { +func AddCommentWithFiles(b Interface, author Person, unixTime int64, message string, files []git.Hash) error { addCommentOp := NewAddCommentOp(author, unixTime, message, files) if err := addCommentOp.Validate(); err != nil { return err diff --git a/operations/create.go b/bug/op_create.go index fd66e732..2852a519 100644 --- a/operations/create.go +++ b/bug/op_create.go @@ -1,28 +1,31 @@ -package operations +package bug import ( "fmt" "strings" - "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/util/git" "github.com/MichaelMure/git-bug/util/text" ) // CreateOperation define the initial creation of a bug -var _ bug.Operation = CreateOperation{} +var _ Operation = CreateOperation{} type CreateOperation struct { - *bug.OpBase + *OpBase Title string `json:"title"` Message string `json:"message"` Files []git.Hash `json:"files"` } -func (op CreateOperation) Apply(snapshot bug.Snapshot) bug.Snapshot { +func (op CreateOperation) base() *OpBase { + return op.OpBase +} + +func (op CreateOperation) Apply(snapshot Snapshot) Snapshot { snapshot.Title = op.Title - snapshot.Comments = []bug.Comment{ + snapshot.Comments = []Comment{ { Message: op.Message, Author: op.Author, @@ -39,7 +42,7 @@ func (op CreateOperation) GetFiles() []git.Hash { } func (op CreateOperation) Validate() error { - if err := bug.OpBaseValidate(op, bug.CreateOp); err != nil { + if err := opBaseValidate(op, CreateOp); err != nil { return err } @@ -62,9 +65,9 @@ func (op CreateOperation) Validate() error { return nil } -func NewCreateOp(author bug.Person, unixTime int64, title, message string, files []git.Hash) CreateOperation { +func NewCreateOp(author Person, unixTime int64, title, message string, files []git.Hash) CreateOperation { return CreateOperation{ - OpBase: bug.NewOpBase(bug.CreateOp, author, unixTime), + OpBase: newOpBase(CreateOp, author, unixTime), Title: title, Message: message, Files: files, @@ -72,12 +75,12 @@ func NewCreateOp(author bug.Person, unixTime int64, title, message string, files } // Convenience function to apply the operation -func Create(author bug.Person, unixTime int64, title, message string) (*bug.Bug, error) { +func Create(author Person, unixTime int64, title, message string) (*Bug, error) { return CreateWithFiles(author, unixTime, title, message, nil) } -func CreateWithFiles(author bug.Person, unixTime int64, title, message string, files []git.Hash) (*bug.Bug, error) { - newBug := bug.NewBug() +func CreateWithFiles(author Person, unixTime int64, title, message string, files []git.Hash) (*Bug, error) { + newBug := NewBug() createOp := NewCreateOp(author, unixTime, title, message, files) if err := createOp.Validate(); err != nil { diff --git a/operations/create_test.go b/bug/op_create_test.go index c32b2868..338067aa 100644 --- a/operations/create_test.go +++ b/bug/op_create_test.go @@ -1,16 +1,15 @@ -package operations +package bug import ( - "github.com/MichaelMure/git-bug/bug" "reflect" "testing" "time" ) func TestCreate(t *testing.T) { - snapshot := bug.Snapshot{} + snapshot := Snapshot{} - var rene = bug.Person{ + var rene = Person{ Name: "René Descartes", Email: "rene@descartes.fr", } @@ -21,9 +20,9 @@ func TestCreate(t *testing.T) { snapshot = create.Apply(snapshot) - expected := bug.Snapshot{ + expected := Snapshot{ Title: "title", - Comments: []bug.Comment{ + Comments: []Comment{ {Author: rene, Message: "message", UnixTime: create.UnixTime}, }, Author: rene, diff --git a/operations/label_change.go b/bug/op_label_change.go index 83e3e692..120671fb 100644 --- a/operations/label_change.go +++ b/bug/op_label_change.go @@ -1,24 +1,27 @@ -package operations +package bug import ( "fmt" "sort" - "github.com/MichaelMure/git-bug/bug" "github.com/pkg/errors" ) -var _ bug.Operation = LabelChangeOperation{} +var _ Operation = LabelChangeOperation{} // LabelChangeOperation define a Bug operation to add or remove labels type LabelChangeOperation struct { - *bug.OpBase - Added []bug.Label `json:"added"` - Removed []bug.Label `json:"removed"` + *OpBase + Added []Label `json:"added"` + Removed []Label `json:"removed"` +} + +func (op LabelChangeOperation) base() *OpBase { + return op.OpBase } // Apply apply the operation -func (op LabelChangeOperation) Apply(snapshot bug.Snapshot) bug.Snapshot { +func (op LabelChangeOperation) Apply(snapshot Snapshot) Snapshot { // Add in the set AddLoop: for _, added := range op.Added { @@ -51,7 +54,7 @@ AddLoop: } func (op LabelChangeOperation) Validate() error { - if err := bug.OpBaseValidate(op, bug.LabelChangeOp); err != nil { + if err := opBaseValidate(op, LabelChangeOp); err != nil { return err } @@ -74,23 +77,23 @@ func (op LabelChangeOperation) Validate() error { return nil } -func NewLabelChangeOperation(author bug.Person, unixTime int64, added, removed []bug.Label) LabelChangeOperation { +func NewLabelChangeOperation(author Person, unixTime int64, added, removed []Label) LabelChangeOperation { return LabelChangeOperation{ - OpBase: bug.NewOpBase(bug.LabelChangeOp, author, unixTime), + OpBase: newOpBase(LabelChangeOp, author, unixTime), Added: added, Removed: removed, } } // ChangeLabels is a convenience function to apply the operation -func ChangeLabels(b bug.Interface, author bug.Person, unixTime int64, add, remove []string) ([]LabelChangeResult, error) { - var added, removed []bug.Label +func ChangeLabels(b Interface, author Person, unixTime int64, add, remove []string) ([]LabelChangeResult, error) { + var added, removed []Label var results []LabelChangeResult snap := b.Compile() for _, str := range add { - label := bug.Label(str) + label := Label(str) // check for duplicate if labelExist(added, label) { @@ -109,7 +112,7 @@ func ChangeLabels(b bug.Interface, author bug.Person, unixTime int64, add, remov } for _, str := range remove { - label := bug.Label(str) + label := Label(str) // check for duplicate if labelExist(removed, label) { @@ -142,7 +145,7 @@ func ChangeLabels(b bug.Interface, author bug.Person, unixTime int64, add, remov return results, nil } -func labelExist(labels []bug.Label, label bug.Label) bool { +func labelExist(labels []Label, label Label) bool { for _, l := range labels { if l == label { return true @@ -164,7 +167,7 @@ const ( ) type LabelChangeResult struct { - Label bug.Label + Label Label Status LabelChangeStatus } diff --git a/bug/op_set_status.go b/bug/op_set_status.go new file mode 100644 index 00000000..d6df3da4 --- /dev/null +++ b/bug/op_set_status.go @@ -0,0 +1,63 @@ +package bug + +import ( + "github.com/pkg/errors" +) + +// SetStatusOperation will change the status of a bug + +var _ Operation = SetStatusOperation{} + +type SetStatusOperation struct { + *OpBase + Status Status `json:"status"` +} + +func (op SetStatusOperation) base() *OpBase { + return op.OpBase +} + +func (op SetStatusOperation) Apply(snapshot Snapshot) Snapshot { + snapshot.Status = op.Status + + return snapshot +} + +func (op SetStatusOperation) Validate() error { + if err := opBaseValidate(op, SetStatusOp); err != nil { + return err + } + + if err := op.Status.Validate(); err != nil { + return errors.Wrap(err, "status") + } + + return nil +} + +func NewSetStatusOp(author Person, unixTime int64, status Status) SetStatusOperation { + return SetStatusOperation{ + OpBase: newOpBase(SetStatusOp, author, unixTime), + Status: status, + } +} + +// Convenience function to apply the operation +func Open(b Interface, author Person, unixTime int64) error { + op := NewSetStatusOp(author, unixTime, OpenStatus) + if err := op.Validate(); err != nil { + return err + } + b.Append(op) + return nil +} + +// Convenience function to apply the operation +func Close(b Interface, author Person, unixTime int64) error { + op := NewSetStatusOp(author, unixTime, ClosedStatus) + if err := op.Validate(); err != nil { + return err + } + b.Append(op) + return nil +} diff --git a/operations/set_title.go b/bug/op_set_title.go index e6964a65..e8c5caf8 100644 --- a/operations/set_title.go +++ b/bug/op_set_title.go @@ -1,31 +1,34 @@ -package operations +package bug import ( "fmt" "strings" - "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/util/text" ) // SetTitleOperation will change the title of a bug -var _ bug.Operation = SetTitleOperation{} +var _ Operation = SetTitleOperation{} type SetTitleOperation struct { - *bug.OpBase + *OpBase Title string `json:"title"` Was string `json:"was"` } -func (op SetTitleOperation) Apply(snapshot bug.Snapshot) bug.Snapshot { +func (op SetTitleOperation) base() *OpBase { + return op.OpBase +} + +func (op SetTitleOperation) Apply(snapshot Snapshot) Snapshot { snapshot.Title = op.Title return snapshot } func (op SetTitleOperation) Validate() error { - if err := bug.OpBaseValidate(op, bug.SetTitleOp); err != nil { + if err := opBaseValidate(op, SetTitleOp); err != nil { return err } @@ -52,22 +55,22 @@ func (op SetTitleOperation) Validate() error { return nil } -func NewSetTitleOp(author bug.Person, unixTime int64, title string, was string) SetTitleOperation { +func NewSetTitleOp(author Person, unixTime int64, title string, was string) SetTitleOperation { return SetTitleOperation{ - OpBase: bug.NewOpBase(bug.SetTitleOp, author, unixTime), + OpBase: newOpBase(SetTitleOp, author, unixTime), Title: title, Was: was, } } // Convenience function to apply the operation -func SetTitle(b bug.Interface, author bug.Person, unixTime int64, title string) error { - it := bug.NewOperationIterator(b) +func SetTitle(b Interface, author Person, unixTime int64, title string) error { + it := NewOperationIterator(b) - var lastTitleOp bug.Operation + var lastTitleOp Operation for it.Next() { op := it.Value() - if op.OpType() == bug.SetTitleOp { + if op.base().OperationType == SetTitleOp { lastTitleOp = op } } diff --git a/bug/operation.go b/bug/operation.go index a408e167..cd4094dc 100644 --- a/bug/operation.go +++ b/bug/operation.go @@ -22,14 +22,12 @@ const ( // Operation define the interface to fulfill for an edit operation of a Bug type Operation interface { - // OpType return the type of operation - OpType() OperationType + // base return the OpBase of the Operation, for package internal use + base() *OpBase // Time return the time when the operation was added Time() time.Time // GetUnixTime return the unix timestamp when the operation was added GetUnixTime() int64 - // GetAuthor return the author of the operation - GetAuthor() Person // GetFiles return the files needed by this operation GetFiles() []git.Hash // Apply the operation to a Snapshot to create the final state @@ -50,8 +48,8 @@ type OpBase struct { Metadata map[string]string `json:"metadata,omitempty"` } -// NewOpBase is the constructor for an OpBase -func NewOpBase(opType OperationType, author Person, unixTime int64) *OpBase { +// newOpBase is the constructor for an OpBase +func newOpBase(opType OperationType, author Person, unixTime int64) *OpBase { return &OpBase{ OperationType: opType, Author: author, @@ -59,11 +57,6 @@ func NewOpBase(opType OperationType, author Person, unixTime int64) *OpBase { } } -// OpType return the type of operation -func (op *OpBase) OpType() OperationType { - return op.OperationType -} - // Time return the time when the operation was added func (op *OpBase) Time() time.Time { return time.Unix(op.UnixTime, 0) @@ -74,27 +67,22 @@ func (op *OpBase) GetUnixTime() int64 { return op.UnixTime } -// GetAuthor return the author of the operation -func (op *OpBase) GetAuthor() Person { - return op.Author -} - // GetFiles return the files needed by this operation func (op *OpBase) GetFiles() []git.Hash { return nil } // Validate check the OpBase for errors -func OpBaseValidate(op Operation, opType OperationType) error { - if op.OpType() != opType { - return fmt.Errorf("incorrect operation type (expected: %v, actual: %v)", opType, op.OpType()) +func opBaseValidate(op Operation, opType OperationType) error { + if op.base().OperationType != opType { + return fmt.Errorf("incorrect operation type (expected: %v, actual: %v)", opType, op.base().OperationType) } if op.GetUnixTime() == 0 { return fmt.Errorf("time not set") } - if err := op.GetAuthor().Validate(); err != nil { + if err := op.base().Author.Validate(); err != nil { return errors.Wrap(err, "author") } diff --git a/tests/operation_iterator_test.go b/bug/operation_iterator_test.go index 524a639c..506cc94f 100644 --- a/tests/operation_iterator_test.go +++ b/bug/operation_iterator_test.go @@ -1,32 +1,30 @@ -package tests +package bug import ( - "github.com/MichaelMure/git-bug/bug" - "github.com/MichaelMure/git-bug/operations" "github.com/MichaelMure/git-bug/repository" "testing" "time" ) var ( - rene = bug.Person{ + rene = Person{ Name: "René Descartes", Email: "rene@descartes.fr", } unix = time.Now().Unix() - createOp = operations.NewCreateOp(rene, unix, "title", "message", nil) - setTitleOp = operations.NewSetTitleOp(rene, unix, "title2", "title1") - addCommentOp = operations.NewAddCommentOp(rene, unix, "message2", nil) - setStatusOp = operations.NewSetStatusOp(rene, unix, bug.ClosedStatus) - labelChangeOp = operations.NewLabelChangeOperation(rene, unix, []bug.Label{"added"}, []bug.Label{"removed"}) + createOp = NewCreateOp(rene, unix, "title", "message", nil) + setTitleOp = NewSetTitleOp(rene, unix, "title2", "title1") + addCommentOp = NewAddCommentOp(rene, unix, "message2", nil) + setStatusOp = NewSetStatusOp(rene, unix, ClosedStatus) + labelChangeOp = NewLabelChangeOperation(rene, unix, []Label{"added"}, []Label{"removed"}) ) func TestOpIterator(t *testing.T) { mockRepo := repository.NewMockRepoForTest() - bug1 := bug.NewBug() + bug1 := NewBug() // first pack bug1.Append(createOp) @@ -47,7 +45,7 @@ func TestOpIterator(t *testing.T) { bug1.Append(setTitleOp) bug1.Append(setTitleOp) - it := bug.NewOperationIterator(bug1) + it := NewOperationIterator(bug1) counter := 0 for it.Next() { diff --git a/bug/operation_pack.go b/bug/operation_pack.go index 03d538d5..2da8bee0 100644 --- a/bug/operation_pack.go +++ b/bug/operation_pack.go @@ -3,7 +3,6 @@ package bug import ( "encoding/json" "fmt" - "reflect" "github.com/MichaelMure/git-bug/repository" "github.com/MichaelMure/git-bug/util/git" @@ -25,17 +24,6 @@ type OperationPack struct { commitHash git.Hash } -// hold the different operation type to instantiate to parse JSON -var operations map[OperationType]reflect.Type - -// Register will register a new type of Operation to be able to parse the corresponding JSON -func Register(t OperationType, op interface{}) { - if operations == nil { - operations = make(map[OperationType]reflect.Type) - } - operations[t] = reflect.TypeOf(op) -} - func (opp *OperationPack) MarshalJSON() ([]byte, error) { return json.Marshal(struct { Version uint `json:"version"` @@ -69,25 +57,44 @@ func (opp *OperationPack) UnmarshalJSON(data []byte) error { return err } - opType, ok := operations[t.OperationType] - if !ok { - return fmt.Errorf("unknown operation type %v", t.OperationType) - } - - op := reflect.New(opType).Interface() - - if err := json.Unmarshal(raw, op); err != nil { + op, err := opp.unmarshalOp(raw, t.OperationType) + if err != nil { return err } - deref := reflect.ValueOf(op).Elem().Interface() - - opp.Operations = append(opp.Operations, deref.(Operation)) + opp.Operations = append(opp.Operations, op) } return nil } +func (opp *OperationPack) unmarshalOp(raw []byte, _type OperationType) (Operation, error) { + switch _type { + case CreateOp: + op := CreateOperation{} + err := json.Unmarshal(raw, &op) + return op, err + case SetTitleOp: + op := SetTitleOperation{} + err := json.Unmarshal(raw, &op) + return op, err + case AddCommentOp: + op := AddCommentOperation{} + err := json.Unmarshal(raw, &op) + return op, err + case SetStatusOp: + op := SetStatusOperation{} + err := json.Unmarshal(raw, &op) + return op, err + case LabelChangeOp: + op := LabelChangeOperation{} + err := json.Unmarshal(raw, &op) + return op, err + default: + return nil, fmt.Errorf("unknown operation type %v", _type) + } +} + // Append a new operation to the pack func (opp *OperationPack) Append(op Operation) { opp.Operations = append(opp.Operations, op) diff --git a/tests/operation_pack_test.go b/bug/operation_pack_test.go index aab1f1c9..48f9f80c 100644 --- a/tests/operation_pack_test.go +++ b/bug/operation_pack_test.go @@ -1,17 +1,15 @@ -package tests +package bug import ( "encoding/json" - "reflect" "testing" - "github.com/MichaelMure/git-bug/bug" - "github.com/MichaelMure/git-bug/operations" "github.com/MichaelMure/git-bug/util/git" + "github.com/go-test/deep" ) func TestOperationPackSerialize(t *testing.T) { - opp := &bug.OperationPack{} + opp := &OperationPack{} opp.Append(createOp) opp.Append(setTitleOp) @@ -19,7 +17,7 @@ func TestOperationPackSerialize(t *testing.T) { opp.Append(setStatusOp) opp.Append(labelChangeOp) - opMeta := operations.NewCreateOp(rene, unix, "title", "message", nil) + opMeta := NewCreateOp(rene, unix, "title", "message", nil) opMeta.SetMetadata("key", "value") opp.Append(opMeta) @@ -27,7 +25,7 @@ func TestOperationPackSerialize(t *testing.T) { t.Fatal() } - opFile := operations.NewCreateOp(rene, unix, "title", "message", []git.Hash{ + opFile := NewCreateOp(rene, unix, "title", "message", []git.Hash{ "abcdef", "ghijkl", }) @@ -42,13 +40,14 @@ func TestOperationPackSerialize(t *testing.T) { t.Fatal(err) } - var opp2 *bug.OperationPack + var opp2 *OperationPack err = json.Unmarshal(data, &opp2) if err != nil { t.Fatal(err) } - if !reflect.DeepEqual(opp, opp2) { - t.Fatalf("%v and %v are different", opp, opp2) + deep.CompareUnexportedFields = false + if diff := deep.Equal(opp, opp2); diff != nil { + t.Fatal(diff) } } diff --git a/operations/operations_test.go b/bug/operation_test.go index b94c2c0c..8561adf3 100644 --- a/operations/operations_test.go +++ b/bug/operation_test.go @@ -1,27 +1,26 @@ -package operations +package bug import ( "testing" "time" - "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/util/git" ) func TestValidate(t *testing.T) { - rene := bug.Person{ + rene := Person{ Name: "René Descartes", Email: "rene@descartes.fr", } unix := time.Now().Unix() - good := []bug.Operation{ + good := []Operation{ NewCreateOp(rene, unix, "title", "message", nil), NewSetTitleOp(rene, unix, "title2", "title1"), NewAddCommentOp(rene, unix, "message2", nil), - NewSetStatusOp(rene, unix, bug.ClosedStatus), - NewLabelChangeOperation(rene, unix, []bug.Label{"added"}, []bug.Label{"removed"}), + NewSetStatusOp(rene, unix, ClosedStatus), + NewLabelChangeOperation(rene, unix, []Label{"added"}, []Label{"removed"}), } for _, op := range good { @@ -30,17 +29,17 @@ func TestValidate(t *testing.T) { } } - bad := []bug.Operation{ + bad := []Operation{ // opbase - NewSetStatusOp(bug.Person{Name: "", Email: "rene@descartes.fr"}, unix, bug.ClosedStatus), - NewSetStatusOp(bug.Person{Name: "René Descartes\u001b", Email: "rene@descartes.fr"}, unix, bug.ClosedStatus), - NewSetStatusOp(bug.Person{Name: "René Descartes", Email: "rene@descartes.fr\u001b"}, unix, bug.ClosedStatus), - NewSetStatusOp(bug.Person{Name: "René \nDescartes", Email: "rene@descartes.fr"}, unix, bug.ClosedStatus), - NewSetStatusOp(bug.Person{Name: "René Descartes", Email: "rene@\ndescartes.fr"}, unix, bug.ClosedStatus), - CreateOperation{OpBase: &bug.OpBase{ + NewSetStatusOp(Person{Name: "", Email: "rene@descartes.fr"}, unix, ClosedStatus), + NewSetStatusOp(Person{Name: "René Descartes\u001b", Email: "rene@descartes.fr"}, unix, ClosedStatus), + NewSetStatusOp(Person{Name: "René Descartes", Email: "rene@descartes.fr\u001b"}, unix, ClosedStatus), + NewSetStatusOp(Person{Name: "René \nDescartes", Email: "rene@descartes.fr"}, unix, ClosedStatus), + NewSetStatusOp(Person{Name: "René Descartes", Email: "rene@\ndescartes.fr"}, unix, ClosedStatus), + CreateOperation{OpBase: &OpBase{ Author: rene, UnixTime: 0, - OperationType: bug.CreateOp, + OperationType: CreateOp, }, Title: "title", Message: "message", @@ -59,8 +58,8 @@ func TestValidate(t *testing.T) { NewAddCommentOp(rene, unix, "message", []git.Hash{git.Hash("invalid")}), NewSetStatusOp(rene, unix, 1000), NewSetStatusOp(rene, unix, 0), - NewLabelChangeOperation(rene, unix, []bug.Label{}, []bug.Label{}), - NewLabelChangeOperation(rene, unix, []bug.Label{"multi\nline"}, []bug.Label{}), + NewLabelChangeOperation(rene, unix, []Label{}, []Label{}), + NewLabelChangeOperation(rene, unix, []Label{"multi\nline"}, []Label{}), } for i, op := range bad { @@ -68,5 +67,4 @@ func TestValidate(t *testing.T) { t.Fatal("validation should have failed", i, op) } } - } diff --git a/cache/bug_cache.go b/cache/bug_cache.go index 92b4af95..e7dd6178 100644 --- a/cache/bug_cache.go +++ b/cache/bug_cache.go @@ -4,7 +4,6 @@ import ( "time" "github.com/MichaelMure/git-bug/bug" - "github.com/MichaelMure/git-bug/operations" "github.com/MichaelMure/git-bug/util/git" ) @@ -50,7 +49,7 @@ func (c *BugCache) AddCommentWithFiles(message string, files []git.Hash) error { } func (c *BugCache) AddCommentRaw(author bug.Person, unixTime int64, message string, files []git.Hash, metadata map[string]string) error { - err := operations.CommentWithFiles(c.bug, author, unixTime, message, files) + err := bug.AddCommentWithFiles(c.bug, author, unixTime, message, files) if err != nil { return err } @@ -58,7 +57,7 @@ func (c *BugCache) AddCommentRaw(author bug.Person, unixTime int64, message stri return c.notifyUpdated() } -func (c *BugCache) ChangeLabels(added []string, removed []string) ([]operations.LabelChangeResult, error) { +func (c *BugCache) ChangeLabels(added []string, removed []string) ([]bug.LabelChangeResult, error) { author, err := bug.GetUser(c.repoCache.repo) if err != nil { return nil, err @@ -67,8 +66,8 @@ func (c *BugCache) ChangeLabels(added []string, removed []string) ([]operations. return c.ChangeLabelsRaw(author, time.Now().Unix(), added, removed) } -func (c *BugCache) ChangeLabelsRaw(author bug.Person, unixTime int64, added []string, removed []string) ([]operations.LabelChangeResult, error) { - changes, err := operations.ChangeLabels(c.bug, author, unixTime, added, removed) +func (c *BugCache) ChangeLabelsRaw(author bug.Person, unixTime int64, added []string, removed []string) ([]bug.LabelChangeResult, error) { + changes, err := bug.ChangeLabels(c.bug, author, unixTime, added, removed) if err != nil { return changes, err } @@ -91,7 +90,7 @@ func (c *BugCache) Open() error { } func (c *BugCache) OpenRaw(author bug.Person, unixTime int64) error { - err := operations.Open(c.bug, author, unixTime) + err := bug.Open(c.bug, author, unixTime) if err != nil { return err } @@ -109,7 +108,7 @@ func (c *BugCache) Close() error { } func (c *BugCache) CloseRaw(author bug.Person, unixTime int64) error { - err := operations.Close(c.bug, author, unixTime) + err := bug.Close(c.bug, author, unixTime) if err != nil { return err } @@ -127,7 +126,7 @@ func (c *BugCache) SetTitle(title string) error { } func (c *BugCache) SetTitleRaw(author bug.Person, unixTime int64, title string) error { - err := operations.SetTitle(c.bug, author, unixTime, title) + err := bug.SetTitle(c.bug, author, unixTime, title) if err != nil { return err } diff --git a/cache/repo_cache.go b/cache/repo_cache.go index 2278b604..0de5bf07 100644 --- a/cache/repo_cache.go +++ b/cache/repo_cache.go @@ -14,7 +14,6 @@ import ( "time" "github.com/MichaelMure/git-bug/bug" - "github.com/MichaelMure/git-bug/operations" "github.com/MichaelMure/git-bug/repository" "github.com/MichaelMure/git-bug/util/git" "github.com/MichaelMure/git-bug/util/process" @@ -362,7 +361,7 @@ func (c *RepoCache) NewBugWithFiles(title string, message string, files []git.Ha // well as metadata for the Create operation. // The new bug is written in the repository (commit) func (c *RepoCache) NewBugRaw(author bug.Person, unixTime int64, title string, message string, files []git.Hash, metadata map[string]string) (*BugCache, error) { - b, err := operations.CreateWithFiles(author, unixTime, title, message, files) + b, err := bug.CreateWithFiles(author, unixTime, title, message, files) if err != nil { return nil, err } diff --git a/graphql/gqlgen.yml b/graphql/gqlgen.yml index 34eb13c2..516f335f 100644 --- a/graphql/gqlgen.yml +++ b/graphql/gqlgen.yml @@ -22,12 +22,12 @@ models: Operation: model: github.com/MichaelMure/git-bug/bug.Operation CreateOperation: - model: github.com/MichaelMure/git-bug/operations.CreateOperation + model: github.com/MichaelMure/git-bug/bug.CreateOperation SetTitleOperation: - model: github.com/MichaelMure/git-bug/operations.SetTitleOperation + model: github.com/MichaelMure/git-bug/bug.SetTitleOperation AddCommentOperation: - model: github.com/MichaelMure/git-bug/operations.AddCommentOperation + model: github.com/MichaelMure/git-bug/bug.AddCommentOperation SetStatusOperation: - model: github.com/MichaelMure/git-bug/operations.SetStatusOperation + model: github.com/MichaelMure/git-bug/bug.SetStatusOperation LabelChangeOperation: - model: github.com/MichaelMure/git-bug/operations.LabelChangeOperation + model: github.com/MichaelMure/git-bug/bug.LabelChangeOperation diff --git a/graphql/graph/gen_graph.go b/graphql/graph/gen_graph.go index 95a15499..1425032a 100644 --- a/graphql/graph/gen_graph.go +++ b/graphql/graph/gen_graph.go @@ -14,7 +14,6 @@ import ( introspection "github.com/99designs/gqlgen/graphql/introspection" bug "github.com/MichaelMure/git-bug/bug" models "github.com/MichaelMure/git-bug/graphql/models" - operations "github.com/MichaelMure/git-bug/operations" git "github.com/MichaelMure/git-bug/util/git" gqlparser "github.com/vektah/gqlparser" ast "github.com/vektah/gqlparser/ast" @@ -176,8 +175,8 @@ type ComplexityRoot struct { } type AddCommentOperationResolver interface { - Author(ctx context.Context, obj *operations.AddCommentOperation) (bug.Person, error) - Date(ctx context.Context, obj *operations.AddCommentOperation) (time.Time, error) + Author(ctx context.Context, obj *bug.AddCommentOperation) (bug.Person, error) + Date(ctx context.Context, obj *bug.AddCommentOperation) (time.Time, error) } type BugResolver interface { Status(ctx context.Context, obj *bug.Snapshot) (models.Status, error) @@ -187,12 +186,12 @@ type BugResolver interface { Operations(ctx context.Context, obj *bug.Snapshot, after *string, before *string, first *int, last *int) (models.OperationConnection, error) } type CreateOperationResolver interface { - Author(ctx context.Context, obj *operations.CreateOperation) (bug.Person, error) - Date(ctx context.Context, obj *operations.CreateOperation) (time.Time, error) + Author(ctx context.Context, obj *bug.CreateOperation) (bug.Person, error) + Date(ctx context.Context, obj *bug.CreateOperation) (time.Time, error) } type LabelChangeOperationResolver interface { - Author(ctx context.Context, obj *operations.LabelChangeOperation) (bug.Person, error) - Date(ctx context.Context, obj *operations.LabelChangeOperation) (time.Time, error) + Author(ctx context.Context, obj *bug.LabelChangeOperation) (bug.Person, error) + Date(ctx context.Context, obj *bug.LabelChangeOperation) (time.Time, error) } type MutationResolver interface { NewBug(ctx context.Context, repoRef *string, title string, message string, files []git.Hash) (bug.Snapshot, error) @@ -212,13 +211,13 @@ type RepositoryResolver interface { Bug(ctx context.Context, obj *models.Repository, prefix string) (*bug.Snapshot, error) } type SetStatusOperationResolver interface { - Author(ctx context.Context, obj *operations.SetStatusOperation) (bug.Person, error) - Date(ctx context.Context, obj *operations.SetStatusOperation) (time.Time, error) - Status(ctx context.Context, obj *operations.SetStatusOperation) (models.Status, error) + Author(ctx context.Context, obj *bug.SetStatusOperation) (bug.Person, error) + Date(ctx context.Context, obj *bug.SetStatusOperation) (time.Time, error) + Status(ctx context.Context, obj *bug.SetStatusOperation) (models.Status, error) } type SetTitleOperationResolver interface { - Author(ctx context.Context, obj *operations.SetTitleOperation) (bug.Person, error) - Date(ctx context.Context, obj *operations.SetTitleOperation) (time.Time, error) + Author(ctx context.Context, obj *bug.SetTitleOperation) (bug.Person, error) + Date(ctx context.Context, obj *bug.SetTitleOperation) (time.Time, error) } func field_Bug_comments_args(rawArgs map[string]interface{}) (map[string]interface{}, error) { @@ -1410,7 +1409,7 @@ type executionContext struct { var addCommentOperationImplementors = []string{"AddCommentOperation", "Operation", "Authored"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _AddCommentOperation(ctx context.Context, sel ast.SelectionSet, obj *operations.AddCommentOperation) graphql.Marshaler { +func (ec *executionContext) _AddCommentOperation(ctx context.Context, sel ast.SelectionSet, obj *bug.AddCommentOperation) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, addCommentOperationImplementors) var wg sync.WaitGroup @@ -1462,7 +1461,7 @@ func (ec *executionContext) _AddCommentOperation(ctx context.Context, sel ast.Se } // nolint: vetshadow -func (ec *executionContext) _AddCommentOperation_author(ctx context.Context, field graphql.CollectedField, obj *operations.AddCommentOperation) graphql.Marshaler { +func (ec *executionContext) _AddCommentOperation_author(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "AddCommentOperation", Args: nil, @@ -1485,7 +1484,7 @@ func (ec *executionContext) _AddCommentOperation_author(ctx context.Context, fie } // nolint: vetshadow -func (ec *executionContext) _AddCommentOperation_date(ctx context.Context, field graphql.CollectedField, obj *operations.AddCommentOperation) graphql.Marshaler { +func (ec *executionContext) _AddCommentOperation_date(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "AddCommentOperation", Args: nil, @@ -1507,7 +1506,7 @@ func (ec *executionContext) _AddCommentOperation_date(ctx context.Context, field } // nolint: vetshadow -func (ec *executionContext) _AddCommentOperation_message(ctx context.Context, field graphql.CollectedField, obj *operations.AddCommentOperation) graphql.Marshaler { +func (ec *executionContext) _AddCommentOperation_message(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "AddCommentOperation", Args: nil, @@ -1529,7 +1528,7 @@ func (ec *executionContext) _AddCommentOperation_message(ctx context.Context, fi } // nolint: vetshadow -func (ec *executionContext) _AddCommentOperation_files(ctx context.Context, field graphql.CollectedField, obj *operations.AddCommentOperation) graphql.Marshaler { +func (ec *executionContext) _AddCommentOperation_files(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "AddCommentOperation", Args: nil, @@ -2574,7 +2573,7 @@ func (ec *executionContext) _CommentEdge_node(ctx context.Context, field graphql var createOperationImplementors = []string{"CreateOperation", "Operation", "Authored"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _CreateOperation(ctx context.Context, sel ast.SelectionSet, obj *operations.CreateOperation) graphql.Marshaler { +func (ec *executionContext) _CreateOperation(ctx context.Context, sel ast.SelectionSet, obj *bug.CreateOperation) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, createOperationImplementors) var wg sync.WaitGroup @@ -2631,7 +2630,7 @@ func (ec *executionContext) _CreateOperation(ctx context.Context, sel ast.Select } // nolint: vetshadow -func (ec *executionContext) _CreateOperation_author(ctx context.Context, field graphql.CollectedField, obj *operations.CreateOperation) graphql.Marshaler { +func (ec *executionContext) _CreateOperation_author(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "CreateOperation", Args: nil, @@ -2654,7 +2653,7 @@ func (ec *executionContext) _CreateOperation_author(ctx context.Context, field g } // nolint: vetshadow -func (ec *executionContext) _CreateOperation_date(ctx context.Context, field graphql.CollectedField, obj *operations.CreateOperation) graphql.Marshaler { +func (ec *executionContext) _CreateOperation_date(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "CreateOperation", Args: nil, @@ -2676,7 +2675,7 @@ func (ec *executionContext) _CreateOperation_date(ctx context.Context, field gra } // nolint: vetshadow -func (ec *executionContext) _CreateOperation_title(ctx context.Context, field graphql.CollectedField, obj *operations.CreateOperation) graphql.Marshaler { +func (ec *executionContext) _CreateOperation_title(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "CreateOperation", Args: nil, @@ -2698,7 +2697,7 @@ func (ec *executionContext) _CreateOperation_title(ctx context.Context, field gr } // nolint: vetshadow -func (ec *executionContext) _CreateOperation_message(ctx context.Context, field graphql.CollectedField, obj *operations.CreateOperation) graphql.Marshaler { +func (ec *executionContext) _CreateOperation_message(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "CreateOperation", Args: nil, @@ -2720,7 +2719,7 @@ func (ec *executionContext) _CreateOperation_message(ctx context.Context, field } // nolint: vetshadow -func (ec *executionContext) _CreateOperation_files(ctx context.Context, field graphql.CollectedField, obj *operations.CreateOperation) graphql.Marshaler { +func (ec *executionContext) _CreateOperation_files(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "CreateOperation", Args: nil, @@ -2753,7 +2752,7 @@ func (ec *executionContext) _CreateOperation_files(ctx context.Context, field gr var labelChangeOperationImplementors = []string{"LabelChangeOperation", "Operation", "Authored"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _LabelChangeOperation(ctx context.Context, sel ast.SelectionSet, obj *operations.LabelChangeOperation) graphql.Marshaler { +func (ec *executionContext) _LabelChangeOperation(ctx context.Context, sel ast.SelectionSet, obj *bug.LabelChangeOperation) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, labelChangeOperationImplementors) var wg sync.WaitGroup @@ -2805,7 +2804,7 @@ func (ec *executionContext) _LabelChangeOperation(ctx context.Context, sel ast.S } // nolint: vetshadow -func (ec *executionContext) _LabelChangeOperation_author(ctx context.Context, field graphql.CollectedField, obj *operations.LabelChangeOperation) graphql.Marshaler { +func (ec *executionContext) _LabelChangeOperation_author(ctx context.Context, field graphql.CollectedField, obj *bug.LabelChangeOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "LabelChangeOperation", Args: nil, @@ -2828,7 +2827,7 @@ func (ec *executionContext) _LabelChangeOperation_author(ctx context.Context, fi } // nolint: vetshadow -func (ec *executionContext) _LabelChangeOperation_date(ctx context.Context, field graphql.CollectedField, obj *operations.LabelChangeOperation) graphql.Marshaler { +func (ec *executionContext) _LabelChangeOperation_date(ctx context.Context, field graphql.CollectedField, obj *bug.LabelChangeOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "LabelChangeOperation", Args: nil, @@ -2850,7 +2849,7 @@ func (ec *executionContext) _LabelChangeOperation_date(ctx context.Context, fiel } // nolint: vetshadow -func (ec *executionContext) _LabelChangeOperation_added(ctx context.Context, field graphql.CollectedField, obj *operations.LabelChangeOperation) graphql.Marshaler { +func (ec *executionContext) _LabelChangeOperation_added(ctx context.Context, field graphql.CollectedField, obj *bug.LabelChangeOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "LabelChangeOperation", Args: nil, @@ -2881,7 +2880,7 @@ func (ec *executionContext) _LabelChangeOperation_added(ctx context.Context, fie } // nolint: vetshadow -func (ec *executionContext) _LabelChangeOperation_removed(ctx context.Context, field graphql.CollectedField, obj *operations.LabelChangeOperation) graphql.Marshaler { +func (ec *executionContext) _LabelChangeOperation_removed(ctx context.Context, field graphql.CollectedField, obj *bug.LabelChangeOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "LabelChangeOperation", Args: nil, @@ -3942,7 +3941,7 @@ func (ec *executionContext) _Repository_bug(ctx context.Context, field graphql.C var setStatusOperationImplementors = []string{"SetStatusOperation", "Operation", "Authored"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _SetStatusOperation(ctx context.Context, sel ast.SelectionSet, obj *operations.SetStatusOperation) graphql.Marshaler { +func (ec *executionContext) _SetStatusOperation(ctx context.Context, sel ast.SelectionSet, obj *bug.SetStatusOperation) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, setStatusOperationImplementors) var wg sync.WaitGroup @@ -3993,7 +3992,7 @@ func (ec *executionContext) _SetStatusOperation(ctx context.Context, sel ast.Sel } // nolint: vetshadow -func (ec *executionContext) _SetStatusOperation_author(ctx context.Context, field graphql.CollectedField, obj *operations.SetStatusOperation) graphql.Marshaler { +func (ec *executionContext) _SetStatusOperation_author(ctx context.Context, field graphql.CollectedField, obj *bug.SetStatusOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "SetStatusOperation", Args: nil, @@ -4016,7 +4015,7 @@ func (ec *executionContext) _SetStatusOperation_author(ctx context.Context, fiel } // nolint: vetshadow -func (ec *executionContext) _SetStatusOperation_date(ctx context.Context, field graphql.CollectedField, obj *operations.SetStatusOperation) graphql.Marshaler { +func (ec *executionContext) _SetStatusOperation_date(ctx context.Context, field graphql.CollectedField, obj *bug.SetStatusOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "SetStatusOperation", Args: nil, @@ -4038,7 +4037,7 @@ func (ec *executionContext) _SetStatusOperation_date(ctx context.Context, field } // nolint: vetshadow -func (ec *executionContext) _SetStatusOperation_status(ctx context.Context, field graphql.CollectedField, obj *operations.SetStatusOperation) graphql.Marshaler { +func (ec *executionContext) _SetStatusOperation_status(ctx context.Context, field graphql.CollectedField, obj *bug.SetStatusOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "SetStatusOperation", Args: nil, @@ -4062,7 +4061,7 @@ func (ec *executionContext) _SetStatusOperation_status(ctx context.Context, fiel var setTitleOperationImplementors = []string{"SetTitleOperation", "Operation", "Authored"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _SetTitleOperation(ctx context.Context, sel ast.SelectionSet, obj *operations.SetTitleOperation) graphql.Marshaler { +func (ec *executionContext) _SetTitleOperation(ctx context.Context, sel ast.SelectionSet, obj *bug.SetTitleOperation) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, setTitleOperationImplementors) var wg sync.WaitGroup @@ -4114,7 +4113,7 @@ func (ec *executionContext) _SetTitleOperation(ctx context.Context, sel ast.Sele } // nolint: vetshadow -func (ec *executionContext) _SetTitleOperation_author(ctx context.Context, field graphql.CollectedField, obj *operations.SetTitleOperation) graphql.Marshaler { +func (ec *executionContext) _SetTitleOperation_author(ctx context.Context, field graphql.CollectedField, obj *bug.SetTitleOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "SetTitleOperation", Args: nil, @@ -4137,7 +4136,7 @@ func (ec *executionContext) _SetTitleOperation_author(ctx context.Context, field } // nolint: vetshadow -func (ec *executionContext) _SetTitleOperation_date(ctx context.Context, field graphql.CollectedField, obj *operations.SetTitleOperation) graphql.Marshaler { +func (ec *executionContext) _SetTitleOperation_date(ctx context.Context, field graphql.CollectedField, obj *bug.SetTitleOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "SetTitleOperation", Args: nil, @@ -4159,7 +4158,7 @@ func (ec *executionContext) _SetTitleOperation_date(ctx context.Context, field g } // nolint: vetshadow -func (ec *executionContext) _SetTitleOperation_title(ctx context.Context, field graphql.CollectedField, obj *operations.SetTitleOperation) graphql.Marshaler { +func (ec *executionContext) _SetTitleOperation_title(ctx context.Context, field graphql.CollectedField, obj *bug.SetTitleOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "SetTitleOperation", Args: nil, @@ -4181,7 +4180,7 @@ func (ec *executionContext) _SetTitleOperation_title(ctx context.Context, field } // nolint: vetshadow -func (ec *executionContext) _SetTitleOperation_was(ctx context.Context, field graphql.CollectedField, obj *operations.SetTitleOperation) graphql.Marshaler { +func (ec *executionContext) _SetTitleOperation_was(ctx context.Context, field graphql.CollectedField, obj *bug.SetTitleOperation) graphql.Marshaler { rctx := &graphql.ResolverContext{ Object: "SetTitleOperation", Args: nil, @@ -5487,25 +5486,25 @@ func (ec *executionContext) _Authored(ctx context.Context, sel ast.SelectionSet, return ec._Comment(ctx, sel, &obj) case *bug.Comment: return ec._Comment(ctx, sel, obj) - case operations.CreateOperation: + case bug.CreateOperation: return ec._CreateOperation(ctx, sel, &obj) - case *operations.CreateOperation: + case *bug.CreateOperation: return ec._CreateOperation(ctx, sel, obj) - case operations.SetTitleOperation: + case bug.SetTitleOperation: return ec._SetTitleOperation(ctx, sel, &obj) - case *operations.SetTitleOperation: + case *bug.SetTitleOperation: return ec._SetTitleOperation(ctx, sel, obj) - case operations.AddCommentOperation: + case bug.AddCommentOperation: return ec._AddCommentOperation(ctx, sel, &obj) - case *operations.AddCommentOperation: + case *bug.AddCommentOperation: return ec._AddCommentOperation(ctx, sel, obj) - case operations.SetStatusOperation: + case bug.SetStatusOperation: return ec._SetStatusOperation(ctx, sel, &obj) - case *operations.SetStatusOperation: + case *bug.SetStatusOperation: return ec._SetStatusOperation(ctx, sel, obj) - case operations.LabelChangeOperation: + case bug.LabelChangeOperation: return ec._LabelChangeOperation(ctx, sel, &obj) - case *operations.LabelChangeOperation: + case *bug.LabelChangeOperation: return ec._LabelChangeOperation(ctx, sel, obj) default: panic(fmt.Errorf("unexpected type %T", obj)) @@ -5516,15 +5515,15 @@ func (ec *executionContext) _Operation(ctx context.Context, sel ast.SelectionSet switch obj := (*obj).(type) { case nil: return graphql.Null - case operations.CreateOperation: + case bug.CreateOperation: return ec._CreateOperation(ctx, sel, &obj) - case operations.SetTitleOperation: + case bug.SetTitleOperation: return ec._SetTitleOperation(ctx, sel, &obj) - case operations.AddCommentOperation: + case bug.AddCommentOperation: return ec._AddCommentOperation(ctx, sel, &obj) - case operations.SetStatusOperation: + case bug.SetStatusOperation: return ec._SetStatusOperation(ctx, sel, &obj) - case operations.LabelChangeOperation: + case bug.LabelChangeOperation: return ec._LabelChangeOperation(ctx, sel, &obj) default: panic(fmt.Errorf("unexpected type %T", obj)) diff --git a/graphql/resolvers/operations.go b/graphql/resolvers/operations.go index e964388b..4b78f0fb 100644 --- a/graphql/resolvers/operations.go +++ b/graphql/resolvers/operations.go @@ -7,60 +7,59 @@ import ( "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/graphql/models" - "github.com/MichaelMure/git-bug/operations" ) type addCommentOperationResolver struct{} -func (addCommentOperationResolver) Author(ctx context.Context, obj *operations.AddCommentOperation) (bug.Person, error) { +func (addCommentOperationResolver) Author(ctx context.Context, obj *bug.AddCommentOperation) (bug.Person, error) { return obj.Author, nil } -func (addCommentOperationResolver) Date(ctx context.Context, obj *operations.AddCommentOperation) (time.Time, error) { +func (addCommentOperationResolver) Date(ctx context.Context, obj *bug.AddCommentOperation) (time.Time, error) { return obj.Time(), nil } type createOperationResolver struct{} -func (createOperationResolver) Author(ctx context.Context, obj *operations.CreateOperation) (bug.Person, error) { +func (createOperationResolver) Author(ctx context.Context, obj *bug.CreateOperation) (bug.Person, error) { return obj.Author, nil } -func (createOperationResolver) Date(ctx context.Context, obj *operations.CreateOperation) (time.Time, error) { +func (createOperationResolver) Date(ctx context.Context, obj *bug.CreateOperation) (time.Time, error) { return obj.Time(), nil } type labelChangeOperation struct{} -func (labelChangeOperation) Author(ctx context.Context, obj *operations.LabelChangeOperation) (bug.Person, error) { +func (labelChangeOperation) Author(ctx context.Context, obj *bug.LabelChangeOperation) (bug.Person, error) { return obj.Author, nil } -func (labelChangeOperation) Date(ctx context.Context, obj *operations.LabelChangeOperation) (time.Time, error) { +func (labelChangeOperation) Date(ctx context.Context, obj *bug.LabelChangeOperation) (time.Time, error) { return obj.Time(), nil } type setStatusOperationResolver struct{} -func (setStatusOperationResolver) Author(ctx context.Context, obj *operations.SetStatusOperation) (bug.Person, error) { +func (setStatusOperationResolver) Author(ctx context.Context, obj *bug.SetStatusOperation) (bug.Person, error) { return obj.Author, nil } -func (setStatusOperationResolver) Date(ctx context.Context, obj *operations.SetStatusOperation) (time.Time, error) { +func (setStatusOperationResolver) Date(ctx context.Context, obj *bug.SetStatusOperation) (time.Time, error) { return obj.Time(), nil } -func (setStatusOperationResolver) Status(ctx context.Context, obj *operations.SetStatusOperation) (models.Status, error) { +func (setStatusOperationResolver) Status(ctx context.Context, obj *bug.SetStatusOperation) (models.Status, error) { return convertStatus(obj.Status) } type setTitleOperationResolver struct{} -func (setTitleOperationResolver) Author(ctx context.Context, obj *operations.SetTitleOperation) (bug.Person, error) { +func (setTitleOperationResolver) Author(ctx context.Context, obj *bug.SetTitleOperation) (bug.Person, error) { return obj.Author, nil } -func (setTitleOperationResolver) Date(ctx context.Context, obj *operations.SetTitleOperation) (time.Time, error) { +func (setTitleOperationResolver) Date(ctx context.Context, obj *bug.SetTitleOperation) (time.Time, error) { return obj.Time(), nil } diff --git a/misc/random_bugs/create_random_bugs.go b/misc/random_bugs/create_random_bugs.go index 66ca18a9..ba4d6a66 100644 --- a/misc/random_bugs/create_random_bugs.go +++ b/misc/random_bugs/create_random_bugs.go @@ -6,7 +6,6 @@ import ( "time" "github.com/MichaelMure/git-bug/bug" - "github.com/MichaelMure/git-bug/operations" "github.com/MichaelMure/git-bug/repository" "github.com/icrowley/fake" ) @@ -66,7 +65,7 @@ func GenerateRandomBugsWithSeed(opts Options, seed int64) []*bug.Bug { for i := 0; i < opts.BugNumber; i++ { addedLabels = []string{} - b, err := operations.Create( + b, err := bug.Create( randomPerson(opts.PersonNumber), time.Now().Unix(), fake.Sentence(), @@ -111,7 +110,7 @@ func GenerateRandomOperationPacksWithSeed(packNumber int, opNumber int, seed int var op bug.Operation - op = operations.NewCreateOp( + op = bug.NewCreateOp( randomPerson(5), time.Now().Unix(), fake.Sentence(), @@ -122,7 +121,7 @@ func GenerateRandomOperationPacksWithSeed(packNumber int, opNumber int, seed int opp.Append(op) for j := 0; j < opNumber-1; j++ { - op = operations.NewAddCommentOp( + op = bug.NewAddCommentOp( randomPerson(5), time.Now().Unix(), paragraphs(), @@ -164,19 +163,19 @@ func paragraphs() string { } func comment(b bug.Interface, p bug.Person) { - _ = operations.Comment(b, p, time.Now().Unix(), paragraphs()) + _ = bug.AddComment(b, p, time.Now().Unix(), paragraphs()) } func title(b bug.Interface, p bug.Person) { - _ = operations.SetTitle(b, p, time.Now().Unix(), fake.Sentence()) + _ = bug.SetTitle(b, p, time.Now().Unix(), fake.Sentence()) } func open(b bug.Interface, p bug.Person) { - _ = operations.Open(b, p, time.Now().Unix()) + _ = bug.Open(b, p, time.Now().Unix()) } func close(b bug.Interface, p bug.Person) { - _ = operations.Close(b, p, time.Now().Unix()) + _ = bug.Close(b, p, time.Now().Unix()) } var addedLabels []string @@ -203,5 +202,5 @@ func labels(b bug.Interface, p bug.Person) { // ignore error // if the randomisation produce no changes, no op // is added to the bug - _, _ = operations.ChangeLabels(b, p, time.Now().Unix(), added, removed) + _, _ = bug.ChangeLabels(b, p, time.Now().Unix(), added, removed) } diff --git a/operations/operations.go b/operations/operations.go deleted file mode 100644 index 020b8151..00000000 --- a/operations/operations.go +++ /dev/null @@ -1,17 +0,0 @@ -// Package operations contains the various bug operations. A bug operation is -// an atomic edit operation of a bug state. These operations are applied -// sequentially to compile the current state of the bug. -package operations - -import ( - "github.com/MichaelMure/git-bug/bug" -) - -// Package initialisation used to register operation's type for (de)serialization -func init() { - bug.Register(bug.CreateOp, CreateOperation{}) - bug.Register(bug.SetTitleOp, SetTitleOperation{}) - bug.Register(bug.AddCommentOp, AddCommentOperation{}) - bug.Register(bug.SetStatusOp, SetStatusOperation{}) - bug.Register(bug.LabelChangeOp, LabelChangeOperation{}) -} diff --git a/operations/set_status.go b/operations/set_status.go deleted file mode 100644 index 3e7eae4a..00000000 --- a/operations/set_status.go +++ /dev/null @@ -1,60 +0,0 @@ -package operations - -import ( - "github.com/MichaelMure/git-bug/bug" - "github.com/pkg/errors" -) - -// SetStatusOperation will change the status of a bug - -var _ bug.Operation = SetStatusOperation{} - -type SetStatusOperation struct { - *bug.OpBase - Status bug.Status `json:"status"` -} - -func (op SetStatusOperation) Apply(snapshot bug.Snapshot) bug.Snapshot { - snapshot.Status = op.Status - - return snapshot -} - -func (op SetStatusOperation) Validate() error { - if err := bug.OpBaseValidate(op, bug.SetStatusOp); err != nil { - return err - } - - if err := op.Status.Validate(); err != nil { - return errors.Wrap(err, "status") - } - - return nil -} - -func NewSetStatusOp(author bug.Person, unixTime int64, status bug.Status) SetStatusOperation { - return SetStatusOperation{ - OpBase: bug.NewOpBase(bug.SetStatusOp, author, unixTime), - Status: status, - } -} - -// Convenience function to apply the operation -func Open(b bug.Interface, author bug.Person, unixTime int64) error { - op := NewSetStatusOp(author, unixTime, bug.OpenStatus) - if err := op.Validate(); err != nil { - return err - } - b.Append(op) - return nil -} - -// Convenience function to apply the operation -func Close(b bug.Interface, author bug.Person, unixTime int64) error { - op := NewSetStatusOp(author, unixTime, bug.ClosedStatus) - if err := op.Validate(); err != nil { - return err - } - b.Append(op) - return nil -} diff --git a/termui/show_bug.go b/termui/show_bug.go index 560ac765..e0621e4b 100644 --- a/termui/show_bug.go +++ b/termui/show_bug.go @@ -5,8 +5,8 @@ import ( "fmt" "strings" + "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/cache" - "github.com/MichaelMure/git-bug/operations" "github.com/MichaelMure/git-bug/util/colors" "github.com/MichaelMure/git-bug/util/text" "github.com/jroimartin/gocui" @@ -234,8 +234,8 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { switch op.(type) { - case operations.CreateOperation: - create := op.(operations.CreateOperation) + case bug.CreateOperation: + create := op.(bug.CreateOperation) content, lines := text.WrapLeftPadded(create.Message, maxX, 4) v, err := sb.createOpView(g, viewName, x0, y0, maxX+1, lines, true) @@ -245,8 +245,8 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { fmt.Fprint(v, content) y0 += lines + 2 - case operations.AddCommentOperation: - comment := op.(operations.AddCommentOperation) + case bug.AddCommentOperation: + comment := op.(bug.AddCommentOperation) message, _ := text.WrapLeftPadded(comment.Message, maxX, 4) content := fmt.Sprintf("%s commented on %s\n\n%s", @@ -263,8 +263,8 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { fmt.Fprint(v, content) y0 += lines + 2 - case operations.SetTitleOperation: - setTitle := op.(operations.SetTitleOperation) + case bug.SetTitleOperation: + setTitle := op.(bug.SetTitleOperation) content := fmt.Sprintf("%s changed the title to %s on %s", colors.Magenta(setTitle.Author.Name), @@ -280,8 +280,8 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { fmt.Fprint(v, content) y0 += lines + 2 - case operations.SetStatusOperation: - setStatus := op.(operations.SetStatusOperation) + case bug.SetStatusOperation: + setStatus := op.(bug.SetStatusOperation) content := fmt.Sprintf("%s %s the bug on %s", colors.Magenta(setStatus.Author.Name), @@ -297,8 +297,8 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { fmt.Fprint(v, content) y0 += lines + 2 - case operations.LabelChangeOperation: - labelChange := op.(operations.LabelChangeOperation) + case bug.LabelChangeOperation: + labelChange := op.(bug.LabelChangeOperation) var added []string for _, label := range labelChange.Added { diff --git a/tests/read_bugs_test.go b/tests/read_bugs_test.go index c3c7d9ea..b28da49b 100644 --- a/tests/read_bugs_test.go +++ b/tests/read_bugs_test.go @@ -1,6 +1,8 @@ package tests import ( + "io/ioutil" + "log" "testing" "github.com/MichaelMure/git-bug/bug" @@ -8,6 +10,30 @@ import ( "github.com/MichaelMure/git-bug/repository" ) +func createRepo(bare bool) *repository.GitRepo { + dir, err := ioutil.TempDir("", "") + if err != nil { + log.Fatal(err) + } + + // fmt.Println("Creating repo:", dir) + + var creator func(string) (*repository.GitRepo, error) + + if bare { + creator = repository.InitBareGitRepo + } else { + creator = repository.InitGitRepo + } + + repo, err := creator(dir) + if err != nil { + log.Fatal(err) + } + + return repo +} + func createFilledRepo(bugNumber int) repository.ClockedRepo { repo := createRepo(false) diff --git a/vendor/github.com/go-test/deep/.gitignore b/vendor/github.com/go-test/deep/.gitignore new file mode 100644 index 00000000..53f12f0f --- /dev/null +++ b/vendor/github.com/go-test/deep/.gitignore @@ -0,0 +1,2 @@ +*.swp +*.out diff --git a/vendor/github.com/go-test/deep/.travis.yml b/vendor/github.com/go-test/deep/.travis.yml new file mode 100644 index 00000000..2279c614 --- /dev/null +++ b/vendor/github.com/go-test/deep/.travis.yml @@ -0,0 +1,13 @@ +language: go + +go: + - 1.7 + - 1.8 + - 1.9 + +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cover + +script: + - $HOME/gopath/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/go-test/deep/CHANGES.md b/vendor/github.com/go-test/deep/CHANGES.md new file mode 100644 index 00000000..4351819d --- /dev/null +++ b/vendor/github.com/go-test/deep/CHANGES.md @@ -0,0 +1,9 @@ +# go-test/deep Changelog + +## v1.0.1 released 2018-01-28 + +* Fixed #12: Arrays are not properly compared (samlitowitz) + +## v1.0.0 releaesd 2017-10-27 + +* First release diff --git a/vendor/github.com/go-test/deep/LICENSE b/vendor/github.com/go-test/deep/LICENSE new file mode 100644 index 00000000..228ef16f --- /dev/null +++ b/vendor/github.com/go-test/deep/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright 2015-2017 Daniel Nichter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-test/deep/README.md b/vendor/github.com/go-test/deep/README.md new file mode 100644 index 00000000..3b78eac7 --- /dev/null +++ b/vendor/github.com/go-test/deep/README.md @@ -0,0 +1,51 @@ +# Deep Variable Equality for Humans + +[![Go Report Card](https://goreportcard.com/badge/github.com/go-test/deep)](https://goreportcard.com/report/github.com/go-test/deep) [![Build Status](https://travis-ci.org/go-test/deep.svg?branch=master)](https://travis-ci.org/go-test/deep) [![Coverage Status](https://coveralls.io/repos/github/go-test/deep/badge.svg?branch=master)](https://coveralls.io/github/go-test/deep?branch=master) [![GoDoc](https://godoc.org/github.com/go-test/deep?status.svg)](https://godoc.org/github.com/go-test/deep) + +This package provides a single function: `deep.Equal`. It's like [reflect.DeepEqual](http://golang.org/pkg/reflect/#DeepEqual) but much friendlier to humans (or any sentient being) for two reason: + +* `deep.Equal` returns a list of differences +* `deep.Equal` does not compare unexported fields (by default) + +`reflect.DeepEqual` is good (like all things Golang!), but it's a game of [Hunt the Wumpus](https://en.wikipedia.org/wiki/Hunt_the_Wumpus). For large maps, slices, and structs, finding the difference is difficult. + +`deep.Equal` doesn't play games with you, it lists the differences: + +```go +package main_test + +import ( + "testing" + "github.com/go-test/deep" +) + +type T struct { + Name string + Numbers []float64 +} + +func TestDeepEqual(t *testing.T) { + // Can you spot the difference? + t1 := T{ + Name: "Isabella", + Numbers: []float64{1.13459, 2.29343, 3.010100010}, + } + t2 := T{ + Name: "Isabella", + Numbers: []float64{1.13459, 2.29843, 3.010100010}, + } + + if diff := deep.Equal(t1, t2); diff != nil { + t.Error(diff) + } +} +``` + + +``` +$ go test +--- FAIL: TestDeepEqual (0.00s) + main_test.go:25: [Numbers.slice[1]: 2.29343 != 2.29843] +``` + +The difference is in `Numbers.slice[1]`: the two values aren't equal using Go `==`. diff --git a/vendor/github.com/go-test/deep/deep.go b/vendor/github.com/go-test/deep/deep.go new file mode 100644 index 00000000..4ea14cb0 --- /dev/null +++ b/vendor/github.com/go-test/deep/deep.go @@ -0,0 +1,352 @@ +// Package deep provides function deep.Equal which is like reflect.DeepEqual but +// returns a list of differences. This is helpful when comparing complex types +// like structures and maps. +package deep + +import ( + "errors" + "fmt" + "log" + "reflect" + "strings" +) + +var ( + // FloatPrecision is the number of decimal places to round float values + // to when comparing. + FloatPrecision = 10 + + // MaxDiff specifies the maximum number of differences to return. + MaxDiff = 10 + + // MaxDepth specifies the maximum levels of a struct to recurse into. + MaxDepth = 10 + + // LogErrors causes errors to be logged to STDERR when true. + LogErrors = false + + // CompareUnexportedFields causes unexported struct fields, like s in + // T{s int}, to be comparsed when true. + CompareUnexportedFields = false +) + +var ( + // ErrMaxRecursion is logged when MaxDepth is reached. + ErrMaxRecursion = errors.New("recursed to MaxDepth") + + // ErrTypeMismatch is logged when Equal passed two different types of values. + ErrTypeMismatch = errors.New("variables are different reflect.Type") + + // ErrNotHandled is logged when a primitive Go kind is not handled. + ErrNotHandled = errors.New("cannot compare the reflect.Kind") +) + +type cmp struct { + diff []string + buff []string + floatFormat string +} + +var errorType = reflect.TypeOf((*error)(nil)).Elem() + +// Equal compares variables a and b, recursing into their structure up to +// MaxDepth levels deep, and returns a list of differences, or nil if there are +// none. Some differences may not be found if an error is also returned. +// +// If a type has an Equal method, like time.Equal, it is called to check for +// equality. +func Equal(a, b interface{}) []string { + aVal := reflect.ValueOf(a) + bVal := reflect.ValueOf(b) + c := &cmp{ + diff: []string{}, + buff: []string{}, + floatFormat: fmt.Sprintf("%%.%df", FloatPrecision), + } + if a == nil && b == nil { + return nil + } else if a == nil && b != nil { + c.saveDiff(b, "<nil pointer>") + } else if a != nil && b == nil { + c.saveDiff(a, "<nil pointer>") + } + if len(c.diff) > 0 { + return c.diff + } + + c.equals(aVal, bVal, 0) + if len(c.diff) > 0 { + return c.diff // diffs + } + return nil // no diffs +} + +func (c *cmp) equals(a, b reflect.Value, level int) { + if level > MaxDepth { + logError(ErrMaxRecursion) + return + } + + // Check if one value is nil, e.g. T{x: *X} and T.x is nil + if !a.IsValid() || !b.IsValid() { + if a.IsValid() && !b.IsValid() { + c.saveDiff(a.Type(), "<nil pointer>") + } else if !a.IsValid() && b.IsValid() { + c.saveDiff("<nil pointer>", b.Type()) + } + return + } + + // If differenet types, they can't be equal + aType := a.Type() + bType := b.Type() + if aType != bType { + c.saveDiff(aType, bType) + logError(ErrTypeMismatch) + return + } + + // Primitive https://golang.org/pkg/reflect/#Kind + aKind := a.Kind() + bKind := b.Kind() + + // If both types implement the error interface, compare the error strings. + // This must be done before dereferencing because the interface is on a + // pointer receiver. + if aType.Implements(errorType) && bType.Implements(errorType) { + if a.Elem().IsValid() && b.Elem().IsValid() { // both err != nil + aString := a.MethodByName("Error").Call(nil)[0].String() + bString := b.MethodByName("Error").Call(nil)[0].String() + if aString != bString { + c.saveDiff(aString, bString) + } + return + } + } + + // Dereference pointers and interface{} + if aElem, bElem := (aKind == reflect.Ptr || aKind == reflect.Interface), + (bKind == reflect.Ptr || bKind == reflect.Interface); aElem || bElem { + + if aElem { + a = a.Elem() + } + + if bElem { + b = b.Elem() + } + + c.equals(a, b, level+1) + return + } + + // Types with an Equal(), like time.Time. + eqFunc := a.MethodByName("Equal") + if eqFunc.IsValid() { + retVals := eqFunc.Call([]reflect.Value{b}) + if !retVals[0].Bool() { + c.saveDiff(a, b) + } + return + } + + switch aKind { + + ///////////////////////////////////////////////////////////////////// + // Iterable kinds + ///////////////////////////////////////////////////////////////////// + + case reflect.Struct: + /* + The variables are structs like: + type T struct { + FirstName string + LastName string + } + Type = <pkg>.T, Kind = reflect.Struct + + Iterate through the fields (FirstName, LastName), recurse into their values. + */ + for i := 0; i < a.NumField(); i++ { + if aType.Field(i).PkgPath != "" && !CompareUnexportedFields { + continue // skip unexported field, e.g. s in type T struct {s string} + } + + c.push(aType.Field(i).Name) // push field name to buff + + // Get the Value for each field, e.g. FirstName has Type = string, + // Kind = reflect.String. + af := a.Field(i) + bf := b.Field(i) + + // Recurse to compare the field values + c.equals(af, bf, level+1) + + c.pop() // pop field name from buff + + if len(c.diff) >= MaxDiff { + break + } + } + case reflect.Map: + /* + The variables are maps like: + map[string]int{ + "foo": 1, + "bar": 2, + } + Type = map[string]int, Kind = reflect.Map + + Or: + type T map[string]int{} + Type = <pkg>.T, Kind = reflect.Map + + Iterate through the map keys (foo, bar), recurse into their values. + */ + + if a.IsNil() || b.IsNil() { + if a.IsNil() && !b.IsNil() { + c.saveDiff("<nil map>", b) + } else if !a.IsNil() && b.IsNil() { + c.saveDiff(a, "<nil map>") + } + return + } + + if a.Pointer() == b.Pointer() { + return + } + + for _, key := range a.MapKeys() { + c.push(fmt.Sprintf("map[%s]", key)) + + aVal := a.MapIndex(key) + bVal := b.MapIndex(key) + if bVal.IsValid() { + c.equals(aVal, bVal, level+1) + } else { + c.saveDiff(aVal, "<does not have key>") + } + + c.pop() + + if len(c.diff) >= MaxDiff { + return + } + } + + for _, key := range b.MapKeys() { + if aVal := a.MapIndex(key); aVal.IsValid() { + continue + } + + c.push(fmt.Sprintf("map[%s]", key)) + c.saveDiff("<does not have key>", b.MapIndex(key)) + c.pop() + if len(c.diff) >= MaxDiff { + return + } + } + case reflect.Array: + n := a.Len() + for i := 0; i < n; i++ { + c.push(fmt.Sprintf("array[%d]", i)) + c.equals(a.Index(i), b.Index(i), level+1) + c.pop() + if len(c.diff) >= MaxDiff { + break + } + } + case reflect.Slice: + if a.IsNil() || b.IsNil() { + if a.IsNil() && !b.IsNil() { + c.saveDiff("<nil slice>", b) + } else if !a.IsNil() && b.IsNil() { + c.saveDiff(a, "<nil slice>") + } + return + } + + if a.Pointer() == b.Pointer() { + return + } + + aLen := a.Len() + bLen := b.Len() + n := aLen + if bLen > aLen { + n = bLen + } + for i := 0; i < n; i++ { + c.push(fmt.Sprintf("slice[%d]", i)) + if i < aLen && i < bLen { + c.equals(a.Index(i), b.Index(i), level+1) + } else if i < aLen { + c.saveDiff(a.Index(i), "<no value>") + } else { + c.saveDiff("<no value>", b.Index(i)) + } + c.pop() + if len(c.diff) >= MaxDiff { + break + } + } + + ///////////////////////////////////////////////////////////////////// + // Primitive kinds + ///////////////////////////////////////////////////////////////////// + + case reflect.Float32, reflect.Float64: + // Avoid 0.04147685731961082 != 0.041476857319611 + // 6 decimal places is close enough + aval := fmt.Sprintf(c.floatFormat, a.Float()) + bval := fmt.Sprintf(c.floatFormat, b.Float()) + if aval != bval { + c.saveDiff(a.Float(), b.Float()) + } + case reflect.Bool: + if a.Bool() != b.Bool() { + c.saveDiff(a.Bool(), b.Bool()) + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if a.Int() != b.Int() { + c.saveDiff(a.Int(), b.Int()) + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if a.Uint() != b.Uint() { + c.saveDiff(a.Uint(), b.Uint()) + } + case reflect.String: + if a.String() != b.String() { + c.saveDiff(a.String(), b.String()) + } + + default: + logError(ErrNotHandled) + } +} + +func (c *cmp) push(name string) { + c.buff = append(c.buff, name) +} + +func (c *cmp) pop() { + if len(c.buff) > 0 { + c.buff = c.buff[0 : len(c.buff)-1] + } +} + +func (c *cmp) saveDiff(aval, bval interface{}) { + if len(c.buff) > 0 { + varName := strings.Join(c.buff, ".") + c.diff = append(c.diff, fmt.Sprintf("%s: %v != %v", varName, aval, bval)) + } else { + c.diff = append(c.diff, fmt.Sprintf("%v != %v", aval, bval)) + } +} + +func logError(err error) { + if LogErrors { + log.Println(err) + } +} |