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.