nix-helpers: d6fd1b6e411c9f625d63e4da7da862f5647faf30
1: # Adding files to the Nix store in a general way turns out to be quite tricky.
2: # In particular:
3: # - Filenames with certain characters (e.g. " " or "'") will cause an error
4: # if we try adding them as-is. We can work around this using builtins.path.
5: # - Paths which reference things in the Nix store can cause errors when used
6: # with functions like builtins.path.
7: # - We can use builtins.unsafeDiscardStringContext to avoid errors, but we
8: # must ensure that the context is added back in so that dependencies are
9: # are built when needed and not garbage collected from under us.
10: {
11: asPath,
12: hello,
13: lib,
14: runCommand,
15: sanitiseName,
16: writeScript,
17: }:
18:
19: with builtins;
20: with lib;
21: p:
22: with rec {
23: strP = unsafeDiscardStringContext (toString p);
24:
25: # Checks whether a path is from the Nix store, since Nix will abort if
26: # store paths are referenced in certain ways.
27: isStore = x: hasPrefix storeDir (toString x);
28:
29: # Chops suffices off a store path until it's a top-level entry, e.g.
30: # getRoot "/nix/store/...-foo/bar/baz" -> "/nix/store/...-foo"
31: # This way we're guaranteed to avoid filename characters which aren't
32: # valid store paths.
33: getRoot =
34: x: if toString (dirOf x) == toString storeDir then x else getRoot (dirOf x);
35:
36: # Complements getRoot:
37: # p = "/nix/store/...-foo/bar/baz" -> trunk = "bar/baz"
38: trunk = removePrefix "/" (removePrefix (getRoot strP) strP);
39:
40: # Avoids characters which are incompatible with store paths
41: safeName = sanitiseName (baseNameOf strP);
42:
43: # For store paths, we make a symlink which depends on p's context. By
44: # using the root we avoid incompatible characters, without using
45: # builtins.path (which Nix complains about if we give it a store path).
46: symlink =
47: runCommand safeName
48: {
49: inherit trunk;
50: root = toString (asPath (getRoot p));
51: }
52: ''
53: ${if isString p then addContextFrom p "" else ""}
54: if [[ -z "$trunk" ]]
55: then
56: ln -s "$root" "$out"
57: else
58: ln -s "$root/$trunk" "$out"
59: fi
60: '';
61: };
62: if isStore p then
63: symlink
64: else
65: builtins.path {
66: name = safeName;
67: path = p;
68: }
Generated by git2html.