diff options
Diffstat (limited to 'diff-lib.c')
-rw-r--r-- | diff-lib.c | 95 |
1 files changed, 62 insertions, 33 deletions
diff --git a/diff-lib.c b/diff-lib.c index 2eddc66bbd..52447466b5 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -91,20 +91,17 @@ int run_diff_files(struct rev_info *revs, unsigned int option) unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED) ? CE_MATCH_RACY_IS_DIRTY : 0); - if (option & DIFF_SILENT_ON_REMOVED) - handle_deprecated_show_diff_q(&revs->diffopt); - diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/"); if (diff_unmerged_stage < 0) diff_unmerged_stage = 2; entries = active_nr; for (i = 0; i < entries; i++) { - struct stat st; unsigned int oldmode, newmode; struct cache_entry *ce = active_cache[i]; int changed; unsigned dirty_submodule = 0; + const unsigned char *old_sha1, *new_sha1; if (diff_can_quit_early(&revs->diffopt)) break; @@ -118,6 +115,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) unsigned int wt_mode = 0; int num_compare_stages = 0; size_t path_len; + struct stat st; path_len = ce_namelen(ce); @@ -125,10 +123,9 @@ int run_diff_files(struct rev_info *revs, unsigned int option) dpath->path = (char *) &(dpath->parent[5]); dpath->next = NULL; - dpath->len = path_len; memcpy(dpath->path, ce->name, path_len); dpath->path[path_len] = '\0'; - hashclr(dpath->sha1); + oidclr(&dpath->oid); memset(&(dpath->parent[0]), 0, sizeof(struct combine_diff_parent)*5); @@ -158,7 +155,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option) if (2 <= stage) { int mode = nce->ce_mode; num_compare_stages++; - hashcpy(dpath->parent[stage-2].sha1, nce->sha1); + oidcpy(&dpath->parent[stage - 2].oid, + &nce->oid); dpath->parent[stage-2].mode = ce_mode_from_stat(nce, mode); dpath->parent[stage-2].status = DIFF_STATUS_MODIFIED; @@ -199,29 +197,48 @@ int run_diff_files(struct rev_info *revs, unsigned int option) continue; /* If CE_VALID is set, don't look at workdir for file removal */ - changed = (ce->ce_flags & CE_VALID) ? 0 : check_removed(ce, &st); - if (changed) { - if (changed < 0) { - perror(ce->name); + if (ce->ce_flags & CE_VALID) { + changed = 0; + newmode = ce->ce_mode; + } else { + struct stat st; + + changed = check_removed(ce, &st); + if (changed) { + if (changed < 0) { + perror(ce->name); + continue; + } + diff_addremove(&revs->diffopt, '-', ce->ce_mode, + ce->oid.hash, + !is_null_oid(&ce->oid), + ce->name, 0); + continue; + } else if (revs->diffopt.ita_invisible_in_index && + ce_intent_to_add(ce)) { + diff_addremove(&revs->diffopt, '+', ce->ce_mode, + EMPTY_BLOB_SHA1_BIN, 0, + ce->name, 0); continue; } - diff_addremove(&revs->diffopt, '-', ce->ce_mode, - ce->sha1, !is_null_sha1(ce->sha1), - ce->name, 0); - continue; + + changed = match_stat_with_submodule(&revs->diffopt, ce, &st, + ce_option, &dirty_submodule); + newmode = ce_mode_from_stat(ce, st.st_mode); } - changed = match_stat_with_submodule(&revs->diffopt, ce, &st, - ce_option, &dirty_submodule); + if (!changed && !dirty_submodule) { ce_mark_uptodate(ce); if (!DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER)) continue; } oldmode = ce->ce_mode; - newmode = ce_mode_from_stat(ce, st.st_mode); + old_sha1 = ce->oid.hash; + new_sha1 = changed ? null_sha1 : ce->oid.hash; diff_change(&revs->diffopt, oldmode, newmode, - ce->sha1, (changed ? null_sha1 : ce->sha1), - !is_null_sha1(ce->sha1), (changed ? 0 : !is_null_sha1(ce->sha1)), + old_sha1, new_sha1, + !is_null_sha1(old_sha1), + !is_null_sha1(new_sha1), ce->name, 0, dirty_submodule); } @@ -252,7 +269,7 @@ static int get_stat_data(const struct cache_entry *ce, int cached, int match_missing, unsigned *dirty_submodule, struct diff_options *diffopt) { - const unsigned char *sha1 = ce->sha1; + const unsigned char *sha1 = ce->oid.hash; unsigned int mode = ce->ce_mode; if (!cached && !ce_uptodate(ce)) { @@ -315,42 +332,42 @@ static int show_modified(struct rev_info *revs, &dirty_submodule, &revs->diffopt) < 0) { if (report_missing) diff_index_show_file(revs, "-", old, - old->sha1, 1, old->ce_mode, 0); + old->oid.hash, 1, old->ce_mode, + 0); return -1; } if (revs->combine_merges && !cached && - (hashcmp(sha1, old->sha1) || hashcmp(old->sha1, new->sha1))) { + (hashcmp(sha1, old->oid.hash) || oidcmp(&old->oid, &new->oid))) { struct combine_diff_path *p; int pathlen = ce_namelen(new); p = xmalloc(combine_diff_path_size(2, pathlen)); p->path = (char *) &p->parent[2]; p->next = NULL; - p->len = pathlen; memcpy(p->path, new->name, pathlen); p->path[pathlen] = 0; p->mode = mode; - hashclr(p->sha1); + oidclr(&p->oid); memset(p->parent, 0, 2 * sizeof(struct combine_diff_parent)); p->parent[0].status = DIFF_STATUS_MODIFIED; p->parent[0].mode = new->ce_mode; - hashcpy(p->parent[0].sha1, new->sha1); + oidcpy(&p->parent[0].oid, &new->oid); p->parent[1].status = DIFF_STATUS_MODIFIED; p->parent[1].mode = old->ce_mode; - hashcpy(p->parent[1].sha1, old->sha1); + oidcpy(&p->parent[1].oid, &old->oid); show_combined_diff(p, 2, revs->dense_combined_merges, revs); free(p); return 0; } oldmode = old->ce_mode; - if (mode == oldmode && !hashcmp(sha1, old->sha1) && !dirty_submodule && + if (mode == oldmode && !hashcmp(sha1, old->oid.hash) && !dirty_submodule && !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER)) return 0; diff_change(&revs->diffopt, oldmode, mode, - old->sha1, sha1, 1, !is_null_sha1(sha1), + old->oid.hash, sha1, 1, !is_null_sha1(sha1), old->name, 0, dirty_submodule); return 0; } @@ -368,6 +385,14 @@ static void do_oneway_diff(struct unpack_trees_options *o, struct rev_info *revs = o->unpack_data; int match_missing, cached; + /* i-t-a entries do not actually exist in the index */ + if (revs->diffopt.ita_invisible_in_index && + idx && ce_intent_to_add(idx)) { + idx = NULL; + if (!tree) + return; /* nothing to diff.. */ + } + /* if the entry is not checked out, don't examine work tree */ cached = o->index_only || (idx && ((idx->ce_flags & CE_VALID) || ce_skip_worktree(idx))); @@ -384,7 +409,8 @@ static void do_oneway_diff(struct unpack_trees_options *o, struct diff_filepair *pair; pair = diff_unmerge(&revs->diffopt, idx->name); if (tree) - fill_filespec(pair->one, tree->sha1, 1, tree->ce_mode); + fill_filespec(pair->one, tree->oid.hash, 1, + tree->ce_mode); return; } @@ -400,7 +426,8 @@ static void do_oneway_diff(struct unpack_trees_options *o, * Something removed from the tree? */ if (!idx) { - diff_index_show_file(revs, "-", tree, tree->sha1, 1, tree->ce_mode, 0); + diff_index_show_file(revs, "-", tree, tree->oid.hash, 1, + tree->ce_mode, 0); return; } @@ -485,7 +512,7 @@ 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)) + if (diff_cache(revs, ent->item->oid.hash, ent->name, cached)) exit(128); diff_set_mnemonic_prefix(&revs->diffopt, "c/", cached ? "i/" : "w/"); @@ -508,7 +535,8 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt) return 0; } -int index_differs_from(const char *def, int diff_flags) +int index_differs_from(const char *def, int diff_flags, + int ita_invisible_in_index) { struct rev_info rev; struct setup_revision_opt opt; @@ -520,6 +548,7 @@ int index_differs_from(const char *def, int diff_flags) DIFF_OPT_SET(&rev.diffopt, QUICK); DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS); rev.diffopt.flags |= diff_flags; + rev.diffopt.ita_invisible_in_index = ita_invisible_in_index; run_diff_index(&rev, 1); if (rev.pending.alloc) free(rev.pending.objects); |