add.c: extract check_path_for_gitlink() from treat_gitlinks() for reuse
[gitweb.git] / builtin / add.c
index b79336d712b4c71cc2f026b0e9f42ea0bcebfc6f..f95ded2567035a41f365df9cb765bfe6820ced96 100644 (file)
@@ -6,6 +6,7 @@
 #include "cache.h"
 #include "builtin.h"
 #include "dir.h"
+#include "pathspec.h"
 #include "exec_cmd.h"
 #include "cache-tree.h"
 #include "run-command.h"
@@ -97,39 +98,6 @@ int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
        return !!data.add_errors;
 }
 
-static void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
-{
-       int num_unmatched = 0, i;
-
-       /*
-        * Since we are walking the index as if we were walking the directory,
-        * we have to mark the matched pathspec as seen; otherwise we will
-        * mistakenly think that the user gave a pathspec that did not match
-        * anything.
-        */
-       for (i = 0; i < specs; i++)
-               if (!seen[i])
-                       num_unmatched++;
-       if (!num_unmatched)
-               return;
-       for (i = 0; i < active_nr; i++) {
-               struct cache_entry *ce = active_cache[i];
-               match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen);
-       }
-}
-
-static char *find_used_pathspec(const char **pathspec)
-{
-       char *seen;
-       int i;
-
-       for (i = 0; pathspec[i];  i++)
-               ; /* just counting */
-       seen = xcalloc(i, 1);
-       fill_pathspec_matches(pathspec, seen, i);
-       return seen;
-}
-
 static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
 {
        char *seen;
@@ -149,10 +117,14 @@ static char *prune_directory(struct dir_struct *dir, const char **pathspec, int
                        *dst++ = entry;
        }
        dir->nr = dst - dir->entries;
-       fill_pathspec_matches(pathspec, seen, specs);
+       add_pathspec_matches_against_index(pathspec, seen, specs);
        return seen;
 }
 
+/*
+ * Checks the index to see whether any path in pathspec refers to
+ * something inside a submodule.  If so, dies with an error message.
+ */
 static void treat_gitlinks(const char **pathspec)
 {
        int i;
@@ -160,24 +132,8 @@ static void treat_gitlinks(const char **pathspec)
        if (!pathspec || !*pathspec)
                return;
 
-       for (i = 0; i < active_nr; i++) {
-               struct cache_entry *ce = active_cache[i];
-               if (S_ISGITLINK(ce->ce_mode)) {
-                       int len = ce_namelen(ce), j;
-                       for (j = 0; pathspec[j]; j++) {
-                               int len2 = strlen(pathspec[j]);
-                               if (len2 <= len || pathspec[j][len] != '/' ||
-                                   memcmp(ce->name, pathspec[j], len))
-                                       continue;
-                               if (len2 == len + 1)
-                                       /* strip trailing slash */
-                                       pathspec[j] = xstrndup(ce->name, len);
-                               else
-                                       die (_("Path '%s' is in submodule '%.*s'"),
-                                               pathspec[j], len, ce->name);
-                       }
-               }
-       }
+       for (i = 0; pathspec[i]; i++)
+               pathspec[i] = check_path_for_gitlink(pathspec[i]);
 }
 
 static void refresh(int verbose, const char **pathspec)
@@ -197,7 +153,7 @@ static void refresh(int verbose, const char **pathspec)
         free(seen);
 }
 
-static const char **validate_pathspec(int argc, const char **argv, const char *prefix)
+static const char **validate_pathspec(const char **argv, const char *prefix)
 {
        const char **pathspec = get_pathspec(prefix, argv);
 
@@ -248,7 +204,7 @@ int interactive_add(int argc, const char **argv, const char *prefix, int patch)
        const char **pathspec = NULL;
 
        if (argc) {
-               pathspec = validate_pathspec(argc, argv, prefix);
+               pathspec = validate_pathspec(argv, prefix);
                if (!pathspec)
                        return -1;
        }
@@ -281,7 +237,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
        argc = setup_revisions(argc, argv, &rev, NULL);
        rev.diffopt.output_format = DIFF_FORMAT_PATCH;
        DIFF_OPT_SET(&rev.diffopt, IGNORE_DIRTY_SUBMODULES);
-       out = open(file, O_CREAT | O_WRONLY, 0644);
+       out = open(file, O_CREAT | O_WRONLY, 0666);
        if (out < 0)
                die (_("Could not open '%s' for writing."), file);
        rev.diffopt.file = xfdopen(out, "w");
@@ -414,7 +370,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
                fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
                return 0;
        }
-       pathspec = validate_pathspec(argc, argv, prefix);
+       pathspec = validate_pathspec(argv, prefix);
 
        if (read_cache() < 0)
                die(_("index file corrupt"));
@@ -443,14 +399,17 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
        if (pathspec) {
                int i;
+               struct path_exclude_check check;
+
+               path_exclude_check_init(&check, &dir);
                if (!seen)
-                       seen = find_used_pathspec(pathspec);
+                       seen = find_pathspecs_matching_against_index(pathspec);
                for (i = 0; pathspec[i]; i++) {
                        if (!seen[i] && pathspec[i][0]
                            && !file_exists(pathspec[i])) {
                                if (ignore_missing) {
                                        int dtype = DT_UNKNOWN;
-                                       if (excluded(&dir, pathspec[i], &dtype))
+                                       if (is_path_excluded(&check, pathspec[i], -1, &dtype))
                                                dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
                                } else
                                        die(_("pathspec '%s' did not match any files"),
@@ -458,6 +417,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
                        }
                }
                free(seen);
+               path_exclude_check_clear(&check);
        }
 
        plug_bulk_checkin();