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.