X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=diff-lib.c;h=f8454dd2918dc74bee43d9f2faa1837cc5665abd;hb=7140c22c8e98042053d5ff63c8514f5cdf1cb6ed;hp=f8e33256ebe7ecd6ebf69669d9bfe50488c01fa1;hpb=34df9fe36a3627e1c2a9ae244820fb61e3891b90;p=git.git diff --git a/diff-lib.c b/diff-lib.c index f8e33256e..f8454dd29 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -102,16 +102,16 @@ int run_diff_files(struct rev_info *revs, unsigned int option) int changed; unsigned dirty_submodule = 0; - if (DIFF_OPT_TST(&revs->diffopt, QUICK) && - !revs->diffopt.filter && - DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES)) + if (diff_can_quit_early(&revs->diffopt)) break; - if (!ce_path_match(ce, revs->prune_data)) + if (!ce_path_match(ce, &revs->prune_data)) continue; if (ce_stage(ce)) { struct combine_diff_path *dpath; + struct diff_filepair *pair; + unsigned int wt_mode = 0; int num_compare_stages = 0; size_t path_len; @@ -130,7 +130,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) changed = check_removed(ce, &st); if (!changed) - dpath->mode = ce_mode_from_stat(ce, st.st_mode); + wt_mode = ce_mode_from_stat(ce, st.st_mode); else { if (changed < 0) { perror(ce->name); @@ -138,7 +138,9 @@ int run_diff_files(struct rev_info *revs, unsigned int option) } if (silent_on_removed) continue; + wt_mode = 0; } + dpath->mode = wt_mode; while (i < entries) { struct cache_entry *nce = active_cache[i]; @@ -184,7 +186,9 @@ int run_diff_files(struct rev_info *revs, unsigned int option) * Show the diff for the 'ce' if we found the one * from the desired stage. */ - diff_unmerge(&revs->diffopt, ce->name, 0, null_sha1); + pair = diff_unmerge(&revs->diffopt, ce->name); + if (wt_mode) + pair->two->mode = wt_mode; if (ce_stage(ce) != diff_unmerged_stage) continue; } @@ -373,8 +377,10 @@ static void do_oneway_diff(struct unpack_trees_options *o, match_missing = !revs->ignore_merges; if (cached && idx && ce_stage(idx)) { - diff_unmerge(&revs->diffopt, idx->name, idx->ce_mode, - idx->sha1); + struct diff_filepair *pair; + pair = diff_unmerge(&revs->diffopt, idx->name); + if (tree) + fill_filespec(pair->one, tree->sha1, tree->ce_mode); return; } @@ -428,26 +434,30 @@ static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o) if (tree == o->df_conflict_entry) tree = NULL; - if (ce_path_match(idx ? idx : tree, revs->prune_data)) + if (ce_path_match(idx ? idx : tree, &revs->prune_data)) { do_oneway_diff(o, idx, tree); + if (diff_can_quit_early(&revs->diffopt)) { + o->exiting_early = 1; + return -1; + } + } return 0; } -int run_diff_index(struct rev_info *revs, int cached) +static int diff_cache(struct rev_info *revs, + const unsigned char *tree_sha1, + const char *tree_name, + int cached) { - struct object *ent; struct tree *tree; - const char *tree_name; - struct unpack_trees_options opts; struct tree_desc t; + struct unpack_trees_options opts; - ent = revs->pending.objects[0].item; - tree_name = revs->pending.objects[0].name; - tree = parse_tree_indirect(ent->sha1); + tree = parse_tree_indirect(tree_sha1); if (!tree) - return error("bad tree object %s", tree_name); - + return error("bad tree object %s", + tree_name ? tree_name : sha1_to_hex(tree_sha1)); memset(&opts, 0, sizeof(opts)); opts.head_idx = 1; opts.index_only = cached; @@ -460,7 +470,15 @@ int run_diff_index(struct rev_info *revs, int cached) opts.dst_index = NULL; init_tree_desc(&t, tree->buffer, tree->size); - if (unpack_trees(1, &t, &opts)) + return unpack_trees(1, &t, &opts); +} + +int run_diff_index(struct rev_info *revs, int cached) +{ + struct object_array_entry *ent; + + ent = revs->pending.objects; + if (diff_cache(revs, ent->item->sha1, ent->name, cached)) exit(128); diff_set_mnemonic_prefix(&revs->diffopt, "c/", cached ? "i/" : "w/"); @@ -472,53 +490,13 @@ int run_diff_index(struct rev_info *revs, int cached) int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt) { - struct tree *tree; struct rev_info revs; - int i; - struct cache_entry **dst; - struct cache_entry *last = NULL; - struct unpack_trees_options opts; - struct tree_desc t; - - /* - * This is used by git-blame to run diff-cache internally; - * it potentially needs to repeatedly run this, so we will - * start by removing the higher order entries the last round - * left behind. - */ - dst = active_cache; - for (i = 0; i < active_nr; i++) { - struct cache_entry *ce = active_cache[i]; - if (ce_stage(ce)) { - if (last && !strcmp(ce->name, last->name)) - continue; - cache_tree_invalidate_path(active_cache_tree, - ce->name); - last = ce; - ce->ce_flags |= CE_REMOVE; - } - *dst++ = ce; - } - active_nr = dst - active_cache; init_revisions(&revs, NULL); - revs.prune_data = opt->paths; - tree = parse_tree_indirect(tree_sha1); - if (!tree) - die("bad tree object %s", sha1_to_hex(tree_sha1)); - - memset(&opts, 0, sizeof(opts)); - opts.head_idx = 1; - opts.index_only = 1; - opts.diff_index_cached = !DIFF_OPT_TST(opt, FIND_COPIES_HARDER); - opts.merge = 1; - opts.fn = oneway_diff; - opts.unpack_data = &revs; - opts.src_index = &the_index; - opts.dst_index = &the_index; + init_pathspec(&revs.prune_data, opt->pathspec.raw); + revs.diffopt = *opt; - init_tree_desc(&t, tree->buffer, tree->size); - if (unpack_trees(1, &t, &opts)) + if (diff_cache(&revs, tree_sha1, NULL, 1)) exit(128); return 0; }