-
-
Save piousdeer/b29c272eaeba398b864da6abf6cb5daa to your computer and use it in GitHub Desktop.
{ | |
home.file."test-file" = { | |
text = "Hello world"; | |
force = true; | |
mutable = true; | |
}; | |
} |
# This module extends home.file, xdg.configFile and xdg.dataFile with the `mutable` option. | |
{ config, lib, ... }: | |
let | |
fileOptionAttrPaths = | |
[ [ "home" "file" ] [ "xdg" "configFile" ] [ "xdg" "dataFile" ] ]; | |
in { | |
options = let | |
mergeAttrsList = builtins.foldl' (lib.mergeAttrs) { }; | |
fileAttrsType = lib.types.attrsOf (lib.types.submodule ({ config, ... }: { | |
options.mutable = lib.mkOption { | |
type = lib.types.bool; | |
default = false; | |
description = '' | |
Whether to copy the file without the read-only attribute instead of | |
symlinking. If you set this to `true`, you must also set `force` to | |
`true`. Mutable files are not removed when you remove them from your | |
configuration. | |
This option is useful for programs that don't have a very good | |
support for read-only configurations. | |
''; | |
}; | |
})); | |
in mergeAttrsList (map (attrPath: | |
lib.setAttrByPath attrPath (lib.mkOption { type = fileAttrsType; })) | |
fileOptionAttrPaths); | |
config = { | |
home.activation.mutableFileGeneration = let | |
allFiles = (builtins.concatLists (map | |
(attrPath: builtins.attrValues (lib.getAttrFromPath attrPath config)) | |
fileOptionAttrPaths)); | |
filterMutableFiles = builtins.filter (file: | |
(file.mutable or false) && lib.assertMsg file.force | |
"if you specify `mutable` to `true` on a file, you must also set `force` to `true`"); | |
mutableFiles = filterMutableFiles allFiles; | |
toCommand = (file: | |
let | |
source = lib.escapeShellArg file.source; | |
target = lib.escapeShellArg file.target; | |
in '' | |
$VERBOSE_ECHO "${source} -> ${target}" | |
$DRY_RUN_CMD cp --remove-destination --no-preserve=mode ${source} ${target} | |
''); | |
command = '' | |
echo "Copying mutable home files for $HOME" | |
'' + lib.concatLines (map toCommand mutableFiles); | |
in (lib.hm.dag.entryAfter [ "linkGeneration" ] command); | |
}; | |
} |
{ config, pkgs, lib, ... }: | |
let | |
# Path logic from: | |
# https://github.com/nix-community/home-manager/blob/3876cc613ac3983078964ffb5a0c01d00028139e/modules/programs/vscode.nix | |
cfg = config.programs.vscode; | |
vscodePname = cfg.package.pname; | |
configDir = { | |
"vscode" = "Code"; | |
"vscode-insiders" = "Code - Insiders"; | |
"vscodium" = "VSCodium"; | |
}.${vscodePname}; | |
userDir = if pkgs.stdenv.hostPlatform.isDarwin then | |
"Library/Application Support/${configDir}/User" | |
else | |
"${config.xdg.configHome}/${configDir}/User"; | |
configFilePath = "${userDir}/settings.json"; | |
tasksFilePath = "${userDir}/tasks.json"; | |
keybindingsFilePath = "${userDir}/keybindings.json"; | |
snippetDir = "${userDir}/snippets"; | |
pathsToMakeWritable = lib.flatten [ | |
(lib.optional (cfg.userTasks != { }) tasksFilePath) | |
(lib.optional (cfg.userSettings != { }) configFilePath) | |
(lib.optional (cfg.keybindings != [ ]) keybindingsFilePath) | |
(lib.optional (cfg.globalSnippets != { }) | |
"${snippetDir}/global.code-snippets") | |
(lib.mapAttrsToList (language: _: "${snippetDir}/${language}.json") | |
cfg.languageSnippets) | |
]; | |
in { | |
home.file = lib.genAttrs pathsToMakeWritable (_: { | |
force = true; | |
mutable = true; | |
}); | |
} |
Fixed, thank you.
no problem. thank you for making these available. it finally fixed the annoying settings issue I was having with vscode
Thanks for your super helpful module.
Are you able to use the mutable
attribute on xdg.configFile
apps? I'm getting an error like the following when I try to.
error: The option `home-manager.users.jnnk.xdg.configFile."mimeapps.list".mutable' does not exist. Definition values:
- In `/nix/store/llwv93n27s5z4g781rf68qw8z4272w24-home-manager/desktop-env/xdg-mime.nix': true
Hello, I am not sure if this is the solution I am looking for and would like some guidance.
I initially tried symlinking my file ../configs/vscode-settings.json to /.config/Code/User/settings.json but had the unable to write to file issue. Original symlink:
".config/Code/User/settings.json".source = ../configs/vscode-settings.json;
Looking for a way for it to be writable and update the file: ../configs/vscode-settings.json I have tried using this module like this:
".config/Code/User/settings.json" = {
source = ../configs/vscode-settings.json;
force = true;
mutable = true;
};
The settings.json is now writable. I can see the updates appear in .config/Code/User/settings.json but not in vscode-settings.json.
Am I missing something here?
@becknik I can reproduce this issue, specifically with xdg.configFile
only. Though I don't currently have time to investigate, so I'm hoping someone else will chip in
@j4t1nd3r It's the expected behavior because the file is copied, not symlinked. I believe mkOutOfStoreSymlink
achieves exactly what you want
Thank you, I saw this in places but without context. I am struggling to find good documentation on commands / options.
Even for home.file in the home-manager documentation. It seems looking at nix related github issues, searching discord history in nix related channels is the way to go or reaching out directly.
Since a few days, I'm getting the following errors when trying to nixos-rebuild
:
error:
… while calling the 'head' builtin
at /nix/store/z7j461v8da67nwrad4xz50dx2l5wk0wz-source/lib/attrsets.nix:1575:11:
1574| || pred here (elemAt values 1) (head values) then
1575| head values
| ^
1576| else
… while evaluating the attribute 'value'
at /nix/store/z7j461v8da67nwrad4xz50dx2l5wk0wz-source/lib/modules.nix:809:9:
808| in warnDeprecation opt //
809| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
| ^
810| inherit (res.defsFinal') highestPrio;
(stack trace truncated; use '--show-trace' to show the full trace)
error: getting status of '/nix/store/34ww4vpn116rriqbhzh4snayh7837k7v-mutability.nix': No such file or directory
I have no clue why this is happening, since I haven't changed anything related to this part of the system for a while. Does anybody have an idea?
To help solve the issue, I suggest sharing your nix configuration, ideally a public repository link if your configuration is saved in a repo.
@j4t1nd3r My intention was to reach people having this snippet in their config, since my problem might also be caused by something else.
If you want to take a look anyways: https://github.com/becknik/dotfiles.nix
Every help is greatly appreciated :)
Can someone explain the implications of this? What happens when "something" writes to the mutable file? On the next apply of your config it will be overwritten again? What is the advantage of this over synlinking ?
What happens when "something" writes to the mutable file?
The file will be modified
On the next apply of your config it will be overwritten again?
Yes. This will also happen after a reboot (at least if you're using home-manager as a NixOS module)
What is the advantage of this over synlinking ?
Normally, config files managed by home-manager are symlinks pointing to /nix/store
. This makes them read-only.
Not being read-only allows for quick iteration on the config before integrating your changes with home-manager. Additionally, some programs, like vscode, just don't work well with a read-only config: nix-community/home-manager#1800
Alternatively, you can use mkOutOfStoreSymlink
to symlink the config to a writable file. Then, however:
- you can't use Nix to generate the config contents
- you have to hardcode the writable file's location, which deducts from reproducibility
Thank you for your response, very much appreciated.
Alternatively, you can use mkOutOfStoreSymlink to symlink the config to a writable file. Then, however:
This is what I was referring to as symlink.
- you can't use Nix to generate the config contents
That is a drawback, but I can live with it by using some other method to generate it (a script or something like that)
- you have to hardcode the writable file's location, which deduces from reproducibility
That is definitely the main problem, and what I have been doing up until now. I was wondering it I was just doing it wrong and nix provides a mechanism for referencing the paths it owns (like a subfolder within my nix dotfiles folder), but if an advanced user like you tell me that is a literal problem, I trust you.
The cherry on top of this would be to have a mechanism to detect conflicts, or even better, to re-incorporate the modified file into the nix repository
on line 29 in
vscode.nix
, the check should be thatcfg.keybindings != [ ]
sincekeybindings
is an array.