aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-13 03:41:54 +0000
committertv <tv@krebsco.de>2026-11-13 03:41:54 +0000
commit0842652921304ba76fbd321756b6b545abc81b01 (patch)
tree0b9679cd9a231728175e3efdbc0834eb2ce2b6dd /README.md
parent4ee857a9f1c9153b944a2f48a89f35d9657b2ca5 (diff)
populate: never write through files or change hard links elsewhere
Populate writes some files in place, and makes files writable, which reaches beyond the target directory where such a file is a symlink or a hard link to one elsewhere: - The key of a derived copy gets written to a new file, which then replaces it, instead of written through a symlink at its place. - Lock files get copied to a new file before Nix rewrites them, instead of to flake.lock.populate, which a source may contain as a symlink. - Before rsync syncs a source, each file with other hard links gets replaced by a copy of its own. rsync fixes the mode and time of a file it takes for unchanged in place, which changes every hard link to it: one elsewhere, e.g. in /etc/nixos, or a backup's. - Removing state makes only directories writable, which is what removing what's in them needs, instead of everything, including files that are hard links to ones elsewhere. - The sentinel file only gets created if it's missing, instead of touched on every run. - A link only counts as pointing into the store if its resolved path is in the store, so a link like /nix/store/../.. gets replaced. Safety scenarios cover a symlink in place of a key, symlinks in a source named like the lock file's copies, a hard link to a read-only file outside in the target directory, and in stale state.
Diffstat (limited to 'README.md')
-rw-r--r--README.md6
1 files changed, 6 insertions, 0 deletions
diff --git a/README.md b/README.md
index 969afcd..c917d3f 100644
--- a/README.md
+++ b/README.md
@@ -316,6 +316,12 @@ everything else. It doesn't change or remove anything outside:
fails, telling what's wrong, unless the source's `reclone` is set. Git
runs no hooks.
+* A file in the target directory that has other hard links, e.g. one in
+ `/etc/nixos`, gets replaced by a copy of its own before rsync syncs it, so
+ the other ones keep their mode and time. Populate writes its own files,
+ and replaces lock files it rewrites, by renaming new files into place, and
+ only makes directories writable that it removes.
+
* Populate keeps its state in the sentinel, `.populate`, which becomes a
directory once there is state to keep. Populating fails if the sentinel,
or a directory populate needs therein, is a symlink.