diff options
Diffstat (limited to 'builtin/commit.c')
-rw-r--r-- | builtin/commit.c | 81 |
1 files changed, 58 insertions, 23 deletions
diff --git a/builtin/commit.c b/builtin/commit.c index 58bad61306..3d99cf9158 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -48,6 +48,11 @@ static const char implicit_ident_advice[] = "\n" " git commit --amend --author='Your Name <you@example.com>'\n"; +static const char empty_amend_advice[] = +"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" +"remove the commit entirely with \"git reset HEAD^\".\n"; + static unsigned char head_sha1[20]; static char *use_message_buffer; @@ -57,7 +62,7 @@ static struct lock_file false_lock; /* used only for partial commits */ static enum { COMMIT_AS_IS = 1, COMMIT_NORMAL, - COMMIT_PARTIAL, + COMMIT_PARTIAL } commit_style; static const char *logfile, *force_author; @@ -66,7 +71,7 @@ static char *edit_message, *use_message; static char *author_name, *author_email, *author_date; static int all, edit_flag, also, interactive, only, amend, signoff; static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship; -static int no_post_rewrite; +static int no_post_rewrite, allow_empty_message; static char *untracked_files_arg, *force_date; /* * The default commit message cleanup mode will remove the lines @@ -78,11 +83,12 @@ static char *untracked_files_arg, *force_date; static enum { CLEANUP_SPACE, CLEANUP_NONE, - CLEANUP_ALL, + CLEANUP_ALL } cleanup_mode; static char *cleanup_arg; static int use_editor = 1, initial_commit, in_merge, include_status = 1; +static int show_ignored_in_status; static const char *only_include_assumed; static struct strbuf message; @@ -90,8 +96,9 @@ static int null_termination; static enum { STATUS_FORMAT_LONG, STATUS_FORMAT_SHORT, - STATUS_FORMAT_PORCELAIN, + STATUS_FORMAT_PORCELAIN } status_format = STATUS_FORMAT_LONG; +static int status_show_branch; static int opt_parse_m(const struct option *opt, const char *arg, int unset) { @@ -133,6 +140,7 @@ static struct option builtin_commit_options[] = { OPT_BOOLEAN(0, "dry-run", &dry_run, "show what would be committed"), OPT_SET_INT(0, "short", &status_format, "show status concisely", STATUS_FORMAT_SHORT), + OPT_BOOLEAN(0, "branch", &status_show_branch, "show branch information"), OPT_SET_INT(0, "porcelain", &status_format, "show porcelain output format", STATUS_FORMAT_PORCELAIN), OPT_BOOLEAN('z', "null", &null_termination, @@ -140,9 +148,15 @@ static struct option builtin_commit_options[] = { OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"), OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, "bypass post-rewrite hook"), { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, - OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"), /* end commit contents options */ + { OPTION_BOOLEAN, 0, "allow-empty", &allow_empty, NULL, + "ok to record an empty change", + PARSE_OPT_NOARG | PARSE_OPT_HIDDEN }, + { OPTION_BOOLEAN, 0, "allow-empty-message", &allow_empty_message, NULL, + "ok to record a change with an empty message", + PARSE_OPT_NOARG | PARSE_OPT_HIDDEN }, + OPT_END() }; @@ -417,7 +431,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int switch (status_format) { case STATUS_FORMAT_SHORT: - wt_shortstatus_print(s, null_termination); + wt_shortstatus_print(s, null_termination, status_show_branch); break; case STATUS_FORMAT_PORCELAIN: wt_porcelain_print(s, null_termination); @@ -455,15 +469,21 @@ static void determine_author_info(void) if (!a) die("invalid commit: %s", use_message); - lb = strstr(a + 8, " <"); - rb = strstr(a + 8, "> "); - eol = strchr(a + 8, '\n'); - if (!lb || !rb || !eol) + lb = strchrnul(a + strlen("\nauthor "), '<'); + rb = strchrnul(lb, '>'); + eol = strchrnul(rb, '\n'); + if (!*lb || !*rb || !*eol) die("invalid commit: %s", use_message); - name = xstrndup(a + 8, lb - (a + 8)); - email = xstrndup(lb + 2, rb - (lb + 2)); - date = xstrndup(rb + 2, eol - (rb + 2)); + if (lb == a + strlen("\nauthor ")) + /* \nauthor <foo@example.com> */ + name = xcalloc(1, 1); + else + name = xmemdupz(a + strlen("\nauthor "), + (lb - strlen(" ") - + (a + strlen("\nauthor ")))); + email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<"))); + date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> "))); } if (force_author) { @@ -693,6 +713,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (!commitable && !in_merge && !allow_empty && !(amend && is_a_merge(head_sha1))) { run_status(stdout, index_file, prefix, 0, s); + if (amend) + fputs(empty_amend_advice, stderr); return 0; } @@ -717,7 +739,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (use_editor) { char index[PATH_MAX]; - const char *env[2] = { index, NULL }; + const char *env[2] = { NULL }; + env[0] = index; snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file); if (launch_editor(git_path(commit_editmsg), NULL, env)) { fprintf(stderr, @@ -1017,11 +1040,14 @@ static int git_status_config(const char *k, const char *v, void *cb) int cmd_status(int argc, const char **argv, const char *prefix) { struct wt_status s; + int fd; unsigned char sha1[20]; static struct option builtin_status_options[] = { OPT__VERBOSE(&verbose), OPT_SET_INT('s', "short", &status_format, "show status concisely", STATUS_FORMAT_SHORT), + OPT_BOOLEAN('b', "branch", &status_show_branch, + "show branch information"), OPT_SET_INT(0, "porcelain", &status_format, "show porcelain output format", STATUS_FORMAT_PORCELAIN), @@ -1031,6 +1057,8 @@ int cmd_status(int argc, const char **argv, const char *prefix) "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, + OPT_BOOLEAN(0, "ignored", &show_ignored_in_status, + "show ignored files"), OPT_END(), }; @@ -1044,12 +1072,21 @@ int cmd_status(int argc, const char **argv, const char *prefix) builtin_status_options, builtin_status_usage, 0); handle_untracked_files_arg(&s); - + if (show_ignored_in_status) + s.show_ignored_files = 1; if (*argv) s.pathspec = get_pathspec(prefix, argv); read_cache_preload(s.pathspec); refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec, NULL, NULL); + + fd = hold_locked_index(&index_lock, 0); + if (0 <= fd) { + if (!write_cache(fd, active_cache, active_nr)) + commit_locked_index(&index_lock); + rollback_lock_file(&index_lock); + } + s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0; s.in_merge = in_merge; wt_status_collect(&s); @@ -1063,7 +1100,7 @@ int cmd_status(int argc, const char **argv, const char *prefix) switch (status_format) { case STATUS_FORMAT_SHORT: - wt_shortstatus_print(&s, null_termination); + wt_shortstatus_print(&s, null_termination, status_show_branch); break; case STATUS_FORMAT_PORCELAIN: wt_porcelain_print(&s, null_termination); @@ -1138,13 +1175,11 @@ static void print_summary(const char *prefix, const unsigned char *sha1) initial_commit ? " (root-commit)" : ""); if (!log_tree_commit(&rev, commit)) { - struct pretty_print_context ctx = {0}; - struct strbuf buf = STRBUF_INIT; - ctx.date_mode = DATE_NORMAL; - format_commit_message(commit, format.buf + 7, &buf, &ctx); - printf("%s\n", buf.buf); - strbuf_release(&buf); + rev.always_show_header = 1; + rev.use_terminator = 1; + log_tree_commit(&rev, commit); } + strbuf_release(&format); } @@ -1298,7 +1333,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) if (cleanup_mode != CLEANUP_NONE) stripspace(&sb, cleanup_mode == CLEANUP_ALL); - if (message_is_empty(&sb)) { + if (message_is_empty(&sb) && !allow_empty_message) { rollback_index_files(); fprintf(stderr, "Aborting commit due to empty commit message.\n"); exit(1); |