{"thread":{"id":"43556","subject":"Re: [PATCH] Add builtin merge-file, a minimal replacement for RCS merge","startedAt":"2006-12-06T15:10:34Z","lastAt":"2006-12-06T15:45:42Z","messageCount":4,"participants":["Jakub Narebski","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"297421","messageId":"Pine.LNX.4.63.0612061609430.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43556","inReplyTo":null,"subject":"[PATCH] Add builtin merge-file, a minimal replacement for RCS merge","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-06T15:10:34Z","receivedAt":"2006-12-06T15:10:34Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nmerge-file has the same syntax as RCS merge, but supports only the\n\"-L\" option.\n\nFor good measure, a test is added, which is quite minimal, though.\n\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n---\n\n\tIs it a good sign that the test makes up for 75% of this patch?\n\n builtin-merge-file.c  |   72 ++++++++++++++\n builtin.h             |    1 +\n git.c                 |    1 +\n t/t6023-merge-file.sh |  251 ++++++++++++++++---------------------------------\n 4 files changed, 157 insertions(+), 168 deletions(-)\n\ndiff --git a/builtin-merge-file.c b/builtin-merge-file.c\nnew file mode 100644\nindex 0000000..11976ea\n--- /dev/null\n+++ b/builtin-merge-file.c\n@@ -0,0 +1,72 @@\n+#include \"cache.h\"\n+#include \"xdiff/xdiff.h\"\n+\n+static const char merge_file_usage[] =\n+\"git merge-file [-L name1 [-L orig [-L name2]]] file1 orig_file file2\";\n+\n+static int read_file(mmfile_t *ptr, const char *filename)\n+{\n+\tstruct stat st;\n+\tFILE *f;\n+\n+\tif (stat(filename, &st))\n+\t\treturn error(\"Could not stat %s\", filename);\n+\tif ((f = fopen(filename, \"rb\")) == NULL)\n+\t\treturn error(\"Could not open %s\", filename);\n+\tptr->ptr = xmalloc(st.st_size);\n+\tif (fread(ptr->ptr, st.st_size, 1, f) != 1)\n+\t\treturn error(\"Could not read %s\", filename);\n+\tfclose(f);\n+\tptr->size = st.st_size;\n+\treturn 0;\n+}\n+\n+int cmd_merge_file(int argc, char **argv, char **envp)\n+{\n+\tchar *names[3];\n+\tchar *buffers[3];\n+\tmmfile_t mmfs[3], result = {NULL, 0};\n+\tint ret = 0, i = 0;\n+\n+\twhile (argc > 4) {\n+\t\tif (!strcmp(argv[1], \"-L\")) {\n+\t\t\tnames[i++] = argv[2];\n+\t\t\targc -= 2;\n+\t\t\targv += 2;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tusage(merge_file_usage);\n+\t}\n+\n+\tif (argc != 4)\n+\t\tusage(merge_file_usage);\n+\n+\tfor (; i < 3; i++)\n+\t\tnames[i] = argv[i + 1];\n+\n+\tfor (i = 0; i < 3; i++)\n+\t\tif (read_file(mmfs + i, argv[i + 1]))\n+\t\t\treturn -1;\n+\n+\txpparam_t xpp = {XDF_NEED_MINIMAL};\n+\tret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],\n+\t\t\t&xpp, XDL_MERGE_ZEALOUS, &result);\n+\n+\tfor (i = 0; i < 3; i++)\n+\t\tfree(mmfs[i].ptr);\n+\n+\tif (ret >= 0) {\n+\t\tchar *filename = argv[1];\n+\t\tFILE *f = fopen(filename, \"wb\");\n+\n+\t\tif (!f)\n+\t\t\tret = error(\"Could not open %s for writing\", filename);\n+\t\telse if (fwrite(result.ptr, result.size, 1, f) != 1)\n+\t\t\tret = error(\"Could not write to %s\", filename);\n+\t\telse if (fclose(f))\n+\t\t\tret = error(\"Could not close %s\", filename);\n+\t\tfree(result.ptr);\n+\t}\n+\n+\treturn ret;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex b5116f3..08519e7 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -42,6 +42,7 @@ extern int cmd_ls_files(int argc, const char **argv, const char *prefix);\n extern int cmd_ls_tree(int argc, const char **argv, const char *prefix);\n extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);\n extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);\n+extern int cmd_merge_file(int argc, const char **argv, const char *prefix);\n extern int cmd_mv(int argc, const char **argv, const char *prefix);\n extern int cmd_name_rev(int argc, const char **argv, const char *prefix);\n extern int cmd_pack_objects(int argc, const char **argv, const char *prefix);\ndiff --git a/git.c b/git.c\nindex 63a4747..cb5a7ef 100644\n--- a/git.c\n+++ b/git.c\n@@ -252,6 +252,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)\n \t\t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n \t\t{ \"mailinfo\", cmd_mailinfo },\n \t\t{ \"mailsplit\", cmd_mailsplit },\n+\t\t{ \"merge-file\", cmd_merge_file },\n \t\t{ \"mv\", cmd_mv, RUN_SETUP },\n \t\t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n \t\t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\ndiff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh\nindex 53246f2..5d9b6f3 100644\n--- a/t/t6023-merge-file.sh\n+++ b/t/t6023-merge-file.sh\n@@ -11,191 +11,106 @@ super aquam refectionis educavit me;\n animam meam convertit,\n deduxit me super semitas jusitiae,\n propter nomen suum.\n+EOF\n+\n+cat > new1.txt << EOF\n+Dominus regit me,\n+et nihil mihi deerit.\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+propter nomen suum.\n Nam et si ambulavero in medio umbrae mortis,\n non timebo mala, quoniam tu mecum es:\n virga tua et baculus tuus ipsa me consolata sunt.\n-Parasti in conspectu meo mensam,\n-adversus eos qui tribulant me;\n-impinguasti in oleo caput meum,\n-et calix meus inebrians quam praeclarus est!\n-Et misericordia tua subsequetur me omnibus diebus vitae meae,\n-et ut inhabitem in domo Domini in longitudinem dierum.\n EOF\n \n-cp orig.txt with-empty-lines.txt\n-git apply --unidiff-zero << EOF\n---- with-empty-lines.txt\n-+++ with-empty-lines.txt\n-@@ -3,0 +3 @@\n-+\n-@@ -5,0 +6 @@\n-+\n-@@ -8,0 +10 @@\n-+\n-@@ -11,0 +14 @@\n-+\n-@@ -15,0 +19 @@\n-+\n-@@ -17,0 +22 @@\n-+\n+cat > new2.txt << EOF\n+Dominus regit me, et nihil mihi deerit.\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+propter nomen suum.\n EOF\n \n-(cat orig.txt; echo; echo \"Psalmus David\") > with-reference.txt\n-\n-cp orig.txt different-capitalisation.txt\n-git apply --unidiff-zero << EOF\n---- different-capitalisation.txt\n-+++ different-capitalisation.txt\n-@@ -3,2 +3,2 @@\n--In loco pascuae ibi me collocavit,\n--super aquam refectionis educavit me;\n-+in loco pascuae ibi me collocavit.\n-+Super aquam refectionis educavit me;\n-@@ -6 +6 @@\n--deduxit me super semitas jusitiae,\n-+Deduxit me super semitas jusitiae,\n-@@ -10 +10 @@\n--virga tua et baculus tuus ipsa me consolata sunt.\n-+Virga tua et baculus tuus ipsa me consolata sunt.\n-@@ -13 +13 @@\n--impinguasti in oleo caput meum,\n-+Impinguasti in oleo caput meum,\n-@@ -16 +16 @@\n--et ut inhabitem in domo Domini in longitudinem dierum.\n-+Et ut inhabitem in domo Domini in longitudinem dierum.\n+cat > new3.txt << EOF\n+DOMINUS regit me,\n+et nihil mihi deerit.\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+propter nomen suum.\n EOF\n \n-cp orig.txt with-numbers.txt\n-git apply --unidiff-zero << EOF\n---- with-numbers.txt\n-+++ with-numbers.txt\n-@@ -1 +1 @@\n--Dominus regit me,\n-+1. Dominus regit me,\n-@@ -3 +3 @@\n--In loco pascuae ibi me collocavit,\n-+2. In loco pascuae ibi me collocavit,\n-@@ -5 +5 @@\n--animam meam convertit,\n-+3. animam meam convertit,\n-@@ -8 +8 @@\n--Nam et si ambulavero in medio umbrae mortis,\n-+4. Nam et si ambulavero in medio umbrae mortis,\n-@@ -11 +11 @@\n--Parasti in conspectu meo mensam,\n-+5. Parasti in conspectu meo mensam,\n-@@ -15 +15 @@\n--Et misericordia tua subsequetur me omnibus diebus vitae meae,\n-+6. Et misericordia tua subsequetur me omnibus diebus vitae meae,\n+cat > new4.txt << EOF\n+Dominus regit me, et nihil mihi deerit.\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n EOF\n+echo -n \"propter nomen suum.\" >> new4.txt\n \n-# Excusez-moi, je n'ai clavier avec des accents...\n-\n-cp orig.txt avec-francais.txt\n-git apply --unidiff-zero << EOF\n---- avec-francais.txt\n-+++ avec-francais.txt\n-@@ -3,0 +3,3 @@\n-+\n-+Le Seigneur est mon berger,\n-+je ne manquerai de rien.\n-@@ -5,0 +8,3 @@\n-+\n-+Il me met au repos dans des pres d'herbe fraiche,\n-+il me conduit au calme pres de l'eau.\n-@@ -8,0 +14,4 @@\n-+\n-+Il ranime mes forces,\n-+il me guide sur la bonne voie,\n-+parce qu'il est le berger d'Israel.\n-@@ -11,0 +21,4 @@\n-+\n-+Meme si je passe par la vallee obscure,\n-+je ne redoute aucun mal, Seigneur, car tu m'accompagnes.\n-+Tu me conduis, tu me defends, voila ce qui me rassure.\n-@@ -15,0 +29,5 @@\n-+\n-+Face a ceux qui me veulent du mal,\n-+tu prepares un banquet pour moi.\n-+Tu m'accueilles en versant sur ma teete un peu d'huile parfumee.\n-+Tu remplis ma coupe jusqu'au bord.\n-@@ -17,0 +35,5 @@\n-+\n-+Oui, tous les jours de ma vie,\n-+ta bonte, ta generosite me suivront pas a pas.\n-+Seigneur, je reviendrai dans ta maison\n-+aussi longtemps que je vivrai.\n-EOF\n+cp new1.txt test.txt\n+test_expect_success \"merge without conflict\" \\\n+\t\"git-merge-file test.txt orig.txt new2.txt\"\n \n-cp with-numbers.txt with-empty-lines-and-numbers-conflict.txt\n-git apply --unidiff-zero << EOF\n---- with-empty-lines-and-numbers-conflict.txt\n-+++ with-empty-lines-and-numbers-conflict.txt\n-@@ -2,0 +3,4 @@\n-+<<<<<<< new.txt\n-+\n-+In loco pascuae ibi me collocavit,\n-+=======\n-@@ -3,0 +8 @@\n-+>>>>>>> with-numbers.txt\n-@@ -4,0 +10,4 @@\n-+<<<<<<< new.txt\n-+\n-+animam meam convertit,\n-+=======\n-@@ -5,0 +15 @@\n-+>>>>>>> with-numbers.txt\n-@@ -7,0 +18,4 @@\n-+<<<<<<< new.txt\n-+\n-+Nam et si ambulavero in medio umbrae mortis,\n-+=======\n-@@ -8,0 +23 @@\n-+>>>>>>> with-numbers.txt\n-@@ -10,0 +26,4 @@\n-+<<<<<<< new.txt\n-+\n-+Parasti in conspectu meo mensam,\n-+=======\n-@@ -11,0 +31 @@\n-+>>>>>>> with-numbers.txt\n-@@ -14,0 +35,4 @@\n-+<<<<<<< new.txt\n-+\n-+Et misericordia tua subsequetur me omnibus diebus vitae meae,\n-+=======\n-@@ -15,0 +40 @@\n-+>>>>>>> with-numbers.txt\n-@@ -16,0 +42 @@\n-+\n-EOF\n+cp new1.txt test2.txt\n+test_expect_success \"merge without conflict (missing LF at EOF)\" \\\n+\t\"git-merge-file test2.txt orig.txt new2.txt\"\n+\n+test_expect_success \"merge result added missing LF\" \\\n+\t\"diff -u test.txt test2.txt\"\n \n-cp with-numbers.txt with-empty-lines-and-numbers.txt\n-git apply --unidiff-zero << EOF\n---- with-empty-lines-and-numbers.txt\n-+++ with-empty-lines-and-numbers.txt\n-@@ -2,0 +3 @@\n-+\n-@@ -4,0 +6 @@\n-+\n-@@ -7,0 +10 @@\n-+\n-@@ -10,0 +14 @@\n-+\n-@@ -14,0 +19 @@\n-+\n+cp test.txt backup.txt\n+test_expect_failure \"merge with conflicts\" \\\n+\t\"git-merge-file test.txt orig.txt new3.txt\"\n+\n+cat > expect.txt << EOF\n+<<<<<<< test.txt\n+Dominus regit me, et nihil mihi deerit.\n+=======\n+DOMINUS regit me,\n+et nihil mihi deerit.\n+>>>>>>> new3.txt\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+propter nomen suum.\n+Nam et si ambulavero in medio umbrae mortis,\n+non timebo mala, quoniam tu mecum es:\n+virga tua et baculus tuus ipsa me consolata sunt.\n EOF\n \n-cp with-empty-lines.txt new.txt\n-test_expect_failure \"merge empty-lines and numbers\" \\\n-\t\"git-merge-file new.txt orig.txt with-numbers.txt\"\n+test_expect_success \"expected conflict markers\" \"diff -u test.txt expect.txt\"\n+\n+cp backup.txt test.txt\n+test_expect_failure \"merge with conflicts, using -L\" \\\n+\t\"git-merge-file -L 1 -L 2 test.txt orig.txt new3.txt\"\n \n-test_expect_success \"conflict markers of failed merge\" \\\n-\t\"diff -u new.txt with-empty-lines-and-numbers-conflict.txt\"\n+cat > expect.txt << EOF\n+<<<<<<< 1\n+Dominus regit me, et nihil mihi deerit.\n+=======\n+DOMINUS regit me,\n+et nihil mihi deerit.\n+>>>>>>> new3.txt\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+propter nomen suum.\n+Nam et si ambulavero in medio umbrae mortis,\n+non timebo mala, quoniam tu mecum es:\n+virga tua et baculus tuus ipsa me consolata sunt.\n+EOF\n \n-cp with-empty-lines-and-numbers.txt new.txt\n-test_expect_success \"merge with title\" \\\n-\t\"git-merge-file new.txt orig.txt with-reference.txt\"\n+test_expect_success \"expected conflict markers, with -L\" \\\n+\t\"diff -u test.txt expect.txt\"\n \n test_done\n \n-- \n1.4.4.1.g064f-dirty\n"},{"id":"296627","messageId":"Pine.LNX.4.63.0612061621420.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43556","inReplyTo":"Pine.LNX.4.63.0612061609430.28348@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] Add builtin merge-file, a minimal replacement for RCS merge","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-06T15:26:06Z","receivedAt":"2006-12-06T15:26:06Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Oops. Here is a corrected patch:\n\n Makefile              |    1 \n builtin-merge-file.c  |   72 ++++++++++++++++++++++++++++++\n builtin.h             |    1 \n git.c                 |    1 \n t/t6023-merge-file.sh |  116 +++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 191 insertions(+), 0 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex cf69242..81cc7c4 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -275,6 +283,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-ls-tree.o \\\n \tbuiltin-mailinfo.o \\\n \tbuiltin-mailsplit.o \\\n+\tbuiltin-merge-file.o \\\n \tbuiltin-mv.o \\\n \tbuiltin-name-rev.o \\\n \tbuiltin-pack-objects.o \\\ndiff --git a/builtin-merge-file.c b/builtin-merge-file.c\nnew file mode 100644\nindex 0000000..11976ea\n--- /dev/null\n+++ b/builtin-merge-file.c\n@@ -0,0 +1,72 @@\n+#include \"cache.h\"\n+#include \"xdiff/xdiff.h\"\n+\n+static const char merge_file_usage[] =\n+\"git merge-file [-L name1 [-L orig [-L name2]]] file1 orig_file file2\";\n+\n+static int read_file(mmfile_t *ptr, const char *filename)\n+{\n+\tstruct stat st;\n+\tFILE *f;\n+\n+\tif (stat(filename, &st))\n+\t\treturn error(\"Could not stat %s\", filename);\n+\tif ((f = fopen(filename, \"rb\")) == NULL)\n+\t\treturn error(\"Could not open %s\", filename);\n+\tptr->ptr = xmalloc(st.st_size);\n+\tif (fread(ptr->ptr, st.st_size, 1, f) != 1)\n+\t\treturn error(\"Could not read %s\", filename);\n+\tfclose(f);\n+\tptr->size = st.st_size;\n+\treturn 0;\n+}\n+\n+int cmd_merge_file(int argc, char **argv, char **envp)\n+{\n+\tchar *names[3];\n+\tchar *buffers[3];\n+\tmmfile_t mmfs[3], result = {NULL, 0};\n+\tint ret = 0, i = 0;\n+\n+\twhile (argc > 4) {\n+\t\tif (!strcmp(argv[1], \"-L\")) {\n+\t\t\tnames[i++] = argv[2];\n+\t\t\targc -= 2;\n+\t\t\targv += 2;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tusage(merge_file_usage);\n+\t}\n+\n+\tif (argc != 4)\n+\t\tusage(merge_file_usage);\n+\n+\tfor (; i < 3; i++)\n+\t\tnames[i] = argv[i + 1];\n+\n+\tfor (i = 0; i < 3; i++)\n+\t\tif (read_file(mmfs + i, argv[i + 1]))\n+\t\t\treturn -1;\n+\n+\txpparam_t xpp = {XDF_NEED_MINIMAL};\n+\tret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],\n+\t\t\t&xpp, XDL_MERGE_ZEALOUS, &result);\n+\n+\tfor (i = 0; i < 3; i++)\n+\t\tfree(mmfs[i].ptr);\n+\n+\tif (ret >= 0) {\n+\t\tchar *filename = argv[1];\n+\t\tFILE *f = fopen(filename, \"wb\");\n+\n+\t\tif (!f)\n+\t\t\tret = error(\"Could not open %s for writing\", filename);\n+\t\telse if (fwrite(result.ptr, result.size, 1, f) != 1)\n+\t\t\tret = error(\"Could not write to %s\", filename);\n+\t\telse if (fclose(f))\n+\t\t\tret = error(\"Could not close %s\", filename);\n+\t\tfree(result.ptr);\n+\t}\n+\n+\treturn ret;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex b5116f3..08519e7 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -42,6 +42,7 @@ extern int cmd_ls_files(int argc, const char **argv, const char *prefix);\n extern int cmd_ls_tree(int argc, const char **argv, const char *prefix);\n extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);\n extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);\n+extern int cmd_merge_file(int argc, const char **argv, const char *prefix);\n extern int cmd_mv(int argc, const char **argv, const char *prefix);\n extern int cmd_name_rev(int argc, const char **argv, const char *prefix);\n extern int cmd_pack_objects(int argc, const char **argv, const char *prefix);\ndiff --git a/git.c b/git.c\nindex 357330e..cb5a7ef 100644\n--- a/git.c\n+++ b/git.c\n@@ -242,6 +252,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)\n \t\t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n \t\t{ \"mailinfo\", cmd_mailinfo },\n \t\t{ \"mailsplit\", cmd_mailsplit },\n+\t\t{ \"merge-file\", cmd_merge_file },\n \t\t{ \"mv\", cmd_mv, RUN_SETUP },\n \t\t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n \t\t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\ndiff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh\nnew file mode 100644\nindex 0000000..5d9b6f3\n--- /dev/null\n+++ b/t/t6023-merge-file.sh\n@@ -0,0 +1,116 @@\n+#!/bin/sh\n+\n+test_description='RCS merge replacement: merge-file'\n+. ./test-lib.sh\n+\n+cat > orig.txt << EOF\n+Dominus regit me,\n+et nihil mihi deerit.\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+propter nomen suum.\n+EOF\n+\n+cat > new1.txt << EOF\n+Dominus regit me,\n+et nihil mihi deerit.\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+propter nomen suum.\n+Nam et si ambulavero in medio umbrae mortis,\n+non timebo mala, quoniam tu mecum es:\n+virga tua et baculus tuus ipsa me consolata sunt.\n+EOF\n+\n+cat > new2.txt << EOF\n+Dominus regit me, et nihil mihi deerit.\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+propter nomen suum.\n+EOF\n+\n+cat > new3.txt << EOF\n+DOMINUS regit me,\n+et nihil mihi deerit.\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+propter nomen suum.\n+EOF\n+\n+cat > new4.txt << EOF\n+Dominus regit me, et nihil mihi deerit.\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+EOF\n+echo -n \"propter nomen suum.\" >> new4.txt\n+\n+cp new1.txt test.txt\n+test_expect_success \"merge without conflict\" \\\n+\t\"git-merge-file test.txt orig.txt new2.txt\"\n+\n+cp new1.txt test2.txt\n+test_expect_success \"merge without conflict (missing LF at EOF)\" \\\n+\t\"git-merge-file test2.txt orig.txt new2.txt\"\n+\n+test_expect_success \"merge result added missing LF\" \\\n+\t\"diff -u test.txt test2.txt\"\n+\n+cp test.txt backup.txt\n+test_expect_failure \"merge with conflicts\" \\\n+\t\"git-merge-file test.txt orig.txt new3.txt\"\n+\n+cat > expect.txt << EOF\n+<<<<<<< test.txt\n+Dominus regit me, et nihil mihi deerit.\n+=======\n+DOMINUS regit me,\n+et nihil mihi deerit.\n+>>>>>>> new3.txt\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+propter nomen suum.\n+Nam et si ambulavero in medio umbrae mortis,\n+non timebo mala, quoniam tu mecum es:\n+virga tua et baculus tuus ipsa me consolata sunt.\n+EOF\n+\n+test_expect_success \"expected conflict markers\" \"diff -u test.txt expect.txt\"\n+\n+cp backup.txt test.txt\n+test_expect_failure \"merge with conflicts, using -L\" \\\n+\t\"git-merge-file -L 1 -L 2 test.txt orig.txt new3.txt\"\n+\n+cat > expect.txt << EOF\n+<<<<<<< 1\n+Dominus regit me, et nihil mihi deerit.\n+=======\n+DOMINUS regit me,\n+et nihil mihi deerit.\n+>>>>>>> new3.txt\n+In loco pascuae ibi me collocavit,\n+super aquam refectionis educavit me;\n+animam meam convertit,\n+deduxit me super semitas jusitiae,\n+propter nomen suum.\n+Nam et si ambulavero in medio umbrae mortis,\n+non timebo mala, quoniam tu mecum es:\n+virga tua et baculus tuus ipsa me consolata sunt.\n+EOF\n+\n+test_expect_success \"expected conflict markers, with -L\" \\\n+\t\"diff -u test.txt expect.txt\"\n+\n+test_done\n+\n"},{"id":"295474","messageId":"el6nhv$58n$1@sea.gmane.org","threadId":"43556","inReplyTo":"Pine.LNX.4.63.0612061609430.28348@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] Add builtin merge-file, a minimal replacement for RCS merge","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-12-06T15:30:08Z","receivedAt":"2006-12-06T15:30:08Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Johannes Schindelin wrote:\n\n> merge-file has the same syntax as RCS merge, but supports only the\n> \"-L\" option.\n\nWould it be hard to add \"-p / --stdout\" options, and \"-q / --quiet\" option?\nI understand that non-standard output format options are rather out of\nquestion...\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n\n"},{"id":"295863","messageId":"Pine.LNX.4.63.0612061644100.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43556","inReplyTo":"el6nhv$58n$1@sea.gmane.org","subject":"[PATCH] merge-file: support -p and -q; fix compile warnings","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-06T15:45:42Z","receivedAt":"2006-12-06T15:45:42Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nNow merge-file also understands --stdout and --quiet options. While\nat it, two compile warnings were fixed.\n\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n---\n\n\tOn Wed, 6 Dec 2006, Jakub Narebski wrote:\n\n\t> Johannes Schindelin wrote:\n\t> \n\t> > merge-file has the same syntax as RCS merge, but supports only \n\t> > the \"-L\" option.\n\t> \n\t> Would it be hard to add \"-p / --stdout\" options, and \"-q / \n\t> --quiet\" option?\n\n\tNo.\n\n\tBut the documentation has to be done by somebody else.\n\n builtin-merge-file.c |   29 ++++++++++++++++++-----------\n 1 files changed, 18 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin-merge-file.c b/builtin-merge-file.c\nindex 11976ea..9ae1009 100644\n--- a/builtin-merge-file.c\n+++ b/builtin-merge-file.c\n@@ -2,7 +2,7 @@\n #include \"xdiff/xdiff.h\"\n \n static const char merge_file_usage[] =\n-\"git merge-file [-L name1 [-L orig [-L name2]]] file1 orig_file file2\";\n+\"git merge-file [-p | --stdout] [-q | --quiet] [-L name1 [-L orig [-L name2]]] file1 orig_file file2\";\n \n static int read_file(mmfile_t *ptr, const char *filename)\n {\n@@ -24,18 +24,25 @@ static int read_file(mmfile_t *ptr, const char *filename)\n int cmd_merge_file(int argc, char **argv, char **envp)\n {\n \tchar *names[3];\n-\tchar *buffers[3];\n-\tmmfile_t mmfs[3], result = {NULL, 0};\n-\tint ret = 0, i = 0;\n+\tmmfile_t mmfs[3];\n+\tmmbuffer_t result = {NULL, 0};\n+\tint ret = 0, i = 0, to_stdout = 0;\n \n \twhile (argc > 4) {\n-\t\tif (!strcmp(argv[1], \"-L\")) {\n+\t\tif (!strcmp(argv[1], \"-L\") && i < 3) {\n \t\t\tnames[i++] = argv[2];\n-\t\t\targc -= 2;\n-\t\t\targv += 2;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tusage(merge_file_usage);\n+\t\t\targc--;\n+\t\t\targv++;\n+\t\t} else if (!strcmp(argv[1], \"-p\") ||\n+\t\t\t\t!strcmp(argv[1], \"--stdout\"))\n+\t\t\tto_stdout = 1;\n+\t\telse if (!strcmp(argv[1], \"-q\") ||\n+\t\t\t\t!strcmp(argv[1], \"--quiet\"))\n+\t\t\tfreopen(\"/dev/null\", \"w\", stderr);\n+\t\telse\n+\t\t\tusage(merge_file_usage);\n+\t\targc--;\n+\t\targv++;\n \t}\n \n \tif (argc != 4)\n@@ -57,7 +64,7 @@ int cmd_merge_file(int argc, char **argv, char **envp)\n \n \tif (ret >= 0) {\n \t\tchar *filename = argv[1];\n-\t\tFILE *f = fopen(filename, \"wb\");\n+\t\tFILE *f = to_stdout ? stdout : fopen(filename, \"wb\");\n \n \t\tif (!f)\n \t\t\tret = error(\"Could not open %s for writing\", filename);\n-- \n"}]}