Code

Merge branch 'js/apply-root'
authorJunio C Hamano <gitster@pobox.com>
Wed, 9 Jul 2008 23:58:21 +0000 (16:58 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 9 Jul 2008 23:58:21 +0000 (16:58 -0700)
* js/apply-root:
  git-apply --directory: make --root more similar to GNU diff
  apply --root: thinkofix.
  Teach "git apply" to prepend a prefix with "--root=<root>"

Documentation/git-apply.txt
builtin-apply.c
t/t4128-apply-root.sh [new file with mode: 0755]

index e9f724b2fa35cf18978dbcba9dcef7ed28a1b19d..feb51f124ac8a806e65d41f6274c58de64d2991f 100644 (file)
@@ -14,7 +14,7 @@ SYNOPSIS
          [--allow-binary-replacement | --binary] [--reject] [-z]
          [-pNUM] [-CNUM] [--inaccurate-eof] [--recount] [--cached]
          [--whitespace=<nowarn|warn|fix|error|error-all>]
-         [--exclude=PATH] [--verbose] [<patch>...]
+         [--exclude=PATH] [--directory=<root>] [--verbose] [<patch>...]
 
 DESCRIPTION
 -----------
@@ -182,6 +182,14 @@ behavior:
        by inspecting the patch (e.g. after editing the patch without
        adjusting the hunk headers appropriately).
 
+--directory=<root>::
+       Prepend <root> to all filenames.  If a "-p" argument was passed, too,
+       it is applied before prepending the new root.
++
+For example, a patch that talks about updating `a/git-gui.sh` to `b/git-gui.sh`
+can be applied to the file in the working tree `modules/git-gui/git-gui.sh` by
+running `git apply --directory=modules/git-gui`.
+
 Configuration
 -------------
 
index c0f867daed351d4b32f871941e14773a44508eaf..b3fc290ff33e6388b25b6cb046ad97856d81169d 100644 (file)
@@ -58,6 +58,8 @@ static int whitespace_error;
 static int squelch_whitespace_errors = 5;
 static int applied_after_fixing_ws;
 static const char *patch_input_file;
+static const char *root;
+static int root_len;
 
 static void parse_whitespace_option(const char *option)
 {
@@ -340,6 +342,8 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
                                 */
                                strbuf_remove(&name, 0, cp - name.buf);
                                free(def);
+                               if (root)
+                                       strbuf_insert(&name, 0, root, root_len);
                                return strbuf_detach(&name, NULL);
                        }
                }
@@ -378,6 +382,14 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
                free(def);
        }
 
+       if (root) {
+               char *ret = xmalloc(root_len + len + 1);
+               strcpy(ret, root);
+               memcpy(ret + root_len, start, len);
+               ret[root_len + len] = '\0';
+               return ret;
+       }
+
        return xmemdupz(start, len);
 }
 
@@ -3240,6 +3252,18 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
                        options |= RECOUNT;
                        continue;
                }
+               if (!prefixcmp(arg, "--directory=")) {
+                       arg += strlen("--directory=");
+                       root_len = strlen(arg);
+                       if (root_len && arg[root_len - 1] != '/') {
+                               char *new_root;
+                               root = new_root = xmalloc(root_len + 2);
+                               strcpy(new_root, arg);
+                               strcpy(new_root + root_len++, "/");
+                       } else
+                               root = arg;
+                       continue;
+               }
                if (0 < prefix_length)
                        arg = prefix_filename(prefix, prefix_length, arg);
 
diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh
new file mode 100755 (executable)
index 0000000..2dd0c75
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+test_description='apply same filename'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+       mkdir -p some/sub/dir &&
+       echo Hello > some/sub/dir/file &&
+       git add some/sub/dir/file &&
+       git commit -m initial &&
+       git tag initial
+
+'
+
+cat > patch << EOF
+diff a/bla/blub/dir/file b/bla/blub/dir/file
+--- a/bla/blub/dir/file
++++ b/bla/blub/dir/file
+@@ -1,1 +1,1 @@
+-Hello
++Bello
+EOF
+
+test_expect_success 'apply --directory -p (1)' '
+
+       git apply --directory=some/sub -p3 --index patch &&
+       test Bello = $(git show :some/sub/dir/file) &&
+       test Bello = $(cat some/sub/dir/file)
+
+'
+
+test_expect_success 'apply --directory -p (2) ' '
+
+       git reset --hard initial &&
+       git apply --directory=some/sub/ -p3 --index patch &&
+       test Bello = $(git show :some/sub/dir/file) &&
+       test Bello = $(cat some/sub/dir/file)
+
+'
+
+test_done