{"thread":{"id":"40116","subject":"[PATCH v9 2/6] notes: extract enum notes_merge_strategy to notes-utils.h","startedAt":"2015-08-17T21:33:28Z","lastAt":"2015-08-18T00:15:13Z","messageCount":10,"participants":["Jacob Keller","Junio C Hamano"],"isPatch":true,"patchVersion":9,"patchTotal":6},"messages":[{"id":"268230","messageId":"1439847214-2980-1-git-send-email-jacob.e.keller@intel.com","threadId":"40116","inReplyTo":null,"subject":"[PATCH v9 0/6] implement notes.mergeStrategy","fromName":"Jacob Keller","fromEmail":"jacob.e.keller@intel.com","sentAt":"2015-08-17T21:33:28Z","receivedAt":"2015-08-17T21:33:28Z","isPatch":true,"sender":{"key":"jacob.e.keller@intel.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"From: Jacob Keller <jacob.keller@gmail.com>\n\nThis series implements mergeStrategy configuration options which take\nthe same value as --strategy. This series does not change the allowed\nrefs to merge from or to. There is a known limitation that you cannot\nmerge from refs outside of refs/notes (precluding the use of such refs\nas refs/tracking/origin/notes/ and so forth).\n\n- Changes since v8 -\n* drop the rewrite and merge option patches, since rewrite names are not\n  really equivalent to merge names (ours/theirs is flipped)\n* change docs on notes.<name>.mergeStrategy\n\nThis series does *not* deal with:\n* changes to which refs can be merged, init_notes_check already prevents\n  git-notes-merge into refs outside of refs/notes*\n* use of rewrite names for merge strategies, including even concatenate\n\nHopefully a future contributor will have some time to look at making\nre-write just use the notes merge instead of doing re-write by hand.\nThis would also potentially allow for manual merges. This series does\nnot begin down this road, since we do not want to limit what this future\nauthor is allowed to do with regards to rewrite and merge strategy\nnames.\n\nI think finally this series is good. It may be worth adding some\ntest_expect_failures around merging from refs/tracking/origin/notes if\nwe intend to ever allow notes merges from these sources.\n\nJacob Keller (6):\n  notes: document cat_sort_uniq rewriteMode\n  notes: extract enum notes_merge_strategy to notes-utils.h\n  note: extract parse_notes_merge_strategy to notes-utils\n  notes: add tests for --commit/--abort/--strategy exclusivity\n  notes: add notes.mergeStrategy option to select default strategy\n  notes: teach git-notes about notes.<name>.mergeStrategy option\n\n Documentation/config.txt              | 16 ++++++-\n Documentation/git-notes.txt           | 25 +++++++++--\n builtin/notes.c                       | 43 +++++++++++++------\n notes-merge.h                         | 10 ++---\n notes-utils.c                         | 18 ++++++++\n notes-utils.h                         |  9 ++++\n t/t3309-notes-merge-auto-resolve.sh   | 79 +++++++++++++++++++++++++++++++++++\n t/t3310-notes-merge-manual-resolve.sh | 12 ++++++\n 8 files changed, 187 insertions(+), 25 deletions(-)\n\n-- \n2.5.0.280.g4aaba03\n"},{"id":"268225","messageId":"1439847214-2980-2-git-send-email-jacob.e.keller@intel.com","threadId":"40116","inReplyTo":"1439847214-2980-1-git-send-email-jacob.e.keller@intel.com","subject":"[PATCH v9 1/6] notes: document cat_sort_uniq rewriteMode","fromName":"Jacob Keller","fromEmail":"jacob.e.keller@intel.com","sentAt":"2015-08-17T21:33:29Z","receivedAt":"2015-08-17T21:33:29Z","isPatch":true,"sender":{"key":"jacob.e.keller@intel.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"From: Jacob Keller <jacob.keller@gmail.com>\n\nTeach documentation about the cat_sort_uniq rewriteMode that got added\nat the same time as the equivalent merge strategy.\n\nSigned-off-by: Jacob Keller <jacob.keller@gmail.com>\n---\n Documentation/config.txt    | 4 ++--\n Documentation/git-notes.txt | 5 +++--\n 2 files changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 75ec02e8e90a..de67ad1fdedf 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1947,8 +1947,8 @@ notes.rewriteMode::\n \tWhen copying notes during a rewrite (see the\n \t\"notes.rewrite.<command>\" option), determines what to do if\n \tthe target commit already has a note.  Must be one of\n-\t`overwrite`, `concatenate`, or `ignore`.  Defaults to\n-\t`concatenate`.\n+\t`overwrite`, `concatenate`, `cat_sort_uniq`, or `ignore`.\n+\tDefaults to `concatenate`.\n +\n This setting can be overridden with the `GIT_NOTES_REWRITE_MODE`\n environment variable.\ndiff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt\nindex 851518d531b5..00c84be33ca9 100644\n--- a/Documentation/git-notes.txt\n+++ b/Documentation/git-notes.txt\n@@ -331,7 +331,8 @@ environment variable.\n notes.rewriteMode::\n \tWhen copying notes during a rewrite, what to do if the target\n \tcommit already has a note.  Must be one of `overwrite`,\n-\t`concatenate`, and `ignore`.  Defaults to `concatenate`.\n+\t`concatenate`, `cat_sort_uniq`, or `ignore`.  Defaults to\n+\t`concatenate`.\n +\n This setting can be overridden with the `GIT_NOTES_REWRITE_MODE`\n environment variable.\n@@ -368,7 +369,7 @@ does not match any refs is silently ignored.\n 'GIT_NOTES_REWRITE_MODE'::\n \tWhen copying notes during a rewrite, what to do if the target\n \tcommit already has a note.\n-\tMust be one of `overwrite`, `concatenate`, and `ignore`.\n+\tMust be one of `overwrite`, `concatenate`, `cat_sort_uniq`, or `ignore`.\n \tThis overrides the `core.rewriteMode` setting.\n \n 'GIT_NOTES_REWRITE_REF'::\n-- \n2.5.0.280.g4aaba03\n"},{"id":"268224","messageId":"1439847214-2980-3-git-send-email-jacob.e.keller@intel.com","threadId":"40116","inReplyTo":"1439847214-2980-1-git-send-email-jacob.e.keller@intel.com","subject":"[PATCH v9 2/6] notes: extract enum notes_merge_strategy to notes-utils.h","fromName":"Jacob Keller","fromEmail":"jacob.e.keller@intel.com","sentAt":"2015-08-17T21:33:30Z","receivedAt":"2015-08-17T21:33:30Z","isPatch":true,"sender":{"key":"jacob.e.keller@intel.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"From: Jacob Keller <jacob.keller@gmail.com>\n\nA future patch will extract parsing of the --strategy string into a\nhelper function in notes.c and will require the enumeration definition.\n\nSigned-off-by: Jacob Keller <jacob.keller@gmail.com>\n---\n notes-merge.h | 10 +++-------\n notes-utils.h |  8 ++++++++\n 2 files changed, 11 insertions(+), 7 deletions(-)\n\ndiff --git a/notes-merge.h b/notes-merge.h\nindex 1d01f6aacf54..0d890563b5f4 100644\n--- a/notes-merge.h\n+++ b/notes-merge.h\n@@ -1,6 +1,8 @@\n #ifndef NOTES_MERGE_H\n #define NOTES_MERGE_H\n \n+#include \"notes-utils.h\"\n+\n #define NOTES_MERGE_WORKTREE \"NOTES_MERGE_WORKTREE\"\n \n enum notes_merge_verbosity {\n@@ -13,13 +15,7 @@ struct notes_merge_options {\n \tconst char *remote_ref;\n \tstruct strbuf commit_msg;\n \tint verbosity;\n-\tenum {\n-\t\tNOTES_MERGE_RESOLVE_MANUAL = 0,\n-\t\tNOTES_MERGE_RESOLVE_OURS,\n-\t\tNOTES_MERGE_RESOLVE_THEIRS,\n-\t\tNOTES_MERGE_RESOLVE_UNION,\n-\t\tNOTES_MERGE_RESOLVE_CAT_SORT_UNIQ\n-\t} strategy;\n+\tenum notes_merge_strategy strategy;\n \tunsigned has_worktree:1;\n };\n \ndiff --git a/notes-utils.h b/notes-utils.h\nindex 890ddb33e13a..db5811e3f718 100644\n--- a/notes-utils.h\n+++ b/notes-utils.h\n@@ -19,6 +19,14 @@ void create_notes_commit(struct notes_tree *t, struct commit_list *parents,\n \n void commit_notes(struct notes_tree *t, const char *msg);\n \n+enum notes_merge_strategy {\n+\t\tNOTES_MERGE_RESOLVE_MANUAL = 0,\n+\t\tNOTES_MERGE_RESOLVE_OURS,\n+\t\tNOTES_MERGE_RESOLVE_THEIRS,\n+\t\tNOTES_MERGE_RESOLVE_UNION,\n+\t\tNOTES_MERGE_RESOLVE_CAT_SORT_UNIQ\n+};\n+\n struct notes_rewrite_cfg {\n \tstruct notes_tree **trees;\n \tconst char *cmd;\n-- \n2.5.0.280.g4aaba03\n"},{"id":"268226","messageId":"1439847214-2980-4-git-send-email-jacob.e.keller@intel.com","threadId":"40116","inReplyTo":"1439847214-2980-1-git-send-email-jacob.e.keller@intel.com","subject":"[PATCH v9 3/6] note: extract parse_notes_merge_strategy to notes-utils","fromName":"Jacob Keller","fromEmail":"jacob.e.keller@intel.com","sentAt":"2015-08-17T21:33:31Z","receivedAt":"2015-08-17T21:33:31Z","isPatch":true,"sender":{"key":"jacob.e.keller@intel.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"From: Jacob Keller <jacob.keller@gmail.com>\n\nCombining rewrite and notes-merge functionality has been left as an\nexercise for a future contributor.\n\nSigned-off-by: Jacob Keller <jacob.keller@gmail.com>\n---\n builtin/notes.c | 12 +-----------\n notes-utils.c   | 18 ++++++++++++++++++\n notes-utils.h   |  1 +\n 3 files changed, 20 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 042348082709..0e7aba98f4d7 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -797,17 +797,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \to.remote_ref = remote_ref.buf;\n \n \tif (strategy) {\n-\t\tif (!strcmp(strategy, \"manual\"))\n-\t\t\to.strategy = NOTES_MERGE_RESOLVE_MANUAL;\n-\t\telse if (!strcmp(strategy, \"ours\"))\n-\t\t\to.strategy = NOTES_MERGE_RESOLVE_OURS;\n-\t\telse if (!strcmp(strategy, \"theirs\"))\n-\t\t\to.strategy = NOTES_MERGE_RESOLVE_THEIRS;\n-\t\telse if (!strcmp(strategy, \"union\"))\n-\t\t\to.strategy = NOTES_MERGE_RESOLVE_UNION;\n-\t\telse if (!strcmp(strategy, \"cat_sort_uniq\"))\n-\t\t\to.strategy = NOTES_MERGE_RESOLVE_CAT_SORT_UNIQ;\n-\t\telse {\n+\t\tif (parse_notes_merge_strategy(strategy, &o.strategy)) {\n \t\t\terror(\"Unknown -s/--strategy: %s\", strategy);\n \t\t\tusage_with_options(git_notes_merge_usage, options);\n \t\t}\ndiff --git a/notes-utils.c b/notes-utils.c\nindex ccbf0737a34e..299e34bccc58 100644\n--- a/notes-utils.c\n+++ b/notes-utils.c\n@@ -54,6 +54,24 @@ void commit_notes(struct notes_tree *t, const char *msg)\n \tstrbuf_release(&buf);\n }\n \n+int parse_notes_merge_strategy(const char *v, enum notes_merge_strategy *s)\n+{\n+\tif (!strcmp(v, \"manual\"))\n+\t\t*s = NOTES_MERGE_RESOLVE_MANUAL;\n+\telse if (!strcmp(v, \"ours\"))\n+\t\t*s = NOTES_MERGE_RESOLVE_OURS;\n+\telse if (!strcmp(v, \"theirs\"))\n+\t\t*s = NOTES_MERGE_RESOLVE_THEIRS;\n+\telse if (!strcmp(v, \"union\"))\n+\t\t*s = NOTES_MERGE_RESOLVE_UNION;\n+\telse if (!strcmp(v, \"cat_sort_uniq\"))\n+\t\t*s = NOTES_MERGE_RESOLVE_CAT_SORT_UNIQ;\n+\telse\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n static combine_notes_fn parse_combine_notes_fn(const char *v)\n {\n \tif (!strcasecmp(v, \"overwrite\"))\ndiff --git a/notes-utils.h b/notes-utils.h\nindex db5811e3f718..fa538e1d9502 100644\n--- a/notes-utils.h\n+++ b/notes-utils.h\n@@ -37,6 +37,7 @@ struct notes_rewrite_cfg {\n \tint mode_from_env;\n };\n \n+int parse_notes_merge_strategy(const char *v, enum notes_merge_strategy *s);\n struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd);\n int copy_note_for_rewrite(struct notes_rewrite_cfg *c,\n \t\t\t  const unsigned char *from_obj, const unsigned char *to_obj);\n-- \n2.5.0.280.g4aaba03\n"},{"id":"268228","messageId":"1439847214-2980-5-git-send-email-jacob.e.keller@intel.com","threadId":"40116","inReplyTo":"1439847214-2980-1-git-send-email-jacob.e.keller@intel.com","subject":"[PATCH v9 4/6] notes: add tests for --commit/--abort/--strategy exclusivity","fromName":"Jacob Keller","fromEmail":"jacob.e.keller@intel.com","sentAt":"2015-08-17T21:33:32Z","receivedAt":"2015-08-17T21:33:32Z","isPatch":true,"sender":{"key":"jacob.e.keller@intel.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"From: Jacob Keller <jacob.keller@gmail.com>\n\nAdd new tests to ensure that --commit, --abort, and --strategy are\nmutually exclusive.\n\nSigned-off-by: Jacob Keller <jacob.keller@gmail.com>\n---\n t/t3310-notes-merge-manual-resolve.sh | 12 ++++++++++++\n 1 file changed, 12 insertions(+)\n\ndiff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh\nindex 195bb97f859d..d5572121da69 100755\n--- a/t/t3310-notes-merge-manual-resolve.sh\n+++ b/t/t3310-notes-merge-manual-resolve.sh\n@@ -314,6 +314,18 @@ y and z notes on 1st commit\n \n EOF\n \n+test_expect_success 'do not allow mixing --commit and --abort' '\n+\ttest_must_fail git notes merge --commit --abort\n+'\n+\n+test_expect_success 'do not allow mixing --commit and --strategy' '\n+\ttest_must_fail git notes merge --commit --strategy theirs\n+'\n+\n+test_expect_success 'do not allow mixing --abort and --strategy' '\n+\ttest_must_fail git notes merge --abort --strategy theirs\n+'\n+\n test_expect_success 'finalize conflicting merge (z => m)' '\n \t# Resolve conflicts and finalize merge\n \tcat >.git/NOTES_MERGE_WORKTREE/$commit_sha1 <<EOF &&\n-- \n2.5.0.280.g4aaba03\n"},{"id":"268229","messageId":"1439847214-2980-6-git-send-email-jacob.e.keller@intel.com","threadId":"40116","inReplyTo":"1439847214-2980-1-git-send-email-jacob.e.keller@intel.com","subject":"[PATCH v9 5/6] notes: add notes.mergeStrategy option to select default strategy","fromName":"Jacob Keller","fromEmail":"jacob.e.keller@intel.com","sentAt":"2015-08-17T21:33:33Z","receivedAt":"2015-08-17T21:33:33Z","isPatch":true,"sender":{"key":"jacob.e.keller@intel.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"From: Jacob Keller <jacob.keller@gmail.com>\n\nTeach git-notes about \"notes.mergeStrategy\" to select a general strategy\nfor all notes merges. This enables a user to always get expected merge\nstrategy such as \"cat_sort_uniq\" without having to pass the \"-s\" option\nmanually.\n\nSigned-off-by: Jacob Keller <jacob.keller@gmail.com>\n---\n Documentation/config.txt            |  6 ++++++\n Documentation/git-notes.txt         | 14 ++++++++++++-\n builtin/notes.c                     | 19 ++++++++++++++++--\n t/t3309-notes-merge-auto-resolve.sh | 40 +++++++++++++++++++++++++++++++++++++\n 4 files changed, 76 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex de67ad1fdedf..2ff3ed64a4d4 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1919,6 +1919,12 @@ mergetool.writeToTemp::\n mergetool.prompt::\n \tPrompt before each invocation of the merge resolution program.\n \n+notes.mergeStrategy::\n+\tWhich merge strategy to choose by default when resolving notes\n+\tconflicts.  Must be one of `manual`, `ours`, `theirs`, `union`, or\n+\t`cat_sort_uniq`.  Defaults to `manual`.  See \"NOTES MERGE STRATEGIES\"\n+\tsection of linkgit:git-notes[1] for more information on each strategy.\n+\n notes.displayRef::\n \tThe (fully qualified) refname from which to show notes when\n \tshowing commit messages.  The value of this variable can be set\ndiff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt\nindex 00c84be33ca9..71453d4a700f 100644\n--- a/Documentation/git-notes.txt\n+++ b/Documentation/git-notes.txt\n@@ -101,7 +101,7 @@ merge::\n \tany) into the current notes ref (called \"local\").\n +\n If conflicts arise and a strategy for automatically resolving\n-conflicting notes (see the -s/--strategy option) is not given,\n+conflicting notes (see the \"NOTES MERGE STRATEGIES\" section) is not given,\n the \"manual\" resolver is used. This resolver checks out the\n conflicting notes in a special worktree (`.git/NOTES_MERGE_WORKTREE`),\n and instructs the user to manually resolve the conflicts there.\n@@ -183,6 +183,7 @@ OPTIONS\n \tWhen merging notes, resolve notes conflicts using the given\n \tstrategy. The following strategies are recognized: \"manual\"\n \t(default), \"ours\", \"theirs\", \"union\" and \"cat_sort_uniq\".\n+\tThis option overrides the \"notes.mergeStrategy\" configuration setting.\n \tSee the \"NOTES MERGE STRATEGIES\" section below for more\n \tinformation on each notes merge strategy.\n \n@@ -247,6 +248,9 @@ When done, the user can either finalize the merge with\n 'git notes merge --commit', or abort the merge with\n 'git notes merge --abort'.\n \n+Users may select an automated merge strategy from among the following using\n+either -s/--strategy option or configuring notes.mergeStrategy accordingly:\n+\n \"ours\" automatically resolves conflicting notes in favor of the local\n version (i.e. the current notes ref).\n \n@@ -310,6 +314,14 @@ core.notesRef::\n \tThis setting can be overridden through the environment and\n \tcommand line.\n \n+notes.mergeStrategy::\n+\tWhich merge strategy to choose by default when resolving notes\n+\tconflicts.  Must be one of `manual`, `ours`, `theirs`, `union`, or\n+\t`cat_sort_uniq`.  Defaults to `manual`.  See \"NOTES MERGE STRATEGIES\"\n+\tsection above for more information on each strategy.\n++\n+This setting can be overridden by passing the `--strategy` option.\n+\n notes.displayRef::\n \tWhich ref (or refs, if a glob or specified more than once), in\n \taddition to the default set by `core.notesRef` or\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 0e7aba98f4d7..91f7a6547b0f 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -738,6 +738,19 @@ static int merge_commit(struct notes_merge_options *o)\n \treturn ret;\n }\n \n+static int git_config_get_notes_strategy(const char *key,\n+\t\t\t\t\t enum notes_merge_strategy *strategy)\n+{\n+\tconst char *value;\n+\n+\tif (git_config_get_string_const(key, &value))\n+\t\treturn 1;\n+\tif (parse_notes_merge_strategy(value, strategy))\n+\t\tgit_die_config(key, \"unknown notes merge strategy %s\", value);\n+\n+\treturn 0;\n+}\n+\n static int merge(int argc, const char **argv, const char *prefix)\n {\n \tstruct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT;\n@@ -796,15 +809,17 @@ static int merge(int argc, const char **argv, const char *prefix)\n \texpand_notes_ref(&remote_ref);\n \to.remote_ref = remote_ref.buf;\n \n+\tt = init_notes_check(\"merge\");\n+\n \tif (strategy) {\n \t\tif (parse_notes_merge_strategy(strategy, &o.strategy)) {\n \t\t\terror(\"Unknown -s/--strategy: %s\", strategy);\n \t\t\tusage_with_options(git_notes_merge_usage, options);\n \t\t}\n+\t} else {\n+\t\tgit_config_get_notes_strategy(\"notes.mergeStrategy\", &o.strategy);\n \t}\n \n-\tt = init_notes_check(\"merge\");\n-\n \tstrbuf_addf(&msg, \"notes: Merged notes from %s into %s\",\n \t\t    remote_ref.buf, default_notes_ref());\n \tstrbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip \"notes: \" */\ndiff --git a/t/t3309-notes-merge-auto-resolve.sh b/t/t3309-notes-merge-auto-resolve.sh\nindex 461fd84755d7..1cd047f8d75f 100755\n--- a/t/t3309-notes-merge-auto-resolve.sh\n+++ b/t/t3309-notes-merge-auto-resolve.sh\n@@ -298,6 +298,13 @@ test_expect_success 'merge z into y with invalid strategy => Fail/No changes' '\n \tverify_notes y y\n '\n \n+test_expect_success 'merge z into y with invalid configuration option => Fail/No changes' '\n+\tgit config core.notesRef refs/notes/y &&\n+\ttest_must_fail git -c notes.mergeStrategy=\"foo\" notes merge z &&\n+\t# Verify no changes (y)\n+\tverify_notes y y\n+'\n+\n cat <<EOF | sort >expect_notes_ours\n 68b8630d25516028bed862719855b3d6768d7833 $commit_sha15\n 5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14\n@@ -365,6 +372,17 @@ test_expect_success 'reset to pre-merge state (y)' '\n \tverify_notes y y\n '\n \n+test_expect_success 'merge z into y with \"ours\" configuration option => Non-conflicting 3-way merge' '\n+\tgit -c notes.mergeStrategy=\"ours\" notes merge z &&\n+\tverify_notes y ours\n+'\n+\n+test_expect_success 'reset to pre-merge state (y)' '\n+\tgit update-ref refs/notes/y refs/notes/y^1 &&\n+\t# Verify pre-merge state\n+\tverify_notes y y\n+'\n+\n cat <<EOF | sort >expect_notes_theirs\n 9b4b2c61f0615412da3c10f98ff85b57c04ec765 $commit_sha15\n 5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14\n@@ -432,6 +450,17 @@ test_expect_success 'reset to pre-merge state (y)' '\n \tverify_notes y y\n '\n \n+test_expect_success 'merge z into y with \"theirs\" strategy overriding configuration option \"ours\" => Non-conflicting 3-way merge' '\n+\tgit -c notes.mergeStrategy=\"ours\" notes merge --strategy=theirs z &&\n+\tverify_notes y theirs\n+'\n+\n+test_expect_success 'reset to pre-merge state (y)' '\n+\tgit update-ref refs/notes/y refs/notes/y^1 &&\n+\t# Verify pre-merge state\n+\tverify_notes y y\n+'\n+\n cat <<EOF | sort >expect_notes_union\n 7c4e546efd0fe939f876beb262ece02797880b54 $commit_sha15\n 5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14\n@@ -644,4 +673,15 @@ test_expect_success 'merge y into z with \"cat_sort_uniq\" strategy => Non-conflic\n \tverify_notes z cat_sort_uniq\n '\n \n+test_expect_success 'reset to pre-merge state (z)' '\n+\tgit update-ref refs/notes/z refs/notes/z^1 &&\n+\t# Verify pre-merge state\n+\tverify_notes z z\n+'\n+\n+test_expect_success 'merge y into z with \"cat_sort_uniq\" strategy configuration option => Non-conflicting 3-way merge' '\n+\tgit -c notes.mergeStrategy=\"cat_sort_uniq\" notes merge y &&\n+\tverify_notes z cat_sort_uniq\n+'\n+\n test_done\n-- \n2.5.0.280.g4aaba03\n"},{"id":"268227","messageId":"1439847214-2980-7-git-send-email-jacob.e.keller@intel.com","threadId":"40116","inReplyTo":"1439847214-2980-1-git-send-email-jacob.e.keller@intel.com","subject":"[PATCH v9 6/6] notes: teach git-notes about notes.<name>.mergeStrategy option","fromName":"Jacob Keller","fromEmail":"jacob.e.keller@intel.com","sentAt":"2015-08-17T21:33:34Z","receivedAt":"2015-08-17T21:33:34Z","isPatch":true,"sender":{"key":"jacob.e.keller@intel.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"From: Jacob Keller <jacob.keller@gmail.com>\n\nTeach notes about a new \"notes.<name>.mergeStrategy\" option for\nconfiguring the notes merge strategy when merging into\nrefs/notes/<name>. This option allows for the selection of merge\nstrategy for particular notes refs, rather than all notes ref merges, as\nuser may not want cat_sort_uniq for all refs, but only some. Note that\nthe <name> is the local reference we are merging into, not the remote\nref we merged from. The assumption is that users will mostly want to\nconfigure separate local ref merge strategies rather than strategies\ndepending on which remote ref they merge from.\n\nnotes.<name>.mergeStrategy overrides the general behavior as it is more\nspecific.\n\nSigned-off-by: Jacob Keller <jacob.keller@gmail.com>\n---\n Documentation/config.txt            |  6 ++++++\n Documentation/git-notes.txt         |  6 ++++++\n builtin/notes.c                     | 14 ++++++++++++-\n t/t3309-notes-merge-auto-resolve.sh | 39 +++++++++++++++++++++++++++++++++++++\n 4 files changed, 64 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 2ff3ed64a4d4..f60a9101df31 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1925,6 +1925,12 @@ notes.mergeStrategy::\n \t`cat_sort_uniq`.  Defaults to `manual`.  See \"NOTES MERGE STRATEGIES\"\n \tsection of linkgit:git-notes[1] for more information on each strategy.\n \n+notes.<name>.mergeStrategy::\n+\tWhich merge strategy to choose when doing a notes merge into\n+\trefs/notes/<name>.  This overrides the more general\n+\t\"notes.mergeStrategy\".  See the \"NOTES MERGE STRATEGIES\" section in\n+\tlinkgit:git-notes[1] for more information on the available strategies.\n+\n notes.displayRef::\n \tThe (fully qualified) refname from which to show notes when\n \tshowing commit messages.  The value of this variable can be set\ndiff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt\nindex 71453d4a700f..a9a916f360ec 100644\n--- a/Documentation/git-notes.txt\n+++ b/Documentation/git-notes.txt\n@@ -322,6 +322,12 @@ notes.mergeStrategy::\n +\n This setting can be overridden by passing the `--strategy` option.\n \n+notes.<name>.mergeStrategy::\n+\tWhich merge strategy to choose when doing a notes merge into\n+\trefs/notes/<name>.  This overrides the more general\n+\t\"notes.mergeStrategy\".  See the \"NOTES MERGE STRATEGIES\" section above\n+\tfor more information on each available strategy.\n+\n notes.displayRef::\n \tWhich ref (or refs, if a glob or specified more than once), in\n \taddition to the default set by `core.notesRef` or\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 91f7a6547b0f..3608c6478528 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -817,7 +817,19 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t\t\tusage_with_options(git_notes_merge_usage, options);\n \t\t}\n \t} else {\n-\t\tgit_config_get_notes_strategy(\"notes.mergeStrategy\", &o.strategy);\n+\t\tstruct strbuf merge_key = STRBUF_INIT;\n+\t\tconst char *short_ref = NULL;\n+\n+\t\tif (!skip_prefix(o.local_ref, \"refs/notes/\", &short_ref))\n+\t\t\tdie(\"BUG: local ref %s is outside of refs/notes/\",\n+\t\t\t    o.local_ref);\n+\n+\t\tstrbuf_addf(&merge_key, \"notes.%s.mergeStrategy\", short_ref);\n+\n+\t\tif (git_config_get_notes_strategy(merge_key.buf, &o.strategy))\n+\t\t\tgit_config_get_notes_strategy(\"notes.mergeStrategy\", &o.strategy);\n+\n+\t\tstrbuf_release(&merge_key);\n \t}\n \n \tstrbuf_addf(&msg, \"notes: Merged notes from %s into %s\",\ndiff --git a/t/t3309-notes-merge-auto-resolve.sh b/t/t3309-notes-merge-auto-resolve.sh\nindex 1cd047f8d75f..14c2adf970d7 100755\n--- a/t/t3309-notes-merge-auto-resolve.sh\n+++ b/t/t3309-notes-merge-auto-resolve.sh\n@@ -383,6 +383,17 @@ test_expect_success 'reset to pre-merge state (y)' '\n \tverify_notes y y\n '\n \n+test_expect_success 'merge z into y with \"ours\" per-ref configuration option => Non-conflicting 3-way merge' '\n+\tgit -c notes.y.mergeStrategy=\"ours\" notes merge z &&\n+\tverify_notes y ours\n+'\n+\n+test_expect_success 'reset to pre-merge state (y)' '\n+\tgit update-ref refs/notes/y refs/notes/y^1 &&\n+\t# Verify pre-merge state\n+\tverify_notes y y\n+'\n+\n cat <<EOF | sort >expect_notes_theirs\n 9b4b2c61f0615412da3c10f98ff85b57c04ec765 $commit_sha15\n 5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14\n@@ -534,6 +545,34 @@ test_expect_success 'reset to pre-merge state (y)' '\n \tverify_notes y y\n '\n \n+test_expect_success 'merge z into y with \"union\" strategy overriding per-ref configuration => Non-conflicting 3-way merge' '\n+\tgit -c notes.y.mergeStrategy=\"theirs\" notes merge --strategy=union z &&\n+\tverify_notes y union\n+'\n+\n+test_expect_success 'reset to pre-merge state (y)' '\n+\tgit update-ref refs/notes/y refs/notes/y^1 &&\n+\t# Verify pre-merge state\n+\tverify_notes y y\n+'\n+\n+test_expect_success 'merge z into y with \"union\" per-ref overriding general configuration => Non-conflicting 3-way merge' '\n+\tgit -c notes.y.mergeStrategy=\"union\" -c notes.mergeStrategy=\"theirs\" notes merge z &&\n+\tverify_notes y union\n+'\n+\n+test_expect_success 'reset to pre-merge state (y)' '\n+\tgit update-ref refs/notes/y refs/notes/y^1 &&\n+\t# Verify pre-merge state\n+\tverify_notes y y\n+'\n+\n+test_expect_success 'merge z into y with \"manual\" per-ref only checks specific ref configuration => Conflicting 3-way merge' '\n+\ttest_must_fail git -c notes.z.mergeStrategy=\"union\" notes merge z &&\n+\tgit notes merge --abort &&\n+\tverify_notes y y\n+'\n+\n cat <<EOF | sort >expect_notes_union2\n d682107b8bf7a7aea1e537a8d5cb6a12b60135f1 $commit_sha15\n 5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14\n-- \n2.5.0.280.g4aaba03\n"},{"id":"268233","messageId":"xmqqfv3hbl20.fsf@gitster.dls.corp.google.com","threadId":"40116","inReplyTo":"1439847214-2980-1-git-send-email-jacob.e.keller@intel.com","subject":"Re: [PATCH v9 0/6] implement notes.mergeStrategy","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-08-17T22:35:19Z","receivedAt":"2015-08-17T22:35:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"I just said v8 needs reroll in the latest \"What's cooking\"; after a\nquick read, this round looks very reasonable, as you said in your\ncover letter.  Will replace what has been queued.\n\nThanks.\n"},{"id":"268234","messageId":"xmqqbne5bkx7.fsf@gitster.dls.corp.google.com","threadId":"40116","inReplyTo":"1439847214-2980-4-git-send-email-jacob.e.keller@intel.com","subject":"Re: [PATCH v9 3/6] note: extract parse_notes_merge_strategy to notes-utils","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-08-17T22:38:12Z","receivedAt":"2015-08-17T22:38:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jacob Keller <jacob.e.keller@intel.com> writes:\n\n> From: Jacob Keller <jacob.keller@gmail.com>\n>\n> Combining rewrite and notes-merge functionality has been left as an\n> exercise for a future contributor.\n\nThis comment is probably unnecessary; we haven't even established if\nsuch a combination is desirable AFAICT in the discussion.\n\nThe patch itself looks very straightforward and obviously good.\n\nThanks.\n\n>\n> Signed-off-by: Jacob Keller <jacob.keller@gmail.com>\n> ---\n>  builtin/notes.c | 12 +-----------\n>  notes-utils.c   | 18 ++++++++++++++++++\n>  notes-utils.h   |  1 +\n>  3 files changed, 20 insertions(+), 11 deletions(-)\n>\n> diff --git a/builtin/notes.c b/builtin/notes.c\n> index 042348082709..0e7aba98f4d7 100644\n> --- a/builtin/notes.c\n> +++ b/builtin/notes.c\n> @@ -797,17 +797,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n>  \to.remote_ref = remote_ref.buf;\n>  \n>  \tif (strategy) {\n> -\t\tif (!strcmp(strategy, \"manual\"))\n> -\t\t\to.strategy = NOTES_MERGE_RESOLVE_MANUAL;\n> -\t\telse if (!strcmp(strategy, \"ours\"))\n> -\t\t\to.strategy = NOTES_MERGE_RESOLVE_OURS;\n> -\t\telse if (!strcmp(strategy, \"theirs\"))\n> -\t\t\to.strategy = NOTES_MERGE_RESOLVE_THEIRS;\n> -\t\telse if (!strcmp(strategy, \"union\"))\n> -\t\t\to.strategy = NOTES_MERGE_RESOLVE_UNION;\n> -\t\telse if (!strcmp(strategy, \"cat_sort_uniq\"))\n> -\t\t\to.strategy = NOTES_MERGE_RESOLVE_CAT_SORT_UNIQ;\n> -\t\telse {\n> +\t\tif (parse_notes_merge_strategy(strategy, &o.strategy)) {\n>  \t\t\terror(\"Unknown -s/--strategy: %s\", strategy);\n>  \t\t\tusage_with_options(git_notes_merge_usage, options);\n>  \t\t}\n> diff --git a/notes-utils.c b/notes-utils.c\n> index ccbf0737a34e..299e34bccc58 100644\n> --- a/notes-utils.c\n> +++ b/notes-utils.c\n> @@ -54,6 +54,24 @@ void commit_notes(struct notes_tree *t, const char *msg)\n>  \tstrbuf_release(&buf);\n>  }\n>  \n> +int parse_notes_merge_strategy(const char *v, enum notes_merge_strategy *s)\n> +{\n> +\tif (!strcmp(v, \"manual\"))\n> +\t\t*s = NOTES_MERGE_RESOLVE_MANUAL;\n> +\telse if (!strcmp(v, \"ours\"))\n> +\t\t*s = NOTES_MERGE_RESOLVE_OURS;\n> +\telse if (!strcmp(v, \"theirs\"))\n> +\t\t*s = NOTES_MERGE_RESOLVE_THEIRS;\n> +\telse if (!strcmp(v, \"union\"))\n> +\t\t*s = NOTES_MERGE_RESOLVE_UNION;\n> +\telse if (!strcmp(v, \"cat_sort_uniq\"))\n> +\t\t*s = NOTES_MERGE_RESOLVE_CAT_SORT_UNIQ;\n> +\telse\n> +\t\treturn -1;\n> +\n> +\treturn 0;\n> +}\n> +\n>  static combine_notes_fn parse_combine_notes_fn(const char *v)\n>  {\n>  \tif (!strcasecmp(v, \"overwrite\"))\n> diff --git a/notes-utils.h b/notes-utils.h\n> index db5811e3f718..fa538e1d9502 100644\n> --- a/notes-utils.h\n> +++ b/notes-utils.h\n> @@ -37,6 +37,7 @@ struct notes_rewrite_cfg {\n>  \tint mode_from_env;\n>  };\n>  \n> +int parse_notes_merge_strategy(const char *v, enum notes_merge_strategy *s);\n>  struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd);\n>  int copy_note_for_rewrite(struct notes_rewrite_cfg *c,\n>  \t\t\t  const unsigned char *from_obj, const unsigned char *to_obj);\n"},{"id":"268239","messageId":"CA+P7+xohUHsJfxjKMTkOfmAmRNPJ5S-z4HgtcGZB0VmYDf5Oyg@mail.gmail.com","threadId":"40116","inReplyTo":"xmqqbne5bkx7.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v9 3/6] note: extract parse_notes_merge_strategy to notes-utils","fromName":"Jacob Keller","fromEmail":"jacob.keller@gmail.com","sentAt":"2015-08-18T00:15:13Z","receivedAt":"2015-08-18T00:15:13Z","isPatch":true,"sender":{"key":"jacob.keller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"On Mon, Aug 17, 2015 at 3:38 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Jacob Keller <jacob.e.keller@intel.com> writes:\n>\n>> From: Jacob Keller <jacob.keller@gmail.com>\n>>\n>> Combining rewrite and notes-merge functionality has been left as an\n>> exercise for a future contributor.\n>\n> This comment is probably unnecessary; we haven't even established if\n> such a combination is desirable AFAICT in the discussion.\n>\n> The patch itself looks very straightforward and obviously good.\n>\n> Thanks.\n>\n\nFeel free to fix that up if you want. Probably easier than me\nrespinning the whole series.\n\nRegards,\nJake\n"}]}