aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-09-28 23:51:47 +0200
committerMichael Muré <batolettre@gmail.com>2018-09-29 00:51:54 +0200
commit794d014fae9a78bd8664e6628a20902bd6dc767a (patch)
tree059fe4469787f792b6ddc4c29e6232c4263ece53
parent1bf268cebc84a9de1e538cbb54bcc0f434022192 (diff)
downloadgit-bug-794d014fae9a78bd8664e6628a20902bd6dc767a.tar.gz
bug: define a hash-based identifier for an operation
-rw-r--r--bug/bug_test.go3
-rw-r--r--bug/op_add_comment.go4
-rw-r--r--bug/op_create.go4
-rw-r--r--bug/op_label_change.go5
-rw-r--r--bug/op_set_status.go5
-rw-r--r--bug/op_set_title.go5
-rw-r--r--bug/operation.go40
-rw-r--r--bug/operation_pack.go3
-rw-r--r--tests/graphql_test.go2
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