From da470993d13ce63087034db9b7e8ffbdf18e87a5 Mon Sep 17 00:00:00 2001 From: Michael Muré Date: Sat, 14 Jul 2018 22:17:37 +0200 Subject: complete the storage/read process + tests (!) --- bug/bug.go | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 4 deletions(-) (limited to 'bug/bug.go') diff --git a/bug/bug.go b/bug/bug.go index fc7c0c2a..9803a970 100644 --- a/bug/bug.go +++ b/bug/bug.go @@ -1,6 +1,7 @@ package bug import ( + "errors" "fmt" "github.com/MichaelMure/git-bug/repository" "github.com/MichaelMure/git-bug/util" @@ -9,6 +10,8 @@ import ( const BugsRefPattern = "refs/bugs/" const BugsRemoteRefPattern = "refs/remote/%s/bugs/" +const OpsEntryName = "ops" +const RootEntryName = "root" // 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 @@ -42,6 +45,80 @@ func NewBug() (*Bug, error) { }, nil } +// Read and parse a Bug from git +func ReadBug(repo repository.Repo, id string) (*Bug, error) { + hashes, err := repo.ListCommits(BugsRefPattern + id) + + if err != nil { + return nil, err + } + + parsedId, err := uuid.FromString(id) + + if err != nil { + return nil, err + } + + bug := Bug{ + id: parsedId, + } + + for _, hash := range hashes { + entries, err := repo.ListEntries(hash) + + bug.lastCommit = hash + + if err != nil { + return nil, err + } + + var opsEntry repository.TreeEntry + opsFound := false + var rootEntry repository.TreeEntry + rootFound := false + + for _, entry := range entries { + if entry.Name == OpsEntryName { + opsEntry = entry + opsFound = true + continue + } + if entry.Name == RootEntryName { + rootEntry = entry + rootFound = true + } + } + + if !opsFound { + return nil, errors.New("Invalid tree, missing the ops entry") + } + + if !rootFound { + return nil, errors.New("Invalid tree, missing the root entry") + } + + if bug.root == "" { + bug.root = rootEntry.Hash + } + + data, err := repo.ReadData(opsEntry.Hash) + + if err != nil { + return nil, err + } + + op, err := ParseOperationPack(data) + + if err != nil { + return nil, err + } + + bug.packs = append(bug.packs, *op) + } + + return &bug, nil +} + // IsValid check if the Bug data is valid func (bug *Bug) IsValid() bool { // non-empty @@ -104,12 +181,13 @@ func (bug *Bug) Commit(repo repository.Repo) error { root := bug.root if root == "" { root = hash + bug.root = hash } // Write a Git tree referencing this blob - hash, err = repo.StoreTree(map[string]util.Hash{ - "ops": hash, // the last pack of ops - "root": root, // always the first pack of ops (might be the same) + hash, err = repo.StoreTree([]repository.TreeEntry{ + {repository.Blob, hash, OpsEntryName}, // the last pack of ops + {repository.Blob, root, RootEntryName}, // always the first pack of ops (might be the same) }) if err != nil { return err @@ -126,6 +204,8 @@ func (bug *Bug) Commit(repo repository.Repo) error { return err } + bug.lastCommit = hash + // Create or update the Git reference for this bug ref := fmt.Sprintf("%s%s", BugsRefPattern, bug.id.String()) err = repo.UpdateRef(ref, hash) @@ -140,8 +220,12 @@ func (bug *Bug) Commit(repo repository.Repo) error { return nil } +func (bug *Bug) Id() string { + return fmt.Sprintf("%x", bug.id) +} + func (bug *Bug) HumanId() string { - return bug.id.String() + return fmt.Sprintf("%.8s", bug.Id()) } func (bug *Bug) firstOp() Operation { @@ -157,3 +241,16 @@ func (bug *Bug) firstOp() Operation { return nil } + +// Compile a bug in a easily usable snapshot +func (bug *Bug) Compile() Snapshot { + snap := Snapshot{} + + it := NewOperationIterator(bug) + + for it.Next() { + snap = it.Value().Apply(snap) + } + + return snap +} -- cgit