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 serves no purpose in this case.  So suppress the warning
unless there are changes outside the cwd that are not being added.

Signed-off-by: Jonathan Nieder <jrnie...@gmail.com>
---
 builtin/add.c | 51 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 7 deletions(-)

diff --git a/builtin/add.c b/builtin/add.c
index a424e69d..f05ec1c1 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -89,6 +89,22 @@ static int fix_unmerged_status(struct diff_filepair *p,
                return DIFF_STATUS_MODIFIED;
 }
 
+static void warn_if_outside_pathspec(struct diff_queue_struct *q,
+                                    struct diff_options *opt, void *cbdata)
+{
+       int i;
+       const char **pathspec = cbdata;
+
+       for (i = 0; i < q->nr; i++) {
+               const char *path = q->queue[i]->one->path;
+
+               if (!match_pathspec(pathspec, path, strlen(path), 0, NULL)) {
+                       warn_pathless_add();
+                       return;
+               }
+       }
+}
+
 static void update_callback(struct diff_queue_struct *q,
                            struct diff_options *opt, void *cbdata)
 {
@@ -121,20 +137,26 @@ static void update_callback(struct diff_queue_struct *q,
        }
 }
 
-int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
+static void diff_files_with_callback(const char *prefix, const char **pathspec,
+                                    diff_format_fn_t callback, void *data)
 {
-       struct update_callback_data data;
        struct rev_info rev;
        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.diffopt.format_callback = callback;
+       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);
+}
+
+int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
+{
+       struct update_callback_data data;
+       data.flags = flags;
+       data.add_errors = 0;
+       diff_files_with_callback(prefix, pathspec, update_callback, &data);
        return !!data.add_errors;
 }
 
@@ -371,6 +393,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 +423,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;
@@ -450,6 +474,19 @@ int cmd_add(int argc, const char **argv, const char 
*prefix)
                goto finish;
        }
 
+       /*
+        * 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)
+               diff_files_with_callback(prefix, NULL,
+                               warn_if_outside_pathspec, pathspec);
+
        if (pathspec) {
                int i;
                struct path_exclude_check check;
-- 
1.8.2.rc3

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to