summaryrefslogtreecommitdiff
path: root/builtin/commit.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/commit.c')
-rw-r--r--builtin/commit.c204
1 files changed, 115 insertions, 89 deletions
diff --git a/builtin/commit.c b/builtin/commit.c
index 985a0445b7..6e1484446b 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -6,33 +6,33 @@
*/
#define USE_THE_INDEX_VARIABLE
-#include "cache.h"
+#include "builtin.h"
+#include "advice.h"
#include "config.h"
#include "lockfile.h"
#include "cache-tree.h"
#include "color.h"
#include "dir.h"
-#include "builtin.h"
+#include "editor.h"
+#include "environment.h"
#include "diff.h"
-#include "diffcore.h"
#include "commit.h"
+#include "gettext.h"
#include "revision.h"
#include "wt-status.h"
#include "run-command.h"
-#include "hook.h"
-#include "refs.h"
-#include "log-tree.h"
#include "strbuf.h"
-#include "utf8.h"
+#include "object-name.h"
#include "parse-options.h"
+#include "path.h"
+#include "preload-index.h"
+#include "read-cache.h"
#include "string-list.h"
#include "rerere.h"
#include "unpack-trees.h"
-#include "quote.h"
-#include "submodule.h"
-#include "gpg-interface.h"
#include "column.h"
#include "sequencer.h"
+#include "sparse-index.h"
#include "mailmap.h"
#include "help.h"
#include "commit-reach.h"
@@ -331,8 +331,9 @@ static void create_base_index(const struct commit *current_head)
tree = parse_tree_indirect(&current_head->object.oid);
if (!tree)
die(_("failed to unpack HEAD tree object"));
- parse_tree(tree);
- init_tree_desc(&t, tree->buffer, tree->size);
+ if (parse_tree(tree) < 0)
+ exit(128);
+ init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);
if (unpack_trees(1, &t, &opts))
exit(128); /* We've already reported the error, finish dying */
}
@@ -440,15 +441,21 @@ static const char *prepare_index(const char **argv, const char *prefix,
* (B) on failure, rollback the real index.
*/
if (all || (also && pathspec.nr)) {
+ char *ps_matched = xcalloc(pathspec.nr, 1);
repo_hold_locked_index(the_repository, &index_lock,
LOCK_DIE_ON_ERROR);
- add_files_to_cache(also ? prefix : NULL, &pathspec, 0);
+ add_files_to_cache(the_repository, also ? prefix : NULL,
+ &pathspec, ps_matched, 0, 0);
+ if (!all && report_path_error(ps_matched, &pathspec))
+ exit(128);
+
refresh_cache_or_die(refresh_flags);
cache_tree_update(&the_index, WRITE_TREE_SILENT);
if (write_locked_index(&the_index, &index_lock, 0))
- die(_("unable to write new_index file"));
+ die(_("unable to write new index file"));
commit_style = COMMIT_NORMAL;
ret = get_lock_file_path(&index_lock);
+ free(ps_matched);
goto out;
}
@@ -470,7 +477,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
cache_tree_update(&the_index, WRITE_TREE_SILENT);
if (write_locked_index(&the_index, &index_lock,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
- die(_("unable to write new_index file"));
+ die(_("unable to write new index file"));
commit_style = COMMIT_AS_IS;
ret = get_index_file();
goto out;
@@ -518,7 +525,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL);
cache_tree_update(&the_index, WRITE_TREE_SILENT);
if (write_locked_index(&the_index, &index_lock, 0))
- die(_("unable to write new_index file"));
+ die(_("unable to write new index file"));
hold_lock_file_for_update(&false_lock,
git_path("next-index-%"PRIuMAX,
@@ -557,7 +564,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
s->index_file = index_file;
s->fp = fp;
s->nowarn = nowarn;
- s->is_initial = get_oid(s->reference, &oid) ? 1 : 0;
+ s->is_initial = repo_get_oid(the_repository, s->reference, &oid) ? 1 : 0;
if (!s->is_initial)
oidcpy(&s->oid_commit, &oid);
s->status_format = status_format;
@@ -683,9 +690,10 @@ static void adjust_comment_line_char(const struct strbuf *sb)
char *candidate;
const char *p;
- comment_line_char = candidates[0];
- if (!memchr(sb->buf, comment_line_char, sb->len))
+ if (!memchr(sb->buf, candidates[0], sb->len)) {
+ comment_line_str = xstrfmt("%c", candidates[0]);
return;
+ }
p = sb->buf;
candidate = strchr(candidates, *p);
@@ -704,7 +712,7 @@ static void adjust_comment_line_char(const struct strbuf *sb)
if (!*p)
die(_("unable to select a comment character that is not used\n"
"in the current commit message"));
- comment_line_char = *p;
+ comment_line_str = xstrfmt("%c", *p);
}
static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,
@@ -712,15 +720,15 @@ static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,
{
const char *buffer, *subject, *fmt;
- buffer = get_commit_buffer(commit, NULL);
+ buffer = repo_get_commit_buffer(the_repository, commit, NULL);
find_commit_subject(buffer, &subject);
/*
* If we amend the 'amend!' commit then we don't want to
* duplicate the subject line.
*/
fmt = starts_with(subject, "amend!") ? "%b" : "%B";
- format_commit_message(commit, fmt, sb, ctx);
- unuse_commit_buffer(commit, buffer);
+ repo_format_commit_message(the_repository, commit, fmt, sb, ctx);
+ repo_unuse_commit_buffer(the_repository, commit, buffer);
}
static int prepare_to_commit(const char *index_file, const char *prefix,
@@ -736,7 +744,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
const char *hook_arg2 = NULL;
int clean_message_contents = (cleanup_mode != COMMIT_MSG_CLEANUP_NONE);
int old_display_comment_prefix;
- int merge_contains_scissors = 0;
int invoked_hook;
/* This checks and barfs if author is badly specified */
@@ -758,10 +765,11 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
struct commit *c;
c = lookup_commit_reference_by_name(squash_message);
if (!c)
- die(_("could not lookup commit %s"), squash_message);
+ die(_("could not lookup commit '%s'"), squash_message);
ctx.output_encoding = get_commit_output_encoding();
- format_commit_message(c, "squash! %s\n\n", &sb,
- &ctx);
+ repo_format_commit_message(the_repository, c,
+ "squash! %s\n\n", &sb,
+ &ctx);
}
}
@@ -792,10 +800,11 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
char *fmt;
commit = lookup_commit_reference_by_name(fixup_commit);
if (!commit)
- die(_("could not lookup commit %s"), fixup_commit);
+ die(_("could not lookup commit '%s'"), fixup_commit);
ctx.output_encoding = get_commit_output_encoding();
fmt = xstrfmt("%s! %%s\n\n", fixup_prefix);
- format_commit_message(commit, fmt, &sb, &ctx);
+ repo_format_commit_message(the_repository, commit, fmt, &sb,
+ &ctx);
free(fmt);
hook_arg1 = "message";
@@ -838,7 +847,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
wt_status_locate_end(sb.buf + merge_msg_start,
sb.len - merge_msg_start) <
sb.len - merge_msg_start)
- merge_contains_scissors = 1;
+ s->added_cut_line = 1;
} else if (!stat(git_path_squash_msg(the_repository), &statbuf)) {
if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 0) < 0)
die_errno(_("could not read SQUASH_MSG"));
@@ -886,10 +895,10 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
s->hints = 0;
if (clean_message_contents)
- strbuf_stripspace(&sb, 0);
+ strbuf_stripspace(&sb, NULL);
if (signoff)
- append_signoff(&sb, ignore_non_trailer(sb.buf, sb.len), 0);
+ append_signoff(&sb, ignored_log_message_bytes(sb.buf, sb.len), 0);
if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
die_errno(_("could not write commit template"));
@@ -906,24 +915,23 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
struct ident_split ci, ai;
const char *hint_cleanup_all = allow_empty_message ?
_("Please enter the commit message for your changes."
- " Lines starting\nwith '%c' will be ignored.\n") :
+ " Lines starting\nwith '%s' will be ignored.\n") :
_("Please enter the commit message for your changes."
- " Lines starting\nwith '%c' will be ignored, and an empty"
+ " Lines starting\nwith '%s' will be ignored, and an empty"
" message aborts the commit.\n");
const char *hint_cleanup_space = allow_empty_message ?
_("Please enter the commit message for your changes."
" Lines starting\n"
- "with '%c' will be kept; you may remove them"
+ "with '%s' will be kept; you may remove them"
" yourself if you want to.\n") :
_("Please enter the commit message for your changes."
" Lines starting\n"
- "with '%c' will be kept; you may remove them"
+ "with '%s' will be kept; you may remove them"
" yourself if you want to.\n"
"An empty message aborts the commit.\n");
if (whence != FROM_COMMIT) {
- if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS &&
- !merge_contains_scissors)
- wt_status_add_cut_line(s->fp);
+ if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS)
+ wt_status_add_cut_line(s);
status_printf_ln(
s, GIT_COLOR_NORMAL,
whence == FROM_MERGE ?
@@ -941,12 +949,12 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
fprintf(s->fp, "\n");
if (cleanup_mode == COMMIT_MSG_CLEANUP_ALL)
- status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_all, comment_line_char);
+ status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_all, comment_line_str);
else if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) {
- if (whence == FROM_COMMIT && !merge_contains_scissors)
- wt_status_add_cut_line(s->fp);
+ if (whence == FROM_COMMIT)
+ wt_status_add_cut_line(s);
} else /* COMMIT_MSG_CLEANUP_SPACE, that is. */
- status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_space, comment_line_char);
+ status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_space, comment_line_str);
/*
* These should never fail because they come from our own
@@ -991,16 +999,13 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
struct object_id oid;
const char *parent = "HEAD";
- if (!the_index.cache_nr) {
- discard_index(&the_index);
- if (repo_read_index(the_repository) < 0)
- die(_("Cannot read index"));
- }
+ if (!the_index.initialized && repo_read_index(the_repository) < 0)
+ die(_("Cannot read index"));
if (amend)
parent = "HEAD^1";
- if (get_oid(parent, &oid)) {
+ if (repo_get_oid(the_repository, parent, &oid)) {
int i, ita_nr = 0;
/* TODO: audit for interaction with sparse-index. */
@@ -1036,7 +1041,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
struct child_process run_trailer = CHILD_PROCESS_INIT;
strvec_pushl(&run_trailer.args, "interpret-trailers",
- "--in-place", git_path_commit_editmsg(), NULL);
+ "--in-place", "--no-divider",
+ git_path_commit_editmsg(), NULL);
strvec_pushv(&run_trailer.args, trailer_args.v);
run_trailer.git_cmd = 1;
if (run_command(&run_trailer))
@@ -1135,7 +1141,8 @@ static const char *find_author_by_nickname(const char *name)
struct pretty_print_context ctx = {0};
ctx.date_mode.type = DATE_NORMAL;
strbuf_release(&buf);
- format_commit_message(commit, "%aN <%aE>", &buf, &ctx);
+ repo_format_commit_message(the_repository, commit,
+ "%aN <%aE>", &buf, &ctx);
release_revisions(&revs);
return strbuf_detach(&buf, NULL);
}
@@ -1156,22 +1163,45 @@ static void handle_ignored_arg(struct wt_status *s)
die(_("Invalid ignored mode '%s'"), ignored_arg);
}
-static void handle_untracked_files_arg(struct wt_status *s)
+static enum untracked_status_type parse_untracked_setting_name(const char *u)
{
- if (!untracked_files_arg)
- ; /* default already initialized */
- else if (!strcmp(untracked_files_arg, "no"))
- s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
- else if (!strcmp(untracked_files_arg, "normal"))
- s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
- else if (!strcmp(untracked_files_arg, "all"))
- s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
/*
* Please update $__git_untracked_file_modes in
* git-completion.bash when you add new options
*/
+ switch (git_parse_maybe_bool(u)) {
+ case 0:
+ u = "no";
+ break;
+ case 1:
+ u = "normal";
+ break;
+ default:
+ break;
+ }
+
+ if (!strcmp(u, "no"))
+ return SHOW_NO_UNTRACKED_FILES;
+ else if (!strcmp(u, "normal"))
+ return SHOW_NORMAL_UNTRACKED_FILES;
+ else if (!strcmp(u, "all"))
+ return SHOW_ALL_UNTRACKED_FILES;
else
- die(_("Invalid untracked files mode '%s'"), untracked_files_arg);
+ return SHOW_UNTRACKED_FILES_ERROR;
+}
+
+static void handle_untracked_files_arg(struct wt_status *s)
+{
+ enum untracked_status_type u;
+
+ if (!untracked_files_arg)
+ return; /* default already initialized */
+
+ u = parse_untracked_setting_name(untracked_files_arg);
+ if (u == SHOW_UNTRACKED_FILES_ERROR)
+ die(_("Invalid untracked files mode '%s'"),
+ untracked_files_arg);
+ s->show_untracked_files = u;
}
static const char *read_commit_message(const char *name)
@@ -1181,9 +1211,9 @@ static const char *read_commit_message(const char *name)
commit = lookup_commit_reference_by_name(name);
if (!commit)
- die(_("could not lookup commit %s"), name);
+ die(_("could not lookup commit '%s'"), name);
out_enc = get_commit_output_encoding();
- return logmsg_reencode(commit, NULL, out_enc);
+ return repo_logmsg_reencode(the_repository, commit, NULL, out_enc);
}
/*
@@ -1397,7 +1427,8 @@ static int parse_status_slot(const char *slot)
return LOOKUP_CONFIG(color_status_slots, slot);
}
-static int git_status_config(const char *k, const char *v, void *cb)
+static int git_status_config(const char *k, const char *v,
+ const struct config_context *ctx, void *cb)
{
struct wt_status *s = cb;
const char *slot_name;
@@ -1406,7 +1437,8 @@ static int git_status_config(const char *k, const char *v, void *cb)
return git_column_config(k, v, "status", &s->colopts);
if (!strcmp(k, "status.submodulesummary")) {
int is_bool;
- s->submodule_summary = git_config_bool_or_int(k, v, &is_bool);
+ s->submodule_summary = git_config_bool_or_int(k, v, ctx->kvi,
+ &is_bool);
if (is_bool && s->submodule_summary)
s->submodule_summary = -1;
return 0;
@@ -1452,25 +1484,21 @@ static int git_status_config(const char *k, const char *v, void *cb)
return 0;
}
if (!strcmp(k, "status.showuntrackedfiles")) {
- if (!v)
- return config_error_nonbool(k);
- else if (!strcmp(v, "no"))
- s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
- else if (!strcmp(v, "normal"))
- s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
- else if (!strcmp(v, "all"))
- s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
- else
+ enum untracked_status_type u;
+
+ u = parse_untracked_setting_name(v);
+ if (u == SHOW_UNTRACKED_FILES_ERROR)
return error(_("Invalid untracked files mode '%s'"), v);
+ s->show_untracked_files = u;
return 0;
}
if (!strcmp(k, "diff.renamelimit")) {
if (s->rename_limit == -1)
- s->rename_limit = git_config_int(k, v);
+ s->rename_limit = git_config_int(k, v, ctx->kvi);
return 0;
}
if (!strcmp(k, "status.renamelimit")) {
- s->rename_limit = git_config_int(k, v);
+ s->rename_limit = git_config_int(k, v, ctx->kvi);
return 0;
}
if (!strcmp(k, "diff.renames")) {
@@ -1482,7 +1510,7 @@ static int git_status_config(const char *k, const char *v, void *cb)
s->detect_rename = git_config_rename(k, v);
return 0;
}
- return git_diff_ui_config(k, v, NULL);
+ return git_diff_ui_config(k, v, ctx, NULL);
}
int cmd_status(int argc, const char **argv, const char *prefix)
@@ -1567,7 +1595,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
else
fd = -1;
- s.is_initial = get_oid(s.reference, &oid) ? 1 : 0;
+ s.is_initial = repo_get_oid(the_repository, s.reference, &oid) ? 1 : 0;
if (!s.is_initial)
oidcpy(&s.oid_commit, &oid);
@@ -1597,10 +1625,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)
return 0;
}
-static int git_commit_config(const char *k, const char *v, void *cb)
+static int git_commit_config(const char *k, const char *v,
+ const struct config_context *ctx, void *cb)
{
struct wt_status *s = cb;
- int status;
if (!strcmp(k, "commit.template"))
return git_config_pathname(&template_file, k, v);
@@ -1616,14 +1644,12 @@ static int git_commit_config(const char *k, const char *v, void *cb)
}
if (!strcmp(k, "commit.verbose")) {
int is_bool;
- config_commit_verbose = git_config_bool_or_int(k, v, &is_bool);
+ config_commit_verbose = git_config_bool_or_int(k, v, ctx->kvi,
+ &is_bool);
return 0;
}
- status = git_gpg_config(k, v, NULL);
- if (status)
- return status;
- return git_status_config(k, v, s);
+ return git_status_config(k, v, ctx, s);
}
int cmd_commit(int argc, const char **argv, const char *prefix)
@@ -1714,11 +1740,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
status_format = STATUS_FORMAT_NONE; /* Ignore status.short */
s.colopts = 0;
- if (get_oid("HEAD", &oid))
+ if (repo_get_oid(the_repository, "HEAD", &oid))
current_head = NULL;
else {
current_head = lookup_commit_or_die(&oid, "HEAD");
- if (parse_commit(current_head))
+ if (repo_parse_commit(the_repository, current_head))
die(_("could not parse HEAD commit"));
}
verbose = -1; /* unspecified */
@@ -1852,7 +1878,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
if (commit_index_files())
die(_("repository has been updated, but unable to write\n"
- "new_index file. Check that disk is not full and quota is\n"
+ "new index file. Check that disk is not full and quota is\n"
"not exceeded, and then \"git restore --staged :/\" to recover."));
git_test_write_commit_graph_or_die();
@@ -1875,7 +1901,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
&oid, flags);
}
- apply_autostash(git_path_merge_autostash(the_repository));
+ apply_autostash_ref(the_repository, "MERGE_AUTOSTASH");
cleanup:
strbuf_release(&author_ident);