Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hm: option for default linking method #182

Merged
merged 5 commits into from
Jan 25, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 48 additions & 34 deletions home-manager.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ let

persistentStorageNames = (filter (path: cfg.${path}.enable) (attrNames cfg));

getDirPath = v: if isString v then v else v.directory;
getDirMethod = v: v.method or "bindfs";
isBindfs = v: (getDirMethod v) == "bindfs";
isSymlink = v: (getDirMethod v) == "symlink";

inherit (pkgs.callPackage ./lib.nix { })
splitPath
dirListToPath
Expand Down Expand Up @@ -44,7 +39,7 @@ in
home.persistence = mkOption {
default = { };
type = with types; attrsOf (
submodule ({ name, ... }: {
submodule ({ name, config, ... }: {
options =
{
persistentStoragePath = mkOption {
Expand All @@ -62,26 +57,45 @@ in
description = "Whether to enable this persistent storage location.";
};

defaultDirectoryMethod = mkOption {
type = types.enum [ "bindfs" "symlink" ];
default = "bindfs";
description = ''
The linking method that should be used for directories.

- bindfs is very transparent, and thus used as a safe
default. It has, however, a significant performance impact in
IO-heavy situations.

- symlinks have great performance but may be treated
specially by some programs that may e.g. generate
errors/warnings, or replace them.

This can be overridden on a per entry basis.
'';
};

directories = mkOption {
type = with types; listOf (either str (submodule {
options = {
directory = mkOption {
type = str;
default = null;
description = "The directory path to be linked.";
};
method = mkOption {
type = types.enum [ "bindfs" "symlink" ];
default = "bindfs";
description = ''
The linking method that should be used for this
directory. bindfs is the default and works for most use
cases, however some programs may behave better with
symlinks.
'';
type = types.listOf (
types.coercedTo types.str (directory: { inherit directory; }) (submodule {
options = {
directory = mkOption {
type = str;
description = "The directory path to be linked.";
};
method = mkOption {
type = types.enum [ "bindfs" "symlink" ];
default = config.defaultDirectoryMethod;
description = ''
The linking method to be used for this specific
directory entry. See
<literal>defaultDirectoryMethod</literal> for more
information on the tradeoffs.
'';
};
};
};
}));
})
);
default = [ ];
example = [
"Downloads"
Expand Down Expand Up @@ -224,8 +238,8 @@ in
mkLinksToPersistentStorage = persistentStorageName:
listToAttrs (map
(mkLinkNameValuePair persistentStorageName)
(map getDirPath (cfg.${persistentStorageName}.files ++
(filter isSymlink cfg.${persistentStorageName}.directories)))
(cfg.${persistentStorageName}.files ++ (map (v: v.directory)
(filter (v: v.method == "symlink") cfg.${persistentStorageName}.directories)))
);
in
foldl' recursiveUpdate { } (map mkLinksToPersistentStorage persistentStorageNames);
Expand Down Expand Up @@ -300,7 +314,7 @@ in
mkBindMountServicesForPath = persistentStorageName:
listToAttrs (map
(mkBindMountService persistentStorageName)
(map getDirPath (filter isBindfs cfg.${persistentStorageName}.directories))
(map (v: v.directory) (filter (v: v.method == "bindfs") cfg.${persistentStorageName}.directories))
);
in
builtins.foldl'
Expand Down Expand Up @@ -364,7 +378,7 @@ in
mkBindMountsForPath = persistentStorageName:
concatMapStrings
(mkBindMount persistentStorageName)
(map getDirPath (filter isBindfs cfg.${persistentStorageName}.directories));
(map (v: v.directory) (filter (v: v.method == "bindfs") cfg.${persistentStorageName}.directories));

mkUnmount = persistentStorageName: dir:
let
Expand All @@ -384,7 +398,7 @@ in
mkUnmountsForPath = persistentStorageName:
concatMapStrings
(mkUnmount persistentStorageName)
(map getDirPath (filter isBindfs cfg.${persistentStorageName}.directories));
(map (v: v.directory) (filter (v: v.method == "bindfs") cfg.${persistentStorageName}.directories));

mkLinkCleanup = persistentStorageName: dir:
let
Expand All @@ -409,12 +423,12 @@ in
mkLinkCleanupForPath = persistentStorageName:
concatMapStrings
(mkLinkCleanup persistentStorageName)
(map getDirPath (filter isSymlink cfg.${persistentStorageName}.directories));
(map (v: v.directory) (filter (v: v.method == "symlink") cfg.${persistentStorageName}.directories));


in
mkMerge [
(mkIf (any (path: (filter isSymlink cfg.${path}.directories) != [ ]) persistentStorageNames) {
(mkIf (any (path: (filter (v: v.method == "symlink") cfg.${path}.directories) != [ ]) persistentStorageNames) {
# Clean up existing empty directories in the way of links
cleanEmptyLinkTargets =
dag.entryBefore
Expand All @@ -423,7 +437,7 @@ in
${concatMapStrings mkLinkCleanupForPath persistentStorageNames}
'';
})
(mkIf (any (path: (filter isBindfs cfg.${path}.directories) != [ ]) persistentStorageNames) {
(mkIf (any (path: (filter (v: v.method == "bindfs") cfg.${path}.directories) != [ ]) persistentStorageNames) {
createAndMountPersistentStoragePaths =
dag.entryBefore
[ "writeBoundary" ]
Expand Down Expand Up @@ -453,7 +467,7 @@ in
unmountBindMounts
'';
})
(mkIf (any (path: (cfg.${path}.files != [ ]) || ((filter isSymlink cfg.${path}.directories) != [ ])) persistentStorageNames) {
(mkIf (any (path: (cfg.${path}.files != [ ]) || ((filter (v: v.method == "symlink") cfg.${path}.directories) != [ ])) persistentStorageNames) {
createTargetFileDirectories =
dag.entryBefore
[ "writeBoundary" ]
Expand All @@ -463,7 +477,7 @@ in
(targetFilePath: ''
mkdir -p ${escapeShellArg (concatPaths [ cfg.${persistentStorageName}.persistentStoragePath (dirOf targetFilePath) ])}
'')
(map getDirPath (cfg.${persistentStorageName}.files ++ (filter isSymlink cfg.${persistentStorageName}.directories))))
(cfg.${persistentStorageName}.files ++ (map (v: v.directory) (filter (v: v.method == "symlink") cfg.${persistentStorageName}.directories))))
persistentStorageNames);
})
];
Expand Down
Loading