[PATCH] Add builtin merge-file, a minimal replacement for RCS merge

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



merge-file has the same syntax as RCS merge, but supports only the
"-L" option.

For good measure, a test is added, which is quite minimal, though.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@xxxxxx>
---

	Is it a good sign that the test makes up for 75% of this patch?

 builtin-merge-file.c  |   72 ++++++++++++++
 builtin.h             |    1 +
 git.c                 |    1 +
 t/t6023-merge-file.sh |  251 ++++++++++++++++---------------------------------
 4 files changed, 157 insertions(+), 168 deletions(-)

diff --git a/builtin-merge-file.c b/builtin-merge-file.c
new file mode 100644
index 0000000..11976ea
--- /dev/null
+++ b/builtin-merge-file.c
@@ -0,0 +1,72 @@
+#include "cache.h"
+#include "xdiff/xdiff.h"
+
+static const char merge_file_usage[] =
+"git merge-file [-L name1 [-L orig [-L name2]]] file1 orig_file file2";
+
+static int read_file(mmfile_t *ptr, const char *filename)
+{
+	struct stat st;
+	FILE *f;
+
+	if (stat(filename, &st))
+		return error("Could not stat %s", filename);
+	if ((f = fopen(filename, "rb")) == NULL)
+		return error("Could not open %s", filename);
+	ptr->ptr = xmalloc(st.st_size);
+	if (fread(ptr->ptr, st.st_size, 1, f) != 1)
+		return error("Could not read %s", filename);
+	fclose(f);
+	ptr->size = st.st_size;
+	return 0;
+}
+
+int cmd_merge_file(int argc, char **argv, char **envp)
+{
+	char *names[3];
+	char *buffers[3];
+	mmfile_t mmfs[3], result = {NULL, 0};
+	int ret = 0, i = 0;
+
+	while (argc > 4) {
+		if (!strcmp(argv[1], "-L")) {
+			names[i++] = argv[2];
+			argc -= 2;
+			argv += 2;
+			continue;
+		}
+		usage(merge_file_usage);
+	}
+
+	if (argc != 4)
+		usage(merge_file_usage);
+
+	for (; i < 3; i++)
+		names[i] = argv[i + 1];
+
+	for (i = 0; i < 3; i++)
+		if (read_file(mmfs + i, argv[i + 1]))
+			return -1;
+
+	xpparam_t xpp = {XDF_NEED_MINIMAL};
+	ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],
+			&xpp, XDL_MERGE_ZEALOUS, &result);
+
+	for (i = 0; i < 3; i++)
+		free(mmfs[i].ptr);
+
+	if (ret >= 0) {
+		char *filename = argv[1];
+		FILE *f = fopen(filename, "wb");
+
+		if (!f)
+			ret = error("Could not open %s for writing", filename);
+		else if (fwrite(result.ptr, result.size, 1, f) != 1)
+			ret = error("Could not write to %s", filename);
+		else if (fclose(f))
+			ret = error("Could not close %s", filename);
+		free(result.ptr);
+	}
+
+	return ret;
+}
diff --git a/builtin.h b/builtin.h
index b5116f3..08519e7 100644
--- a/builtin.h
+++ b/builtin.h
@@ -42,6 +42,7 @@ extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
 extern int cmd_ls_tree(int argc, const char **argv, const char *prefix);
 extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);
 extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);
+extern int cmd_merge_file(int argc, const char **argv, const char *prefix);
 extern int cmd_mv(int argc, const char **argv, const char *prefix);
 extern int cmd_name_rev(int argc, const char **argv, const char *prefix);
 extern int cmd_pack_objects(int argc, const char **argv, const char *prefix);
diff --git a/git.c b/git.c
index 63a4747..cb5a7ef 100644
--- a/git.c
+++ b/git.c
@@ -252,6 +252,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
 		{ "ls-tree", cmd_ls_tree, RUN_SETUP },
 		{ "mailinfo", cmd_mailinfo },
 		{ "mailsplit", cmd_mailsplit },
+		{ "merge-file", cmd_merge_file },
 		{ "mv", cmd_mv, RUN_SETUP },
 		{ "name-rev", cmd_name_rev, RUN_SETUP },
 		{ "pack-objects", cmd_pack_objects, RUN_SETUP },
diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh
index 53246f2..5d9b6f3 100644
--- a/t/t6023-merge-file.sh
+++ b/t/t6023-merge-file.sh
@@ -11,191 +11,106 @@ super aquam refectionis educavit me;
 animam meam convertit,
 deduxit me super semitas jusitiae,
 propter nomen suum.
