]>
git.ipfire.org Git - thirdparty/git.git/blob - builtin/merge-file.c
5 #include "xdiff/xdiff.h"
6 #include "xdiff-interface.h"
7 #include "parse-options.h"
9 static const char *const merge_file_usage
[] = {
10 N_("git merge-file [<options>] [-L <name1> [-L <orig> [-L <name2>]]] <file1> <orig-file> <file2>"),
14 static int label_cb(const struct option
*opt
, const char *arg
, int unset
)
16 static int label_count
= 0;
17 const char **names
= (const char **)opt
->value
;
19 BUG_ON_OPT_NEG(unset
);
22 return error("too many labels on the command line");
23 names
[label_count
++] = arg
;
27 int cmd_merge_file(int argc
, const char **argv
, const char *prefix
)
29 const char *names
[3] = { 0 };
30 mmfile_t mmfs
[3] = { 0 };
31 mmbuffer_t result
= { 0 };
32 xmparam_t xmp
= { 0 };
33 int ret
= 0, i
= 0, to_stdout
= 0;
35 struct option options
[] = {
36 OPT_BOOL('p', "stdout", &to_stdout
, N_("send results to standard output")),
37 OPT_SET_INT(0, "diff3", &xmp
.style
, N_("use a diff3 based merge"), XDL_MERGE_DIFF3
),
38 OPT_SET_INT(0, "zdiff3", &xmp
.style
, N_("use a zealous diff3 based merge"),
39 XDL_MERGE_ZEALOUS_DIFF3
),
40 OPT_SET_INT(0, "ours", &xmp
.favor
, N_("for conflicts, use our version"),
41 XDL_MERGE_FAVOR_OURS
),
42 OPT_SET_INT(0, "theirs", &xmp
.favor
, N_("for conflicts, use their version"),
43 XDL_MERGE_FAVOR_THEIRS
),
44 OPT_SET_INT(0, "union", &xmp
.favor
, N_("for conflicts, use a union version"),
45 XDL_MERGE_FAVOR_UNION
),
46 OPT_INTEGER(0, "marker-size", &xmp
.marker_size
,
47 N_("for conflicts, use this marker size")),
48 OPT__QUIET(&quiet
, N_("do not warn about conflicts")),
49 OPT_CALLBACK('L', NULL
, names
, N_("name"),
50 N_("set labels for file1/orig-file/file2"), &label_cb
),
54 xmp
.level
= XDL_MERGE_ZEALOUS_ALNUM
;
58 if (startup_info
->have_repository
) {
59 /* Read the configuration file */
60 git_config(git_xmerge_config
, NULL
);
61 if (0 <= git_xmerge_style
)
62 xmp
.style
= git_xmerge_style
;
65 argc
= parse_options(argc
, argv
, prefix
, options
, merge_file_usage
, 0);
67 usage_with_options(merge_file_usage
, options
);
69 if (!freopen("/dev/null", "w", stderr
))
70 return error_errno("failed to redirect stderr to /dev/null");
73 for (i
= 0; i
< 3; i
++) {
75 mmfile_t
*mmf
= mmfs
+ i
;
80 fname
= prefix_filename(prefix
, argv
[i
]);
82 if (read_mmfile(mmf
, fname
))
84 else if (mmf
->size
> MAX_XDIFF_SIZE
||
85 buffer_is_binary(mmf
->ptr
, mmf
->size
))
86 ret
= error("Cannot merge binary files: %s",
95 xmp
.ancestor
= names
[1];
98 ret
= xdl_merge(mmfs
+ 1, mmfs
+ 0, mmfs
+ 2, &xmp
, &result
);
101 const char *filename
= argv
[0];
102 char *fpath
= prefix_filename(prefix
, argv
[0]);
103 FILE *f
= to_stdout
? stdout
: fopen(fpath
, "wb");
106 ret
= error_errno("Could not open %s for writing",
108 else if (result
.size
&&
109 fwrite(result
.ptr
, result
.size
, 1, f
) != 1)
110 ret
= error_errno("Could not write to %s", filename
);
112 ret
= error_errno("Could not close %s", filename
);
121 for (i
= 0; i
< 3; i
++)