32de4cbd93
Another day, another import from derivation avoided by builtins.unsafeDiscardStringContext! Change-Id: I67274b1ba13ba980bb3346b22f2955c702aa3151 Reviewed-on: https://cl.tvl.fyi/c/depot/+/3372 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi> Reviewed-by: tazjin <mail@tazj.in>
131 lines
3.5 KiB
Nix
131 lines
3.5 KiB
Nix
{ depot, lib, ... }:
|
|
|
|
let
|
|
|
|
/* Takes an attribute set and adds a meta.targets
|
|
attribute to it which contains all direct children
|
|
of the attribute set which are derivations.
|
|
|
|
Type: attrs -> attrs
|
|
*/
|
|
drvTargets = attrs:
|
|
attrs // {
|
|
meta = {
|
|
targets = builtins.filter
|
|
(x: lib.isDerivation attrs."${x}")
|
|
(builtins.attrNames attrs);
|
|
} // (attrs.meta or {});
|
|
};
|
|
|
|
/* Get the basename of a store path without
|
|
the leading hash.
|
|
|
|
Type: (path | drv | string) -> string
|
|
|
|
Example:
|
|
storePathName ./foo.c
|
|
=> "foo.c"
|
|
|
|
storePathName (writeText "foo.c" "int main() { return 0; }")
|
|
=> "foo.c"
|
|
|
|
storePathName "${hello}/bin/hello"
|
|
=> "hello"
|
|
*/
|
|
storePathName = p:
|
|
if lib.isDerivation p
|
|
then p.name
|
|
else if builtins.isPath p
|
|
then builtins.baseNameOf p
|
|
else if builtins.isString p
|
|
then
|
|
let
|
|
# strip leading storeDir and trailing slashes
|
|
noStoreDir = lib.removeSuffix "/"
|
|
(lib.removePrefix "${builtins.storeDir}/" p);
|
|
# a basename of a child of a store path isn't really
|
|
# referring to a store path, so removing the string
|
|
# context is safe (e. g. "hello" for "${hello}/bin/hello").
|
|
basename = builtins.unsafeDiscardStringContext
|
|
(builtins.baseNameOf p);
|
|
in
|
|
# If p is a direct child of storeDir, we need to remove
|
|
# the leading hash as well to make sure that:
|
|
# `storePathName drv == storePathName (toString drv)`.
|
|
if noStoreDir == basename
|
|
then builtins.substring 33 (-1) basename
|
|
else basename
|
|
else builtins.throw "Don't know how to get (base)name of "
|
|
+ lib.generators.toPretty {} p;
|
|
|
|
/* Get the type of a path itself as it would be returned for a
|
|
directory child by builtins.readDir.
|
|
|
|
Type: path(-like) -> option<string>
|
|
|
|
Example:
|
|
pathType ./foo.c
|
|
=> "regular"
|
|
|
|
pathType /home/lukas
|
|
=> "directory"
|
|
|
|
pathType ./result
|
|
=> "symlink"
|
|
|
|
pathType /does/not/exist
|
|
=> null
|
|
*/
|
|
pathType = path:
|
|
let
|
|
# baseNameOf is very annoyed if we proceed with string context.
|
|
# We need to call toString to prevent unsafeDiscardStringContext
|
|
# from importing a path into store which messes with base- and
|
|
# dirname of course.
|
|
path'= builtins.unsafeDiscardStringContext (toString path);
|
|
# To read the containing directory we absolutely need
|
|
# to keep the string context, otherwise a derivation
|
|
# would not be realized before our check (at eval time)
|
|
containingDir = builtins.readDir (builtins.dirOf path);
|
|
in
|
|
containingDir.${builtins.baseNameOf path'} or null;
|
|
|
|
pathType' = path:
|
|
let
|
|
p = pathType path;
|
|
in
|
|
if p == null
|
|
then builtins.throw "${lib.generators.toPretty {} path} does not exist"
|
|
else p;
|
|
|
|
/* Check whether the given path is a directory.
|
|
Throws if the path in question doesn't exist.
|
|
|
|
Type: path(-like) -> bool
|
|
*/
|
|
isDirectory = path: pathType' path == "directory";
|
|
|
|
/* Check whether the given path is a regular file.
|
|
Throws if the path in question doesn't exist.
|
|
|
|
Type: path(-like) -> bool
|
|
*/
|
|
isRegularFile = path: pathType' path == "regular";
|
|
|
|
/* Check whether the given path is a symbolic link.
|
|
Throws if the path in question doesn't exist.
|
|
|
|
Type: path(-like) -> bool
|
|
*/
|
|
isSymlink = path: pathType' path == "symlink";
|
|
|
|
in {
|
|
inherit
|
|
drvTargets
|
|
storePathName
|
|
pathType
|
|
isDirectory
|
|
isRegularFile
|
|
isSymlink
|
|
;
|
|
}
|