Clean up CLI flag plumbing and small duplications · Entire
Clean up CLI flag plumbing and small duplications
c493362·
Soph·2w ago·9 files·+49 added/-62 removed
- convert-sha256 re-registered the four source-auth flags by hand; reuse addSourceAuth, which also carries the secret-leak protection for token flags.
- sync/plan/replicate and bootstrap had identical --map parse loops; extract parseMappings in flags.go.
- Collapse the protocolMode/operationMode intermediate types: the flag types now derive directly from the public gitsync types, removing triple conversions like protocolModeFlag(protocolMode(gitsync.ProtocolMode(mode))).
- The version line format existed in root.go and version.go; move it to versioninfo.String().
- bench: uniqueStrings hand-rolled slices.Compact.
- sha256convert: the resolveCacheEntry type had been inserted between resolveMessageRef and its doc comment, silently reattaching the comment to the wrong declaration.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Sessions
6a45cb3266a7View transcript
Changes
9
cmd
git-sync-bench
Mmain.go+1/-9
git-sync
Mbootstrap.go+4/-10
Mconvert_sha256.go+1/-7
Mflags.go+20/-10
internal
sha256convert
Msha256convert.go+7/-7
versioninfo
Mversioninfo.go+8
Mroot.go+1/-2
Msyncplan.go+6/-15
Mversion.go+1/-2
382 unmodified lines
383
384
385
386
387
388
389
390
391
392
393
394
386
387
388
389
382 unmodified lines
return nil
}
slices.Sort(input)
out := input[:0]
var prev string
for i, item := range input {
if i == 0 || item != prev {
out = append(out, item)
prev = item
}
}
return out
return slices.Compact(input)
}
func normalizeRepoURL(raw string) (string, error) {
Mcmd/git-sync-bench/main.go+1/-9
4 unmodified lines
5
6
7
8
8
9
10
25 unmodified lines
36
37
38
40
41
42
43
44
45
46
47
48
39
40
41
42
43
44
45
46
4 unmodified lines
"fmt"
gitsync "entire.io/entire/git-sync"
"entire.io/entire/git-sync/internal/validation"
"entire.io/entire/git-sync/unstable"
"github.com/spf13/cobra"
)
25 unmodified lines
if branches != "" {
req.Scope.Branches = splitCSV(branches)
}
for _, raw := range mappings {
mapping, err := validation.ParseMapping(raw)
if err != nil {
return fmt.Errorf("parse mapping %q: %w", raw, err)
}
req.Scope.Mappings = append(req.Scope.Mappings, gitsync.RefMapping{
Source: mapping.Source,
Target: mapping.Target,
})
}
parsed, err := parseMappings(mappings)
if err != nil {
return err
}
req.Scope.Mappings = parsed
if req.Source.URL == "" || req.Target.URL == "" {
return errors.New("bootstrap requires source and target repository URLs")
}
Mcmd/git-sync/bootstrap.go+4/-10
73 unmodified lines
74
75
76
77
78
79
80
81
82
83
77
78
79
80
73 unmodified lines
cmd.Flags().BoolVar(&req.SourceFollowInfoRefsRedirect, "source-follow-info-refs-redirect",
envBool("GITSYNC_SOURCE_FOLLOW_INFO_REFS_REDIRECT"),
"send follow-up source RPCs to the final /info/refs redirect host")
addSecretFlag(cmd, &req.SourceAuth.Token, "source-token", "GITSYNC_SOURCE_TOKEN", "source token/password")
cmd.Flags().StringVar(&req.SourceAuth.Username, "source-username",
envOr("GITSYNC_SOURCE_USERNAME", "git"), "source basic auth username")
addSecretFlag(cmd, &req.SourceAuth.BearerToken, "source-bearer-token", "GITSYNC_SOURCE_BEARER_TOKEN", "source bearer token")
cmd.Flags().BoolVar(&req.SourceAuth.SkipTLSVerify, "source-insecure-skip-tls-verify",
envBool("GITSYNC_SOURCE_INSECURE_SKIP_TLS_VERIFY"),
"skip TLS certificate verification for the source")
addSourceAuth(cmd, &req.SourceAuth)
cmd.Flags().StringVar(&req.TargetDir, "target-dir", "", "directory to initialize as a SHA256 bare repository")
allRefsFlag(cmd, allRefsUsageScopeOnly, &req.AllRefs)
Mcmd/git-sync/convert_sha256.go+1/-7
125 unmodified lines
126
127
128
129
129
130
131
132
46 unmodified lines
179
180
181
182
183
182
183
184
185
186
187
188
189
190
191
192
193
194
185
186
195
196
197
198
199
3 unmodified lines
203
204
205
196
206
207
208
209
3 unmodified lines
213
214
215
206
216
217
218
219
3 unmodified lines
223
224
225
216
226
227
218
228
229
220
230
231
125 unmodified lines
}
func newProtocolFlag() protocolModeFlag {
return protocolModeFlag(protocolMode(envOr("GITSYNC_PROTOCOL", validation.ProtocolAuto)))
return protocolModeFlag(envOr("GITSYNC_PROTOCOL", validation.ProtocolAuto))
}
func envOr(key, fallback string) string {
46 unmodified lines
return out
}
type protocolMode gitsync.ProtocolMode
type operationMode gitsync.OperationMode
// parseMappings converts raw --map values (src:dst form) into ref mappings.
func parseMappings(raw []string) ([]gitsync.RefMapping, error) {
out := make([]gitsync.RefMapping, 0, len(raw))
for _, value := range raw {
mapping, err := validation.ParseMapping(value)
if err != nil {
return nil, fmt.Errorf("parse mapping %q: %w", value, err)
}
out = append(out, gitsync.RefMapping{Source: mapping.Source, Target: mapping.Target})
}
return out, nil
}
type protocolModeFlag protocolMode
type operationModeFlag operationMode
type protocolModeFlag gitsync.ProtocolMode
type operationModeFlag gitsync.OperationMode
func (p *protocolModeFlag) String() string { return string(*p) }
func (p *protocolModeFlag) Type() string { return "string" }
3 unmodified lines
if err != nil {
return fmt.Errorf("normalize protocol: %w", err)
}
*p = protocolModeFlag(protocolMode(gitsync.ProtocolMode(mode)))
*p = protocolModeFlag(mode)
return nil
}
3 unmodified lines
func (m *operationModeFlag) Set(value string) error {
switch gitsync.OperationMode(value) {
case gitsync.ModeSync, gitsync.ModeReplicate:
*m = operationModeFlag(operationMode(value))
*m = operationModeFlag(value)
return nil
default:
return fmt.Errorf("unsupported mode %q", value)
3 unmodified lines
// defaultOperationMode returns the starting value for the --mode flag.
// Subcommands that pin a mode (sync, replicate) pass it in; plan passes ""
// and gets sync as the default, letting --mode override it.
func defaultOperationMode(defaultMode gitsync.OperationMode) operationMode {
func defaultOperationMode(defaultMode gitsync.OperationMode) operationModeFlag {
if defaultMode != "" {
return operationMode(defaultMode)
return operationModeFlag(defaultMode)
}
return operationMode(gitsync.ModeSync)
return operationModeFlag(gitsync.ModeSync)
}
Mcmd/git-sync/flags.go+20/-10
1524 unmodified lines
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1524 unmodified lines
return b.String(), count, nil
}
// resolveCacheEntry holds a memoized (Hash, matchResult) pair from
// resolveMessageRef. Stored in t.resolveCache keyed by lowercased prefix.
type resolveCacheEntry struct {
hash plumbing.Hash
result matchResult
}
// resolveMessageRef classifies a hex prefix against the reachable set.
// Returns matchUnique with the resolved SHA1 when exactly one commit
// or tag in scope matches; matchAmbiguous when more than one does;
// matchNone otherwise (no match, or the match is a blob/tree — those
// are filtered so incidental hex collisions on content hashes aren't
// rewritten).
// resolveCacheEntry holds a memoized (Hash, matchResult) pair from
// resolveMessageRef. Stored in t.resolveCache keyed by lowercased prefix.
type resolveCacheEntry struct {
hash plumbing.Hash
result matchResult
}
func (t *translator) resolveMessageRef(prefix string) (plumbing.Hash, matchResult) {
// Canonicalize to lowercase: hashPattern is case-insensitive so
// the caller can match `ABCD1234` in a message, but reachable
Mcmd/git-sync/internal/sha256convert/sha256convert.go+7/-7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package versioninfo
import "fmt"
var (
Version = "dev"
Commit = "none"
Date = "unknown"
)
// String renders the one-line build description shared by `git-sync version`
// and `git-sync --version`.
func String() string {
return fmt.Sprintf("git-sync %s (commit %s, built %s)", Version, Commit, Date)
}
Mcmd/git-sync/internal/versioninfo/versioninfo.go+8
26 unmodified lines
27
28
29
30
31
30
31
32
33
26 unmodified lines
return cmd.Help()
},
}
cmd.SetVersionTemplate(fmt.Sprintf("git-sync %s (commit %s, built %s)\n",
versioninfo.Version, versioninfo.Commit, versioninfo.Date))
cmd.SetVersionTemplate(versioninfo.String() + "\n")
cmd.AddCommand(newSyncCmd())
cmd.AddCommand(newReplicateCmd())
Mcmd/git-sync/root.go+1/-2
4 unmodified lines
5
6
7
8
8
9
10
17 unmodified lines
28
29
30
32
31
32
33
34
19 unmodified lines
54
55
56
58
59
60
61
62
63
64
65
66
57
58
59
60
61
62
63
64
3 unmodified lines
68
69
70
77
78
79
80
71
72
73
74
4 unmodified lines
"fmt"
gitsync "entire.io/entire/git-sync"
"entire.io/entire/git-sync/internal/validation"
"entire.io/entire/git-sync/unstable"
"github.com/spf13/cobra"
)
17 unmodified lines
sourceAuth gitsync.EndpointAuth
targetAuth gitsync.EndpointAuth
branches string
modeValue = operationModeFlag(defaultOperationMode(defaultMode))
modeValue = defaultOperationMode(defaultMode)
protocolVal = newProtocolFlag()
legacyForce bool
req = unstable.SyncRequest{DryRun: dryRun}
19 unmodified lines
if req.Source.URL == "" || req.Target.URL == "" {
return fmt.Errorf("%s requires source and target repository URLs", name)
}
3 unmodified lines
Auth: gitsync.StaticAuthProvider{Source: sourceAuth, Target: targetAuth},
})
var (
result unstable.Result
err error
)
var result unstable.Result
ctx := cmd.Context()
switch {
case dryRun:
Mcmd/git-sync/syncplan.go+6/-15
11 unmodified lines
12
13
14
15
16
15
16
17
18
11 unmodified lines
Use: "version",
Short: "Show build information",
Run: func(cmd *cobra.Command, _ []string) {
fmt.Fprintf(cmd.OutOrStdout(), "git-sync %s (commit %s, built %s)\n",
versioninfo.Version, versioninfo.Commit, versioninfo.Date)
fmt.Fprintln(cmd.OutOrStdout(), versioninfo.String())
},
}
}
Mcmd/git-sync/version.go+1/-2