nix-helpers: 7088ca92cb14775b21217c274acb49fbca96e915

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

Generated by git2html.