{"thread":{"id":"40048","subject":"[PATCH v6] notes: handle multiple worktrees","startedAt":"2015-08-10T17:43:50Z","lastAt":"2015-08-10T17:48:33Z","messageCount":2,"participants":["David Turner"],"isPatch":true,"patchVersion":6,"patchTotal":null},"messages":[{"id":"267780","messageId":"1439228630-25146-1-git-send-email-dturner@twopensource.com","threadId":"40048","inReplyTo":null,"subject":"[PATCH v6] notes: handle multiple worktrees","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-08-10T17:43:50Z","receivedAt":"2015-08-10T17:43:50Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Before creating NOTES_MERGE_REF, check NOTES_MERGE_REF using\nfind_shared_symref and die if we find one.  This prevents simultaneous\nmerges to the same notes branch from different worktrees.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n\nThis reroll addresses Eric Sunshine's comments on v5.\n\n---\n builtin/notes.c                  |  6 ++++\n t/t3320-notes-merge-worktrees.sh | 72 ++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 78 insertions(+)\n create mode 100755 t/t3320-notes-merge-worktrees.sh\n\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 63f95fc..0423480 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -19,6 +19,7 @@\n #include \"string-list.h\"\n #include \"notes-merge.h\"\n #include \"notes-utils.h\"\n+#include \"branch.h\"\n \n static const char * const git_notes_usage[] = {\n \tN_(\"git notes [--ref <notes-ref>] [list [<object>]]\"),\n@@ -825,10 +826,15 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t\tupdate_ref(msg.buf, default_notes_ref(), result_sha1, NULL,\n \t\t\t   0, UPDATE_REFS_DIE_ON_ERR);\n \telse { /* Merge has unresolved conflicts */\n+\t\tchar *existing;\n \t\t/* Update .git/NOTES_MERGE_PARTIAL with partial merge result */\n \t\tupdate_ref(msg.buf, \"NOTES_MERGE_PARTIAL\", result_sha1, NULL,\n \t\t\t   0, UPDATE_REFS_DIE_ON_ERR);\n \t\t/* Store ref-to-be-updated into .git/NOTES_MERGE_REF */\n+\t\texisting = find_shared_symref(\"NOTES_MERGE_REF\", default_notes_ref());\n+\t\tif (existing)\n+\t\t\tdie(_(\"A notes merge into %s is already in-progress at %s\"),\n+\t\t\t    default_notes_ref(), existing);\n \t\tif (create_symref(\"NOTES_MERGE_REF\", default_notes_ref(), NULL))\n \t\t\tdie(\"Failed to store link to current notes ref (%s)\",\n \t\t\t    default_notes_ref());\ndiff --git a/t/t3320-notes-merge-worktrees.sh b/t/t3320-notes-merge-worktrees.sh\nnew file mode 100755\nindex 0000000..a7beef2\n--- /dev/null\n+++ b/t/t3320-notes-merge-worktrees.sh\n@@ -0,0 +1,72 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2015 Twitter, Inc\n+#\n+\n+test_description='Test merging of notes trees in multiple worktrees'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup commit' '\n+\ttest_commit tantrum\n+'\n+\n+commit_tantrum=$(git rev-parse tantrum^{commit})\n+\n+test_expect_success 'setup notes ref (x)' '\n+\tgit config core.notesRef refs/notes/x &&\n+\tgit notes add -m \"x notes on tantrum\" tantrum\n+'\n+\n+test_expect_success 'setup local branch (y)' '\n+\tgit update-ref refs/notes/y refs/notes/x &&\n+\tgit config core.notesRef refs/notes/y &&\n+\tgit notes remove tantrum\n+'\n+\n+test_expect_success 'setup remote branch (z)' '\n+\tgit update-ref refs/notes/z refs/notes/x &&\n+\tgit config core.notesRef refs/notes/z &&\n+\tgit notes add -f -m \"conflicting notes on tantrum\" tantrum\n+'\n+\n+test_expect_success 'modify notes ref ourselves (x)' '\n+\tgit config core.notesRef refs/notes/x &&\n+\tgit notes add -f -m \"more conflicting notes on tantrum\" tantrum\n+'\n+\n+test_expect_success 'create some new worktrees' '\n+\tgit worktree add -b newbranch worktree master &&\n+\tgit worktree add -b newbranch2 worktree2 master\n+'\n+\n+test_expect_success 'merge z into y fails and sets NOTES_MERGE_REF' '\n+\tgit config core.notesRef refs/notes/y &&\n+\ttest_must_fail git notes merge z &&\n+\techo \"ref: refs/notes/y\" > expect &&\n+\ttest_cmp .git/NOTES_MERGE_REF expect\n+'\n+\n+test_expect_success 'merge z into y while mid-merge in another workdir fails' '\n+\t(\n+\t\tcd worktree &&\n+\t\tgit config core.notesRef refs/notes/y &&\n+\t\ttest_must_fail git notes merge z 2>err &&\n+\t\tgrep \"A notes merge into refs/notes/y is already in-progress at\" err\n+\t) &&\n+\ttest_path_is_missing .git/worktrees/worktree/NOTES_MERGE_REF\n+'\n+\n+test_expect_success 'merge z into x while mid-merge on y succeeds' '\n+\t(\n+\t\tcd worktree2 &&\n+\t\tgit config core.notesRef refs/notes/x &&\n+\t\ttest_must_fail git notes merge z 2>&1 >out &&\n+\t\tgrep \"Automatic notes merge failed\" out &&\n+\t\tgrep -v \"A notes merge into refs/notes/x is already in-progress in\" out\n+\t) &&\n+\techo \"ref: refs/notes/x\" > expect &&\n+\ttest_cmp .git/worktrees/worktree2/NOTES_MERGE_REF expect\n+'\n+\n+test_done\n-- \n2.0.4.315.gad8727a-twtrsrc\n"},{"id":"267782","messageId":"1439228913.5283.0.camel@twopensource.com","threadId":"40048","inReplyTo":"1439228630-25146-1-git-send-email-dturner@twopensource.com","subject":"Re: [PATCH v6] notes: handle multiple worktrees","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-08-10T17:48:33Z","receivedAt":"2015-08-10T17:48:33Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Sorry, that should have included the first patch as well.  Will re-send\nas .v7\n\nOn Mon, 2015-08-10 at 13:43 -0400, David Turner wrote:\n> Before creating NOTES_MERGE_REF, check NOTES_MERGE_REF using\n> find_shared_symref and die if we find one.  This prevents simultaneous\n> merges to the same notes branch from different worktrees.\n> \n> Signed-off-by: David Turner <dturner@twopensource.com>\n> ---\n> \n> This reroll addresses Eric Sunshine's comments on v5.\n> \n> ---\n>  builtin/notes.c                  |  6 ++++\n>  t/t3320-notes-merge-worktrees.sh | 72 ++++++++++++++++++++++++++++++++++++++++\n>  2 files changed, 78 insertions(+)\n>  create mode 100755 t/t3320-notes-merge-worktrees.sh\n> \n> diff --git a/builtin/notes.c b/builtin/notes.c\n> index 63f95fc..0423480 100644\n> --- a/builtin/notes.c\n> +++ b/builtin/notes.c\n> @@ -19,6 +19,7 @@\n>  #include \"string-list.h\"\n>  #include \"notes-merge.h\"\n>  #include \"notes-utils.h\"\n> +#include \"branch.h\"\n>  \n>  static const char * const git_notes_usage[] = {\n>  \tN_(\"git notes [--ref <notes-ref>] [list [<object>]]\"),\n> @@ -825,10 +826,15 @@ static int merge(int argc, const char **argv, const char *prefix)\n>  \t\tupdate_ref(msg.buf, default_notes_ref(), result_sha1, NULL,\n>  \t\t\t   0, UPDATE_REFS_DIE_ON_ERR);\n>  \telse { /* Merge has unresolved conflicts */\n> +\t\tchar *existing;\n>  \t\t/* Update .git/NOTES_MERGE_PARTIAL with partial merge result */\n>  \t\tupdate_ref(msg.buf, \"NOTES_MERGE_PARTIAL\", result_sha1, NULL,\n>  \t\t\t   0, UPDATE_REFS_DIE_ON_ERR);\n>  \t\t/* Store ref-to-be-updated into .git/NOTES_MERGE_REF */\n> +\t\texisting = find_shared_symref(\"NOTES_MERGE_REF\", default_notes_ref());\n> +\t\tif (existing)\n> +\t\t\tdie(_(\"A notes merge into %s is already in-progress at %s\"),\n> +\t\t\t    default_notes_ref(), existing);\n>  \t\tif (create_symref(\"NOTES_MERGE_REF\", default_notes_ref(), NULL))\n>  \t\t\tdie(\"Failed to store link to current notes ref (%s)\",\n>  \t\t\t    default_notes_ref());\n> diff --git a/t/t3320-notes-merge-worktrees.sh b/t/t3320-notes-merge-worktrees.sh\n> new file mode 100755\n> index 0000000..a7beef2\n> --- /dev/null\n> +++ b/t/t3320-notes-merge-worktrees.sh\n> @@ -0,0 +1,72 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2015 Twitter, Inc\n> +#\n> +\n> +test_description='Test merging of notes trees in multiple worktrees'\n> +\n> +. ./test-lib.sh\n> +\n> +test_expect_success 'setup commit' '\n> +\ttest_commit tantrum\n> +'\n> +\n> +commit_tantrum=$(git rev-parse tantrum^{commit})\n> +\n> +test_expect_success 'setup notes ref (x)' '\n> +\tgit config core.notesRef refs/notes/x &&\n> +\tgit notes add -m \"x notes on tantrum\" tantrum\n> +'\n> +\n> +test_expect_success 'setup local branch (y)' '\n> +\tgit update-ref refs/notes/y refs/notes/x &&\n> +\tgit config core.notesRef refs/notes/y &&\n> +\tgit notes remove tantrum\n> +'\n> +\n> +test_expect_success 'setup remote branch (z)' '\n> +\tgit update-ref refs/notes/z refs/notes/x &&\n> +\tgit config core.notesRef refs/notes/z &&\n> +\tgit notes add -f -m \"conflicting notes on tantrum\" tantrum\n> +'\n> +\n> +test_expect_success 'modify notes ref ourselves (x)' '\n> +\tgit config core.notesRef refs/notes/x &&\n> +\tgit notes add -f -m \"more conflicting notes on tantrum\" tantrum\n> +'\n> +\n> +test_expect_success 'create some new worktrees' '\n> +\tgit worktree add -b newbranch worktree master &&\n> +\tgit worktree add -b newbranch2 worktree2 master\n> +'\n> +\n> +test_expect_success 'merge z into y fails and sets NOTES_MERGE_REF' '\n> +\tgit config core.notesRef refs/notes/y &&\n> +\ttest_must_fail git notes merge z &&\n> +\techo \"ref: refs/notes/y\" > expect &&\n> +\ttest_cmp .git/NOTES_MERGE_REF expect\n> +'\n> +\n> +test_expect_success 'merge z into y while mid-merge in another workdir fails' '\n> +\t(\n> +\t\tcd worktree &&\n> +\t\tgit config core.notesRef refs/notes/y &&\n> +\t\ttest_must_fail git notes merge z 2>err &&\n> +\t\tgrep \"A notes merge into refs/notes/y is already in-progress at\" err\n> +\t) &&\n> +\ttest_path_is_missing .git/worktrees/worktree/NOTES_MERGE_REF\n> +'\n> +\n> +test_expect_success 'merge z into x while mid-merge on y succeeds' '\n> +\t(\n> +\t\tcd worktree2 &&\n> +\t\tgit config core.notesRef refs/notes/x &&\n> +\t\ttest_must_fail git notes merge z 2>&1 >out &&\n> +\t\tgrep \"Automatic notes merge failed\" out &&\n> +\t\tgrep -v \"A notes merge into refs/notes/x is already in-progress in\" out\n> +\t) &&\n> +\techo \"ref: refs/notes/x\" > expect &&\n> +\ttest_cmp .git/worktrees/worktree2/NOTES_MERGE_REF expect\n> +'\n> +\n> +test_done\n"}]}