Merge branch 'ss/wt-status-committable'

Code clean-up in the internal machinery used by "git status" and
"git commit --dry-run".

* ss/wt-status-committable:
  roll wt_status_state into wt_status and populate in the collect phase
  wt-status.c: set the committable flag in the collect phase
  t7501: add test of "commit --dry-run --short"
  wt-status: rename commitable to committable
  wt-status.c: move has_unmerged earlier in the file
This commit is contained in:
Junio C Hamano 2018-10-19 13:34:02 +09:00
Родитель 11877b9ebe 73ba5d78b4
Коммит 929e85ade8
4 изменённых файлов: 123 добавлений и 119 удалений

Просмотреть файл

@ -508,8 +508,9 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
wt_status_collect(s);
wt_status_print(s);
wt_status_collect_free_buffers(s);
return s->commitable;
return s->committable;
}
static int is_a_merge(const struct commit *current_head)
@ -655,7 +656,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
{
struct stat statbuf;
struct strbuf committer_ident = STRBUF_INIT;
int commitable;
int committable;
struct strbuf sb = STRBUF_INIT;
const char *hook_arg1 = NULL;
const char *hook_arg2 = NULL;
@ -872,7 +873,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
saved_color_setting = s->use_color;
s->use_color = 0;
commitable = run_status(s->fp, index_file, prefix, 1, s);
committable = run_status(s->fp, index_file, prefix, 1, s);
s->use_color = saved_color_setting;
string_list_clear(&s->change, 1);
} else {
@ -891,7 +892,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
for (i = 0; i < active_nr; i++)
if (ce_intent_to_add(active_cache[i]))
ita_nr++;
commitable = active_nr - ita_nr > 0;
committable = active_nr - ita_nr > 0;
} else {
/*
* Unless the user did explicitly request a submodule
@ -907,7 +908,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
if (ignore_submodule_arg &&
!strcmp(ignore_submodule_arg, "all"))
flags.ignore_submodules = 1;
commitable = index_differs_from(parent, &flags, 1);
committable = index_differs_from(parent, &flags, 1);
}
}
strbuf_release(&committer_ident);
@ -919,7 +920,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
* explicit --allow-empty. In the cherry-pick case, it may be
* empty due to conflict resolution, which the user should okay.
*/
if (!commitable && whence != FROM_MERGE && !allow_empty &&
if (!committable && whence != FROM_MERGE && !allow_empty &&
!(amend && is_a_merge(current_head))) {
s->display_comment_prefix = old_display_comment_prefix;
run_status(stdout, index_file, prefix, 0, s);
@ -1189,14 +1190,14 @@ static int parse_and_validate_options(int argc, const char *argv[],
static int dry_run_commit(int argc, const char **argv, const char *prefix,
const struct commit *current_head, struct wt_status *s)
{
int commitable;
int committable;
const char *index_file;
index_file = prepare_index(argc, argv, prefix, current_head, 1);
commitable = run_status(stdout, index_file, prefix, 0, s);
committable = run_status(stdout, index_file, prefix, 0, s);
rollback_index_files();
return commitable ? 0 : 1;
return committable ? 0 : 1;
}
define_list_config_array_extra(color_status_slots, {"added"});
@ -1391,6 +1392,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
s.prefix = prefix;
wt_status_print(&s);
wt_status_collect_free_buffers(&s);
return 0;
}

Просмотреть файл

@ -99,12 +99,12 @@ test_expect_success '--dry-run with stuff to commit returns ok' '
git commit -m next -a --dry-run
'
test_expect_failure '--short with stuff to commit returns ok' '
test_expect_success '--short with stuff to commit returns ok' '
echo bongo bongo bongo >>file &&
git commit -m next -a --short
'
test_expect_failure '--porcelain with stuff to commit returns ok' '
test_expect_success '--porcelain with stuff to commit returns ok' '
echo bongo bongo bongo >>file &&
git commit -m next -a --porcelain
'
@ -698,4 +698,10 @@ test_expect_success '--dry-run with conflicts fixed from a merge' '
git commit -m "conflicts fixed from merge."
'
test_expect_success '--dry-run --short' '
>test-file &&
git add test-file &&
git commit --dry-run --short
'
test_done

Просмотреть файл

@ -540,10 +540,12 @@ static void wt_status_collect_updated_cb(struct diff_queue_struct *q,
/* Leave {mode,oid}_head zero for an add. */
d->mode_index = p->two->mode;
oidcpy(&d->oid_index, &p->two->oid);
s->committable = 1;
break;
case DIFF_STATUS_DELETED:
d->mode_head = p->one->mode;
oidcpy(&d->oid_head, &p->one->oid);
s->committable = 1;
/* Leave {mode,oid}_index zero for a delete. */
break;
@ -561,6 +563,7 @@ static void wt_status_collect_updated_cb(struct diff_queue_struct *q,
d->mode_index = p->two->mode;
oidcpy(&d->oid_head, &p->one->oid);
oidcpy(&d->oid_index, &p->two->oid);
s->committable = 1;
break;
case DIFF_STATUS_UNMERGED:
d->stagemask = unmerged_mask(p->two->path);
@ -665,11 +668,13 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
* code will output the stage values directly and not use the
* values in these fields.
*/
s->committable = 1;
} else {
d->index_status = DIFF_STATUS_ADDED;
/* Leave {mode,oid}_head zero for adds. */
d->mode_index = ce->ce_mode;
oidcpy(&d->oid_index, &ce->oid);
s->committable = 1;
}
}
}
@ -724,15 +729,38 @@ static void wt_status_collect_untracked(struct wt_status *s)
s->untracked_in_ms = (getnanotime() - t_begin) / 1000000;
}
static int has_unmerged(struct wt_status *s)
{
int i;
for (i = 0; i < s->change.nr; i++) {
struct wt_status_change_data *d;
d = s->change.items[i].util;
if (d->stagemask)
return 1;
}
return 0;
}
void wt_status_collect(struct wt_status *s)
{
wt_status_collect_changes_worktree(s);
if (s->is_initial)
wt_status_collect_changes_initial(s);
else
wt_status_collect_changes_index(s);
wt_status_collect_untracked(s);
wt_status_get_state(&s->state, s->branch && !strcmp(s->branch, "HEAD"));
if (s->state.merge_in_progress && !has_unmerged(s))
s->committable = 1;
}
void wt_status_collect_free_buffers(struct wt_status *s)
{
free(s->state.branch);
free(s->state.onto);
free(s->state.detached_from);
}
static void wt_longstatus_print_unmerged(struct wt_status *s)
@ -773,7 +801,6 @@ static void wt_longstatus_print_updated(struct wt_status *s)
continue;
if (!shown_header) {
wt_longstatus_print_cached_header(s);
s->commitable = 1;
shown_header = 1;
}
wt_longstatus_print_change_data(s, WT_STATUS_UPDATED, it);
@ -1008,7 +1035,7 @@ static void wt_longstatus_print_verbose(struct wt_status *s)
rev.diffopt.use_color = 0;
wt_status_add_cut_line(s->fp);
}
if (s->verbose > 1 && s->commitable) {
if (s->verbose > 1 && s->committable) {
/* print_updated() printed a header, so do we */
if (s->fp != stdout)
wt_longstatus_print_trailer(s);
@ -1063,22 +1090,8 @@ static void wt_longstatus_print_tracking(struct wt_status *s)
strbuf_release(&sb);
}
static int has_unmerged(struct wt_status *s)
{
int i;
for (i = 0; i < s->change.nr; i++) {
struct wt_status_change_data *d;
d = s->change.items[i].util;
if (d->stagemask)
return 1;
}
return 0;
}
static void show_merge_in_progress(struct wt_status *s,
struct wt_status_state *state,
const char *color)
const char *color)
{
if (has_unmerged(s)) {
status_printf_ln(s, color, _("You have unmerged paths."));
@ -1089,7 +1102,6 @@ static void show_merge_in_progress(struct wt_status *s,
_(" (use \"git merge --abort\" to abort the merge)"));
}
} else {
s-> commitable = 1;
status_printf_ln(s, color,
_("All conflicts fixed but you are still merging."));
if (s->hints)
@ -1100,16 +1112,15 @@ static void show_merge_in_progress(struct wt_status *s,
}
static void show_am_in_progress(struct wt_status *s,
struct wt_status_state *state,
const char *color)
{
status_printf_ln(s, color,
_("You are in the middle of an am session."));
if (state->am_empty_patch)
if (s->state.am_empty_patch)
status_printf_ln(s, color,
_("The current patch is empty."));
if (s->hints) {
if (!state->am_empty_patch)
if (!s->state.am_empty_patch)
status_printf_ln(s, color,
_(" (fix conflicts and then run \"git am --continue\")"));
status_printf_ln(s, color,
@ -1233,10 +1244,9 @@ static int read_rebase_todolist(const char *fname, struct string_list *lines)
}
static void show_rebase_information(struct wt_status *s,
struct wt_status_state *state,
const char *color)
const char *color)
{
if (state->rebase_interactive_in_progress) {
if (s->state.rebase_interactive_in_progress) {
int i;
int nr_lines_to_show = 2;
@ -1287,28 +1297,26 @@ static void show_rebase_information(struct wt_status *s,
}
static void print_rebase_state(struct wt_status *s,
struct wt_status_state *state,
const char *color)
const char *color)
{
if (state->branch)
if (s->state.branch)
status_printf_ln(s, color,
_("You are currently rebasing branch '%s' on '%s'."),
state->branch,
state->onto);
s->state.branch,
s->state.onto);
else
status_printf_ln(s, color,
_("You are currently rebasing."));
}
static void show_rebase_in_progress(struct wt_status *s,
struct wt_status_state *state,
const char *color)
const char *color)
{
struct stat st;
show_rebase_information(s, state, color);
show_rebase_information(s, color);
if (has_unmerged(s)) {
print_rebase_state(s, state, color);
print_rebase_state(s, color);
if (s->hints) {
status_printf_ln(s, color,
_(" (fix conflicts and then run \"git rebase --continue\")"));
@ -1317,17 +1325,18 @@ static void show_rebase_in_progress(struct wt_status *s,
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(the_repository), &st)) {
print_rebase_state(s, state, color);
} else if (s->state.rebase_in_progress ||
!stat(git_path_merge_msg(the_repository), &st)) {
print_rebase_state(s, color);
if (s->hints)
status_printf_ln(s, color,
_(" (all conflicts fixed: run \"git rebase --continue\")"));
} else if (split_commit_in_progress(s)) {
if (state->branch)
if (s->state.branch)
status_printf_ln(s, color,
_("You are currently splitting a commit while rebasing branch '%s' on '%s'."),
state->branch,
state->onto);
s->state.branch,
s->state.onto);
else
status_printf_ln(s, color,
_("You are currently splitting a commit during a rebase."));
@ -1335,11 +1344,11 @@ static void show_rebase_in_progress(struct wt_status *s,
status_printf_ln(s, color,
_(" (Once your working directory is clean, run \"git rebase --continue\")"));
} else {
if (state->branch)
if (s->state.branch)
status_printf_ln(s, color,
_("You are currently editing a commit while rebasing branch '%s' on '%s'."),
state->branch,
state->onto);
s->state.branch,
s->state.onto);
else
status_printf_ln(s, color,
_("You are currently editing a commit during a rebase."));
@ -1354,11 +1363,10 @@ static void show_rebase_in_progress(struct wt_status *s,
}
static void show_cherry_pick_in_progress(struct wt_status *s,
struct wt_status_state *state,
const char *color)
const char *color)
{
status_printf_ln(s, color, _("You are currently cherry-picking commit %s."),
find_unique_abbrev(&state->cherry_pick_head_oid, DEFAULT_ABBREV));
find_unique_abbrev(&s->state.cherry_pick_head_oid, DEFAULT_ABBREV));
if (s->hints) {
if (has_unmerged(s))
status_printf_ln(s, color,
@ -1373,11 +1381,10 @@ static void show_cherry_pick_in_progress(struct wt_status *s,
}
static void show_revert_in_progress(struct wt_status *s,
struct wt_status_state *state,
const char *color)
const char *color)
{
status_printf_ln(s, color, _("You are currently reverting commit %s."),
find_unique_abbrev(&state->revert_head_oid, DEFAULT_ABBREV));
find_unique_abbrev(&s->state.revert_head_oid, DEFAULT_ABBREV));
if (s->hints) {
if (has_unmerged(s))
status_printf_ln(s, color,
@ -1392,13 +1399,12 @@ static void show_revert_in_progress(struct wt_status *s,
}
static void show_bisect_in_progress(struct wt_status *s,
struct wt_status_state *state,
const char *color)
const char *color)
{
if (state->branch)
if (s->state.branch)
status_printf_ln(s, color,
_("You are currently bisecting, started from branch '%s'."),
state->branch);
s->state.branch);
else
status_printf_ln(s, color,
_("You are currently bisecting."));
@ -1572,48 +1578,45 @@ void wt_status_get_state(struct wt_status_state *state,
wt_status_get_detached_from(state);
}
static void wt_longstatus_print_state(struct wt_status *s,
struct wt_status_state *state)
static void wt_longstatus_print_state(struct wt_status *s)
{
const char *state_color = color(WT_STATUS_HEADER, s);
struct wt_status_state *state = &s->state;
if (state->merge_in_progress)
show_merge_in_progress(s, state, state_color);
show_merge_in_progress(s, state_color);
else if (state->am_in_progress)
show_am_in_progress(s, state, state_color);
show_am_in_progress(s, state_color);
else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
show_rebase_in_progress(s, state, state_color);
show_rebase_in_progress(s, state_color);
else if (state->cherry_pick_in_progress)
show_cherry_pick_in_progress(s, state, state_color);
show_cherry_pick_in_progress(s, state_color);
else if (state->revert_in_progress)
show_revert_in_progress(s, state, state_color);
show_revert_in_progress(s, state_color);
if (state->bisect_in_progress)
show_bisect_in_progress(s, state, state_color);
show_bisect_in_progress(s, state_color);
}
static void wt_longstatus_print(struct wt_status *s)
{
const char *branch_color = color(WT_STATUS_ONBRANCH, s);
const char *branch_status_color = color(WT_STATUS_HEADER, s);
struct wt_status_state state;
memset(&state, 0, sizeof(state));
wt_status_get_state(&state,
s->branch && !strcmp(s->branch, "HEAD"));
if (s->branch) {
const char *on_what = _("On branch ");
const char *branch_name = s->branch;
if (!strcmp(branch_name, "HEAD")) {
branch_status_color = color(WT_STATUS_NOBRANCH, s);
if (state.rebase_in_progress || state.rebase_interactive_in_progress) {
if (state.rebase_interactive_in_progress)
if (s->state.rebase_in_progress ||
s->state.rebase_interactive_in_progress) {
if (s->state.rebase_interactive_in_progress)
on_what = _("interactive rebase in progress; onto ");
else
on_what = _("rebase in progress; onto ");
branch_name = state.onto;
} else if (state.detached_from) {
branch_name = state.detached_from;
if (state.detached_at)
branch_name = s->state.onto;
} else if (s->state.detached_from) {
branch_name = s->state.detached_from;
if (s->state.detached_at)
on_what = _("HEAD detached at ");
else
on_what = _("HEAD detached from ");
@ -1630,10 +1633,7 @@ static void wt_longstatus_print(struct wt_status *s)
wt_longstatus_print_tracking(s);
}
wt_longstatus_print_state(s, &state);
free(state.branch);
free(state.onto);
free(state.detached_from);
wt_longstatus_print_state(s);
if (s->is_initial) {
status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
@ -1665,14 +1665,14 @@ static void wt_longstatus_print(struct wt_status *s)
"new files yourself (see 'git help status')."),
s->untracked_in_ms / 1000.0);
}
} else if (s->commitable)
} else if (s->committable)
status_printf_ln(s, GIT_COLOR_NORMAL, _("Untracked files not listed%s"),
s->hints
? _(" (use -u option to show untracked files)") : "");
if (s->verbose)
wt_longstatus_print_verbose(s);
if (!s->commitable) {
if (!s->committable) {
if (s->amend)
status_printf_ln(s, GIT_COLOR_NORMAL, _("No changes"));
else if (s->nowarn)
@ -1937,13 +1937,9 @@ static void wt_porcelain_v2_print_tracking(struct wt_status *s)
struct branch *branch;
const char *base;
const char *branch_name;
struct wt_status_state state;
int ab_info, nr_ahead, nr_behind;
char eol = s->null_termination ? '\0' : '\n';
memset(&state, 0, sizeof(state));
wt_status_get_state(&state, s->branch && !strcmp(s->branch, "HEAD"));
fprintf(s->fp, "# branch.oid %s%c",
(s->is_initial ? "(initial)" : sha1_to_hex(s->sha1_commit)),
eol);
@ -1954,10 +1950,11 @@ static void wt_porcelain_v2_print_tracking(struct wt_status *s)
if (!strcmp(s->branch, "HEAD")) {
fprintf(s->fp, "# branch.head %s%c", "(detached)", eol);
if (state.rebase_in_progress || state.rebase_interactive_in_progress)
branch_name = state.onto;
else if (state.detached_from)
branch_name = state.detached_from;
if (s->state.rebase_in_progress ||
s->state.rebase_interactive_in_progress)
branch_name = s->state.onto;
else if (s->state.detached_from)
branch_name = s->state.detached_from;
else
branch_name = "";
} else {
@ -1991,10 +1988,6 @@ static void wt_porcelain_v2_print_tracking(struct wt_status *s)
}
}
}
free(state.branch);
free(state.onto);
free(state.detached_from);
}
/*

Просмотреть файл

@ -64,6 +64,24 @@ enum wt_status_format {
STATUS_FORMAT_UNSPECIFIED
};
struct wt_status_state {
int merge_in_progress;
int am_in_progress;
int am_empty_patch;
int rebase_in_progress;
int rebase_interactive_in_progress;
int cherry_pick_in_progress;
int bisect_in_progress;
int revert_in_progress;
int detached_at;
char *branch;
char *onto;
char *detached_from;
struct object_id detached_oid;
struct object_id revert_head_oid;
struct object_id cherry_pick_head_oid;
};
struct wt_status {
int is_initial;
char *branch;
@ -93,10 +111,11 @@ struct wt_status {
int rename_score;
int rename_limit;
enum wt_status_format status_format;
struct wt_status_state state;
unsigned char sha1_commit[GIT_MAX_RAWSZ]; /* when not Initial */
/* These are computed during processing of the individual sections */
int commitable;
int committable;
int workdir_dirty;
const char *index_file;
FILE *fp;
@ -107,29 +126,12 @@ struct wt_status {
uint32_t untracked_in_ms;
};
struct wt_status_state {
int merge_in_progress;
int am_in_progress;
int am_empty_patch;
int rebase_in_progress;
int rebase_interactive_in_progress;
int cherry_pick_in_progress;
int bisect_in_progress;
int revert_in_progress;
int detached_at;
char *branch;
char *onto;
char *detached_from;
struct object_id detached_oid;
struct object_id revert_head_oid;
struct object_id cherry_pick_head_oid;
};
size_t wt_status_locate_end(const char *s, size_t len);
void wt_status_add_cut_line(FILE *fp);
void wt_status_prepare(struct wt_status *s);
void wt_status_print(struct wt_status *s);
void wt_status_collect(struct wt_status *s);
void wt_status_collect_free_buffers(struct wt_status *s);
void wt_status_get_state(struct wt_status_state *state, int get_detached_from);
int wt_status_check_rebase(const struct worktree *wt,
struct wt_status_state *state);