Merge branch 'bc/master-diff-hunk-header-fix'
[git/git.git] / builtin-apply.c
index 70c9f93..e2c611b 100644 (file)
@@ -2987,29 +2987,45 @@ static int write_out_results(struct patch *list, int skipped_patch)
 
 static struct lock_file lock_file;
 
-static struct excludes {
-       struct excludes *next;
-       const char *path;
-} *excludes;
+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(name, &limit_by_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;
-       struct excludes *x = excludes;
-       while (x) {
-               if (fnmatch(x->path, pathname, 0) == 0)
-                       return 0;
-               x = x->next;
-       }
+       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;
        }
-       return 1;
+
+       /* 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 (!fnmatch(it->string, pathname, 0))
+                       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;
@@ -3150,10 +3166,12 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
                        continue;
                }
                if (!prefixcmp(arg, "--exclude=")) {
-                       struct excludes *x = xmalloc(sizeof(*x));
-                       x->path = arg + 10;
-                       x->next = excludes;
-                       excludes = x;
+                       add_name_limit(arg + 10, 1);
+                       continue;
+               }
+               if (!prefixcmp(arg, "--include=")) {
+                       add_name_limit(arg + 10, 0);
+                       has_include = 1;
                        continue;
                }
                if (!prefixcmp(arg, "-p")) {