···99 split
1010 match
1111 typeOf
1212+ storeDir
1213 ;
13141415 inherit (lib.lists)
···2324 take
2425 drop
2526 ;
2727+2828+ listHasPrefix = lib.lists.hasPrefix;
26292730 inherit (lib.strings)
2831 concatStringsSep
···119122 if base == dirOf base then { root = base; inherit components; }
120123 else recurse ([ (baseNameOf base) ] ++ components) (dirOf base);
121124 in recurse [];
125125+126126+ # The components of the store directory, typically [ "nix" "store" ]
127127+ storeDirComponents = splitRelPath ("./" + storeDir);
128128+ # The number of store directory components, typically 2
129129+ storeDirLength = length storeDirComponents;
130130+131131+ # Type: [ String ] -> Bool
132132+ #
133133+ # Whether path components have a store path as a prefix, according to
134134+ # https://nixos.org/manual/nix/stable/store/store-path.html#store-path.
135135+ componentsHaveStorePathPrefix = components:
136136+ # path starts with the store directory (typically /nix/store)
137137+ listHasPrefix storeDirComponents components
138138+ # is not the store directory itself, meaning there's at least one extra component
139139+ && storeDirComponents != components
140140+ # and the first component after the store directory has the expected format.
141141+ # NOTE: We could change the hash regex to be [0-9a-df-np-sv-z],
142142+ # because these are the actual ASCII characters used by Nix's base32 implementation,
143143+ # but this is not fully specified, so let's tie this too much to the currently implemented concept of store paths.
144144+ # Similar reasoning applies to the validity of the name part.
145145+ # We care more about discerning store path-ness on realistic values. Making it airtight would be fragile and slow.
146146+ && match ".{32}-.+" (elemAt components storeDirLength) != null;
122147123148in /* No rec! Add dependencies on this file at the top. */ {
124149···320345 root = deconstructed.root;
321346 subpath = joinRelPath deconstructed.components;
322347 };
348348+349349+ /*
350350+ Whether a [path](https://nixos.org/manual/nix/stable/language/values.html#type-path)
351351+ has a [store path](https://nixos.org/manual/nix/stable/store/store-path.html#store-path)
352352+ as a prefix.
353353+354354+ :::{.note}
355355+ As with all functions of this `lib.path` library, it does not work on paths in strings,
356356+ which is how you'd typically get store paths.
357357+358358+ Instead, this function only handles path values themselves,
359359+ which occur when Nix files in the store use relative path expressions.
360360+ :::
361361+362362+ Type:
363363+ hasStorePathPrefix :: Path -> Bool
364364+365365+ Example:
366366+ # Subpaths of derivation outputs have a store path as a prefix
367367+ hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo/bar/baz
368368+ => true
369369+370370+ # The store directory itself is not a store path
371371+ hasStorePathPrefix /nix/store
372372+ => false
373373+374374+ # Derivation outputs are store paths themselves
375375+ hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo
376376+ => true
377377+378378+ # Paths outside the Nix store don't have a store path prefix
379379+ hasStorePathPrefix /home/user
380380+ => false
381381+382382+ # Not all paths under the Nix store are store paths
383383+ hasStorePathPrefix /nix/store/.links/10gg8k3rmbw8p7gszarbk7qyd9jwxhcfq9i6s5i0qikx8alkk4hq
384384+ => false
385385+386386+ # Store derivations are also store paths themselves
387387+ hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo.drv
388388+ => true
389389+ */
390390+ hasStorePathPrefix = path:
391391+ let
392392+ deconstructed = deconstructPath path;
393393+ in
394394+ assert assertMsg
395395+ (isPath path)
396396+ "lib.path.hasStorePathPrefix: Argument is of type ${typeOf path}, but a path was expected";
397397+ assert assertMsg
398398+ # This function likely breaks or needs adjustment if used with other filesystem roots, if they ever get implemented.
399399+ # 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.
400400+ # See also https://github.com/NixOS/nix/pull/6530#discussion_r1422843117
401401+ (deconstructed.root == /. && toString deconstructed.root == "/")
402402+ "lib.path.hasStorePathPrefix: Argument has a filesystem root (${toString deconstructed.root}) that's not /, which is currently not supported.";
403403+ componentsHaveStorePathPrefix deconstructed.components;
323404324405 /*
325406 Whether a value is a valid subpath string.