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

All passing. Summary of changes:
internal/validation/validation.go— addedValidateEndpoints(sourceURL, targetURL)that rejects identical (whitespace-trimmed) URLs and ignores empties so the existing "missing URL" errors stay specific.internal/syncer/syncer.go—newSessionnow callsValidateEndpointswhen a target is required, before any network I/O.internal/validation/validation_test.go—TestValidateEndpointscovers same/different/whitespace/empty/trailing-slash cases.internal/syncer/syncer_test.go—TestPublicAPIRejectsIdenticalSourceAndTargetprovesRun,Bootstrap, andProbe-with-target all reject same URLs;TestProbeWithoutTargetIgnoresEndpointEqualityCheckguards against false positives when probe has no target.
Pre-existing TestRun_IntegrationReplicate* failures (gpg-signing in test setup) reproduce on main and are unrelated.
For --prune add negative tests proving --branch main --prune and --map main:stable --prune preserve unrelated target branches
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.
All tests pass, lint is clean.
What I added:
internal/planner/planner_test.go:TestBuildPlansPrunePreservesUnrelatedBranchesUnderFilterandTestBuildReplicationPlansPrunePreservesUnrelatedBranchesUnderFilter. Both are table-driven over the two scenarios (--branch mainand--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 realRunpipeline against smart-HTTP servers. First sync seeds the target, then areleaseorphan is added, then the filtered--prunerun 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.
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.
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.
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?
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.
Add an integration test that confirm the handling and recovery from push failures when acting in incremental manner.
Test passes; lint clean (the diagnostics are pre-existing).
Added TestRun_IntegrationIncrementalPushFailureRecoversOnRetry next to the existing incremental success test (TestRun_IntegrationResyncFetchesLessFromSource). It:
- Seeds the target via an initial sync.
- Advances source by one commit so the next plan is a fast-forward update — the shape that takes the incremental relay path.
- Installs a one-shot
receivePackHookthat returns "ng" status for every command on the first push attempt. - Asserts the first sync errors out and the target ref hasn't moved (receive-pack only commits refs the server reports as ok).
- 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.