aboutsummaryrefslogtreecommitdiffstats
path: root/formats/packfile/packfile.go
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2015-10-23 14:28:49 +0200
committerMáximo Cuadros <mcuadros@gmail.com>2015-10-23 14:28:49 +0200
commitd0a18ccd8eea3bdabc76d6dc5420af1ea30aae9f (patch)
treed6b15f621627027810a6a0ecf33edb74ab433905 /formats/packfile/packfile.go
parentcf2874632223220e0445abf0a7806dc772c0b37a (diff)
downloadgo-git-d0a18ccd8eea3bdabc76d6dc5420af1ea30aae9f.tar.gz
formats/packfile: type Hash instead of strings
Diffstat (limited to 'formats/packfile/packfile.go')
-rw-r--r--formats/packfile/packfile.go82
1 files changed, 82 insertions, 0 deletions
diff --git a/formats/packfile/packfile.go b/formats/packfile/packfile.go
new file mode 100644
index 0000000..d70f396
--- /dev/null
+++ b/formats/packfile/packfile.go
@@ -0,0 +1,82 @@
+package packfile
+
+import "fmt"
+
+type Packfile struct {
+ Version uint32
+ Size int64
+ ObjectCount int
+ Checksum []byte
+ Commits map[Hash]*Commit
+ Trees map[Hash]*Tree
+ Blobs map[Hash]*Blob
+}
+
+func NewPackfile() *Packfile {
+ return &Packfile{
+ Commits: make(map[Hash]*Commit, 0),
+ Trees: make(map[Hash]*Tree, 0),
+ Blobs: make(map[Hash]*Blob, 0),
+ }
+}
+
+type BlobEntry struct {
+ path string
+ *Blob
+}
+
+type SubtreeEntry struct {
+ path string
+ *Tree
+ TreeCh
+}
+
+type treeEntry interface {
+ isTreeEntry()
+ Path() string
+}
+
+func (b BlobEntry) isTreeEntry() {}
+func (b BlobEntry) Path() string { return b.path }
+func (b SubtreeEntry) isTreeEntry() {}
+func (b SubtreeEntry) Path() string { return b.path }
+
+type TreeCh <-chan treeEntry
+
+func (p *Packfile) WalkCommit(commitHash Hash) (TreeCh, error) {
+ commit, ok := p.Commits[commitHash]
+ if !ok {
+ return nil, fmt.Errorf("Unable to find %q commit", commitHash)
+ }
+
+ return p.WalkTree(p.Trees[commit.Tree]), nil
+}
+
+func (p *Packfile) WalkTree(tree *Tree) TreeCh {
+ return p.walkTree(tree, "")
+}
+
+func (p *Packfile) walkTree(tree *Tree, pathPrefix string) TreeCh {
+ ch := make(chan treeEntry)
+
+ if tree == nil {
+ close(ch)
+ return ch
+ }
+
+ go func() {
+ defer func() {
+ close(ch)
+ }()
+ for _, e := range tree.Entries {
+ path := pathPrefix + e.Name
+ if blob, ok := p.Blobs[e.Hash]; ok {
+ ch <- BlobEntry{path, blob}
+ } else if subtree, ok := p.Trees[e.Hash]; ok {
+ ch <- SubtreeEntry{path, subtree, p.walkTree(subtree, path+"/")}
+ }
+ }
+ }()
+
+ return ch
+}