fetchgit: Add rootDir argument

With this argument fetchgit will make a subdirectory of the Git
repository a root of the resulting store path. This is helpful for
dealing with monorepos where many projects are in separate directories
and don't need a new source hash every time the monorepo is updated.

Commit hash is removed from the name of the derivation to prevent it
from changing the store path when nothing in the subdirectory changes.
This commit is contained in:
Yuriy Taraday 2025-07-18 16:45:45 +02:00
parent 3985afc65c
commit 34612851db
5 changed files with 33 additions and 6 deletions

View File

@ -827,6 +827,10 @@ Additionally, the following optional arguments can be given:
See [git sparse-checkout](https://git-scm.com/docs/git-sparse-checkout) for more information.
*`rootDir`* (String)
: When not empty, copy only contents of the subdirectory of the repository to the result. Automatically sets `sparseCheckout` and `nonConeMode` to avoid checking out any extra pieces. Incompatible with `leaveDotGit`.
Some additional parameters for niche use-cases can be found listed in the function parameters in the declaration of `fetchgit`: `pkgs/build-support/fetchgit/default.nix`.
Future parameters additions might also happen without immediately being documented here.

View File

@ -75,6 +75,7 @@
* `$debug/lib/debug/.build-id/48/3bd7f7229bdb06462222e1e353e4f37e15c293.sourceoverlay` is a symlink to a directory with the same structure as the expanded `$sourceRoot` but containing only a copy of files which were patched during the build
* `$debug/lib/debug/.build-id/48/3bd7f7229bdb06462222e1e353e4f37e15c293.debug` is the file containing debug symbols (like before).
- `fetchgit`: Add `rootDir` argument to limit the resulting source to one subdirectory of the whole Git repository. Corresponding `--root-dir` option added to `nix-prefetch-git`.
## Nixpkgs Library {#sec-nixpkgs-release-25.11-lib}

View File

@ -16,6 +16,7 @@ $SHELL $fetcher --builder --url "$url" --out "$out" --rev "$rev" --name "$name"
${fetchTags:+--fetch-tags} \
${sparseCheckout:+--sparse-checkout "$sparseCheckout"} \
${nonConeMode:+--non-cone-mode} \
${branchName:+--branch-name "$branchName"}
${branchName:+--branch-name "$branchName"} \
${rootDir:+--root-dir "$rootDir"}
runHook postFetch

View File

@ -8,12 +8,16 @@
let
urlToName =
url: rev:
{
url,
rev,
append,
}:
let
shortRev = lib.sources.shortRev rev;
appendShort = lib.optionalString ((builtins.match "[a-f0-9]*" rev) != null) "-${shortRev}";
in
"${lib.sources.urlToName url}${appendShort}";
"${lib.sources.urlToName url}${if append == "" then appendShort else append}";
in
lib.makeOverridable (
@ -24,15 +28,20 @@ lib.makeOverridable (
url,
tag ? null,
rev ? null,
name ? urlToName url (lib.revOrTag rev tag),
name ? urlToName {
inherit url;
rev = lib.revOrTag rev tag;
# when rootDir is specified, avoid invalidating the result when rev changes
append = if rootDir != "" then "-${lib.strings.sanitizeDerivationName rootDir}" else "";
},
leaveDotGit ? deepClone || fetchTags,
outputHash ? lib.fakeHash,
outputHashAlgo ? null,
fetchSubmodules ? true,
deepClone ? false,
branchName ? null,
sparseCheckout ? [ ],
nonConeMode ? false,
sparseCheckout ? lib.optional (rootDir != "") rootDir,
nonConeMode ? rootDir != "",
nativeBuildInputs ? [ ],
# Shell code executed before the file has been fetched. This, in
# particular, can do things like set NIX_PREFETCH_GIT_CHECKOUT_HOOK to
@ -53,6 +62,8 @@ lib.makeOverridable (
allowedRequisites ? null,
# fetch all tags after tree (useful for git describe)
fetchTags ? false,
# make this subdirectory the root of the result
rootDir ? "",
}:
/*
@ -80,6 +91,7 @@ lib.makeOverridable (
assert nonConeMode -> (sparseCheckout != [ ]);
assert fetchTags -> leaveDotGit;
assert rootDir != "" -> !leaveDotGit;
let
revWithTag =
@ -136,6 +148,7 @@ lib.makeOverridable (
preFetch
postFetch
fetchTags
rootDir
;
rev = revWithTag;

View File

@ -97,4 +97,12 @@
rm -rf .git
'';
};
rootDir = testers.invalidateFetcherByDrvHash fetchgit {
name = "fetchgit-with-rootdir";
url = "https://github.com/NixOS/nix";
rev = "9d9dbe6ed05854e03811c361a3380e09183f4f4a";
rootDir = "misc/systemd";
sha256 = "sha256-UhxHk4SrXYq7ZDMtXLig5SigpbITrVgkpFTmryuvpcM=";
};
}