nix-helpers: 3985aa5ad766223caebe5c131099a87c8955e511
1: # Turns a list of Nix expressions into an attrset suitable for use in
2: # derivations, WITHOUT forcing anything to be built at eval time. Also provides
3: # a snippet of bash code to splice into scripts, which turns these env vars into
4: # a proper bash array.
5: #
6: # For example, if we did:
7: #
8: # nixListToBashArray { name = "x"; args = [ "bar", "baz", <derivation..> ]; }
9: #
10: # We will get back an 'env' attrset like this:
11: #
12: # { x1 = "bar"; x2 = "baz"; x3 = <derivation...>; }
13: #
14: # Note that the derivation hasn't been forced; if we append this set to a build
15: # environment, it will be treated like any other dependency. We also get a
16: # 'code' snippet, which will loop over these distinct variables to construct a
17: # single array (in this case, called "x")
18:
19: # Take lib from nixpkgs1609, since other versions (e.g. 1603) mess up escaping
20: { nothing, pinnedNixpkgs, runCmd }:
21:
22: with builtins;
23: with pinnedNixpkgs.nixpkgs1609.lib;
24: with rec {
25: # This is the actual implementation
26: go = { args, name }: rec {
27: # Store each arg in a separate variable, named numerically
28: env = with foldl' (result: arg: {
29: # Increment the count, for the next arg (if any)
30: count = result.count + 1;
31:
32: # Append a variable to the environment for this arg
33: vars = result.vars // { "${name}${toString result.count}" = arg; };
34: })
35: # Start with variable 1 in an empty environment
36: {
37: count = 1;
38: vars = { };
39: } args;
40: vars;
41:
42: code = ''
43: ### Auto-generated by nixListToBashArray
44: ${name}=()
45:
46: for N in $(seq 1 "${toString (length args)}")
47: do
48: # Use a "variable variable" to look up "$name$N" as a variable name
49: NIXLISTTOBASHARRAYTEMP="${name}$N"
50: ${name}=("''${${name}[@]}" "''${!NIXLISTTOBASHARRAYTEMP}")
51: unset NIXLISTTOBASHARRAYTEMP
52: done
53: ### End of auto-generated code
54: '';
55: };
56:
57: ## Tests follow
58:
59: checkArgsAreNotForced = with go {
60: name = "checkNotForced";
61: args = [ (abort "NLTBA shouldn't have forced") ];
62: };
63: # Force the code to be generated, and hence the content of any splices
64: (stringLength code > 0 || abort "No code generated") &&
65:
66: # Force the environment "spine"/structure to be generated
67: (length (attrValues env) == 1 || abort "Wrong number of vars") &&
68:
69: # Force the variable names (but not values!) to be generated
70: (attrNames env == [ "checkNotForced1" ] || abort "Wrong var name");
71:
72: checkWeGetTheRightValues =
73: with { mixture = ''mixture "of 'special" $characters''; };
74: with go {
75: name = "foo";
76: args = [ "simple" "single 'quoted'" ''double "quoted"'' mixture nothing ];
77: };
78: with rec {
79: context = env;
80:
81: check = runCmd "check-NLTBA.nix" context ''
82: function fail() {
83: echo -e "$*" 1>&2
84: exit 1
85: }
86:
87: function match() {
88: [[ "x$2" = "x$3" ]] || fail "Wrong $1 value '$2' (should be '$3')"
89: }
90:
91: match foo1 "$foo1" "simple"
92: match foo2 "$foo2" "single 'quoted'"
93: match foo3 "$foo3" 'double "quoted"'
94: match foo4 "$foo4" ${escapeShellArg mixture}
95:
96: [[ -d "$foo5" ]] || fail "foo5 should have been dir, got '$foo5'"
97:
98: ${code}
99:
100: [[ -n "$foo" ]] || fail "Didn't get foo: '$foo'"
101:
102: FOUND=0
103: for VAL in "''${foo[@]}"
104: do
105: FOUND=$(( FOUND + 1 ))
106: done
107: [[ "$FOUND" -eq 5 ]] || fail "foo has '$FOUND' elements"
108:
109: match 'foo[0]' "''${foo[0]}" "simple"
110: match 'foo[1]' "''${foo[1]}" "single 'quoted'"
111: match 'foo[2]' "''${foo[2]}" 'double "quoted"'
112: match 'foo[3]' "''${foo[3]}" ${escapeShellArg mixture}
113:
114: [[ -d "''${foo[4]}" ]] || fail "foo[4] should be dir, got: ''${foo[4]}"
115:
116: echo true > "$out"
117: '';
118: };
119: import check;
120: };
121:
122: assert checkArgsAreNotForced;
123: assert checkWeGetTheRightValues;
124: go
Generated by git2html.