about summary refs log tree commit diff
path: root/nixpkgs/lib/fileset
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2024-03-01 11:40:12 +0100
committerAlyssa Ross <hi@alyssa.is>2024-03-01 11:40:12 +0100
commitbf6d657e5dbcb5e39fda280ef7e86b2a7794ca86 (patch)
tree8eb035cbab19794f6415cc460fac7226f7a58afc /nixpkgs/lib/fileset
parent66f707d69f1e423db5a35c2fe43b32781125a9af (diff)
parent09c1497ce5d4ed4a0edfdd44450d3048074cb300 (diff)
downloadnixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar.gz
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar.bz2
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar.lz
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar.xz
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar.zst
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.zip
Merge branch 'nixos-unstable-small' of https://github.com/NixOS/nixpkgs
Diffstat (limited to 'nixpkgs/lib/fileset')
-rw-r--r--nixpkgs/lib/fileset/default.nix37
-rw-r--r--nixpkgs/lib/fileset/internal.nix23
-rwxr-xr-xnixpkgs/lib/fileset/tests.sh124
3 files changed, 134 insertions, 50 deletions
diff --git a/nixpkgs/lib/fileset/default.nix b/nixpkgs/lib/fileset/default.nix
index c007b60def0a..ce9afc796a3f 100644
--- a/nixpkgs/lib/fileset/default.nix
+++ b/nixpkgs/lib/fileset/default.nix
@@ -23,6 +23,10 @@
 
     Add files in file sets to the store to use as derivation sources.
 
