add: convert to use parse_pathspec

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Jul 14, 2013 at 15:35 UTC 5a76aff1a6f112cc2888b63ee97ade679e6e3e01
2 files changed +45 -101
builtin/add.c
+45 -58
@@ -226,21 +226,6 @@ static char *prune_directory(struct dir_struct *dir, const char **pathspec,
226 return seen;
227 }
228
229 -/*
230 - * Checks the index to see whether any path in pathspec refers to
231 - * something inside a submodule. If so, dies with an error message.
232 - */
233 -static void treat_gitlinks(const char **pathspec)
234 -{
235 - int i;
236 -
237 - if (!pathspec || !*pathspec)
238 - return;
239 -
240 - for (i = 0; pathspec[i]; i++)
241 - pathspec[i] = check_path_for_gitlink(pathspec[i]);
242 -}
243 -
229 static void refresh(int verbose, const char **pathspec)
230 {
231 char *seen;
@@ -258,25 +243,6 @@ static void refresh(int verbose, const char **pathspec)
243 free(seen);
244 }
245
261 -/*
262 - * Normalizes argv relative to prefix, via get_pathspec(), and then
263 - * runs die_if_path_beyond_symlink() on each path in the normalized
264 - * list.
265 - */
266 -static const char **validate_pathspec(const char **argv, const char *prefix)
267 -{
268 - const char **pathspec = get_pathspec(prefix, argv);
269 -
270 - if (pathspec) {
271 - const char **p;
272 - for (p = pathspec; *p; p++) {
273 - die_if_path_beyond_symlink(*p, prefix);
274 - }
275 - }
276 -
277 - return pathspec;
278 -}
279 -
246 int run_add_interactive(const char *revision, const char *patch_mode,
247 const char **pathspec)
248 {
@@ -308,17 +274,23 @@ int run_add_interactive(const char *revision, const char *patch_mode,
274
275 int interactive_add(int argc, const char **argv, const char *prefix, int patch)
276 {
311 - const char **pathspec = NULL;
277 + struct pathspec pathspec;
278
313 - if (argc) {
314 - pathspec = validate_pathspec(argv, prefix);
315 - if (!pathspec)
316 - return -1;
317 - }
279 + /*
280 + * git-add--interactive itself does not parse pathspec. It
281 + * simply passes the pathspec to other builtin commands. Let's
282 + * hope all of them support all magic, or we'll need to limit
283 + * the magic here. There is still a problem with prefix. But
284 + * that'll be worked on later on.
285 + */
286 + parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC & ~PATHSPEC_FROMTOP,
287 + PATHSPEC_PREFER_FULL |
288 + PATHSPEC_SYMLINK_LEADING_PATH,
289 + prefix, argv);
290
291 return run_add_interactive(NULL,
292 patch ? "--patch" : NULL,
321 - pathspec);
293 + pathspec.raw);
294 }
295
296 static int edit_patch(int argc, const char **argv, const char *prefix)
@@ -445,7 +417,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
417 {
418 int exit_status = 0;
419 int newfd;
448 - const char **pathspec;
420 + struct pathspec pathspec;
421 struct dir_struct dir;
422 int flags;
423 int add_new_files;
@@ -526,11 +498,19 @@ int cmd_add(int argc, const char **argv, const char *prefix)
498 fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
499 return 0;
500 }
529 - pathspec = validate_pathspec(argv, prefix);
501
502 if (read_cache() < 0)
503 die(_("index file corrupt"));
533 - treat_gitlinks(pathspec);
504 +
505 + /*
506 + * Check the "pathspec '%s' did not match any files" block
507 + * below before enabling new magic.
508 + */
509 + parse_pathspec(&pathspec, 0,
510 + PATHSPEC_PREFER_FULL |
511 + PATHSPEC_SYMLINK_LEADING_PATH |
512 + PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE,
513 + prefix, argv);
514
515 if (add_new_files) {
516 int baselen;
@@ -543,34 +523,40 @@ int cmd_add(int argc, const char **argv, const char *prefix)
523 }
524
525 /* This picks up the paths that are not tracked */
546 - baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec);
547 - if (pathspec)
548 - seen = prune_directory(&dir, pathspec, baselen,
526 + baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec.raw);
527 + if (pathspec.nr)
528 + seen = prune_directory(&dir, pathspec.raw, baselen,
529 implicit_dot ? WARN_IMPLICIT_DOT : 0);
530 }
531
532 if (refresh_only) {
553 - refresh(verbose, pathspec);
533 + refresh(verbose, pathspec.raw);
534 goto finish;
535 }
536 if (implicit_dot && prefix)
537 refresh_cache(REFRESH_QUIET);
538
559 - if (pathspec) {
539 + if (pathspec.nr) {
540 int i;
541
542 if (!seen)
563 - seen = find_pathspecs_matching_against_index(pathspec);
564 - for (i = 0; pathspec[i]; i++) {
565 - if (!seen[i] && pathspec[i][0]
566 - && !file_exists(pathspec[i])) {
543 + seen = find_pathspecs_matching_against_index(pathspec.raw);
544 +
545 + /*
546 + * file_exists() assumes exact match
547 + */
548 + GUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP);
549 +
550 + for (i = 0; pathspec.raw[i]; i++) {
551 + if (!seen[i] && pathspec.raw[i][0]
552 + && !file_exists(pathspec.raw[i])) {
553 if (ignore_missing) {
554 int dtype = DT_UNKNOWN;
569 - if (is_excluded(&dir, pathspec[i], &dtype))
570 - dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
555 + if (is_excluded(&dir, pathspec.raw[i], &dtype))
556 + dir_add_ignored(&dir, pathspec.raw[i], strlen(pathspec.raw[i]));
557 } else
558 die(_("pathspec '%s' did not match any files"),
573 - pathspec[i]);
559 + pathspec.raw[i]);
560 }
561 }
562 free(seen);
@@ -586,10 +572,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
572 */
573 update_data.implicit_dot = prefix;
574 update_data.implicit_dot_len = strlen(prefix);
589 - pathspec = NULL;
575 + free_pathspec(&pathspec);
576 + memset(&pathspec, 0, sizeof(pathspec));
577 }
578 update_data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
592 - update_files_in_cache(prefix, pathspec, &update_data);
579 + update_files_in_cache(prefix, pathspec.raw, &update_data);
580
581 exit_status |= !!update_data.add_errors;
582 if (add_new_files)
pathspec.c
-43
@@ -57,49 +57,6 @@ char *find_pathspecs_matching_against_index(const char **pathspec)
57 return seen;
58 }
59
60 -/*
61 - * Check the index to see whether path refers to a submodule, or
62 - * something inside a submodule. If the former, returns the path with
63 - * any trailing slash stripped. If the latter, dies with an error
64 - * message.
65 - */
66 -const char *check_path_for_gitlink(const char *path)
67 -{
68 - int i, path_len = strlen(path);
69 - for (i = 0; i < active_nr; i++) {
70 - struct cache_entry *ce = active_cache[i];
71 - if (S_ISGITLINK(ce->ce_mode)) {
72 - int ce_len = ce_namelen(ce);
73 - if (path_len <= ce_len || path[ce_len] != '/' ||
74 - memcmp(ce->name, path, ce_len))
75 - /* path does not refer to this
76 - * submodule or anything inside it */
77 - continue;
78 - if (path_len == ce_len + 1) {
79 - /* path refers to submodule;
80 - * strip trailing slash */
81 - return xstrndup(ce->name, ce_len);
82 - } else {
83 - die (_("Path '%s' is in submodule '%.*s'"),
84 - path, ce_len, ce->name);
85 - }
86 - }
87 - }
88 - return path;
89 -}
90 -
91 -/*
92 - * Dies if the given path refers to a file inside a symlinked
93 - * directory in the index.
94 - */
95 -void die_if_path_beyond_symlink(const char *path, const char *prefix)
96 -{
97 - if (has_symlink_leading_path(path, strlen(path))) {
98 - int len = prefix ? strlen(prefix) : 0;
99 - die(_("'%s' is beyond a symbolic link"), path + len);
100 - }
101 -}
102 -
60 /*
61 * Magic pathspec
62 *