{"thread":{"id":"43090","subject":"Re: [PATCH] merge-recursive: configurable 'merge' program","startedAt":"2006-12-04T11:36:18Z","lastAt":"2006-12-05T15:01:50Z","messageCount":8,"participants":["Johannes Schindelin","Sam Vilain","Jakub Narebski"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"294912","messageId":"20061204235647.9BA8B139B0E@magnus.utsl.gen.nz","threadId":"43090","inReplyTo":null,"subject":"[PATCH] merge-recursive: configurable 'merge' program","fromName":"Sam Vilain","fromEmail":"sam@vilain.net","sentAt":"2006-12-04T11:36:18Z","receivedAt":"2006-12-04T11:36:18Z","isPatch":true,"sender":{"key":"sam@vilain.net","avatar":"https://gravatar.com/avatar/8fc840ca854dbf6f7065b4335e3b934951c1dca3b11db688e95e471901f8f4a8?d=mp&s=160"},"body":"For those who like to spawn interactive merge tools on a merge failure\nor otherwise run some kind of script, allow a \"merge.tool\" repo-config\noption that will take arguments as merge(1) does.\n---\n merge-recursive.c |   23 ++++++++++++++++++++++-\n 1 files changed, 22 insertions(+), 1 deletions(-)\n\nHere's the script I use:\n\n#!/bin/sh\n\noutput=`mktemp -p . .merge_file_XXXXXX`\nbranch1=\"$7\"\nbranch2=\"$9\"\nancestor=\"$8\"\n\ncp $branch1 $output\n\nif merge -L $2 -L $4 -L $6 $output $ancestor $branch2\nthen\n    mv $output $branch1\n    exit 0\nelse\n\n    rm $output\n\n    emacs --eval \"(ediff-merge-files-with-ancestor \\\"${branch1}\\\" \n\\\"${branch2}\\\" \\\"${ancestor}\\\" nil \\\"${output}\\\")\"\n\n    if [ -s \"$output\" ]\n    then\n        mv $output $branch1\n        exit 0\n    else\n        exit 1\n    fi\nfi\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 5a70a5c..0e2da57 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -627,6 +627,8 @@ static char *git_unpack_file(const unsigned char *sha1, char *path)\n \treturn path;\n }\n \n+static char* merge_tool = \"merge\";\n+\n static struct merge_file_info merge_file(struct diff_filespec *o,\n \t\tstruct diff_filespec *a, struct diff_filespec *b,\n \t\tconst char *branch1, const char *branch2)\n@@ -661,12 +663,14 @@ static struct merge_file_info merge_file(struct diff_filespec *o,\n \t\t\tchar src1[PATH_MAX];\n \t\t\tchar src2[PATH_MAX];\n \t\t\tconst char *argv[] = {\n-\t\t\t\t\"merge\", \"-L\", NULL, \"-L\", NULL, \"-L\", NULL,\n+\t\t\t\tNULL, \"-L\", NULL, \"-L\", NULL, \"-L\", NULL,\n \t\t\t\tNULL, NULL, NULL,\n \t\t\t\tNULL\n \t\t\t};\n \t\t\tchar *la, *lb, *lo;\n \n+\t\t\targv[0] = merge_tool;\n+\n \t\t\tgit_unpack_file(o->sha1, orig);\n \t\t\tgit_unpack_file(a->sha1, src1);\n \t\t\tgit_unpack_file(b->sha1, src2);\n@@ -1134,6 +1138,21 @@ static int process_entry(const char *path, struct stage_data *entry,\n \treturn clean_merge;\n }\n \n+static int\n+git_merge_config(const char *key, const char *val)\n+{\n+\tchar merge_key[] = \"merge.\";\n+\tif (strncmp( key, merge_key, sizeof merge_key - 1 ))\n+\t\treturn 0;\n+\tkey += sizeof merge_key - 1;\n+\n+\tif (!strcmp( \"tool\", key )) {\n+\t    merge_tool = xstrdup(val);\n+\t}\n+\n+\treturn 0;\n+}\n+\n static int merge_trees(struct tree *head,\n \t\t       struct tree *merge,\n \t\t       struct tree *common,\n@@ -1148,6 +1167,8 @@ static int merge_trees(struct tree *head,\n \t\treturn 1;\n \t}\n \n+\tgit_config( git_merge_config );\n+\n \tcode = git_merge_trees(index_only, common, head, merge);\n \n \tif (code != 0)\n-- \n1.4.4.1.ge918e-dirty\n"},{"id":"297104","messageId":"el2cpj$cna$1@sea.gmane.org","threadId":"43090","inReplyTo":"20061204235647.9BA8B139B0E@magnus.utsl.gen.nz","subject":"Re: [PATCH] merge-recursive: configurable 'merge' program","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-12-05T00:01:55Z","receivedAt":"2006-12-05T00:01:55Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Sam Vilain wrote:\n\n> For those who like to spawn interactive merge tools on a merge failure\n> or otherwise run some kind of script, allow a \"merge.tool\" repo-config\n> option that will take arguments as merge(1) does.\n\nHow it goes together with merge-recursive rewrite using built-in merge tool\nfrom xdiff, xdl_merge?\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n\n"},{"id":"294877","messageId":"Pine.LNX.4.63.0612050836570.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43090","inReplyTo":"el2cpj$cna$1@sea.gmane.org","subject":"Re: [PATCH] merge-recursive: configurable 'merge' program","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-05T07:38:21Z","receivedAt":"2006-12-05T07:38:21Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 5 Dec 2006, Jakub Narebski wrote:\n\n> Sam Vilain wrote:\n> \n> > For those who like to spawn interactive merge tools on a merge failure\n> > or otherwise run some kind of script, allow a \"merge.tool\" repo-config\n> > option that will take arguments as merge(1) does.\n> \n> How it goes together with merge-recursive rewrite using built-in merge tool\n> >from xdiff, xdl_merge?\n\nNot a big problem. If people like Sam's patch, it is easy to integrate, \nsince it only means that if merge.tool is set to something non-empty, \nxdl_merge is not called, but the merge.tool is forked.\n\nCiao,\nDscho\n"},{"id":"296737","messageId":"200612051123.33210.jnareb@gmail.com","threadId":"43090","inReplyTo":"Pine.LNX.4.63.0612050836570.28348@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] merge-recursive: configurable 'merge' program","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-12-05T10:23:32Z","receivedAt":"2006-12-05T10:23:32Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Johannes Schindelin wrote:\n> \n> On Tue 5 Dec 2006 Jakub Narebski wrote:\n> \n>> Sam Vilain wrote:\n>> \n>>> For those who like to spawn interactive merge tools on a merge failure\n>>> or otherwise run some kind of script allow a \"merge.tool\" repo-config\n>>> option that will take arguments as merge(1) does.\n>> \n>> How it goes together with merge-recursive rewrite using built-in merge tool\n>> from xdiff xdl_merge?\n> \n> Not a big problem. If people like Sam's patch it is easy to integrate \n> since it only means that if merge.tool is set to something non-empty \n> xdl_merge is not called but the merge.tool is forked.\n\nGood idea. By the way, is it replacement for RCS merge, i.e. is it\nfile-level merge tool, merge.onefile rather than merge.tool? What happens\nif there are multiple merge [contents] conflicts: is merge.tool invoked\nin parallel for each conflict, or is it waiting for earlier merge.tool\nto finish (well, in which case we can always do set merge.tool to \n\"<program> &\")? And is merge.tool invoked for recursive part of recursive\nmerge strategy? This merge startegy depended on resolving conflict\nmarkers, i.e. had built-in knowledge of 'merge'/'diff3 -E' output.\n\nBesides, it would be useful not only to spawn interactive merge tools,\nbut also to use mergers specific for file-type, for example 3DM or xmlcmp\ntools for merging XML files.\n\n-- \nJakub Narebski\n"},{"id":"296073","messageId":"Pine.LNX.4.63.0612051459380.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43090","inReplyTo":"200612051123.33210.jnareb@gmail.com","subject":"Re: [PATCH] merge-recursive: configurable 'merge' program","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-05T14:07:06Z","receivedAt":"2006-12-05T14:07:06Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 5 Dec 2006, Jakub Narebski wrote:\n\n> By the way, is it [ed: xdl_merge()] replacement for RCS merge, i.e. is \n> it file-level merge tool, merge.onefile rather than merge.tool?\n\nIt is a C function, but yes, it does what RCS merge does.\n\n> What happens if there are multiple merge [contents] conflicts: is \n> merge.tool invoked in parallel for each conflict, or is it waiting for \n> earlier merge.tool to finish (well, in which case we can always do set \n> merge.tool to \"<program> &\")?\n\nRecursively. It is merge-recursive, so the merges are done sequentially. \n(Have to be, since the result of one merge is reused as one input for the \nnext merge.)\n\n> And is merge.tool invoked for recursive part of recursive merge \n> strategy?\n\nYes.\n\n> This merge startegy depended on resolving conflict markers, i.e. had \n> built-in knowledge of 'merge'/'diff3 -E' output.\n\nNo. git-merge-recursive never resolved conflict markers, but treated them \nas text.\n\n> Besides, it would be useful not only to spawn interactive merge tools, \n> but also to use mergers specific for file-type, for example 3DM or \n> xmlcmp tools for merging XML files.\n\nIf you need that, write a wrapper script, which detects the file type and \nexecs the corresponding merge program.\n\nCiao,\nDscho\n"},{"id":"296714","messageId":"200612051526.12636.jnareb@gmail.com","threadId":"43090","inReplyTo":"Pine.LNX.4.63.0612051459380.28348@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] merge-recursive: configurable 'merge' program","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-12-05T14:26:11Z","receivedAt":"2006-12-05T14:26:11Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Hi!\n\nOn Tue 5 Dec 2006 Johannes Schindelin wrote:\n> \n> On Tue 5 Dec 2006 Jakub Narebski wrote:\n> \n>> By the way is it [ed: xdl_merge()] replacement for RCS merge i.e. is \n>> it file-level merge tool merge.onefile rather than merge.tool?\n\nActually by \"it\" I meant here the value of merge.tool configuration\nvariable. I think the name of configuration variable should be\nmerge.onefile and not merge.tool, but this are just details.\n \n> It is a C function but yes it does what RCS merge does.\n\nAnd more if I remember correctly.\n\n>> What happens if there are multiple merge [contents] conflicts: is \n>> merge.tool invoked in parallel for each conflict or is it waiting for \n>> earlier merge.tool to finish (well in which case we can always do set \n>> merge.tool to \"<program> &\")?\n> \n> Recursively. It is merge-recursive so the merges are done sequentially. \n> (Have to be since the result of one merge is reused as one input for the \n> next merge.)\n\nHmmm... is there a way to pass merge.tool / merge.onefile program the\ninfo if it is invoked in final stage (here it is nice to invoke graphical\nmerge tool to resolve conflicts in working area before commiting merge\nresult) and in recursive stage (here it would be better to leave conflict\nmarkers to be resolved later)?\n\n>> And is merge.tool invoked for recursive part of recursive merge \n>> strategy?\n> \n> Yes.\n\nHmmm... would it be possible to use xdl_merge() for recursion, and\ngraphical merge tool for result? <Checks out earlier discussion>.\nI think yes, because of exposing xdl_merge() in git-merge-onefile...\n\n>> This merge startegy depended on resolving conflict markers i.e. had \n>> built-in knowledge of 'merge'/'diff3 -E' output.\n> \n> No. git-merge-recursive never resolved conflict markers but treated them \n> as text.\n\nHmmm... I wonder if anyone get in real life example conflict markers\nto be resolved (in final file)...\n\n>> Besides it would be useful not only to spawn interactive merge tools \n>> but also to use mergers specific for file-type for example 3DM or \n>> xmlcmp tools for merging XML files.\n> \n> If you need that write a wrapper script which detects the file type and \n> execs the corresponding merge program.\n\nThat was meant as an example why one might want to use \nmerge.tool / merge.onefile feature.\n\n-- \nJakub Narebski\n"},{"id":"293832","messageId":"Pine.LNX.4.63.0612051540230.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43090","inReplyTo":"200612051526.12636.jnareb@gmail.com","subject":"Re: [PATCH] merge-recursive: configurable 'merge' program","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-05T14:48:01Z","receivedAt":"2006-12-05T14:48:01Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 5 Dec 2006, Jakub Narebski wrote:\n\n> Hmmm... is there a way to pass merge.tool / merge.onefile program the \n> info if it is invoked in final stage (here it is nice to invoke \n> graphical merge tool to resolve conflicts in working area before \n> commiting merge result) and in recursive stage (here it would be better \n> to leave conflict markers to be resolved later)?\n\nIn a sense, you get that information: \"merge\" is called as\n\n$ merge -L new1 -L orig -L new2 fnew1 forig fnew2\n\nwhere few1 is the filename of the _temporary_ file, and new1 is the name \nthat should be displayed instead. For every but the final stage, new1 \nbegins with \"Temporary merge branch\".\n\n> Hmmm... would it be possible to use xdl_merge() for recursion, and \n> graphical merge tool for result? <Checks out earlier discussion>. I \n> think yes, because of exposing xdl_merge() in git-merge-onefile...\n\nIn \"next\", only git-merge-recursive is converted to use xdl_merge(), and \nit did not use git-merge-one-file to begin with. Since this is a shell \nscript (with a different syntax than merge), it would have to be converted \nto a C builtin first. But feasible: git-merge-one-file takes 7 parameters, \nthe first 3 being SHA1s or empty strings. \"merge\" takes 3 filenames, with \npossibly up to three \"-L <name>\" pairs before them.\n\nCiao,\nDscho\n"},{"id":"297891","messageId":"200612051601.50784.jnareb@gmail.com","threadId":"43090","inReplyTo":"Pine.LNX.4.63.0612051540230.28348@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] merge-recursive: configurable 'merge' program","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-12-05T15:01:50Z","receivedAt":"2006-12-05T15:01:50Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Dnia wtorek 5. grudnia 2006 15:48, Johannes Schindelin napisał:\n> \n> On Tue, 5 Dec 2006, Jakub Narebski wrote:\n>\n>> Hmmm... would it be possible to use xdl_merge() for recursion, and \n>> graphical merge tool for result? <Checks out earlier discussion>. I \n>> think yes, because of exposing xdl_merge() in git-merge-onefile...\n> \n> In \"next\", only git-merge-recursive is converted to use xdl_merge(), and \n> it did not use git-merge-one-file to begin with. Since this is a shell \n> script (with a different syntax than merge), it would have to be converted \n> to a C builtin first. But feasible: git-merge-one-file takes 7 parameters, \n> the first 3 being SHA1s or empty strings. \"merge\" takes 3 filenames, with \n> possibly up to three \"-L <name>\" pairs before them.\n\nI thought that Junio implemented (but perhaps not published) some script,\nI thought that was git-merge-onefile with some non-standard options,\nto function as replacement for RCS' merge, or Diffutils diff3. \n\nGuess I was wrong (at least there is nothing I can find in pu about this).\n-- \nJakub Narebski\n"}]}