}
static const char *add_would_remove_warning = N_(
- "You ran 'git add' with neither '-A (--all)' or '--no-all', whose\n"
-"behaviour will change in Git 2.0 with respect to paths you removed from\n"
-"your working tree. Paths like '%s' that are\n"
-"removed are ignored with this version of Git.\n"
+ "You ran 'git add' with neither '-A (--all)' or '--ignore-removal',\n"
+"whose behaviour will change in Git 2.0 with respect to paths you removed.\n"
+"Paths like '%s' that are\n"
+"removed from your working tree are ignored with this version of Git.\n"
"\n"
-"* 'git add --no-all <pathspec>', which is the current default, ignores\n"
-" paths you removed from your working tree.\n"
+"* 'git add --ignore-removal <pathspec>', which is the current default,\n"
+" ignores paths you removed from your working tree.\n"
"\n"
"* 'git add --all <pathspec>' will let you also record the removals.\n"
"\n"
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;
-
- if (!pathspec || !*pathspec)
- return;
-
- for (i = 0; pathspec[i]; i++)
- pathspec[i] = check_path_for_gitlink(pathspec[i]);
-}
-
static void refresh(int verbose, const char **pathspec)
{
char *seen;
free(seen);
}
-/*
- * Normalizes argv relative to prefix, via get_pathspec(), and then
- * runs die_if_path_beyond_symlink() on each path in the normalized
- * list.
- */
-static const char **validate_pathspec(const char **argv, const char *prefix)
-{
- const char **pathspec = get_pathspec(prefix, argv);
-
- if (pathspec) {
- const char **p;
- for (p = pathspec; *p; p++) {
- die_if_path_beyond_symlink(*p, prefix);
- }
- }
-
- return pathspec;
-}
-
int run_add_interactive(const char *revision, const char *patch_mode,
const char **pathspec)
{
int interactive_add(int argc, const char **argv, const char *prefix, int patch)
{
- const char **pathspec = NULL;
+ struct pathspec pathspec;
- if (argc) {
- pathspec = validate_pathspec(argv, prefix);
- if (!pathspec)
- return -1;
- }
+ /*
+ * git-add--interactive itself does not parse pathspec. It
+ * simply passes the pathspec to other builtin commands. Let's
+ * hope all of them support all magic, or we'll need to limit
+ * the magic here. There is still a problem with prefix. But
+ * that'll be worked on later on.
+ */
+ parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC & ~PATHSPEC_FROMTOP,
+ PATHSPEC_PREFER_FULL |
+ PATHSPEC_SYMLINK_LEADING_PATH,
+ prefix, argv);
return run_add_interactive(NULL,
patch ? "--patch" : NULL,
- pathspec);
+ pathspec.raw);
}
static int edit_patch(int argc, const char **argv, const char *prefix)
static int addremove = ADDREMOVE_DEFAULT;
static int addremove_explicit = -1; /* unspecified */
+static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
+{
+ /* if we are told to ignore, we are not adding removals */
+ *(int *)opt->value = !unset ? 0 : 1;
+ return 0;
+}
+
static struct option builtin_add_options[] = {
OPT__DRY_RUN(&show_only, N_("dry run")),
OPT__VERBOSE(&verbose, N_("be verbose")),
OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
+ { OPTION_CALLBACK, 0, "ignore-removal", &addremove_explicit,
+ NULL /* takes no arguments */,
+ N_("ignore paths removed in the working tree (same as --no-all)"),
+ PARSE_OPT_NOARG, ignore_removal_cb },
OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
{
int exit_status = 0;
int newfd;
- const char **pathspec;
+ struct pathspec pathspec;
struct dir_struct dir;
int flags;
int add_new_files;
fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
return 0;
}
- pathspec = validate_pathspec(argv, prefix);
if (read_cache() < 0)
die(_("index file corrupt"));
- treat_gitlinks(pathspec);
+
+ /*
+ * Check the "pathspec '%s' did not match any files" block
+ * below before enabling new magic.
+ */
+ parse_pathspec(&pathspec, 0,
+ PATHSPEC_PREFER_FULL |
+ PATHSPEC_SYMLINK_LEADING_PATH |
+ PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE,
+ prefix, argv);
if (add_new_files) {
int baselen;
}
/* This picks up the paths that are not tracked */
- baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec);
- if (pathspec)
- seen = prune_directory(&dir, pathspec, baselen,
+ baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec.raw);
+ if (pathspec.nr)
+ seen = prune_directory(&dir, pathspec.raw, baselen,
implicit_dot ? WARN_IMPLICIT_DOT : 0);
}
if (refresh_only) {
- refresh(verbose, pathspec);
+ refresh(verbose, pathspec.raw);
goto finish;
}
+ if (implicit_dot && prefix)
+ refresh_cache(REFRESH_QUIET);
- if (pathspec) {
+ if (pathspec.nr) {
int i;
if (!seen)
- seen = find_pathspecs_matching_against_index(pathspec);
- for (i = 0; pathspec[i]; i++) {
- if (!seen[i] && pathspec[i][0]
- && !file_exists(pathspec[i])) {
+ seen = find_pathspecs_matching_against_index(pathspec.raw);
+
+ /*
+ * file_exists() assumes exact match
+ */
+ GUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP);
+
+ for (i = 0; pathspec.raw[i]; i++) {
+ if (!seen[i] && pathspec.raw[i][0]
+ && !file_exists(pathspec.raw[i])) {
if (ignore_missing) {
int dtype = DT_UNKNOWN;
- if (is_excluded(&dir, pathspec[i], &dtype))
- dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
+ if (is_excluded(&dir, pathspec.raw[i], &dtype))
+ dir_add_ignored(&dir, pathspec.raw[i], strlen(pathspec.raw[i]));
} else
die(_("pathspec '%s' did not match any files"),
- pathspec[i]);
+ pathspec.raw[i]);
}
}
free(seen);
*/
update_data.implicit_dot = prefix;
update_data.implicit_dot_len = strlen(prefix);
- pathspec = NULL;
+ free_pathspec(&pathspec);
+ memset(&pathspec, 0, sizeof(pathspec));
}
update_data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
- update_files_in_cache(prefix, pathspec, &update_data);
+ update_files_in_cache(prefix, pathspec.raw, &update_data);
exit_status |= !!update_data.add_errors;
if (add_new_files)