diff options
author | Michael Muré <batolettre@gmail.com> | 2018-09-28 23:51:47 +0200 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2018-09-29 00:51:54 +0200 |
commit | 794d014fae9a78bd8664e6628a20902bd6dc767a (patch) | |
tree | 059fe4469787f792b6ddc4c29e6232c4263ece53 | |
parent | 1bf268cebc84a9de1e538cbb54bcc0f434022192 (diff) | |
download | git-bug-794d014fae9a78bd8664e6628a20902bd6dc767a.tar.gz |
bug: define a hash-based identifier for an operation
-rw-r--r-- | bug/bug_test.go | 3 | ||||
-rw-r--r-- | bug/op_add_comment.go | 4 | ||||
-rw-r--r-- | bug/op_create.go | 4 | ||||
-rw-r--r-- | bug/op_label_change.go | 5 | ||||
-rw-r--r-- | bug/op_set_status.go | 5 | ||||
-rw-r--r-- | bug/op_set_title.go | 5 | ||||
-rw-r--r-- | bug/operation.go | 40 | ||||
-rw-r--r-- | bug/operation_pack.go | 3 | ||||
-rw-r--r-- | tests/graphql_test.go | 2 |
9 files changed, 64 insertions, 7 deletions
diff --git a/bug/bug_test.go b/bug/bug_test.go index d85db6d2..6504da1a 100644 --- a/bug/bug_test.go +++ b/bug/bug_test.go @@ -74,6 +74,9 @@ func TestBugSerialisation(t *testing.T) { // ignore some fields bug2.packs[0].commitHash = bug1.packs[0].commitHash + for i := range bug1.packs[0].Operations { + bug2.packs[0].Operations[i].base().hash = bug1.packs[0].Operations[i].base().hash + } deep.CompareUnexportedFields = true if diff := deep.Equal(bug1, bug2); diff != nil { diff --git a/bug/op_add_comment.go b/bug/op_add_comment.go index 0a3a5a37..300609fb 100644 --- a/bug/op_add_comment.go +++ b/bug/op_add_comment.go @@ -22,6 +22,10 @@ func (op AddCommentOperation) base() *OpBase { return op.OpBase } +func (op AddCommentOperation) Hash() (git.Hash, error) { + return hashOperation(op) +} + func (op AddCommentOperation) Apply(snapshot Snapshot) Snapshot { comment := Comment{ Message: op.Message, diff --git a/bug/op_create.go b/bug/op_create.go index 2852a519..c65b3bd8 100644 --- a/bug/op_create.go +++ b/bug/op_create.go @@ -23,6 +23,10 @@ func (op CreateOperation) base() *OpBase { return op.OpBase } +func (op CreateOperation) Hash() (git.Hash, error) { + return hashOperation(op) +} + func (op CreateOperation) Apply(snapshot Snapshot) Snapshot { snapshot.Title = op.Title snapshot.Comments = []Comment{ diff --git a/bug/op_label_change.go b/bug/op_label_change.go index 120671fb..c245d1a5 100644 --- a/bug/op_label_change.go +++ b/bug/op_label_change.go @@ -4,6 +4,7 @@ import ( "fmt" "sort" + "github.com/MichaelMure/git-bug/util/git" "github.com/pkg/errors" ) @@ -20,6 +21,10 @@ func (op LabelChangeOperation) base() *OpBase { return op.OpBase } +func (op LabelChangeOperation) Hash() (git.Hash, error) { + return hashOperation(op) +} + // Apply apply the operation func (op LabelChangeOperation) Apply(snapshot Snapshot) Snapshot { // Add in the set diff --git a/bug/op_set_status.go b/bug/op_set_status.go index d6df3da4..19af46c2 100644 --- a/bug/op_set_status.go +++ b/bug/op_set_status.go @@ -1,6 +1,7 @@ package bug import ( + "github.com/MichaelMure/git-bug/util/git" "github.com/pkg/errors" ) @@ -17,6 +18,10 @@ func (op SetStatusOperation) base() *OpBase { return op.OpBase } +func (op SetStatusOperation) Hash() (git.Hash, error) { + return hashOperation(op) +} + func (op SetStatusOperation) Apply(snapshot Snapshot) Snapshot { snapshot.Status = op.Status diff --git a/bug/op_set_title.go b/bug/op_set_title.go index e8c5caf8..a4912143 100644 --- a/bug/op_set_title.go +++ b/bug/op_set_title.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/MichaelMure/git-bug/util/git" "github.com/MichaelMure/git-bug/util/text" ) @@ -21,6 +22,10 @@ func (op SetTitleOperation) base() *OpBase { return op.OpBase } +func (op SetTitleOperation) Hash() (git.Hash, error) { + return hashOperation(op) +} + func (op SetTitleOperation) Apply(snapshot Snapshot) Snapshot { snapshot.Title = op.Title diff --git a/bug/operation.go b/bug/operation.go index cd4094dc..4c6f2e5a 100644 --- a/bug/operation.go +++ b/bug/operation.go @@ -1,11 +1,13 @@ package bug import ( - "github.com/MichaelMure/git-bug/util/git" - "github.com/pkg/errors" - + "crypto/sha256" + "encoding/json" "fmt" "time" + + "github.com/MichaelMure/git-bug/util/git" + "github.com/pkg/errors" ) // OperationType is an operation type identifier @@ -24,6 +26,8 @@ const ( type Operation interface { // base return the OpBase of the Operation, for package internal use base() *OpBase + // Hash return the hash of the operation + Hash() (git.Hash, error) // Time return the time when the operation was added Time() time.Time // GetUnixTime return the unix timestamp when the operation was added @@ -40,11 +44,35 @@ type Operation interface { GetMetadata(key string) (string, bool) } +func hashRaw(data []byte) git.Hash { + hasher := sha256.New() + return git.Hash(fmt.Sprintf("%x", hasher.Sum(data))) +} + +// hash compute the hash of the serialized operation +func hashOperation(op Operation) (git.Hash, error) { + base := op.base() + + if base.hash != "" { + return base.hash, nil + } + + data, err := json.Marshal(op) + if err != nil { + return "", err + } + + base.hash = hashRaw(data) + + return base.hash, nil +} + // OpBase implement the common code for all operations type OpBase struct { - OperationType OperationType `json:"type"` - Author Person `json:"author"` - UnixTime int64 `json:"timestamp"` + OperationType OperationType `json:"type"` + Author Person `json:"author"` + UnixTime int64 `json:"timestamp"` + hash git.Hash Metadata map[string]string `json:"metadata,omitempty"` } diff --git a/bug/operation_pack.go b/bug/operation_pack.go index 2da8bee0..5238ea60 100644 --- a/bug/operation_pack.go +++ b/bug/operation_pack.go @@ -62,6 +62,9 @@ func (opp *OperationPack) UnmarshalJSON(data []byte) error { return err } + // Compute the hash of the operation + op.base().hash = hashRaw(raw) + opp.Operations = append(opp.Operations, op) } diff --git a/tests/graphql_test.go b/tests/graphql_test.go index c6dcd9e0..77008628 100644 --- a/tests/graphql_test.go +++ b/tests/graphql_test.go @@ -111,7 +111,7 @@ func TestQueries(t *testing.T) { Nodes []struct { Author Person CreatedAt string `json:"createdAt"` - HumandId string `json:"humanId"` + HumanId string `json:"humanId"` Id string LastEdit string `json:"lastEdit"` Status string |