diff --git a/modules/files.nix b/modules/files.nix
index 66d71510..c61560c5 100644
--- a/modules/files.nix
+++ b/modules/files.nix
@@ -9,27 +9,9 @@ let
homeDirectory = config.home.homeDirectory;
- # Figures out a valid Nix store name for the given path.
- storeFileName = path:
- let
- # All characters that are considered safe. Note "-" is not
- # included to avoid "-" followed by digit being interpreted as a
- # version.
- safeChars =
- [ "+" "." "_" "?" "=" ]
- ++ lowerChars
- ++ upperChars
- ++ stringToCharacters "0123456789";
-
- empties = l: genList (x: "") (length l);
-
- unsafeInName = stringToCharacters (
- replaceStrings safeChars (empties safeChars) path
- );
-
- safeName = replaceStrings unsafeInName (empties unsafeInName) path;
- in
- "home_file_" + safeName;
+ fileType = (import lib/file-type.nix {
+ inherit homeDirectory lib pkgs;
+ }).fileType;
# A symbolic link whose target path matches this pattern will be
# considered part of a Home Manager generation.
@@ -42,67 +24,7 @@ in
home.file = mkOption {
description = "Attribute set of files to link into the user home.";
default = {};
- type = types.loaOf (types.submodule (
- { name, config, ... }: {
- options = {
- target = mkOption {
- type = types.str;
- apply = removePrefix (homeDirectory + "/");
- description = ''
- Path to target file relative to HOME.
- '';
- };
-
- text = mkOption {
- default = null;
- type = types.nullOr types.lines;
- description = "Text of the file.";
- };
-
- source = mkOption {
- type = types.path;
- description = ''
- Path of the source file. The file name must not start
- with a period since Nix will not allow such names in
- the Nix store.
-
- This may refer to a directory.
- '';
- };
-
- mode = mkOption {
- type = types.nullOr types.str;
- default = null;
- description = ''
- The permissions to apply to the file.
-
- DEPRECATED: use home.file.<name?>.executable
- instead.
- '';
- };
-
- executable = mkOption {
- type = types.nullOr types.bool;
- default = null;
- description = ''
- Set the execute bit. If null, defaults to the mode
- of the source file or to false
- for files created through the text option.
- '';
- };
- };
-
- config = {
- target = mkDefault name;
- source = mkIf (config.text != null) (
- mkDefault (pkgs.writeTextFile {
- inherit (config) executable text;
- name = storeFileName name;
- })
- );
- };
- })
- );
+ type = fileType "HOME" homeDirectory;
};
home-files = mkOption {
diff --git a/modules/lib/file-type.nix b/modules/lib/file-type.nix
new file mode 100644
index 00000000..ebdcb774
--- /dev/null
+++ b/modules/lib/file-type.nix
@@ -0,0 +1,105 @@
+{ homeDirectory, lib, pkgs }:
+
+with lib;
+
+let
+
+ # Figures out a valid Nix store name for the given path.
+ storeFileName = path:
+ let
+ # All characters that are considered safe. Note "-" is not
+ # included to avoid "-" followed by digit being interpreted as a
+ # version.
+ safeChars =
+ [ "+" "." "_" "?" "=" ]
+ ++ lowerChars
+ ++ upperChars
+ ++ stringToCharacters "0123456789";
+
+ empties = l: genList (x: "") (length l);
+
+ unsafeInName = stringToCharacters (
+ replaceStrings safeChars (empties safeChars) path
+ );
+
+ safeName = replaceStrings unsafeInName (empties unsafeInName) path;
+ in
+ "home_file_" + safeName;
+
+in
+
+{
+ # Constructs a type suitable for a `home.file` like option. The
+ # target path may be either absolute or relative, in which case it
+ # is relative the `basePath` argument (which itself must be an
+ # absolute path).
+ #
+ # Arguments:
+ # - basePathDesc docbook compatible description of the base path
+ # - basePath the file base path
+ fileType = basePathDesc: basePath: types.loaOf (types.submodule (
+ { name, config, ... }: {
+ options = {
+ target = mkOption {
+ type = types.str;
+ apply = p:
+ let
+ absPath = if hasPrefix "/" p then p else "${basePath}/${p}";
+ in
+ removePrefix (homeDirectory + "/") absPath;
+ description = ''
+ Path to target file relative to ${basePathDesc}.
+ '';
+ };
+
+ text = mkOption {
+ default = null;
+ type = types.nullOr types.lines;
+ description = "Text of the file.";
+ };
+
+ source = mkOption {
+ type = types.path;
+ description = ''
+ Path of the source file. The file name must not start
+ with a period since Nix will not allow such names in
+ the Nix store.
+
+ This may refer to a directory.
+ '';
+ };
+
+ mode = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ The permissions to apply to the file.
+
+ DEPRECATED: use home.file.<name?>.executable
+ instead.
+ '';
+ };
+
+ executable = mkOption {
+ type = types.nullOr types.bool;
+ default = null;
+ description = ''
+ Set the execute bit. If null, defaults to the mode
+ of the source file or to false
+ for files created through the text option.
+ '';
+ };
+ };
+
+ config = {
+ target = mkDefault name;
+ source = mkIf (config.text != null) (
+ mkDefault (pkgs.writeTextFile {
+ inherit (config) executable text;
+ name = storeFileName name;
+ })
+ );
+ };
+ }
+ ));
+}