lib.path.hasStorePathPrefix: init
Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
This commit is contained in:
parent
c4e2e52a21
commit
d4b7b15407
2 changed files with 110 additions and 1 deletions
|
@ -9,6 +9,7 @@ let
|
|||
split
|
||||
match
|
||||
typeOf
|
||||
storeDir
|
||||
;
|
||||
|
||||
inherit (lib.lists)
|
||||
|
@ -24,6 +25,8 @@ let
|
|||
drop
|
||||
;
|
||||
|
||||
listHasPrefix = lib.lists.hasPrefix;
|
||||
|
||||
inherit (lib.strings)
|
||||
concatStringsSep
|
||||
substring
|
||||
|
@ -120,6 +123,28 @@ let
|
|||
else recurse ([ (baseNameOf base) ] ++ components) (dirOf base);
|
||||
in recurse [];
|
||||
|
||||
# The components of the store directory, typically [ "nix" "store" ]
|
||||
storeDirComponents = splitRelPath ("./" + storeDir);
|
||||
# The number of store directory components, typically 2
|
||||
storeDirLength = length storeDirComponents;
|
||||
|
||||
# Type: [ String ] -> Bool
|
||||
#
|
||||
# Whether path components have a store path as a prefix, according to
|
||||
# https://nixos.org/manual/nix/stable/store/store-path.html#store-path.
|
||||
componentsHaveStorePathPrefix = components:
|
||||
# path starts with the store directory (typically /nix/store)
|
||||
listHasPrefix storeDirComponents components
|
||||
# is not the store directory itself, meaning there's at least one extra component
|
||||
&& storeDirComponents != components
|
||||
# and the first component after the store directory has the expected format.
|
||||
# NOTE: We could change the hash regex to be [0-9a-df-np-sv-z],
|
||||
# because these are the actual ASCII characters used by Nix's base32 implementation,
|
||||
# but this is not fully specified, so let's tie this too much to the currently implemented concept of store paths.
|
||||
# Similar reasoning applies to the validity of the name part.
|
||||
# We care more about discerning store path-ness on realistic values. Making it airtight would be fragile and slow.
|
||||
&& match ".{32}-.+" (elemAt components storeDirLength) != null;
|
||||
|
||||
in /* No rec! Add dependencies on this file at the top. */ {
|
||||
|
||||
/*
|
||||
|
@ -321,6 +346,62 @@ in /* No rec! Add dependencies on this file at the top. */ {
|
|||
subpath = joinRelPath deconstructed.components;
|
||||
};
|
||||
|
||||
/*
|
||||
Whether a [path](https://nixos.org/manual/nix/stable/language/values.html#type-path)
|
||||
has a [store path](https://nixos.org/manual/nix/stable/store/store-path.html#store-path)
|
||||
as a prefix.
|
||||
|
||||
:::{.note}
|
||||
As with all functions of this `lib.path` library, it does not work on paths in strings,
|
||||
which is how you'd typically get store paths.
|
||||
|
||||
Instead, this function only handles path values themselves,
|
||||
which occur when Nix files in the store use relative path expressions.
|
||||
:::
|
||||
|
||||
Type:
|
||||
hasStorePathPrefix :: Path -> Bool
|
||||
|
||||
Example:
|
||||
# Subpaths of derivation outputs have a store path as a prefix
|
||||
hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo/bar/baz
|
||||
=> true
|
||||
|
||||
# The store directory itself is not a store path
|
||||
hasStorePathPrefix /nix/store
|
||||
=> false
|
||||
|
||||
# Derivation outputs are store paths themselves
|
||||
hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo
|
||||
=> true
|
||||
|
||||
# Paths outside the Nix store don't have a store path prefix
|
||||
hasStorePathPrefix /home/user
|
||||
=> false
|
||||
|
||||
# Not all paths under the Nix store are store paths
|
||||
hasStorePathPrefix /nix/store/.links/10gg8k3rmbw8p7gszarbk7qyd9jwxhcfq9i6s5i0qikx8alkk4hq
|
||||
=> false
|
||||
|
||||
# Store derivations are also store paths themselves
|
||||
hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo.drv
|
||||
=> true
|
||||
*/
|
||||
hasStorePathPrefix = path:
|
||||
let
|
||||
deconstructed = deconstructPath path;
|
||||
in
|
||||
assert assertMsg
|
||||
(isPath path)
|
||||
"lib.path.hasStorePathPrefix: Argument is of type ${typeOf path}, but a path was expected";
|
||||
assert assertMsg
|
||||
# This function likely breaks or needs adjustment if used with other filesystem roots, if they ever get implemented.
|
||||
# Let's try to error nicely in such a case, though it's unclear how an implementation would work even and whether this could be detected.
|
||||
# See also https://github.com/NixOS/nix/pull/6530#discussion_r1422843117
|
||||
(deconstructed.root == /. && toString deconstructed.root == "/")
|
||||
"lib.path.hasStorePathPrefix: Argument has a filesystem root (${toString deconstructed.root}) that's not /, which is currently not supported.";
|
||||
componentsHaveStorePathPrefix deconstructed.components;
|
||||
|
||||
/*
|
||||
Whether a value is a valid subpath string.
|
||||
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
{ libpath }:
|
||||
let
|
||||
lib = import libpath;
|
||||
inherit (lib.path) hasPrefix removePrefix append splitRoot subpath;
|
||||
inherit (lib.path) hasPrefix removePrefix append splitRoot hasStorePathPrefix subpath;
|
||||
|
||||
# This is not allowed generally, but we're in the tests here, so we'll allow ourselves.
|
||||
storeDirPath = /. + builtins.storeDir;
|
||||
|
||||
cases = lib.runTests {
|
||||
# Test examples from the lib.path.append documentation
|
||||
|
@ -91,6 +94,31 @@ let
|
|||
expected = false;
|
||||
};
|
||||
|
||||
testHasStorePathPrefixExample1 = {
|
||||
expr = hasStorePathPrefix (storeDirPath + "/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo/bar/baz");
|
||||
expected = true;
|
||||
};
|
||||
testHasStorePathPrefixExample2 = {
|
||||
expr = hasStorePathPrefix storeDirPath;
|
||||
expected = false;
|
||||
};
|
||||
testHasStorePathPrefixExample3 = {
|
||||
expr = hasStorePathPrefix (storeDirPath + "/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo");
|
||||
expected = true;
|
||||
};
|
||||
testHasStorePathPrefixExample4 = {
|
||||
expr = hasStorePathPrefix /home/user;
|
||||
expected = false;
|
||||
};
|
||||
testHasStorePathPrefixExample5 = {
|
||||
expr = hasStorePathPrefix (storeDirPath + "/.links/10gg8k3rmbw8p7gszarbk7qyd9jwxhcfq9i6s5i0qikx8alkk4hq");
|
||||
expected = false;
|
||||
};
|
||||
testHasStorePathPrefixExample6 = {
|
||||
expr = hasStorePathPrefix (storeDirPath + "/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo.drv");
|
||||
expected = true;
|
||||
};
|
||||
|
||||
# Test examples from the lib.path.subpath.isValid documentation
|
||||
testSubpathIsValidExample1 = {
|
||||
expr = subpath.isValid null;
|
||||
|
|
Loading…
Reference in a new issue