+  - [`lib.fileset.toList`](#function-library-lib.fileset.toList):
+
+    The list of files contained in a file set.
+
   Combinators:
   - [`lib.fileset.union`](#function-library-lib.fileset.union)/[`lib.fileset.unions`](#function-library-lib.fileset.unions):
 
@@ -102,6 +106,7 @@ let
     _coerceMany
     _toSourceFilter
     _fromSourceFilter
+    _toList
     _unionMany
     _fileFilter
     _printFileset
@@ -412,6 +417,38 @@ in {
         filter = sourceFilter;
       };
 
+
+  /*
+    The list of file paths contained in the given file set.
+
+    :::{.note}
+    This function is strict in the entire file set.
+    This is in contrast with combinators [`lib.fileset.union`](#function-library-lib.fileset.union),
+    [`lib.fileset.intersection`](#function-library-lib.fileset.intersection) and [`lib.fileset.difference`](#function-library-lib.fileset.difference).
+
+    Thus it is recommended to call `toList` on file sets created using the combinators,
+    instead of doing list processing on the result of `toList`.
+    :::
+
+    The resulting list of files can be turned back into a file set using [`lib.fileset.unions`](#function-library-lib.fileset.unions).
+
+    Type:
+      toList :: FileSet -> [ Path ]
+
+    Example:
+      toList ./.
+      [ ./README.md ./Makefile ./src/main.c ./src/main.h ]
+
+      toList (difference ./. ./src)
+      [ ./README.md ./Makefile ]
+  */
+  toList =
+    # The file set whose file paths to return.
+    # This argument can also be a path,
+    # which gets [implicitly coerced to a file set](#sec-fileset-path-coercion).
+    fileset:
+    _toList (_coerce "lib.fileset.toList: Argument" fileset);
+
   /*
     The file set containing all files that are in either of two given file sets.
     This is the same as [`unions`](#function-library-lib.fileset.unions),
diff --git a/nixpkgs/lib/fileset/internal.nix b/nixpkgs/lib/fileset/internal.nix
index f4fcc83e1012..0d97ef174568 100644
--- a/nixpkgs/lib/fileset/internal.nix
+++ b/nixpkgs/lib/fileset/internal.nix
@@ -18,6 +18,7 @@ let
     attrNames
     attrValues
     mapAttrs
+    mapAttrsToList
     optionalAttrs
     zipAttrsWith
     ;
@@ -29,6 +30,7 @@ let
   inherit (lib.lists)
     all
     commonPrefix
+    concatLists
     elemAt
     filter
     findFirst
@@ -539,6 +541,27 @@ rec {
           ${baseNameOf root} = rootPathType;
         };
 
+  # Turns a file set into the list of file paths it includes.
+  # Type: fileset -> [ Path ]
+  _toList = fileset:
+    let
+      recurse = path: tree:
+        if isAttrs tree then
+          concatLists (mapAttrsToList (name: value:
+            recurse (path + "/${name}") value
+          ) tree)
+        else if tree == "directory" then
+          recurse path (readDir path)
+        else if tree == null then
+          [ ]
+        else
+          [ path ];
+    in
+    if fileset._internalIsEmptyWithoutBase then
+      [ ]
+    else
+      recurse fileset._internalBase fileset._internalTree;
+
   # Transforms the filesetTree of a file set to a shorter base path, e.g.
   # _shortenTreeBase [ "foo" ] (_create /foo/bar null)
   # => { bar = null; }
diff --git a/nixpkgs/lib/fileset/tests.sh b/nixpkgs/lib/fileset/tests.sh
index af8338eb7855..405fa04d8e06 100755
--- a/nixpkgs/lib/fileset/tests.sh
+++ b/nixpkgs/lib/fileset/tests.sh
@@ -275,7 +275,6 @@ createTree() {
 # )
 # checkFileset './a' # Pass the fileset as the argument
 checkFileset() {
-    # New subshell so that we can have a separate trap handler, see `trap` below
     local fileset=$1
 
     # Create the tree
@@ -283,16 +282,20 @@ checkFileset() {
 
     # Process the tree into separate arrays for included paths, excluded paths and excluded files.
     local -a included=()
+    local -a includedFiles=()
     local -a excluded=()
     local -a excludedFiles=()
     for p in "${!tree[@]}"; do
         case "${tree[$p]}" in
             1)
                 included+=("$p")
+                # If keys end with a `/` we treat them as directories, otherwise files
+                if [[ ! "$p" =~ /$ ]]; then
+                    includedFiles+=("$p")
+                fi
                 ;;
             0)
                 excluded+=("$p")
-                # If keys end with a `/` we treat them as directories, otherwise files
                 if [[ ! "$p" =~ /$ ]]; then
                     excludedFiles+=("$p")
                 fi
@@ -302,6 +305,10 @@ checkFileset() {
         esac
     done
 
+    # Test that lib.fileset.toList contains exactly the included files.
+    # The /#/./ part prefixes each element with `./`
+    expectEqual "toList ($fileset)" "sort lessThan [ ${includedFiles[*]/#/./} ]"
+
     expression="toSource { root = ./.; fileset = $fileset; }"
 
     # We don't have lambda's in bash unfortunately,
@@ -338,13 +345,17 @@ checkFileset() {
 
 #### Error messages #####
 
+# We're using [[:blank:]] here instead of \s, because only the former is POSIX
+# (see https://pubs.opengroup.org/onlinepubs/007908799/xbd/re.html#tag_007_003_005).
+# And indeed, Darwin's bash only supports the former
+
 # Absolute paths in strings cannot be passed as `root`
 expectFailure 'toSource { root = "/nix/store/foobar"; fileset = ./.; }' 'lib.fileset.toSource: `root` \(/nix/store/foobar\) is a string-like value, but it should be a path instead.
-\s*Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
+[[:blank:]]*Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
 
 expectFailure 'toSource { root = cleanSourceWith { src = ./.; }; fileset = ./.; }' 'lib.fileset.toSource: `root` is a `lib.sources`-based value, but it should be a path instead.
-\s*To use a `lib.sources`-based value, convert it to a file set using `lib.fileset.fromSource` and pass it as `fileset`.
-\s*Note that this only works for sources created from paths.'
+[[:blank:]]*To use a `lib.sources`-based value, convert it to a file set using `lib.fileset.fromSource` and pass it as `fileset`.
+[[:blank:]]*Note that this only works for sources created from paths.'
 
 # Only paths are accepted as `root`
 expectFailure 'toSource { root = 10; fileset = ./.; }' 'lib.fileset.toSource: `root` is of type int, but it should be a path instead.'
@@ -354,9 +365,9 @@ mkdir -p {foo,bar}/mock-root
 expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
   toSource { root = ./foo/mock-root; fileset = ./bar/mock-root; }
 ' 'lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` \('"$work"'/foo/mock-root\):
-\s*`root`: Filesystem root is "'"$work"'/foo/mock-root"
-\s*`fileset`: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*`root`: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*`fileset`: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*Different filesystem roots are not supported.'
 rm -rf -- *
 
 # `root` needs to exist
@@ -365,8 +376,8 @@ expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `
 # `root` needs to be a file
 touch a
 expectFailure 'toSource { root = ./a; fileset = ./a; }' 'lib.fileset.toSource: `root` \('"$work"'/a\) is a file, but it should be a directory instead. Potential solutions:
-\s*- If you want to import the file into the store _without_ a containing directory, use string interpolation or `builtins.path` instead of this function.
-\s*- If you want to import the file into the store _with_ a containing directory, set `root` to the containing directory, such as '"$work"', and set `fileset` to the file path.'
+[[:blank:]]*- If you want to import the file into the store _without_ a containing directory, use string interpolation or `builtins.path` instead of this function.
+[[:blank:]]*- If you want to import the file into the store _with_ a containing directory, set `root` to the containing directory, such as '"$work"', and set `fileset` to the file path.'
 rm -rf -- *
 
 # The fileset argument should be evaluated, even if the directory is empty
@@ -375,36 +386,36 @@ expectFailure 'toSource { root = ./.; fileset = abort "This should be evaluated"
 # Only paths under `root` should be able to influence the result
 mkdir a
 expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `fileset` could contain files in '"$work"', which is not under the `root` \('"$work"'/a\). Potential solutions:
-\s*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
-\s*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
+[[:blank:]]*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
+[[:blank:]]*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
 rm -rf -- *
 
 # non-regular and non-symlink files cannot be added to the Nix store
 mkfifo a
 expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` contains a file that cannot be added to the store: '"$work"'/a
-\s*This file is neither a regular file nor a symlink, the only file types supported by the Nix store.
-\s*Therefore the file set cannot be added to the Nix store as is. Make sure to not include that file to avoid this error.'
+[[:blank:]]*This file is neither a regular file nor a symlink, the only file types supported by the Nix store.
+[[:blank:]]*Therefore the file set cannot be added to the Nix store as is. Make sure to not include that file to avoid this error.'
 rm -rf -- *
 
 # Path coercion only works for paths
 expectFailure 'toSource { root = ./.; fileset = 10; }' 'lib.fileset.toSource: `fileset` is of type int, but it should be a file set or a path instead.'
 expectFailure 'toSource { root = ./.; fileset = "/some/path"; }' 'lib.fileset.toSource: `fileset` \("/some/path"\) is a string-like value, but it should be a file set or a path instead.
-\s*Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
+[[:blank:]]*Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
 expectFailure 'toSource { root = ./.; fileset = cleanSourceWith { src = ./.; }; }' 'lib.fileset.toSource: `fileset` is a `lib.sources`-based value, but it should be a file set or a path instead.
-\s*To convert a `lib.sources`-based value to a file set you can use `lib.fileset.fromSource`.
-\s*Note that this only works for sources created from paths.'
+[[:blank:]]*To convert a `lib.sources`-based value to a file set you can use `lib.fileset.fromSource`.
+[[:blank:]]*Note that this only works for sources created from paths.'
 
 # Path coercion errors for non-existent paths
 expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` \('"$work"'/a\) is a path that does not exist.
-\s*To create a file set from a path that may not exist, use `lib.fileset.maybeMissing`.'
+[[:blank:]]*To create a file set from a path that may not exist, use `lib.fileset.maybeMissing`.'
 
 # File sets cannot be evaluated directly
 expectFailure 'union ./. ./.' 'lib.fileset: Directly evaluating a file set is not supported.
-\s*To turn it into a usable source, use `lib.fileset.toSource`.
-\s*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
+[[:blank:]]*To turn it into a usable source, use `lib.fileset.toSource`.
+[[:blank:]]*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
 expectFailure '_emptyWithoutBase' 'lib.fileset: Directly evaluating a file set is not supported.
-\s*To turn it into a usable source, use `lib.fileset.toSource`.
-\s*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
+[[:blank:]]*To turn it into a usable source, use `lib.fileset.toSource`.
+[[:blank:]]*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
 
 # Past versions of the internal representation are supported
 expectEqual '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 0; _internalBase = ./.; }' \
@@ -416,9 +427,9 @@ expectEqual '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 2;
 
 # Future versions of the internal representation are unsupported
 expectFailure '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 4; }' '<tests>: value is a file set created from a future version of the file set library with a different internal representation:
-\s*- Internal version of the file set: 4
-\s*- Internal version of the library: 3
-\s*Make sure to update your Nixpkgs to have a newer version of `lib.fileset`.'
+[[:blank:]]*- Internal version of the file set: 4
+[[:blank:]]*- Internal version of the library: 3
+[[:blank:]]*Make sure to update your Nixpkgs to have a newer version of `lib.fileset`.'
 
 # _create followed by _coerce should give the inputs back without any validation
 expectEqual '{
@@ -511,6 +522,19 @@ expectEqual '_toSourceFilter (_create /. { foo = "regular"; }) "/foo" ""' 'true'
 expectEqual '_toSourceFilter (_create /. { foo = null; }) "/foo" ""' 'false'
 
 
+## lib.fileset.toList
+# This function is mainly tested in checkFileset
+
+# The error context for an invalid argument must be correct
+expectFailure 'toList null' 'lib.fileset.toList: Argument is of type null, but it should be a file set or a path instead.'
+
+# Works for the empty fileset
+expectEqual 'toList _emptyWithoutBase' '[ ]'
+
+# Works on empty paths
+expectEqual 'toList ./.' '[ ]'
+
+
 ## lib.fileset.union, lib.fileset.unions
 
 
@@ -519,16 +543,16 @@ mkdir -p {foo,bar}/mock-root
 expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
   toSource { root = ./.; fileset = union ./foo/mock-root ./bar/mock-root; }
 ' 'lib.fileset.union: Filesystem roots are not the same:
-\s*First argument: Filesystem root is "'"$work"'/foo/mock-root"
-\s*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*First argument: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*Different filesystem roots are not supported.'
 
 expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
   toSource { root = ./.; fileset = unions [ ./foo/mock-root ./bar/mock-root ]; }
 ' 'lib.fileset.unions: Filesystem roots are not the same:
-\s*Element 0: Filesystem root is "'"$work"'/foo/mock-root"
-\s*Element 1: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*Element 0: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*Element 1: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*Different filesystem roots are not supported.'
 rm -rf -- *
 
 # Coercion errors show the correct context
@@ -632,9 +656,9 @@ mkdir -p {foo,bar}/mock-root
 expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
   toSource { root = ./.; fileset = intersection ./foo/mock-root ./bar/mock-root; }
 ' 'lib.fileset.intersection: Filesystem roots are not the same:
-\s*First argument: Filesystem root is "'"$work"'/foo/mock-root"
-\s*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*First argument: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*Different filesystem roots are not supported.'
 rm -rf -- *
 
 # Coercion errors show the correct context
@@ -741,8 +765,8 @@ rm -rf -- *
 # Also not the other way around
 mkdir a
 expectFailure 'toSource { root = ./a; fileset = difference ./. ./a; }' 'lib.fileset.toSource: `fileset` could contain files in '"$work"', which is not under the `root` \('"$work"'/a\). Potential solutions:
-\s*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
-\s*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
+[[:blank:]]*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
+[[:blank:]]*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
 rm -rf -- *
 
 # Difference actually works
@@ -819,7 +843,7 @@ expectFailure 'fileFilter null (abort "this is not needed")' 'lib.fileset.fileFi
 
 # The second argument needs to be an existing path
 expectFailure 'fileFilter (file: abort "this is not needed") _emptyWithoutBase' 'lib.fileset.fileFilter: Second argument is a file set, but it should be a path instead.
-\s*If you need to filter files in a file set, use `intersection fileset \(fileFilter pred \./\.\)` instead.'
+[[:blank:]]*If you need to filter files in a file set, use `intersection fileset \(fileFilter pred \./\.\)` instead.'
 expectFailure 'fileFilter (file: abort "this is not needed") null' 'lib.fileset.fileFilter: Second argument is of type null, but it should be a path instead.'
 expectFailure 'fileFilter (file: abort "this is not needed") ./a' 'lib.fileset.fileFilter: Second argument \('"$work"'/a\) is a path that does not exist.'
 
@@ -1083,7 +1107,7 @@ rm -rf -- *
 
 # String-like values are not supported
 expectFailure 'fromSource (lib.cleanSource "")' 'lib.fileset.fromSource: The source origin of the argument is a string-like value \(""\), but it should be a path instead.
-\s*Sources created from paths in strings cannot be turned into file sets, use `lib.sources` or derivations instead.'
+[[:blank:]]*Sources created from paths in strings cannot be turned into file sets, use `lib.sources` or derivations instead.'
 
 # Wrong type
 expectFailure 'fromSource null' 'lib.fileset.fromSource: The source origin of the argument is of type null, but it should be a path instead.'
@@ -1400,10 +1424,10 @@ expectEqual '(import '"$storePath"' { fs = lib.fileset; }).outPath' \""$storePat
 
 ## But it fails if the path is imported with a fetcher that doesn't remove .git (like just using "${./.}")
 expectFailure 'import "${./.}" { fs = lib.fileset; }' 'lib.fileset.gitTracked: The argument \(.*\) is a store path within a working tree of a Git repository.
-\s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
-\s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
-\s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
-\s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
+[[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
+[[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
+[[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
+[[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
 
 ## Even with submodules
 if [[ -n "$fetchGitSupportsSubmodules" ]]; then
@@ -1427,15 +1451,15 @@ if [[ -n "$fetchGitSupportsSubmodules" ]]; then
 
     ## But it fails if the path is imported with a fetcher that doesn't remove .git (like just using "${./.}")
     expectFailure 'import "${./.}" { fs = lib.fileset; }' 'lib.fileset.gitTrackedWith: The second argument \(.*\) is a store path within a working tree of a Git repository.
-    \s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
-    \s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
-    \s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
-    \s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
+    [[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
+    [[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
+    [[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
+    [[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
     expectFailure 'import "${./.}/sub" { fs = lib.fileset; }' 'lib.fileset.gitTracked: The argument \(.*/sub\) is a store path within a working tree of a Git repository.
-    \s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
-    \s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
-    \s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
-    \s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
+    [[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
+    [[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
+    [[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
+    [[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
 fi
 rm -rf -- *