From 1779a0f3b92d58654b43444addeaf437a64d77a8 Mon Sep 17 00:00:00 2001 From: Michael Muré Date: Fri, 13 Jul 2018 21:21:24 +0200 Subject: serialize a Bug to git as a blob+tree+commit+ref --- bug/bug.go | 86 +++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 20 deletions(-) (limited to 'bug/bug.go') diff --git a/bug/bug.go b/bug/bug.go index b36246e3..8b5f4be9 100644 --- a/bug/bug.go +++ b/bug/bug.go @@ -1,27 +1,32 @@ package bug import ( + "fmt" + "github.com/MichaelMure/git-bug/repository" + "github.com/MichaelMure/git-bug/util" "github.com/kevinburke/go.uuid" ) +const BugsRefPattern = "refs/bugs/" + // Bug hold the data of a bug thread, organized in a way close to // how it will be persisted inside Git. This is the datastructure // used for merge of two different version. type Bug struct { // Id used as unique identifier - Id uuid.UUID + id uuid.UUID + + lastCommit util.Hash - // TODO: need a way to order bugs - // Probably a Lamport clock + // TODO: need a way to order bugs, probably a Lamport clock - Packs []OperationPack + packs []OperationPack - Staging OperationPack + staging OperationPack } // Create a new Bug func NewBug() (*Bug, error) { - // Creating UUID Version 4 id, err := uuid.ID4() @@ -30,27 +35,28 @@ func NewBug() (*Bug, error) { } return &Bug{ - Id: id, + id: id, + lastCommit: "", }, nil } // IsValid check if the Bug data is valid func (bug *Bug) IsValid() bool { // non-empty - if len(bug.Packs) == 0 && bug.Staging.IsEmpty() { + if len(bug.packs) == 0 && bug.staging.IsEmpty() { return false } // check if each pack is valid - for _, pack := range bug.Packs { + for _, pack := range bug.packs { if !pack.IsValid() { return false } } - // check if Staging is valid if needed - if !bug.Staging.IsEmpty() { - if !bug.Staging.IsValid() { + // check if staging is valid if needed + if !bug.staging.IsEmpty() { + if !bug.staging.IsValid() { return false } } @@ -78,27 +84,67 @@ func (bug *Bug) IsValid() bool { } func (bug *Bug) Append(op Operation) { - bug.Staging.Append(op) + bug.staging.Append(op) } -func (bug *Bug) Commit() { - bug.Packs = append(bug.Packs, bug.Staging) - bug.Staging = OperationPack{} +// Write the staging area in Git move the operations to the packs +func (bug *Bug) Commit(repo repository.Repo) error { + if bug.staging.IsEmpty() { + return nil + } + + // Write the Ops as a Git blob containing the serialized array + hash, err := bug.staging.Write(repo) + if err != nil { + return err + } + + // Write a Git tree referencing this blob + hash, err = repo.StoreTree(map[string]util.Hash{ + "ops": hash, + }) + if err != nil { + return err + } + + // Write a Git commit referencing the tree, with the previous commit as parent + if bug.lastCommit != "" { + hash, err = repo.StoreCommitWithParent(hash, bug.lastCommit) + } else { + hash, err = repo.StoreCommit(hash) + } + + if err != nil { + return err + } + + // Create or update the Git reference for this bug + ref := fmt.Sprintf("%s%s", BugsRefPattern, bug.id.String()) + err = repo.UpdateRef(ref, hash) + + if err != nil { + return err + } + + bug.packs = append(bug.packs, bug.staging) + bug.staging = OperationPack{} + + return nil } func (bug *Bug) HumanId() string { - return bug.Id.String() + return bug.id.String() } func (bug *Bug) firstOp() Operation { - for _, pack := range bug.Packs { + for _, pack := range bug.packs { for _, op := range pack.Operations { return op } } - if !bug.Staging.IsEmpty() { - return bug.Staging.Operations[0] + if !bug.staging.IsEmpty() { + return bug.staging.Operations[0] } return nil -- cgit