From be9177fcf4081d86cd4b865515a8cb406b3c00db Mon Sep 17 00:00:00 2001 From: Luflosi Date: Mon, 6 May 2024 14:12:39 +0200 Subject: [PATCH] files: don't handle symlinks in a special way when home.file..recursive is set to true MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm using `pass` as my password manager. In order to use it in Firefox, I use the passff extension. The passff extension needs the `passff-host` native messaging host to access the passwords. Here is what the file structure of the `passff-host` package looks like: ``` result ├── etc │   ├── chromium │   │   └── native-messaging-hosts │   │   └── passff.json -> ../../../share/passff-host/passff.json │   ├── opt │   │   └── chrome │   │   └── native-messaging-hosts │   │   └── passff.json -> ../../../../share/passff-host/passff.json │   └── vivaldi │   └── native-messaging-hosts │   └── passff.json -> ../../../share/passff-host/passff.json ├── lib │   ├── librewolf │   │   └── native-messaging-hosts │   │   └── passff.json -> ../../../share/passff-host/passff.json │   └── mozilla │   └── native-messaging-hosts │   └── passff.json -> ../../../share/passff-host/passff.json └── share └── passff-host ├── passff.json └── passff.py ``` As you can see, `lib/mozilla/native-messaging-hosts/passff.json` is a relative symlink. This is perfectly reasonable. When adding `programs.firefox.nativeMessagingHosts = [ pkgs.passff-host ]` to the home-manager configuration, the firefox module first joins all the `nativeMessagingHosts` using `symlinkJoin` and stores the result in a variable called `nativeMessagingHostsJoined`. This creates `ff_native-messaging-hosts` in the Nix store: ``` /nix/store/bv62k5yl7jwzkhyci838ir3vgz59gqsa-ff_native-messaging-hosts ├── bin │   └── firefox -> /nix/store/0zqxaz44w75gjq32xj53i32jl2j91pzy-firefox-125.0.1/bin/firefox ├── etc │   ├── chromium │   │   └── native-messaging-hosts │   │   └── passff.json -> ../../../share/passff-host/passff.json │   ├── opt │   │   └── chrome │   │   └── native-messaging-hosts │   │   └── passff.json -> ../../../../share/passff-host/passff.json │   └── vivaldi │   └── native-messaging-hosts │   └── passff.json -> ../../../share/passff-host/passff.json ├── lib │   ├── [...] │   ├── librewolf │   │   └── native-messaging-hosts │   │   └── passff.json -> ../../../share/passff-host/passff.json │   └── mozilla │   ├── native-messaging-hosts │   │   └── passff.json -> ../../../share/passff-host/passff.json │   └── pkcs11-modules └── share ├── [...] └── passff-host ├── passff.json -> /nix/store/pag1akgbmls1xa63h6rzmb0h6xxwwzmy-passff-host-1.2.4/share/passff-host/passff.json └── passff.py -> /nix/store/pag1akgbmls1xa63h6rzmb0h6xxwwzmy-passff-host-1.2.4/share/passff-host/passff.py ``` Still perfectly fine. Then the `firefox` module sets ```nix home.file.".mozilla/native-messaging-hosts" = { source = "${nativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts"; recursive = true; } ``` The `file` module then calls `lndir -silent "/nix/store/bv62k5yl7jwzkhyci838ir3vgz59gqsa-ff_native-messaging-hosts/lib/mozilla/native-messaging-hosts" ".mozilla/native-messaging-hosts"` To see the problem, here is the resulting directory tree: ``` .mozilla ├── [...] └── native-messaging-hosts └── passff.json -> ../../../share/passff-host/passff.json ``` Obviously this symlink doesn't go anywhere. `lndir` created a broken symlink. To fix this, add the `-ignorelinks` argument to `lndir`, which causes it to instead just create a symlink to the symlink in `ff_native-messaging-hosts`: ``` .mozilla ├── [...] └── native-messaging-hosts └── passff.json -> /nix/store/bv62k5yl7jwzkhyci838ir3vgz59gqsa-ff_native-messaging-hosts/lib/mozilla/native-messaging-hosts/passff.json ``` --- modules/files.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/files.nix b/modules/files.nix index 59e9c2578..4252f9780 100644 --- a/modules/files.nix +++ b/modules/files.nix @@ -322,7 +322,7 @@ in if [[ -d $source ]]; then if [[ $recursive ]]; then mkdir -p "$target" - lndir -silent "$source" "$target" + lndir -silent -ignorelinks "$source" "$target" else ln -s "$source" "$target" fi