22

Is it possible to know if a file has been patched already, before apply the patch?

I need to do this in a script, any thoughts?

20

Yep, just run patch with --dry-run option, it either would fail or succeed which can be found out with its exit status.

But in more common (and error prone) way, you probably have to run it with -R option which means "reverse" since only if it was able to revert the whole patch it could be considered as "applied". Otherwise (without '-R') it could fail just due to some parts of the original file was changed. Below is a simple example:

if ! patch -R -p0 -s -f --dry-run <patchfile; then
  patch -p0 <patchfile
fi

(Evenmore, in the snippet above you might even prefer to silence patch completely redirecting its stdout and stderr to /dev/null)

  • 1
    This does not work for me. When I run that command, if the patch has not been applied, it asks whether to 'un-reverse' the patch in interactive mode and, if I use batch mode, it will ignore the reverse operation and apply the patch, returning 0. – synack Oct 19 '17 at 20:30
  • 1
    Hey, try adding -sf to patch (can be written as patch -Rsfp0 --dry-run) – poige Oct 20 '17 at 5:31
  • 1
    @synack did it go ok? – poige Oct 26 '17 at 9:06
16

Just in case it helps someone, if you are using bash script then the example given by Omnifarious would not work. In bash the exit status of a successful command is 0

So the following would work:

patch -p0 -N --dry-run --silent < patchfile 2>/dev/null
#If the patch has not been applied then the $? which is the exit status 
#for last command would have a success status code = 0
if [ $? -eq 0 ];
then
    #apply the patch
    patch -p0 -N < patchfile
fi
  • The checking should be against 1 instead of 0: if [ $? -eq 1 ] – Crisson Dec 20 '15 at 5:46
  • 2
    No, 0 is correct. Patch would exit with non-zero if the dry-run failed for some reason, in which case the patch shouldn't be applied. – Fls'Zen Aug 10 '16 at 2:49
  • My script was correct in bash. bash considers an exit code of 0 to be true for the purposes of if. Precisely because most commands use an exit code of 0 to indicate success. – Omnifarious Oct 16 at 2:44
2

Here is a guess, assuming that you are using the patch utility and each file to be patched has its own patch:

if patch <options> -N --dry-run --silent <patchfile 2>/dev/null; then
    echo The file has not had the patch applied,
    echo and the patch will apply cleanly.
else
    echo The file may not have had the patch applied.
    echo Or maybe the patch doesn't apply to the file.
fi
  • Or, if you patched the files before and want to know, whether it touched some specific file, you can run the first patch round with the -B option, which would cause backup to be made. Then you check for existence of the backup. – peterph Nov 15 '12 at 10:12
  • 8
    Could you expand a bit on why you chose to use nohup in that if case? – zrajm Apr 17 '13 at 12:48
  • @zrajm - I can't remember why I did that. And by the time I noticed (because of an edit approval request) that it was there, it was so long ago there's no chance I'll ever recover the reason. It seems quite pointless to me looking at it now. – Omnifarious Oct 16 at 2:41
0

In my case I wanted to make that check so that running the patch command wouldn't end up with an interactive terminal asking what to do (especially for CI).

Turns out that if you only need that you can also use the --forward argument and it'll skip the patch if already applied!

0

This worked to me.

"scripts": {
    "symfony-scripts": [
        "patch -N --silent -p0 < patches/vendor/somefile.js.patch &2>/dev/null",
        "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.