From: Junio C Hamano Date: Tue, 16 Aug 2011 18:23:25 +0000 (-0700) Subject: Merge branch 'jc/diff-index-quick-exit-early' into maint X-Git-Tag: v1.7.6.1~32 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/f253376dcbadb384d8c8af287c3f9e2271cb5ff4?ds=inline;hp=-c Merge branch 'jc/diff-index-quick-exit-early' into maint * jc/diff-index-quick-exit-early: diff-index --quiet: learn the "stop feeding the backend early" logic Conflicts: unpack-trees.h --- f253376dcbadb384d8c8af287c3f9e2271cb5ff4 diff --combined unpack-trees.c index e22b9ec408,b2b6a901b2..cc616c3f99 --- a/unpack-trees.c +++ b/unpack-trees.c @@@ -203,7 -203,7 +203,7 @@@ static int check_updates(struct unpack_ if (ce->ce_flags & CE_WT_REMOVE) { display_progress(progress, ++cnt); - if (o->update) + if (o->update && !o->dry_run) unlink_entry(ce); continue; } @@@ -217,7 -217,7 +217,7 @@@ if (ce->ce_flags & CE_UPDATE) { display_progress(progress, ++cnt); ce->ce_flags &= ~CE_UPDATE; - if (o->update) { + if (o->update && !o->dry_run) { errs |= checkout_entry(ce, &state, NULL); } } @@@ -593,7 -593,7 +593,7 @@@ static int unpack_nondirectories(int n static int unpack_failed(struct unpack_trees_options *o, const char *message) { discard_index(&o->result); - if (!o->gently) { + if (!o->gently && !o->exiting_early) { if (message) return error("%s", message); return -1; @@@ -814,45 -814,43 +814,45 @@@ static int unpack_callback(int n, unsig return mask; } +static int clear_ce_flags_1(struct cache_entry **cache, int nr, + char *prefix, int prefix_len, + int select_mask, int clear_mask, + struct exclude_list *el, int defval); + /* Whole directory matching */ static int clear_ce_flags_dir(struct cache_entry **cache, int nr, char *prefix, int prefix_len, char *basename, int select_mask, int clear_mask, - struct exclude_list *el) + struct exclude_list *el, int defval) { - struct cache_entry **cache_end = cache + nr; + struct cache_entry **cache_end; int dtype = DT_DIR; int ret = excluded_from_list(prefix, prefix_len, basename, &dtype, el); prefix[prefix_len++] = '/'; - /* included, no clearing for any entries under this directory */ - if (!ret) { - for (; cache != cache_end; cache++) { - struct cache_entry *ce = *cache; - if (strncmp(ce->name, prefix, prefix_len)) - break; - } - return nr - (cache_end - cache); - } + /* If undecided, use matching result of parent dir in defval */ + if (ret < 0) + ret = defval; - /* excluded, clear all selected entries under this directory. */ - if (ret == 1) { - for (; cache != cache_end; cache++) { - struct cache_entry *ce = *cache; - if (select_mask && !(ce->ce_flags & select_mask)) - continue; - if (strncmp(ce->name, prefix, prefix_len)) - break; - ce->ce_flags &= ~clear_mask; - } - return nr - (cache_end - cache); + for (cache_end = cache; cache_end != cache + nr; cache_end++) { + struct cache_entry *ce = *cache_end; + if (strncmp(ce->name, prefix, prefix_len)) + break; } - return 0; + /* + * TODO: check el, if there are no patterns that may conflict + * with ret (iow, we know in advance the incl/excl + * decision for the entire directory), clear flag here without + * calling clear_ce_flags_1(). That function will call + * the expensive excluded_from_list() on every entry. + */ + return clear_ce_flags_1(cache, cache_end - cache, + prefix, prefix_len, + select_mask, clear_mask, + el, ret); } /* @@@ -873,7 -871,7 +873,7 @@@ static int clear_ce_flags_1(struct cache_entry **cache, int nr, char *prefix, int prefix_len, int select_mask, int clear_mask, - struct exclude_list *el) + struct exclude_list *el, int defval) { struct cache_entry **cache_end = cache + nr; @@@ -884,7 -882,7 +884,7 @@@ while(cache != cache_end) { struct cache_entry *ce = *cache; const char *name, *slash; - int len, dtype; + int len, dtype, ret; if (select_mask && !(ce->ce_flags & select_mask)) { cache++; @@@ -913,7 -911,7 +913,7 @@@ prefix, prefix_len + len, prefix + prefix_len, select_mask, clear_mask, - el); + el, defval); /* clear_c_f_dir eats a whole dir already? */ if (processed) { @@@ -924,16 -922,13 +924,16 @@@ prefix[prefix_len + len++] = '/'; cache += clear_ce_flags_1(cache, cache_end - cache, prefix, prefix_len + len, - select_mask, clear_mask, el); + select_mask, clear_mask, el, defval); continue; } /* Non-directory */ dtype = ce_to_dtype(ce); - if (excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, el) > 0) + ret = excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, el); + if (ret < 0) + ret = defval; + if (ret > 0) ce->ce_flags &= ~clear_mask; cache++; } @@@ -948,7 -943,7 +948,7 @@@ static int clear_ce_flags(struct cache_ return clear_ce_flags_1(cache, nr, prefix, 0, select_mask, clear_mask, - el); + el, 0); } /* @@@ -1133,6 -1128,8 +1133,8 @@@ return_failed display_error_msgs(o); mark_all_ce_unused(o->src_index); ret = unpack_failed(o, NULL); + if (o->exiting_early) + ret = 0; goto done; } @@@ -1166,22 -1163,11 +1168,22 @@@ static int verify_uptodate_1(struct cac { struct stat st; - if (o->index_only || (!((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) && (o->reset || ce_uptodate(ce)))) + if (o->index_only) + return 0; + + /* + * CE_VALID and CE_SKIP_WORKTREE cheat, we better check again + * if this entry is truly up-to-date because this file may be + * overwritten. + */ + if ((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) + ; /* keep checking */ + else if (o->reset || ce_uptodate(ce)) return 0; if (!lstat(ce->name, &st)) { - unsigned changed = ie_match_stat(o->src_index, ce, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE); + int flags = CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE; + unsigned changed = ie_match_stat(o->src_index, ce, &st, flags); if (!changed) return 0; /* diff --combined unpack-trees.h index 64f02cb03a,4c6c54033e..7998948307 --- a/unpack-trees.h +++ b/unpack-trees.h @@@ -46,8 -46,8 +46,9 @@@ struct unpack_trees_options debug_unpack, skip_sparse_checkout, gently, + exiting_early, - show_all_errors; + show_all_errors, + dry_run; const char *prefix; int cache_bottom; struct dir_struct *dir;