diff options
author | Michael Muré <batolettre@gmail.com> | 2018-07-13 21:21:24 +0200 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2018-07-13 21:21:24 +0200 |
commit | 1779a0f3b92d58654b43444addeaf437a64d77a8 (patch) | |
tree | 9f973413454894f0456d7379425070d468712242 /bug | |
parent | 289f8d53ee960d35c1f0c42e8753ad536737b875 (diff) | |
download | git-bug-1779a0f3b92d58654b43444addeaf437a64d77a8.tar.gz |
serialize a Bug to git as a blob+tree+commit+ref
Diffstat (limited to 'bug')
-rw-r--r-- | bug/bug.go | 86 | ||||
-rw-r--r-- | bug/comment.go | 3 | ||||
-rw-r--r-- | bug/operation.go | 8 | ||||
-rw-r--r-- | bug/operation_iterator.go | 20 | ||||
-rw-r--r-- | bug/operation_pack.go | 39 | ||||
-rw-r--r-- | bug/operations/create.go | 14 | ||||
-rw-r--r-- | bug/operations/set_title.go | 10 |
7 files changed, 134 insertions, 46 deletions
@@ -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 diff --git a/bug/comment.go b/bug/comment.go index edd5666c..f7727709 100644 --- a/bug/comment.go +++ b/bug/comment.go @@ -1,9 +1,6 @@ package bug -import "github.com/MichaelMure/git-bug/util" - type Comment struct { Author Person Message string - Media []util.Hash } diff --git a/bug/operation.go b/bug/operation.go index f36e9e39..591c7176 100644 --- a/bug/operation.go +++ b/bug/operation.go @@ -13,3 +13,11 @@ type Operation interface { OpType() OperationType Apply(snapshot Snapshot) Snapshot } + +type OpBase struct { + OperationType OperationType `json:"op"` +} + +func (op OpBase) OpType() OperationType { + return op.OperationType +} diff --git a/bug/operation_iterator.go b/bug/operation_iterator.go index fe001d45..0df8b599 100644 --- a/bug/operation_iterator.go +++ b/bug/operation_iterator.go @@ -16,17 +16,17 @@ func NewOperationIterator(bug *Bug) *OperationIterator { func (it *OperationIterator) Next() bool { // Special case of the staging area - if it.packIndex == len(it.bug.Packs) { - pack := it.bug.Staging + if it.packIndex == len(it.bug.packs) { + pack := it.bug.staging it.opIndex++ return it.opIndex < len(pack.Operations) } - if it.packIndex >= len(it.bug.Packs) { + if it.packIndex >= len(it.bug.packs) { return false } - pack := it.bug.Packs[it.packIndex] + pack := it.bug.packs[it.packIndex] it.opIndex++ @@ -39,17 +39,17 @@ func (it *OperationIterator) Next() bool { it.packIndex++ // Special case of the non-empty staging area - if it.packIndex == len(it.bug.Packs) && len(it.bug.Staging.Operations) > 0 { + if it.packIndex == len(it.bug.packs) && len(it.bug.staging.Operations) > 0 { return true } - return it.packIndex < len(it.bug.Packs) + return it.packIndex < len(it.bug.packs) } func (it *OperationIterator) Value() Operation { // Special case of the staging area - if it.packIndex == len(it.bug.Packs) { - pack := it.bug.Staging + if it.packIndex == len(it.bug.packs) { + pack := it.bug.staging if it.opIndex >= len(pack.Operations) { panic("Iterator is not valid anymore") @@ -58,11 +58,11 @@ func (it *OperationIterator) Value() Operation { return pack.Operations[it.opIndex] } - if it.packIndex >= len(it.bug.Packs) { + if it.packIndex >= len(it.bug.packs) { panic("Iterator is not valid anymore") } - pack := it.bug.Packs[it.packIndex] + pack := it.bug.packs[it.packIndex] if it.opIndex >= len(pack.Operations) { panic("Iterator is not valid anymore") diff --git a/bug/operation_pack.go b/bug/operation_pack.go index 21376b9c..67a2a072 100644 --- a/bug/operation_pack.go +++ b/bug/operation_pack.go @@ -1,5 +1,11 @@ package bug +import ( + "encoding/json" + "github.com/MichaelMure/git-bug/repository" + "github.com/MichaelMure/git-bug/util" +) + // OperationPack represent an ordered set of operation to apply // to a Bug. These operations are stored in a single Git commit. // @@ -7,7 +13,22 @@ package bug // inside Git to form the complete ordered chain of operation to // apply to get the final state of the Bug type OperationPack struct { - Operations []Operation + Operations []Operation `json:"ops"` + hash util.Hash +} + +func Parse() (OperationPack, error) { + // TODO + return OperationPack{}, nil +} + +func (opp *OperationPack) Serialize() ([]byte, error) { + jsonBytes, err := json.Marshal(*opp) + if err != nil { + return nil, err + } + + return jsonBytes, nil } // Append a new operation to the pack @@ -22,3 +43,19 @@ func (opp *OperationPack) IsEmpty() bool { func (opp *OperationPack) IsValid() bool { return !opp.IsEmpty() } + +func (opp *OperationPack) Write(repo repository.Repo) (util.Hash, error) { + data, err := opp.Serialize() + + if err != nil { + return "", err + } + + hash, err := repo.StoreData(data) + + if err != nil { + return "", err + } + + return hash, nil +} diff --git a/bug/operations/create.go b/bug/operations/create.go index 57cca907..9911ee89 100644 --- a/bug/operations/create.go +++ b/bug/operations/create.go @@ -10,22 +10,24 @@ import ( var _ bug.Operation = CreateOperation{} type CreateOperation struct { - Title string - Message string - Author bug.Person + bug.OpBase + Title string `json:"t"` + Message string `json:"m"` + Author bug.Person `json:"a"` } func NewCreateOp(author bug.Person, title, message string) CreateOperation { return CreateOperation{ + OpBase: bug.OpBase{OperationType: bug.CREATE}, Title: title, Message: message, Author: author, } } -func (op CreateOperation) OpType() bug.OperationType { - return bug.CREATE -} +//func (op CreateOperation) OpType() bug.OperationType { +// return bug.CREATE +//} func (op CreateOperation) Apply(snapshot bug.Snapshot) bug.Snapshot { empty := bug.Snapshot{} diff --git a/bug/operations/set_title.go b/bug/operations/set_title.go index 1e2ef20a..39f4b332 100644 --- a/bug/operations/set_title.go +++ b/bug/operations/set_title.go @@ -5,19 +5,17 @@ import "github.com/MichaelMure/git-bug/bug" var _ bug.Operation = SetTitleOperation{} type SetTitleOperation struct { - Title string + bug.OpBase + Title string `json:"t"` } func NewSetTitleOp(title string) SetTitleOperation { return SetTitleOperation{ - Title: title, + OpBase: bug.OpBase{OperationType: bug.SET_TITLE}, + Title: title, } } -func (op SetTitleOperation) OpType() bug.OperationType { - return bug.SET_TITLE -} - func (op SetTitleOperation) Apply(snapshot bug.Snapshot) bug.Snapshot { snapshot.Title = op.Title return snapshot |