0

I'm going to be applying about 305 patches, and I know that there will be a great many "rejects."

Before I do this, I'd like to know what patch will do if a .rej file already exists, as I fully expect that it will be.

My alternative is to use --merge, which creates the <<<...>>> tags that are so-familiar to git users. (Heh ...) But in this case I'm afraid that the presence of those tags, if there were many of them, might interfere with future patching.

(Any opinions as to which one might be best?)

I basically plan to "apply the patches, in a for-loop, let them do the best they can, and then clean-up." (It promises to be a delightful afternoon.) I know that I will be doing this step very manually and I do not yet know how many .rej files there might be. (I can already see that there will be well over 100, however.)

War-stories welcomed.

Mike Robinson
  • 8,490
  • 5
  • 28
  • 41

2 Answers2

1

patch simply overwrites the existing .rej file. But you can send rejects into the file of your choice using the -r option:

-r rejectfile or --reject-file=rejectfile

Put rejects into rejectfile instead of the default .rej file. When rejectfile is -, discard rejects.

Note that in this case rejected hunks for different files are all put into the same file in unified diff format.

Thus, you can write your loop to use a different reject file on each iteration:

for p in patch*
do
    patch -p0 -r "$p".rej <"$p" 
done

However, my advice is to stop the patching process as soon as even a single hunk is rejected and resolve the conflict before continuing. You can code that logic in your patching loop similar to the following:

apply_patches

#!/bin/bash

for p in "$@"
do
    echo
    echo "----------- Applying patch $p ------------"
    rejectfile="$p".rej
    patch -p0 -r "$rejectfile" <"$p"
    if [ -s "$rejectfile" ]
    then
        echo
        echo "Some hunks could not be applied (see $rejectfile)"
        read -p "Please address them and then press ENTER "
    fi
done
Leon
  • 31,443
  • 4
  • 72
  • 97
  • *Ick.* **O_o ...** But, *aye,* I agree with ye. And, thank you *(upvoted ...)* that is what I will now do. I did some experiments with `--dry-run` to predict how many of the patches will apply cleanly and how many will fail. – Mike Robinson Jul 14 '16 at 18:32
  • I also see it documented that the *return-code* from `patch` is a reliable indicator: the usual "zero equals success." I considered using the `--merge` option so that the differences would be "right there, `git`-style, in the file(s)." Any opinions on that? I'm not quite sure *how* to "resolve a `.rej` file" other than by pure-manual examination of its contents . . . *(Edit:* Googled-upon "http://stackoverflow.com/questions/542895/how-to-read-rej-files-i-e" in StackOverflow. Comments requested. *("3-way merge?")* – Mike Robinson Jul 14 '16 at 18:34
  • *Meh ...* Most of the Google responses say, "you have to manually look at the contents of the `.rej` file and resolve it with an editor. *Well, if that's what I must do ...* – Mike Robinson Jul 14 '16 at 18:38
  • Excellent explanation of 3-way merge here (on SO, of course): http://stackoverflow.com/questions/4129049/why-is-a-3-way-merge-advantageous-over-a-2-way-merge ... *(See especially 2nd answer.)* – Mike Robinson Jul 14 '16 at 18:44
0

To now document how this effort turned out:

Yes, patch does overwrite .rej files, and Leon's suggested script was my very fine starting point. However, I found that the content of the .rej file was essentially useless to me. Re-reading the patch documentation (on Linux, but not(!) on Macintosh OS/X!), I saw that there was a --merge option available which would produce the <<<< ==== >>>> modifications to the file (as git routinely does ...)

I used the git format-patch command to obtain the list of commits as individual patch files, and modified Leon's original script to loop through the contents of that directory.

Instead of using the -r option, as Leon suggested, I used the --merge option. Since there would now be no reject-file to test for, I changed the script to use the exit-code ("$?") of the patch command, instead. (As usual, "zero equals success.")

If the patch command succeeded (returned zero ...), my script would mv the patch-file into another directory of "patches applied." If not, it would print a message and stop. I resolved each such occurrence in the following way:

  • One by one, notice which of the files in the patch had errors. Open each of these files and search for the <<<<< tag. In this way I could see the two alternatives side-by-side, and, case-by-case, I made an individual choice and manual correction.

  • Then, mv the patch-file to the "patches applied" directory, just as the script would have done had the patch been entirely applied without error.

  • Scan the (PHP ...) source-directory for any syntax errors, using a custom tool of my devising. Immediately(!) resolve any issues found.

  • git commit the changes ... just in case!

  • Start the script again ...

And now, an interesting issue . . .

Now, as I said in the original post, I was applying these (hundreds of ...) patches to a source-code base that had been textually copied from it for many months' time. (At the time of the split, a git repository didn't even exist. The company was still using SVN.) So, patch almost-never was able to rely on line-numbers.

In every case, patch did find thought that it had found the correct place to apply each patch, at some "offset" from the line-number listed in the patch. Nevertheless, I found in some cases that patch had not(!) correctly identified everything. Sometimes, it flagged an "insertion" in front of an identical piece of existing code, where a human being would recognize that it was not an insertion at all.

I am, of course, at this moment "anxiously hoping" that in each case patch did "recognize its own uncertainty," and that therefore none of the "successfully applied" patches (about two-thirds of them, as it turns out ...) will prove to have duplication issues. (This is one of the primary reasons why we constantly checked for syntax-errors anywhere in the code base, and, as it happens, almost never found any.)

Mike Robinson
  • 8,490
  • 5
  • 28
  • 41