Sitelet https://github.com/linuxmint/timeshift/pull/566
Skip to content

Emit exclusion patterns before inclusion patterns - #566

Open
fitnesscontactgallery wants to merge 1 commit into
linuxmint:masterfrom
fitnesscontactgallery:fix/exclude-ordering
Open

fitnesscontactgallery wants to merge 1 commit into
linuxmint:masterfrom
fitnesscontactgallery:fix/exclude-ordering

Conversation

@fitnesscontactgallery

Copy link
Copy Markdown

Problem

create_exclude_list_for_backup() writes the user's patterns in the order they appear in config. rsync applies the first pattern that matches, so when a user's list mixes inclusion (+) and exclusion patterns, an inclusion covering a parent directory is written first and every exclusion beneath it becomes unreachable.

The effect is silent: the GUI still displays the excludes as active, but they are not applied to the snapshot.

This is most severe when a network or FUSE filesystem is mounted inside a user's home directory. rsync walks the entire remote filesystem over the network, then exits non-zero on the entries it cannot read. Timeshift discards the snapshot, so no snapshot is created at all.

Reproduction

Config with a parent inclusion plus two exclusions:

"exclude": [
  "+ /home/frank/**",
  "/home/frank/models/***",
  "/home/frank/Desktop/C on Player (NoMachine)/***"
]

Generated exclude.list in 25.12.4 — the + lands on line 1:

+ /home/frank/**
/home/frank/models/***
/home/frank/Desktop/C on Player (NoMachine)/***
...
$ rsync -a --dry-run -v --exclude-from=exclude.list / /dest | grep -c "C on Player"
99772

models/ and the NoMachine mount (an sshfs mount of a Windows C: drive) are both traversed in full, and the snapshot fails with rsync error: errors with program diagnostics (code 13).

Fix

Emit exclusion patterns first and inclusion patterns second. User entries still precede the built-in defaults, so users continue to override them; only the relative order of the user's own entries changes.

Generated exclude.list after the change:

/home/frank/models/***
...
/home/frank/Desktop/C on Player (NoMachine)/***
+ /home/frank/**

Verification

Built and tested on Ubuntu 26.04 (kernel 7.0) against timeshift 25.12.4 / upstream 26.09.0, with the NoMachine sshfs mount actively present.

Before, using the generated exclude.list verbatim:

$ rsync -a --dry-run -v --exclude-from=exclude.list / /dest | grep -c "C on Player"
99772

After:

$ timeshift --create --snapshot-device /dev/sda1
RSYNC Snapshot saved successfully (621s)
  • mount skipped: Desktop/ in the snapshot contains only the local file, 0 references to C on Player in the rsync log
  • models/ excluded as intended
  • 0 rsync errors, previously exit code 13
  • 10m21s for a ~66G first snapshot

Scope

Changes only the emission order in create_exclude_list_for_backup(). No changes to pattern parsing, matching, defaults, or the restore path. A user whose list contains only inclusions, or only exclusions, gets a byte-identical exclude.list.

Note for maintainers

create_exclude_list_for_restore() already skips + patterns outright (line 931) and does not have this ordering issue, so it is left unchanged.

create_exclude_list_for_backup() writes the user's patterns in config
order. When a user's list mixes inclusion ("+") and exclusion patterns,
an inclusion such as "+ /home/frank/**" is written first, and because
rsync applies the first pattern that matches, every exclusion after it
becomes unreachable.

In practice this means a user's own excludes silently do nothing as soon
as they also include a parent directory, while the GUI still shows them
as active. On a machine with an sshfs mount inside $HOME this is severe:
rsync walks the whole remote filesystem over the network, then exits
non-zero on unreadable entries, and Timeshift discards the snapshot.

Emit exclusions first and inclusions second. User entries still precede
the built-in defaults, so users continue to override them.

Verified on Ubuntu 26.04 against timeshift 25.12.4: with the exclusion
placed last, rsync traversed 99772 paths under a NoMachine C: drive mount
and the snapshot failed with rsync exit code 13. With the fix applied,
the mount is skipped, the snapshot completes in ~10 minutes with zero
rsync errors, and the generated exclude.list lists excludes before
"+ /home/frank/**".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant