Skip to content
This repository
tree: 16d26b168b
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 107 lines (92 sloc) 3.056 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
#include "builtin.h"
#include "cache.h"
#include "xdiff/xdiff.h"
#include "xdiff-interface.h"
#include "parse-options.h"

static const char *const merge_file_usage[] = {
"git merge-file [options] [-L name1 [-L orig [-L name2]]] file1 orig_file file2",
NULL
};

static int label_cb(const struct option *opt, const char *arg, int unset)
{
static int label_count = 0;
const char **names = (const char **)opt->value;

if (label_count >= 3)
return error("too many labels on the command line");
names[label_count++] = arg;
return 0;
}

int cmd_merge_file(int argc, const char **argv, const char *prefix)
{
const char *names[3] = { NULL, NULL, NULL };
mmfile_t mmfs[3];
mmbuffer_t result = {NULL, 0};
xmparam_t xmp = {{0}};
int ret = 0, i = 0, to_stdout = 0;
int quiet = 0;
int prefixlen = 0;
struct option options[] = {
OPT_BOOLEAN('p', "stdout", &to_stdout, "send results to standard output"),
OPT_SET_INT(0, "diff3", &xmp.style, "use a diff3 based merge", XDL_MERGE_DIFF3),
OPT_SET_INT(0, "ours", &xmp.favor, "for conflicts, use our version",
XDL_MERGE_FAVOR_OURS),
OPT_SET_INT(0, "theirs", &xmp.favor, "for conflicts, use their version",
XDL_MERGE_FAVOR_THEIRS),
OPT_SET_INT(0, "union", &xmp.favor, "for conflicts, use a union version",
XDL_MERGE_FAVOR_UNION),
OPT_INTEGER(0, "marker-size", &xmp.marker_size,
"for conflicts, use this marker size"),
OPT__QUIET(&quiet, "do not warn about conflicts"),
OPT_CALLBACK('L', NULL, names, "name",
"set labels for file1/orig_file/file2", &label_cb),
OPT_END(),
};

xmp.level = XDL_MERGE_ZEALOUS_ALNUM;
xmp.style = 0;
xmp.favor = 0;

if (startup_info->have_repository) {
/* Read the configuration file */
git_config(git_xmerge_config, NULL);
if (0 <= git_xmerge_style)
xmp.style = git_xmerge_style;
}

argc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);
if (argc != 3)
usage_with_options(merge_file_usage, options);
if (quiet) {
if (!freopen("/dev/null", "w", stderr))
return error("failed to redirect stderr to /dev/null: "
"%s", strerror(errno));
}

if (prefix)
prefixlen = strlen(prefix);

for (i = 0; i < 3; i++) {
const char *fname = prefix_filename(prefix, prefixlen, argv[i]);
if (!names[i])
names[i] = argv[i];
if (read_mmfile(mmfs + i, fname))
return -1;
if (buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
return error("Cannot merge binary files: %s",
argv[i]);
}

xmp.ancestor = names[1];
xmp.file1 = names[0];
xmp.file2 = names[2];
ret = xdl_merge(mmfs + 1, mmfs + 0, mmfs + 2, &xmp, &result);

for (i = 0; i < 3; i++)
free(mmfs[i].ptr);

if (ret >= 0) {
const char *filename = argv[0];
FILE *f = to_stdout ? stdout : fopen(filename, "wb");

if (!f)
ret = error("Could not open %s for writing", filename);
else if (result.size &&
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;
}
Something went wrong with that request. Please try again.