Skip to content

Commit

Permalink
Add builtin merge-file, a minimal replacement for RCS merge
Browse files Browse the repository at this point in the history
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.

[jc: further fix for compliation errors included.]

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
dscho authored and Junio C Hamano committed Dec 6, 2006
1 parent 98e6da8 commit ba1f5f3
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -275,6 +275,7 @@ BUILTIN_OBJS = \
builtin-ls-tree.o \
builtin-mailinfo.o \
builtin-mailsplit.o \
builtin-merge-file.o \
builtin-mv.o \
builtin-name-rev.o \
builtin-pack-objects.o \
Expand Down
72 changes: 72 additions & 0 deletions 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];
mmfile_t mmfs[3];
mmbuffer_t result = {NULL, 0};
xpparam_t xpp = {XDF_NEED_MINIMAL};
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;

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;
}
1 change: 1 addition & 0 deletions builtin.h
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions git.c
Expand Up @@ -247,6 +247,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 },
Expand Down
116 changes: 116 additions & 0 deletions t/t6023-merge-file.sh
@@ -0,0 +1,116 @@
#!/bin/sh

test_description='RCS merge replacement: merge-file'
. ./test-lib.sh

cat > orig.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 > 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.
EOF

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 > 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

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

cp new1.txt test.txt
test_expect_success "merge without conflict" \
"git-merge-file test.txt orig.txt new2.txt"

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 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

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"

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

test_expect_success "expected conflict markers, with -L" \
"diff -u test.txt expect.txt"

test_done

0 comments on commit ba1f5f3

Please sign in to comment.