Merge branch 'mv/commit-tree'

* mv/commit-tree:
  t7603: add new testcases to ensure builtin-commit uses reduce_heads()
  builtin-commit: use commit_tree()
  commit_tree(): add a new author parameter
This commit is contained in:
Shawn O. Pearce 2008-09-25 09:16:33 -07:00
commit 1fa24f8f3d
5 changed files with 79 additions and 57 deletions

View File

@ -46,7 +46,8 @@ static const char commit_utf8_warn[] =
"variable i18n.commitencoding to the encoding your project uses.\n"; "variable i18n.commitencoding to the encoding your project uses.\n";
int commit_tree(const char *msg, unsigned char *tree, int commit_tree(const char *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret) struct commit_list *parents, unsigned char *ret,
const char *author)
{ {
int result; int result;
int encoding_is_utf8; int encoding_is_utf8;
@ -74,7 +75,9 @@ int commit_tree(const char *msg, unsigned char *tree,
} }
/* Person/date information */ /* Person/date information */
strbuf_addf(&buffer, "author %s\n", git_author_info(IDENT_ERROR_ON_NO_NAME)); if (!author)
author = git_author_info(IDENT_ERROR_ON_NO_NAME);
strbuf_addf(&buffer, "author %s\n", author);
strbuf_addf(&buffer, "committer %s\n", git_committer_info(IDENT_ERROR_ON_NO_NAME)); strbuf_addf(&buffer, "committer %s\n", git_committer_info(IDENT_ERROR_ON_NO_NAME));
if (!encoding_is_utf8) if (!encoding_is_utf8)
strbuf_addf(&buffer, "encoding %s\n", git_commit_encoding); strbuf_addf(&buffer, "encoding %s\n", git_commit_encoding);
@ -123,7 +126,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
if (strbuf_read(&buffer, 0, 0) < 0) if (strbuf_read(&buffer, 0, 0) < 0)
die("git commit-tree: read returned %s", strerror(errno)); die("git commit-tree: read returned %s", strerror(errno));
if (!commit_tree(buffer.buf, tree_sha1, parents, commit_sha1)) { if (!commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) {
printf("%s\n", sha1_to_hex(commit_sha1)); printf("%s\n", sha1_to_hex(commit_sha1));
return 0; return 0;
} }

View File

@ -667,14 +667,14 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
} }
/* /*
* Find out if the message starting at position 'start' in the strbuf * Find out if the message in the strbuf contains only whitespace and
* contains only whitespace and Signed-off-by lines. * Signed-off-by lines.
*/ */
static int message_is_empty(struct strbuf *sb, int start) static int message_is_empty(struct strbuf *sb)
{ {
struct strbuf tmpl; struct strbuf tmpl;
const char *nl; const char *nl;
int eol, i; int eol, i, start = 0;
if (cleanup_mode == CLEANUP_NONE && sb->len) if (cleanup_mode == CLEANUP_NONE && sb->len)
return 0; return 0;
@ -929,34 +929,14 @@ static const char commit_utf8_warn[] =
"You may want to amend it after fixing the message, or set the config\n" "You may want to amend it after fixing the message, or set the config\n"
"variable i18n.commitencoding to the encoding your project uses.\n"; "variable i18n.commitencoding to the encoding your project uses.\n";
static void add_parent(struct strbuf *sb, const unsigned char *sha1)
{
struct object *obj = parse_object(sha1);
const char *parent = sha1_to_hex(sha1);
const char *cp;
if (!obj)
die("Unable to find commit parent %s", parent);
if (obj->type != OBJ_COMMIT)
die("Parent %s isn't a proper commit", parent);
for (cp = sb->buf; cp && (cp = strstr(cp, "\nparent ")); cp += 8) {
if (!memcmp(cp + 8, parent, 40) && cp[48] == '\n') {
error("duplicate parent %s ignored", parent);
return;
}
}
strbuf_addf(sb, "parent %s\n", parent);
}
int cmd_commit(int argc, const char **argv, const char *prefix) int cmd_commit(int argc, const char **argv, const char *prefix)
{ {
int header_len;
struct strbuf sb; struct strbuf sb;
const char *index_file, *reflog_msg; const char *index_file, *reflog_msg;
char *nl, *p; char *nl, *p;
unsigned char commit_sha1[20]; unsigned char commit_sha1[20];
struct ref_lock *ref_lock; struct ref_lock *ref_lock;
struct commit_list *parents = NULL, **pptr = &parents;
git_config(git_commit_config, NULL); git_config(git_commit_config, NULL);
@ -971,13 +951,6 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
return 1; return 1;
} }
/*
* The commit object
*/
strbuf_init(&sb, 0);
strbuf_addf(&sb, "tree %s\n",
sha1_to_hex(active_cache_tree->sha1));
/* Determine parents */ /* Determine parents */
if (initial_commit) { if (initial_commit) {
reflog_msg = "commit (initial)"; reflog_msg = "commit (initial)";
@ -991,13 +964,13 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
die("could not parse HEAD commit"); die("could not parse HEAD commit");
for (c = commit->parents; c; c = c->next) for (c = commit->parents; c; c = c->next)
add_parent(&sb, c->item->object.sha1); pptr = &commit_list_insert(c->item, pptr)->next;
} else if (in_merge) { } else if (in_merge) {
struct strbuf m; struct strbuf m;
FILE *fp; FILE *fp;
reflog_msg = "commit (merge)"; reflog_msg = "commit (merge)";
add_parent(&sb, head_sha1); pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
strbuf_init(&m, 0); strbuf_init(&m, 0);
fp = fopen(git_path("MERGE_HEAD"), "r"); fp = fopen(git_path("MERGE_HEAD"), "r");
if (fp == NULL) if (fp == NULL)
@ -1007,24 +980,18 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
unsigned char sha1[20]; unsigned char sha1[20];
if (get_sha1_hex(m.buf, sha1) < 0) if (get_sha1_hex(m.buf, sha1) < 0)
die("Corrupt MERGE_HEAD file (%s)", m.buf); die("Corrupt MERGE_HEAD file (%s)", m.buf);
add_parent(&sb, sha1); pptr = &commit_list_insert(lookup_commit(sha1), pptr)->next;
} }
fclose(fp); fclose(fp);
strbuf_release(&m); strbuf_release(&m);
} else { } else {
reflog_msg = "commit"; reflog_msg = "commit";
strbuf_addf(&sb, "parent %s\n", sha1_to_hex(head_sha1)); pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
} }
parents = reduce_heads(parents);
strbuf_addf(&sb, "author %s\n",
fmt_ident(author_name, author_email, author_date, IDENT_ERROR_ON_NO_NAME));
strbuf_addf(&sb, "committer %s\n", git_committer_info(IDENT_ERROR_ON_NO_NAME));
if (!is_encoding_utf8(git_commit_encoding))
strbuf_addf(&sb, "encoding %s\n", git_commit_encoding);
strbuf_addch(&sb, '\n');
/* Finally, get the commit message */ /* Finally, get the commit message */
header_len = sb.len; strbuf_init(&sb, 0);
if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) { if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
rollback_index_files(); rollback_index_files();
die("could not read commit message"); die("could not read commit message");
@ -1037,16 +1004,15 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
if (cleanup_mode != CLEANUP_NONE) if (cleanup_mode != CLEANUP_NONE)
stripspace(&sb, cleanup_mode == CLEANUP_ALL); stripspace(&sb, cleanup_mode == CLEANUP_ALL);
if (sb.len < header_len || message_is_empty(&sb, header_len)) { if (message_is_empty(&sb)) {
rollback_index_files(); rollback_index_files();
fprintf(stderr, "Aborting commit due to empty commit message.\n"); fprintf(stderr, "Aborting commit due to empty commit message.\n");
exit(1); exit(1);
} }
strbuf_addch(&sb, '\0');
if (is_encoding_utf8(git_commit_encoding) && !is_utf8(sb.buf))
fprintf(stderr, commit_utf8_warn);
if (write_sha1_file(sb.buf, sb.len - 1, commit_type, commit_sha1)) { if (commit_tree(sb.buf, active_cache_tree->sha1, parents, commit_sha1,
fmt_ident(author_name, author_email, author_date,
IDENT_ERROR_ON_NO_NAME))) {
rollback_index_files(); rollback_index_files();
die("failed to write commit object"); die("failed to write commit object");
} }
@ -1055,12 +1021,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
initial_commit ? NULL : head_sha1, initial_commit ? NULL : head_sha1,
0); 0);
nl = strchr(sb.buf + header_len, '\n'); nl = strchr(sb.buf, '\n');
if (nl) if (nl)
strbuf_setlen(&sb, nl + 1 - sb.buf); strbuf_setlen(&sb, nl + 1 - sb.buf);
else else
strbuf_addch(&sb, '\n'); strbuf_addch(&sb, '\n');
strbuf_remove(&sb, 0, header_len);
strbuf_insert(&sb, 0, reflog_msg, strlen(reflog_msg)); strbuf_insert(&sb, 0, reflog_msg, strlen(reflog_msg));
strbuf_insert(&sb, strlen(reflog_msg), ": ", 2); strbuf_insert(&sb, strlen(reflog_msg), ": ", 2);

