{"thread":{"id":"3940","subject":"[PATCH] Libify diff-index.","startedAt":"2006-04-22T10:14:52Z","lastAt":"2006-04-22T11:04:25Z","messageCount":2,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"18985","messageId":"7v64l1lxwj.fsf@assigned-by-dhcp.cox.net","threadId":"3940","inReplyTo":null,"subject":"[PATCH] Libify diff-index.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-22T10:14:52Z","receivedAt":"2006-04-22T10:14:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The second installment to libify diff brothers.  The pathname\narguments are checked more strictly than before because we now\nuse the revision.c::setup_revisions() infrastructure.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n diff-index.c             |  254 ++++------------------------------------------\n diff-lib.c               |  203 +++++++++++++++++++++++++++++++++++++\n diff.h                   |    2 \n t/t4010-diff-pathspec.sh |   10 +-\n 4 files changed, 231 insertions(+), 238 deletions(-)\n\ndiff --git a/diff-index.c b/diff-index.c\nindex e376d65..4a243b3 100644\n--- a/diff-index.c\n+++ b/diff-index.c\n@@ -1,166 +1,7 @@\n #include \"cache.h\"\n-#include \"tree.h\"\n #include \"diff.h\"\n-\n-static int cached_only = 0;\n-static int match_nonexisting = 0;\n-static struct diff_options diff_options;\n-\n-/* A file entry went away or appeared */\n-static void show_file(const char *prefix,\n-\t\t      struct cache_entry *ce,\n-\t\t      unsigned char *sha1, unsigned int mode)\n-{\n-\tdiff_addremove(&diff_options, prefix[0], ntohl(mode),\n-\t\t       sha1, ce->name, NULL);\n-}\n-\n-static int get_stat_data(struct cache_entry *ce,\n-\t\t\t unsigned char ** sha1p, unsigned int *modep)\n-{\n-\tunsigned char *sha1 = ce->sha1;\n-\tunsigned int mode = ce->ce_mode;\n-\n-\tif (!cached_only) {\n-\t\tstatic unsigned char no_sha1[20];\n-\t\tint changed;\n-\t\tstruct stat st;\n-\t\tif (lstat(ce->name, &st) < 0) {\n-\t\t\tif (errno == ENOENT && match_nonexisting) {\n-\t\t\t\t*sha1p = sha1;\n-\t\t\t\t*modep = mode;\n-\t\t\t\treturn 0;\n-\t\t\t}\n-\t\t\treturn -1;\n-\t\t}\n-\t\tchanged = ce_match_stat(ce, &st, 0);\n-\t\tif (changed) {\n-\t\t\tmode = create_ce_mode(st.st_mode);\n-\t\t\tif (!trust_executable_bit && S_ISREG(st.st_mode))\n-\t\t\t\tmode = ce->ce_mode;\n-\t\t\tsha1 = no_sha1;\n-\t\t}\n-\t}\n-\n-\t*sha1p = sha1;\n-\t*modep = mode;\n-\treturn 0;\n-}\n-\n-static void show_new_file(struct cache_entry *new)\n-{\n-\tunsigned char *sha1;\n-\tunsigned int mode;\n-\n-\t/* New file in the index: it might actually be different in\n-\t * the working copy.\n-\t */\n-\tif (get_stat_data(new, &sha1, &mode) < 0)\n-\t\treturn;\n-\n-\tshow_file(\"+\", new, sha1, mode);\n-}\n-\n-static int show_modified(struct cache_entry *old,\n-\t\t\t struct cache_entry *new,\n-\t\t\t int report_missing)\n-{\n-\tunsigned int mode, oldmode;\n-\tunsigned char *sha1;\n-\n-\tif (get_stat_data(new, &sha1, &mode) < 0) {\n-\t\tif (report_missing)\n-\t\t\tshow_file(\"-\", old, old->sha1, old->ce_mode);\n-\t\treturn -1;\n-\t}\n-\n-\toldmode = old->ce_mode;\n-\tif (mode == oldmode && !memcmp(sha1, old->sha1, 20) &&\n-\t    !diff_options.find_copies_harder)\n-\t\treturn 0;\n-\n-\tmode = ntohl(mode);\n-\toldmode = ntohl(oldmode);\n-\n-\tdiff_change(&diff_options, oldmode, mode,\n-\t\t    old->sha1, sha1, old->name, NULL);\n-\treturn 0;\n-}\n-\n-static int diff_cache(struct cache_entry **ac, int entries, const char **pathspec)\n-{\n-\twhile (entries) {\n-\t\tstruct cache_entry *ce = *ac;\n-\t\tint same = (entries > 1) && ce_same_name(ce, ac[1]);\n-\n-\t\tif (!ce_path_match(ce, pathspec))\n-\t\t\tgoto skip_entry;\n-\n-\t\tswitch (ce_stage(ce)) {\n-\t\tcase 0:\n-\t\t\t/* No stage 1 entry? That means it's a new file */\n-\t\t\tif (!same) {\n-\t\t\t\tshow_new_file(ce);\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\t/* Show difference between old and new */\n-\t\t\tshow_modified(ac[1], ce, 1);\n-\t\t\tbreak;\n-\t\tcase 1:\n-\t\t\t/* No stage 3 (merge) entry? That means it's been deleted */\n-\t\t\tif (!same) {\n-\t\t\t\tshow_file(\"-\", ce, ce->sha1, ce->ce_mode);\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\t/* We come here with ce pointing at stage 1\n-\t\t\t * (original tree) and ac[1] pointing at stage\n-\t\t\t * 3 (unmerged).  show-modified with\n-\t\t\t * report-missing set to false does not say the\n-\t\t\t * file is deleted but reports true if work\n-\t\t\t * tree does not have it, in which case we\n-\t\t\t * fall through to report the unmerged state.\n-\t\t\t * Otherwise, we show the differences between\n-\t\t\t * the original tree and the work tree.\n-\t\t\t */\n-\t\t\tif (!cached_only && !show_modified(ce, ac[1], 0))\n-\t\t\t\tbreak;\n-\t\t\t/* fallthru */\n-\t\tcase 3:\n-\t\t\tdiff_unmerge(&diff_options, ce->name);\n-\t\t\tbreak;\n-\n-\t\tdefault:\n-\t\t\tdie(\"impossible cache entry stage\");\n-\t\t}\n-\n-skip_entry:\n-\t\t/*\n-\t\t * Ignore all the different stages for this file,\n-\t\t * we've handled the relevant cases now.\n-\t\t */\n-\t\tdo {\n-\t\t\tac++;\n-\t\t\tentries--;\n-\t\t} while (entries && ce_same_name(ce, ac[0]));\n-\t}\n-\treturn 0;\n-}\n-\n-/*\n- * This turns all merge entries into \"stage 3\". That guarantees that\n- * when we read in the new tree (into \"stage 1\"), we won't lose sight\n- * of the fact that we had unmerged entries.\n- */\n-static void mark_merge_entries(void)\n-{\n-\tint i;\n-\tfor (i = 0; i < active_nr; i++) {\n-\t\tstruct cache_entry *ce = active_cache[i];\n-\t\tif (!ce_stage(ce))\n-\t\t\tcontinue;\n-\t\tce->ce_flags |= htons(CE_STAGEMASK);\n-\t}\n-}\n+#include \"commit.h\"\n+#include \"revision.h\"\n \n static const char diff_cache_usage[] =\n \"git-diff-index [-m] [--cached] \"\n@@ -169,85 +10,32 @@ COMMON_DIFF_OPTIONS_HELP;\n \n int main(int argc, const char **argv)\n {\n-\tconst char *tree_name = NULL;\n-\tunsigned char sha1[20];\n-\tconst char *prefix = setup_git_directory();\n-\tconst char **pathspec = NULL;\n-\tstruct tree *tree;\n-\tint ret;\n-\tint allow_options = 1;\n+\tstruct rev_info rev;\n+\tint match_missing = 0;\n+\tint cached = 0;\n \tint i;\n \n \tgit_config(git_diff_config);\n-\tdiff_setup(&diff_options);\n+\tinit_revisions(&rev);\n+\trev.abbrev = 0;\n+\n+\targc = setup_revisions(argc, argv, &rev, NULL);\n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n-\t\tint diff_opt_cnt;\n-\n-\t\tif (!allow_options || *arg != '-') {\n-\t\t\tif (tree_name)\n-\t\t\t\tbreak;\n-\t\t\ttree_name = arg;\n-\t\t\tcontinue;\n-\t\t}\n \t\t\t\n-\t\tif (!strcmp(arg, \"--\")) {\n-\t\t\tallow_options = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"-r\")) {\n-\t\t\t/* We accept the -r flag just to look like git-diff-tree */\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--cc\"))\n-\t\t\t/*\n-\t\t\t * I _think_ \"diff-index --cached HEAD\" with an\n-\t\t\t * unmerged index could show something else\n-\t\t\t * later, but pretend --cc is the same as -p for\n-\t\t\t * now.  \"git diff\" uses --cc by default.\n-\t\t\t */\n-\t\t\targv[i] = arg = \"-p\";\n-\t\tdiff_opt_cnt = diff_opt_parse(&diff_options, argv + i,\n-\t\t\t\t\t      argc - i);\n-\t\tif (diff_opt_cnt < 0)\n+\t\tif (!strcmp(arg, \"-m\"))\n+\t\t\tmatch_missing = 1; \n+\t\telse if (!strcmp(arg, \"--cached\"))\n+\t\t\tcached = 1;\n+\t\telse\n \t\t\tusage(diff_cache_usage);\n-\t\telse if (diff_opt_cnt) {\n-\t\t\ti += diff_opt_cnt - 1;\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\tif (!strcmp(arg, \"-m\")) {\n-\t\t\tmatch_nonexisting = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--cached\")) {\n-\t\t\tcached_only = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tusage(diff_cache_usage);\n \t}\n-\n-\tpathspec = get_pathspec(prefix, argv + i);\n-\n-\tif (diff_setup_done(&diff_options) < 0)\n-\t\tusage(diff_cache_usage);\n-\n-\tif (!tree_name || get_sha1(tree_name, sha1))\n+\t/*\n+\t * Make sure there is one revision (i.e. pending object),\n+\t * and there is no revision filtering parameters.\n+\t */\n+\tif (!rev.pending_objects || rev.pending_objects->next ||\n+\t    rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)\n \t\tusage(diff_cache_usage);\n-\n-\tread_cache();\n-\n-\tmark_merge_entries();\n-\n-\ttree = parse_tree_indirect(sha1);\n-\tif (!tree)\n-\t\tdie(\"bad tree object %s\", tree_name);\n-\tif (read_tree(tree, 1, pathspec))\n-\t\tdie(\"unable to read tree object %s\", tree_name);\n-\n-\tret = diff_cache(active_cache, active_nr, pathspec);\n-\n-\tdiffcore_std(&diff_options);\n-\tdiff_flush(&diff_options);\n-\treturn ret;\n+\treturn run_diff_index(&rev, cached, match_missing);\n }\ndiff --git a/diff-lib.c b/diff-lib.c\nindex a28dd3d..63da3b5 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -131,3 +131,206 @@ int run_diff_files(struct rev_info *revs\n \treturn 0;\n }\n \n+/*\n+ * diff-index\n+ */\n+\n+/* A file entry went away or appeared */\n+static void diff_index_show_file(struct rev_info *revs,\n+\t\t\t\t const char *prefix,\n+\t\t\t\t struct cache_entry *ce,\n+\t\t\t\t unsigned char *sha1, unsigned int mode)\n+{\n+\tdiff_addremove(&revs->diffopt, prefix[0], ntohl(mode),\n+\t\t       sha1, ce->name, NULL);\n+}\n+\n+static int get_stat_data(struct cache_entry *ce,\n+\t\t\t unsigned char **sha1p,\n+\t\t\t unsigned int *modep,\n+\t\t\t int cached, int match_missing)\n+{\n+\tunsigned char *sha1 = ce->sha1;\n+\tunsigned int mode = ce->ce_mode;\n+\n+\tif (!cached) {\n+\t\tstatic unsigned char no_sha1[20];\n+\t\tint changed;\n+\t\tstruct stat st;\n+\t\tif (lstat(ce->name, &st) < 0) {\n+\t\t\tif (errno == ENOENT && match_missing) {\n+\t\t\t\t*sha1p = sha1;\n+\t\t\t\t*modep = mode;\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t\treturn -1;\n+\t\t}\n+\t\tchanged = ce_match_stat(ce, &st, 0);\n+\t\tif (changed) {\n+\t\t\tmode = create_ce_mode(st.st_mode);\n+\t\t\tif (!trust_executable_bit && S_ISREG(st.st_mode))\n+\t\t\t\tmode = ce->ce_mode;\n+\t\t\tsha1 = no_sha1;\n+\t\t}\n+\t}\n+\n+\t*sha1p = sha1;\n+\t*modep = mode;\n+\treturn 0;\n+}\n+\n+static void show_new_file(struct rev_info *revs,\n+\t\t\t  struct cache_entry *new,\n+\t\t\t  int cached, int match_missing)\n+{\n+\tunsigned char *sha1;\n+\tunsigned int mode;\n+\n+\t/* New file in the index: it might actually be different in\n+\t * the working copy.\n+\t */\n+\tif (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0)\n+\t\treturn;\n+\n+\tdiff_index_show_file(revs, \"+\", new, sha1, mode);\n+}\n+\n+static int show_modified(struct rev_info *revs,\n+\t\t\t struct cache_entry *old,\n+\t\t\t struct cache_entry *new,\n+\t\t\t int report_missing,\n+\t\t\t int cached, int match_missing)\n+{\n+\tunsigned int mode, oldmode;\n+\tunsigned char *sha1;\n+\n+\tif (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0) {\n+\t\tif (report_missing)\n+\t\t\tdiff_index_show_file(revs, \"-\", old,\n+\t\t\t\t\t     old->sha1, old->ce_mode);\n+\t\treturn -1;\n+\t}\n+\n+\toldmode = old->ce_mode;\n+\tif (mode == oldmode && !memcmp(sha1, old->sha1, 20) &&\n+\t    !revs->diffopt.find_copies_harder)\n+\t\treturn 0;\n+\n+\tmode = ntohl(mode);\n+\toldmode = ntohl(oldmode);\n+\n+\tdiff_change(&revs->diffopt, oldmode, mode,\n+\t\t    old->sha1, sha1, old->name, NULL);\n+\treturn 0;\n+}\n+\n+static int diff_cache(struct rev_info *revs,\n+\t\t      struct cache_entry **ac, int entries,\n+\t\t      const char **pathspec,\n+\t\t      int cached, int match_missing)\n+{\n+\twhile (entries) {\n+\t\tstruct cache_entry *ce = *ac;\n+\t\tint same = (entries > 1) && ce_same_name(ce, ac[1]);\n+\n+\t\tif (!ce_path_match(ce, pathspec))\n+\t\t\tgoto skip_entry;\n+\n+\t\tswitch (ce_stage(ce)) {\n+\t\tcase 0:\n+\t\t\t/* No stage 1 entry? That means it's a new file */\n+\t\t\tif (!same) {\n+\t\t\t\tshow_new_file(revs, ce, cached, match_missing);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\t/* Show difference between old and new */\n+\t\t\tshow_modified(revs,ac[1], ce, 1,\n+\t\t\t\t      cached, match_missing);\n+\t\t\tbreak;\n+\t\tcase 1:\n+\t\t\t/* No stage 3 (merge) entry?\n+\t\t\t * That means it's been deleted.\n+\t\t\t */\n+\t\t\tif (!same) {\n+\t\t\t\tdiff_index_show_file(revs, \"-\", ce,\n+\t\t\t\t\t\t     ce->sha1, ce->ce_mode);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\t/* We come here with ce pointing at stage 1\n+\t\t\t * (original tree) and ac[1] pointing at stage\n+\t\t\t * 3 (unmerged).  show-modified with\n+\t\t\t * report-missing set to false does not say the\n+\t\t\t * file is deleted but reports true if work\n+\t\t\t * tree does not have it, in which case we\n+\t\t\t * fall through to report the unmerged state.\n+\t\t\t * Otherwise, we show the differences between\n+\t\t\t * the original tree and the work tree.\n+\t\t\t */\n+\t\t\tif (!cached &&\n+\t\t\t    !show_modified(revs, ce, ac[1], 0,\n+\t\t\t\t\t   cached, match_missing))\n+\t\t\t\tbreak;\n+\t\t\t/* fallthru */\n+\t\tcase 3:\n+\t\t\tdiff_unmerge(&revs->diffopt, ce->name);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\tdie(\"impossible cache entry stage\");\n+\t\t}\n+\n+skip_entry:\n+\t\t/*\n+\t\t * Ignore all the different stages for this file,\n+\t\t * we've handled the relevant cases now.\n+\t\t */\n+\t\tdo {\n+\t\t\tac++;\n+\t\t\tentries--;\n+\t\t} while (entries && ce_same_name(ce, ac[0]));\n+\t}\n+\treturn 0;\n+}\n+\n+/*\n+ * This turns all merge entries into \"stage 3\". That guarantees that\n+ * when we read in the new tree (into \"stage 1\"), we won't lose sight\n+ * of the fact that we had unmerged entries.\n+ */\n+static void mark_merge_entries(void)\n+{\n+\tint i;\n+\tfor (i = 0; i < active_nr; i++) {\n+\t\tstruct cache_entry *ce = active_cache[i];\n+\t\tif (!ce_stage(ce))\n+\t\t\tcontinue;\n+\t\tce->ce_flags |= htons(CE_STAGEMASK);\n+\t}\n+}\n+\n+int run_diff_index(struct rev_info *revs, int cached, int match_missing)\n+{\n+\tint ret;\n+\tstruct object *ent;\n+\tstruct tree *tree;\n+\tconst char *tree_name;\n+\n+\tif (read_cache() < 0) {\n+\t\tperror(\"read_cache\");\n+\t\treturn -1;\n+\t}\n+\tmark_merge_entries();\n+\n+\tent = revs->pending_objects->item;\n+\ttree_name = revs->pending_objects->name;\n+\ttree = parse_tree_indirect(ent->sha1);\n+\tif (!tree)\n+\t\treturn error(\"bad tree object %s\", tree_name);\n+\tif (read_tree(tree, 1, revs->prune_data))\n+\t\treturn error(\"unable to read tree object %s\", tree_name);\n+\tret = diff_cache(revs, active_cache, active_nr, revs->prune_data,\n+\t\t\t cached, match_missing);\n+\tdiffcore_std(&revs->diffopt);\n+\tdiff_flush(&revs->diffopt);\n+\treturn ret;\n+}\ndiff --git a/diff.h b/diff.h\nindex da4bd42..837d449 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -171,4 +171,6 @@ extern const char *diff_unique_abbrev(co\n \n extern int run_diff_files(struct rev_info *revs, int silent_on_removed);\n \n+extern int run_diff_index(struct rev_info *revs, int cached, int match_missing);\n+\n #endif /* DIFF_H */\ndiff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh\nindex 8db329d..9e1544d 100755\n--- a/t/t4010-diff-pathspec.sh\n+++ b/t/t4010-diff-pathspec.sh\n@@ -28,7 +28,7 @@ cat >expected <<\\EOF\n EOF\n test_expect_success \\\n     'limit to path should show nothing' \\\n-    'git-diff-index --cached $tree path >current &&\n+    'git-diff-index --cached $tree -- path >current &&\n      compare_diff_raw current expected'\n \n cat >expected <<\\EOF\n@@ -36,7 +36,7 @@ cat >expected <<\\EOF\n EOF\n test_expect_success \\\n     'limit to path1 should show path1/file1' \\\n-    'git-diff-index --cached $tree path1 >current &&\n+    'git-diff-index --cached $tree -- path1 >current &&\n      compare_diff_raw current expected'\n \n cat >expected <<\\EOF\n@@ -44,7 +44,7 @@ cat >expected <<\\EOF\n EOF\n test_expect_success \\\n     'limit to path1/ should show path1/file1' \\\n-    'git-diff-index --cached $tree path1/ >current &&\n+    'git-diff-index --cached $tree -- path1/ >current &&\n      compare_diff_raw current expected'\n \n cat >expected <<\\EOF\n@@ -52,14 +52,14 @@ cat >expected <<\\EOF\n EOF\n test_expect_success \\\n     'limit to file0 should show file0' \\\n-    'git-diff-index --cached $tree file0 >current &&\n+    'git-diff-index --cached $tree -- file0 >current &&\n      compare_diff_raw current expected'\n \n cat >expected <<\\EOF\n EOF\n test_expect_success \\\n     'limit to file0/ should emit nothing.' \\\n-    'git-diff-index --cached $tree file0/ >current &&\n+    'git-diff-index --cached $tree -- file0/ >current &&\n      compare_diff_raw current expected'\n \n test_done\n-- \n1.3.0.g6082\n"},{"id":"19002","messageId":"7vbqutkh1i.fsf@assigned-by-dhcp.cox.net","threadId":"3940","inReplyTo":"7v64l1lxwj.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Libified diff-index: backward compatibility fix.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-04-22T11:04:25Z","receivedAt":"2006-04-22T11:04:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"diff-index -m\" does not mean \"do not ignore merges\", but means\n\"pretend missing files match the index\".\n\nThe previous round tried to address this, but failed because\nsetup_revisions() ate \"-m\" flag before the caller had a chance\nto intervene.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n diff-index.c |    6 ++----\n diff-lib.c   |   10 +++++++++-\n diff.h       |    2 +-\n 3 files changed, 12 insertions(+), 6 deletions(-)\n\ndiff --git a/diff-index.c b/diff-index.c\nindex 4a243b3..8694012 100644\n--- a/diff-index.c\n+++ b/diff-index.c\n@@ -23,9 +23,7 @@ int main(int argc, const char **argv)\n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n \t\t\t\n-\t\tif (!strcmp(arg, \"-m\"))\n-\t\t\tmatch_missing = 1; \n-\t\telse if (!strcmp(arg, \"--cached\"))\n+\t\tif (!strcmp(arg, \"--cached\"))\n \t\t\tcached = 1;\n \t\telse\n \t\t\tusage(diff_cache_usage);\n@@ -37,5 +35,5 @@ int main(int argc, const char **argv)\n \tif (!rev.pending_objects || rev.pending_objects->next ||\n \t    rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)\n \t\tusage(diff_cache_usage);\n-\treturn run_diff_index(&rev, cached, match_missing);\n+\treturn run_diff_index(&rev, cached);\n }\ndiff --git a/diff-lib.c b/diff-lib.c\nindex 63da3b5..2183b41 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -308,12 +308,20 @@ static void mark_merge_entries(void)\n \t}\n }\n \n-int run_diff_index(struct rev_info *revs, int cached, int match_missing)\n+int run_diff_index(struct rev_info *revs, int cached)\n {\n \tint ret;\n \tstruct object *ent;\n \tstruct tree *tree;\n \tconst char *tree_name;\n+\tint match_missing = 0;\n+\n+\t/* \n+\t * Backward compatibility wart - \"diff-index -m\" does\n+\t * not mean \"do not ignore merges\", but totally different.\n+\t */\n+\tif (!revs->ignore_merges)\n+\t\tmatch_missing = 1;\n \n \tif (read_cache() < 0) {\n \t\tperror(\"read_cache\");\ndiff --git a/diff.h b/diff.h\nindex 837d449..7150b90 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -171,6 +171,6 @@ extern const char *diff_unique_abbrev(co\n \n extern int run_diff_files(struct rev_info *revs, int silent_on_removed);\n \n-extern int run_diff_index(struct rev_info *revs, int cached, int match_missing);\n+extern int run_diff_index(struct rev_info *revs, int cached);\n \n #endif /* DIFF_H */\n-- \n1.3.0.g0bc6\n"}]}