static int get_stat_data(struct cache_entry *ce, const unsigned char **sha1p, unsigned int *modep, int cached, int match_missing) { const unsigned char *sha1 = ce->sha1; unsigned int mode = ce->ce_mode; if (!cached && !ce_uptodate(ce)) { int changed; struct stat st; changed = check_removed(ce, &st); if (changed < 0) return -1; else if (changed) { if (match_missing) { *sha1p = sha1; *modep = mode; return 0; } return -1; } changed = ce_match_stat(ce, &st, 0); if (changed) { mode = ce_mode_from_stat(ce, st.st_mode); sha1 = null_sha1; } } *sha1p = sha1; *modep = mode; return 0; }
void stage_updated_gitmodules(void) { struct strbuf buf = STRBUF_INIT; struct stat st; int pos; struct cache_entry *ce; int namelen = strlen(".gitmodules"); pos = cache_name_pos(".gitmodules", namelen); if (pos < 0) { warning(_("could not find .gitmodules in index")); return; } ce = active_cache[pos]; ce->ce_flags = namelen; if (strbuf_read_file(&buf, ".gitmodules", 0) < 0) die(_("reading updated .gitmodules failed")); if (lstat(".gitmodules", &st) < 0) die_errno(_("unable to stat updated .gitmodules")); fill_stat_cache_info(ce, &st); ce->ce_mode = ce_mode_from_stat(ce, st.st_mode); if (remove_cache_entry_at(pos) < 0) die(_("unable to remove .gitmodules from index")); if (write_sha1_file(buf.buf, buf.len, blob_type, ce->sha1)) die(_("adding updated .gitmodules failed")); if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE)) die(_("staging updated .gitmodules failed")); }
static int add_one_path(const struct cache_entry *old, const char *path, int len, struct stat *st) { int option, size; struct cache_entry *ce; /* Was the old index entry already up-to-date? */ if (old && !ce_stage(old) && !ce_match_stat(old, st, 0)) return 0; size = cache_entry_size(len); ce = xcalloc(1, size); memcpy(ce->name, path, len); ce->ce_flags = create_ce_flags(0); ce->ce_namelen = len; fill_stat_cache_info(ce, st); ce->ce_mode = ce_mode_from_stat(old, st->st_mode); if (index_path(ce->sha1, path, st, info_only ? 0 : HASH_WRITE_OBJECT)) { free(ce); return -1; } option = allow_add ? ADD_CACHE_OK_TO_ADD : 0; option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0; if (add_cache_entry(ce, option)) return error("%s: cannot add to the index - missing --add option?", path); return 0; }
static int get_stat_data(const struct cache_entry *ce, const struct object_id **oidp, unsigned int *modep, int cached, int match_missing, unsigned *dirty_submodule, struct diff_options *diffopt) { const struct object_id *oid = &ce->oid; unsigned int mode = ce->ce_mode; if (!cached && !ce_uptodate(ce)) { int changed; struct stat st; changed = check_removed(ce, &st); if (changed < 0) return -1; else if (changed) { if (match_missing) { *oidp = oid; *modep = mode; return 0; } return -1; } changed = match_stat_with_submodule(diffopt, ce, &st, 0, dirty_submodule); if (changed) { mode = ce_mode_from_stat(ce, st.st_mode); oid = &null_oid; } } *oidp = oid; *modep = mode; return 0; }
static int get_stat_data(struct cache_entry *ce, const unsigned char **sha1p, unsigned int *modep, int cached, int match_missing, unsigned *dirty_submodule, struct diff_options *diffopt) { const unsigned char *sha1 = ce->sha1; unsigned int mode = ce->ce_mode; if (!cached && !ce_uptodate(ce)) { int changed; struct stat st; changed = check_removed(ce, &st); if (changed < 0) return -1; else if (changed) { if (match_missing) { *sha1p = sha1; *modep = mode; return 0; } return -1; } changed = ce_match_stat(ce, &st, 0); if (S_ISGITLINK(ce->ce_mode) && !DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES) && (!changed || (diffopt->output_format & DIFF_FORMAT_PATCH)) && is_submodule_modified(ce->name)) { changed = 1; *dirty_submodule = 1; } if (changed) { mode = ce_mode_from_stat(ce, st.st_mode); sha1 = null_sha1; } } *sha1p = sha1; *modep = mode; return 0; }
int run_diff_files(struct rev_info *revs, unsigned int option) { int entries, i; int diff_unmerged_stage = revs->max_count; int silent_on_removed = option & DIFF_SILENT_ON_REMOVED; unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED) ? CE_MATCH_RACY_IS_DIRTY : 0); 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; if (DIFF_OPT_TST(&revs->diffopt, QUIET) && DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES)) break; if (!ce_path_match(ce, revs->prune_data)) continue; if (ce_stage(ce)) { struct combine_diff_path *dpath; int num_compare_stages = 0; size_t path_len; path_len = ce_namelen(ce); dpath = xmalloc(combine_diff_path_size(5, path_len)); 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); memset(&(dpath->parent[0]), 0, sizeof(struct combine_diff_parent)*5); changed = check_removed(ce, &st); if (!changed) dpath->mode = ce_mode_from_stat(ce, st.st_mode); else { if (changed < 0) { perror(ce->name); continue; } if (silent_on_removed) continue; } while (i < entries) { struct cache_entry *nce = active_cache[i]; int stage; if (strcmp(ce->name, nce->name)) break; /* Stage #2 (ours) is the first parent, * stage #3 (theirs) is the second. */ stage = ce_stage(nce); if (2 <= stage) { int mode = nce->ce_mode; num_compare_stages++; hashcpy(dpath->parent[stage-2].sha1, nce->sha1); dpath->parent[stage-2].mode = ce_mode_from_stat(nce, mode); dpath->parent[stage-2].status = DIFF_STATUS_MODIFIED; } /* diff against the proper unmerged stage */ if (stage == diff_unmerged_stage) ce = nce; i++; } /* * Compensate for loop update */ i--; if (revs->combine_merges && num_compare_stages == 2) { show_combined_diff(dpath, 2, revs->dense_combined_merges, revs); free(dpath); continue; } free(dpath); dpath = NULL; /* * Show the diff for the 'ce' if we found the one * from the desired stage. */ diff_unmerge(&revs->diffopt, ce->name, 0, null_sha1); if (ce_stage(ce) != diff_unmerged_stage) continue; } if (ce_uptodate(ce)) continue; changed = check_removed(ce, &st); if (changed) { if (changed < 0) { perror(ce->name); continue; } if (silent_on_removed) continue; diff_addremove(&revs->diffopt, '-', ce->ce_mode, ce->sha1, ce->name); continue; } changed = ce_match_stat(ce, &st, ce_option); if (!changed) { 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); diff_change(&revs->diffopt, oldmode, newmode, ce->sha1, (changed ? null_sha1 : ce->sha1), ce->name); } diffcore_std(&revs->diffopt); diff_flush(&revs->diffopt); return 0; }
int run_diff_files(struct rev_info *revs, unsigned int option) { int entries, i; int diff_unmerged_stage = revs->max_count; unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED) ? CE_MATCH_RACY_IS_DIRTY : 0); 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++) { 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; if (!ce_path_match(ce, &revs->prune_data, NULL)) 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; struct stat st; path_len = ce_namelen(ce); dpath = xmalloc(combine_diff_path_size(5, path_len)); dpath->path = (char *) &(dpath->parent[5]); dpath->next = NULL; memcpy(dpath->path, ce->name, path_len); dpath->path[path_len] = '\0'; oidclr(&dpath->oid); memset(&(dpath->parent[0]), 0, sizeof(struct combine_diff_parent)*5); changed = check_removed(ce, &st); if (!changed) wt_mode = ce_mode_from_stat(ce, st.st_mode); else { if (changed < 0) { perror(ce->name); continue; } wt_mode = 0; } dpath->mode = wt_mode; while (i < entries) { struct cache_entry *nce = active_cache[i]; int stage; if (strcmp(ce->name, nce->name)) break; /* Stage #2 (ours) is the first parent, * stage #3 (theirs) is the second. */ stage = ce_stage(nce); if (2 <= stage) { int mode = nce->ce_mode; num_compare_stages++; hashcpy(dpath->parent[stage-2].oid.hash, nce->sha1); dpath->parent[stage-2].mode = ce_mode_from_stat(nce, mode); dpath->parent[stage-2].status = DIFF_STATUS_MODIFIED; } /* diff against the proper unmerged stage */ if (stage == diff_unmerged_stage) ce = nce; i++; } /* * Compensate for loop update */ i--; if (revs->combine_merges && num_compare_stages == 2) { show_combined_diff(dpath, 2, revs->dense_combined_merges, revs); free(dpath); continue; } free(dpath); dpath = NULL; /* * Show the diff for the 'ce' if we found the one * from the desired stage. */ pair = diff_unmerge(&revs->diffopt, ce->name); if (wt_mode) pair->two->mode = wt_mode; if (ce_stage(ce) != diff_unmerged_stage) continue; } if (ce_uptodate(ce) || ce_skip_worktree(ce)) continue; /* If CE_VALID is set, don't look at workdir for file removal */ 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->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); } if (!changed && !dirty_submodule) { ce_mark_uptodate(ce); if (!DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER)) continue; } oldmode = ce->ce_mode; old_sha1 = ce->sha1; new_sha1 = changed ? null_sha1 : ce->sha1; diff_change(&revs->diffopt, oldmode, newmode, old_sha1, new_sha1, !is_null_sha1(old_sha1), !is_null_sha1(new_sha1), ce->name, 0, dirty_submodule); } diffcore_std(&revs->diffopt); diff_flush(&revs->diffopt); return 0; }
static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, int argc, const char **argv) { char tmpdir[PATH_MAX]; struct strbuf info = STRBUF_INIT, lpath = STRBUF_INIT; struct strbuf rpath = STRBUF_INIT, buf = STRBUF_INIT; struct strbuf ldir = STRBUF_INIT, rdir = STRBUF_INIT; struct strbuf wtdir = STRBUF_INIT; size_t ldir_len, rdir_len, wtdir_len; struct cache_entry *ce = xcalloc(1, sizeof(ce) + PATH_MAX + 1); const char *workdir, *tmp; int ret = 0, i; FILE *fp; struct hashmap working_tree_dups, submodules, symlinks2; struct hashmap_iter iter; struct pair_entry *entry; enum object_type type; unsigned long size; struct index_state wtindex; struct checkout lstate, rstate; int rc, flags = RUN_GIT_CMD, err = 0; struct child_process child = CHILD_PROCESS_INIT; const char *helper_argv[] = { "difftool--helper", NULL, NULL, NULL }; struct hashmap wt_modified, tmp_modified; int indices_loaded = 0; workdir = get_git_work_tree(); /* Setup temp directories */ tmp = getenv("TMPDIR"); xsnprintf(tmpdir, sizeof(tmpdir), "%s/git-difftool.XXXXXX", tmp ? tmp : "/tmp"); if (!mkdtemp(tmpdir)) return error("could not create '%s'", tmpdir); strbuf_addf(&ldir, "%s/left/", tmpdir); strbuf_addf(&rdir, "%s/right/", tmpdir); strbuf_addstr(&wtdir, workdir); if (!wtdir.len || !is_dir_sep(wtdir.buf[wtdir.len - 1])) strbuf_addch(&wtdir, '/'); mkdir(ldir.buf, 0700); mkdir(rdir.buf, 0700); memset(&wtindex, 0, sizeof(wtindex)); memset(&lstate, 0, sizeof(lstate)); lstate.base_dir = ldir.buf; lstate.base_dir_len = ldir.len; lstate.force = 1; memset(&rstate, 0, sizeof(rstate)); rstate.base_dir = rdir.buf; rstate.base_dir_len = rdir.len; rstate.force = 1; ldir_len = ldir.len; rdir_len = rdir.len; wtdir_len = wtdir.len; hashmap_init(&working_tree_dups, (hashmap_cmp_fn)working_tree_entry_cmp, 0); hashmap_init(&submodules, (hashmap_cmp_fn)pair_cmp, 0); hashmap_init(&symlinks2, (hashmap_cmp_fn)pair_cmp, 0); child.no_stdin = 1; child.git_cmd = 1; child.use_shell = 0; child.clean_on_exit = 1; child.dir = prefix; child.out = -1; argv_array_pushl(&child.args, "diff", "--raw", "--no-abbrev", "-z", NULL); for (i = 0; i < argc; i++) argv_array_push(&child.args, argv[i]); if (start_command(&child)) die("could not obtain raw diff"); fp = xfdopen(child.out, "r"); /* Build index info for left and right sides of the diff */ i = 0; while (!strbuf_getline_nul(&info, fp)) { int lmode, rmode; struct object_id loid, roid; char status; const char *src_path, *dst_path; size_t src_path_len, dst_path_len; if (starts_with(info.buf, "::")) die(N_("combined diff formats('-c' and '--cc') are " "not supported in\n" "directory diff mode('-d' and '--dir-diff').")); if (parse_index_info(info.buf, &lmode, &rmode, &loid, &roid, &status)) break; if (strbuf_getline_nul(&lpath, fp)) break; src_path = lpath.buf; src_path_len = lpath.len; i++; if (status != 'C' && status != 'R') { dst_path = src_path; dst_path_len = src_path_len; } else { if (strbuf_getline_nul(&rpath, fp)) break; dst_path = rpath.buf; dst_path_len = rpath.len; } if (S_ISGITLINK(lmode) || S_ISGITLINK(rmode)) { strbuf_reset(&buf); strbuf_addf(&buf, "Subproject commit %s", oid_to_hex(&loid)); add_left_or_right(&submodules, src_path, buf.buf, 0); strbuf_reset(&buf); strbuf_addf(&buf, "Subproject commit %s", oid_to_hex(&roid)); if (!oidcmp(&loid, &roid)) strbuf_addstr(&buf, "-dirty"); add_left_or_right(&submodules, dst_path, buf.buf, 1); continue; } if (S_ISLNK(lmode)) { char *content = read_sha1_file(loid.hash, &type, &size); add_left_or_right(&symlinks2, src_path, content, 0); free(content); } if (S_ISLNK(rmode)) { char *content = read_sha1_file(roid.hash, &type, &size); add_left_or_right(&symlinks2, dst_path, content, 1); free(content); } if (lmode && status != 'C') { ce->ce_mode = lmode; oidcpy(&ce->oid, &loid); strcpy(ce->name, src_path); ce->ce_namelen = src_path_len; if (checkout_entry(ce, &lstate, NULL)) return error("could not write '%s'", src_path); } if (rmode) { struct working_tree_entry *entry; /* Avoid duplicate working_tree entries */ FLEX_ALLOC_STR(entry, path, dst_path); hashmap_entry_init(entry, strhash(dst_path)); if (hashmap_get(&working_tree_dups, entry, NULL)) { free(entry); continue; } hashmap_add(&working_tree_dups, entry); if (!use_wt_file(workdir, dst_path, &roid)) { ce->ce_mode = rmode; oidcpy(&ce->oid, &roid); strcpy(ce->name, dst_path); ce->ce_namelen = dst_path_len; if (checkout_entry(ce, &rstate, NULL)) return error("could not write '%s'", dst_path); } else if (!is_null_oid(&roid)) { /* * Changes in the working tree need special * treatment since they are not part of the * index. */ struct cache_entry *ce2 = make_cache_entry(rmode, roid.hash, dst_path, 0, 0); ce_mode_from_stat(ce2, rmode); add_index_entry(&wtindex, ce2, ADD_CACHE_JUST_APPEND); add_path(&wtdir, wtdir_len, dst_path); add_path(&rdir, rdir_len, dst_path); if (ensure_leading_directories(rdir.buf)) return error("could not create " "directory for '%s'", dst_path); if (symlinks) { if (symlink(wtdir.buf, rdir.buf)) { ret = error_errno("could not symlink '%s' to '%s'", wtdir.buf, rdir.buf); goto finish; } } else { struct stat st; if (stat(wtdir.buf, &st)) st.st_mode = 0644; if (copy_file(rdir.buf, wtdir.buf, st.st_mode)) { ret = error("could not copy '%s' to '%s'", wtdir.buf, rdir.buf); goto finish; } } } } } if (finish_command(&child)) { ret = error("error occurred running diff --raw"); goto finish; } if (!i) return 0; /* * Changes to submodules require special treatment.This loop writes a * temporary file to both the left and right directories to show the * change in the recorded SHA1 for the submodule. */ hashmap_iter_init(&submodules, &iter); while ((entry = hashmap_iter_next(&iter))) { if (*entry->left) { add_path(&ldir, ldir_len, entry->path); ensure_leading_directories(ldir.buf); write_file(ldir.buf, "%s", entry->left); } if (*entry->right) { add_path(&rdir, rdir_len, entry->path); ensure_leading_directories(rdir.buf); write_file(rdir.buf, "%s", entry->right); } } /* * Symbolic links require special treatment.The standard "git diff" * shows only the link itself, not the contents of the link target. * This loop replicates that behavior. */ hashmap_iter_init(&symlinks2, &iter); while ((entry = hashmap_iter_next(&iter))) { if (*entry->left) { add_path(&ldir, ldir_len, entry->path); ensure_leading_directories(ldir.buf); write_file(ldir.buf, "%s", entry->left); } if (*entry->right) { add_path(&rdir, rdir_len, entry->path); ensure_leading_directories(rdir.buf); write_file(rdir.buf, "%s", entry->right); } } strbuf_release(&buf); strbuf_setlen(&ldir, ldir_len); helper_argv[1] = ldir.buf; strbuf_setlen(&rdir, rdir_len); helper_argv[2] = rdir.buf; if (extcmd) { helper_argv[0] = extcmd; flags = 0; } else setenv("GIT_DIFFTOOL_DIRDIFF", "true", 1); rc = run_command_v_opt(helper_argv, flags); /* * If the diff includes working copy files and those * files were modified during the diff, then the changes * should be copied back to the working tree. * Do not copy back files when symlinks are used and the * external tool did not replace the original link with a file. * * These hashes are loaded lazily since they aren't needed * in the common case of --symlinks and the difftool updating * files through the symlink. */ hashmap_init(&wt_modified, (hashmap_cmp_fn)path_entry_cmp, wtindex.cache_nr); hashmap_init(&tmp_modified, (hashmap_cmp_fn)path_entry_cmp, wtindex.cache_nr); for (i = 0; i < wtindex.cache_nr; i++) { struct hashmap_entry dummy; const char *name = wtindex.cache[i]->name; struct stat st; add_path(&rdir, rdir_len, name); if (lstat(rdir.buf, &st)) continue; if ((symlinks && S_ISLNK(st.st_mode)) || !S_ISREG(st.st_mode)) continue; if (!indices_loaded) { static struct lock_file lock; strbuf_reset(&buf); strbuf_addf(&buf, "%s/wtindex", tmpdir); if (hold_lock_file_for_update(&lock, buf.buf, 0) < 0 || write_locked_index(&wtindex, &lock, COMMIT_LOCK)) { ret = error("could not write %s", buf.buf); rollback_lock_file(&lock); goto finish; } changed_files(&wt_modified, buf.buf, workdir); strbuf_setlen(&rdir, rdir_len); changed_files(&tmp_modified, buf.buf, rdir.buf); add_path(&rdir, rdir_len, name); indices_loaded = 1; } hashmap_entry_init(&dummy, strhash(name)); if (hashmap_get(&tmp_modified, &dummy, name)) { add_path(&wtdir, wtdir_len, name); if (hashmap_get(&wt_modified, &dummy, name)) { warning(_("both files modified: '%s' and '%s'."), wtdir.buf, rdir.buf); warning(_("working tree file has been left.")); warning(""); err = 1; } else if (unlink(wtdir.buf) || copy_file(wtdir.buf, rdir.buf, st.st_mode)) warning_errno(_("could not copy '%s' to '%s'"), rdir.buf, wtdir.buf); } } if (err) { warning(_("temporary files exist in '%s'."), tmpdir); warning(_("you may want to cleanup or recover these.")); exit(1); } else exit_cleanup(tmpdir, rc); finish: free(ce); strbuf_release(&ldir); strbuf_release(&rdir); strbuf_release(&wtdir); strbuf_release(&buf); return ret; }
int run_diff_files(struct rev_info *revs, unsigned int option) { int entries, i; int diff_unmerged_stage = revs->max_count; unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED) ? CE_MATCH_RACY_IS_DIRTY : 0); uint64_t start = getnanotime(); struct index_state *istate = revs->diffopt.repo->index; diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/"); if (diff_unmerged_stage < 0) diff_unmerged_stage = 2; entries = istate->cache_nr; for (i = 0; i < entries; i++) { unsigned int oldmode, newmode; struct cache_entry *ce = istate->cache[i]; int changed; unsigned dirty_submodule = 0; const struct object_id *old_oid, *new_oid; if (diff_can_quit_early(&revs->diffopt)) break; if (!ce_path_match(istate, ce, &revs->prune_data, NULL)) 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; struct stat st; path_len = ce_namelen(ce); dpath = xmalloc(combine_diff_path_size(5, path_len)); dpath->path = (char *) &(dpath->parent[5]); dpath->next = NULL; memcpy(dpath->path, ce->name, path_len); dpath->path[path_len] = '\0'; oidclr(&dpath->oid); memset(&(dpath->parent[0]), 0, sizeof(struct combine_diff_parent)*5); changed = check_removed(ce, &st); if (!changed) wt_mode = ce_mode_from_stat(ce, st.st_mode); else { if (changed < 0) { perror(ce->name); continue; } wt_mode = 0; } dpath->mode = wt_mode; while (i < entries) { struct cache_entry *nce = istate->cache[i]; int stage; if (strcmp(ce->name, nce->name)) break; /* Stage #2 (ours) is the first parent, * stage #3 (theirs) is the second. */ stage = ce_stage(nce); if (2 <= stage) { int mode = nce->ce_mode; num_compare_stages++; 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; } /* diff against the proper unmerged stage */ if (stage == diff_unmerged_stage) ce = nce; i++; } /* * Compensate for loop update */ i--; if (revs->combine_merges && num_compare_stages == 2) { show_combined_diff(dpath, 2, revs->dense_combined_merges, revs); free(dpath); continue; } FREE_AND_NULL(dpath); /* * Show the diff for the 'ce' if we found the one * from the desired stage. */ pair = diff_unmerge(&revs->diffopt, ce->name); if (wt_mode) pair->two->mode = wt_mode; if (ce_stage(ce) != diff_unmerged_stage) continue; } if (ce_uptodate(ce) || ce_skip_worktree(ce)) continue; /* If CE_VALID is set, don't look at workdir for file removal */ 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, !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, the_hash_algo->empty_tree, 0, 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); } if (!changed && !dirty_submodule) { ce_mark_uptodate(ce); mark_fsmonitor_valid(ce); if (!revs->diffopt.flags.find_copies_harder) continue; } oldmode = ce->ce_mode; old_oid = &ce->oid; new_oid = changed ? &null_oid : &ce->oid; diff_change(&revs->diffopt, oldmode, newmode, old_oid, new_oid, !is_null_oid(old_oid), !is_null_oid(new_oid), ce->name, 0, dirty_submodule); } diffcore_std(&revs->diffopt); diff_flush(&revs->diffopt); trace_performance_since(start, "diff-files"); return 0; }