about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2014-09-09 12:53:58 -0700
committerJunio C Hamano <gitster@pobox.com>2014-09-09 12:53:58 -0700
commitead51a75d5ca432daa7429b70d363dba0cdf6507 (patch)
tree852b67645fe3e0b97daa72634dc9ab18533fb631
parent93424a0fd882a3ed1c1f7a8b6fe71fdaa21cce99 (diff)
parent477a08af04c227064860ce99197c501037f7f39c (diff)
downloadgit-svn-ead51a75d5ca432daa7429b70d363dba0cdf6507.tar.gz
Applying a patch not generated by Git in a subdirectory used to
check the whitespace breakage using the attributes for incorrect
paths. Also whitespace checks were performed even for paths
excluded via "git apply --exclude=<path>" mechanism.

* jc/apply-ws-prefix:
  apply: omit ws check for excluded paths
  apply: hoist use_patch() helper for path exclusion up
  apply: use the right attribute for paths in non-Git patches
-rw-r--r--builtin/apply.c131
-rwxr-xr-xt/t4119-apply-config.sh17
-rwxr-xr-xt/t4124-apply-ws-rule.sh11
3 files changed, 96 insertions, 63 deletions
diff --git a/builtin/apply.c b/builtin/apply.c
index be2b4ce2fd..6b7c764918 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -1920,6 +1920,66 @@ static int parse_binary(char *buffer, unsigned long size, struct patch *patch)
         return used;
 }
 
+static void prefix_one(char **name)
+{
+        char *old_name = *name;
+        if (!old_name)
+                return;
+        *name = xstrdup(prefix_filename(prefix, prefix_length, *name));
+        free(old_name);
+}
+
+static void prefix_patch(struct patch *p)
+{
+        if (!prefix || p->is_toplevel_relative)
+                return;
+        prefix_one(&p->new_name);
+        prefix_one(&p->old_name);
+}
+
+/*
+ * include/exclude
+ */
+
+static struct string_list limit_by_name;
+static int has_include;
+static void add_name_limit(const char *name, int exclude)
+{
+        struct string_list_item *it;
+
+        it = string_list_append(&limit_by_name, name);
+        it->util = exclude ? NULL : (void *) 1;
+}
+
+static int use_patch(struct patch *p)
+{
+        const char *pathname = p->new_name ? p->new_name : p->old_name;
+        int i;
+
+        /* Paths outside are not touched regardless of "--include" */
+        if (0 < prefix_length) {
+                int pathlen = strlen(pathname);
+                if (pathlen <= prefix_length ||
+                    memcmp(prefix, pathname, prefix_length))
+                        return 0;
+        }
+
+        /* See if it matches any of exclude/include rule */
+        for (i = 0; i < limit_by_name.nr; i++) {
+                struct string_list_item *it = &limit_by_name.items[i];
+                if (!wildmatch(it->string, pathname, 0, NULL))
+                        return (it->util != NULL);
+        }
+
+        /*
+         * If we had any include, a path that does not match any rule is
+         * not used.  Otherwise, we saw bunch of exclude rules (or none)
+         * and such a path is used.
+         */
+        return !has_include;
+}
+
+
 /*
  * Read the patch text in "buffer" that extends for "size" bytes; stop
  * reading after seeing a single patch (i.e. changes to a single file).
@@ -1935,9 +1995,14 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
         if (offset < 0)
                 return offset;
 
-        patch->ws_rule = whitespace_rule(patch->new_name
-                                         ? patch->new_name
-                                         : patch->old_name);
+        prefix_patch(patch);
+
+        if (!use_patch(patch))
+                patch->ws_rule = 0;
+        else
+                patch->ws_rule = whitespace_rule(patch->new_name
+                                                 ? patch->new_name
+                                                 : patch->old_name);
 
         patchsize = parse_single_patch(buffer + offset + hdrsize,
                                        size - offset - hdrsize, patch);
@@ -4127,64 +4192,6 @@ static int write_out_results(struct patch *list)
 
 static struct lock_file lock_file;
 
-static struct string_list limit_by_name;
-static int has_include;
-static void add_name_limit(const char *name, int exclude)
-{
-        struct string_list_item *it;
-
-        it = string_list_append(&limit_by_name, name);
-        it->util = exclude ? NULL : (void *) 1;
-}
-
-static int use_patch(struct patch *p)
-{
-        const char *pathname = p->new_name ? p->new_name : p->old_name;
-        int i;
-
-        /* Paths outside are not touched regardless of "--include" */
-        if (0 < prefix_length) {
-                int pathlen = strlen(pathname);
-                if (pathlen <= prefix_length ||
-                    memcmp(prefix, pathname, prefix_length))
-                        return 0;
-        }
-
-        /* See if it matches any of exclude/include rule */
-        for (i = 0; i < limit_by_name.nr; i++) {
-                struct string_list_item *it = &limit_by_name.items[i];
-                if (!wildmatch(it->string, pathname, 0, NULL))
-                        return (it->util != NULL);
-        }
-
-        /*
-         * If we had any include, a path that does not match any rule is
-         * not used.  Otherwise, we saw bunch of exclude rules (or none)
-         * and such a path is used.
-         */
-        return !has_include;
-}
-
-
-static void prefix_one(char **name)
-{
-        char *old_name = *name;
-        if (!old_name)
-                return;
-        *name = xstrdup(prefix_filename(prefix, prefix_length, *name));
-        free(old_name);
-}
-
-static void prefix_patches(struct patch *p)
-{
-        if (!prefix || p->is_toplevel_relative)
-                return;
-        for ( ; p; p = p->next) {
-                prefix_one(&p->new_name);
-                prefix_one(&p->old_name);
-        }
-}
-
 #define INACCURATE_EOF        (1<<0)
 #define RECOUNT                (1<<1)
 
