You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summary
nextcloudcmd --exclude <path> silently produced zero exclusions for
every pattern in the file, unless <path> happened to be literally
named "sync-exclude.lst" -- with no warning or error anywhere. Any
other filename (a typo'd extension, a descriptive name, a per-tool
name like myapp-exclude.lst) caused every single pattern to be
matched against the wrong base directory, so none of them ever
excluded anything under the sync root.
Root cause
ExcludedFiles::addExcludeFilePath() in src/csync/csync_exclude.cpp
anchors patterns either at the sync root (_localPath) or at the
exclude file's own containing directory, based on a filename check:
literally "sync-exclude.lst" -> sync root, anything else -> own
directory. That heuristic was introduced in 5788f35 (2020-12-09,
"Skip sync exclude file from list of exclude files if it doesn't
exist") to merge two previously-separate code paths: the GUI's
global exclude list (always named sync-exclude.lst, lives outside
any sync folder, needs sync-root anchoring) and a per-directory
.sync-exclude.lst discovered during traversal (needs anchoring at
its own directory). It was a side effect of that merge, not a
deliberate choice -- the commit's own description and linked issue
are unrelated to anchoring behavior.
src/cmd/cmd.cpp passes the CLI's --exclude value into the same
function unconditionally, so it inherited this GUI-specific
heuristic even though CLI users can name their exclude file
anything. Reported independently by multiple users:
#2916, #7682, and a comment
diagnosing the exact same filename dependency on #2916.
Fix
Added an explicit anchorToLocalPath parameter (now the
ExcludedFiles::ExcludeFileAnchor enum) to addExcludeFilePath()
in csync_exclude.cpp/.h (default FileDirectory, preserving current
behavior everywhere else).
Per @mgallien's review, --exclude's own anchoring behavior is left
unchanged (still FileDirectory / the historic filename heuristic) so
existing setups relying on it, however unintentionally, don't
silently change behavior. Instead cmd.cpp gets a new, separate
--exclude-anchored [file] option that always anchors at the sync
root (ExcludeFileAnchor::SyncRoot) regardless of the file's name --
use it instead of --exclude when patterns aren't matching because
the exclude file isn't literally named "sync-exclude.lst".
Test plan
- [x] New unit test:
testAddExcludeFilePath_syncRootAnchor_bypassesFilenameHeuristic
(covers both ExcludeFileAnchor values directly on ExcludedFiles)
- [x] Full ExcludedFilesTest suite: 25 passed, 0 failed
- [x] Manual repro against a live Nextcloud account: an exclude file
not named sync-exclude.lst had zero effect via --exclude
(unchanged, by design); passed via --exclude-anchored instead,
its patterns are correctly applied (FileIgnored) with no
behavior change for --exclude or GUI-managed exclude lists.
Signed-off-by: Thomas Mosandl <mosandl@concreativ.de>
Assisted-by: ClaudeCode:claude-sonnet-5
0 commit comments