Merge master into staging-next

This commit is contained in:
Frederik Rietdijk
2020-01-13 16:08:59 +01:00
79 changed files with 753 additions and 384 deletions

View File

@@ -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

View File

@@ -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";

View File

@@ -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

View File

@@ -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;

View File

@@ -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;