about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorSilvan Mosberger <silvan.mosberger@tweag.io>2023-11-03 01:32:02 +0100
committerSilvan Mosberger <silvan.mosberger@tweag.io>2023-11-16 01:12:18 +0100
commitd33f1a62f5bd8b5187632b8f562d62a39540da89 (patch)
treec836f29a18007f0ad717fe9c55c285fa27d4b3d7 /lib
parent2dfb1d36cf5ff1fc9b39292ff202e895f92eae0c (diff)
downloadnixlib-d33f1a62f5bd8b5187632b8f562d62a39540da89.tar
nixlib-d33f1a62f5bd8b5187632b8f562d62a39540da89.tar.gz
nixlib-d33f1a62f5bd8b5187632b8f562d62a39540da89.tar.bz2
nixlib-d33f1a62f5bd8b5187632b8f562d62a39540da89.tar.lz
nixlib-d33f1a62f5bd8b5187632b8f562d62a39540da89.tar.xz
nixlib-d33f1a62f5bd8b5187632b8f562d62a39540da89.tar.zst
nixlib-d33f1a62f5bd8b5187632b8f562d62a39540da89.zip
lib.fileset.gitTrackedWith: Introduce recurseSubmodules parameter
Diffstat (limited to 'lib')
-rw-r--r--lib/fileset/default.nix26
-rw-r--r--lib/fileset/internal.nix4
-rwxr-xr-xlib/fileset/tests.sh29
3 files changed, 53 insertions, 6 deletions
diff --git a/lib/fileset/default.nix b/lib/fileset/default.nix
index 0248c16c645e..1ccd3013ce5c 100644
--- a/lib/fileset/default.nix
+++ b/lib/fileset/default.nix
@@ -13,14 +13,17 @@ let
     _intersection
     _difference
     _mirrorStorePath
+    _fetchGitSubmodulesMinver
     ;
 
   inherit (builtins)
+    isBool
     isList
     isPath
     pathExists
     seq
     typeOf
+    nixVersion
     ;
 
   inherit (lib.lists)
@@ -35,6 +38,7 @@ let
 
   inherit (lib.strings)
     isStringLike
+    versionOlder
     ;
 
   inherit (lib.filesystem)
