{"thread":{"id":"13531","subject":"[BUG] git add -u ignores --dry-run flag","startedAt":"2008-05-15T16:08:24Z","lastAt":"2008-05-23T08:14:48Z","messageCount":13,"participants":["Gustaf Hendeby","Miklos Vajna","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"77050","messageId":"482C5FF8.1060200@isy.liu.se","threadId":"13531","inReplyTo":null,"subject":"[BUG] git add -u ignores --dry-run flag","fromName":"Gustaf Hendeby","fromEmail":"hendeby@isy.liu.se","sentAt":"2008-05-15T16:08:24Z","receivedAt":"2008-05-15T16:08:24Z","isPatch":false,"sender":{"key":"hendeby@isy.liu.se","avatar":"https://avatars.githubusercontent.com/u/730316?v=4"},"body":"Hi!\n\nI think this is a bug in the built in implementation of git add -u\n\n$ git --version\ngit version 1.5.5.1.373.ga3200\n$ git init\nInitialized empty Git repository in /home/hendeby/bar/.git/\n$ echo foo > foo\n$ git add foo && git commit -m \"Test\"\nCreated initial commit 7477e8b: Test\n  1 files changed, 1 insertions(+), 0 deletions(-)\n  create mode 100644 foo\n$ echo foo >> foo\n$ git add -u --dry-run\n$ git status\n# On branch master\n# Changes to be committed:\n#   (use \"git reset HEAD <file>...\" to unstage)\n#\n#       modified:   foo\n#\n\nI was expecting to get foo listed, and not actually added to the index.\n\nI've had a quick look in builtin-add.c, and the -u option is tested for \nbefore the --dry-run option, and in the process of handling the -u \noption the code makes a jump that bypasses the --dry-run handling. \nUnfortunately, I'm not familiar enough with the code to see how to best \nfix it.\n\n/Gustaf\n"},{"id":"77052","messageId":"1210868459-9511-1-git-send-email-vmiklos@frugalware.org","threadId":"13531","inReplyTo":"482C5FF8.1060200@isy.liu.se","subject":"[PATCH] Make git add -u honor --dry-run","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2008-05-15T16:20:59Z","receivedAt":"2008-05-15T16:20:59Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>\n---\n\nOn Thu, May 15, 2008 at 06:08:24PM +0200, Gustaf Hendeby <hendeby@isy.liu.se> wrote:\n> I'm not familiar enough with the code to see how to best fix it.\n\nSomething like this?\n\n builtin-add.c         |    3 ++-\n t/t2200-add-update.sh |    7 +++++++\n 2 files changed, 9 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin-add.c b/builtin-add.c\nindex 4a91e3e..222497d 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -212,7 +212,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t\tif (read_cache() < 0)\n \t\t\tdie(\"index file corrupt\");\n \t\tpathspec = get_pathspec(prefix, argv);\n-\t\tadd_files_to_cache(verbose, prefix, pathspec);\n+\t\tif(!show_only)\n+\t\t\tadd_files_to_cache(verbose, prefix, pathspec);\n \t\tgoto finish;\n \t}\n \ndiff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh\nindex b664341..13ad975 100755\n--- a/t/t2200-add-update.sh\n+++ b/t/t2200-add-update.sh\n@@ -88,6 +88,13 @@ test_expect_success 'replace a file with a symlink' '\n \n '\n \n+test_expect_success 'add everything changed with --dry-run' '\n+\n+\tgit add -u --dry-run &&\n+\ttest -n \"$(git diff-files)\"\n+\n+'\n+\n test_expect_success 'add everything changed' '\n \n \tgit add -u &&\n-- \n1.5.5.1.211.g65ea3.dirty\n"},{"id":"77061","messageId":"482C8515.6020303@isy.liu.se","threadId":"13531","inReplyTo":"1210868459-9511-1-git-send-email-vmiklos@frugalware.org","subject":"Re: [PATCH] Make git add -u honor --dry-run","fromName":"Gustaf Hendeby","fromEmail":"hendeby@isy.liu.se","sentAt":"2008-05-15T18:46:45Z","receivedAt":"2008-05-15T18:46:45Z","isPatch":true,"sender":{"key":"hendeby@isy.liu.se","avatar":"https://avatars.githubusercontent.com/u/730316?v=4"},"body":"On 2008-05-15 18:20, Miklos Vajna wrote:\n> Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>\n> ---\n> \n> On Thu, May 15, 2008 at 06:08:24PM +0200, Gustaf Hendeby <hendeby@isy.liu.se> wrote:\n>> I'm not familiar enough with the code to see how to best fix it.\n> \n> Something like this?\n\nThis fixes part of the problem.  Nothing gets written to the index now, \nhowever, I get no list of what files would have been added.  That is \nwhat I would have suspected.  Am I reading the docs incorrectly?\n\n> \n>  builtin-add.c         |    3 ++-\n>  t/t2200-add-update.sh |    7 +++++++\n>  2 files changed, 9 insertions(+), 1 deletions(-)\n> \n> diff --git a/builtin-add.c b/builtin-add.c\n> index 4a91e3e..222497d 100644\n> --- a/builtin-add.c\n> +++ b/builtin-add.c\n> @@ -212,7 +212,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n>  \t\tif (read_cache() < 0)\n>  \t\t\tdie(\"index file corrupt\");\n>  \t\tpathspec = get_pathspec(prefix, argv);\n> -\t\tadd_files_to_cache(verbose, prefix, pathspec);\n> +\t\tif(!show_only)\n> +\t\t\tadd_files_to_cache(verbose, prefix, pathspec);\n>  \t\tgoto finish;\n>  \t}\nSince the other code path for show_only, does not end up in finish but \nreturns 0 directly, I'm assuming the same could be done here (after \nprinting the changed files) to save some cycles.\n\n>  \n> diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh\n> index b664341..13ad975 100755\n> --- a/t/t2200-add-update.sh\n> +++ b/t/t2200-add-update.sh\n> @@ -88,6 +88,13 @@ test_expect_success 'replace a file with a symlink' '\n>  \n>  '\n>  \n> +test_expect_success 'add everything changed with --dry-run' '\n> +\n> +\tgit add -u --dry-run &&\n> +\ttest -n \"$(git diff-files)\"\nDon't you need to validate the output from git add -u --dry-run too?\n\n/Gustaf\n\n> +\n> +'\n> +\n>  test_expect_success 'add everything changed' '\n>  \n>  \tgit add -u &&\n"},{"id":"77085","messageId":"7vmymrf81x.fsf@gitster.siamese.dyndns.org","threadId":"13531","inReplyTo":"1210868459-9511-1-git-send-email-vmiklos@frugalware.org","subject":"Re* [PATCH] Make git add -u honor --dry-run","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-15T23:42:50Z","receivedAt":"2008-05-15T23:42:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Miklos Vajna <vmiklos@frugalware.org> writes:\n\n> Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>\n> ---\n>\n> On Thu, May 15, 2008 at 06:08:24PM +0200, Gustaf Hendeby <hendeby@isy.liu.se> wrote:\n>> I'm not familiar enough with the code to see how to best fix it.\n>\n> Something like this?\n>\n>  builtin-add.c         |    3 ++-\n>  t/t2200-add-update.sh |    7 +++++++\n>  2 files changed, 9 insertions(+), 1 deletions(-)\n>\n> diff --git a/builtin-add.c b/builtin-add.c\n> index 4a91e3e..222497d 100644\n> --- a/builtin-add.c\n> +++ b/builtin-add.c\n> @@ -212,7 +212,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n>  \t\tif (read_cache() < 0)\n>  \t\t\tdie(\"index file corrupt\");\n>  \t\tpathspec = get_pathspec(prefix, argv);\n> -\t\tadd_files_to_cache(verbose, prefix, pathspec);\n> +\t\tif(!show_only)\n> +\t\t\tadd_files_to_cache(verbose, prefix, pathspec);\n>  \t\tgoto finish;\n>  \t}\n\nThat makes the whole thing noop, doesn't it?  We could do the surgery at a\nbit lower layer, I guess.\n\n\n cache.h          |    8 +++++---\n builtin-add.c    |   22 +++++++++++++---------\n builtin-commit.c |    2 +-\n builtin-mv.c     |    2 +-\n read-cache.c     |   20 ++++++++++++++++----\n 5 files changed, 36 insertions(+), 18 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 98cfed6..cf30e53 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -173,7 +173,7 @@ extern struct index_state the_index;\n #define add_cache_entry(ce, option) add_index_entry(&the_index, (ce), (option))\n #define remove_cache_entry_at(pos) remove_index_entry_at(&the_index, (pos))\n #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path))\n-#define add_file_to_cache(path, verbose) add_file_to_index(&the_index, (path), (verbose))\n+#define add_file_to_cache(path, flags) add_file_to_index(&the_index, (path), (flags))\n #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL)\n #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))\n #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))\n@@ -272,7 +272,9 @@ extern int add_index_entry(struct index_state *, struct cache_entry *ce, int opt\n extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);\n extern int remove_index_entry_at(struct index_state *, int pos);\n extern int remove_file_from_index(struct index_state *, const char *path);\n-extern int add_file_to_index(struct index_state *, const char *path, int verbose);\n+#define ADD_CACHE_VERBOSE 1\n+#define ADD_CACHE_PRETEND 2\n+extern int add_file_to_index(struct index_state *, const char *path, int flags);\n extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);\n extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);\n \n@@ -640,7 +642,7 @@ extern int convert_to_git(const char *path, const char *src, size_t len, struct\n extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);\n \n /* add */\n-void add_files_to_cache(int verbose, const char *prefix, const char **pathspec);\n+void add_files_to_cache(const char *prefix, const char **pathspec, int flags);\n \n /* diff.c */\n extern int diff_auto_refresh_index;\ndiff --git a/builtin-add.c b/builtin-add.c\nindex 4a91e3e..cb61366 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -82,9 +82,9 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec,\n static void update_callback(struct diff_queue_struct *q,\n \t\t\t    struct diff_options *opt, void *cbdata)\n {\n-\tint i, verbose;\n+\tint i, flags;\n \n-\tverbose = *((int *)cbdata);\n+\tflags = *((int *)cbdata);\n \tfor (i = 0; i < q->nr; i++) {\n \t\tstruct diff_filepair *p = q->queue[i];\n \t\tconst char *path = p->one->path;\n@@ -94,18 +94,19 @@ static void update_callback(struct diff_queue_struct *q,\n \t\tcase DIFF_STATUS_UNMERGED:\n \t\tcase DIFF_STATUS_MODIFIED:\n \t\tcase DIFF_STATUS_TYPE_CHANGED:\n-\t\t\tadd_file_to_cache(path, verbose);\n+\t\t\tadd_file_to_cache(path, flags);\n \t\t\tbreak;\n \t\tcase DIFF_STATUS_DELETED:\n-\t\t\tremove_file_from_cache(path);\n-\t\t\tif (verbose)\n+\t\t\tif (!(flags & ADD_CACHE_PRETEND))\n+\t\t\t\tremove_file_from_cache(path);\n+\t\t\tif (flags)\n \t\t\t\tprintf(\"remove '%s'\\n\", path);\n \t\t\tbreak;\n \t\t}\n \t}\n }\n \n-void add_files_to_cache(int verbose, const char *prefix, const char **pathspec)\n+void add_files_to_cache(const char *prefix, const char **pathspec, int flags)\n {\n \tstruct rev_info rev;\n \tinit_revisions(&rev, prefix);\n@@ -113,7 +114,7 @@ void add_files_to_cache(int verbose, const char *prefix, const char **pathspec)\n \trev.prune_data = pathspec;\n \trev.diffopt.output_format = DIFF_FORMAT_CALLBACK;\n \trev.diffopt.format_callback = update_callback;\n-\trev.diffopt.format_callback_data = &verbose;\n+\trev.diffopt.format_callback_data = &flags;\n \trun_diff_files(&rev, DIFF_RACY_IS_MODIFIED);\n }\n \n@@ -209,10 +210,13 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \n \tif (take_worktree_changes) {\n \t\tconst char **pathspec;\n+\t\tint flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |\n+\t\t\t     (show_only ? ADD_CACHE_PRETEND : 0));\n+\n \t\tif (read_cache() < 0)\n \t\t\tdie(\"index file corrupt\");\n \t\tpathspec = get_pathspec(prefix, argv);\n-\t\tadd_files_to_cache(verbose, prefix, pathspec);\n+\t\tadd_files_to_cache(prefix, pathspec, flags);\n \t\tgoto finish;\n \t}\n \n@@ -254,7 +258,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t}\n \n \tfor (i = 0; i < dir.nr; i++)\n-\t\tadd_file_to_cache(dir.entries[i]->name, verbose);\n+\t\tadd_file_to_cache(dir.entries[i]->name, ADD_CACHE_VERBOSE);\n \n  finish:\n \tif (active_cache_changed) {\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex 2f4d6cc..f31bf59 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -239,7 +239,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)\n \t */\n \tif (all || (also && pathspec && *pathspec)) {\n \t\tint fd = hold_locked_index(&index_lock, 1);\n-\t\tadd_files_to_cache(0, also ? prefix : NULL, pathspec);\n+\t\tadd_files_to_cache(also ? prefix : NULL, pathspec, 0);\n \t\trefresh_cache(REFRESH_QUIET);\n \t\tif (write_cache(fd, active_cache, active_nr) ||\n \t\t    close_lock_file(&index_lock))\ndiff --git a/builtin-mv.c b/builtin-mv.c\nindex 990e213..1ad3178 100644\n--- a/builtin-mv.c\n+++ b/builtin-mv.c\n@@ -256,7 +256,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \n \t\tfor (i = 0; i < added.nr; i++) {\n \t\t\tconst char *path = added.items[i].path;\n-\t\t\tadd_file_to_cache(path, verbose);\n+\t\t\tadd_file_to_cache(path, verbose ? ADD_CACHE_VERBOSE : 0);\n \t\t}\n \n \t\tfor (i = 0; i < deleted.nr; i++)\ndiff --git a/read-cache.c b/read-cache.c\nindex 7db5588..a95861b 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -384,12 +384,14 @@ static int index_name_pos_also_unmerged(struct index_state *istate,\n \treturn pos;\n }\n \n-int add_file_to_index(struct index_state *istate, const char *path, int verbose)\n+int add_file_to_index(struct index_state *istate, const char *path, int flags)\n {\n-\tint size, namelen, pos;\n+\tint size, namelen, pos, was_same;\n \tstruct stat st;\n \tstruct cache_entry *ce;\n \tunsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;\n+\tint verbose = flags & (ADD_CACHE_VERBOSE|ADD_CACHE_PRETEND);\n+\tint pretend = flags & ADD_CACHE_PRETEND;\n \n \tif (lstat(path, &st))\n \t\tdie(\"%s: unable to stat (%s)\", path, strerror(errno));\n@@ -432,9 +434,19 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose)\n \n \tif (index_path(ce->sha1, path, &st, 1))\n \t\tdie(\"unable to index file %s\", path);\n-\tif (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n+\n+\t/* It was suspected to be racily clean but it turns out to be Ok */\n+\twas_same = (0 <= pos &&\n+\t\t    !ce_stage(istate->cache[pos]) &&\n+\t\t    !hashcmp(ce->sha1, istate->cache[pos]->sha1) &&\n+\t\t    ce->ce_mode == istate->cache[pos]->ce_mode);\n+\n+\tif (pretend)\n+\t\t;\n+\telse if (add_index_entry(istate, ce,\n+\t\t\t\t ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n \t\tdie(\"unable to add %s to index\",path);\n-\tif (verbose)\n+\tif (verbose && !was_same)\n \t\tprintf(\"add '%s'\\n\", path);\n \treturn 0;\n }\n"},{"id":"77089","messageId":"20080516001305.GR27724@genesis.frugalware.org","threadId":"13531","inReplyTo":"7vmymrf81x.fsf@gitster.siamese.dyndns.org","subject":"Re: Re* [PATCH] Make git add -u honor --dry-run","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2008-05-16T00:13:05Z","receivedAt":"2008-05-16T00:13:05Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Thu, May 15, 2008 at 04:42:50PM -0700, Junio C Hamano <gitster@pobox.com> wrote:\n> That makes the whole thing noop, doesn't it?\n\nExactly. I just considered git add -u --dry-run doing anything a bug.\nThen Gustaf pointed out that it would be nice to print the to-be-added\nfiles. Just forget my patch. :)\n"},{"id":"77296","messageId":"4831FBD8.3050402@isy.liu.se","threadId":"13531","inReplyTo":"7vmymrf81x.fsf@gitster.siamese.dyndns.org","subject":"Re: Re* [PATCH] Make git add -u honor --dry-run","fromName":"Gustaf Hendeby","fromEmail":"hendeby@isy.liu.se","sentAt":"2008-05-19T22:14:48Z","receivedAt":"2008-05-19T22:14:48Z","isPatch":true,"sender":{"key":"hendeby@isy.liu.se","avatar":"https://avatars.githubusercontent.com/u/730316?v=4"},"body":"On 2008-05-16 01:42, Junio C Hamano wrote:\n> Miklos Vajna <vmiklos@frugalware.org> writes:\n>> On Thu, May 15, 2008 at 06:08:24PM +0200, Gustaf Hendeby <hendeby@isy.liu.se> wrote:\n>>> I'm not familiar enough with the code to see how to best fix it.\n> \n> That makes the whole thing noop, doesn't it?  We could do the surgery at a\n> bit lower layer, I guess.\n\nWhat is the status on this one?  I've been away for a while and when I \ngot back I didn't see any more than this suggestion.  I'm really in over \nmy head here, but I think (judging from a compiler warning) the \nfollowing needs to be amended:\n\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex cf9875c..39fef84 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -282,7 +282,7 @@ static int merge_working_tree(struct checkout_opts \n*opts,\n                          * entries in the index.\n                          */\n\n-                       add_files_to_cache(0, NULL, NULL);\n+                       add_files_to_cache(NULL, NULL, 0);\n                         work = write_tree_from_memory();\n\n                         ret = reset_to_new(new->commit->tree, opts->quiet);\n\n\nI had started to think about a much less intrusive solution limited to \nbuiltin-add.c but, without really understanding all that is going on \nhere, this seems to be a more flexible and better solution for the long run.\n\n/Gustaf\n\n> \n> \n>  cache.h          |    8 +++++---\n>  builtin-add.c    |   22 +++++++++++++---------\n>  builtin-commit.c |    2 +-\n>  builtin-mv.c     |    2 +-\n>  read-cache.c     |   20 ++++++++++++++++----\n>  5 files changed, 36 insertions(+), 18 deletions(-)\n> \n> diff --git a/cache.h b/cache.h\n> index 98cfed6..cf30e53 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -173,7 +173,7 @@ extern struct index_state the_index;\n>  #define add_cache_entry(ce, option) add_index_entry(&the_index, (ce), (option))\n>  #define remove_cache_entry_at(pos) remove_index_entry_at(&the_index, (pos))\n>  #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path))\n> -#define add_file_to_cache(path, verbose) add_file_to_index(&the_index, (path), (verbose))\n> +#define add_file_to_cache(path, flags) add_file_to_index(&the_index, (path), (flags))\n>  #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL)\n>  #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))\n>  #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))\n> @@ -272,7 +272,9 @@ extern int add_index_entry(struct index_state *, struct cache_entry *ce, int opt\n>  extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);\n>  extern int remove_index_entry_at(struct index_state *, int pos);\n>  extern int remove_file_from_index(struct index_state *, const char *path);\n> -extern int add_file_to_index(struct index_state *, const char *path, int verbose);\n> +#define ADD_CACHE_VERBOSE 1\n> +#define ADD_CACHE_PRETEND 2\n> +extern int add_file_to_index(struct index_state *, const char *path, int flags);\n>  extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);\n>  extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);\n>  \n> @@ -640,7 +642,7 @@ extern int convert_to_git(const char *path, const char *src, size_t len, struct\n>  extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);\n>  \n>  /* add */\n> -void add_files_to_cache(int verbose, const char *prefix, const char **pathspec);\n> +void add_files_to_cache(const char *prefix, const char **pathspec, int flags);\n>  \n>  /* diff.c */\n>  extern int diff_auto_refresh_index;\n> diff --git a/builtin-add.c b/builtin-add.c\n> index 4a91e3e..cb61366 100644\n> --- a/builtin-add.c\n> +++ b/builtin-add.c\n> @@ -82,9 +82,9 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec,\n>  static void update_callback(struct diff_queue_struct *q,\n>  \t\t\t    struct diff_options *opt, void *cbdata)\n>  {\n> -\tint i, verbose;\n> +\tint i, flags;\n>  \n> -\tverbose = *((int *)cbdata);\n> +\tflags = *((int *)cbdata);\n>  \tfor (i = 0; i < q->nr; i++) {\n>  \t\tstruct diff_filepair *p = q->queue[i];\n>  \t\tconst char *path = p->one->path;\n> @@ -94,18 +94,19 @@ static void update_callback(struct diff_queue_struct *q,\n>  \t\tcase DIFF_STATUS_UNMERGED:\n>  \t\tcase DIFF_STATUS_MODIFIED:\n>  \t\tcase DIFF_STATUS_TYPE_CHANGED:\n> -\t\t\tadd_file_to_cache(path, verbose);\n> +\t\t\tadd_file_to_cache(path, flags);\n>  \t\t\tbreak;\n>  \t\tcase DIFF_STATUS_DELETED:\n> -\t\t\tremove_file_from_cache(path);\n> -\t\t\tif (verbose)\n> +\t\t\tif (!(flags & ADD_CACHE_PRETEND))\n> +\t\t\t\tremove_file_from_cache(path);\n> +\t\t\tif (flags)\n>  \t\t\t\tprintf(\"remove '%s'\\n\", path);\n>  \t\t\tbreak;\n>  \t\t}\n>  \t}\n>  }\n>  \n> -void add_files_to_cache(int verbose, const char *prefix, const char **pathspec)\n> +void add_files_to_cache(const char *prefix, const char **pathspec, int flags)\n>  {\n>  \tstruct rev_info rev;\n>  \tinit_revisions(&rev, prefix);\n> @@ -113,7 +114,7 @@ void add_files_to_cache(int verbose, const char *prefix, const char **pathspec)\n>  \trev.prune_data = pathspec;\n>  \trev.diffopt.output_format = DIFF_FORMAT_CALLBACK;\n>  \trev.diffopt.format_callback = update_callback;\n> -\trev.diffopt.format_callback_data = &verbose;\n> +\trev.diffopt.format_callback_data = &flags;\n>  \trun_diff_files(&rev, DIFF_RACY_IS_MODIFIED);\n>  }\n>  \n> @@ -209,10 +210,13 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n>  \n>  \tif (take_worktree_changes) {\n>  \t\tconst char **pathspec;\n> +\t\tint flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |\n> +\t\t\t     (show_only ? ADD_CACHE_PRETEND : 0));\n> +\n>  \t\tif (read_cache() < 0)\n>  \t\t\tdie(\"index file corrupt\");\n>  \t\tpathspec = get_pathspec(prefix, argv);\n> -\t\tadd_files_to_cache(verbose, prefix, pathspec);\n> +\t\tadd_files_to_cache(prefix, pathspec, flags);\n>  \t\tgoto finish;\n>  \t}\n>  \n> @@ -254,7 +258,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n>  \t}\n>  \n>  \tfor (i = 0; i < dir.nr; i++)\n> -\t\tadd_file_to_cache(dir.entries[i]->name, verbose);\n> +\t\tadd_file_to_cache(dir.entries[i]->name, ADD_CACHE_VERBOSE);\n>  \n>   finish:\n>  \tif (active_cache_changed) {\n> diff --git a/builtin-commit.c b/builtin-commit.c\n> index 2f4d6cc..f31bf59 100644\n> --- a/builtin-commit.c\n> +++ b/builtin-commit.c\n> @@ -239,7 +239,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)\n>  \t */\n>  \tif (all || (also && pathspec && *pathspec)) {\n>  \t\tint fd = hold_locked_index(&index_lock, 1);\n> -\t\tadd_files_to_cache(0, also ? prefix : NULL, pathspec);\n> +\t\tadd_files_to_cache(also ? prefix : NULL, pathspec, 0);\n>  \t\trefresh_cache(REFRESH_QUIET);\n>  \t\tif (write_cache(fd, active_cache, active_nr) ||\n>  \t\t    close_lock_file(&index_lock))\n> diff --git a/builtin-mv.c b/builtin-mv.c\n> index 990e213..1ad3178 100644\n> --- a/builtin-mv.c\n> +++ b/builtin-mv.c\n> @@ -256,7 +256,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n>  \n>  \t\tfor (i = 0; i < added.nr; i++) {\n>  \t\t\tconst char *path = added.items[i].path;\n> -\t\t\tadd_file_to_cache(path, verbose);\n> +\t\t\tadd_file_to_cache(path, verbose ? ADD_CACHE_VERBOSE : 0);\n>  \t\t}\n>  \n>  \t\tfor (i = 0; i < deleted.nr; i++)\n> diff --git a/read-cache.c b/read-cache.c\n> index 7db5588..a95861b 100644\n> --- a/read-cache.c\n> +++ b/read-cache.c\n> @@ -384,12 +384,14 @@ static int index_name_pos_also_unmerged(struct index_state *istate,\n>  \treturn pos;\n>  }\n>  \n> -int add_file_to_index(struct index_state *istate, const char *path, int verbose)\n> +int add_file_to_index(struct index_state *istate, const char *path, int flags)\n>  {\n> -\tint size, namelen, pos;\n> +\tint size, namelen, pos, was_same;\n>  \tstruct stat st;\n>  \tstruct cache_entry *ce;\n>  \tunsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;\n> +\tint verbose = flags & (ADD_CACHE_VERBOSE|ADD_CACHE_PRETEND);\n> +\tint pretend = flags & ADD_CACHE_PRETEND;\n>  \n>  \tif (lstat(path, &st))\n>  \t\tdie(\"%s: unable to stat (%s)\", path, strerror(errno));\n> @@ -432,9 +434,19 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose)\n>  \n>  \tif (index_path(ce->sha1, path, &st, 1))\n>  \t\tdie(\"unable to index file %s\", path);\n> -\tif (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n> +\n> +\t/* It was suspected to be racily clean but it turns out to be Ok */\n> +\twas_same = (0 <= pos &&\n> +\t\t    !ce_stage(istate->cache[pos]) &&\n> +\t\t    !hashcmp(ce->sha1, istate->cache[pos]->sha1) &&\n> +\t\t    ce->ce_mode == istate->cache[pos]->ce_mode);\n> +\n> +\tif (pretend)\n> +\t\t;\n> +\telse if (add_index_entry(istate, ce,\n> +\t\t\t\t ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n>  \t\tdie(\"unable to add %s to index\",path);\n> -\tif (verbose)\n> +\tif (verbose && !was_same)\n>  \t\tprintf(\"add '%s'\\n\", path);\n>  \treturn 0;\n>  }\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n"},{"id":"77487","messageId":"7vskwauruo.fsf@gitster.siamese.dyndns.org","threadId":"13531","inReplyTo":"4831FBD8.3050402@isy.liu.se","subject":"Re: Re* [PATCH] Make git add -u honor --dry-run","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-22T18:16:31Z","receivedAt":"2008-05-22T18:16:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Gustaf Hendeby <hendeby@isy.liu.se> writes:\n\n> On 2008-05-16 01:42, Junio C Hamano wrote:\n>> Miklos Vajna <vmiklos@frugalware.org> writes:\n>>> On Thu, May 15, 2008 at 06:08:24PM +0200, Gustaf Hendeby <hendeby@isy.liu.se> wrote:\n>>>> I'm not familiar enough with the code to see how to best fix it.\n>>\n>> That makes the whole thing noop, doesn't it?  We could do the surgery at a\n>> bit lower layer, I guess.\n>\n> What is the status on this one?  I've been away for a while and when I\n> got back I didn't see any more than this suggestion.\n\nWe need a slightly different patch for 'master' (for 1.5.6) and 'maint'\n(for 1.5.5.X), due to recent introduction of add_to_index() API.  This is\nan updated one for 'master'; I rolled your one-liner fix into it as well.\n\n-- >8 --\nSubject: \"git-add -n -u\" should not add but just report\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-add.c         |   22 +++++++++++++---------\n builtin-checkout.c    |    2 +-\n builtin-commit.c      |    2 +-\n builtin-mv.c          |    2 +-\n cache.h               |   12 +++++++-----\n read-cache.c          |   23 +++++++++++++++++------\n t/t2200-add-update.sh |   17 +++++++++++++++++\n 7 files changed, 57 insertions(+), 23 deletions(-)\n\ndiff --git a/builtin-add.c b/builtin-add.c\nindex 4a91e3e..05af57f 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -82,9 +82,9 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec,\n static void update_callback(struct diff_queue_struct *q,\n \t\t\t    struct diff_options *opt, void *cbdata)\n {\n-\tint i, verbose;\n+\tint i, flags;\n \n-\tverbose = *((int *)cbdata);\n+\tflags = *((int *)cbdata);\n \tfor (i = 0; i < q->nr; i++) {\n \t\tstruct diff_filepair *p = q->queue[i];\n \t\tconst char *path = p->one->path;\n@@ -94,18 +94,19 @@ static void update_callback(struct diff_queue_struct *q,\n \t\tcase DIFF_STATUS_UNMERGED:\n \t\tcase DIFF_STATUS_MODIFIED:\n \t\tcase DIFF_STATUS_TYPE_CHANGED:\n-\t\t\tadd_file_to_cache(path, verbose);\n+\t\t\tadd_file_to_cache(path, flags);\n \t\t\tbreak;\n \t\tcase DIFF_STATUS_DELETED:\n-\t\t\tremove_file_from_cache(path);\n-\t\t\tif (verbose)\n+\t\t\tif (!(flags & ADD_CACHE_PRETEND))\n+\t\t\t\tremove_file_from_cache(path);\n+\t\t\tif (flags)\n \t\t\t\tprintf(\"remove '%s'\\n\", path);\n \t\t\tbreak;\n \t\t}\n \t}\n }\n \n-void add_files_to_cache(int verbose, const char *prefix, const char **pathspec)\n+void add_files_to_cache(const char *prefix, const char **pathspec, int flags)\n {\n \tstruct rev_info rev;\n \tinit_revisions(&rev, prefix);\n@@ -113,7 +114,7 @@ void add_files_to_cache(int verbose, const char *prefix, const char **pathspec)\n \trev.prune_data = pathspec;\n \trev.diffopt.output_format = DIFF_FORMAT_CALLBACK;\n \trev.diffopt.format_callback = update_callback;\n-\trev.diffopt.format_callback_data = &verbose;\n+\trev.diffopt.format_callback_data = &flags;\n \trun_diff_files(&rev, DIFF_RACY_IS_MODIFIED);\n }\n \n@@ -209,10 +210,13 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \n \tif (take_worktree_changes) {\n \t\tconst char **pathspec;\n+\t\tint flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |\n+\t\t\t     (show_only ? ADD_CACHE_PRETEND : 0));\n+\n \t\tif (read_cache() < 0)\n \t\t\tdie(\"index file corrupt\");\n \t\tpathspec = get_pathspec(prefix, argv);\n-\t\tadd_files_to_cache(verbose, prefix, pathspec);\n+\t\tadd_files_to_cache(prefix, pathspec, flags);\n \t\tgoto finish;\n \t}\n \n@@ -254,7 +258,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t}\n \n \tfor (i = 0; i < dir.nr; i++)\n-\t\tadd_file_to_cache(dir.entries[i]->name, verbose);\n+\t\tadd_file_to_cache(dir.entries[i]->name, verbose ? ADD_CACHE_VERBOSE : 0);\n \n  finish:\n \tif (active_cache_changed) {\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex 10ec137..05c0642 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -282,7 +282,7 @@ static int merge_working_tree(struct checkout_opts *opts,\n \t\t\t * entries in the index.\n \t\t\t */\n \n-\t\t\tadd_files_to_cache(0, NULL, NULL);\n+\t\t\tadd_files_to_cache(NULL, NULL, 0);\n \t\t\twork = write_tree_from_memory();\n \n \t\t\tret = reset_to_new(new->commit->tree, opts->quiet);\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex 0baec6d..924fca1 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -246,7 +246,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)\n \t */\n \tif (all || (also && pathspec && *pathspec)) {\n \t\tint fd = hold_locked_index(&index_lock, 1);\n-\t\tadd_files_to_cache(0, also ? prefix : NULL, pathspec);\n+\t\tadd_files_to_cache(also ? prefix : NULL, pathspec, 0);\n \t\trefresh_cache(REFRESH_QUIET);\n \t\tif (write_cache(fd, active_cache, active_nr) ||\n \t\t    close_lock_file(&index_lock))\ndiff --git a/builtin-mv.c b/builtin-mv.c\nindex 94f6dd2..df9ea97 100644\n--- a/builtin-mv.c\n+++ b/builtin-mv.c\n@@ -256,7 +256,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \n \t\tfor (i = 0; i < added.nr; i++) {\n \t\t\tconst char *path = added.items[i].path;\n-\t\t\tadd_file_to_cache(path, verbose);\n+\t\t\tadd_file_to_cache(path, verbose ? ADD_CACHE_VERBOSE : 0);\n \t\t}\n \n \t\tfor (i = 0; i < deleted.nr; i++)\ndiff --git a/cache.h b/cache.h\nindex 093f04c..b1a8427 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -261,8 +261,8 @@ static inline void remove_name_hash(struct cache_entry *ce)\n #define add_cache_entry(ce, option) add_index_entry(&the_index, (ce), (option))\n #define remove_cache_entry_at(pos) remove_index_entry_at(&the_index, (pos))\n #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path))\n-#define add_to_cache(path, st, verbose) add_to_index(&the_index, (path), (st), (verbose))\n-#define add_file_to_cache(path, verbose) add_file_to_index(&the_index, (path), (verbose))\n+#define add_to_cache(path, st, flags) add_to_index(&the_index, (path), (st), (flags))\n+#define add_file_to_cache(path, flags) add_file_to_index(&the_index, (path), (flags))\n #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL)\n #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))\n #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))\n@@ -366,8 +366,10 @@ extern int add_index_entry(struct index_state *, struct cache_entry *ce, int opt\n extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);\n extern int remove_index_entry_at(struct index_state *, int pos);\n extern int remove_file_from_index(struct index_state *, const char *path);\n-extern int add_to_index(struct index_state *, const char *path, struct stat *, int verbose);\n-extern int add_file_to_index(struct index_state *, const char *path, int verbose);\n+#define ADD_CACHE_VERBOSE 1\n+#define ADD_CACHE_PRETEND 2\n+extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);\n+extern int add_file_to_index(struct index_state *, const char *path, int flags);\n extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);\n extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);\n \n@@ -782,7 +784,7 @@ extern int convert_to_git(const char *path, const char *src, size_t len,\n extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);\n \n /* add */\n-void add_files_to_cache(int verbose, const char *prefix, const char **pathspec);\n+void add_files_to_cache(const char *prefix, const char **pathspec, int flags);\n \n /* diff.c */\n extern int diff_auto_refresh_index;\ndiff --git a/read-cache.c b/read-cache.c\nindex 0382804..5d967e8 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -462,12 +462,14 @@ static struct cache_entry *create_alias_ce(struct cache_entry *ce, struct cache_\n \treturn new;\n }\n \n-int add_to_index(struct index_state *istate, const char *path, struct stat *st, int verbose)\n+int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)\n {\n-\tint size, namelen;\n+\tint size, namelen, was_same;\n \tmode_t st_mode = st->st_mode;\n \tstruct cache_entry *ce, *alias;\n \tunsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;\n+\tint verbose = flags & (ADD_CACHE_VERBOSE | ADD_CACHE_PRETEND);\n+\tint pretend = flags & ADD_CACHE_PRETEND;\n \n \tif (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))\n \t\tdie(\"%s: can only add regular files, symbolic links or git-directories\", path);\n@@ -509,19 +511,28 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \tif (ignore_case && alias && different_name(ce, alias))\n \t\tce = create_alias_ce(ce, alias);\n \tce->ce_flags |= CE_ADDED;\n-\tif (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n+\n+\t/* It was suspected to be recily clean, but it turns out to be Ok */\n+\twas_same = (alias &&\n+\t\t    !ce_stage(alias) &&\n+\t\t    !hashcmp(alias->sha1, ce->sha1) &&\n+\t\t    ce->ce_mode == alias->ce_mode);\n+\n+\tif (pretend)\n+\t\t;\n+\telse if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n \t\tdie(\"unable to add %s to index\",path);\n-\tif (verbose)\n+\tif (verbose && !was_same)\n \t\tprintf(\"add '%s'\\n\", path);\n \treturn 0;\n }\n \n-int add_file_to_index(struct index_state *istate, const char *path, int verbose)\n+int add_file_to_index(struct index_state *istate, const char *path, int flags)\n {\n \tstruct stat st;\n \tif (lstat(path, &st))\n \t\tdie(\"%s: unable to stat (%s)\", path, strerror(errno));\n-\treturn add_to_index(istate, path, &st, verbose);\n+\treturn add_to_index(istate, path, &st, flags);\n }\n \n struct cache_entry *make_cache_entry(unsigned int mode,\ndiff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh\nindex b664341..f57a6e0 100755\n--- a/t/t2200-add-update.sh\n+++ b/t/t2200-add-update.sh\n@@ -111,4 +111,21 @@ test_expect_success 'touch and then add explicitly' '\n \n '\n \n+test_expect_success 'add -n -u should not add but just report' '\n+\n+\t(\n+\t\techo \"add '\\''check'\\''\" &&\n+\t\techo \"remove '\\''top'\\''\"\n+\t) >expect &&\n+\tbefore=$(git ls-files -s check top) &&\n+\techo changed >>check &&\n+\trm -f top &&\n+\tgit add -n -u >actual &&\n+\tafter=$(git ls-files -s check top) &&\n+\n+\ttest \"$before\" = \"$after\" &&\n+\ttest_cmp expect actual\n+\n+'\n+\n test_done\n"},{"id":"77490","messageId":"4835CACE.1070006@isy.liu.se","threadId":"13531","inReplyTo":"7vskwauruo.fsf@gitster.siamese.dyndns.org","subject":"Re: Re* [PATCH] Make git add -u honor --dry-run","fromName":"Gustaf Hendeby","fromEmail":"hendeby@isy.liu.se","sentAt":"2008-05-22T19:34:38Z","receivedAt":"2008-05-22T19:34:38Z","isPatch":true,"sender":{"key":"hendeby@isy.liu.se","avatar":"https://avatars.githubusercontent.com/u/730316?v=4"},"body":"On 2008-05-22 20:16, Junio C Hamano wrote:\n> Gustaf Hendeby <hendeby@isy.liu.se> writes:\n> \n>> On 2008-05-16 01:42, Junio C Hamano wrote:\n>>> Miklos Vajna <vmiklos@frugalware.org> writes:\n>>>> On Thu, May 15, 2008 at 06:08:24PM +0200, Gustaf Hendeby <hendeby@isy.liu.se> wrote:\n>>>>> I'm not familiar enough with the code to see how to best fix it.\n>>> That makes the whole thing noop, doesn't it?  We could do the surgery at a\n>>> bit lower layer, I guess.\n>> What is the status on this one?  I've been away for a while and when I\n>> got back I didn't see any more than this suggestion.\n> \n> We need a slightly different patch for 'master' (for 1.5.6) and 'maint'\n> (for 1.5.5.X), due to recent introduction of add_to_index() API.  This is\n> an updated one for 'master'; I rolled your one-liner fix into it as well.\n\nI'm sorry, but I don't get this to apply cleanly at all.  Did I \nmisunderstand you, or is it actually meant for master (1af8bca)?  The \nmerge is too complicated for me to do anything sensible with.\n\n/Gustaf\n\n> \n> -- >8 --\n> Subject: \"git-add -n -u\" should not add but just report\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  builtin-add.c         |   22 +++++++++++++---------\n>  builtin-checkout.c    |    2 +-\n>  builtin-commit.c      |    2 +-\n>  builtin-mv.c          |    2 +-\n>  cache.h               |   12 +++++++-----\n>  read-cache.c          |   23 +++++++++++++++++------\n>  t/t2200-add-update.sh |   17 +++++++++++++++++\n>  7 files changed, 57 insertions(+), 23 deletions(-)\n> \n> diff --git a/builtin-add.c b/builtin-add.c\n> index 4a91e3e..05af57f 100644\n> --- a/builtin-add.c\n> +++ b/builtin-add.c\n> @@ -82,9 +82,9 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec,\n>  static void update_callback(struct diff_queue_struct *q,\n>  \t\t\t    struct diff_options *opt, void *cbdata)\n>  {\n> -\tint i, verbose;\n> +\tint i, flags;\n>  \n> -\tverbose = *((int *)cbdata);\n> +\tflags = *((int *)cbdata);\n>  \tfor (i = 0; i < q->nr; i++) {\n>  \t\tstruct diff_filepair *p = q->queue[i];\n>  \t\tconst char *path = p->one->path;\n> @@ -94,18 +94,19 @@ static void update_callback(struct diff_queue_struct *q,\n>  \t\tcase DIFF_STATUS_UNMERGED:\n>  \t\tcase DIFF_STATUS_MODIFIED:\n>  \t\tcase DIFF_STATUS_TYPE_CHANGED:\n> -\t\t\tadd_file_to_cache(path, verbose);\n> +\t\t\tadd_file_to_cache(path, flags);\n>  \t\t\tbreak;\n>  \t\tcase DIFF_STATUS_DELETED:\n> -\t\t\tremove_file_from_cache(path);\n> -\t\t\tif (verbose)\n> +\t\t\tif (!(flags & ADD_CACHE_PRETEND))\n> +\t\t\t\tremove_file_from_cache(path);\n> +\t\t\tif (flags)\n>  \t\t\t\tprintf(\"remove '%s'\\n\", path);\n>  \t\t\tbreak;\n>  \t\t}\n>  \t}\n>  }\n>  \n> -void add_files_to_cache(int verbose, const char *prefix, const char **pathspec)\n> +void add_files_to_cache(const char *prefix, const char **pathspec, int flags)\n>  {\n>  \tstruct rev_info rev;\n>  \tinit_revisions(&rev, prefix);\n> @@ -113,7 +114,7 @@ void add_files_to_cache(int verbose, const char *prefix, const char **pathspec)\n>  \trev.prune_data = pathspec;\n>  \trev.diffopt.output_format = DIFF_FORMAT_CALLBACK;\n>  \trev.diffopt.format_callback = update_callback;\n> -\trev.diffopt.format_callback_data = &verbose;\n> +\trev.diffopt.format_callback_data = &flags;\n>  \trun_diff_files(&rev, DIFF_RACY_IS_MODIFIED);\n>  }\n>  \n> @@ -209,10 +210,13 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n>  \n>  \tif (take_worktree_changes) {\n>  \t\tconst char **pathspec;\n> +\t\tint flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |\n> +\t\t\t     (show_only ? ADD_CACHE_PRETEND : 0));\n> +\n>  \t\tif (read_cache() < 0)\n>  \t\t\tdie(\"index file corrupt\");\n>  \t\tpathspec = get_pathspec(prefix, argv);\n> -\t\tadd_files_to_cache(verbose, prefix, pathspec);\n> +\t\tadd_files_to_cache(prefix, pathspec, flags);\n>  \t\tgoto finish;\n>  \t}\n>  \n> @@ -254,7 +258,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n>  \t}\n>  \n>  \tfor (i = 0; i < dir.nr; i++)\n> -\t\tadd_file_to_cache(dir.entries[i]->name, verbose);\n> +\t\tadd_file_to_cache(dir.entries[i]->name, verbose ? ADD_CACHE_VERBOSE : 0);\n>  \n>   finish:\n>  \tif (active_cache_changed) {\n> diff --git a/builtin-checkout.c b/builtin-checkout.c\n> index 10ec137..05c0642 100644\n> --- a/builtin-checkout.c\n> +++ b/builtin-checkout.c\n> @@ -282,7 +282,7 @@ static int merge_working_tree(struct checkout_opts *opts,\n>  \t\t\t * entries in the index.\n>  \t\t\t */\n>  \n> -\t\t\tadd_files_to_cache(0, NULL, NULL);\n> +\t\t\tadd_files_to_cache(NULL, NULL, 0);\n>  \t\t\twork = write_tree_from_memory();\n>  \n>  \t\t\tret = reset_to_new(new->commit->tree, opts->quiet);\n> diff --git a/builtin-commit.c b/builtin-commit.c\n> index 0baec6d..924fca1 100644\n> --- a/builtin-commit.c\n> +++ b/builtin-commit.c\n> @@ -246,7 +246,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)\n>  \t */\n>  \tif (all || (also && pathspec && *pathspec)) {\n>  \t\tint fd = hold_locked_index(&index_lock, 1);\n> -\t\tadd_files_to_cache(0, also ? prefix : NULL, pathspec);\n> +\t\tadd_files_to_cache(also ? prefix : NULL, pathspec, 0);\n>  \t\trefresh_cache(REFRESH_QUIET);\n>  \t\tif (write_cache(fd, active_cache, active_nr) ||\n>  \t\t    close_lock_file(&index_lock))\n> diff --git a/builtin-mv.c b/builtin-mv.c\n> index 94f6dd2..df9ea97 100644\n> --- a/builtin-mv.c\n> +++ b/builtin-mv.c\n> @@ -256,7 +256,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n>  \n>  \t\tfor (i = 0; i < added.nr; i++) {\n>  \t\t\tconst char *path = added.items[i].path;\n> -\t\t\tadd_file_to_cache(path, verbose);\n> +\t\t\tadd_file_to_cache(path, verbose ? ADD_CACHE_VERBOSE : 0);\n>  \t\t}\n>  \n>  \t\tfor (i = 0; i < deleted.nr; i++)\n> diff --git a/cache.h b/cache.h\n> index 093f04c..b1a8427 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -261,8 +261,8 @@ static inline void remove_name_hash(struct cache_entry *ce)\n>  #define add_cache_entry(ce, option) add_index_entry(&the_index, (ce), (option))\n>  #define remove_cache_entry_at(pos) remove_index_entry_at(&the_index, (pos))\n>  #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path))\n> -#define add_to_cache(path, st, verbose) add_to_index(&the_index, (path), (st), (verbose))\n> -#define add_file_to_cache(path, verbose) add_file_to_index(&the_index, (path), (verbose))\n> +#define add_to_cache(path, st, flags) add_to_index(&the_index, (path), (st), (flags))\n> +#define add_file_to_cache(path, flags) add_file_to_index(&the_index, (path), (flags))\n>  #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL)\n>  #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))\n>  #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))\n> @@ -366,8 +366,10 @@ extern int add_index_entry(struct index_state *, struct cache_entry *ce, int opt\n>  extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);\n>  extern int remove_index_entry_at(struct index_state *, int pos);\n>  extern int remove_file_from_index(struct index_state *, const char *path);\n> -extern int add_to_index(struct index_state *, const char *path, struct stat *, int verbose);\n> -extern int add_file_to_index(struct index_state *, const char *path, int verbose);\n> +#define ADD_CACHE_VERBOSE 1\n> +#define ADD_CACHE_PRETEND 2\n> +extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);\n> +extern int add_file_to_index(struct index_state *, const char *path, int flags);\n>  extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);\n>  extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);\n>  \n> @@ -782,7 +784,7 @@ extern int convert_to_git(const char *path, const char *src, size_t len,\n>  extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);\n>  \n>  /* add */\n> -void add_files_to_cache(int verbose, const char *prefix, const char **pathspec);\n> +void add_files_to_cache(const char *prefix, const char **pathspec, int flags);\n>  \n>  /* diff.c */\n>  extern int diff_auto_refresh_index;\n> diff --git a/read-cache.c b/read-cache.c\n> index 0382804..5d967e8 100644\n> --- a/read-cache.c\n> +++ b/read-cache.c\n> @@ -462,12 +462,14 @@ static struct cache_entry *create_alias_ce(struct cache_entry *ce, struct cache_\n>  \treturn new;\n>  }\n>  \n> -int add_to_index(struct index_state *istate, const char *path, struct stat *st, int verbose)\n> +int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)\n>  {\n> -\tint size, namelen;\n> +\tint size, namelen, was_same;\n>  \tmode_t st_mode = st->st_mode;\n>  \tstruct cache_entry *ce, *alias;\n>  \tunsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;\n> +\tint verbose = flags & (ADD_CACHE_VERBOSE | ADD_CACHE_PRETEND);\n> +\tint pretend = flags & ADD_CACHE_PRETEND;\n>  \n>  \tif (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))\n>  \t\tdie(\"%s: can only add regular files, symbolic links or git-directories\", path);\n> @@ -509,19 +511,28 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n>  \tif (ignore_case && alias && different_name(ce, alias))\n>  \t\tce = create_alias_ce(ce, alias);\n>  \tce->ce_flags |= CE_ADDED;\n> -\tif (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n> +\n> +\t/* It was suspected to be recily clean, but it turns out to be Ok */\n> +\twas_same = (alias &&\n> +\t\t    !ce_stage(alias) &&\n> +\t\t    !hashcmp(alias->sha1, ce->sha1) &&\n> +\t\t    ce->ce_mode == alias->ce_mode);\n> +\n> +\tif (pretend)\n> +\t\t;\n> +\telse if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n>  \t\tdie(\"unable to add %s to index\",path);\n> -\tif (verbose)\n> +\tif (verbose && !was_same)\n>  \t\tprintf(\"add '%s'\\n\", path);\n>  \treturn 0;\n>  }\n>  \n> -int add_file_to_index(struct index_state *istate, const char *path, int verbose)\n> +int add_file_to_index(struct index_state *istate, const char *path, int flags)\n>  {\n>  \tstruct stat st;\n>  \tif (lstat(path, &st))\n>  \t\tdie(\"%s: unable to stat (%s)\", path, strerror(errno));\n> -\treturn add_to_index(istate, path, &st, verbose);\n> +\treturn add_to_index(istate, path, &st, flags);\n>  }\n>  \n>  struct cache_entry *make_cache_entry(unsigned int mode,\n> diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh\n> index b664341..f57a6e0 100755\n> --- a/t/t2200-add-update.sh\n> +++ b/t/t2200-add-update.sh\n> @@ -111,4 +111,21 @@ test_expect_success 'touch and then add explicitly' '\n>  \n>  '\n>  \n> +test_expect_success 'add -n -u should not add but just report' '\n> +\n> +\t(\n> +\t\techo \"add '\\''check'\\''\" &&\n> +\t\techo \"remove '\\''top'\\''\"\n> +\t) >expect &&\n> +\tbefore=$(git ls-files -s check top) &&\n> +\techo changed >>check &&\n> +\trm -f top &&\n> +\tgit add -n -u >actual &&\n> +\tafter=$(git ls-files -s check top) &&\n> +\n> +\ttest \"$before\" = \"$after\" &&\n> +\ttest_cmp expect actual\n> +\n> +'\n> +\n>  test_done\n"},{"id":"77493","messageId":"7vfxsaula8.fsf@gitster.siamese.dyndns.org","threadId":"13531","inReplyTo":"4835CACE.1070006@isy.liu.se","subject":"Re: Re* [PATCH] Make git add -u honor --dry-run","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-22T20:38:23Z","receivedAt":"2008-05-22T20:38:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Gustaf Hendeby <hendeby@isy.liu.se> writes:\n\n> On 2008-05-22 20:16, Junio C Hamano wrote:\n>> ...\n>> We need a slightly different patch for 'master' (for 1.5.6) and 'maint'\n>> (for 1.5.5.X), due to recent introduction of add_to_index() API.  This is\n>> an updated one for 'master'; I rolled your one-liner fix into it as well.\n>\n> I'm sorry, but I don't get this to apply cleanly at all.  Did I\n> misunderstand you, or is it actually meant for master (1af8bca)?  The\n> merge is too complicated for me to do anything sensible with.\n\nOh, sorry about that.  I prepared the patch and the message before\nyesterday's merge binge, and one of the topics graduated to 'master'\nsomewhat conflicts with the patch.\n\nThe attached patch should apply cleanly to 1af8bca (Merge branch 'maint',\n2008-05-21).\n\nSide note.  The patch is already merged to 'next', so if you can try it to\nsee if it fixes your issue, we are hopefully in a good shape.\n\nSide note2.  I applied the patch with \"git-am -3\" to 'master', which reused\nthe recorded resolution I previously had to make when I merged the topic\nto 'next' to resolve the conflict fully.  This patch was created by taking\nthe diff between that result and 'master'.\n\n---\n\n builtin-add.c         |   22 ++++++++++------------\n builtin-mv.c          |    2 +-\n cache.h               |   13 +++++++------\n read-cache.c          |   23 +++++++++++++++++------\n t/t2200-add-update.sh |   17 +++++++++++++++++\n 5 files changed, 52 insertions(+), 25 deletions(-)\n\ndiff --git a/builtin-add.c b/builtin-add.c\nindex 73235ed..dd2ca4b 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -100,15 +100,16 @@ static void update_callback(struct diff_queue_struct *q,\n \t\tcase DIFF_STATUS_UNMERGED:\n \t\tcase DIFF_STATUS_MODIFIED:\n \t\tcase DIFF_STATUS_TYPE_CHANGED:\n-\t\t\tif (add_file_to_cache(path, data->flags & ADD_FILES_VERBOSE)) {\n-\t\t\t\tif (!(data->flags & ADD_FILES_IGNORE_ERRORS))\n+\t\t\tif (add_file_to_cache(path, data->flags)) {\n+\t\t\t\tif (!(data->flags & ADD_CACHE_IGNORE_ERRORS))\n \t\t\t\t\tdie(\"updating files failed\");\n \t\t\t\tdata->add_errors++;\n \t\t\t}\n \t\t\tbreak;\n \t\tcase DIFF_STATUS_DELETED:\n-\t\t\tremove_file_from_cache(path);\n-\t\t\tif (data->flags & ADD_FILES_VERBOSE)\n+\t\t\tif (!(data->flags & ADD_CACHE_PRETEND))\n+\t\t\t\tremove_file_from_cache(path);\n+\t\t\tif (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))\n \t\t\t\tprintf(\"remove '%s'\\n\", path);\n \t\t\tbreak;\n \t\t}\n@@ -234,17 +235,14 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \tnewfd = hold_locked_index(&lock_file, 1);\n \n \tif (take_worktree_changes) {\n-\t\tint flags = 0;\n \t\tconst char **pathspec;\n+\t\tint flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |\n+\t\t\t     (show_only ? ADD_CACHE_PRETEND : 0) |\n+\t\t\t     (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0));\n+\n \t\tif (read_cache() < 0)\n \t\t\tdie(\"index file corrupt\");\n \t\tpathspec = get_pathspec(prefix, argv);\n-\n-\t\tif (verbose)\n-\t\t\tflags |= ADD_FILES_VERBOSE;\n-\t\tif (ignore_add_errors)\n-\t\t\tflags |= ADD_FILES_IGNORE_ERRORS;\n-\n \t\texit_status = add_files_to_cache(prefix, pathspec, flags);\n \t\tgoto finish;\n \t}\n@@ -287,7 +285,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t}\n \n \tfor (i = 0; i < dir.nr; i++)\n-\t\tif (add_file_to_cache(dir.entries[i]->name, verbose)) {\n+\t\tif (add_file_to_cache(dir.entries[i]->name, verbose ? ADD_CACHE_VERBOSE : 0)) {\n \t\t\tif (!ignore_add_errors)\n \t\t\t\tdie(\"adding files failed\");\n \t\t\texit_status = 1;\ndiff --git a/builtin-mv.c b/builtin-mv.c\nindex fb8ffb4..fb906b3 100644\n--- a/builtin-mv.c\n+++ b/builtin-mv.c\n@@ -256,7 +256,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \n \t\tfor (i = 0; i < added.nr; i++) {\n \t\t\tconst char *path = added.items[i].path;\n-\t\t\tif (add_file_to_cache(path, verbose))\n+\t\t\tif (add_file_to_cache(path, verbose ? ADD_CACHE_VERBOSE : 0))\n \t\t\t\tdie(\"updating index entries failed\");\n \t\t}\n \ndiff --git a/cache.h b/cache.h\nindex 0f89f15..123d6cc 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -261,8 +261,8 @@ static inline void remove_name_hash(struct cache_entry *ce)\n #define add_cache_entry(ce, option) add_index_entry(&the_index, (ce), (option))\n #define remove_cache_entry_at(pos) remove_index_entry_at(&the_index, (pos))\n #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path))\n-#define add_to_cache(path, st, verbose) add_to_index(&the_index, (path), (st), (verbose))\n-#define add_file_to_cache(path, verbose) add_file_to_index(&the_index, (path), (verbose))\n+#define add_to_cache(path, st, flags) add_to_index(&the_index, (path), (st), (flags))\n+#define add_file_to_cache(path, flags) add_file_to_index(&the_index, (path), (flags))\n #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL)\n #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))\n #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))\n@@ -366,8 +366,11 @@ extern int add_index_entry(struct index_state *, struct cache_entry *ce, int opt\n extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);\n extern int remove_index_entry_at(struct index_state *, int pos);\n extern int remove_file_from_index(struct index_state *, const char *path);\n-extern int add_to_index(struct index_state *, const char *path, struct stat *, int verbose);\n-extern int add_file_to_index(struct index_state *, const char *path, int verbose);\n+#define ADD_CACHE_VERBOSE 1\n+#define ADD_CACHE_PRETEND 2\n+#define ADD_CACHE_IGNORE_ERRORS\t4\n+extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);\n+extern int add_file_to_index(struct index_state *, const char *path, int flags);\n extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);\n extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);\n \n@@ -782,8 +785,6 @@ extern int convert_to_git(const char *path, const char *src, size_t len,\n extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);\n \n /* add */\n-#define ADD_FILES_VERBOSE\t01\n-#define ADD_FILES_IGNORE_ERRORS\t02\n /*\n  * return 0 if success, 1 - if addition of a file failed and\n  * ADD_FILES_IGNORE_ERRORS was specified in flags\ndiff --git a/read-cache.c b/read-cache.c\nindex 8b467f8..c90cbb9 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -462,12 +462,14 @@ static struct cache_entry *create_alias_ce(struct cache_entry *ce, struct cache_\n \treturn new;\n }\n \n-int add_to_index(struct index_state *istate, const char *path, struct stat *st, int verbose)\n+int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)\n {\n-\tint size, namelen;\n+\tint size, namelen, was_same;\n \tmode_t st_mode = st->st_mode;\n \tstruct cache_entry *ce, *alias;\n \tunsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;\n+\tint verbose = flags & (ADD_CACHE_VERBOSE | ADD_CACHE_PRETEND);\n+\tint pretend = flags & ADD_CACHE_PRETEND;\n \n \tif (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))\n \t\treturn error(\"%s: can only add regular files, symbolic links or git-directories\", path);\n@@ -509,19 +511,28 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \tif (ignore_case && alias && different_name(ce, alias))\n \t\tce = create_alias_ce(ce, alias);\n \tce->ce_flags |= CE_ADDED;\n-\tif (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n+\n+\t/* It was suspected to be recily clean, but it turns out to be Ok */\n+\twas_same = (alias &&\n+\t\t    !ce_stage(alias) &&\n+\t\t    !hashcmp(alias->sha1, ce->sha1) &&\n+\t\t    ce->ce_mode == alias->ce_mode);\n+\n+\tif (pretend)\n+\t\t;\n+\telse if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n \t\treturn error(\"unable to add %s to index\",path);\n-\tif (verbose)\n+\tif (verbose && !was_same)\n \t\tprintf(\"add '%s'\\n\", path);\n \treturn 0;\n }\n \n-int add_file_to_index(struct index_state *istate, const char *path, int verbose)\n+int add_file_to_index(struct index_state *istate, const char *path, int flags)\n {\n \tstruct stat st;\n \tif (lstat(path, &st))\n \t\tdie(\"%s: unable to stat (%s)\", path, strerror(errno));\n-\treturn add_to_index(istate, path, &st, verbose);\n+\treturn add_to_index(istate, path, &st, flags);\n }\n \n struct cache_entry *make_cache_entry(unsigned int mode,\ndiff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh\nindex b664341..f57a6e0 100755\n--- a/t/t2200-add-update.sh\n+++ b/t/t2200-add-update.sh\n@@ -111,4 +111,21 @@ test_expect_success 'touch and then add explicitly' '\n \n '\n \n+test_expect_success 'add -n -u should not add but just report' '\n+\n+\t(\n+\t\techo \"add '\\''check'\\''\" &&\n+\t\techo \"remove '\\''top'\\''\"\n+\t) >expect &&\n+\tbefore=$(git ls-files -s check top) &&\n+\techo changed >>check &&\n+\trm -f top &&\n+\tgit add -n -u >actual &&\n+\tafter=$(git ls-files -s check top) &&\n+\n+\ttest \"$before\" = \"$after\" &&\n+\ttest_cmp expect actual\n+\n+'\n+\n test_done\n"},{"id":"77496","messageId":"4835E1AE.6030201@isy.liu.se","threadId":"13531","inReplyTo":"7vfxsaula8.fsf@gitster.siamese.dyndns.org","subject":"Re: Re* [PATCH] Make git add -u honor --dry-run","fromName":"Gustaf Hendeby","fromEmail":"hendeby@isy.liu.se","sentAt":"2008-05-22T21:12:14Z","receivedAt":"2008-05-22T21:12:14Z","isPatch":true,"sender":{"key":"hendeby@isy.liu.se","avatar":"https://avatars.githubusercontent.com/u/730316?v=4"},"body":"On 2008-05-22 22:38, Junio C Hamano wrote:\n> Gustaf Hendeby <hendeby@isy.liu.se> writes:\n>> On 2008-05-22 20:16, Junio C Hamano wrote:\n>>> ...\n>>> We need a slightly different patch for 'master' (for 1.5.6) and 'maint'\n>>> (for 1.5.5.X), due to recent introduction of add_to_index() API.  This is\n>>> an updated one for 'master'; I rolled your one-liner fix into it as well.\n>> I'm sorry, but I don't get this to apply cleanly at all.  Did I\n>> misunderstand you, or is it actually meant for master (1af8bca)?  The\n>> merge is too complicated for me to do anything sensible with.\n> \n> Oh, sorry about that.  I prepared the patch and the message before\n> yesterday's merge binge, and one of the topics graduated to 'master'\n> somewhat conflicts with the patch.\n\nNo problem!\n\n> The attached patch should apply cleanly to 1af8bca (Merge branch 'maint',\n> 2008-05-21).\n\nApplies and fixes my problem (master, and the fix in next works too). \nThank you!  However, in my process of testing I noticed something else, \nnot really a bug but an inconsistency in how things are reported to the \nuser:\n\n$ git --version\ngit version 1.5.5.1.501.gefb4\n$ git status\n# On branch master\n# Changed but not updated:\n#   (use \"git add <file>...\" to update what will be committed)\n#\n#       modified:   bar/bar\n#       modified:   foo\n#\nno changes added to commit (use \"git add\" and/or \"git commit -a\")\n$ git add -u -n\nadd 'bar/bar'\nadd 'foo'\n$ git add -n foo bar/bar\nbar/bar foo\n\nI would have expected the output to be the same in this case.\n\n/Gustaf\n\nPS\nSorry for the duplicate Junio, I hit the wrong reply button, and lost \nthe whole reply-list.\n\n> Side note.  The patch is already merged to 'next', so if you can try it to\n> see if it fixes your issue, we are hopefully in a good shape.\n> \n> Side note2.  I applied the patch with \"git-am -3\" to 'master', which reused\n> the recorded resolution I previously had to make when I merged the topic\n> to 'next' to resolve the conflict fully.  This patch was created by taking\n> the diff between that result and 'master'.\n> \n> ---\n> \n>  builtin-add.c         |   22 ++++++++++------------\n>  builtin-mv.c          |    2 +-\n>  cache.h               |   13 +++++++------\n>  read-cache.c          |   23 +++++++++++++++++------\n>  t/t2200-add-update.sh |   17 +++++++++++++++++\n>  5 files changed, 52 insertions(+), 25 deletions(-)\n> \n> diff --git a/builtin-add.c b/builtin-add.c\n> index 73235ed..dd2ca4b 100644\n> --- a/builtin-add.c\n> +++ b/builtin-add.c\n> @@ -100,15 +100,16 @@ static void update_callback(struct diff_queue_struct *q,\n>  \t\tcase DIFF_STATUS_UNMERGED:\n>  \t\tcase DIFF_STATUS_MODIFIED:\n>  \t\tcase DIFF_STATUS_TYPE_CHANGED:\n> -\t\t\tif (add_file_to_cache(path, data->flags & ADD_FILES_VERBOSE)) {\n> -\t\t\t\tif (!(data->flags & ADD_FILES_IGNORE_ERRORS))\n> +\t\t\tif (add_file_to_cache(path, data->flags)) {\n> +\t\t\t\tif (!(data->flags & ADD_CACHE_IGNORE_ERRORS))\n>  \t\t\t\t\tdie(\"updating files failed\");\n>  \t\t\t\tdata->add_errors++;\n>  \t\t\t}\n>  \t\t\tbreak;\n>  \t\tcase DIFF_STATUS_DELETED:\n> -\t\t\tremove_file_from_cache(path);\n> -\t\t\tif (data->flags & ADD_FILES_VERBOSE)\n> +\t\t\tif (!(data->flags & ADD_CACHE_PRETEND))\n> +\t\t\t\tremove_file_from_cache(path);\n> +\t\t\tif (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))\n>  \t\t\t\tprintf(\"remove '%s'\\n\", path);\n>  \t\t\tbreak;\n>  \t\t}\n> @@ -234,17 +235,14 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n>  \tnewfd = hold_locked_index(&lock_file, 1);\n>  \n>  \tif (take_worktree_changes) {\n> -\t\tint flags = 0;\n>  \t\tconst char **pathspec;\n> +\t\tint flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |\n> +\t\t\t     (show_only ? ADD_CACHE_PRETEND : 0) |\n> +\t\t\t     (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0));\n> +\n>  \t\tif (read_cache() < 0)\n>  \t\t\tdie(\"index file corrupt\");\n>  \t\tpathspec = get_pathspec(prefix, argv);\n> -\n> -\t\tif (verbose)\n> -\t\t\tflags |= ADD_FILES_VERBOSE;\n> -\t\tif (ignore_add_errors)\n> -\t\t\tflags |= ADD_FILES_IGNORE_ERRORS;\n> -\n>  \t\texit_status = add_files_to_cache(prefix, pathspec, flags);\n>  \t\tgoto finish;\n>  \t}\n> @@ -287,7 +285,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n>  \t}\n>  \n>  \tfor (i = 0; i < dir.nr; i++)\n> -\t\tif (add_file_to_cache(dir.entries[i]->name, verbose)) {\n> +\t\tif (add_file_to_cache(dir.entries[i]->name, verbose ? ADD_CACHE_VERBOSE : 0)) {\n>  \t\t\tif (!ignore_add_errors)\n>  \t\t\t\tdie(\"adding files failed\");\n>  \t\t\texit_status = 1;\n> diff --git a/builtin-mv.c b/builtin-mv.c\n> index fb8ffb4..fb906b3 100644\n> --- a/builtin-mv.c\n> +++ b/builtin-mv.c\n> @@ -256,7 +256,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n>  \n>  \t\tfor (i = 0; i < added.nr; i++) {\n>  \t\t\tconst char *path = added.items[i].path;\n> -\t\t\tif (add_file_to_cache(path, verbose))\n> +\t\t\tif (add_file_to_cache(path, verbose ? ADD_CACHE_VERBOSE : 0))\n>  \t\t\t\tdie(\"updating index entries failed\");\n>  \t\t}\n>  \n> diff --git a/cache.h b/cache.h\n> index 0f89f15..123d6cc 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -261,8 +261,8 @@ static inline void remove_name_hash(struct cache_entry *ce)\n>  #define add_cache_entry(ce, option) add_index_entry(&the_index, (ce), (option))\n>  #define remove_cache_entry_at(pos) remove_index_entry_at(&the_index, (pos))\n>  #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path))\n> -#define add_to_cache(path, st, verbose) add_to_index(&the_index, (path), (st), (verbose))\n> -#define add_file_to_cache(path, verbose) add_file_to_index(&the_index, (path), (verbose))\n> +#define add_to_cache(path, st, flags) add_to_index(&the_index, (path), (st), (flags))\n> +#define add_file_to_cache(path, flags) add_file_to_index(&the_index, (path), (flags))\n>  #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL)\n>  #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))\n>  #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))\n> @@ -366,8 +366,11 @@ extern int add_index_entry(struct index_state *, struct cache_entry *ce, int opt\n>  extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);\n>  extern int remove_index_entry_at(struct index_state *, int pos);\n>  extern int remove_file_from_index(struct index_state *, const char *path);\n> -extern int add_to_index(struct index_state *, const char *path, struct stat *, int verbose);\n> -extern int add_file_to_index(struct index_state *, const char *path, int verbose);\n> +#define ADD_CACHE_VERBOSE 1\n> +#define ADD_CACHE_PRETEND 2\n> +#define ADD_CACHE_IGNORE_ERRORS\t4\n> +extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);\n> +extern int add_file_to_index(struct index_state *, const char *path, int flags);\n>  extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);\n>  extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);\n>  \n> @@ -782,8 +785,6 @@ extern int convert_to_git(const char *path, const char *src, size_t len,\n>  extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);\n>  \n>  /* add */\n> -#define ADD_FILES_VERBOSE\t01\n> -#define ADD_FILES_IGNORE_ERRORS\t02\n>  /*\n>   * return 0 if success, 1 - if addition of a file failed and\n>   * ADD_FILES_IGNORE_ERRORS was specified in flags\n> diff --git a/read-cache.c b/read-cache.c\n> index 8b467f8..c90cbb9 100644\n> --- a/read-cache.c\n> +++ b/read-cache.c\n> @@ -462,12 +462,14 @@ static struct cache_entry *create_alias_ce(struct cache_entry *ce, struct cache_\n>  \treturn new;\n>  }\n>  \n> -int add_to_index(struct index_state *istate, const char *path, struct stat *st, int verbose)\n> +int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)\n>  {\n> -\tint size, namelen;\n> +\tint size, namelen, was_same;\n>  \tmode_t st_mode = st->st_mode;\n>  \tstruct cache_entry *ce, *alias;\n>  \tunsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;\n> +\tint verbose = flags & (ADD_CACHE_VERBOSE | ADD_CACHE_PRETEND);\n> +\tint pretend = flags & ADD_CACHE_PRETEND;\n>  \n>  \tif (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))\n>  \t\treturn error(\"%s: can only add regular files, symbolic links or git-directories\", path);\n> @@ -509,19 +511,28 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n>  \tif (ignore_case && alias && different_name(ce, alias))\n>  \t\tce = create_alias_ce(ce, alias);\n>  \tce->ce_flags |= CE_ADDED;\n> -\tif (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n> +\n> +\t/* It was suspected to be recily clean, but it turns out to be Ok */\n> +\twas_same = (alias &&\n> +\t\t    !ce_stage(alias) &&\n> +\t\t    !hashcmp(alias->sha1, ce->sha1) &&\n> +\t\t    ce->ce_mode == alias->ce_mode);\n> +\n> +\tif (pretend)\n> +\t\t;\n> +\telse if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))\n>  \t\treturn error(\"unable to add %s to index\",path);\n> -\tif (verbose)\n> +\tif (verbose && !was_same)\n>  \t\tprintf(\"add '%s'\\n\", path);\n>  \treturn 0;\n>  }\n>  \n> -int add_file_to_index(struct index_state *istate, const char *path, int verbose)\n> +int add_file_to_index(struct index_state *istate, const char *path, int flags)\n>  {\n>  \tstruct stat st;\n>  \tif (lstat(path, &st))\n>  \t\tdie(\"%s: unable to stat (%s)\", path, strerror(errno));\n> -\treturn add_to_index(istate, path, &st, verbose);\n> +\treturn add_to_index(istate, path, &st, flags);\n>  }\n>  \n>  struct cache_entry *make_cache_entry(unsigned int mode,\n> diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh\n> index b664341..f57a6e0 100755\n> --- a/t/t2200-add-update.sh\n> +++ b/t/t2200-add-update.sh\n> @@ -111,4 +111,21 @@ test_expect_success 'touch and then add explicitly' '\n>  \n>  '\n>  \n> +test_expect_success 'add -n -u should not add but just report' '\n> +\n> +\t(\n> +\t\techo \"add '\\''check'\\''\" &&\n> +\t\techo \"remove '\\''top'\\''\"\n> +\t) >expect &&\n> +\tbefore=$(git ls-files -s check top) &&\n> +\techo changed >>check &&\n> +\trm -f top &&\n> +\tgit add -n -u >actual &&\n> +\tafter=$(git ls-files -s check top) &&\n> +\n> +\ttest \"$before\" = \"$after\" &&\n> +\ttest_cmp expect actual\n> +\n> +'\n> +\n>  test_done\n"},{"id":"77503","messageId":"1211493582-13400-1-git-send-email-hendeby@isy.liu.se","threadId":"13531","inReplyTo":"4835E1AE.6030201@isy.liu.se","subject":"[PATCH] Make git add -n and git -u -n output consistent","fromName":"Gustaf Hendeby","fromEmail":"hendeby@isy.liu.se","sentAt":"2008-05-22T21:59:42Z","receivedAt":"2008-05-22T21:59:42Z","isPatch":true,"sender":{"key":"hendeby@isy.liu.se","avatar":"https://avatars.githubusercontent.com/u/730316?v=4"},"body":"\nSigned-off-by: Gustaf Hendeby <hendeby@isy.liu.se>\n---\n\nThis would be one way to go to get a more coherent behavior or the -n\nswitch to git add.  It would also unify the implementation somewhat.\nI'd suggest amending this to your patch, or would the output be likely\nto be used by scrips?  In that case I'd vote for changing the output\nof git add -n -u,\n\n/Gustaf\n\n\n builtin-add.c |   19 ++++++-------------\n 1 files changed, 6 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin-add.c b/builtin-add.c\nindex dd2ca4b..e8dce30 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -261,17 +261,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \n \tfill_directory(&dir, pathspec, ignored_too);\n \n-\tif (show_only) {\n-\t\tconst char *sep = \"\", *eof = \"\";\n-\t\tfor (i = 0; i < dir.nr; i++) {\n-\t\t\tprintf(\"%s%s\", sep, dir.entries[i]->name);\n-\t\t\tsep = \" \";\n-\t\t\teof = \"\\n\";\n-\t\t}\n-\t\tfputs(eof, stdout);\n-\t\treturn 0;\n-\t}\n-\n \tif (read_cache() < 0)\n \t\tdie(\"index file corrupt\");\n \n@@ -284,12 +273,16 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t\tdie(\"no files added\");\n \t}\n \n-\tfor (i = 0; i < dir.nr; i++)\n-\t\tif (add_file_to_cache(dir.entries[i]->name, verbose ? ADD_CACHE_VERBOSE : 0)) {\n+\tfor (i = 0; i < dir.nr; i++) {\n+\t\tint flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |\n+\t\t\t\t\t\t\t\t (show_only ? ADD_CACHE_PRETEND : 0) |\n+\t\t\t\t\t\t\t\t (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0));\n+\t\tif (add_file_to_cache(dir.entries[i]->name, flags)) {\n \t\t\tif (!ignore_add_errors)\n \t\t\t\tdie(\"adding files failed\");\n \t\t\texit_status = 1;\n \t\t}\n+\t}\n \n  finish:\n \tif (active_cache_changed) {\n-- \n1.5.5.1.501.gefb4\n"},{"id":"77521","messageId":"7vabihtyxw.fsf@gitster.siamese.dyndns.org","threadId":"13531","inReplyTo":"1211493582-13400-1-git-send-email-hendeby@isy.liu.se","subject":"Re: [PATCH] Make git add -n and git -u -n output consistent","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-23T04:40:59Z","receivedAt":"2008-05-23T04:40:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Gustaf Hendeby <hendeby@isy.liu.se> writes:\n\n> Signed-off-by: Gustaf Hendeby <hendeby@isy.liu.se>\n> ---\n>\n> This would be one way to go to get a more coherent behavior or the -n\n> switch to git add.  It would also unify the implementation somewhat.\n> I'd suggest amending this to your patch, or would the output be likely\n> to be used by scrips?  In that case I'd vote for changing the output\n> of git add -n -u,\n\nThe commit log message should describe what kind of consistency you are\ntalking about to people who are not familiar with the topic.\n\nOutput format from \"git add -n $path\" lists path to blobs that are going\nto be added on a single line, separated with SP.  On the other hand, the\nsuggested \"git add -u -n\" shows one path per line, like \"add '<file>'\\n\".\nOf course, these two are inconsistent.\n\nPlain \"git add -n\" can afford to only say names of paths, as all it does\nis to add (update).  However, \"git add -u\" needs to be able to express\n\"remove\" somehow.  So if we need to have them formatted the same way, we\nneed to unify with the \"git add -n -u\" format.  Incidentally, this is\nconsistent with how 'update-index' says it.\n\nI do not think we need to worry about people who wrote script around\noutput from \"git add -n\".  Output from Porcelain commands is a fair game\nfor improvements.\n"},{"id":"77532","messageId":"48367CF8.8040307@isy.liu.se","threadId":"13531","inReplyTo":"7vabihtyxw.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Make git add -n and git -u -n output consistent","fromName":"Gustaf Hendeby","fromEmail":"hendeby@isy.liu.se","sentAt":"2008-05-23T08:14:48Z","receivedAt":"2008-05-23T08:14:48Z","isPatch":true,"sender":{"key":"hendeby@isy.liu.se","avatar":"https://avatars.githubusercontent.com/u/730316?v=4"},"body":"On 05/23/2008 06:40 AM, Junio C Hamano wrote:\n> Gustaf Hendeby <hendeby@isy.liu.se> writes:\n> \n>> Signed-off-by: Gustaf Hendeby <hendeby@isy.liu.se>\n>> ---\n>>\n>> This would be one way to go to get a more coherent behavior or the -n\n>> switch to git add.  It would also unify the implementation somewhat.\n>> I'd suggest amending this to your patch, or would the output be likely\n>> to be used by scrips?  In that case I'd vote for changing the output\n>> of git add -n -u,\n> \n> The commit log message should describe what kind of consistency you are\n> talking about to people who are not familiar with the topic.\n\nPoint taken, I will try to do better next time.\n\n> \n> Output format from \"git add -n $path\" lists path to blobs that are going\n> to be added on a single line, separated with SP.  On the other hand, the\n> suggested \"git add -u -n\" shows one path per line, like \"add '<file>'\\n\".\n> Of course, these two are inconsistent.\n> \n> Plain \"git add -n\" can afford to only say names of paths, as all it does\n> is to add (update).  However, \"git add -u\" needs to be able to express\n> \"remove\" somehow.  So if we need to have them formatted the same way, we\n> need to unify with the \"git add -n -u\" format.  Incidentally, this is\n> consistent with how 'update-index' says it.\n> \n> I do not think we need to worry about people who wrote script around\n> output from \"git add -n\".  Output from Porcelain commands is a fair game\n> for improvements.\n\nThanks for the explaination.\n\n/Gustaf\n"}]}