5
5
// "github.com/pborman/getopt/v2"
6
6
"gopkg.in/src-d/go-git.v4"
7
7
"gopkg.in/src-d/go-git.v4/plumbing"
8
+ "gopkg.in/src-d/go-git.v4/plumbing/filemode"
8
9
"gopkg.in/src-d/go-git.v4/plumbing/object"
9
10
"log"
10
11
"strings"
@@ -19,35 +20,36 @@ func fatalf(fmt string, args ...interface{}) {
19
20
}
20
21
21
22
type Trac struct {
22
- commit object.Commit
23
- subHeads []Trac
23
+ name string
24
+ hash plumbing.Hash
25
+ subHeads []* Trac
24
26
tracCommit * object.Commit
25
27
}
26
28
27
29
func (t Trac ) String () string {
28
30
var heads []string
29
31
for _ , v := range t .subHeads {
30
- heads = append (heads , fmt .Sprintf ("%.10v" , v .commit . Hash ))
32
+ heads = append (heads , fmt .Sprintf ("%.10v" , v .hash ))
31
33
}
32
34
headstr := strings .Join (heads , "," )
33
35
34
36
if t .tracCommit != nil {
35
- return fmt .Sprintf ("%.10v[%v]<%.10v>" ,
36
- t .commit . Hash , headstr , t .tracCommit .Hash )
37
+ return fmt .Sprintf ("%.10v:%v [%v]<%.10v>" ,
38
+ t .hash , t . name , headstr , t .tracCommit .Hash )
37
39
} else {
38
- return fmt .Sprintf ("%.10v[%v]<>" , t .commit . Hash , headstr )
40
+ return fmt .Sprintf ("%.10v:%v [%v]<>" , t .hash , t . name , headstr )
39
41
}
40
42
}
41
43
42
44
type Cache struct {
43
45
repo * git.Repository
44
- tracs map [plumbing.Hash ]Trac
46
+ tracs map [plumbing.Hash ]* Trac
45
47
}
46
48
47
49
func NewCache (r * git.Repository ) * Cache {
48
50
c := Cache {
49
51
repo : r ,
50
- tracs : make (map [plumbing.Hash ]Trac ),
52
+ tracs : make (map [plumbing.Hash ]* Trac ),
51
53
}
52
54
return & c
53
55
}
@@ -60,27 +62,77 @@ func (c *Cache) String() string {
60
62
return strings .Join (out , "\n " )
61
63
}
62
64
65
+ func (c * Cache ) tracByRef (refname string ) (* Trac , error ) {
66
+ rn := plumbing .NewBranchReferenceName (refname )
67
+ ref , err := c .repo .Reference (rn , true )
68
+ if err != nil {
69
+ return nil , err
70
+ }
71
+ commit , err := c .repo .CommitObject (ref .Hash ())
72
+ if err != nil {
73
+ return nil , err
74
+ }
75
+ return c .tracCommit (commit )
76
+ }
77
+
63
78
// Mercifully, git's content-addressable storage means there are never
64
79
// any cycles when traversing the commit+submodule hierarchy, although the
65
80
// same sub-objects may occur many times at different points in the tree.
66
- func (c * Cache ) Add (commit * object.Commit ) error {
67
- c .tracs [commit .Hash ] = Trac {
68
- commit : * commit ,
81
+ func (c * Cache ) tracCommit (commit * object.Commit ) (* Trac , error ) {
82
+ trac := c .tracs [commit .Hash ]
83
+ if trac != nil {
84
+ return trac , nil
69
85
}
70
- return nil
71
- }
72
-
73
- func (c * Cache ) AddByRef (refname string ) error {
74
- rn := plumbing .NewBranchReferenceName (refname )
75
- ref , err := c .repo .Reference (rn , true )
86
+ trac = & Trac {
87
+ name : "<COMMIT>" ,
88
+ hash : commit .Hash ,
89
+ }
90
+ tree , err := commit .Tree ()
76
91
if err != nil {
77
- return err
92
+ return nil , fmt . Errorf ( "%.10v.Tree: %v" , commit . Hash , err )
78
93
}
79
- commit , err : = c .repo . CommitObject ( ref . Hash () )
94
+ _ , err = c .tracTree ( "<ROOT>" , tree )
80
95
if err != nil {
81
- return err
96
+ return nil , fmt .Errorf ("%.10v.addTree: %v" , commit .Hash , err )
97
+ }
98
+ for _ , parent := range commit .ParentHashes {
99
+ pc , err := c .repo .CommitObject (parent )
100
+ if err != nil {
101
+ return nil , fmt .Errorf ("%.10v: %v" , pc .Hash , err )
102
+ }
103
+ _ , err = c .tracCommit (pc )
104
+ }
105
+ c .tracs [commit .Hash ] = trac
106
+ return trac , nil
107
+ }
108
+
109
+ func (c * Cache ) tracTree (name string , tree * object.Tree ) (* Trac , error ) {
110
+ trac := c .tracs [tree .Hash ]
111
+ if trac != nil {
112
+ return trac , nil
113
+ }
114
+ for _ , e := range tree .Entries {
115
+ if e .Mode == filemode .Submodule {
116
+ debugf ("submodule: %v/\n " , e .Name )
117
+ } else if e .Mode == filemode .Dir {
118
+ t , err := c .repo .TreeObject (e .Hash )
119
+ if err != nil {
120
+ return nil , fmt .Errorf ("%.10v.Tree.%.10v: %v" ,
121
+ tree .Hash , e .Hash , err )
122
+ }
123
+ _ , err = c .tracTree (e .Name , t )
124
+ if err != nil {
125
+ return nil , fmt .Errorf ("%.10v.addTree: %v" ,
126
+ t .Hash , err )
127
+ }
128
+ }
129
+ }
130
+ trac = & Trac {
131
+ name : name ,
132
+ hash : tree .Hash ,
82
133
}
83
- return c .Add (commit )
134
+ c .tracs [tree .Hash ] = trac
135
+ return trac , nil
84
136
}
85
137
86
138
func main () {
@@ -91,9 +143,9 @@ func main() {
91
143
}
92
144
c := NewCache (r )
93
145
refname := "junk"
94
- err = c .AddByRef (refname )
146
+ _ , err = c .tracByRef (refname )
95
147
if err != nil {
96
148
fatalf ("AddByRef: %v: %v\n " , refname , err )
97
149
}
98
- debugf ( "cache: \n %v\n " , c )
150
+ fmt . Printf ( " %v\n " , c )
99
151
}
0 commit comments