@@ -4210,8 +4217,6 @@ static int apply_patch(int fd, const char *filename, int options)
                         break;
                 if (apply_in_reverse)
                         reverse_patches(patch);
-                if (prefix)
-                        prefix_patches(patch);
                 if (use_patch(patch)) {
                         patch_stats(patch);
                         *listp = patch;
diff --git a/t/t4119-apply-config.sh b/t/t4119-apply-config.sh
index c393be691b..a9a0583811 100755
--- a/t/t4119-apply-config.sh
+++ b/t/t4119-apply-config.sh
@@ -159,4 +159,21 @@ test_expect_success 'same but with traditional patch input of depth 2' '
         check_result sub/file1
 '
 
+test_expect_success 'in subdir with traditional patch input' '
+        cd "$D" &&
+        git config apply.whitespace strip &&
+        cat >.gitattributes <<-EOF &&
+        /* whitespace=blank-at-eol
+        sub/* whitespace=-blank-at-eol
+        EOF
+        rm -f sub/file1 &&
+        cp saved sub/file1 &&
+        git update-index --refresh &&
+
+        cd sub &&
+        git apply ../gpatch.file &&
+        echo "B " >expect &&
+        test_cmp expect file1
+'
+
 test_done
diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh
index 5d0c598338..c6474de4c8 100755
--- a/t/t4124-apply-ws-rule.sh
+++ b/t/t4124-apply-ws-rule.sh
@@ -512,4 +512,15 @@ test_expect_success 'whitespace=fix to expand' '
         git -c core.whitespace=tab-in-indent apply --whitespace=fix patch
 '
 
+test_expect_success 'whitespace check skipped for excluded paths' '
+        git config core.whitespace blank-at-eol &&
+        >used &&
+        >unused &&
+        git add used unused &&
+        echo "used" >used &&
+        echo "unused " >unused &&
+        git diff-files -p used unused >patch &&
+        git apply --include=used --stat --whitespace=error <patch
+'
+
 test_done