(ctx context.Context, args []string)
| 85 | } |
| 86 | |
| 87 | func run(ctx context.Context, args []string) error { |
| 88 | fs := flag.NewFlagSet("git-sync-bench", flag.ContinueOnError) |
| 89 | fs.SetOutput(os.Stderr) |
| 90 | |
| 91 | var scenarioName string |
| 92 | var workDir string |
| 93 | var repeat int |
| 94 | var keepTargets bool |
| 95 | var jsonOutput bool |
| 96 | var mappings multiStringFlag |
| 97 | cfg := benchmarkConfig{} |
| 98 | |
| 99 | fs.StringVar(&scenarioName, "scenario", string(scenarioBootstrap), "benchmark scenario: bootstrap or sync") |
| 100 | fs.StringVar(&cfg.SourceURL, "source-url", "", "source repository URL or local path") |
| 101 | fs.StringVar(&workDir, "work-dir", "", "directory for temporary target repositories") |
| 102 | fs.IntVar(&repeat, "repeat", 1, "number of runs to execute") |
| 103 | fs.BoolVar(&keepTargets, "keep-targets", false, "retain generated target repositories after the run") |
| 104 | fs.BoolVar(&jsonOutput, "json", false, "print JSON output") |
| 105 | |
| 106 | branches := fs.String("branch", "", "comma-separated branch list; default is all source branches") |
| 107 | fs.Var(&mappings, "map", "ref mapping in src:dst form; short names map branches, full refs map exact refs") |
| 108 | fs.BoolVar(&cfg.Policy.IncludeTags, "tags", false, "mirror tags") |
| 109 | fs.BoolVar(&cfg.Policy.ForceWithLease, "force-with-lease", false, "allow non-fast-forward branch updates with per-run lease") |
| 110 | fs.BoolVar(&cfg.Policy.ForceBlind, "force-blind", false, "allow non-fast-forward branch updates; overwrite regardless of current target tip") |
| 111 | var legacyForce bool |
| 112 | fs.BoolVar(&legacyForce, "force", false, "removed: pick --force-with-lease or --force-blind") |
| 113 | fs.BoolVar(&cfg.Policy.Prune, "prune", false, "delete managed target refs that no longer exist on source") |
| 114 | fs.BoolVar(&cfg.Options.CollectStats, "stats", false, "collect transfer statistics") |
| 115 | fs.BoolVar(&cfg.Options.MeasureMemory, "measure-memory", true, "sample elapsed time and Go heap usage") |
| 116 | fs.Int64Var(&cfg.Options.MaxPackBytes, "max-pack-bytes", 0, "abort bootstrap if the streamed source pack exceeds this many bytes") |
| 117 | fs.Int64Var(&cfg.Options.TargetMaxPackBytes, "target-max-pack-bytes", 0, "target receive-pack body size limit; batches are planned and auto-subdivided to fit") |
| 118 | benchProtocol := benchProtocolModeFlag(benchProtocolMode(validation.ProtocolAuto)) |
| 119 | fs.Var(&benchProtocol, "protocol", "protocol mode: auto, v1, or v2") |
| 120 | fs.BoolVar(&cfg.Options.Verbose, "v", false, "verbose logging") |
| 121 | |
| 122 | if err := fs.Parse(args); err != nil { |
| 123 | return fmt.Errorf("parse flags: %w", err) |
| 124 | } |
| 125 | if legacyForce { |
| 126 | return usageError("--force has been removed; use --force-with-lease or --force-blind") |
| 127 | } |
| 128 | if cfg.Policy.ForceWithLease && cfg.Policy.ForceBlind { |
| 129 | return usageError("--force-with-lease and --force-blind are mutually exclusive") |
| 130 | } |
| 131 | cfg.Policy.Protocol = gitsync.ProtocolMode(benchProtocol) |
| 132 | if len(fs.Args()) > 0 { |
| 133 | return usageError("unexpected positional arguments") |
| 134 | } |
| 135 | if repeat < 1 { |
| 136 | return usageError("--repeat must be at least 1") |
| 137 | } |
| 138 | |
| 139 | if *branches != "" { |
| 140 | cfg.Scope.Branches = splitCSV(*branches) |
| 141 | } |
| 142 | for _, raw := range mappings { |
| 143 | mapping, err := validation.ParseMapping(raw) |
| 144 | if err != nil { |
no test coverage detected