@@ -13,12 +13,15 @@ import (
13
13
"strings"
14
14
)
15
15
16
+ // A Trac represents a commit or tree somewhere in the project's hierarchy,
17
+ // including submodules. If one of its children contains submodules,
18
+ // subHeads and tracCommit will be populated.
16
19
type Trac struct {
17
- name string
18
- hash plumbing.Hash
19
- parents []* Trac
20
- subHeads []* Trac
21
- tracCommit * object.Commit
20
+ name string // a human-readable path to this object
21
+ hash plumbing.Hash // the git hash of this object
22
+ parents []* Trac // parent commits (if this is a commit)
23
+ subHeads []* Trac // submodule commits contained by this
24
+ tracCommit * object.Commit // synthetic commit with parents+subHeads
22
25
}
23
26
24
27
func (t Trac ) String () string {
@@ -39,11 +42,11 @@ func (t Trac) String() string {
39
42
type Cache struct {
40
43
debugf func (fmt string , args ... interface {})
41
44
infof func (fmt string , args ... interface {})
42
- repoDir string
43
- repo * git.Repository
44
- autoexclude bool
45
- excludes map [plumbing.Hash ]bool
46
- tracs map [plumbing.Hash ]* Trac
45
+ repoDir string // toplevel repo dir
46
+ repo * git.Repository // open copy of the toplevel repo
47
+ autoexclude bool // --auto-exclude enabled
48
+ excludes map [plumbing.Hash ]bool // specifically excluded objects
49
+ tracs map [plumbing.Hash ]* Trac // object lookup cache
47
50
}
48
51
49
52
func NewCache (rdir string , r * git.Repository , excludes []string ,
@@ -82,13 +85,15 @@ func (c *Cache) String() string {
82
85
return strings .Join (out , "\n " )
83
86
}
84
87
88
+ // Add one commit to the exclusion list.
85
89
func (c * Cache ) exclude (hash plumbing.Hash ) {
86
90
if ! c .excludes [hash ] {
87
91
c .excludes [hash ] = true
88
92
c .infof ("Excluding %v\n " , hash )
89
93
}
90
94
}
91
95
96
+ // Load all branches into the cache, and update a .trac ref for each one.
92
97
func (c * Cache ) UpdateBranchRefs () error {
93
98
branchIter , err := c .repo .Branches ()
94
99
if err != nil {
@@ -132,6 +137,7 @@ func (c *Cache) UpdateBranchRefs() error {
132
137
return nil
133
138
}
134
139
140
+ // Generate a synthetic commit for the given ref.
135
141
func (c * Cache ) TracByRef (refname string ) (* object.Commit , error ) {
136
142
h , err := c .repo .ResolveRevision (plumbing .Revision (refname ))
137
143
if err != nil {
@@ -148,6 +154,12 @@ func (c *Cache) TracByRef(refname string) (*object.Commit, error) {
148
154
return tc .tracCommit , nil
149
155
}
150
156
157
+ // Starting at the given commit, load all its recursive parents and
158
+ // submodule references into the cache, returning the cache entry.
159
+ //
160
+ // This doesn't update any references in the repo itself, it just returns a
161
+ // new object representing the commit, including its synthetic trac commit.
162
+ //
151
163
// Mercifully, git's content-addressable storage means there are never
152
164
// any cycles when traversing the commit+submodule hierarchy, although the
153
165
// same sub-objects may occur many times at different points in the tree.
@@ -222,6 +234,7 @@ func (c *Cache) tracCommit(path string, commit *object.Commit) (*Trac, error) {
222
234
return trac , nil
223
235
}
224
236
237
+ // True if a and b are equal.
225
238
func equalSubs (a , b []* Trac ) bool {
226
239
if len (a ) != len (b ) {
227
240
return false
@@ -234,6 +247,9 @@ func equalSubs(a, b []*Trac) bool {
234
247
return true
235
248
}
236
249
250
+ // Given a list of parents and submodules for a given real git commit,
251
+ // produce a synthetic trac commit that includes all parents and submodules,
252
+ // but not the commit itself.
237
253
func (c * Cache ) newTracCommit (commit * object.Commit , tracs []* object.Commit , heads []* Trac ) (* object.Commit , error ) {
238
254
var parents []plumbing.Hash
239
255
@@ -283,6 +299,13 @@ func (c *Cache) newTracCommit(commit *object.Commit, tracs []*object.Commit, hea
283
299
return tc , nil
284
300
}
285
301
302
+ // Update a "commit path" which represents how we get to a given commit
303
+ // from a starting point. So if the starting point is "master^2~25, and sub is
304
+ // 1, the result is master^2~26. If sub is 3, the result is master^2~25^3, and
305
+ // so on.
306
+ //
307
+ // These paths look weird but are valid git syntax, and are somewhat human-
308
+ // friendly once you get used to them.
286
309
func commitPath (path string , sub int ) string {
287
310
if sub != 1 {
288
311
return fmt .Sprintf ("%s^%d" , path , sub )
@@ -298,6 +321,9 @@ func commitPath(path string, sub int) string {
298
321
return fmt .Sprintf ("%s~%d" , path [:ix ], v + 1 )
299
322
}
300
323
324
+ // Try to find a given commit object in all submodule repositories. If it
325
+ // exists, 'git fetch' it into the main repository so we can refer to it
326
+ // as a parent of our synthetic commits.
301
327
func (c * Cache ) tryFetchFromSubmodules (path string , hash plumbing.Hash ) error {
302
328
c .infof ("Searching submodules for: %v\n " , path )
303
329
wt , err := c .repo .Worktree ()
@@ -360,6 +386,9 @@ func (c *Cache) tryFetchFromSubmodules(path string, hash plumbing.Hash) error {
360
386
return fmt .Errorf ("%v: %v not found." , path , hash )
361
387
}
362
388
389
+ // Starting from a given git tree object, recursively add all its subtree
390
+ // and submodules into the cache, returning the cache object representing
391
+ // this tree.
363
392
func (c * Cache ) tracTree (path string , tree * object.Tree ) (* Trac , error ) {
364
393
trac := c .tracs [tree .Hash ]
365
394
if trac != nil {
@@ -421,6 +450,7 @@ func (c *Cache) tracTree(path string, tree *object.Tree) (*Trac, error) {
421
450
return trac , nil
422
451
}
423
452
453
+ // Add a given entry into the cache.
424
454
func (c * Cache ) add (trac * Trac ) {
425
455
c .debugf (" add %.10v %v\n " , trac .hash , trac .name )
426
456
c .tracs [trac .hash ] = trac
0 commit comments