#include "bulk-checkin.h"
static const char * const builtin_add_usage[] = {
- "git add [options] [--] <filepattern>...",
+ N_("git add [options] [--] <pathspec>..."),
NULL
};
static int patch_interactive, add_interactive, edit_interactive;
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++) {
- if (has_symlink_leading_path(*p, strlen(*p))) {
- int len = prefix ? strlen(prefix) : 0;
- die(_("'%s' is beyond a symbolic link"), *p + len);
- }
+ die_if_path_beyond_symlink(*p, prefix);
}
}
static int edit_patch(int argc, const char **argv, const char *prefix)
{
- char *file = xstrdup(git_path("ADD_EDIT.patch"));
+ char *file = git_pathdup("ADD_EDIT.patch");
const char *apply_argv[] = { "apply", "--recount", "--cached",
NULL, NULL };
struct child_process child;
die (_("Could not apply '%s'"), file);
unlink(file);
+ free(file);
return 0;
}
static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
static struct option builtin_add_options[] = {
- OPT__DRY_RUN(&show_only, "dry run"),
- OPT__VERBOSE(&verbose, "be verbose"),
+ OPT__DRY_RUN(&show_only, N_("dry run")),
+ OPT__VERBOSE(&verbose, N_("be verbose")),
OPT_GROUP(""),
- OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
- OPT_BOOLEAN('p', "patch", &patch_interactive, "select hunks interactively"),
- OPT_BOOLEAN('e', "edit", &edit_interactive, "edit current diff and apply"),
- OPT__FORCE(&ignored_too, "allow adding otherwise ignored files"),
- OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
- OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, "record only the fact that the path will be added later"),
- OPT_BOOLEAN('A', "all", &addremove, "add changes from all tracked and untracked files"),
- OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
- OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip files which cannot be added because of errors"),
- OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, "check if - even missing - files are ignored in dry run"),
+ OPT_BOOLEAN('i', "interactive", &add_interactive, N_("interactive picking")),
+ OPT_BOOLEAN('p', "patch", &patch_interactive, N_("select hunks interactively")),
+ OPT_BOOLEAN('e', "edit", &edit_interactive, N_("edit current diff and apply")),
+ OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
+ OPT_BOOLEAN('u', "update", &take_worktree_changes, N_("update tracked files")),
+ OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
+ OPT_BOOLEAN('A', "all", &addremove, N_("add changes from all tracked and untracked files")),
+ OPT_BOOLEAN( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
+ OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
+ OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
OPT_END(),
};
return exit_status;
}
+static void warn_pathless_add(const char *option_name, const char *short_name) {
+ /*
+ * To be consistent with "git add -p" and most Git
+ * commands, we should default to being tree-wide, but
+ * this is not the original behavior and can't be
+ * changed until users trained themselves not to type
+ * "git add -u" or "git add -A". For now, we warn and
+ * keep the old behavior. Later, this warning can be
+ * turned into a die(...), and eventually we may
+ * reallow the command with a new behavior.
+ */
+ warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
+ "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
+ "To add content for the whole tree, run:\n"
+ "\n"
+ " git add %s :/\n"
+ " (or git add %s :/)\n"
+ "\n"
+ "To restrict the command to the current directory, run:\n"
+ "\n"
+ " git add %s .\n"
+ " (or git add %s .)\n"
+ "\n"
+ "With the current Git version, the command is restricted to the current directory."),
+ option_name, short_name,
+ option_name, short_name,
+ option_name, short_name);
+}
+
int cmd_add(int argc, const char **argv, const char *prefix)
{
int exit_status = 0;
int add_new_files;
int require_pathspec;
char *seen = NULL;
+ const char *option_with_implicit_dot = NULL;
+ const char *short_option_with_implicit_dot = NULL;
git_config(add_config, NULL);
die(_("-A and -u are mutually incompatible"));
if (!show_only && ignore_missing)
die(_("Option --ignore-missing can only be used together with --dry-run"));
- if ((addremove || take_worktree_changes) && !argc) {
+ if (addremove) {
+ option_with_implicit_dot = "--all";
+ short_option_with_implicit_dot = "-A";
+ }
+ if (take_worktree_changes) {
+ option_with_implicit_dot = "--update";
+ short_option_with_implicit_dot = "-u";
+ }
+ if (option_with_implicit_dot && !argc) {
static const char *here[2] = { ".", NULL };
+ if (prefix)
+ warn_pathless_add(option_with_implicit_dot,
+ short_option_with_implicit_dot);
argc = 1;
argv = here;
}