summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorLinus Heckemann <git@sphalerite.org>2020-01-13 12:01:49 +0100
committerGitHub <noreply@github.com>2020-01-13 12:01:49 +0100
commit247c25d302f7fa04e354261340d875a8214ceecc (patch)
tree0a17d6ccaa1b42ebe43fef7da675ab83c24c531c /lib
parentbf91434c136d8556f17d2484c0fb142987e4f8aa (diff)
parentc9214c394b248e1f26e45dbe1be2bd82363af3a6 (diff)
downloadnixpkgs-247c25d302f7fa04e354261340d875a8214ceecc.tar
nixpkgs-247c25d302f7fa04e354261340d875a8214ceecc.tar.gz
nixpkgs-247c25d302f7fa04e354261340d875a8214ceecc.tar.bz2
nixpkgs-247c25d302f7fa04e354261340d875a8214ceecc.tar.lz
nixpkgs-247c25d302f7fa04e354261340d875a8214ceecc.tar.xz
nixpkgs-247c25d302f7fa04e354261340d875a8214ceecc.tar.zst
nixpkgs-247c25d302f7fa04e354261340d875a8214ceecc.zip
Merge pull request #77473 from mayflower/worktrees
lib.commitIdFromGitRepo: support git-worktree
Diffstat (limited to 'lib')
-rw-r--r--lib/default.nix2
-rw-r--r--lib/sources.nix34
-rw-r--r--lib/trivial.nix2
3 files changed, 30 insertions, 8 deletions
diff --git a/lib/default.nix b/lib/default.nix
index 9f7a088d792..77dda17f3b4 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 51bcf5559e3..0fd172c42b7 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/trivial.nix b/lib/trivial.nix
index 3a25e31fb05..940ec1a3d59 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;