about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorFrederik Rietdijk <fridh@fridh.nl>2020-01-13 16:08:59 +0100
committerFrederik Rietdijk <fridh@fridh.nl>2020-01-13 16:08:59 +0100
commited1b0d0bac6438fbfcb2dca77493edcbe3384114 (patch)
treed9ddecb505723c8c45ca2837e08e121f41b49fd2 /lib
parent960f062825d22e328828766f4910b702f81ddade (diff)
parentde66fc6a2a2483f4bbbb759c55176643df6e38ba (diff)
downloadnixlib-ed1b0d0bac6438fbfcb2dca77493edcbe3384114.tar
nixlib-ed1b0d0bac6438fbfcb2dca77493edcbe3384114.tar.gz
nixlib-ed1b0d0bac6438fbfcb2dca77493edcbe3384114.tar.bz2
nixlib-ed1b0d0bac6438fbfcb2dca77493edcbe3384114.tar.lz
nixlib-ed1b0d0bac6438fbfcb2dca77493edcbe3384114.tar.xz
nixlib-ed1b0d0bac6438fbfcb2dca77493edcbe3384114.tar.zst
nixlib-ed1b0d0bac6438fbfcb2dca77493edcbe3384114.zip
Merge master into staging-next
Diffstat (limited to 'lib')
-rw-r--r--lib/default.nix2
-rw-r--r--lib/sources.nix34
-rwxr-xr-xlib/tests/modules.sh3
-rw-r--r--lib/trivial.nix2
-rw-r--r--lib/types.nix80
5 files changed, 103 insertions, 18 deletions
diff --git a/lib/default.nix b/lib/default.nix
index 9f7a088d792d..77dda17f3b4f 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -100,7 +100,7 @@ let
     inherit (sources) pathType pathIsDirectory cleanSourceFilter
       cleanSource sourceByRegex sourceFilesBySuffices
       commitIdFromGitRepo cleanSourceWith pathHasContext
-      canCleanSource;
+      canCleanSource pathIsRegularFile;
     inherit (modules) evalModules unifyModuleSyntax
       applyIfFunction mergeModules
       mergeModules' mergeOptionDecls evalOptionValue mergeDefinitions
