aboutsummaryrefslogtreecommitdiffstats
path: root/bug
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-07-13 21:21:24 +0200
committerMichael Muré <batolettre@gmail.com>2018-07-13 21:21:24 +0200
commit1779a0f3b92d58654b43444addeaf437a64d77a8 (patch)
tree9f973413454894f0456d7379425070d468712242 /bug
parent289f8d53ee960d35c1f0c42e8753ad536737b875 (diff)
downloadgit-bug-1779a0f3b92d58654b43444addeaf437a64d77a8.tar.gz
serialize a Bug to git as a blob+tree+commit+ref
Diffstat (limited to 'bug')
-rw-r--r--bug/bug.go86
-rw-r--r--bug/comment.go3
-rw-r--r--bug/operation.go8
-rw-r--r--bug/operation_iterator.go20
-rw-r--r--bug/operation_pack.go39
-rw-r--r--bug/operations/create.go14
-rw-r--r--bug/operations/set_title.go10
7 files changed, 134 insertions, 46 deletions
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
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