send-email: change --no-validate to boolean --[no-]validate
[gitweb.git] / builtin-apply.c
index 4eb263ec5807a771b3a61c147b74a6f2f68dddee..e2c611bf964d8cd589171f74e5ccce5aeb392643 100644 (file)
@@ -13,6 +13,7 @@
 #include "delta.h"
 #include "builtin.h"
 #include "string-list.h"
+#include "dir.h"
 
 /*
  *  --check turns on checking that the working tree matches the
@@ -1996,6 +1997,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
        /*
         * A hunk to change lines at the beginning would begin with
         * @@ -1,L +N,M @@
+        * but we need to be careful.  -U0 that inserts before the second
+        * line also has this pattern.
         *
         * And a hunk to add to an empty file would begin with
         * @@ -0,0 +N,M @@
@@ -2003,7 +2006,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
         * In other words, a hunk that is (frag->oldpos <= 1) with or
         * without leading context must match at the beginning.
         */
-       match_beginning = frag->oldpos <= 1;
+       match_beginning = (!frag->oldpos ||
+                          (frag->oldpos == 1 && !unidiff_zero));
 
        /*
         * A hunk without trailing lines must match at the end.
@@ -2732,15 +2736,7 @@ static void remove_file(struct patch *patch, int rmdir_empty)
                                warning("unable to remove submodule %s",
                                        patch->old_name);
                } else if (!unlink(patch->old_name) && rmdir_empty) {
-                       char *name = xstrdup(patch->old_name);
-                       char *end = strrchr(name, '/');
-                       while (end) {
-                               *end = 0;
-                               if (rmdir(name))
-                                       break;
-                               end = strrchr(name, '/');
-                       }
-                       free(name);
+                       remove_path(patch->old_name);
                }
        }
 }
@@ -2991,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;
@@ -3154,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")) {