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();
diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/");
}
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
+ trace_performance_since(start, "diff-files");
return 0;
}
}
static void show_new_file(struct rev_info *revs,
- const struct cache_entry *new,
+ const struct cache_entry *new_file,
int cached, int match_missing)
{
const struct object_id *oid;
* New file in the index: it might actually be different in
* the working tree.
*/
- if (get_stat_data(new, &oid, &mode, cached, match_missing,
+ if (get_stat_data(new_file, &oid, &mode, cached, match_missing,
&dirty_submodule, &revs->diffopt) < 0)
return;
- diff_index_show_file(revs, "+", new, oid, !is_null_oid(oid), mode, dirty_submodule);
+ diff_index_show_file(revs, "+", new_file, oid, !is_null_oid(oid), mode, dirty_submodule);
}
static int show_modified(struct rev_info *revs,
- const struct cache_entry *old,
- const struct cache_entry *new,
+ const struct cache_entry *old_entry,
+ const struct cache_entry *new_entry,
int report_missing,
int cached, int match_missing)
{
const struct object_id *oid;
unsigned dirty_submodule = 0;
- if (get_stat_data(new, &oid, &mode, cached, match_missing,
+ if (get_stat_data(new_entry, &oid, &mode, cached, match_missing,
&dirty_submodule, &revs->diffopt) < 0) {
if (report_missing)
- diff_index_show_file(revs, "-", old,
- &old->oid, 1, old->ce_mode,
+ diff_index_show_file(revs, "-", old_entry,
+ &old_entry->oid, 1, old_entry->ce_mode,
0);
return -1;
}
if (revs->combine_merges && !cached &&
- (oidcmp(oid, &old->oid) || oidcmp(&old->oid, &new->oid))) {
+ (oidcmp(oid, &old_entry->oid) || oidcmp(&old_entry->oid, &new_entry->oid))) {
struct combine_diff_path *p;
- int pathlen = ce_namelen(new);
+ int pathlen = ce_namelen(new_entry);
p = xmalloc(combine_diff_path_size(2, pathlen));
p->path = (char *) &p->parent[2];
p->next = NULL;
- memcpy(p->path, new->name, pathlen);
+ memcpy(p->path, new_entry->name, pathlen);
p->path[pathlen] = 0;
p->mode = mode;
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;
- oidcpy(&p->parent[0].oid, &new->oid);
+ p->parent[0].mode = new_entry->ce_mode;
+ oidcpy(&p->parent[0].oid, &new_entry->oid);
p->parent[1].status = DIFF_STATUS_MODIFIED;
- p->parent[1].mode = old->ce_mode;
- oidcpy(&p->parent[1].oid, &old->oid);
+ p->parent[1].mode = old_entry->ce_mode;
+ oidcpy(&p->parent[1].oid, &old_entry->oid);
show_combined_diff(p, 2, revs->dense_combined_merges, revs);
free(p);
return 0;
}
- oldmode = old->ce_mode;
- if (mode == oldmode && !oidcmp(oid, &old->oid) && !dirty_submodule &&
+ oldmode = old_entry->ce_mode;
+ if (mode == oldmode && !oidcmp(oid, &old_entry->oid) && !dirty_submodule &&
!revs->diffopt.flags.find_copies_harder)
return 0;
diff_change(&revs->diffopt, oldmode, mode,
- &old->oid, oid, 1, !is_null_oid(oid),
- old->name, 0, dirty_submodule);
+ &old_entry->oid, oid, 1, !is_null_oid(oid),
+ old_entry->name, 0, dirty_submodule);
return 0;
}
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 &&
+ /*
+ * i-t-a entries do not actually exist in the index (if we're
+ * looking at its content)
+ */
+ if (o->index_only &&
+ revs->diffopt.ita_invisible_in_index &&
idx && ce_intent_to_add(idx)) {
idx = NULL;
if (!tree)
int run_diff_index(struct rev_info *revs, int cached)
{
struct object_array_entry *ent;
+ uint64_t start = getnanotime();
+ if (revs->pending.nr != 1)
+ BUG("run_diff_index must be passed exactly one tree");
+
ent = revs->pending.objects;
if (diff_cache(revs, &ent->item->oid, ent->name, cached))
exit(128);
diffcore_fix_diff_index(&revs->diffopt);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
+ trace_performance_since(start, "diff-index");
return 0;
}
s->ignored.strdup_strings = 1;
s->show_branch = -1; /* unspecified */
s->show_stash = 0;
+ s->ahead_behind_flags = AHEAD_BEHIND_UNSPECIFIED;
s->display_comment_prefix = 0;
+ s->detect_rename = -1;
+ s->rename_score = -1;
+ s->rename_limit = -1;
}
static void wt_longstatus_print_unmerged_header(struct wt_status *s)
case 7:
return _("both modified:");
default:
- die("BUG: unhandled unmerged status %x", stagemask);
+ BUG("unhandled unmerged status %x", stagemask);
}
}
status = d->worktree_status;
break;
default:
- die("BUG: unhandled change_type %d in wt_longstatus_print_change_data",
+ BUG("unhandled change_type %d in wt_longstatus_print_change_data",
change_type);
}
status_printf(s, color(WT_STATUS_HEADER, s), "\t");
what = wt_status_diff_status_string(status);
if (!what)
- die("BUG: unhandled diff status %c", status);
+ BUG("unhandled diff status %c", status);
len = label_width - utf8_strwidth(what);
assert(len >= 0);
if (one_name != two_name)
case DIFF_STATUS_COPIED:
case DIFF_STATUS_RENAMED:
if (d->rename_status)
- die("BUG: multiple renames on the same target? how?");
+ BUG("multiple renames on the same target? how?");
d->rename_source = xstrdup(p->one->path);
d->rename_score = p->score * 100 / MAX_SCORE;
d->rename_status = p->status;
break;
default:
- die("BUG: unhandled diff-files status '%c'", p->status);
+ BUG("unhandled diff-files status '%c'", p->status);
break;
}
case DIFF_STATUS_COPIED:
case DIFF_STATUS_RENAMED:
if (d->rename_status)
- die("BUG: multiple renames on the same target? how?");
+ BUG("multiple renames on the same target? how?");
d->rename_source = xstrdup(p->one->path);
d->rename_score = p->score * 100 / MAX_SCORE;
d->rename_status = p->status;
break;
default:
- die("BUG: unhandled diff-index status '%c'", p->status);
+ BUG("unhandled diff-index status '%c'", p->status);
break;
}
}
}
rev.diffopt.format_callback = wt_status_collect_changed_cb;
rev.diffopt.format_callback_data = s;
+ rev.diffopt.detect_rename = s->detect_rename >= 0 ? s->detect_rename : rev.diffopt.detect_rename;
+ rev.diffopt.rename_limit = s->rename_limit >= 0 ? s->rename_limit : rev.diffopt.rename_limit;
+ rev.diffopt.rename_score = s->rename_score >= 0 ? s->rename_score : rev.diffopt.rename_score;
copy_pathspec(&rev.prune_data, &s->pathspec);
run_diff_files(&rev, 0);
}
init_revisions(&rev, NULL);
memset(&opt, 0, sizeof(opt));
- opt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference;
+ opt.def = s->is_initial ? empty_tree_oid_hex() : s->reference;
setup_revisions(0, NULL, &rev, &opt);
rev.diffopt.flags.override_submodule_config = 1;
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = wt_status_collect_updated_cb;
rev.diffopt.format_callback_data = s;
- rev.diffopt.detect_rename = DIFF_DETECT_RENAME;
- rev.diffopt.rename_limit = 200;
- rev.diffopt.break_opt = 0;
+ rev.diffopt.detect_rename = s->detect_rename >= 0 ? s->detect_rename : rev.diffopt.detect_rename;
+ rev.diffopt.rename_limit = s->rename_limit >= 0 ? s->rename_limit : rev.diffopt.rename_limit;
+ rev.diffopt.rename_score = s->rename_score >= 0 ? s->rename_score : rev.diffopt.rename_score;
copy_pathspec(&rev.prune_data, &s->pathspec);
run_diff_index(&rev, 1);
}
rev.diffopt.ita_invisible_in_index = 1;
memset(&opt, 0, sizeof(opt));
- opt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference;
+ opt.def = s->is_initial ? empty_tree_oid_hex() : s->reference;
setup_revisions(0, NULL, &rev, &opt);
rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
- rev.diffopt.detect_rename = DIFF_DETECT_RENAME;
+ rev.diffopt.detect_rename = s->detect_rename >= 0 ? s->detect_rename : rev.diffopt.detect_rename;
+ rev.diffopt.rename_limit = s->rename_limit >= 0 ? s->rename_limit : rev.diffopt.rename_limit;
+ rev.diffopt.rename_score = s->rename_score >= 0 ? s->rename_score : rev.diffopt.rename_score;
rev.diffopt.file = s->fp;
rev.diffopt.close_file = 0;
/*
if (!skip_prefix(s->branch, "refs/heads/", &branch_name))
return;
branch = branch_get(branch_name);
- if (!format_tracking_info(branch, &sb))
+ if (!format_tracking_info(branch, &sb, s->ahead_behind_flags))
return;
i = 0;
strbuf_trim(split[1]);
if (!get_oid(split[1]->buf, &oid)) {
strbuf_reset(split[1]);
- strbuf_add_unique_abbrev(split[1], oid.hash,
+ strbuf_add_unique_abbrev(split[1], &oid,
DEFAULT_ABBREV);
strbuf_addch(split[1], ' ');
strbuf_reset(line);
status_printf_ln(s, color,
_(" (use \"git rebase --abort\" to check out the original branch)"));
}
- } else if (state->rebase_in_progress || !stat(git_path_merge_msg(), &st)) {
+ } else if (state->rebase_in_progress || !stat(git_path_merge_msg(the_repository), &st)) {
print_rebase_state(s, state, color);
if (s->hints)
status_printf_ln(s, color,
const char *color)
{
status_printf_ln(s, color, _("You are currently cherry-picking commit %s."),
- find_unique_abbrev(state->cherry_pick_head_sha1, DEFAULT_ABBREV));
+ find_unique_abbrev(&state->cherry_pick_head_oid, DEFAULT_ABBREV));
if (s->hints) {
if (has_unmerged(s))
status_printf_ln(s, color,
const char *color)
{
status_printf_ln(s, color, _("You are currently reverting commit %s."),
- find_unique_abbrev(state->revert_head_sha1, DEFAULT_ABBREV));
+ find_unique_abbrev(&state->revert_head_oid, DEFAULT_ABBREV));
if (s->hints) {
if (has_unmerged(s))
status_printf_ln(s, color,
;
else if (!get_oid_hex(sb.buf, &oid)) {
strbuf_reset(&sb);
- strbuf_add_unique_abbrev(&sb, oid.hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(&sb, &oid, DEFAULT_ABBREV);
} else if (!strcmp(sb.buf, "detached HEAD")) /* rebase */
goto got_nothing;
else /* bisect */
if (!strcmp(cb->buf.buf, "HEAD")) {
/* HEAD is relative. Resolve it to the right reflog entry. */
strbuf_reset(&cb->buf);
- strbuf_add_unique_abbrev(&cb->buf, noid->hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(&cb->buf, noid, DEFAULT_ABBREV);
}
return 1;
}
state->detached_from = xstrdup(from);
} else
state->detached_from =
- xstrdup(find_unique_abbrev(cb.noid.hash, DEFAULT_ABBREV));
- hashcpy(state->detached_sha1, cb.noid.hash);
+ xstrdup(find_unique_abbrev(&cb.noid, DEFAULT_ABBREV));
+ oidcpy(&state->detached_oid, &cb.noid);
state->detached_at = !get_oid("HEAD", &oid) &&
- !hashcmp(oid.hash, state->detached_sha1);
+ !oidcmp(&oid, &state->detached_oid);
free(ref);
strbuf_release(&cb.buf);
struct stat st;
struct object_id oid;
- if (!stat(git_path_merge_head(), &st)) {
+ if (!stat(git_path_merge_head(the_repository), &st)) {
state->merge_in_progress = 1;
} else if (wt_status_check_rebase(NULL, state)) {
; /* all set */
- } else if (!stat(git_path_cherry_pick_head(), &st) &&
+ } else if (!stat(git_path_cherry_pick_head(the_repository), &st) &&
!get_oid("CHERRY_PICK_HEAD", &oid)) {
state->cherry_pick_in_progress = 1;
- hashcpy(state->cherry_pick_head_sha1, oid.hash);
+ oidcpy(&state->cherry_pick_head_oid, &oid);
}
wt_status_check_bisect(NULL, state);
- if (!stat(git_path_revert_head(), &st) &&
+ if (!stat(git_path_revert_head(the_repository), &st) &&
!get_oid("REVERT_HEAD", &oid)) {
state->revert_in_progress = 1;
- hashcpy(state->revert_head_sha1, oid.hash);
+ oidcpy(&state->revert_head_oid, &oid);
}
if (get_detached_from)
const char *base;
char *short_base;
const char *branch_name;
- int num_ours, num_theirs;
+ int num_ours, num_theirs, sti;
int upstream_is_gone = 0;
color_fprintf(s->fp, color(WT_STATUS_HEADER, s), "## ");
color_fprintf(s->fp, branch_color_local, "%s", branch_name);
- if (stat_tracking_info(branch, &num_ours, &num_theirs, &base) < 0) {
+ sti = stat_tracking_info(branch, &num_ours, &num_theirs, &base,
+ s->ahead_behind_flags);
+ if (sti < 0) {
if (!base)
goto conclude;
color_fprintf(s->fp, branch_color_remote, "%s", short_base);
free(short_base);
- if (!upstream_is_gone && !num_ours && !num_theirs)
+ if (!upstream_is_gone && !sti)
goto conclude;
color_fprintf(s->fp, header_color, " [");
if (upstream_is_gone) {
color_fprintf(s->fp, header_color, LABEL(N_("gone")));
+ } else if (s->ahead_behind_flags == AHEAD_BEHIND_QUICK) {
+ color_fprintf(s->fp, header_color, LABEL(N_("different")));
} else if (!num_ours) {
color_fprintf(s->fp, header_color, LABEL(N_("behind ")));
color_fprintf(s->fp, branch_color_remote, "%d", num_theirs);
*
* <upstream> ::= the upstream branch name, when set.
*
- * <ahead> ::= integer ahead value, when upstream set
- * and the commit is present (not gone).
- *
- * <behind> ::= integer behind value, when upstream set
- * and commit is present.
+ * <ahead> ::= integer ahead value or '?'.
*
+ * <behind> ::= integer behind value or '?'.
*
* The end-of-line is defined by the -z flag.
*
* <eol> ::= NUL when -z,
* LF when NOT -z.
*
+ * When an upstream is set and present, the 'branch.ab' line will
+ * be printed with the ahead/behind counts for the branch and the
+ * upstream. When AHEAD_BEHIND_QUICK is requested and the branches
+ * are different, '?' will be substituted for the actual count.
*/
static void wt_porcelain_v2_print_tracking(struct wt_status *s)
{
/* Lookup stats on the upstream tracking branch, if set. */
branch = branch_get(branch_name);
base = NULL;
- ab_info = (stat_tracking_info(branch, &nr_ahead, &nr_behind, &base) == 0);
+ ab_info = stat_tracking_info(branch, &nr_ahead, &nr_behind,
+ &base, s->ahead_behind_flags);
if (base) {
base = shorten_unambiguous_ref(base, 0);
fprintf(s->fp, "# branch.upstream %s%c", base, eol);
free((char *)base);
- if (ab_info)
- fprintf(s->fp, "# branch.ab +%d -%d%c", nr_ahead, nr_behind, eol);
+ if (ab_info > 0) {
+ /* different */
+ if (nr_ahead || nr_behind)
+ fprintf(s->fp, "# branch.ab +%d -%d%c",
+ nr_ahead, nr_behind, eol);
+ else
+ fprintf(s->fp, "# branch.ab +? -?%c",
+ eol);
+ } else if (!ab_info) {
+ /* same */
+ fprintf(s->fp, "# branch.ab +0 -0%c", eol);
+ }
}
}
case 6: key = "AA"; break; /* both added */
case 7: key = "UU"; break; /* both modified */
default:
- die("BUG: unhandled unmerged status %x", d->stagemask);
+ BUG("unhandled unmerged status %x", d->stagemask);
}
/*
sum |= (1 << (stage - 1));
}
if (sum != d->stagemask)
- die("BUG: observed stagemask 0x%x != expected stagemask 0x%x", sum, d->stagemask);
+ BUG("observed stagemask 0x%x != expected stagemask 0x%x", sum, d->stagemask);
if (s->null_termination)
path_index = it->string;
wt_porcelain_v2_print(s);
break;
case STATUS_FORMAT_UNSPECIFIED:
- die("BUG: finalize_deferred_config() should have been called");
+ BUG("finalize_deferred_config() should have been called");
break;
case STATUS_FORMAT_NONE:
case STATUS_FORMAT_LONG:
if (ignore_submodules)
rev_info.diffopt.flags.ignore_submodules = 1;
rev_info.diffopt.flags.quick = 1;
+
add_head_to_pending(&rev_info);
+ if (!rev_info.pending.nr) {
+ /*
+ * We have no head (or it's corrupt); use the empty tree,
+ * which will complain if the index is non-empty.
+ */
+ struct tree *tree = lookup_tree(the_hash_algo->empty_tree);
+ add_pending_object(&rev_info, &tree->object, "");
+ }
+
diff_setup_done(&rev_info.diffopt);
result = run_diff_index(&rev_info, 1);
return diff_result_code(&rev_info.diffopt, result);