[PATCH 0/2] "git add -u/-A" from future

STALE3736d

Revision v1 of 2 in this series.

11 messages, 3 authors, 2016-06-15 · open the first message on its own page

[PATCH 0/2] "git add -u/-A" from future

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:56:20

Here are two future steps to update the behaviour of "add -u/-A" run
without pathspec towards Git 2.0; the first step may probably be
optional, but it is included for completeness.

Junio C Hamano (2):
  require pathspec for "git add -u/-A"
  git add: -u/-A now affects the entire working tree

 Documentation/git-add.txt |  8 ++++----
 builtin/add.c             | 49 ++++-------------------------------------------
 2 files changed, 8 insertions(+), 49 deletions(-)

-- 
1.8.2-rc3-196-gfcda97c

[PATCH 1/2] require pathspec for "git add -u/-A"

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:56:20

As promised in 0fa2eb530fb7 (add: warn when -u or -A is used without
pathspec, 2013-01-28), "git add -u/-A" that is run without pathspec
in a subdirectory will stop working sometime before Git 2.0, to wean
users off of the old default, in preparation for adopting the new
default in Git 2.0.

Signed-off-by: Junio C Hamano <redacted>
---
 Documentation/git-add.txt | 12 ++++++++----
 builtin/add.c             | 38 ++++++++++++++++++--------------------
 2 files changed, 26 insertions(+), 24 deletions(-)
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 388a225..1ea1d39 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -107,10 +107,14 @@ apply to the index. See EDITING PATCHES below.
 	from the index if the corresponding files in the working tree
 	have been removed.
 +
-If no <pathspec> is given, the current version of Git defaults to
-"."; in other words, update all tracked files in the current directory
-and its subdirectories. This default will change in a future version
-of Git, hence the form without <pathspec> should not be used.
+If no <pathspec> is given when `-u` or `-A` option is used, Git used
+to update all tracked files in the current directory and its
+subdirectories. We would eventually want to change this to operate
+on the entire working tree, not limiting it to the current
+directory, to make it consistent with `git commit -a` and other
+commands.  In order to avoid harming users who are used to the old
+default, Git *errors out* when no <pathspec> is given to train their
+fingers to explicitly type `git add -u .` when they mean it.
 
 -A::
 --all::
diff --git a/builtin/add.c b/builtin/add.c
index 0dd014e..4b9d57c 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -321,30 +321,28 @@ static int add_files(struct dir_struct *dir, int flags)
 	return exit_status;
 }
 
-static void warn_pathless_add(const char *option_name, const char *short_name) {
+static void die_on_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.
+	 * "git add -u" or "git add -A". In the previous release,
+	 * we kept the old behavior but gave a big warning.
 	 */
-	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."),
+	die(_("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 .)"),
 		option_name, short_name,
 		option_name, short_name,
 		option_name, short_name);
@@ -392,8 +390,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 	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);
+			die_on_pathless_add(option_with_implicit_dot,
+					    short_option_with_implicit_dot);
 		argc = 1;
 		argv = here;
 	}
-- 
1.8.2-rc3-196-gfcda97c

[PATCH 2/2] git add: -u/-A now affects the entire working tree

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:56:20

As promised in 0fa2eb530fb7 (add: warn when -u or -A is used without
pathspec, 2013-01-28), in Git 2.0, "git add -u/-A" that is run
without pathspec in a subdirectory updates all updated paths in the
entire working tree, not just the current directory and its
subdirectories.

Signed-off-by: Junio C Hamano <redacted>
---
 Documentation/git-add.txt | 12 ++++--------
 builtin/add.c             | 47 ++++-------------------------------------------
 2 files changed, 8 insertions(+), 51 deletions(-)
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 1ea1d39..15a8859 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -107,14 +107,10 @@ apply to the index. See EDITING PATCHES below.
 	from the index if the corresponding files in the working tree
 	have been removed.
 +
