When you are using Nix, especially with Home-Manager, there are times when you want to test something or maybe debug some issue in your configuration. Those times it would be really convenient if you could avoid a rebuild of your Home-Manager configuration, since this takes time until evaluation and activation.
For those times I have this small script in my Nix configuration called
realise-symlinks
, that is defined as:
{ pkgs, ... }:
let
realise-symlink = pkgs.writeShellApplication {
name = "realise-symlink";
runtimeInputs = with pkgs; [ coreutils ];
text = ''
for file in "$@"; do
if [[ -L "$file" ]]; then
if [[ -d "$file" ]]; then
tmpdir="''${file}.tmp"
mkdir -p "$tmpdir"
cp --verbose --recursive "$file"/* "$tmpdir"
unlink "$file"
mv "$tmpdir" "$file"
chmod --changes --recursive +w "$file"
else
cp --verbose --remove-destination "$(readlink "$file")" "$file"
chmod --changes +w "$file"
fi
else
>&2 echo "Not a symlink: $file"
exit 1
fi
done
'';
};
in
{
home.packages = [ realise-symlink ];
}
The idea of this script is that you can call it against a symlink against Nix store and it will realise, e.g.: convert to an "actual" file, e.g.:
$ ls -lah .zshrc
lrwxrwxrwx 1 thiagoko users 69 Aug 1 00:10 .zshrc -> /nix/store/glz018yyh0qfqc9lywx1yhr7c3l96lv7-home-manager-files/.zshrc
$ realise-symlink .zshrc
removed '.zshrc'
'/nix/store/glz018yyh0qfqc9lywx1yhr7c3l96lv7-home-manager-files/.zshrc' -> '.zshrc'
mode of '.zshrc' changed from 0444 (r--r--r--) to 0644 (rw-r--r--)
$ ls -lah .zshrc
-rw-r--r-- 1 thiagoko users 5.8K Aug 1 00:16 .zshrc
It also add write permissions to the resulting file, to make it easier to edit. By the way, it also works with directories:
$ ls -lah zim-completion
lrwxrwxrwx 1 thiagoko users 90 Aug 1 00:10 zim-completion -> /nix/store/glz018yyh0qfqc9lywx1yhr7c3l96lv7-home-manager-files/.zsh/plugins/zim-completion
$ realise-symlink zim-completion
'zim-completion/init.zsh' -> 'zim-completion.tmp/init.zsh'
'zim-completion/init.zsh.zwc' -> 'zim-completion.tmp/init.zsh.zwc'
'zim-completion/LICENSE' -> 'zim-completion.tmp/LICENSE'
'zim-completion/README.md' -> 'zim-completion.tmp/README.md'
mode of 'zim-completion/init.zsh' changed from 0444 (r--r--r--) to 0644 (rw-r--r--)
mode of 'zim-completion/init.zsh.zwc' changed from 0444 (r--r--r--) to 0644 (rw-r--r--)
mode of 'zim-completion/LICENSE' changed from 0444 (r--r--r--) to 0644 (rw-r--r--)
mode of 'zim-completion/README.md' changed from 0444 (r--r--r--) to 0644 (rw-r--r--)
$ ls -lah zim-completion
total 28K
drwxr-xr-x 1 thiagoko users 72 Aug 1 00:18 .
drwxr-xr-x 1 thiagoko users 130 Aug 1 00:18 ..
-rw-r--r-- 1 thiagoko users 5.3K Aug 1 00:18 init.zsh
-rw-r--r-- 1 thiagoko users 12K Aug 1 00:18 init.zsh.zwc
-rw-r--r-- 1 thiagoko users 1.3K Aug 1 00:18 LICENSE
-rw-r--r-- 1 thiagoko users 2.2K Aug 1 00:18 README.md
After you finish whatever you are testing, to return to your configuration you can just delete those files and re-run your Home-Manager activation:
$ rm -rf .zshrc
$ sudo systemctl restart home-manager-<user>.service # or `home-manager switch`
$ ls -lah .zshrc
lrwxrwxrwx 1 thiagoko users 69 Aug 1 00:20 .zshrc -> /nix/store/glz018yyh0qfqc9lywx1yhr7c3l96lv7-home-manager-files/.zshrc
It even works with system files (i.e.: NixOS):
$ sudo realise-symlink /etc/nix/nix.conf
[sudo] password for thiagoko:
removed 'nix.conf'
'/etc/static/nix/nix.conf' -> 'nix.conf'
mode of 'nix.conf' changed from 0444 (r--r--r--) to 0644 (rw-r--r--)
But I never needed for this case since it is more rare to me to experiment with OS level configuration.