commit: move print_commit_summary() to libgit
Move print_commit_summary() from builtin/commit.c to sequencer.c so it can be shared with other commands. The function is modified by changing the last argument to a flag so callers can specify whether they want to show the author date in addition to specifying if this is an initial commit. If the sequencer dies in print_commit_summary() (which can only happen when cherry-picking or reverting) then neither the todo list nor the abort safety file are updated to reflect the commit that was just made. print_commit_summary() can die if: - The commit that was just created cannot be found or parsed. - HEAD cannot be resolved either because some other process is updating it (which is bad news in the middle of a cherry-pick) or because it is corrupt. - log_tree_commit() cannot read some objects. In all those cases dying will leave the sequencer in a sane state for aborting; 'git cherry-pick --abort' will rewind HEAD to the last successful commit before there was a problem with HEAD or the object database. If the user somehow fixes the problem and runs 'git cherry-pick --continue' then the sequencer will try and pick the same commit again which may or may not be what the user wants depending on what caused print_commit_summary() to die. If print_commit_summary() returned an error instead then update_abort_safety_file() would try to resolve HEAD which may or may not be successful. If it is successful then running 'git rebase --abort' would not rewind HEAD to the last successful commit which is not what we want. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
a87a6f3c98
commit
e47c6cafcb
128
builtin/commit.c
128
builtin/commit.c
@ -43,31 +43,6 @@ static const char * const builtin_status_usage[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char implicit_ident_advice_noconfig[] =
|
||||
N_("Your name and email address were configured automatically based\n"
|
||||
"on your username and hostname. Please check that they are accurate.\n"
|
||||
"You can suppress this message by setting them explicitly. Run the\n"
|
||||
"following command and follow the instructions in your editor to edit\n"
|
||||
"your configuration file:\n"
|
||||
"\n"
|
||||
" git config --global --edit\n"
|
||||
"\n"
|
||||
"After doing this, you may fix the identity used for this commit with:\n"
|
||||
"\n"
|
||||
" git commit --amend --reset-author\n");
|
||||
|
||||
static const char implicit_ident_advice_config[] =
|
||||
N_("Your name and email address were configured automatically based\n"
|
||||
"on your username and hostname. Please check that they are accurate.\n"
|
||||
"You can suppress this message by setting them explicitly:\n"
|
||||
"\n"
|
||||
" git config --global user.name \"Your Name\"\n"
|
||||
" git config --global user.email you@example.com\n"
|
||||
"\n"
|
||||
"After doing this, you may fix the identity used for this commit with:\n"
|
||||
"\n"
|
||||
" git commit --amend --reset-author\n");
|
||||
|
||||
static const char empty_amend_advice[] =
|
||||
N_("You asked to amend the most recent commit, but doing so would make\n"
|
||||
"it empty. You can repeat your command with --allow-empty, or you can\n"
|
||||
@ -1355,98 +1330,6 @@ int cmd_status(int argc, const char **argv, const char *prefix)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *implicit_ident_advice(void)
|
||||
{
|
||||
char *user_config = expand_user_path("~/.gitconfig", 0);
|
||||
char *xdg_config = xdg_config_home("config");
|
||||
int config_exists = file_exists(user_config) || file_exists(xdg_config);
|
||||
|
||||
free(user_config);
|
||||
free(xdg_config);
|
||||
|
||||
if (config_exists)
|
||||
return _(implicit_ident_advice_config);
|
||||
else
|
||||
return _(implicit_ident_advice_noconfig);
|
||||
|
||||
}
|
||||
|
||||
static void print_summary(const char *prefix, const struct object_id *oid,
|
||||
int initial_commit)
|
||||
{
|
||||
struct rev_info rev;
|
||||
struct commit *commit;
|
||||
struct strbuf format = STRBUF_INIT;
|
||||
const char *head;
|
||||
struct pretty_print_context pctx = {0};
|
||||
struct strbuf author_ident = STRBUF_INIT;
|
||||
struct strbuf committer_ident = STRBUF_INIT;
|
||||
|
||||
commit = lookup_commit(oid);
|
||||
if (!commit)
|
||||
die(_("couldn't look up newly created commit"));
|
||||
if (parse_commit(commit))
|
||||
die(_("could not parse newly created commit"));
|
||||
|
||||
strbuf_addstr(&format, "format:%h] %s");
|
||||
|
||||
format_commit_message(commit, "%an <%ae>", &author_ident, &pctx);
|
||||
format_commit_message(commit, "%cn <%ce>", &committer_ident, &pctx);
|
||||
if (strbuf_cmp(&author_ident, &committer_ident)) {
|
||||
strbuf_addstr(&format, "\n Author: ");
|
||||
strbuf_addbuf_percentquote(&format, &author_ident);
|
||||
}
|
||||
if (author_date_is_interesting()) {
|
||||
struct strbuf date = STRBUF_INIT;
|
||||
format_commit_message(commit, "%ad", &date, &pctx);
|
||||
strbuf_addstr(&format, "\n Date: ");
|
||||
strbuf_addbuf_percentquote(&format, &date);
|
||||
strbuf_release(&date);
|
||||
}
|
||||
if (!committer_ident_sufficiently_given()) {
|
||||
strbuf_addstr(&format, "\n Committer: ");
|
||||
strbuf_addbuf_percentquote(&format, &committer_ident);
|
||||
if (advice_implicit_identity) {
|
||||
strbuf_addch(&format, '\n');
|
||||
strbuf_addstr(&format, implicit_ident_advice());
|
||||
}
|
||||
}
|
||||
strbuf_release(&author_ident);
|
||||
strbuf_release(&committer_ident);
|
||||
|
||||
init_revisions(&rev, prefix);
|
||||
setup_revisions(0, NULL, &rev, NULL);
|
||||
|
||||
rev.diff = 1;
|
||||
rev.diffopt.output_format =
|
||||
DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY;
|
||||
|
||||
rev.verbose_header = 1;
|
||||
rev.show_root_diff = 1;
|
||||
get_commit_format(format.buf, &rev);
|
||||
rev.always_show_header = 0;
|
||||
rev.diffopt.detect_rename = 1;
|
||||
rev.diffopt.break_opt = 0;
|
||||
diff_setup_done(&rev.diffopt);
|
||||
|
||||
head = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
|
||||
if (!head)
|
||||
die_errno(_("unable to resolve HEAD after creating commit"));
|
||||
if (!strcmp(head, "HEAD"))
|
||||
head = _("detached HEAD");
|
||||
else
|
||||
skip_prefix(head, "refs/heads/", &head);
|
||||
printf("[%s%s ", head, initial_commit ? _(" (root-commit)") : "");
|
||||
|
||||
if (!log_tree_commit(&rev, commit)) {
|
||||
rev.always_show_header = 1;
|
||||
rev.use_terminator = 1;
|
||||
log_tree_commit(&rev, commit);
|
||||
}
|
||||
|
||||
strbuf_release(&format);
|
||||
}
|
||||
|
||||
static int git_commit_config(const char *k, const char *v, void *cb)
|
||||
{
|
||||
struct wt_status *s = cb;
|
||||
@ -1708,8 +1591,15 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
||||
if (amend && !no_post_rewrite) {
|
||||
commit_post_rewrite(current_head, &oid);
|
||||
}
|
||||
if (!quiet)
|
||||
print_summary(prefix, &oid, !current_head);
|
||||
if (!quiet) {
|
||||
unsigned int flags = 0;
|
||||
|
||||
if (!current_head)
|
||||
flags |= SUMMARY_INITIAL_COMMIT;
|
||||
if (author_date_is_interesting())
|
||||
flags |= SUMMARY_SHOW_AUTHOR_DATE;
|
||||
print_commit_summary(prefix, &oid, flags);
|
||||
}
|
||||
|
||||
UNLEAK(err);
|
||||
UNLEAK(sb);
|
||||
|
119
sequencer.c
119
sequencer.c
@ -836,6 +836,125 @@ void commit_post_rewrite(const struct commit *old_head,
|
||||
run_rewrite_hook(&old_head->object.oid, new_head);
|
||||
}
|
||||
|
||||
static const char implicit_ident_advice_noconfig[] =
|
||||
N_("Your name and email address were configured automatically based\n"
|
||||
"on your username and hostname. Please check that they are accurate.\n"
|
||||
"You can suppress this message by setting them explicitly. Run the\n"
|
||||
"following command and follow the instructions in your editor to edit\n"
|
||||
"your configuration file:\n"
|
||||
"\n"
|
||||
" git config --global --edit\n"
|
||||
"\n"
|
||||
"After doing this, you may fix the identity used for this commit with:\n"
|
||||
"\n"
|
||||
" git commit --amend --reset-author\n");
|
||||
|
||||
static const char implicit_ident_advice_config[] =
|
||||
N_("Your name and email address were configured automatically based\n"
|
||||
"on your username and hostname. Please check that they are accurate.\n"
|
||||
"You can suppress this message by setting them explicitly:\n"
|
||||
"\n"
|
||||
" git config --global user.name \"Your Name\"\n"
|
||||
" git config --global user.email you@example.com\n"
|
||||
"\n"
|
||||
"After doing this, you may fix the identity used for this commit with:\n"
|
||||
"\n"
|
||||
" git commit --amend --reset-author\n");
|
||||
|
||||
static const char *implicit_ident_advice(void)
|
||||
{
|
||||
char *user_config = expand_user_path("~/.gitconfig", 0);
|
||||
char *xdg_config = xdg_config_home("config");
|
||||
int config_exists = file_exists(user_config) || file_exists(xdg_config);
|
||||
|
||||
free(user_config);
|
||||
free(xdg_config);
|
||||
|
||||
if (config_exists)
|
||||
return _(implicit_ident_advice_config);
|
||||
else
|
||||
return _(implicit_ident_advice_noconfig);
|
||||
|
||||
}
|
||||
|
||||
void print_commit_summary(const char *prefix, const struct object_id *oid,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct rev_info rev;
|
||||
struct commit *commit;
|
||||
struct strbuf format = STRBUF_INIT;
|
||||
const char *head;
|
||||
struct pretty_print_context pctx = {0};
|
||||
struct strbuf author_ident = STRBUF_INIT;
|
||||
struct strbuf committer_ident = STRBUF_INIT;
|
||||
|
||||
commit = lookup_commit(oid);
|
||||
if (!commit)
|
||||
die(_("couldn't look up newly created commit"));
|
||||
if (parse_commit(commit))
|
||||
die(_("could not parse newly created commit"));
|
||||
|
||||
strbuf_addstr(&format, "format:%h] %s");
|
||||
|
||||
format_commit_message(commit, "%an <%ae>", &author_ident, &pctx);
|
||||
format_commit_message(commit, "%cn <%ce>", &committer_ident, &pctx);
|
||||
if (strbuf_cmp(&author_ident, &committer_ident)) {
|
||||
strbuf_addstr(&format, "\n Author: ");
|
||||
strbuf_addbuf_percentquote(&format, &author_ident);
|
||||
}
|
||||
if (flags & SUMMARY_SHOW_AUTHOR_DATE) {
|
||||
struct strbuf date = STRBUF_INIT;
|
||||
|
||||
format_commit_message(commit, "%ad", &date, &pctx);
|
||||
strbuf_addstr(&format, "\n Date: ");
|
||||
strbuf_addbuf_percentquote(&format, &date);
|
||||
strbuf_release(&date);
|
||||
}
|
||||
if (!committer_ident_sufficiently_given()) {
|
||||
strbuf_addstr(&format, "\n Committer: ");
|
||||
strbuf_addbuf_percentquote(&format, &committer_ident);
|
||||
if (advice_implicit_identity) {
|
||||
strbuf_addch(&format, '\n');
|
||||
strbuf_addstr(&format, implicit_ident_advice());
|
||||
}
|
||||
}
|
||||
strbuf_release(&author_ident);
|
||||
strbuf_release(&committer_ident);
|
||||
|
||||
init_revisions(&rev, prefix);
|
||||
setup_revisions(0, NULL, &rev, NULL);
|
||||
|
||||
rev.diff = 1;
|
||||
rev.diffopt.output_format =
|
||||
DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY;
|
||||
|
||||
rev.verbose_header = 1;
|
||||
rev.show_root_diff = 1;
|
||||
get_commit_format(format.buf, &rev);
|
||||
rev.always_show_header = 0;
|
||||
rev.diffopt.detect_rename = 1;
|
||||
rev.diffopt.break_opt = 0;
|
||||
diff_setup_done(&rev.diffopt);
|
||||
|
||||
head = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
|
||||
if (!head)
|
||||
die_errno(_("unable to resolve HEAD after creating commit"));
|
||||
if (!strcmp(head, "HEAD"))
|
||||
head = _("detached HEAD");
|
||||
else
|
||||
skip_prefix(head, "refs/heads/", &head);
|
||||
printf("[%s%s ", head, (flags & SUMMARY_INITIAL_COMMIT) ?
|
||||
_(" (root-commit)") : "");
|
||||
|
||||
if (!log_tree_commit(&rev, commit)) {
|
||||
rev.always_show_header = 1;
|
||||
rev.use_terminator = 1;
|
||||
log_tree_commit(&rev, commit);
|
||||
}
|
||||
|
||||
strbuf_release(&format);
|
||||
}
|
||||
|
||||
static int is_original_commit_empty(struct commit *commit)
|
||||
{
|
||||
const struct object_id *ptree_oid;
|
||||
|
@ -75,4 +75,9 @@ int update_head_with_reflog(const struct commit *old_head,
|
||||
struct strbuf *err);
|
||||
void commit_post_rewrite(const struct commit *current_head,
|
||||
const struct object_id *new_head);
|
||||
|
||||
#define SUMMARY_INITIAL_COMMIT (1 << 0)
|
||||
#define SUMMARY_SHOW_AUTHOR_DATE (1 << 1)
|
||||
void print_commit_summary(const char *prefix, const struct object_id *oid,
|
||||
unsigned int flags);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user