-If no <pathspec> is given when `-u` or `-A` option is used, Git used
-to update all tracked files in the current directory and its
-subdirectories. We would eventually want to change this to operate
-on the entire working tree, not limiting it to the current
-directory, to make it consistent with `git commit -a` and other
-commands.  In order to avoid harming users who are used to the old
-default, Git *errors out* when no <pathspec> is given to train their
-fingers to explicitly type `git add -u .` when they mean it.
+If no <pathspec> is given when `-u` or `-A` option is used, all
+tracked files in the entire working tree are updated (old versions
+of Git used to limit the update to the current directory and its
+subdirectories).
 
 -A::
 --all::
diff --git a/builtin/add.c b/builtin/add.c
index 4b9d57c..6cd063f 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -321,33 +321,6 @@ static int add_files(struct dir_struct *dir, int flags)
 	return exit_status;
 }
 
-static void die_on_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". In the previous release,
-	 * we kept the old behavior but gave a big warning.
-	 */
-	die(_("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 .)"),
-		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;
@@ -358,8 +331,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 	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);
 
@@ -379,21 +350,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		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) {
-		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)
-			die_on_pathless_add(option_with_implicit_dot,
-					    short_option_with_implicit_dot);
+
+	if ((addremove || take_worktree_changes) && !argc) {
+		static const char *whole[2] = { ":/", NULL };
 		argc = 1;
-		argv = here;
+		argv = whole;
 	}
 
 	add_new_files = !take_worktree_changes && !refresh_only;
-- 
1.8.2-rc3-196-gfcda97c

[PATCH v2 0/6] make pathless 'add [-u|-A]' warning less noisy

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:56:27

As promised, here is a rerolled version of the "make pathless 'add
[-u|-A]' warning less noisy", incorporating patches from
jc/add-2.0-u-A-sans-pathspec.  Thanks for your help so far.

Just like jc/add-2.0-u-A-sans-pathspec, the only transition in this
series is the "pull the bandaid" kind.  That is, there are two steps:

 0. the current state, where the warning is a little too noisy
 1. the current state but with the warning only firing in cases
    where the user will be affected by the change to default
    'git add -u' behavior
 2. no more warning, 'git add -u' defaulting to 'git add -u :/'

Patch 1 is the same as in jc/add-2.0-u-A-sans-pathspec, included for
reference.

Patches 2-5 correspond to the original patches 1-4.  Any changes are
described after the '---' in each patch.

Patch 6 is just the patch from the tip of jc/add-2.0-u-A-sans-pathspec,
rebased.  It is meant to be applied in the 2.0 cycle.

Jeff King (1):
  t2200: check that "add -u" limits itself to subdirectory

Jonathan Nieder (4):
  add: make pathless 'add [-u|-A]' warning a file-global function
  add: make warn_pathless_add() a no-op after first call
  add -u: only show pathless 'add -u' warning when changes exist outside
    cwd
  add -A: only show pathless 'add -A' warning when changes exist outside
    cwd

Junio C Hamano (1):
  git add: -u/-A now affects the entire working tree

 Documentation/git-add.txt | 16 +++++++-------
 builtin/add.c             | 56 ++++++++---------------------------------------
 t/t2200-add-update.sh     | 11 ++++++++++
 3 files changed, 28 insertions(+), 55 deletions(-)

[PATCH 1/6] t2200: check that "add -u" limits itself to subdirectory

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:56:27

From: Jeff King <redacted>
Date: Thu, 14 Mar 2013 02:44:04 -0400

This behavior is due to change in the future, but let's test
it anyway. That helps make sure we do not accidentally
switch the behavior too soon while we are working in the
area, and it means that we can easily verify the change when
we do make it.

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
Unchanged, only included for reference.

 t/t2200-add-update.sh | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh
index 4cdebda..c317254 100755
--- a/t/t2200-add-update.sh
+++ b/t/t2200-add-update.sh
@@ -80,6 +80,22 @@ test_expect_success 'change gets noticed' '
 
 '
 
