Add tests to ensure that source and target must not be the same repository

Claude Code·Opus 4.7[1m]·pjbgf·4mo ago·17hr 54min·5 Checkpoints·48 file changes·+806/-82·226.6K tokens

Add tests to ensure that source and target must not be the same repository

4mo ago·8m

All passing. Summary of changes:

  • internal/validation/validation.go — added ValidateEndpoints(sourceURL, targetURL) that rejects identical (whitespace-trimmed) URLs and ignores empties so the existing "missing URL" errors stay specific.
  • internal/syncer/syncer.go — newSession now calls ValidateEndpoints when a target is required, before any network I/O.
  • internal/validation/validation_test.go — TestValidateEndpoints covers same/different/whitespace/empty/trailing-slash cases.
  • internal/syncer/syncer_test.go — TestPublicAPIRejectsIdenticalSourceAndTarget proves Run, Bootstrap, and Probe-with-target all reject same URLs; TestProbeWithoutTargetIgnoresEndpointEqualityCheck guards against false positives when probe has no target.

Pre-existing TestRun_IntegrationReplicate* failures (gpg-signing in test setup) reproduce on main and are unrelated.

commit changes

4mo ago·37.4s

Committed as 834619c on changes.

For --prune add negative tests proving --branch main --prune and --map main:stable --prune preserve unrelated target branches

4mo ago·20m

Now to address the gpg signing issue:

Register an empty config plugin https://github.com/go-git/go-git/blob/main/x/plugin/config/empty.go via Register(ConfigLoader(), func() ConfigSource { return config.NewEmpty() })

TO remove settings such as gpgsign from both global and system levels.

4mo ago·2h 51m

All tests pass, lint is clean.

What I added:

  • internal/planner/planner_test.go: TestBuildPlansPrunePreservesUnrelatedBranchesUnderFilter and TestBuildReplicationPlansPrunePreservesUnrelatedBranchesUnderFilter. Both are table-driven over the two scenarios (--branch main and --map main:stable) and prove the prune-scoping rule directly at the planner layer.
  • internal/syncer/integration_test.go: TestRun_IntegrationPrunePreservesUnrelatedTargetBranchUnderFilter — end-to-end via the real Run pipeline against smart-HTTP servers. First sync seeds the target, then a release orphan is added, then the filtered --prune run must leave it intact.

On the gpgSign disable: I initially added an init() in internal/syncertest/plugin.go. You moved it to a dedicated production package internal/gogitconfig and wired blank imports into both internal/syncer/syncer.go and internal/syncertest/repo.go — that's a cleaner placement, so I deleted my redundant file and the blank import I'd added in cmd/git-sync/main_test.go.

Pre-existing lint warnings in integration_test.go (lines 2548, 2615, 2865) are in code I didn't touch.

commit staged changes

4mo ago·6m

Committed as d4cca23. The internal/planner/planner_test.go changes are still unstaged — let me know if you want those committed too.

There is no full sync integration test for branch prune in normal sync mode. Existing sync integration covers stale tags: internal/syncer/integration_test.go:1533. Branch prune is covered at planner level, not end to end.

4mo ago·4m

Added TestRun_IntegrationSyncPruneDeletesOrphanedBranch at internal/syncer/integration_test.go:1725. It seeds the target via an initial sync, places an orphan release branch on the target, then runs sync with Prune: true and asserts the orphan is deleted, result.Deleted == 1, and main survives.

What if during the sync target receives a new tag, would that tag also be removed? Let's create a test to confirm that behaviour.

4mo ago·35.7s

Test passes; lint clean (the diagnostics are pre-existing in code I didn't touch).

The new test confirms: when --tags is unset, sync's --prune only operates on branches. A tag the target gained on its own — e.g., a release marker added after a prior sync — survives. The result.Deleted == 0 assertion proves nothing was queued for deletion at all, which is the right end-to-end check for "this ref was outside of prune scope."

What about when --tags was used, however the tag was created in the target after the sync process started?

4mo ago·3m

Added TestRun_IntegrationSyncPruneTagsPreservesTagCreatedDuringSync. The test seeds a stale tag on both source and target, then drops it from source so the next --tags --prune run plans a delete for stale. The target server's receivePackHook fires after target ref discovery but before the test server applies the commands — that's the race window where a brand-new deployed tag gets injected onto the target. After the sync, stale is gone and deployed survives, because the planner's snapshot never saw deployed and so no command was issued for it.

commit changes

4mo ago·2m

Committed as b5c8e3b.

Add an integration test that confirm the handling and recovery from push failures when acting in incremental manner.

4mo ago·2m

Test passes; lint clean (the diagnostics are pre-existing).

Added TestRun_IntegrationIncrementalPushFailureRecoversOnRetry next to the existing incremental success test (TestRun_IntegrationResyncFetchesLessFromSource). It:

  1. Seeds the target via an initial sync.
  2. Advances source by one commit so the next plan is a fast-forward update — the shape that takes the incremental relay path.
  3. Installs a one-shot receivePackHook that returns "ng" status for every command on the first push attempt.
  4. Asserts the first sync errors out and the target ref hasn't moved (receive-pack only commits refs the server reports as ok).
  5. Asserts the retry succeeds via incremental relay (result.Relay && result.RelayMode == "incremental"), pushes exactly one ref, fires exactly two receive-pack attempts total, and lands the target at the new source head.

commit changes

4mo ago·38.1s

Committed as 32f773e.