@@ -54,34 +54,61 @@ in
54if builtins.pathExists (toString src + "/.git")
54if builtins.pathExists (toString src + "/.git")
57− git_dir =
57+ # Identify the .git directory and filter just the files that we need.
58+ gitDir = cleanSourceWith ({
60+ type == "directory" ||
61+ lib.any (i: (lib.hasSuffix i path)) [
62+ "/config" "/index" "/HEAD" ] ||
63+ (lib.strings.hasInfix "modules/" path &&
64+ lib.any (i: (lib.hasSuffix i path)) [
65+ "/config" "/index" "/HEAD" "/objects" "/refs" ]);
58 if builtins.pathExists (toString src + "/.git/index")
67 if builtins.pathExists (toString src + "/.git/index")
59− then (toString src + "/.git")
68+ then { inherit src; subDir = ".git"; }
60− else # likely a git worktree, so follow the indirection
70+ # likely a git worktree, so follow the indirection
62− git_content = lines (readFile (toString src + "/.git"));
73+ git_content = lines (readFile (toString src + "/.git"));
63− first_line = head git_content;
74+ first_line = head git_content;
64− prefix = "gitdir: ";
75+ prefix = "gitdir: ";
65− ok = length git_content == 1 && has_prefix prefix first_line;
76+ ok = length git_content == 1 && has_prefix prefix first_line;
68− then /. + remove_prefix prefix first_line
79+ then /. + remove_prefix prefix first_line
69− else abort "gitSource.nix: Cannot parse ${toString src + "/.git"}";
80+ else abort "gitSource.nix: Cannot parse ${toString src + "/.git"}";
71− gitFiles = cleanSourceWith {
83+ # Worktrees have a commondir pointing to the common `.git` dir. We need the
72− inherit src;
84+ # config file from there to get the list of active submodules right.
73− filter = path: type:
85+ commonConfig = if builtins.pathExists (toString gitDir.origSrc + "/commondir")
74− type == "directory" ||
86+ then
75− lib.any (i: (lib.hasSuffix i path)) [
87+ # The commondir file contains just the relative path of the
76− ".gitmodules" ".git/config" ".git/index" ".git/HEAD" ".git/objects" ".git/refs" ] ||
88+ # common `.git` dir.
77− (lib.strings.hasInfix ".git/modules/" path &&
89+ let
78− lib.any (i: (lib.hasSuffix i path)) [
90+ git_content = lines (readFile (toString gitDir.origSrc + "/commondir"));
79− "config" "index" "HEAD" "objects" "refs" ]);
91+ first_line = head git_content;
80− };
92+ in toString gitDir.origSrc + "/" + first_line + "/config"
93+ else toString gitDir + "/config";
95+ # We need the .gitmodules file for submoules to work.
96+ gitModules = builtins.path { name = "gitmodules"; path = toString src + "/.gitmodules"; };
98+ # Make a temporary dir that looks enough like the real thing for
99+ # `git ls-files --recurse-submodules` to give us an accurate list
100+ # of all the files in the index.
82 whitelist_file =
101 whitelist_file =
83 runCommand "git-ls-files" {envVariable = true;} ''
102 runCommand "git-ls-files" {envVariable = true;} ''
84− cd ${gitFiles}
103+ tmp=$(mktemp -d)
105+ cp -r ${gitDir} .git
107+ mkdir -p .git/objects .git/refs
108+ mkdir -p .git-common/objects .git-common/refs
109+ cp ${commonConfig} .git-common/config
110+ echo ../.git-common > .git/commondir
111+ cp ${gitModules} ./.gitmodules
85 ${git}/bin/git ls-files --recurse-submodules > $out
112 ${git}/bin/git ls-files --recurse-submodules > $out