+# Note that this is scheduled to change in Git 2.0, when
+# "git add -u" will become full-tree by default.
+test_expect_success 'non-limited update in subdir leaves root alone' '
+	(
+		cd dir1 &&
+		echo even more >>sub2 &&
+		git add -u
+	) &&
+	cat >expect <<-\EOF &&
+	check
+	top
+	EOF
+	git diff-files --name-only >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success SYMLINKS 'replace a file with a symlink' '
 
 	rm foo &&
-- 
1.8.2.rc3

[PATCH 2/6] add: make pathless 'add [-u|-A]' warning a file-global function

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:56:27

Currently warn_pathless_add() is only called directly by cmd_add(),
but that is about to change.  Move its definition higher in the file
and pass the "--update" or "--all" option name used in its message
through globals instead of function arguments to make it easier to
call without passing values that will not change through the call
chain.

Signed-off-by: Jonathan Nieder <redacted>
---
Unchanged.

 builtin/add.c | 69 +++++++++++++++++++++++++++++++----------------------------
 1 file changed, 36 insertions(+), 33 deletions(-)
diff --git a/builtin/add.c b/builtin/add.c
index ab1c9e8..a4028ee 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -28,6 +28,41 @@ struct update_callback_data {
 	int add_errors;
 };
 
+static const char *option_with_implicit_dot;
+static const char *short_option_with_implicit_dot;
+
+static void warn_pathless_add(void)
+{
+	assert(option_with_implicit_dot && short_option_with_implicit_dot);
+
+	/*
+	 * 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, the behavior can be changed
+	 * to tree-wide, keeping the warning for a while, and
+	 * eventually we can drop the warning.
+	 */
+	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_with_implicit_dot, short_option_with_implicit_dot,
+		option_with_implicit_dot, short_option_with_implicit_dot,
+		option_with_implicit_dot, short_option_with_implicit_dot);
+}
+
 static int fix_unmerged_status(struct diff_filepair *p,
 			       struct update_callback_data *data)
 {
@@ -321,35 +356,6 @@ static int add_files(struct dir_struct *dir, int flags)
 	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, the behavior can be changed
-	 * to tree-wide, keeping the warning for a while, and
-	 * eventually we can drop the warning.
-	 */
-	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;
@@ -360,8 +366,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 	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);
 
@@ -392,8 +396,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 	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);
+			warn_pathless_add();
 		argc = 1;
 		argv = here;
 	}
-- 
1.8.2.rc3

[PATCH 3/6] add: make warn_pathless_add() a no-op after first call

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:56:27

Make warn_pathless_add() print its warning the first time it is called
and do nothing if called again.  This will make it easier to show the
warning on the fly when a relevant condition is detected without
risking showing it multiple times when multiple such conditions hold.

Signed-off-by: Jonathan Nieder <redacted>
---
As before.

 builtin/add.c | 5 +++++
 1 file changed, 5 insertions(+)
