aboutsummaryrefslogtreecommitdiffstats
path: root/packfile/packfile.go
diff options
context:
space:
mode:
authorMáximo Cuadros Ortiz <mcuadros@gmail.com>2015-04-05 23:34:43 +0200
committerMáximo Cuadros Ortiz <mcuadros@gmail.com>2015-04-06 04:12:04 +0200
commit5d7303c49ac984a9fec60523f2d5297682e16646 (patch)
tree53ac3a7eae7e271e58cc37ab1b7d2c27f3f2a9e5 /packfile/packfile.go
downloadgo-git-5d7303c49ac984a9fec60523f2d5297682e16646.tar.gz
some refactor in folders and crawler
Diffstat (limited to 'packfile/packfile.go')
-rw-r--r--packfile/packfile.go82
1 files changed, 82 insertions, 0 deletions
diff --git a/packfile/packfile.go b/packfile/packfile.go
new file mode 100644
index 0000000..e670cd0
--- /dev/null
+++ b/packfile/packfile.go
@@ -0,0 +1,82 @@
+package packfile
+
+import "fmt"
+
+type Packfile struct {
+ Version uint32
+ ObjectCount int
+ Checksum []byte
+ Commits map[string]*Commit
+ Trees map[string]*Tree
+ Blobs map[string]*Blob
+}
+
+func NewPackfile() *Packfile {
+ return &Packfile{
+ Commits: make(map[string]*Commit, 0),
+ Trees: make(map[string]*Tree, 0),
+ Blobs: make(map[string]*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 string) (TreeCh, error) {
+ commit, ok := p.Commits[commitHash]
+ if !ok {
+ return nil, fmt.Errorf("Unable to find %q commit", commitHash)
+ }
+
+ treeHash := fmt.Sprintf("%x", string(commit.Tree))
+ return p.WalkTree(p.Trees[treeHash]), 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
+}