66fa718ceb
In order to make readTree import symlinked directories I've been looking into how to detect if a symlink points to a directory (since this would allow us to use symlinks for //nix/sparseTree). I've found a hack for this: symlinkPointsToDir = path: isSymlink path && builtins.pathExists (toString path + "/.") Unfortunately it doesn't seem to be possible to distinguish whether the symlink target does not exist or is a regular file. Since it's possible, I thought might as well add this to `pathType`. To make returning the extra information workable, I've elected to use the attribute set layout used by `//nix/tag`. This doesn't require us to depend anything (as opposed to yants), but gives us pattern matching (via `nix.tag.match`) and also quite idiomatic checking of pathTypes: pathType ./foo ? file (pathType ./foo).symlink or null == "symlink-directory" Nonexistent paths are encoded like this: pathType ./foo ? missing Of course we can't use this in readTree (since it must be zero dependency), but we can easily inline this hack at some point. Change-Id: I15b64a1ea69953c95dc3239ef5860623652b3089 Reviewed-on: https://cl.tvl.fyi/c/depot/+/3535 Tested-by: BuildkiteCI Reviewed-by: Profpatsch <mail@profpatsch.de> Reviewed-by: tazjin <mail@tazj.in>
104 lines
3.8 KiB
Nix
104 lines
3.8 KiB
Nix
{ depot, lib, ... }:
|
|
|
|
let
|
|
inherit (depot.nix.runTestsuite)
|
|
runTestsuite
|
|
it
|
|
assertEq
|
|
assertThrows
|
|
assertDoesNotThrow
|
|
;
|
|
|
|
inherit (depot.nix.utils)
|
|
isDirectory
|
|
realPathIsDirectory
|
|
isRegularFile
|
|
isSymlink
|
|
pathType
|
|
storePathName
|
|
;
|
|
|
|
assertUtilsPred = msg: act: exp: [
|
|
(assertDoesNotThrow "${msg} does not throw" act)
|
|
(assertEq msg (builtins.tryEval act).value exp)
|
|
];
|
|
|
|
pathPredicates = it "judges paths correctly" (lib.flatten [
|
|
# isDirectory
|
|
(assertUtilsPred "directory isDirectory"
|
|
(isDirectory ./directory) true)
|
|
(assertUtilsPred "symlink not isDirectory"
|
|
(isDirectory ./symlink-directory) false)
|
|
(assertUtilsPred "file not isDirectory"
|
|
(isDirectory ./directory/file) false)
|
|
# realPathIsDirectory
|
|
(assertUtilsPred "directory realPathIsDirectory"
|
|
(realPathIsDirectory ./directory) true)
|
|
(assertUtilsPred "symlink to directory realPathIsDirectory"
|
|
(realPathIsDirectory ./symlink-directory) true)
|
|
(assertUtilsPred "realPathIsDirectory resolves chained symlinks"
|
|
(realPathIsDirectory ./symlink-symlink-directory) true)
|
|
# isRegularFile
|
|
(assertUtilsPred "file isRegularFile"
|
|
(isRegularFile ./directory/file) true)
|
|
(assertUtilsPred "symlink not isRegularFile"
|
|
(isRegularFile ./symlink-file) false)
|
|
(assertUtilsPred "directory not isRegularFile"
|
|
(isRegularFile ./directory) false)
|
|
# isSymlink
|
|
(assertUtilsPred "symlink to file isSymlink"
|
|
(isSymlink ./symlink-file) true)
|
|
(assertUtilsPred "symlink to directory isSymlink"
|
|
(isSymlink ./symlink-directory) true)
|
|
(assertUtilsPred "symlink to symlink isSymlink"
|
|
(isSymlink ./symlink-symlink-file) true)
|
|
(assertUtilsPred "symlink to missing file isSymlink"
|
|
(isSymlink ./missing) true)
|
|
(assertUtilsPred "directory not isSymlink"
|
|
(isSymlink ./directory) false)
|
|
(assertUtilsPred "file not isSymlink"
|
|
(isSymlink ./directory/file) false)
|
|
# missing files throw
|
|
(assertThrows "isDirectory throws on missing file"
|
|
(isDirectory ./does-not-exist))
|
|
(assertThrows "realPathIsDirectory throws on missing file"
|
|
(realPathIsDirectory ./does-not-exist))
|
|
(assertThrows "isRegularFile throws on missing file"
|
|
(isRegularFile ./does-not-exist))
|
|
(assertThrows "isSymlink throws on missing file"
|
|
(isSymlink ./does-not-exist))
|
|
]);
|
|
|
|
symlinkPathTypeTests = it "correctly judges symlinks" [
|
|
(assertEq "symlinks to directories are detected correcty"
|
|
((pathType ./symlink-directory).symlink or null) "directory")
|
|
(assertEq "symlinks to symlinks to directories are detected correctly"
|
|
((pathType ./symlink-symlink-directory).symlink or null) "directory")
|
|
(assertEq "symlinks to files are detected-ish"
|
|
((pathType ./symlink-file).symlink or null) "regular-or-missing")
|
|
(assertEq "symlinks to symlinks to files are detected-ish"
|
|
((pathType ./symlink-symlink-file).symlink or null) "regular-or-missing")
|
|
(assertEq "symlinks to nowhere are not distinguished from files"
|
|
((pathType ./missing).symlink or null) "regular-or-missing")
|
|
];
|
|
|
|
cheddarStorePath =
|
|
builtins.unsafeDiscardStringContext depot.tools.cheddar.outPath;
|
|
|
|
storePathNameTests = it "correctly gets the basename of a store path" [
|
|
(assertEq "base name of a derivation"
|
|
(storePathName depot.tools.cheddar) depot.tools.cheddar.name)
|
|
(assertEq "base name of a store path string"
|
|
(storePathName cheddarStorePath) depot.tools.cheddar.name)
|
|
(assertEq "base name of a path within a store path"
|
|
(storePathName "${cheddarStorePath}/bin/cheddar") "cheddar")
|
|
(assertEq "base name of a path"
|
|
(storePathName ../default.nix) "default.nix")
|
|
];
|
|
in
|
|
|
|
runTestsuite "nix.utils" [
|
|
pathPredicates
|
|
symlinkPathTypeTests
|
|
storePathNameTests
|
|
]
|