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
*