+EOF
+
+cat > new1.txt << EOF
+Dominus regit me,
+et nihil mihi deerit.
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+animam meam convertit,
+deduxit me super semitas jusitiae,
+propter nomen suum.
 Nam et si ambulavero in medio umbrae mortis,
 non timebo mala, quoniam tu mecum es:
 virga tua et baculus tuus ipsa me consolata sunt.
-Parasti in conspectu meo mensam,
-adversus eos qui tribulant me;
-impinguasti in oleo caput meum,
-et calix meus inebrians quam praeclarus est!
-Et misericordia tua subsequetur me omnibus diebus vitae meae,
-et ut inhabitem in domo Domini in longitudinem dierum.
 EOF
 
-cp orig.txt with-empty-lines.txt
-git apply --unidiff-zero << EOF
---- with-empty-lines.txt
-+++ with-empty-lines.txt
-@@ -3,0 +3 @@
-+
-@@ -5,0 +6 @@
-+
-@@ -8,0 +10 @@
-+
-@@ -11,0 +14 @@
-+
-@@ -15,0 +19 @@
-+
-@@ -17,0 +22 @@
-+
+cat > new2.txt << EOF
+Dominus regit me, et nihil mihi deerit.
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+animam meam convertit,
+deduxit me super semitas jusitiae,
+propter nomen suum.
 EOF
 
-(cat orig.txt; echo; echo "Psalmus David") > with-reference.txt
-
-cp orig.txt different-capitalisation.txt
-git apply --unidiff-zero << EOF
---- different-capitalisation.txt
-+++ different-capitalisation.txt
-@@ -3,2 +3,2 @@
--In loco pascuae ibi me collocavit,
--super aquam refectionis educavit me;
-+in loco pascuae ibi me collocavit.
-+Super aquam refectionis educavit me;
-@@ -6 +6 @@
--deduxit me super semitas jusitiae,
-+Deduxit me super semitas jusitiae,
-@@ -10 +10 @@
--virga tua et baculus tuus ipsa me consolata sunt.
-+Virga tua et baculus tuus ipsa me consolata sunt.
-@@ -13 +13 @@
--impinguasti in oleo caput meum,
-+Impinguasti in oleo caput meum,
-@@ -16 +16 @@
--et ut inhabitem in domo Domini in longitudinem dierum.
-+Et ut inhabitem in domo Domini in longitudinem dierum.
+cat > new3.txt << EOF
+DOMINUS regit me,
+et nihil mihi deerit.
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+animam meam convertit,
+deduxit me super semitas jusitiae,
+propter nomen suum.
 EOF
 
-cp orig.txt with-numbers.txt
-git apply --unidiff-zero << EOF
---- with-numbers.txt
-+++ with-numbers.txt
-@@ -1 +1 @@
--Dominus regit me,
-+1. Dominus regit me,
-@@ -3 +3 @@
--In loco pascuae ibi me collocavit,
-+2. In loco pascuae ibi me collocavit,
-@@ -5 +5 @@
--animam meam convertit,
-+3. animam meam convertit,
-@@ -8 +8 @@
--Nam et si ambulavero in medio umbrae mortis,
-+4. Nam et si ambulavero in medio umbrae mortis,
-@@ -11 +11 @@
--Parasti in conspectu meo mensam,
-+5. Parasti in conspectu meo mensam,
-@@ -15 +15 @@
--Et misericordia tua subsequetur me omnibus diebus vitae meae,
-+6. Et misericordia tua subsequetur me omnibus diebus vitae meae,
+cat > new4.txt << EOF
+Dominus regit me, et nihil mihi deerit.
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+animam meam convertit,
+deduxit me super semitas jusitiae,
 EOF
+echo -n "propter nomen suum." >> new4.txt
 
-# Excusez-moi, je n'ai clavier avec des accents...
-
-cp orig.txt avec-francais.txt
-git apply --unidiff-zero << EOF
---- avec-francais.txt
-+++ avec-francais.txt
-@@ -3,0 +3,3 @@
-+
-+Le Seigneur est mon berger,
-+je ne manquerai de rien.
-@@ -5,0 +8,3 @@
-+
-+Il me met au repos dans des pres d'herbe fraiche,
-+il me conduit au calme pres de l'eau.
-@@ -8,0 +14,4 @@
-+
-+Il ranime mes forces,
-+il me guide sur la bonne voie,
-+parce qu'il est le berger d'Israel.
-@@ -11,0 +21,4 @@
-+
-+Meme si je passe par la vallee obscure,
-+je ne redoute aucun mal, Seigneur, car tu m'accompagnes.
-+Tu me conduis, tu me defends, voila ce qui me rassure.
-@@ -15,0 +29,5 @@
-+
-+Face a ceux qui me veulent du mal,
-+tu prepares un banquet pour moi.
-+Tu m'accueilles en versant sur ma teete un peu d'huile parfumee.
-+Tu remplis ma coupe jusqu'au bord.
-@@ -17,0 +35,5 @@
-+
-+Oui, tous les jours de ma vie,
-+ta bonte, ta generosite me suivront pas a pas.
-+Seigneur, je reviendrai dans ta maison
-+aussi longtemps que je vivrai.
-EOF
+cp new1.txt test.txt
+test_expect_success "merge without conflict" \
+	"git-merge-file test.txt orig.txt new2.txt"
 