diff --git a/builtin/add.c b/builtin/add.c
index a4028ee..a424e69 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -33,8 +33,13 @@ static const char *short_option_with_implicit_dot;
 
 static void warn_pathless_add(void)
 {
+	static int shown;
 	assert(option_with_implicit_dot && short_option_with_implicit_dot);
 
+	if (shown)
+		return;
+	shown = 1;
+
 	/*
 	 * To be consistent with "git add -p" and most Git
 	 * commands, we should default to being tree-wide, but
-- 
1.8.2.rc3

[PATCH 4/6] add -u: only show pathless 'add -u' warning when changes exist outside cwd

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:56:27

A common workflow in large projects is to chdir into a subdirectory of
interest and only do work there:

	cd src
	vi foo.c
	make test
	git add -u
	git commit

The upcoming change to 'git add -u' behavior would not affect such a
workflow: when the only changes present are in the current directory,
'git add -u' will add all changes, and whether that happens via an
implicit "." or implicit ":/" parameter is an unimportant
implementation detail.

The warning about use of 'git add -u' with no pathspec is annoying
because it seemingly serves no purpose in this case.  So suppress the
warning unless there are changes outside the cwd that are not being
added.

A previous version of this patch ran two I/O-intensive diff-files
passes: one to find changes outside the cwd, and another to find
changes to add to the index within the cwd.  This version runs one
full-tree diff and decides for each change whether to add it or warn
and suppress it in update_callback.  As a result, even on very large
repositories "git add -u" will not be significantly slower than the
future default behavior ("git add -u :/"), and the slowdown relative
to "git add -u ." should be a useful clue to users of such
repositories to get into the habit of explicitly passing '.'.

Signed-off-by: Jonathan Nieder <redacted>
Acked-by: Jeff King <redacted>
Improved-by: Junio C Hamano [off-list ref]
---
This is the interesting one.

Changes since v1:
 * run only one diff-files pass, as explained in the log message
 * use strncmp_icase, not match_pathspec, to check if paths are
   under cwd
 * expand log message with performance implications
 * summarized Peff's review with an Ack.  I hope that's ok.

Thanks for your help getting this into good shape.

 builtin/add.c | 43 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 39 insertions(+), 4 deletions(-)
diff --git a/builtin/add.c b/builtin/add.c
index a424e69..4d8d441 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -26,6 +26,8 @@ static int take_worktree_changes;
 struct update_callback_data {
 	int flags;
 	int add_errors;
+	const char *implicit_dot;
+	size_t implicit_dot_len;
 };
 
 static const char *option_with_implicit_dot;
@@ -94,10 +96,27 @@ static void update_callback(struct diff_queue_struct *q,
 {
 	int i;
 	struct update_callback_data *data = cbdata;
+	const char *implicit_dot = data->implicit_dot;
+	size_t implicit_dot_len = data->implicit_dot_len;
 
 	for (i = 0; i < q->nr; i++) {
 		struct diff_filepair *p = q->queue[i];
 		const char *path = p->one->path;
+
+		/*
+		 * Check if "git add -A" or "git add -u" was run from a
+		 * subdirectory with a modified file outside that directory,
+		 * and warn if so.
+		 *
+		 * "git add -u" will behave like "git add -u :/" instead of
+		 * "git add -u ." in the future.  This warning prepares for
+		 * that change.
+		 */
+		if (implicit_dot &&
+		    strncmp_icase(path, implicit_dot, implicit_dot_len)) {
+			warn_pathless_add();
+			continue;
+		}
 		switch (fix_unmerged_status(p, data)) {
 		default:
 			die(_("unexpected diff status %c"), p->status);
@@ -121,17 +140,30 @@ static void update_callback(struct diff_queue_struct *q,
 	}
 }
 
+#define ADD_CACHE_IMPLICIT_DOT 32
 int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
 {
 	struct update_callback_data data;
 	struct rev_info rev;
+
+	memset(&data, 0, sizeof(data));
+	data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
+	if ((flags & ADD_CACHE_IMPLICIT_DOT) && prefix) {
+		/*
+		 * Check for modified files throughout the worktree so
+		 * update_callback has a chance to warn about changes
+		 * outside the cwd.
+		 */
+		data.implicit_dot = prefix;
+		data.implicit_dot_len = strlen(prefix);
+		pathspec = NULL;
+	}
+
 	init_revisions(&rev, prefix);
 	setup_revisions(0, NULL, &rev, NULL);
 	init_pathspec(&rev.prune_data, pathspec);
 	rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
 	rev.diffopt.format_callback = update_callback;
-	data.flags = flags;
-	data.add_errors = 0;
 	rev.diffopt.format_callback_data = &data;
 	rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
 	run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
@@ -371,6 +403,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 	int add_new_files;
 	int require_pathspec;
 	char *seen = NULL;
+	int implicit_dot = 0;
 
 	git_config(add_config, NULL);
 
@@ -400,10 +433,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 	}
 	if (option_with_implicit_dot && !argc) {
 		static const char *here[2] = { ".", NULL };
-		if (prefix)
+		if (prefix && addremove)
 			warn_pathless_add();
 		argc = 1;
 		argv = here;
+		implicit_dot = 1;
 	}
 
 	add_new_files = !take_worktree_changes && !refresh_only;
@@ -416,7 +450,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		 (intent_to_add ? ADD_CACHE_INTENT : 0) |
 		 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
 		 (!(addremove || take_worktree_changes)
-		  ? ADD_CACHE_IGNORE_REMOVAL : 0));
+		  ? ADD_CACHE_IGNORE_REMOVAL : 0)) |
+		 (implicit_dot ? ADD_CACHE_IMPLICIT_DOT : 0);
 
 	if (require_pathspec && argc == 0) {
 		fprintf(stderr, _("Nothing specified, nothing added.\n"));
-- 
1.8.2.rc3

[PATCH 5/6] add -A: only show pathless 'add -A' warning when changes exist outside cwd

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:56:27

In the spirit of the recent similar change for 'git add -u', avoid
pestering users that restrict their attention to a subdirectory and
will not be affected by the coming change in the behavior of pathless
'git add -A'.

Signed-off-by: Jonathan Nieder <redacted>
---
As before.

 builtin/add.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/builtin/add.c b/builtin/add.c
index 4d8d441..2493493 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -170,7 +170,9 @@ int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
 	return !!data.add_errors;
 }
 
