python311Packages.moto: 4.2.6 -> 4.2.10
[NixPkgs.git] / pkgs / build-support / fetchpatch / default.nix
bloba3ca6685147d361fb8324196f8340b9d639f0f26
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.
7 { lib, fetchurl, patchutils }:
9 { relative ? null
10 , stripLen ? 0
11 , decode ? "cat" # custom command to decode patch e.g. base64 -d
12 , extraPrefix ? null
13 , excludes ? []
14 , includes ? []
15 , revert ? false
16 , postFetch ? ""
17 , ...
18 }@args:
19 let
20   args' = if relative != null then {
21     stripLen = 1 + lib.length (lib.splitString "/" relative) + stripLen;
22     extraPrefix = lib.optionalString (extraPrefix != null) extraPrefix;
23   } else {
24     inherit stripLen extraPrefix;
25   };
26 in let
27   inherit (args') stripLen extraPrefix;
29 lib.throwIfNot (excludes == [] || includes == [])
30   "fetchpatch: cannot use excludes and includes simultaneously"
31 fetchurl ({
32   postFetch = ''
33     tmpfile="$TMPDIR/patch"
35     if [ ! -s "$out" ]; then
36       echo "error: Fetched patch file '$out' is empty!" 1>&2
37       exit 1
38     fi
40     set +e
41     ${decode} < "$out" > "$tmpfile"
42     if [ $? -ne 0 ] || [ ! -s "$tmpfile" ]; then
43         echo 'Failed to decode patch with command "'${lib.escapeShellArg decode}'"' >&2
44         echo 'Fetched file was (limited to 128 bytes):' >&2
45         od -A x -t x1z -v -N 128 "$out" >&2
46         exit 1
47     fi
48     set -e
49     mv "$tmpfile" "$out"
51     "${patchutils}/bin/lsdiff" \
52       ${lib.optionalString (relative != null) "-p1 -i ${lib.escapeShellArg relative}/'*'"} \
53       "$out" \
54     | sort -u | sed -e 's/[*?]/\\&/g' \
55     | xargs -I{} \
56       "${patchutils}/bin/filterdiff" \
57       --include={} \
58       --strip=${toString stripLen} \
59       ${lib.optionalString (extraPrefix != null) ''
60           --addoldprefix=a/${lib.escapeShellArg extraPrefix} \
61           --addnewprefix=b/${lib.escapeShellArg extraPrefix} \
62       ''} \
63       --clean "$out" > "$tmpfile"
65     if [ ! -s "$tmpfile" ]; then
66       echo "error: Normalized patch '$tmpfile' is empty (while the fetched file was not)!" 1>&2
67       echo "Did you maybe fetch a HTML representation of a patch instead of a raw patch?" 1>&2
68       echo "Fetched file was:" 1>&2
69       cat "$out" 1>&2
70       exit 1
71     fi
73     ${patchutils}/bin/filterdiff \
74       -p1 \
75       ${builtins.toString (builtins.map (x: "-x ${lib.escapeShellArg x}") excludes)} \
76       ${builtins.toString (builtins.map (x: "-i ${lib.escapeShellArg x}") includes)} \
77       "$tmpfile" > "$out"
79     if [ ! -s "$out" ]; then
80       echo "error: Filtered patch '$out' is empty (while the original patch file was not)!" 1>&2
81       echo "Check your includes and excludes." 1>&2
82       echo "Normalized patch file was:" 1>&2
83       cat "$tmpfile" 1>&2
84       exit 1
85     fi
86   '' + lib.optionalString revert ''
87     ${patchutils}/bin/interdiff "$out" /dev/null > "$tmpfile"
88     mv "$tmpfile" "$out"
89   '' + postFetch;
90 } // builtins.removeAttrs args [
91   "relative" "stripLen" "decode" "extraPrefix" "excludes" "includes" "revert"
92   "postFetch"