views:

233

answers:

1

G'day,

Edit: Just thought I'd mention that this somewhat long question is now fixed thanks to Adam Goode's answer below if you're just skimming while passing through.

I've been given a patch to add to Apache 2.2.14 and one unified diff is not patching the file at all. I'm using GNU patch 2.5.4.

I have to ignore whitespace because the original patch wasn't made well, i.e. many of the diffs are seemingly for tab -> spaces conversions. These sorts of diffs are even less useful because the patch file has been modified somewhere along the delivery chain, e.g. svn repository, Jira system, web interface, etc., so that all tabs have been converted to spaces anyway!

The command I am using on Solaris 10 is:

/usr/bin/gpatch --verbose --ignore-whitespace -p1 -d . \
    <mod_cache.diff

and the output is:

...

Hmm...  The next patch looks like a unified diff to me...
The text leading up to this was:
--------------------------
|Index: httpd/modules/cache/mod_cache.h
|===================================================================
|--- httpd/modules/cache/mod_cache.h
|+++ httpd/modules/cache/mod_cache.h
--------------------------
Patching file modules/cache/mod_cache.h using Plan A...
Hunk #1 succeeded at 24.
Hunk #2 succeeded at 86.
Hunk #3 succeeded at 138.
Hunk #4 succeeded at 163.
Hunk #5 succeeded at 184.
Hunk #6 succeeded at 217.
Hunk #7 succeeded at 271.
Hunk #8 succeeded at 380.

...

Notice the

Hunk #2 succeeded at 86.

line.

The patch file contains several unified diffs but the relevant diff is:

...

Index: httpd/modules/cache/mod_cache.h
===================================================================
--- httpd/modules/cache/mod_cache.h
+++ httpd/modules/cache/mod_cache.h
@@ -86,9 +86,13 @@
 #define DEFAULT_CACHE_MAXEXPIRE MSEC_ONE_DAY
 #define DEFAULT_CACHE_EXPIRE    MSEC_ONE_HR
 #define DEFAULT_CACHE_LMFACTOR  (0.1)
+#define DEFAULT_CACHE_MAXAGE    5
+#define DEFAULT_CACHE_LOCKPATH "/mod_cache-lock"
+#define CACHE_LOCKNAME_KEY "mod_cache-lockname"
+#define CACHE_LOCKFILE_KEY "mod_cache-lockfile"

-/* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
- * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
+/* Create a set of CACHE_DECLARE(type), CACHE_DECLARE_NONSTD(type) and
+ * CACHE_DECLARE_DATA with appropriate export and import tags for the platform
  */
 #if !defined(WIN32)
 #define CACHE_DECLARE(type)            type

...

and the relevant part of the source, after applying the patch (supposedly), with some added context, is:

...

#define MSEC_ONE_DAY    ((apr_time_t)(86400*APR_USEC_PER_SEC)) /* one day, in microseconds */
#define MSEC_ONE_HR     ((apr_time_t)(3600*APR_USEC_PER_SEC))  /* one hour, in microseconds */
#define MSEC_ONE_MIN    ((apr_time_t)(60*APR_USEC_PER_SEC))    /* one minute, in microseconds */
#define MSEC_ONE_SEC    ((apr_time_t)(APR_USEC_PER_SEC))       /* one second, in microseconds */
#define DEFAULT_CACHE_MAXEXPIRE MSEC_ONE_DAY
#define DEFAULT_CACHE_EXPIRE    MSEC_ONE_HR
#define DEFAULT_CACHE_LMFACTOR  (0.1)

/* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and 
 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
 */
#if !defined(WIN32)
#define CACHE_DECLARE(type)            type
#define CACHE_DECLARE_NONSTD(type)     type
#define CACHE_DECLARE_DATA
#elif defined(CACHE_DECLARE_STATIC)

...

All other patches seem to have either been successfully applied or ignored.

Any ideas why this particular diff isn't taking?

Edit: After reducing the patch fuzz factor down to zero as recommended by Adam below, the patch has worked successfully.

Thanks to Adam Goode, if I could give you another vote up for the answer I would! Here's the relevant paragraph for fuzz in the GNU diffutils manual if you're interested.

Edit 2: BTW There's this highly relevant caveat at the bottom of that fuzz paragraph:

patch usually produces the correct results, even when it must make many guesses. However, the results are guaranteed only when the patch is applied to an exact copy of the file that the patch was generated from.

Unfortunately, in this case, I can't be sure that their mod_cache.h is the same as the official 2.2.14 mod_cache,h! )-:

+6  A: 

When you use --ignore-whitespace and don't use --fuzz=0, you are basically telling patch that it should do a best-effort patch, instead of failing completely. Because it is best effort, there is really no way to assure that it will work perfectly. For this reason, git and Fedora RPM set --fuzz=0 by default so that these types of problems fail at patch time (instead of compile- or run-time).

If you want to preserve your files as upstream-tarball + patches, you should redo the patch and make sure it can apply with --fuzz=0.

Adam Goode
@Adam, thanks for the answer. +1! Unfortunately I don't have control over the generation of the patch. And even worse, the people creating the patch are using what they *think* is Apache v2.2.14 as a baseline by applying a series of patches themselves on an independently maintained source tree! Looks like they've been doing this since 2.2.9. They don't seem to want to make sure that they're in step with the Apache org reference. )-:
Rob Wells