diff --git a/lib/sources.nix b/lib/sources.nix
index 51bcf5559e32..0fd172c42b77 100644
--- a/lib/sources.nix
+++ b/lib/sources.nix
@@ -9,6 +9,9 @@ rec {
   # Returns true if the path exists and is a directory, false otherwise
   pathIsDirectory = p: if builtins.pathExists p then (pathType p) == "directory" else false;
 
+  # Returns true if the path exists and is a regular file, false otherwise
+  pathIsRegularFile = p: if builtins.pathExists p then (pathType p) == "regular" else false;
+
   # Bring in a path as a source, filtering out all Subversion and CVS
   # directories, as well as backup files (*~).
   cleanSourceFilter = name: type: let baseName = baseNameOf (toString name); in ! (
@@ -110,24 +113,43 @@ rec {
       with builtins;
         let fileName       = toString path + "/" + file;
             packedRefsName = toString path + "/packed-refs";
-        in if lib.pathExists fileName
+        in if pathIsRegularFile path
+           # Resolve git worktrees. See gitrepository-layout(5)
+           then
+             let m   = match "^gitdir: (.*)$" (lib.fileContents path);
+             in if m == null
+                then throw ("File contains no gitdir reference: " + path)
+                else
+                  let gitDir     = lib.head m;
+                      commonDir' = if pathIsRegularFile "${gitDir}/commondir"
+                                   then lib.fileContents "${gitDir}/commondir"
+                                   else gitDir;
+                      commonDir  = if lib.hasPrefix "/" commonDir'
+                                   then commonDir'
+                                   else toString (/. + "${gitDir}/${commonDir'}");
+                      refFile    = lib.removePrefix "${commonDir}/" "${gitDir}/${file}";
+                  in readCommitFromFile refFile commonDir
+
+           else if pathIsRegularFile fileName
+           # Sometimes git stores the commitId directly in the file but
+           # sometimes it stores something like: «ref: refs/heads/branch-name»
            then
              let fileContent = lib.fileContents fileName;
-                 # Sometimes git stores the commitId directly in the file but
-                 # sometimes it stores something like: «ref: refs/heads/branch-name»
                  matchRef    = match "^ref: (.*)$" fileContent;
-             in if   matchRef == null
+             in if  matchRef == null
                 then fileContent
                 else readCommitFromFile (lib.head matchRef) path
+
+           else if pathIsRegularFile packedRefsName
            # Sometimes, the file isn't there at all and has been packed away in the
            # packed-refs file, so we have to grep through it:
-           else if lib.pathExists packedRefsName
            then
              let fileContent = readFile packedRefsName;
                  matchRef    = match (".*\n([^\n ]*) " + file + "\n.*") fileContent;
-             in if   matchRef == null
+             in if  matchRef == null
                 then throw ("Could not find " + file + " in " + packedRefsName)
                 else lib.head matchRef
+
            else throw ("Not a .git directory: " + path);
     in readCommitFromFile "HEAD";
 
diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh
index c8340ff7f157..8cd632a439cd 100755
--- a/lib/tests/modules.sh
+++ b/lib/tests/modules.sh
@@ -174,8 +174,7 @@ checkConfigOutput "true" config.submodule.inner ./declare-submoduleWith-modules.
 checkConfigOutput "true" config.submodule.outer ./declare-submoduleWith-modules.nix
 
 ## Paths should be allowed as values and work as expected
-# Temporarily disabled until https://github.com/NixOS/nixpkgs/pull/76861
-#checkConfigOutput "true" config.submodule.enable ./declare-submoduleWith-path.nix
+checkConfigOutput "true" config.submodule.enable ./declare-submoduleWith-path.nix
 
 # Check that disabledModules works recursively and correctly
 checkConfigOutput "true" config.enable ./disable-recursive/main.nix
diff --git a/lib/trivial.nix b/lib/trivial.nix
index 3a25e31fb052..940ec1a3d59e 100644
--- a/lib/trivial.nix
+++ b/lib/trivial.nix
@@ -191,7 +191,7 @@ rec {
     let
       revisionFile = "${toString ./..}/.git-revision";
       gitRepo      = "${toString ./..}/.git";
-    in if lib.pathIsDirectory gitRepo
+    in if builtins.pathExists gitRepo
        then lib.commitIdFromGitRepo gitRepo
        else if lib.pathExists revisionFile then lib.fileContents revisionFile
        else default;
diff --git a/lib/types.nix b/lib/types.nix
index e86f6d364761..ab325fd20091 100644
--- a/lib/types.nix
+++ b/lib/types.nix
@@ -340,18 +340,80 @@ rec {
             let
               padWidth = stringLength (toString (length def.value));
               unnamed = i: unnamedPrefix + fixedWidthNumber padWidth i;
+              anyString = placeholder "name";
+              nameAttrs = [
+                { path = [ "environment" "etc" ];
+                  name = "target";
+                }
+                { path = [ "containers" anyString "bindMounts" ];
+                  name = "mountPoint";
+                }
+                { path = [ "programs" "ssh" "knownHosts" ];
+                  # hostNames is actually a list so we would need to handle it only when singleton
+                  name = "hostNames";
+                }
+                { path = [ "fileSystems" ];
+                  name = "mountPoint";
+                }
+                { path = [ "boot" "specialFileSystems" ];
+                  name = "mountPoint";
+                }
+                { path = [ "services" "znapzend" "zetup" ];
+                  name = "dataset";
+                }
+                { path = [ "services" "znapzend" "zetup" anyString "destinations" ];
+                  name = "label";
+                }
+                { path = [ "services" "geoclue2" "appConfig" ];
+                  name = "desktopID";
+                }
+                { path = [ "home-manager" "users" anyString "programs" "ssh" "matchBlocks" ];
+                  name = "host"; # https://github.com/rycee/home-manager/blob/e8dbc3561373b68d12decb3c0d7c1ba245f138f7/modules/programs/ssh.nix#L265
+                }
+                { path = [ "home-manager" "users" anyString "home" "file" ];
+                  name = "target"; # https://github.com/rycee/home-manager/blob/0e9b7aab3c6c27bf020402e0e2ef20b65c040552/modules/files.nix#L33
+                }
+                { path = [ "home-manager" "users" anyString "xdg" "configFile" ];
+                  name = "target"; # https://github.com/rycee/home-manager/blob/54de0e1d79a1370e57a8f23bef89f99f9b92ab67/modules/misc/xdg.nix#L41
+                }
+                { path = [ "home-manager" "users" anyString "xdg" "dataFile" ];
+                  name = "target"; # https://github.com/rycee/home-manager/blob/54de0e1d79a1370e57a8f23bef89f99f9b92ab67/modules/misc/xdg.nix#L58
+                }
+              ];
+              matched = let
+                equals = a: b: b == anyString || a == b;
+                fallback = { name = "name"; };
+              in findFirst ({ path, ... }: all (v: v == true) (zipListsWith equals loc path)) fallback nameAttrs;
+              nameAttr = matched.name;
+              nameValueOld = value:
+                if isList value then
+                  if length value > 0 then
+                    "[ " + concatMapStringsSep " " escapeNixString value + " ]"
+                  else
+                    "[ ]"
+                else
+                  escapeNixString value;
+              nameValueNew = value: unnamed:
+                if isList value then
+                  if length value > 0 then
+                    head value
+                  else
+                    unnamed
+                else
+                  value;
               res =
                 { inherit (def) file;
                   value = listToAttrs (
                     imap1 (elemIdx: elem:
-                      { name  = elem.name or (unnamed elemIdx);
+                      { name  = nameValueNew (elem.${nameAttr} or (unnamed elemIdx)) (unnamed elemIdx);
                         value = elem;
                       }) def.value);
                 };
               option = concatStringsSep "." loc;
               sample = take 3 def.value;
-              list = concatMapStrings (x: ''{ name = "${x.name or "unnamed"}"; ...} '') sample;
-              set = concatMapStrings (x: ''${x.name or "unnamed"} = {...}; '') sample;
+              more = lib.optionalString (length def.value > 3) "... ";
+              list = concatMapStrings (x: ''{ ${nameAttr} = ${nameValueOld (x.${nameAttr} or "unnamed")}; ...} '') sample;
+              set = concatMapStrings (x: ''${nameValueNew (x.${nameAttr} or "unnamed") "unnamed"} = {...}; '') sample;
               msg = ''
                 In file ${def.file}
                 a list is being assigned to the option config.${option}.
@@ -359,10 +421,10 @@ rec {
                 See https://git.io/fj2zm for more information.
                 Do
                   ${option} =
-                    { ${set}...}
+                    { ${set}${more}}
                 instead of
                   ${option} =
-                    [ ${list}...]
+                    [ ${list}${more}]
               '';
             in
               lib.warn msg res
@@ -430,14 +492,16 @@ rec {
           else unify (if shorthandOnlyDefinesConfig then { config = value; } else value);
 
         allModules = defs: modules ++ imap1 (n: { value, file }:
-          # Annotate the value with the location of its definition for better error messages
-          coerce (lib.modules.unifyModuleSyntax file "${toString file}-${toString n}") value
+          if isAttrs value || isFunction value then
+            # Annotate the value with the location of its definition for better error messages
+            coerce (lib.modules.unifyModuleSyntax file "${toString file}-${toString n}") value
+          else value
         ) defs;
 
       in
       mkOptionType rec {
         name = "submodule";
-        check = x: isAttrs x || isFunction x;
+        check = x: isAttrs x || isFunction x || path.check x;
         merge = loc: defs:
           (evalModules {
             modules = allModules defs;