3 #include "xdiff/xdiff.h"
4 #include "xdiff-interface.h"
5 #include "parse-options.h"
7 static const char *const merge_file_usage
[] = {
8 "git merge-file [options] [-L name1 [-L orig [-L name2]]] file1 orig_file file2",
12 static int label_cb(const struct option
*opt
, const char *arg
, int unset
)
14 static int label_count
= 0;
15 const char **names
= (const char **)opt
->value
;
18 return error("too many labels on the command line");
19 names
[label_count
++] = arg
;
23 int cmd_merge_file(int argc
, const char **argv
, const char *prefix
)
25 const char *names
[3] = { NULL
, NULL
, NULL
};
27 mmbuffer_t result
= {NULL
, 0};
28 xpparam_t xpp
= {XDF_NEED_MINIMAL
};
29 int ret
= 0, i
= 0, to_stdout
= 0;
30 int level
= XDL_MERGE_ZEALOUS_ALNUM
;
31 int style
= 0, quiet
= 0;
35 struct option options
[] = {
36 OPT_BOOLEAN('p', "stdout", &to_stdout
, "send results to standard output"),
37 OPT_SET_INT(0, "diff3", &style
, "use a diff3 based merge", XDL_MERGE_DIFF3
),
38 OPT_SET_INT(0, "ours", &favor
, "for conflicts, use our version",
39 XDL_MERGE_FAVOR_OURS
),
40 OPT_SET_INT(0, "theirs", &favor
, "for conflicts, use their version",
41 XDL_MERGE_FAVOR_THEIRS
),
43 OPT_CALLBACK('L', NULL
, names
, "name",
44 "set labels for file1/orig_file/file2", &label_cb
),
48 prefix
= setup_git_directory_gently(&nongit
);
50 /* Read the configuration file */
51 git_config(git_xmerge_config
, NULL
);
52 if (0 <= git_xmerge_style
)
53 style
= git_xmerge_style
;
56 argc
= parse_options(argc
, argv
, prefix
, options
, merge_file_usage
, 0);
58 usage_with_options(merge_file_usage
, options
);
60 if (!freopen("/dev/null", "w", stderr
))
61 return error("failed to redirect stderr to /dev/null: "
62 "%s\n", strerror(errno
));
65 for (i
= 0; i
< 3; i
++) {
68 if (read_mmfile(mmfs
+ i
, argv
[i
]))
70 if (buffer_is_binary(mmfs
[i
].ptr
, mmfs
[i
].size
))
71 return error("Cannot merge binary files: %s\n",
75 ret
= xdl_merge(mmfs
+ 1, mmfs
+ 0, names
[0], mmfs
+ 2, names
[2],
76 &xpp
, XDL_MERGE_FLAGS(level
, style
, favor
), &result
);
78 for (i
= 0; i
< 3; i
++)
82 const char *filename
= argv
[0];
83 FILE *f
= to_stdout
? stdout
: fopen(filename
, "wb");
86 ret
= error("Could not open %s for writing", filename
);
87 else if (result
.size
&&
88 fwrite(result
.ptr
, result
.size
, 1, f
) != 1)
89 ret
= error("Could not write to %s", filename
);
91 ret
= error("Could not close %s", filename
);