* src/common.h: Add guess_strip flag variable.
* src/patch.c: Make '-p' and '--strip' commandline option understand 'g'
  argument.
* src/util.c (strip_leading_slashes): Eliminate the longest existent
  pathname to patch.

New option make the patch utility try to eliminate the longest existent
pathname to patch.
---
 src/common.h |  1 +
 src/patch.c  |  9 ++++++++-
 src/util.c   | 19 +++++++++++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/common.h b/src/common.h
index 53c5e3282..986f57c7a 100644
--- a/src/common.h
+++ b/src/common.h
@@ -113,6 +113,7 @@ XTERN bool reverse;
 XTERN enum { DEFAULT_VERBOSITY, SILENT, VERBOSE } verbosity;
 XTERN bool skip_rest_of_patch;
 XTERN int strippath;
+XTERN bool guess_strip;
 XTERN bool canonicalize_ws;
 XTERN int patch_get;
 XTERN bool set_time;
diff --git a/src/patch.c b/src/patch.c
index 917437095..9d1a92143 100644
--- a/src/patch.c
+++ b/src/patch.c
@@ -135,6 +135,7 @@ main (int argc, char **argv)
     buf = xmalloc (bufsize);
 
     strippath = -1;
+    guess_strip = false;
 
     val = getenv ("QUOTING_STYLE");
     {
@@ -970,7 +971,13 @@ get_some_switches (void)
                outfile = xstrdup (optarg);
                break;
            case 'p':
-               strippath = numeric_string (optarg, false, "strip count");
+               if (!strcmp(optarg, "g")) {
+                   guess_strip = true;
+                   strippath = -1;
+               } else {
+                   strippath = numeric_string (optarg, false, "strip count");
+                   guess_strip = false;
+               }
                break;
            case 'r':
                rejname = xstrdup (optarg);
diff --git a/src/util.c b/src/util.c
index 392eff19d..15a374dcf 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1422,18 +1422,37 @@ fail:
 
 /* Strip up to STRIP_LEADING leading slashes.
    If STRIP_LEADING is negative, strip all leading slashes.
+   If GUESS_STRIP is true, try to guess how many leading slashes
+   should be stripped.
    Returns a pointer into NAME on success, and NULL otherwise.
   */
 static bool
 strip_leading_slashes (char *name, int strip_leading)
 {
   int s = strip_leading;
+  int gs = 0;
   char *p, *n;
 
   for (p = n = name;  *p;  p++)
     {
       if (ISSLASH (*p))
        {
+         if (guess_strip && strip_leading == -1)
+           {
+             struct stat st;
+             /* If "n" is an existent file and is not a directory,
+                we successfully guessed strip.  */
+             if (safe_stat (n, &st) == 0 && !(st.st_mode & S_IFDIR))
+               {
+                 /* We guessed the strip value. As this value should
+                    be the same for each files being patched, assign
+                    global strippath to this value.  */
+                 strippath = gs;
+                 break;
+               }
+             gs++;
+           }
+
          while (ISSLASH (p[1]))
            p++;
          if (strip_leading < 0 || --s >= 0)
-- 
2.24.1


Reply via email to