bug: define a hash-based identifier for an operation

This commit is contained in:
Michael Muré 2018-09-28 23:51:47 +02:00
parent 1bf268cebc
commit 794d014fae
No known key found for this signature in database
GPG Key ID: A4457C029293126F
9 changed files with 64 additions and 7 deletions

View File

@ -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 {

View File

@ -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,

View File

@ -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{

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"`
}

View File

@ -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)
}

View File

@ -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