View File

@ -693,7 +693,7 @@ static int merge_trivial(void)
parent->next = xmalloc(sizeof(struct commit_list *)); parent->next = xmalloc(sizeof(struct commit_list *));
parent->next->item = remoteheads->item; parent->next->item = remoteheads->item;
parent->next->next = NULL; parent->next->next = NULL;
commit_tree(merge_msg.buf, result_tree, parent, result_commit); commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);
finish(result_commit, "In-index merge"); finish(result_commit, "In-index merge");
drop_save(); drop_save();
return 0; return 0;
@ -722,7 +722,7 @@ static int finish_automerge(struct commit_list *common,
} }
free_commit_list(remoteheads); free_commit_list(remoteheads);
strbuf_addch(&merge_msg, '\n'); strbuf_addch(&merge_msg, '\n');
commit_tree(merge_msg.buf, result_tree, parents, result_commit); commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);
strbuf_addf(&buf, "Merge made by %s.", wt_strategy); strbuf_addf(&buf, "Merge made by %s.", wt_strategy);
finish(result_commit, buf.buf); finish(result_commit, buf.buf);
strbuf_release(&buf); strbuf_release(&buf);

View File

@ -17,7 +17,8 @@ extern int read_line_with_nul(char *buf, int size, FILE *file);
extern int fmt_merge_msg(int merge_summary, struct strbuf *in, extern int fmt_merge_msg(int merge_summary, struct strbuf *in,
struct strbuf *out); struct strbuf *out);
extern int commit_tree(const char *msg, unsigned char *tree, extern int commit_tree(const char *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret); struct commit_list *parents, unsigned char *ret,
const char *author);
extern int check_pager_config(const char *cmd); extern int check_pager_config(const char *cmd);
extern int cmd_add(int argc, const char **argv, const char *prefix); extern int cmd_add(int argc, const char **argv, const char *prefix);