-static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
+#define WARN_IMPLICIT_DOT (1u << 0)
+static char *prune_directory(struct dir_struct *dir, const char **pathspec,
+			     int prefix, unsigned flag)
 {
 	char *seen;
 	int i, specs;
@@ -187,6 +189,16 @@ static char *prune_directory(struct dir_struct *dir, const char **pathspec, int
 		if (match_pathspec(pathspec, entry->name, entry->len,
 				   prefix, seen))
 			*dst++ = entry;
+		else if (flag & WARN_IMPLICIT_DOT)
+			/*
+			 * "git add -A" was run from a subdirectory with a
+			 * new file outside that directory.
+			 *
+			 * "git add -A" will behave like "git add -A :/"
+			 * instead of "git add -A ." in the future.
+			 * Warn about the coming behavior change.
+			 */
+			warn_pathless_add();
 	}
 	dir->nr = dst - dir->entries;
 	add_pathspec_matches_against_index(pathspec, seen, specs);
@@ -433,8 +445,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 	}
 	if (option_with_implicit_dot && !argc) {
 		static const char *here[2] = { ".", NULL };
-		if (prefix && addremove)
-			warn_pathless_add();
 		argc = 1;
 		argv = here;
 		implicit_dot = 1;
@@ -475,9 +485,10 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		}
 
 		/* This picks up the paths that are not tracked */
-		baselen = fill_directory(&dir, pathspec);
+		baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec);
 		if (pathspec)
