Clean up CLI flag plumbing and small duplications · Entire

Clean up CLI flag plumbing and small duplications

e7ceddd→main·

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

382 unmodified lines

383
384
385
386
387
388
389
390
391
392
393
394
386
387
388
389

382 unmodified lines

\t\treturn nil
\t}\n\tslices.Sort(input)\n\tout := input[:0]\n\tvar prev string\n\tfor i, item := range input {\n\t\tif i == 0 || item != prev {\n\t\tout = append(out, item)\n\t\tprev = item\n\t\t}\n\t}\n\treturn out\n\treturn slices.Compact(input)\n\nfunc normalizeRepoURL(raw string) (string, error) {\n```

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

\t\t\t\t\t\t"fmt"\n\n\tgitsync "entire.io/entire/git-sync"\n\t\t\t\t\t\t"entire.io/entire/git-sync/internal/validation"\n\t\t\t\t\t\t"entire.io/entire/git-sync/unstable"\n\t\t\t\t\t\t"github.com/spf13/cobra"\n\t\t\t\t\t\t\n\n25 unmodified lines

\t\t\t\t\t\t\t\tif branches != "" {\n\t\t\t\t\t\t\t\t\treq.Scope.Branches = splitCSV(branches)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor _, raw := range mappings {\n\t\t\t\t\t\t\tmapping, err := validation.ParseMapping(raw)\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\treturn fmt.Errorf("parse mapping %q: %w", raw, err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treq.Scope.Mappings = append(req.Scope.Mappings, gitsync.RefMapping{\n\t\t\t\t\t\t\t\tSource: mapping.Source,\n\t\t\t\t\t\t\t\tTarget: mapping.Target,\n\t\t\t\t\t\t\t})\n\t\t\t\t\tparsed, err := parseMappings(mappings)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\treq.Scope.Mappings = parsed\n\n\t\t\t\t\tif req.Source.URL == "" || req.Target.URL == "" {\n\t\t\t\t\t\t\treturn errors.New("bootstrap requires source and target repository URLs")\n\t\t\t\t\t}\n```

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

\tcmd.Flags().BoolVar(&req.SourceFollowInfoRefsRedirect, \"source-follow-info-refs-redirect\",
\tenvBool(\"GITSYNC_SOURCE_FOLLOW_INFO_REFS_REDIRECT\"),
\t\"send follow-up source RPCs to the final /info/refs redirect host\")
\taddSecretFlag(cmd, &req.SourceAuth.Token, \"source-token\", \"GITSYNC_SOURCE_TOKEN\", \"source token/password\")
\tcmd.Flags().StringVar(&req.SourceAuth.Username, \"source-username\",
\tenvOr(\"GITSYNC_SOURCE_USERNAME\", \"git\"), \"source basic auth username\")
\taddSecretFlag(cmd, &req.SourceAuth.BearerToken, \"source-bearer-token\", \"GITSYNC_SOURCE_BEARER_TOKEN\", \"source bearer token\")
\tcmd.Flags().BoolVar(&req.SourceAuth.SkipTLSVerify, \"source-insecure-skip-tls-verify\",
\tenvBool(\"GITSYNC_SOURCE_INSECURE_SKIP_TLS_VERIFY\"),
\t\"skip TLS certificate verification for the source\")
\taddSourceAuth(cmd, &req.SourceAuth)
\tcmd.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 {
\treturn protocolModeFlag(protocolMode(envOr(\"GITSYNC_PROTOCOL\", validation.ProtocolAuto)))
\treturn 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\"\n
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

\treturn cmd.Help()\n\t},
\t\ncmd.SetVersionTemplate(fmt.Sprintf(\"git-sync %s (commit %s, built %s)\n\",
\t\tversioninfo.Version, versioninfo.Commit, versioninfo.Date))\ncmd.SetVersionTemplate(versioninfo.String() + \"\n\")
\tcmd.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

\t\"fmt\"\n\n\tgitsync \"entire.io/entire/git-sync\"\n\"entire.io/entire/git-sync/internal/validation\"\n\"entire.io/entire/git-sync/unstable\"\n\"github.com/spf13/cobra\"\n\n\n\t\n\tcmd.Execute()\n\t\n\t//  }  // do your stuff here
\n17 unmodified lines

\t\tsourceAuth  gitsync.EndpointAuth
\t\ttargetAuth  gitsync.EndpointAuth
\t\t\tbranches    string
\t\t\tmodeValue   = operationModeFlag(defaultOperationMode(defaultMode))
\t\t\tmodeValue   = defaultOperationMode(defaultMode)
\t\t\tprotocolVal = newProtocolFlag()
\t\t\tlegacyForce bool
\t\t\treq         = unstable.SyncRequest{DryRun: dryRun}
\n19 unmodified lines

\t\tif branches != \"\" {\nreq.Scope.Branches = splitCSV(branches)\n\t\tfor _, raw := range mappings {\n\tmapping, err := validation.ParseMapping(raw)\nif err != nil {\nreturn fmt.Errorf(\"parse mapping %q: %w\", raw, err)\n}\n\treq.Scope.Mappings = append(req.Scope.Mappings, gitsync.RefMapping{\nSource: mapping.Source,\nTarget: mapping.Target,\n})
\tparsed, err := parseMappings(mappings)\nif err != nil {\nreturn err\n}\n\req.Scope.Mappings = parsed\n\n\t\t}}
}

Mcmd/git-sync/syncplan.go+6/-15

11 unmodified lines

12
13
14
15
16
15
16
17
18

11 unmodified lines

\tUse:   \"version\",
\tShort: \"Show build information\",
\tRun: func(cmd *cobra.Command, _ []string) {
\t\tfmt.Fprintf(cmd.OutOrStdout(), \"git-sync %s (commit %s, built %s)\n\",
\t\t\t\tversioninfo.Version, versioninfo.Commit, versioninfo.Date)\n\tfmt.Fprintln(cmd.OutOrStdout(), versioninfo.String())\n}
\t}
}

Mcmd/git-sync/version.go+1/-2