16

I have a build tool that runs a patch command and if the patch command returns non-zero, it will cause the build to fail. I am applying a patch that may or may not already be applied, so I use the -N option to patch, which skips as it should. However, when it does skip, patch is returning non-zero. Is there a way to force it to return 0 even if it skips applying patches? I couldn't find any such capability from the man page.

zjm555
  • 781
  • 1
  • 5
  • 14

4 Answers4

5

Accepted answer did not work for me because patch was returning 1 also on other types of errors (maybe different version or sth). So instead, in case of error I am checking output for "Skipping patch" message to ignore such but return error on other issues.

OUT="$(patch -p0 --forward < FILENAME)" || echo "${OUT}" | grep "Skipping patch" -q || (echo "$OUT" && false);
fsw
  • 3,595
  • 3
  • 20
  • 34
4

I believe that the following recipe should do the trick, it is what I am using in the same situation;

patches: $(wildcard $(SOMEWHERE)/patches/*.patch)
    for patch_file in $^; do \
        patch --strip=2 --unified --backup --forward --directory=<somewhere> --input=$$patch_file; \
        retCode=$$?; \
        [[ $$retCode -gt 1 ]] && exit $$retCode; \
    done; \
    exit 0

This recipe loops over the dependencies (in my case the patch files) and calls patch for each one. The "trick" on which I am relying is that patch returns 1 if the patch has already been applied and other higher numbers for other errors (such as a non existent patch file). The DIAGNOSTICS section of the patch manual entry describes the return code situation. YMMV

awol
  • 66
  • 3
  • 7
    This strikes me as a head-scratching deficiency in the CLI of `patch`. The reason I ran into this at all is because I have another tool than runs patch and uses its return code (0 vs. nonzero) to determine whether it succeeded or failed. Thank you for your answer, I will use this script instead of `patch` as the patch command. Still, it's just odd that they don't have a switch for this. – zjm555 Feb 27 '15 at 18:24
1

You can also do that as a one line only

patch -p0 --forward < patches/patch-babylonjs.diff || true

So if you want to apply the patch and make sure that's it's working:

(patch -p0 --forward < patches/patch-babylonjs.diff || true) && echo OK

No matter whether the patch has already been applied or not, you'll always get "OK" displayed here.

maxime1992
  • 22,502
  • 10
  • 80
  • 121
  • 4
    This will say still say `OK` if the patch hasn't already been applied and also fails to apply. – Tom Hale Dec 11 '18 at 07:20
  • 2
    But the first example works well. Exit code is 0, and if patch has already been applied it says "Reversed (or previously applied) patch detected! Skipping patch." – Lukasz Frankowski Jan 18 '19 at 16:59
1

Below is a script that iterates on the above idea from @fsw and handles removal of .rej files as necessary.

#! /bin/sh

set +x
set -euo pipefail

bn=$(basename "$0")

patch="$1"; shift

r=$(mktemp /tmp/"$bn".XXXX)

if ! out=$(patch -p1 -N -r "$r" < "$patch")
then
    echo "$out" | grep -q "Reversed (or previously applied) patch detected!  Skipping patch."
    test -s "$r" # Make sure we have rejects.
else
    test -f "$r" && ! test -s "$r" # Make sure we have no rejects.
fi

rm -f "$r"
Grigory Entin
  • 1,617
  • 18
  • 20