From 2085b16aefdbb1dc081aa40c62eb8110a222731d Mon Sep 17 00:00:00 2001 From: Johan Herland Date: Mon, 15 Nov 2010 00:54:11 +0100 Subject: git notes merge: Handle real, non-conflicting notes merges This continuation of the 'git notes merge' implementation teaches notes-merge to properly do real merges between notes trees: Two diffs are performed, one from $base to $remote, and another from $base to $local. The paths in each diff are normalized to SHA1 object names. The two diffs are then consolidated into a single list of change pairs to be evaluated. Each change pair consist of: - The annotated object's SHA1 - The $base SHA1 (i.e. the common ancestor notes for this object) - The $local SHA1 (i.e. the current notes for this object) - The $remote SHA1 (i.e. the to-be-merged notes for this object) From the pair ($base -> $local, $base -> $remote), we can determine the merge result using regular 3-way rules. If conflicts are encountered in this process, we fail loudly and exit (conflict handling to be added in a future patch), If we can complete the merge without conflicts, the resulting notes tree is committed, and the current notes ref updated. The patch includes added testcases verifying that we can successfully do real conflict-less merges. This patch has been improved by the following contributions: - Jonathan Nieder: Future-proof by always checking add_note() return value - Stephen Boyd: Use test_commit - Jonathan Nieder: Use trace_printf(...) instead of OUTPUT(o, 5, ...) - Junio C Hamano: fixup minor style issues Thanks-to: Jonathan Nieder Thanks-to: Stephen Boyd Thanks-to: Junio C Hamano Signed-off-by: Johan Herland Signed-off-by: Junio C Hamano --- builtin/notes.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'builtin') diff --git a/builtin/notes.c b/builtin/notes.c index 32d8a24944..c7761b1140 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -765,6 +765,7 @@ static int merge(int argc, const char **argv, const char *prefix) { struct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT; unsigned char result_sha1[20]; + struct notes_tree *t; struct notes_merge_options o; int verbosity = 0, result; struct option options[] = { @@ -788,19 +789,23 @@ static int merge(int argc, const char **argv, const char *prefix) expand_notes_ref(&remote_ref); o.remote_ref = remote_ref.buf; - result = notes_merge(&o, result_sha1); + t = init_notes_check("merge"); strbuf_addf(&msg, "notes: Merged notes from %s into %s", remote_ref.buf, default_notes_ref()); - if (result == 0) { /* Merge resulted (trivially) in result_sha1 */ + o.commit_msg = msg.buf + 7; // skip "notes: " prefix + + result = notes_merge(&o, t, result_sha1); + + if (result >= 0) /* Merge resulted (trivially) in result_sha1 */ /* Update default notes ref with new commit */ update_ref(msg.buf, default_notes_ref(), result_sha1, NULL, 0, DIE_ON_ERR); - } else { + else /* TODO: */ - die("'git notes merge' cannot yet handle non-trivial merges!"); - } + die("'git notes merge' cannot yet handle conflicts!"); + free_notes(t); strbuf_release(&remote_ref); strbuf_release(&msg); return 0; -- cgit v1.2.3