Skip to content

Commit 559b030

Browse files
committed
Collect references before starting the object traversal
This provides a better separation of concerns, which will be taken advantage of shortly.
1 parent 9ed78b1 commit 559b030

File tree

2 files changed

+90
-71
lines changed

2 files changed

+90
-71
lines changed

sizes/graph.go

Lines changed: 8 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -11,50 +11,6 @@ import (
1111
"github.com/github/git-sizer/meter"
1212
)
1313

14-
// RefGroupSymbol is the string "identifier" that is used to refer to
15-
// a refgroup, for example in the gitconfig. Nesting of refgroups is
16-
// inferred from their names, using "." as separator between
17-
// components. For example, if there are three refgroups with symbols
18-
// "tags", "tags.releases", and "foo.bar", then "tags.releases" is
19-
// considered to be nested within "tags", and "foo.bar" is considered
20-
// to be nested within "foo", the latter being created automatically
21-
// if it was not configured explicitly.
22-
type RefGroupSymbol string
23-
24-
// RefGroup is a group of references, for example "branches" or
25-
// "tags". Reference groups might overlap.
26-
type RefGroup struct {
27-
// Symbol is the unique string by which this `RefGroup` is
28-
// identified and configured. It consists of dot-separated
29-
// components, which implicitly makes a nested tree-like
30-
// structure.
31-
Symbol RefGroupSymbol
32-
33-
// Name is the name for this `ReferenceGroup` to be presented
34-
// in user-readable output.
35-
Name string
36-
}
37-
38-
// RefGrouper describes a type that can collate reference names into
39-
// groups and decide which ones to walk.
40-
type RefGrouper interface {
41-
// Categorize tells whether `refname` should be walked at all,
42-
// and if so, the symbols of the reference groups to which it
43-
// belongs.
44-
Categorize(refname string) (bool, []RefGroupSymbol)
45-
46-
// Groups returns the list of `ReferenceGroup`s, in the order
47-
// that they should be presented. The return value might
48-
// depend on which references have been seen so far.
49-
Groups() []RefGroup
50-
}
51-
52-
type refSeen struct {
53-
git.Reference
54-
walked bool
55-
groups []RefGroupSymbol
56-
}
57-
5814
// ScanRepositoryUsingGraph scans `repo`, using `rg` to decide which
5915
// references to scan and how to group them. `nameStyle` specifies
6016
// whether the output should include full names, hashes only, or
@@ -71,9 +27,9 @@ func ScanRepositoryUsingGraph(
7127

7228
graph := NewGraph(nameStyle)
7329

74-
refIter, err := repo.NewReferenceIter(ctx)
30+
refsSeen, err := CollectReferences(ctx, repo, rg)
7531
if err != nil {
76-
return HistorySize{}, err
32+
return HistorySize{}, fmt.Errorf("reading references: %w", err)
7733
}
7834

7935
objIter, err := repo.NewObjectIter(context.TODO())
@@ -82,41 +38,22 @@ func ScanRepositoryUsingGraph(
8238
}
8339

8440
errChan := make(chan error, 1)
85-
var refsSeen []refSeen
86-
// Feed the references that we want into the stdin of the object
87-
// iterator:
41+
// Feed the references that we want to walk into the stdin of the
42+
// object iterator:
8843
go func() {
8944
defer objIter.Close()
9045

9146
errChan <- func() error {
92-
for {
93-
ref, ok, err := refIter.Next()
94-
if err != nil {
95-
return err
96-
}
97-
if !ok {
98-
return nil
99-
}
100-
101-
walk, groups := rg.Categorize(ref.Refname)
102-
103-
refsSeen = append(
104-
refsSeen,
105-
refSeen{
106-
Reference: ref,
107-
walked: walk,
108-
groups: groups,
109-
},
110-
)
111-
112-
if !walk {
47+
for _, refSeen := range refsSeen {
48+
if !refSeen.walked {
11349
continue
11450
}
11551

116-
if err := objIter.AddRoot(ref.OID); err != nil {
52+
if err := objIter.AddRoot(refSeen.OID); err != nil {
11753
return err
11854
}
11955
}
56+
return nil
12057
}()
12158
}()
12259

sizes/grouper.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package sizes
2+
3+
import (
4+
"context"
5+
6+
"github.com/github/git-sizer/git"
7+
)
8+
9+
// RefGroupSymbol is the string "identifier" that is used to refer to
10+
// a refgroup, for example in the gitconfig. Nesting of refgroups is
11+
// inferred from their names, using "." as separator between
12+
// components. For example, if there are three refgroups with symbols
13+
// "tags", "tags.releases", and "foo.bar", then "tags.releases" is
14+
// considered to be nested within "tags", and "foo.bar" is considered
15+
// to be nested within "foo", the latter being created automatically
16+
// if it was not configured explicitly.
17+
type RefGroupSymbol string
18+
19+
// RefGroup is a group of references, for example "branches" or
20+
// "tags". Reference groups might overlap.
21+
type RefGroup struct {
22+
// Symbol is the unique string by which this `RefGroup` is
23+
// identified and configured. It consists of dot-separated
24+
// components, which implicitly makes a nested tree-like
25+
// structure.
26+
Symbol RefGroupSymbol
27+
28+
// Name is the name for this `ReferenceGroup` to be presented
29+
// in user-readable output.
30+
Name string
31+
}
32+
33+
// RefGrouper describes a type that can collate reference names into
34+
// groups and decide which ones to walk.
35+
type RefGrouper interface {
36+
// Categorize tells whether `refname` should be walked at all,
37+
// and if so, the symbols of the reference groups to which it
38+
// belongs.
39+
Categorize(refname string) (bool, []RefGroupSymbol)
40+
41+
// Groups returns the list of `ReferenceGroup`s, in the order
42+
// that they should be presented. The return value might
43+
// depend on which references have been seen so far.
44+
Groups() []RefGroup
45+
}
46+
47+
type refSeen struct {
48+
git.Reference
49+
walked bool
50+
groups []RefGroupSymbol
51+
}
52+
53+
func CollectReferences(
54+
ctx context.Context, repo *git.Repository, rg RefGrouper,
55+
) ([]refSeen, error) {
56+
refIter, err := repo.NewReferenceIter(ctx)
57+
if err != nil {
58+
return nil, err
59+
}
60+
61+
var refsSeen []refSeen
62+
for {
63+
ref, ok, err := refIter.Next()
64+
if err != nil {
65+
return nil, err
66+
}
67+
if !ok {
68+
return refsSeen, nil
69+
}
70+
71+
walk, groups := rg.Categorize(ref.Refname)
72+
73+
refsSeen = append(
74+
refsSeen,
75+
refSeen{
76+
Reference: ref,
77+
walked: walk,
78+
groups: groups,
79+
},
80+
)
81+
}
82+
}

0 commit comments

Comments
 (0)