nix-helpers: c70b8942fa5b54da3ebc340454c039d7258931a1

     1: # A wrapper around the 'replace' command, which is simpler and saner. We used to
     2: # use a binary from MariaDB but it's now removed, and it was a heavy dependency.
     3: {
     4:   bash,
     5:   die,
     6:   fail,
     7:   mkBin,
     8:   runCommand,
     9:   nixpkgs,
    10: }:
    11: 
    12: with builtins;
    13: assert nixpkgs ? replace || die { error = "No 'replace' in given nixpkgs."; };
    14: with { delim = x: "$" + "{" + x + "}"; };
    15: mkBin {
    16:   name = "replace";
    17:   paths = [
    18:     bash
    19:     fail
    20:   ];
    21:   script = ''
    22:     #!${bash}/bin/bash
    23:     set -e
    24: 
    25:     REPLACEMENTS=()
    26:     FILES=()
    27: 
    28:     function nonEven {
    29:       fail "Non-even number of replacement strings. Found string pairs '${delim "REPLACEMENTS[*]"}' and failed with leftovers '$*'."
    30:     }
    31: 
    32:     function dodgy {
    33:       # Check for strings beginning with "-" in case 'go' treats them as flags
    34:       # FIXME: There should be a way to do this.
    35:       if [[ "x${delim "1:0:1"}" = "x-" ]]
    36:       then
    37:         return 0
    38:       else
    39:         return 1
    40:       fi
    41:     }
    42: 
    43:     # Keep popping off pairs of strings, until we run out or hit "--"
    44:     while [[ "$#" -gt 0 ]]
    45:     do
    46:       # "--" should only appear after a pair of strings, not a single string.
    47:       if [[ "x$2" = "x--" ]]
    48:       then
    49:         nonEven
    50:         exit 1 # Just in case
    51:       fi
    52: 
    53:       # If we find "--" then shift it off and break the loop; any remaining
    54:       # arguments will be treated as filenames.
    55:       if [[ "x$1" = "x--" ]]
    56:       then
    57:         shift
    58:         break
    59:       fi
    60: 
    61:       # Shouldn't have a lone replacement string, even without "--"
    62:       if [[ "$#" -lt 2 ]]
    63:       then
    64:         nonEven
    65:         exit 1 # Just in case
    66:       fi
    67: 
    68:       [[ -z "$1" ]] && fail "Can't replace empty string"
    69:       dodgy "$1" && fail "Can't replace strings ($1) beginning with '-'"
    70:       dodgy "$2" && fail "Can't insert strings ($2) beginning with '-'"
    71: 
    72:       # If we reach here we have another old/new pair of strings to replace
    73:       if [[ "${delim "#REPLACEMENTS[@]"}" -gt 0 ]]
    74:       then
    75:         REPLACEMENTS=("${delim "REPLACEMENTS[@]"}" -a "$1" "$2")
    76:       else
    77:         # First pair doesn't need "-a" flag
    78:         REPLACEMENTS=("${delim "REPLACEMENTS[@]"}"    "$1" "$2")
    79:       fi
    80:       shift
    81:       shift
    82:     done
    83: 
    84:     [[ "${delim "#REPLACEMENTS[@]"}" -gt 0 ]] || fail "No replacements given?"
    85: 
    86:     # Gather up remain args as filenames to process in-place
    87:     while [[ "$#" -gt 0 ]]
    88:     do
    89:       dodgy "$1" && fail "Spotted dodgy argument '$1' (empty or '-')"
    90:       FILES=("${delim "FILES[@]"}" "$1")
    91:       shift
    92:     done
    93: 
    94:     function go {
    95:       # Do the actual replacement. The 'replace' command does the magic, but
    96:       # we constrain its peculiar defaults:
    97:       #   -e forces case sensitivity
    98:       #   -s allows replacement anywhere, not just at "word boundaries"
    99:       #   -f forces in-place replacement,
   100:       "${nixpkgs.replace}/bin/replace-literal" -e -s "$@"
   101:     }
   102: 
   103:     if [[ "${delim "#FILES[@]"}" -eq 0 ]]
   104:     then
   105:       # No files, use stdio
   106:       go "${delim "REPLACEMENTS[@]"}"
   107:       exit 0
   108:     else
   109:       # Filenames given, replace them without backing up
   110:       go -f "${delim "REPLACEMENTS[@]"}" "${delim "FILES[@]"}"
   111:       exit 0
   112:     fi
   113:   '';
   114: }

Generated by git2html.