@@ -650,14 +654,21 @@ in {
     :::
 
     Type:
-      gitTrackedWith :: { } -> Path -> FileSet
+      gitTrackedWith :: { recurseSubmodules :: Bool ? false } -> Path -> FileSet
 
     Example:
       # Include all files tracked by the Git repository in the current directory
-      gitTracked { } ./.
+      # and any submodules under it
+      gitTracked { recurseSubmodules = true; } ./.
   */
   gitTrackedWith =
     {
+      /*
+        (optional, default: `false`) Whether to recurse into [Git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) to also include their tracked files.
+
+        If `true`, this is equivalent to passing the [--recurse-submodules](https://git-scm.com/docs/git-ls-files#Documentation/git-ls-files.txt---recurse-submodules) flag to `git ls-files`.
+      */
+      recurseSubmodules ? false,
     }:
     /*
       The [path](https://nixos.org/manual/nix/stable/language/values#type-path) to the working directory of a local Git repository.
@@ -672,9 +683,18 @@ in {
       # However a simpler alternative still would be [a builtins.gitLsFiles](https://github.com/NixOS/nix/issues/2944).
       fetchResult = builtins.fetchGit {
         url = path;
+
+        # This is the only `fetchGit` parameter that makes sense in this context.
+        # We can't just pass `submodules = recurseSubmodules` here because
+        # this would fail for Nix versions that don't support `submodules`.
+        ${if recurseSubmodules then "submodules" else null} = true;
       };
     in
-    if ! isPath path then
+    if ! isBool recurseSubmodules then
+      throw "lib.fileset.gitTrackedWith: Expected the attribute `recurseSubmodules` of the first argument to be a boolean, but it's a ${typeOf recurseSubmodules} instead."
+    else if recurseSubmodules && versionOlder nixVersion _fetchGitSubmodulesMinver then
+      throw "lib.fileset.gitTrackedWith: Setting the attribute `recurseSubmodules` to `true` is only supported for Nix version ${_fetchGitSubmodulesMinver} and after, but Nix version ${nixVersion} is used."
+    else if ! isPath path then
       throw "lib.fileset.gitTrackedWith: Expected the second argument to be a path, but it's a ${typeOf path} instead."
     # We can identify local working directories by checking for .git,
     # see https://git-scm.com/docs/gitrepository-layout#_description.
diff --git a/lib/fileset/internal.nix b/lib/fileset/internal.nix
index 93f3d5e18b96..0769e654c8fb 100644
--- a/lib/fileset/internal.nix
+++ b/lib/fileset/internal.nix
@@ -826,6 +826,10 @@ rec {
           fromFile (baseNameOf root) rootType;
       };
 
+  # Support for `builtins.fetchGit` with `submodules = true` was introduced in 2.4
+  # https://github.com/NixOS/nix/commit/55cefd41d63368d4286568e2956afd535cb44018
+  _fetchGitSubmodulesMinver = "2.4";
+
   # Mirrors the contents of a Nix store path relative to a local path as a file set.
   # Some notes:
   # - The store path is read at evaluation time.
diff --git a/lib/fileset/tests.sh b/lib/fileset/tests.sh
index c7991e06bdf9..ef8bee9e66cf 100755
--- a/lib/fileset/tests.sh
+++ b/lib/fileset/tests.sh
@@ -1262,11 +1262,30 @@ expectFailure 'gitTrackedWith {} null' 'lib.fileset.gitTrackedWith: Expected the
 expectFailure 'gitTracked ./.' 'lib.fileset.gitTracked: Expected the argument \('"$work"'\) to point to a local working tree of a Git repository, but it'\''s not.'
 expectFailure 'gitTrackedWith {} ./.' 'lib.fileset.gitTrackedWith: Expected the second argument \('"$work"'\) to point to a local working tree of a Git repository, but it'\''s not.'
 
+# recurseSubmodules has to be a boolean
+expectFailure 'gitTrackedWith { recurseSubmodules = null; } ./.' 'lib.fileset.gitTrackedWith: Expected the attribute `recurseSubmodules` of the first argument to be a boolean, but it'\''s a null instead.'
+
+# recurseSubmodules = true is not supported on all Nix versions
+if [[ "$(nix-instantiate --eval --expr "$prefixExpression (versionAtLeast builtins.nixVersion _fetchGitSubmodulesMinver)")" == true ]]; then
+    fetchGitSupportsSubmodules=1
+else
+    fetchGitSupportsSubmodules=
+    expectFailure 'gitTrackedWith { recurseSubmodules = true; } ./.' 'lib.fileset.gitTrackedWith: Setting the attribute `recurseSubmodules` to `true` is only supported for Nix version 2.4 and after, but Nix version [0-9.]+ is used.'
+fi
+
 # Checks that `gitTrackedWith` contains the same files as `git ls-files`
 # for the current working directory.
 # If --recurse-submodules is passed, the flag is passed through to `git ls-files`
 # and as `recurseSubmodules` to `gitTrackedWith`
 checkGitTrackedWith() {
+    if [[ "${1:-}" == "--recurse-submodules" ]]; then
+        gitLsFlags="--recurse-submodules"
+        gitTrackedArg="{ recurseSubmodules = true; }"
+    else
+        gitLsFlags=""
+        gitTrackedArg="{ }"
+    fi
+
     # All files listed by `git ls-files`
     expectedFiles=()
     while IFS= read -r -d $'\0' file; do
@@ -1276,9 +1295,9 @@ checkGitTrackedWith() {
         if [[ -f "$file" ]]; then
             expectedFiles+=("$file")
         fi
-    done < <(git ls-files -z)
+    done < <(git ls-files -z $gitLsFlags)
 
-    storePath=$(expectStorePath 'toSource { root = ./.; fileset = gitTrackedWith { } ./.; }')
+    storePath=$(expectStorePath 'toSource { root = ./.; fileset = gitTrackedWith '"$gitTrackedArg"' ./.; }')
 
     # Check that each expected file is also in the store path with the same content
     for expectedFile in "${expectedFiles[@]}"; do
@@ -1299,9 +1318,13 @@ checkGitTrackedWith() {
 }
 
 
-# Runs checkGitTrackedWith, this will make more sense in the next commit
+# Runs checkGitTrackedWith with and without --recurse-submodules
+# Allows testing both variants together
 checkGitTracked() {
     checkGitTrackedWith
+    if [[ -n "$fetchGitSupportsSubmodules" ]]; then
+        checkGitTrackedWith --recurse-submodules
+    fi
 }
 
 createGitRepo() {