Open DrRuhe opened 1 year ago
In my experience with a flakes-only configuration, I misused mkOutOfStoreSymlink
initially -- after much frustration and digging through prior conversations about its usage, I realised that a relative path (like ./config
in your example) would not result in an out-of-store symlink at all, because a relative path in a flake is always relative to the flake's store path. It took some time to figure out that it only has the desired effect when its argument is an absolute path on the filesystem. AFAIK, there's no "flake-native" way to detect the flake's out-of-store path on a filesystem, so I've resorted to a concoction of custom module options, environment variables, and hard-coded paths to get the desired behavior.
So, with that said, I suspect that adding an option to the file linker options as described would also necessitate the addition of at least one other option to define an assumed base path for the flake-based home-manager configuration.
But overall I agree that it would be nice to establish some clearer conventions for dealing with this kind of setup!
I marked my previous comment as "outdated" since I'm not sure if my musings were accurate or not… I had been under the impression that mkOutOfStoreSymlink
requires an absolute path argument in a flake-based configuration. While #257 seems to indicate otherwise (hence my hesitance in spouting misinformation), it also predates the widespread adoption of flakes -- other more recent issues (#2660, #2085) indicate absolute paths are indeed required for flakes.
@montchr , I had a similar experience on my side.
Using the following:
{
home.file = {
".config/hypr/hyprland.conf".source = config.lib.file.mkOutOfStoreSymlink ./hyprland/hyprland.conf;
};
}
Results in the creation of the following symlink chain:
~/.config/hypr/hyprland.conf
-> /nix/store/k76965c6lx8xdqc2swha74s8k0hw7xgc-home-manager-files/.config/hypr/hyprland.conf
-> /nix/store/9wm464xzpmwnaav4q0li0nmdm98slfab-hm_hyprland.conf
-> /nix/store/mnaq3pzm0qrkvs8kpgpjw456iprj36sy-source/core/hyprland/hyprland.conf
In the previous case, the symlink failed since it was pointing to a missing file.
Passing a string instead, the path will be relative to the Nix store:
/nix/store/5rnm8ch7ybg5ddk1jj20c2avrbrji0af-hm_hyprland.conf -> ./hyprland/hyprland.conf
Thus, an absolute path must be used.
Thank you for your contribution! I marked this issue as stale due to inactivity. Please be considerate of people watching this issue and receiving notifications before commenting 'I have this issue too'. We welcome additional information that will help resolve this issue. Please read the relevant sections below before commenting.
* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.
* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.
Don't be afraid to manually close an issue, even if it holds valuable information. Closed issues stay in the system for people to search, read, cross-reference, or even reopen – nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.
A potential benefit of a dedicated option for OOS-symlinks could be validating the type of the option definition. Perhaps a warning could be logged if the value points to a store path, which is most likely not desirable.
Thank you for your contribution! I marked this issue as stale due to inactivity. Please be considerate of people watching this issue and receiving notifications before commenting 'I have this issue too'. We welcome additional information that will help resolve this issue. Please read the relevant sections below before commenting.
* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.
* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.
Don't be afraid to manually close an issue, even if it holds valuable information. Closed issues stay in the system for people to search, read, cross-reference, or even reopen – nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.
i just needed this so this is relevant still
For me, this issue is still relevant too!
I'm also using a flake for my configuration. The following helper function solved my issues with the absolute path:
createSymlink = localPath:
config.lib.file.mkOutOfStoreSymlink "${config.xdg.configHome}/home-manager/${localPath}";
In my case I would like to use:
home.file."bin" = {
source = "${config.xdg.configHome}/home-manager/bin";
recursive = true;
outOfStoreSymlink = true;
};
It would be nice to have this feature in future versions. Thanks!
I figured out a way to do this with listFilesRecursive
. Here's my minimal working example:
# home.nix
{ config, pkgs, lib, ... }:
let
utils = import ./utils.nix { inherit config pkgs lib; };
dotfiles = "${config.home.homeDirectory}/dotfiles";
in {
# patch the attrSet with linkHomeFiles (see utils.nix below)
home.file = utils.linkHomeFiles {
# set outOfStoreSymlink = true and recursive = true to recursively link all files within source
"bin" = { source = "${dotfiles}/bin"; outOfStoreSymlink = true; recursive = true; };
".config" = { source = "${dotfiles}/config"; outOfStoreSymlink = true; recursive = true; };
".ssh" = { source = "${dotfiles}/config/ssh"; outOfStoreSymlink = true; recursive = true; };
# set outOfStoreSymlink = true to replicate normal mkOutOfStoreSymlink behavior
".editorconfig" = { source = "${dotfiles}/config/editorconfig/config"; outOfStoreSymlink = true; };
".zshenv" = { source = "${dotfiles}/config/zsh/.zshenv"; outOfStoreSymlink = true; };
# set outOfStoreSymlink = false for default behavior. E.g.,
".profile".text = '' . "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh" '';
};
}
# utils.nix
{ config, pkgs, lib, ... }:
{
# Add out-of-store-symlinks to given attrSet
linkHomeFiles =
let
ln = config.lib.file.mkOutOfStoreSymlink;
lndir = path: link: builtins.listToAttrs (
map (file: {
name = "${link}/${lib.path.removePrefix (/. + path) (/. + file)}";
value = { source = ln "${file}"; };
}) (lib.filesystem.listFilesRecursive path)
);
rmopts = attrs: builtins.removeAttrs attrs ["source" "recursive" "outOfStoreSymlink"];
in
fileAttrs: lib.attrsets.concatMapAttrs (name: value:
if value.outOfStoreSymlink or false
then
if value.recursive or false
then
# Recursive version of mkOutOfStoreSymlink
lib.attrsets.mapAttrs (_: attrs: attrs // rmopts value) (lndir value.source name)
else
# Same as mkOutOfStoreSymlink
{ "${name}" = { source = ln value.source; } // rmopts value; }
else
# Use default handler for in-store links
{ "${name}" = value; }
) fileAttrs;
}
Note: since we are linking to /home
, we need to pass --impure
to home-manager when (re)building. E.g.,
home-manager switch --flake . --impure
Thank you for your contribution! I marked this issue as stale due to inactivity. Please be considerate of people watching this issue and receiving notifications before commenting 'I have this issue too'. We welcome additional information that will help resolve this issue. Please read the relevant sections below before commenting.
* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.
* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.
Don't be afraid to manually close an issue, even if it holds valuable information. Closed issues stay in the system for people to search, read, cross-reference, or even reopen – nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.
Not stale.
I'd like to have an configuration option for
home.file
entries, that allows to declare these files as outOfStoreSymlinks. So something like this:This would allow me to have a config folder for the related things in my dotfiles under VCS, but still allow the files to be changed by the programs. Changes could then be managed by the VCS.
As a concrete example: The config files of KDE and related programs are plenty. And I'd like to manage these via nix and track them in the dotfiles. When these link to the files in the dotfiles directory, I could still use the GUI for managing the Settings, which would not be possible with links to immutable files in the nix store.
In particular, I'd like it to work with the recursive option mentioned above since AFAICT currently it is only possible to do this with single files.
I think this also helps with discoverability.