-			seen = prune_directory(&dir, pathspec, baselen);
+			seen = prune_directory(&dir, pathspec, baselen,
+					implicit_dot ? WARN_IMPLICIT_DOT : 0);
 	}
 
 	if (refresh_only) {
-- 
1.8.2.rc3

[PATCH 6/6] git add: -u/-A now affects the entire working tree

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:56:27

From: Junio C Hamano <redacted>

As promised in 0fa2eb530fb7 (add: warn when -u or -A is used without
pathspec, 2013-01-28), in Git 2.0, "git add -u/-A" that is run
without pathspec in a subdirectory updates all updated paths in the
entire working tree, not just the current directory and its
subdirectories.

Signed-off-by: Junio C Hamano <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
Thanks for reading.

 Documentation/git-add.txt |  16 +++----
 builtin/add.c             | 110 ++++------------------------------------------
 t/t2200-add-update.sh     |   9 +---
 3 files changed, 19 insertions(+), 116 deletions(-)
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index b0944e5..02b99cb 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -104,10 +104,10 @@ apply to the index. See EDITING PATCHES below.
 	<pathspec>.  This removes as well as modifies index entries to
 	match the working tree, but adds no new files.
 +
-If no <pathspec> is given, the current version of Git defaults to
-"."; in other words, update all tracked files in the current directory
-and its subdirectories. This default will change in a future version
-of Git, hence the form without <pathspec> should not be used.
+If no <pathspec> is given when `-u` option is used, all
+tracked files in the entire working tree are updated (old versions
+of Git used to limit the update to the current directory and its
+subdirectories).
 
 -A::
 --all::
@@ -116,10 +116,10 @@ of Git, hence the form without <pathspec> should not be used.
 	entry.	This adds, modifies, and removes index entries to
 	match the working tree.
 +
-If no <pathspec> is given, the current version of Git defaults to
-"."; in other words, update all files in the current directory
-and its subdirectories. This default will change in a future version
-of Git, hence the form without <pathspec> should not be used.
+If no <pathspec> is given when `-A` option is used, all
+files in the entire working tree are updated (old versions
+of Git used to limit the update to the current directory and its
+subdirectories).
 
 -N::
 --intent-to-add::
diff --git a/builtin/add.c b/builtin/add.c
index 2493493..5c0a869 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -26,50 +26,8 @@ static int take_worktree_changes;
 struct update_callback_data {
 	int flags;
 	int add_errors;
-	const char *implicit_dot;
-	size_t implicit_dot_len;
 };
 
-static const char *option_with_implicit_dot;
-static const char *short_option_with_implicit_dot;
-
-static void warn_pathless_add(void)
-{
-	static int shown;
-	assert(option_with_implicit_dot && short_option_with_implicit_dot);
-
-	if (shown)
-		return;
-	shown = 1;
-
-	/*
-	 * 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, the behavior can be changed
-	 * to tree-wide, keeping the warning for a while, and
-	 * eventually we can drop the warning.
-	 */
-	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_with_implicit_dot, short_option_with_implicit_dot,
-		option_with_implicit_dot, short_option_with_implicit_dot,
-		option_with_implicit_dot, short_option_with_implicit_dot);
-}
-
 static int fix_unmerged_status(struct diff_filepair *p,
 			       struct update_callback_data *data)
 {
@@ -96,27 +54,11 @@ static void update_callback(struct diff_queue_struct *q,
 {
 	int i;
 	struct update_callback_data *data = cbdata;
-	const char *implicit_dot = data->implicit_dot;
-	size_t implicit_dot_len = data->implicit_dot_len;
 
 	for (i = 0; i < q->nr; i++) {
 		struct diff_filepair *p = q->queue[i];
 		const char *path = p->one->path;
 
-		/*
-		 * Check if "git add -A" or "git add -u" was run from a
-		 * subdirectory with a modified file outside that directory,
-		 * and warn if so.
-		 *
-		 * "git add -u" will behave like "git add -u :/" instead of
-		 * "git add -u ." in the future.  This warning prepares for
-		 * that change.
-		 */
-		if (implicit_dot &&
-		    strncmp_icase(path, implicit_dot, implicit_dot_len)) {
-			warn_pathless_add();
-			continue;
-		}
 		switch (fix_unmerged_status(p, data)) {
 		default:
 			die(_("unexpected diff status %c"), p->status);
@@ -140,24 +82,13 @@ static void update_callback(struct diff_queue_struct *q,
 	}
 }
 
-#define ADD_CACHE_IMPLICIT_DOT 32
 int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
 {
 	struct update_callback_data data;
 	struct rev_info rev;
 
 	memset(&data, 0, sizeof(data));
-	data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
-	if ((flags & ADD_CACHE_IMPLICIT_DOT) && prefix) {
-		/*
-		 * Check for modified files throughout the worktree so
-		 * update_callback has a chance to warn about changes
-		 * outside the cwd.
-		 */
-		data.implicit_dot = prefix;
-		data.implicit_dot_len = strlen(prefix);
-		pathspec = NULL;
-	}
+	data.flags = flags;
 
 	init_revisions(&rev, prefix);
 	setup_revisions(0, NULL, &rev, NULL);
@@ -170,9 +101,7 @@ int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
 	return !!data.add_errors;
 }
 
-#define WARN_IMPLICIT_DOT (1u << 0)
-static char *prune_directory(struct dir_struct *dir, const char **pathspec,
-			     int prefix, unsigned flag)
+static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
 {
 	char *seen;
 	int i, specs;
@@ -189,16 +118,6 @@ static char *prune_directory(struct dir_struct *dir, const char **pathspec,
 		if (match_pathspec(pathspec, entry->name, entry->len,
 				   prefix, seen))
 			*dst++ = entry;
-		else if (flag & WARN_IMPLICIT_DOT)
-			/*
-			 * "git add -A" was run from a subdirectory with a
-			 * new file outside that directory.
-			 *
-			 * "git add -A" will behave like "git add -A :/"
-			 * instead of "git add -A ." in the future.
-			 * Warn about the coming behavior change.
-			 */
-			warn_pathless_add();
 	}
 	dir->nr = dst - dir->entries;
 	add_pathspec_matches_against_index(pathspec, seen, specs);
@@ -415,7 +334,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 	int add_new_files;
 	int require_pathspec;
 	char *seen = NULL;
-	int implicit_dot = 0;
 
 	git_config(add_config, NULL);
 
@@ -435,19 +353,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		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) {
-		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 ((addremove || take_worktree_changes) && !argc) {
+		static const char *whole[2] = { ":/", NULL };
 		argc = 1;
-		argv = here;
-		implicit_dot = 1;
+		argv = whole;
 	}
 
 	add_new_files = !take_worktree_changes && !refresh_only;
@@ -460,8 +370,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		 (intent_to_add ? ADD_CACHE_INTENT : 0) |
 		 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
 		 (!(addremove || take_worktree_changes)
-		  ? ADD_CACHE_IGNORE_REMOVAL : 0)) |
-		 (implicit_dot ? ADD_CACHE_IMPLICIT_DOT : 0);
+		  ? ADD_CACHE_IGNORE_REMOVAL : 0));
 
 	if (require_pathspec && argc == 0) {
 		fprintf(stderr, _("Nothing specified, nothing added.\n"));
@@ -485,10 +394,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		}
 
 		/* This picks up the paths that are not tracked */
-		baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec);
+		baselen = fill_directory(&dir, pathspec);
 		if (pathspec)
-			seen = prune_directory(&dir, pathspec, baselen,
-					implicit_dot ? WARN_IMPLICIT_DOT : 0);
+			seen = prune_directory(&dir, pathspec, baselen);
 	}
 
 	if (refresh_only) {
diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh
index c317254..4281e18 100755
--- a/t/t2200-add-update.sh
+++ b/t/t2200-add-update.sh
@@ -80,18 +80,13 @@ test_expect_success 'change gets noticed' '
 
 '
 
-# Note that this is scheduled to change in Git 2.0, when
-# "git add -u" will become full-tree by default.
-test_expect_success 'non-limited update in subdir leaves root alone' '
+test_expect_success 'non-qualified update in subdir updates from the root' '
 	(
 		cd dir1 &&
 		echo even more >>sub2 &&
 		git add -u
 	) &&
-	cat >expect <<-\EOF &&
-	check
-	top
-	EOF
+	: >expect &&
 	git diff-files --name-only >actual &&
 	test_cmp expect actual
 '
-- 
1.8.2.rc3

Re: [PATCH 4/6] add -u: only show pathless 'add -u' warning when changes exist outside cwd

From: Jeff King <hidden>
Date: 2016-06-15 22:56:27

On Tue, Mar 19, 2013 at 03:50:50PM -0700, Jonathan Nieder wrote:
This is the interesting one.
[...]
 * summarized Peff's review with an Ack.  I hope that's ok.
Yeah, OK with me. I certainly agree with the intent, and I think your
reasoning on the performance change is valid.

I don't see anything wrong in the patch itself, except for one minor
nit:
quoted hunk
@@ -121,17 +140,30 @@ static void update_callback(struct diff_queue_struct *q,
 	}
 }
 
+#define ADD_CACHE_IMPLICIT_DOT 32
 int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
 {
 	struct update_callback_data data;
 	struct rev_info rev;
Should this be defined in cache.h with the other flags? I realize it's
mostly private to builtin/add.c, but without even a comment in cache.h
saying "/* 32 is reserved */", we run the risk of another commit
adding a new flag with the same number.

-Peff
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help