summaryrefslogtreecommitdiff
path: root/builtin/commit.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/commit.c')
-rw-r--r--builtin/commit.c153
1 files changed, 55 insertions, 98 deletions
diff --git a/builtin/commit.c b/builtin/commit.c
index b0fe784..7f46713 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -6,6 +6,7 @@
*/
#include "cache.h"
+#include "lockfile.h"
#include "cache-tree.h"
#include "color.h"
#include "dir.h"
@@ -33,12 +34,12 @@
#include "mailmap.h"
static const char * const builtin_commit_usage[] = {
- N_("git commit [options] [--] <pathspec>..."),
+ N_("git commit [<options>] [--] <pathspec>..."),
NULL
};
static const char * const builtin_status_usage[] = {
- N_("git status [options] [--] <pathspec>..."),
+ N_("git status [<options>] [--] <pathspec>..."),
NULL
};
@@ -315,8 +316,8 @@ static void refresh_cache_or_die(int refresh_flags)
die_resolve_conflict("commit");
}
-static char *prepare_index(int argc, const char **argv, const char *prefix,
- const struct commit *current_head, int is_status)
+static const char *prepare_index(int argc, const char **argv, const char *prefix,
+ const struct commit *current_head, int is_status)
{
struct string_list partial;
struct pathspec pathspec;
@@ -341,7 +342,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
die(_("unable to create temporary index"));
old_index_env = getenv(INDEX_ENVIRONMENT);
- setenv(INDEX_ENVIRONMENT, index_lock.filename, 1);
+ setenv(INDEX_ENVIRONMENT, index_lock.filename.buf, 1);
if (interactive_add(argc, argv, prefix, patch_interactive) != 0)
die(_("interactive add failed"));
@@ -352,7 +353,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
unsetenv(INDEX_ENVIRONMENT);
discard_cache();
- read_cache_from(index_lock.filename);
+ read_cache_from(index_lock.filename.buf);
if (update_main_cache_tree(WRITE_TREE_SILENT) == 0) {
if (reopen_lock_file(&index_lock) < 0)
die(_("unable to write index file"));
@@ -362,7 +363,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
warning(_("Failed to update main cache tree"));
commit_style = COMMIT_NORMAL;
- return index_lock.filename;
+ return index_lock.filename.buf;
}
/*
@@ -385,7 +386,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
if (write_locked_index(&the_index, &index_lock, CLOSE_LOCK))
die(_("unable to write new_index file"));
commit_style = COMMIT_NORMAL;
- return index_lock.filename;
+ return index_lock.filename.buf;
}
/*
@@ -472,9 +473,9 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
die(_("unable to write temporary index file"));
discard_cache();
- read_cache_from(false_lock.filename);
+ read_cache_from(false_lock.filename.buf);
- return false_lock.filename;
+ return false_lock.filename.buf;
}
static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn,
@@ -521,6 +522,12 @@ static int is_a_merge(const struct commit *current_head)
return !!(current_head->parents && current_head->parents->next);
}
+static void assert_split_ident(struct ident_split *id, const struct strbuf *buf)
+{
+ if (split_ident_line(id, buf->buf, buf->len) || !id->date_begin)
+ die("BUG: unable to parse our own ident: %s", buf->buf);
+}
+
static void export_one(const char *var, const char *s, const char *e, int hack)
{
struct strbuf buf = STRBUF_INIT;
@@ -531,20 +538,6 @@ static void export_one(const char *var, const char *s, const char *e, int hack)
strbuf_release(&buf);
}
-static int sane_ident_split(struct ident_split *person)
-{
- if (!person->name_begin || !person->name_end ||
- person->name_begin == person->name_end)
- return 0; /* no human readable name */
- if (!person->mail_begin || !person->mail_end ||
- person->mail_begin == person->mail_end)
- return 0; /* no usable mail */
- if (!person->date_begin || !person->date_end ||
- !person->tz_begin || !person->tz_end)
- return 0;
- return 1;
-}
-
static int parse_force_date(const char *in, struct strbuf *out)
{
strbuf_addch(out, '@');
@@ -566,20 +559,14 @@ static void set_ident_var(char **buf, char *val)
*buf = val;
}
-static char *envdup(const char *var)
-{
- const char *val = getenv(var);
- return val ? xstrdup(val) : NULL;
-}
-
static void determine_author_info(struct strbuf *author_ident)
{
char *name, *email, *date;
struct ident_split author;
- name = envdup("GIT_AUTHOR_NAME");
- email = envdup("GIT_AUTHOR_EMAIL");
- date = envdup("GIT_AUTHOR_DATE");
+ name = xstrdup_or_null(getenv("GIT_AUTHOR_NAME"));
+ email = xstrdup_or_null(getenv("GIT_AUTHOR_EMAIL"));
+ date = xstrdup_or_null(getenv("GIT_AUTHOR_DATE"));
if (author_message) {
struct ident_split ident;
@@ -622,25 +609,15 @@ static void determine_author_info(struct strbuf *author_ident)
}
strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
- if (!split_ident_line(&author, author_ident->buf, author_ident->len) &&
- sane_ident_split(&author)) {
- export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
- export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
- export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
- }
-
+ assert_split_ident(&author, author_ident);
+ export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
+ export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
+ export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
free(name);
free(email);
free(date);
}
-static void split_ident_or_die(struct ident_split *id, const struct strbuf *buf)
-{
- if (split_ident_line(id, buf->buf, buf->len) ||
- !sane_ident_split(id))
- die(_("Malformed ident string: '%s'"), buf->buf);
-}
-
static int author_date_is_interesting(void)
{
return author_message || force_date;
@@ -799,32 +776,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
if (clean_message_contents)
stripspace(&sb, 0);
- if (signoff) {
- /*
- * See if we have a Conflicts: block at the end. If yes, count
- * its size, so we can ignore it.
- */
- int ignore_footer = 0;
- int i, eol, previous = 0;
- const char *nl;
-
- for (i = 0; i < sb.len; i++) {
- nl = memchr(sb.buf + i, '\n', sb.len - i);
- if (nl)
- eol = nl - sb.buf;
- else
- eol = sb.len;
- if (starts_with(sb.buf + previous, "\nConflicts:\n")) {
- ignore_footer = sb.len - previous;
- break;
- }
- while (i < eol)
- i++;
- previous = eol;
- }
-
- append_signoff(&sb, ignore_footer, 0);
- }
+ if (signoff)
+ append_signoff(&sb, ignore_non_trailer(&sb), 0);
if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
die_errno(_("could not write commit template"));
@@ -879,8 +832,14 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
status_printf_ln(s, GIT_COLOR_NORMAL,
"%s", only_include_assumed);
- split_ident_or_die(&ai, author_ident);
- split_ident_or_die(&ci, &committer_ident);
+ /*
+ * These should never fail because they come from our own
+ * fmt_ident. They may fail the sane_ident test, but we know
+ * that the name and mail pointers will at least be valid,
+ * which is enough for our tests and printing here.
+ */
+ assert_split_ident(&ai, author_ident);
+ assert_split_ident(&ci, &committer_ident);
if (ident_cmp(&ai, &ci))
status_printf_ln(s, GIT_COLOR_NORMAL,
@@ -1271,22 +1230,21 @@ static int dry_run_commit(int argc, const char **argv, const char *prefix,
return commitable ? 0 : 1;
}
-static int parse_status_slot(const char *var, int offset)
+static int parse_status_slot(const char *slot)
{
- if (!strcasecmp(var+offset, "header"))
+ if (!strcasecmp(slot, "header"))
return WT_STATUS_HEADER;
- if (!strcasecmp(var+offset, "branch"))
+ if (!strcasecmp(slot, "branch"))
return WT_STATUS_ONBRANCH;
- if (!strcasecmp(var+offset, "updated")
- || !strcasecmp(var+offset, "added"))
+ if (!strcasecmp(slot, "updated") || !strcasecmp(slot, "added"))
return WT_STATUS_UPDATED;
- if (!strcasecmp(var+offset, "changed"))
+ if (!strcasecmp(slot, "changed"))
return WT_STATUS_CHANGED;
- if (!strcasecmp(var+offset, "untracked"))
+ if (!strcasecmp(slot, "untracked"))
return WT_STATUS_UNTRACKED;
- if (!strcasecmp(var+offset, "nobranch"))
+ if (!strcasecmp(slot, "nobranch"))
return WT_STATUS_NOBRANCH;
- if (!strcasecmp(var+offset, "unmerged"))
+ if (!strcasecmp(slot, "unmerged"))
return WT_STATUS_UNMERGED;
return -1;
}
@@ -1294,6 +1252,7 @@ static int parse_status_slot(const char *var, int offset)
static int git_status_config(const char *k, const char *v, void *cb)
{
struct wt_status *s = cb;
+ const char *slot_name;
if (starts_with(k, "column."))
return git_column_config(k, v, "status", &s->colopts);
@@ -1323,14 +1282,14 @@ static int git_status_config(const char *k, const char *v, void *cb)
s->display_comment_prefix = git_config_bool(k, v);
return 0;
}
- if (starts_with(k, "status.color.") || starts_with(k, "color.status.")) {
- int slot = parse_status_slot(k, 13);
+ if (skip_prefix(k, "status.color.", &slot_name) ||
+ skip_prefix(k, "color.status.", &slot_name)) {
+ int slot = parse_status_slot(slot_name);
if (slot < 0)
return 0;
if (!v)
return config_error_nonbool(k);
- color_parse(v, k, s->color_palette[slot]);
- return 0;
+ return color_parse(v, s->color_palette[slot]);
}
if (!strcmp(k, "status.relativepaths")) {
s->relative_paths = git_config_bool(k, v);
@@ -1512,14 +1471,12 @@ static void print_summary(const char *prefix, const unsigned char *sha1,
rev.diffopt.break_opt = 0;
diff_setup_done(&rev.diffopt);
- head = resolve_ref_unsafe("HEAD", junk_sha1, 0, NULL);
- printf("[%s%s ",
- starts_with(head, "refs/heads/") ?
- head + 11 :
- !strcmp(head, "HEAD") ?
- _("detached HEAD") :
- head,
- initial_commit ? _(" (root-commit)") : "");
+ head = resolve_ref_unsafe("HEAD", 0, junk_sha1, NULL);
+ 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;
@@ -1810,8 +1767,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
ref_transaction_update(transaction, "HEAD", sha1,
current_head
? current_head->object.sha1 : NULL,
- 0, !!current_head, &err) ||
- ref_transaction_commit(transaction, sb.buf, &err)) {
+ 0, !!current_head, sb.buf, &err) ||
+ ref_transaction_commit(transaction, &err)) {
rollback_index_files();
die("%s", err.buf);
}