aboutsummaryrefslogtreecommitdiff
path: root/lib/sources.nix
diff options
context:
space:
mode:
authorelseym <elseym@me.com>2020-01-10 21:24:31 +0100
committerelseym <elseym@me.com>2020-01-10 22:29:48 +0100
commitc9214c394b248e1f26e45dbe1be2bd82363af3a6 (patch)
treef28e88086f844a4d781fc9eb23bf7c078814b963 /lib/sources.nix
parentb74c26a17f1856735577c29d92939721d542f0f5 (diff)
lib.commitIdFromGitRepo: support git-worktree
lib.commitIdFromGitRepo now resolves the refs from the parent repository in case the supplied path is a file containing the path to said repository. this adds support for git-worktree and things alike. see gitrepository-layout(5). this also: - adds a new boolean function lib.pathIsRegularFile to check whether a path is a regular file - patches lib.revisionWithDefault and the revision and versionSuffix attributes in config.system.nixos in order to support git-worktrees
Diffstat (limited to '')
-rw-r--r--lib/sources.nix34
1 files changed, 28 insertions, 6 deletions
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";