From fdd29ff8d57db8cd79ee833ad17394b5a2e2cb4c Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Fri, 2 Aug 2024 19:33:28 -0600 Subject: [PATCH] fix: always isolate modules Previous to this fix, if `dir` was passed as a string instead of a path literal, then the isolation mechanisms provided by the implicit copy behavior of a path in string interpolation was broken, and modules could see the files in their directory. Now both cases are treated identically and isolation is preserved. `strToPath` takes a path like string and converts it back to a path literal to accomplish this. --- default.nix | 8 +++++++- std/mod.nix | 1 + std/path/mod.nix | 1 + std/path/strToPath.nix | 13 +++++++++++++ test/bld.nix | 5 ++++- 5 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 std/path/mod.nix create mode 100644 std/path/strToPath.nix diff --git a/default.nix b/default.nix index 37ab32d..19a18fa 100644 --- a/default.nix +++ b/default.nix @@ -2,6 +2,7 @@ let fix = import ./std/fix.nix; filterMap = scopedImport { std = builtins; } ./std/set/filterMap.nix; parse = scopedImport { std = builtins; } ./std/file/parse.nix; + strToPath = scopedImport { std = builtins; } ./std/path/strToPath.nix; cond = import ./std/set/cond.nix; compose = import ./.; @@ -42,8 +43,13 @@ let ); atom = fix ( - f: pre: dir: + f: pre: dir': let + # It is crucial that the directory is a path literal, not a string + # since the implicit copy to the /nix/store, which provides isolation, + # only happens for path literals. + dir = strToPath dir'; + contents = builtins.readDir dir; hasMod = contents."mod.nix" or null == "regular"; diff --git a/std/mod.nix b/std/mod.nix index 7e98ede..2427783 100644 --- a/std/mod.nix +++ b/std/mod.nix @@ -2,4 +2,5 @@ pub_fix = mod.fix; pub_file = mod.file; pub_set = mod.set; + pub_path = mod.path; } diff --git a/std/path/mod.nix b/std/path/mod.nix new file mode 100644 index 0000000..9ded5fd --- /dev/null +++ b/std/path/mod.nix @@ -0,0 +1 @@ +{ pub_strToPath = mod.strToPath; } diff --git a/std/path/strToPath.nix b/std/path/strToPath.nix new file mode 100644 index 0000000..dcfb15f --- /dev/null +++ b/std/path/strToPath.nix @@ -0,0 +1,13 @@ +str: +let + # strip off the first `/` of an absolute path + frag = std.substring 1 (-1) str; + # will fail if the string does not represent an absolute path + # which is what we want since this function makes little sense otherwise + validate = std.toPath str; + # recombine the fragment string with an absolute path starting at the root + # the result with be a path literal instead of a string + path = /. + frag; +in +# avoid the extra work if it is already a path literal +if std.isPath str then str else std.seq validate path diff --git a/test/bld.nix b/test/bld.nix index 478d522..11c1600 100644 --- a/test/bld.nix +++ b/test/bld.nix @@ -1,4 +1,7 @@ let - mod = import ../. { } ./bld; + mod = + import ../. { } + # added to test implicit path conversion when path is a string + (builtins.toPath ./bld); in builtins.deepSeq mod mod