-cp with-numbers.txt with-empty-lines-and-numbers-conflict.txt
-git apply --unidiff-zero << EOF
---- with-empty-lines-and-numbers-conflict.txt
-+++ with-empty-lines-and-numbers-conflict.txt
-@@ -2,0 +3,4 @@
-+<<<<<<< new.txt
-+
-+In loco pascuae ibi me collocavit,
-+=======
-@@ -3,0 +8 @@
-+>>>>>>> with-numbers.txt
-@@ -4,0 +10,4 @@
-+<<<<<<< new.txt
-+
-+animam meam convertit,
-+=======
-@@ -5,0 +15 @@
-+>>>>>>> with-numbers.txt
-@@ -7,0 +18,4 @@
-+<<<<<<< new.txt
-+
-+Nam et si ambulavero in medio umbrae mortis,
-+=======
-@@ -8,0 +23 @@
-+>>>>>>> with-numbers.txt
-@@ -10,0 +26,4 @@
-+<<<<<<< new.txt
-+
-+Parasti in conspectu meo mensam,
-+=======
-@@ -11,0 +31 @@
-+>>>>>>> with-numbers.txt
-@@ -14,0 +35,4 @@
-+<<<<<<< new.txt
-+
-+Et misericordia tua subsequetur me omnibus diebus vitae meae,
-+=======
-@@ -15,0 +40 @@
-+>>>>>>> with-numbers.txt
-@@ -16,0 +42 @@
-+
-EOF
+cp new1.txt test2.txt
+test_expect_success "merge without conflict (missing LF at EOF)" \
+	"git-merge-file test2.txt orig.txt new2.txt"
+
+test_expect_success "merge result added missing LF" \
+	"diff -u test.txt test2.txt"
 
-cp with-numbers.txt with-empty-lines-and-numbers.txt
-git apply --unidiff-zero << EOF
---- with-empty-lines-and-numbers.txt
-+++ with-empty-lines-and-numbers.txt
-@@ -2,0 +3 @@
-+
-@@ -4,0 +6 @@
-+
-@@ -7,0 +10 @@
-+
-@@ -10,0 +14 @@
-+
-@@ -14,0 +19 @@
-+
+cp test.txt backup.txt
+test_expect_failure "merge with conflicts" \
+	"git-merge-file test.txt orig.txt new3.txt"
+
+cat > expect.txt << EOF
+<<<<<<< test.txt
+Dominus regit me, et nihil mihi deerit.
+=======
+DOMINUS regit me,
+et nihil mihi deerit.
+>>>>>>> new3.txt
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+animam meam convertit,
+deduxit me super semitas jusitiae,
+propter nomen suum.
+Nam et si ambulavero in medio umbrae mortis,
+non timebo mala, quoniam tu mecum es:
+virga tua et baculus tuus ipsa me consolata sunt.
 EOF
 
-cp with-empty-lines.txt new.txt
-test_expect_failure "merge empty-lines and numbers" \
-	"git-merge-file new.txt orig.txt with-numbers.txt"
+test_expect_success "expected conflict markers" "diff -u test.txt expect.txt"
+
+cp backup.txt test.txt
+test_expect_failure "merge with conflicts, using -L" \
+	"git-merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
 
-test_expect_success "conflict markers of failed merge" \
-	"diff -u new.txt with-empty-lines-and-numbers-conflict.txt"
+cat > expect.txt << EOF
+<<<<<<< 1
+Dominus regit me, et nihil mihi deerit.
+=======
+DOMINUS regit me,
+et nihil mihi deerit.
+>>>>>>> new3.txt
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+animam meam convertit,
+deduxit me super semitas jusitiae,
+propter nomen suum.
+Nam et si ambulavero in medio umbrae mortis,
+non timebo mala, quoniam tu mecum es:
+virga tua et baculus tuus ipsa me consolata sunt.
+EOF
 
-cp with-empty-lines-and-numbers.txt new.txt
-test_expect_success "merge with title" \
-	"git-merge-file new.txt orig.txt with-reference.txt"
+test_expect_success "expected conflict markers, with -L" \
+	"diff -u test.txt expect.txt"
 
 test_done
 
-- 
1.4.4.1.g064f-dirty

-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]