Skip to content

Commit 554bb8b

Browse files
committed
internal/refopts: new package
Move some reference option related code to a separate internal package.
1 parent 1b49fb4 commit 554bb8b

4 files changed

Lines changed: 328 additions & 269 deletions

File tree

git-sizer.go

Lines changed: 14 additions & 269 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import (
99
"runtime/pprof"
1010
"strconv"
1111

12+
"github.com/spf13/pflag"
13+
1214
"github.com/github/git-sizer/git"
15+
"github.com/github/git-sizer/internal/refopts"
1316
"github.com/github/git-sizer/isatty"
1417
"github.com/github/git-sizer/sizes"
15-
16-
"github.com/spf13/pflag"
1718
)
1819

1920
const Usage = `usage: git-sizer [OPTS]
@@ -79,150 +80,6 @@ const Usage = `usage: git-sizer [OPTS]
7980
var ReleaseVersion string
8081
var BuildVersion string
8182

82-
type filterValue struct {
83-
// filter is the filter that will be modified if this option
84-
// is used.
85-
filter *git.ReferenceFilter
86-
87-
// combiner specifies how the filter generated by this option
88-
// is combined with the existing filter; i.e., does it cause
89-
// the matching references to be included or excluded?
90-
combiner git.Combiner
91-
92-
// pattern, if it is set, is the pattern (prefix or regexp) to
93-
// be matched. If it is not set, then the user must supply the
94-
// pattern.
95-
pattern string
96-
97-
// regexp specifies whether `pattern` should be interpreted as
98-
// a regexp (as opposed to a prefix).
99-
regexp bool
100-
}
101-
102-
func (v *filterValue) Set(s string) error {
103-
var filter git.ReferenceFilter
104-
combiner := v.combiner
105-
106-
var pattern string
107-
if v.pattern != "" {
108-
// The pattern is fixed for this option:
109-
pattern = v.pattern
110-
111-
// It's not really expected, but if the user supplied a
112-
// `false` boolean value, invert the polarity:
113-
b, err := strconv.ParseBool(s)
114-
if err != nil {
115-
return err
116-
}
117-
if !b {
118-
combiner = combiner.Inverted()
119-
}
120-
} else {
121-
// The user must supply the pattern.
122-
pattern = s
123-
}
124-
125-
if v.regexp {
126-
var err error
127-
filter, err = git.RegexpFilter(pattern)
128-
if err != nil {
129-
return fmt.Errorf("invalid regexp: %q", s)
130-
}
131-
} else {
132-
filter = git.PrefixFilter(pattern)
133-
}
134-
135-
*v.filter = combiner.Combine(*v.filter, filter)
136-
137-
return nil
138-
}
139-
140-
func (v *filterValue) Get() interface{} {
141-
return nil
142-
}
143-
144-
func (v *filterValue) String() string {
145-
return ""
146-
}
147-
148-
func (v *filterValue) Type() string {
149-
if v.pattern != "" {
150-
return "bool"
151-
} else if v.regexp {
152-
return "regexp"
153-
} else {
154-
return "prefix"
155-
}
156-
}
157-
158-
type filterGroupValue struct {
159-
filter *git.ReferenceFilter
160-
repo *git.Repository
161-
}
162-
163-
func (v *filterGroupValue) Set(name string) error {
164-
// At this point, it is not yet certain that the command was run
165-
// inside a Git repository. If not, ignore this option (the
166-
// command will error out anyway).
167-
if v.repo == nil {
168-
fmt.Fprintf(
169-
os.Stderr,
170-
"warning: not in Git repository; ignoring '--refgroup' option.\n",
171-
)
172-
return nil
173-
}
174-
175-
config, err := v.repo.Config(fmt.Sprintf("refgroup.%s", name))
176-
if err != nil {
177-
return err
178-
}
179-
for _, entry := range config.Entries {
180-
switch entry.Key {
181-
case "include":
182-
*v.filter = git.Include.Combine(
183-
*v.filter, git.PrefixFilter(entry.Value),
184-
)
185-
case "includeregexp":
186-
filter, err := git.RegexpFilter(entry.Value)
187-
if err != nil {
188-
return fmt.Errorf(
189-
"invalid regular expression for 'refgroup.%s.%s': %w",
190-
name, entry.Key, err,
191-
)
192-
}
193-
*v.filter = git.Include.Combine(*v.filter, filter)
194-
case "exclude":
195-
*v.filter = git.Exclude.Combine(
196-
*v.filter, git.PrefixFilter(entry.Value),
197-
)
198-
case "excluderegexp":
199-
filter, err := git.RegexpFilter(entry.Value)
200-
if err != nil {
201-
return fmt.Errorf(
202-
"invalid regular expression for 'refgroup.%s.%s': %w",
203-
name, entry.Key, err,
204-
)
205-
}
206-
*v.filter = git.Exclude.Combine(*v.filter, filter)
207-
default:
208-
// Ignore unrecognized keys.
209-
}
210-
}
211-
return nil
212-
}
213-
214-
func (v *filterGroupValue) Get() interface{} {
215-
return nil
216-
}
217-
218-
func (v *filterGroupValue) String() string {
219-
return ""
220-
}
221-
222-
func (v *filterGroupValue) Type() string {
223-
return "name"
224-
}
225-
22683
func main() {
22784
err := mainImplementation(os.Args[1:])
22885
if err != nil {
@@ -239,8 +96,6 @@ func mainImplementation(args []string) error {
23996
var threshold sizes.Threshold = 1
24097
var progress bool
24198
var version bool
242-
var filter git.ReferenceFilter
243-
var showRefs bool
24499

245100
// Try to open the repository, but it's not an error yet if this
246101
// fails, because the user might only be asking for `--help`.
@@ -254,88 +109,6 @@ func mainImplementation(args []string) error {
254109
fmt.Print(Usage)
255110
}
256111

257-
flags.Var(
258-
&filterValue{&filter, git.Include, "", false}, "include",
259-
"include specified references",
260-
)
261-
flags.Var(
262-
&filterValue{&filter, git.Include, "", true}, "include-regexp",
263-
"include references matching the specified regular expression",
264-
)
265-
flags.Var(
266-
&filterValue{&filter, git.Exclude, "", false}, "exclude",
267-
"exclude specified references",
268-
)
269-
flags.Var(
270-
&filterValue{&filter, git.Exclude, "", true}, "exclude-regexp",
271-
"exclude references matching the specified regular expression",
272-
)
273-
274-
flag := flags.VarPF(
275-
&filterValue{&filter, git.Include, "refs/heads", false}, "branches", "",
276-
"process all branches",
277-
)
278-
flag.NoOptDefVal = "true"
279-
280-
flag = flags.VarPF(
281-
&filterValue{&filter, git.Exclude, "refs/heads", false}, "no-branches", "",
282-
"exclude all branches",
283-
)
284-
flag.NoOptDefVal = "true"
285-
286-
flag = flags.VarPF(
287-
&filterValue{&filter, git.Include, "refs/tags", false}, "tags", "",
288-
"process all tags",
289-
)
290-
flag.NoOptDefVal = "true"
291-
292-
flag = flags.VarPF(
293-
&filterValue{&filter, git.Exclude, "refs/tags", false}, "no-tags", "",
294-
"exclude all tags",
295-
)
296-
flag.NoOptDefVal = "true"
297-
298-
flag = flags.VarPF(
299-
&filterValue{&filter, git.Include, "refs/remotes", false}, "remotes", "",
300-
"process all remote-tracking references",
301-
)
302-
flag.NoOptDefVal = "true"
303-
304-
flag = flags.VarPF(
305-
&filterValue{&filter, git.Exclude, "refs/remotes", false}, "no-remotes", "",
306-
"exclude all remote-tracking references",
307-
)
308-
flag.NoOptDefVal = "true"
309-
310-
flag = flags.VarPF(
311-
&filterValue{&filter, git.Include, "refs/notes", false}, "notes", "",
312-
"process all git-notes references",
313-
)
314-
flag.NoOptDefVal = "true"
315-
316-
flag = flags.VarPF(
317-
&filterValue{&filter, git.Exclude, "refs/notes", false}, "no-notes", "",
318-
"exclude all git-notes references",
319-
)
320-
flag.NoOptDefVal = "true"
321-
322-
flag = flags.VarPF(
323-
&filterValue{&filter, git.Include, "refs/stash", true}, "stash", "",
324-
"process refs/stash",
325-
)
326-
flag.NoOptDefVal = "true"
327-
328-
flag = flags.VarPF(
329-
&filterValue{&filter, git.Exclude, "refs/stash", true}, "no-stash", "",
330-
"exclude refs/stash",
331-
)
332-
flag.NoOptDefVal = "true"
333-
334-
flag = flags.VarPF(
335-
&filterGroupValue{&filter, repo}, "refgroup", "",
336-
"process references in refgroup defined by gitconfig",
337-
)
338-
339112
flags.VarP(
340113
sizes.NewThresholdFlagValue(&threshold, 0),
341114
"verbose", "v", "report all statistics, whether concerning or not",
@@ -376,14 +149,20 @@ func mainImplementation(args []string) error {
376149
atty = false
377150
}
378151
flags.BoolVar(&progress, "progress", atty, "report progress to stderr")
379-
flags.BoolVar(&showRefs, "show-refs", false, "list the references being processed")
380152
flags.BoolVar(&version, "version", false, "report the git-sizer version number")
381153
flags.Var(&NegatedBoolValue{&progress}, "no-progress", "suppress progress output")
382154
flags.Lookup("no-progress").NoOptDefVal = "true"
383155

384156
flags.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file")
385157
flags.MarkHidden("cpuprofile")
386158

159+
var rgb refopts.RefGroupBuilder
160+
var configger refopts.Configger
161+
if repo != nil {
162+
configger = repo
163+
}
164+
rgb.AddRefopts(flags, configger)
165+
387166
flags.SortFlags = false
388167

389168
err = flags.Parse(args)
@@ -469,20 +248,12 @@ func mainImplementation(args []string) error {
469248
progress = v
470249
}
471250

472-
if filter == nil {
473-
filter = git.AllReferencesFilter
474-
}
475-
476-
if showRefs {
477-
fmt.Fprintf(os.Stderr, "References (included references marked with '+'):\n")
478-
filter = showRefFilter{filter}
479-
}
480-
481-
rg := refGrouper{
482-
filter: filter,
251+
rg, err := rgb.Finish()
252+
if err != nil {
253+
return err
483254
}
484255

485-
historySize, err := sizes.ScanRepositoryUsingGraph(repo, &rg, nameStyle, progress)
256+
historySize, err := sizes.ScanRepositoryUsingGraph(repo, rg, nameStyle, progress)
486257
if err != nil {
487258
return fmt.Errorf("error scanning repository: %s", err)
488259
}
@@ -511,29 +282,3 @@ func mainImplementation(args []string) error {
511282

512283
return nil
513284
}
514-
515-
type refGrouper struct {
516-
filter git.ReferenceFilter
517-
}
518-
519-
func (rg *refGrouper) Categorize(refname string) (bool, []sizes.RefGroupSymbol) {
520-
return rg.filter.Filter(refname), nil
521-
}
522-
523-
func (rg *refGrouper) Groups() []sizes.RefGroup {
524-
return nil
525-
}
526-
527-
type showRefFilter struct {
528-
f git.ReferenceFilter
529-
}
530-
531-
func (f showRefFilter) Filter(refname string) bool {
532-
b := f.f.Filter(refname)
533-
if b {
534-
fmt.Fprintf(os.Stderr, "+ %s\n", refname)
535-
} else {
536-
fmt.Fprintf(os.Stderr, " %s\n", refname)
537-
}
538-
return b
539-
}

0 commit comments

Comments
 (0)