2

I have a directory contains several files to be modified. Instead of doing changes manually(because there are so many files) i downloaded a diff file(made by some other user), this diff file is executed by a .bat file.

let me make it more systematic.

  1. bat file is WinDDK_7600.16385.1_patch.bat and path of this file is(C:\Users\kunze\Documents\Visual Studio 2010\Projects\busmaster-master\Documents\1 Development Environment\files)

contents of this file are

@echo on

set PATH=%PATH%;%ProgramFiles%\Git\bin

patch -p1 -d C:/ < WinDDK_7600.16385.1.diff

pause
  1. When i run bat file this will run WinDDK_7600.16385.1.diff and this difference file has changes for many fileslocated in C:\WinDDK. Path of this file is C:\Users\kunze\Documents\Visual Studio 2010\Projects\busmaster-master\Documents\1 Development Environment\files

  2. Files for which differences need to be updated are located in this directory C:\WinDDK

  3. I already have set path environment variable for git/bin

  4. Can someone please let me know what changes should i made in my WinDDK_7600.16385.1_patch.bat file so that it will find and update all the files located in C:\WinDDK directory

I have tried several times and every time i am getting this error "Assertion failed: hunk, file ../patch-2.5.9-src/patch.c, line 354" ? whats the issue ?

kostix
  • 51,517
  • 14
  • 93
  • 176
User
  • 619
  • 1
  • 9
  • 24

4 Answers4

7

.diff files, the patch tool and their relevance to Git

First of all, this problem has nothing to do with Git. Git for Windows, which you supposedly have installed on your computer, just happens to be shipped with the Windows port of patcha program to apply changes described by specially-formatted files. Specifically, GfW includes the GNU patch program.

The patch.exe program supplied with GfW is located under %ProgramFiles%\Git\bin (unless you've overriden the installation location).

What does a .diff file contain and how patch works

The patch file format

To cite the Wikipedia article linked above, a diff file looks like this:

--- /path/to/original   ''timestamp''
+++ /path/to/new    ''timestamp''
@@ -1,3 +1,9 @@
+This is an important
+notice! It should
+therefore be located at
+the beginning of this
+document!
+
 This part of the
 document has stayed the
 same from version to
@@ -5,16 +11,10 @@
 be shown if it doesn't
 change.  Otherwise, that
 would not be helping to
-compress the size of the
-changes.
-
-This paragraph contains
-text that is outdated.
-It will be deleted in the
-near future.
+compress anything.

 It is important to spell
-check this dokument. On
+check this document. On
 the other hand, a
 misspelled word isn't
 the end of the world.

Here's what we have here:

  • First are the two lines of the header which describe which file was original and which one was "new" when the diff file was generated based on them—the differences are in the "new" file compared to the "original" one.
  • The @@ ... @@ blocks delimit "hunks" which describe where in the original file the piece to change by this hunk is located, how many lines it originally contained and how many it will contain after patching.

    The next (and most important) thing about the hunk is change markers: + denote added lines, - denote deleted lines while lines prefixed with (a single space character) do not change and provide context for the patch tool to be able to perform "fuzzy matching"—based not only on line count but on actual file content as well.

How the patch tool works

The patch tool takes the .diff file and

  1. Reads it up until the first header, parses the header, extracts the name of the file to patch from it.
  2. Locates the file with the name obtained on step (1) in the target directory.
  3. Reads the first hunk, locates it in the file it found, and applies the patch from the hunk.

    If patching the hunk fails, patch creates a special "rejects" file (by combining the tail name of the file it attempted to patch plus the .rej extension) and writes there the failed hunk.

  4. Goes to the next hunk and repeats until the end of the patch file is hit of the new header is found.

    If the next header is found, it repeats the steps starting from (2), otherwise it exits.

How the patch tool locates the files to patch

Most often, headers in patch files contain relative pathnames (like foo/bar/baz.c) and the patch tool goes like this:

  1. Extracts that name from the header.
  2. Takes the tool's current directory and appends that pathname onto it to get the name of the file to patch.

Two command-line options affect the patch tool's behaviour:

  • The -d <dir> option tell it to change its current directory to <dir> before doing its work.
  • The -p N option tell it to trim N path components off the pathname extracted from the header before further considering it.

    This means that with -p1 passed to it, patch would convert foo/bar/baz.c to bar/baz.c before trying to locate that file.

By now, you should be able to fully understand what your batch file does, and I ask you to work this out to stop considering all this the black voodoo.

"Assertion failed" error from the patch tool

My guess is that you've hit an unfortunate bug which occasionally manifests itself in various Windows ports of patch—a problem with EOL markers: the tool simply chokes on CR&plus;LF sequences.

Possible ways to work around this:

  • Try git apply as explained here—Git does not use patch.exe but rather its own machinery which is taught by GfW porters to work okay with Windows EOLs.
  • Try other ports of patch, for instance this one from the GnuWin32 project.

    Note that you might hit some UAC problem with it; here is how to fix it.

Community
  • 1
  • 1
kostix
  • 51,517
  • 14
  • 93
  • 176
  • Just a note that I am experiencing the same issue and am already using GnuWin32, so this is not a solution. The line number referenced by OP is the same as mine, suggesting he's already using GnuWin32 too and this is where the problem is coming from. – SikoSoft Sep 05 '17 at 08:57
  • @Lev I then wonder if it's possible for you to research this further to see if it's possible (say, through modifying `PATH` in a running shell) to make `patch.exe` bundled with GfW being picked up rather than that from MinGW? – kostix Sep 05 '17 at 10:14
  • Other workaround: unix2dos on the .patch file, then patch from GnuWin32 project works perfectly ;) – Ablia Oct 27 '21 at 08:14
