about summary refs log tree commit diff
path: root/nix/utils
diff options
context:
space:
mode:
Diffstat (limited to 'nix/utils')
-rw-r--r--nix/utils/default.nix42
1 files changed, 42 insertions, 0 deletions
diff --git a/nix/utils/default.nix b/nix/utils/default.nix
index 33f72e3903..2d765c0c45 100644
--- a/nix/utils/default.nix
+++ b/nix/utils/default.nix
@@ -17,8 +17,50 @@ let
       } // (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;
+
 in {
   inherit
     drvTargets
+    storePathName
     ;
 }