View File

@ -60,4 +60,57 @@ test_expect_success 'merge c1 with c2, c3, c4, c5' '
test -f c5.c test -f c5.c
' '
test_expect_success 'setup' '
for i in A B C D E
do
echo $i > $i.c &&
git add $i.c &&
git commit -m $i &&
git tag $i
done &&
git reset --hard A &&
for i in F G H I
do
echo $i > $i.c &&
git add $i.c &&
git commit -m $i &&
git tag $i
done
'
test_expect_success 'merge E and I' '
git reset --hard A &&
git merge E I
'
test_expect_success 'verify merge result' '
test $(git rev-parse HEAD^1) = $(git rev-parse E) &&
test $(git rev-parse HEAD^2) = $(git rev-parse I)
'
test_expect_success 'add conflicts' '
git reset --hard E &&
echo foo > file.c &&
git add file.c &&
git commit -m E2 &&
git tag E2 &&
git reset --hard I &&
echo bar >file.c &&
git add file.c &&
git commit -m I2 &&
git tag I2
'
test_expect_success 'merge E2 and I2, causing a conflict and resolve it' '
git reset --hard A &&
test_must_fail git merge E2 I2 &&
echo baz > file.c &&
git add file.c &&
git commit -m "resolve conflict"
'
test_expect_success 'verify merge result' '
test $(git rev-parse HEAD^1) = $(git rev-parse E2) &&
test $(git rev-parse HEAD^2) = $(git rev-parse I2)
'
test_done test_done