go-musicfox: 4.5.7 -> 4.6.0 (#364326)
[NixPkgs.git] / pkgs / build-support / fetchpatch / default.nix
blob1b1f23b44c690b49dd79ddbf5042fdcfbb6c2754
1 # This function downloads and normalizes a patch/diff file.
2 # This is primarily useful for dynamically generated patches,
3 # such as GitHub's or cgit's, where the non-significant content parts
4 # often change with updating of git or cgit.
5 # stripLen acts as the -p parameter when applying a patch.
8   lib,
9   fetchurl,
10   patchutils,
14   relative ? null,
15   stripLen ? 0,
16   decode ? "cat", # custom command to decode patch e.g. base64 -d
17   extraPrefix ? null,
18   excludes ? [ ],
19   includes ? [ ],
20   revert ? false,
21   postFetch ? "",
22   nativeBuildInputs ? [ ],
23   ...
24 }@args:
25 let
26   args' =
27     if relative != null then
28       {
29         stripLen = 1 + lib.length (lib.splitString "/" relative) + stripLen;
30         extraPrefix = lib.optionalString (extraPrefix != null) extraPrefix;
31       }
32     else
33       {
34         inherit stripLen extraPrefix;
35       };
37 let
38   inherit (args') stripLen extraPrefix;
40 lib.throwIfNot (excludes == [ ] || includes == [ ])
41   "fetchpatch: cannot use excludes and includes simultaneously"
42   fetchurl
43   (
44     {
45       nativeBuildInputs = [ patchutils ] ++ nativeBuildInputs;
46       postFetch =
47         ''
48           tmpfile="$TMPDIR/patch"
50           if [ ! -s "$out" ]; then
51             echo "error: Fetched patch file '$out' is empty!" 1>&2
52             exit 1
53           fi
55           set +e
56           ${decode} < "$out" > "$tmpfile"
57           if [ $? -ne 0 ] || [ ! -s "$tmpfile" ]; then
58               echo 'Failed to decode patch with command "'${lib.escapeShellArg decode}'"' >&2
59               echo 'Fetched file was (limited to 128 bytes):' >&2
60               od -A x -t x1z -v -N 128 "$out" >&2
61               exit 1
62           fi
63           set -e
64           mv "$tmpfile" "$out"
66           lsdiff \
67             ${lib.optionalString (relative != null) "-p1 -i ${lib.escapeShellArg relative}/'*'"} \
68             "$out" \
69           | sort -u | sed -e 's/[*?]/\\&/g' \
70           | xargs -I{} \
71             filterdiff \
72             --include={} \
73             --strip=${toString stripLen} \
74             ${
75               lib.optionalString (extraPrefix != null) ''
76                 --addoldprefix=a/${lib.escapeShellArg extraPrefix} \
77                 --addnewprefix=b/${lib.escapeShellArg extraPrefix} \
78               ''
79             } \
80             --clean "$out" > "$tmpfile"
82           if [ ! -s "$tmpfile" ]; then
83             echo "error: Normalized patch '$tmpfile' is empty (while the fetched file was not)!" 1>&2
84             echo "Did you maybe fetch a HTML representation of a patch instead of a raw patch?" 1>&2
85             echo "Fetched file was:" 1>&2
86             cat "$out" 1>&2
87             exit 1
88           fi
90           filterdiff \
91             -p1 \
92             ${builtins.toString (builtins.map (x: "-x ${lib.escapeShellArg x}") excludes)} \
93             ${builtins.toString (builtins.map (x: "-i ${lib.escapeShellArg x}") includes)} \
94             "$tmpfile" > "$out"
96           if [ ! -s "$out" ]; then
97             echo "error: Filtered patch '$out' is empty (while the original patch file was not)!" 1>&2
98             echo "Check your includes and excludes." 1>&2
99             echo "Normalized patch file was:" 1>&2
100             cat "$tmpfile" 1>&2
101             exit 1
102           fi
103         ''
104         + lib.optionalString revert ''
105           interdiff "$out" /dev/null > "$tmpfile"
106           mv "$tmpfile" "$out"
107         ''
108         + postFetch;
109     }
110     // builtins.removeAttrs args [
111       "relative"
112       "stripLen"
113       "decode"
114       "extraPrefix"
115       "excludes"
116       "includes"
117       "revert"
118       "postFetch"
119       "nativeBuildInputs"
120     ]
121   )