4

You need to convert the EOL-marker of the diff file(s) to match your OS platform.

If you are using Linux, you can use the tool dos2unix file_name.diff

On Windows you can use notepad++:

  • Load the file in notepad++
  • Edit->EOL Conversion -> Windows Format
langlauf.io
  • 3,009
  • 2
  • 28
  • 45
  • 1
    Bless you for this post. Wasted 2 weeks in attempting to patch a SDK from Dialog and faced countless issues. The latest one was the Assertion error as per the OP. The notepad++ trick works like a champ! Thank you thank you thank you. – mon2 Dec 01 '20 at 17:13
0

Everything was correct except a small problem. Actually a patch command works fine on linux OS but on Winows one must have a patch file only in txt format i.e should be WinDDK_7600.16385.1.txt instead of WinDDK_7600.16385.1.diff.

And also go through the answer of @kistix and try his recommendation, if my solution dosent work, he explained things nicely.

User
  • 619
  • 1
  • 9
  • 24
  • Note that you have a sort of confusion here (an easily to solve one, happily). There's no "txt format" as opposed to "diff format" -- a patch (or diff) file is just [plain text](http://en.wikipedia.org/wiki/Plain_text) so it's already "in txt format", by definition. The extension used in a file's name has nothing to do with its content (and hence format). – kostix Jun 04 '14 at 16:29
  • 2
    The change in behaviour you've observed while "converting the format" -- by saving it "as a text file" -- most probably was EOL-marker conversion performed by the program you have used for this: the `.diff` file given to you supposedly contained "Unix line endings (sole LFs), and the text editor you've used to save the file "as text" converted them to Windows-style line endings (CR+LFs) behind your back, and `patch` stopped crashing while parsing it. – kostix Jun 04 '14 at 16:31
0

The explanation, and the --binary option that avoids the assertion failure, are documented at http://gnuwin32.sourceforge.net/packages/patch.htm

Interestingly, I found that the --verbose option also avoided the assertion failure. I don't know why.

The gnuwin32 patch.exe 2.5.9-7 [1] produces that assertion failure. This

patch -p 1 -u < mypatch.patch

reports

patching file CalibrationTools/Hashes.xml
Assertion failed: hunk, file ../patch-2.5.9-src/patch.c, line 354

BUT if I add the --verbose option, the patch is successful. This

patch -p 1 -u --verbose < mypatch.patch

reports

Hmm...  Looks like a unified diff to me...
  ...
patching file CalibrationTools/Hashes.xml using Plan A...
Hunk #1 succeeded at 4.

This observed on Windows 10.

John

[1] from patch-2.5.9-7-bin.zip (dated 15 years ago!), from https://sourceforge.net/projects/gnuwin32/files/patch/2.5.9-7/

ruck
  • 21
  • 3