From 125fd98434ce773de45c4a40927c222ec5c43ae1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 24 Jan 2010 00:10:20 -0800 Subject: Make ce_uptodate() trustworthy again The rule has always been that a cache entry that is ce_uptodate(ce) means that we already have checked the work tree entity and we know there is no change in the work tree compared to the index, and nobody should have to double check. Note that false ce_uptodate(ce) does not mean it is known to be dirty---it only means we don't know if it is clean. There are a few codepaths (refresh-index and preload-index are among them) that mark a cache entry as up-to-date based solely on the return value from ie_match_stat(); this function uses lstat() to see if the work tree entity has been touched, and for a submodule entry, if its HEAD points at the same commit as the commit recorded in the index of the superproject (a submodule that is not even cloned is considered clean). A submodule is no longer considered unmodified merely because its HEAD matches the index of the superproject these days, in order to prevent people from forgetting to commit in the submodule and updating the superproject index with the new submodule commit, before commiting the state in the superproject. However, the patch to do so didn't update the codepath that marks cache entries up-to-date based on the updated definition and instead worked it around by saying "we don't trust the return value of ce_uptodate() for submodules." This makes ce_uptodate() trustworthy again by not marking submodule entries up-to-date. The next step _could_ be to introduce a few "in-core" flag bits to cache_entry structure to record "this entry is _known_ to be dirty", call is_submodule_modified() from ie_match_stat(), and use these new bits to avoid running this rather expensive check more than once, but that can be a separate patch. Signed-off-by: Junio C Hamano --- diff-lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'diff-lib.c') diff --git a/diff-lib.c b/diff-lib.c index 23e180eed1..c6c425e624 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -161,7 +161,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) continue; } - if ((ce_uptodate(ce) && !S_ISGITLINK(ce->ce_mode)) || ce_skip_worktree(ce)) + if (ce_uptodate(ce) || ce_skip_worktree(ce)) continue; /* If CE_VALID is set, don't look at workdir for file removal */ -- cgit v1.2.1 From 4d34477f4c5dbebc55aa1362fd705440590a85f1 Mon Sep 17 00:00:00 2001 From: Jens Lehmann Date: Sat, 23 Jan 2010 17:37:26 +0100 Subject: git diff: Don't test submodule dirtiness with --ignore-submodules The diff family suppresses the output of submodule changes when requested but checks them nonetheless. But since recently submodules get examined for their dirtiness, which is rather expensive. There is no need to do that when the --ignore-submodules option is used, as the gathered information is never used anyway. Signed-off-by: Jens Lehmann Signed-off-by: Junio C Hamano --- diff-lib.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'diff-lib.c') diff --git a/diff-lib.c b/diff-lib.c index c6c425e624..899034d354 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -179,6 +179,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) } changed = ce_match_stat(ce, &st, ce_option); if (S_ISGITLINK(ce->ce_mode) + && !DIFF_OPT_TST(&revs->diffopt, IGNORE_SUBMODULES) && (!changed || (revs->diffopt.output_format & DIFF_FORMAT_PATCH)) && is_submodule_modified(ce->name)) { changed = 1; @@ -220,7 +221,7 @@ static int get_stat_data(struct cache_entry *ce, const unsigned char **sha1p, unsigned int *modep, int cached, int match_missing, - unsigned *dirty_submodule, int output_format) + unsigned *dirty_submodule, struct diff_options *diffopt) { const unsigned char *sha1 = ce->sha1; unsigned int mode = ce->ce_mode; @@ -241,7 +242,8 @@ static int get_stat_data(struct cache_entry *ce, } changed = ce_match_stat(ce, &st, 0); if (S_ISGITLINK(ce->ce_mode) - && (!changed || (output_format & DIFF_FORMAT_PATCH)) + && !DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES) + && (!changed || (diffopt->output_format & DIFF_FORMAT_PATCH)) && is_submodule_modified(ce->name)) { changed = 1; *dirty_submodule = 1; @@ -270,7 +272,7 @@ static void show_new_file(struct rev_info *revs, * the working copy. */ if (get_stat_data(new, &sha1, &mode, cached, match_missing, - &dirty_submodule, revs->diffopt.output_format) < 0) + &dirty_submodule, &revs->diffopt) < 0) return; diff_index_show_file(revs, "+", new, sha1, mode, dirty_submodule); @@ -287,7 +289,7 @@ static int show_modified(struct rev_info *revs, unsigned dirty_submodule = 0; if (get_stat_data(new, &sha1, &mode, cached, match_missing, - &dirty_submodule, revs->diffopt.output_format) < 0) { + &dirty_submodule, &revs->diffopt) < 0) { if (report_missing) diff_index_show_file(revs, "-", old, old->sha1, old->ce_mode, 0); -- cgit v1.2.1