notes: allow merging from arbitrary references

Create a new expansion function, expand_loose_notes_ref which will first check whether the ref can be found using get_sha1. If it can't be found then it will fallback to using expand_notes_ref. The content of the strbuf will not be changed if the notes ref can be located using get_sha1. Otherwise, it may be updated as done by expand_notes_ref. Since we now support merging from non-notes refs, remove the test case associated with that behavior. Add a test case for merging from a non-notes ref. Signed-off-by: Jacob Keller <jacob.keller@gmail.com> Reviewed-by: Johan Herland <johan@herland.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jacob Keller committed Dec 29, 2015 at 14:40 UTC b3715b75226668e26f1f2abe7e2f93cdbbf6e2f5
4 files changed +29 -12
builtin/notes.c
+1 -1
@@ -806,7 +806,7 @@ static int merge(int argc, const char **argv, const char *prefix)
806
807 o.local_ref = default_notes_ref();
808 strbuf_addstr(&remote_ref, argv[0]);
809 - expand_notes_ref(&remote_ref);
809 + expand_loose_notes_ref(&remote_ref);
810 o.remote_ref = remote_ref.buf;
811
812 t = init_notes_check("merge");
notes.c
+10
@@ -1303,3 +1303,13 @@ void expand_notes_ref(struct strbuf *sb)
1303 else
1304 strbuf_insert(sb, 0, "refs/notes/", 11);
1305 }
1306 +
1307 +void expand_loose_notes_ref(struct strbuf *sb)
1308 +{
1309 + unsigned char object[20];
1310 +
1311 + if (get_sha1(sb->buf, object)) {
1312 + /* fallback to expand_notes_ref */
1313 + expand_notes_ref(sb);
1314 + }
1315 +}
notes.h
+7
@@ -294,4 +294,11 @@ void string_list_add_refs_from_colon_sep(struct string_list *list,
294 /* Expand inplace a note ref like "foo" or "notes/foo" into "refs/notes/foo" */
295 void expand_notes_ref(struct strbuf *sb);
296
297 +/*
298 + * Similar to expand_notes_ref, but will check whether the ref can be located
299 + * via get_sha1 first, and only falls back to expand_notes_ref in the case
300 + * where get_sha1 fails.
301 + */
302 +void expand_loose_notes_ref(struct strbuf *sb);
303 +
304 #endif
t/t3308-notes-merge.sh
+11 -11
@@ -18,7 +18,9 @@ test_expect_success setup '
18 git notes add -m "Notes on 1st commit" 1st &&
19 git notes add -m "Notes on 2nd commit" 2nd &&
20 git notes add -m "Notes on 3rd commit" 3rd &&
21 - git notes add -m "Notes on 4th commit" 4th
21 + git notes add -m "Notes on 4th commit" 4th &&
22 + # Copy notes to remote-notes
23 + git fetch . refs/notes/*:refs/remote-notes/origin/*
24 '
25
26 commit_sha1=$(git rev-parse 1st^{commit})
@@ -66,7 +68,9 @@ test_expect_success 'verify initial notes (x)' '
68 '
69
70 cp expect_notes_x expect_notes_y
71 +cp expect_notes_x expect_notes_v
72 cp expect_log_x expect_log_y
73 +cp expect_log_x expect_log_v
74
75 test_expect_success 'fail to merge empty notes ref into empty notes ref (z => y)' '
76 test_must_fail git -c "core.notesRef=refs/notes/y" notes merge z
@@ -84,16 +88,12 @@ test_expect_success 'fail to merge into various non-notes refs' '
88 test_must_fail git -c "core.notesRef=refs/notes/foo^{bar" notes merge x
89 '
90
87 -test_expect_success 'fail to merge various non-note-trees' '
88 - git config core.notesRef refs/notes/y &&
89 - test_must_fail git notes merge refs/notes &&
90 - test_must_fail git notes merge refs/notes/ &&
91 - test_must_fail git notes merge refs/notes/dir &&
92 - test_must_fail git notes merge refs/notes/dir/ &&
93 - test_must_fail git notes merge refs/heads/master &&
94 - test_must_fail git notes merge x: &&
95 - test_must_fail git notes merge x:foo &&
96 - test_must_fail git notes merge foo^{bar
91 +test_expect_success 'merge non-notes ref into empty notes ref (remote-notes/origin/x => v)' '
92 + git config core.notesRef refs/notes/v &&
93 + git notes merge refs/remote-notes/origin/x &&
94 + verify_notes v &&
95 + # refs/remote-notes/origin/x and v should point to the same notes commit
96 + test "$(git rev-parse refs/remote-notes/origin/x)" = "$(git rev-parse refs/notes/v)"
97 '
98
99 test_expect_success 'merge notes into empty notes ref (x => y)' '