Skip to content

fix: sync --delete respects --exclude and --include (#815) - #883

Open
terryrankine wants to merge 1 commit into
peak:masterfrom
terryrankine:fix/sync-delete-filters
Open

terryrankine wants to merge 1 commit into
peak:masterfrom
terryrankine:fix/sync-delete-filters

Conversation

@terryrankine

@terryrankine terryrankine commented Sep 17, 2026 •

Copy link
Copy Markdown

Context

Fixes #815. sync --delete deleted destination objects that --exclude should have protected, and with --include it deleted nothing at all.

Root cause

sync forwarded --exclude / --include to the generated rm --raw … command. Raw URLs have an empty prefix, so rm matched the patterns against the full object key rather than the path relative to the destination prefix. Suffix patterns like *.txt happened to work; folder/* never matched; and because --include then matched nothing, the rm was a no-op.

Fix

  • Sync.Run compiles the patterns once (same error handling as cp).
  • planRun filters the delete candidates with isURLMatched(patterns, d.Path, dsturl.Prefix) — relative to the destination prefix, like every other command.
  • generateCommand now omits a default flag whose value is nil; the rm command is built with exclude: nil, include: nil so it is not re-filtered.
  • README: one sentence documenting that the filters apply to --delete.

Tests

  • command/context_test.go: nil default flags are omitted even when set in the context.
  • e2e/sync_test.go: sync --delete --exclude "sub/*" keeps sub/keep.txt and deletes old.log; --include "*.md" --include "sub/*" deletes only matching objects. Both fail on master and pass with this change.

Linux, Go 1.24, go test -count=1 -race ./...: all packages ok. gofmt, go vet, staticcheck, unparam, semgrep: clean.

CI note: the test matrix fails before running anything — bitnami/minio:2023.7.18 no longer exists on Docker Hub (fixed by #840). All build and qa jobs pass. The full suite was run locally on Linux as above.

🤖 Generated with Claude Code

Objects that exist only in the destination were deleted even when they
matched an --exclude pattern or did not match an --include pattern.
The generated rm command did receive the patterns, but rm runs in raw
mode and matched them against the full object key, so a pattern like
"folder/*" never matched under a destination prefix.

sync now filters the delete candidates itself, relative to the
destination prefix, and omits --exclude/--include from the generated
rm command. generateCommand treats a nil default flag value as "omit
this flag".

Fixes peak#815

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@terryrankine
terryrankine force-pushed the fix/sync-delete-filters branch from ab3b04a to c281acb Compare September 17, 2026 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sync with --delete does not respect --exclude

1 participant