Currently, rsync does not check basis dirs for existing destination files. As the man page description of --link-dest puts it, existing destination files are "definitive". I would like an option, tenatively named --recheck-basis-dirs, to make them non-definitive. Specifically, with this option:
- An existing destination file that matches a --compare-dest file would be deleted regardless of --delete. (Deletion without --delete might seem surprising, but the goal is to leave the destination in the correct state with respect to the basis dir for the paths that are being processed on the current run. Think of it like --force.)
- An existing destination file that matches a --link-dest file would be replaced with a hard link to the --link-dest file.
(The analogue for --copy-dest would be to replace a destination file matched in a --copy-dest dir with a copy of the --copy-dest file, but I don't see any point in doing that.)
I'm thinking that both cases should be itemized as if the destination file never existed, but I'm not sure of this.
Inspired by this thread:
I think this is a good idea, although I don't really like the option name. I think it should have "dest" in the name to relate it to the dest options. The term "basis file" is used in the man page but not in any option names, and the term "basis dir" doesn't appear in the man page at all. Perhaps "--override-dest-files".
Note: The term "basis dir" is widely used in the source and on the list; its omission from the man page should be considered a fault of the man page.
The word "override" makes sense with --compare-dest but is inappropriately scary when one is using --link-dest to reduce transfer time and/or disk usage without affecting the contents ultimately found in the destination. I think this is a sign that my approach in these three enhancement requests, of generalizing the existing basis dir semantics along several different axes until saner semantics are available, will be messier than I realized. Instead, perhaps we should make a list of motivating use cases, figure out what the new design should be, and finally figure out how to retain backward compatibility.
Created attachment 4759 [details]
replace DEST files with basis files when basis files match the src exactly
Here is a proposed patch for rsync 3.0.6 that implements this functionality.
There are no extra options, as proposed in some of the previous posts. If a "basis file" passes the unchanged_file() *and* the unchanged_attrs() tests, the DEST file will be removed and replaced with a hard link to the basis file.
Note: unchanged_file() is the internal rsync test for checking file sizes, times, and/or checksums when comparing files. unchanged_attrs() checks ownership, permissions, and ACL's.
Now the tricky part: in the case that a basis file passes the unchanged_file() test, but not the unchanged_attrs() test, it's tempting to replace DEST with a hardlink *if* the DEST fails the unchanged_file() test. However, the danger is that attributes & ACL's from the basis file would eventually be thrown away in later rsync operations, since these basis file attributes are now coupled with the DEST.
I have implemented this as the default behavior for 3.1.0. I think that this doesn't need to be an option since most uses of the --ALT-dest options are copies into a new directory hierarchy. Those that are not will be better served by the new behaviors.
*** Bug 8712 has been marked as a duplicate of this bug. ***