static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, mmbuffer_t *result, const char *path_unused, mmfile_t *orig, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, int virtual_ancestor) { xpparam_t xpp; if (buffer_is_binary(orig->ptr, orig->size) || buffer_is_binary(src1->ptr, src1->size) || buffer_is_binary(src2->ptr, src2->size)) { warning("Cannot merge binary files: %s vs. %s\n", name1, name2); return ll_binary_merge(drv_unused, result, path_unused, orig, src1, name1, src2, name2, virtual_ancestor); } memset(&xpp, 0, sizeof(xpp)); return xdl_merge(orig, src1, name1, src2, name2, &xpp, XDL_MERGE_ZEALOUS, result); }
static int merge(const char *name, const char *path) { int ret; mmfile_t cur, base, other; mmbuffer_t result = {NULL, 0}; xpparam_t xpp = {XDF_NEED_MINIMAL}; if (handle_file(path, NULL, rr_path(name, "thisimage")) < 0) return 1; if (read_mmfile(&cur, rr_path(name, "thisimage")) || read_mmfile(&base, rr_path(name, "preimage")) || read_mmfile(&other, rr_path(name, "postimage"))) return 1; ret = xdl_merge(&base, &cur, "", &other, "", &xpp, XDL_MERGE_ZEALOUS, &result); if (!ret) { FILE *f = fopen(path, "w"); if (!f) return error("Could not open %s: %s", path, strerror(errno)); if (fwrite(result.ptr, result.size, 1, f) != 1) error("Could not write %s: %s", path, strerror(errno)); if (fclose(f)) return error("Writing %s failed: %s", path, strerror(errno)); } free(cur.ptr); free(base.ptr); free(other.ptr); free(result.ptr); return ret; }
static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, mmbuffer_t *result, const char *path, mmfile_t *orig, const char *orig_name, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, int flag, int marker_size) { xmparam_t xmp; if (buffer_is_binary(orig->ptr, orig->size) || buffer_is_binary(src1->ptr, src1->size) || buffer_is_binary(src2->ptr, src2->size)) { warning("Cannot merge binary files: %s (%s vs. %s)\n", path, name1, name2); return ll_binary_merge(drv_unused, result, path, orig, orig_name, src1, name1, src2, name2, flag, marker_size); } memset(&xmp, 0, sizeof(xmp)); xmp.level = XDL_MERGE_ZEALOUS; xmp.favor = ll_opt_favor(flag); if (git_xmerge_style >= 0) xmp.style = git_xmerge_style; if (marker_size > 0) xmp.marker_size = marker_size; xmp.ancestor = orig_name; xmp.file1 = name1; xmp.file2 = name2; return xdl_merge(orig, src1, src2, &xmp, result); }
static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, mmbuffer_t *result, const char *path, mmfile_t *orig, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, int flag, int marker_size) { xmparam_t xmp; int style = 0; int favor = (flag >> 1) & 03; if (buffer_is_binary(orig->ptr, orig->size) || buffer_is_binary(src1->ptr, src1->size) || buffer_is_binary(src2->ptr, src2->size)) { warning("Cannot merge binary files: %s (%s vs. %s)\n", path, name1, name2); return ll_binary_merge(drv_unused, result, path, orig, src1, name1, src2, name2, flag, marker_size); } memset(&xmp, 0, sizeof(xmp)); if (git_xmerge_style >= 0) style = git_xmerge_style; if (marker_size > 0) xmp.marker_size = marker_size; return xdl_merge(orig, src1, name1, src2, name2, &xmp, XDL_MERGE_FLAGS(XDL_MERGE_ZEALOUS, style, favor), result); }
static void *three_way_filemerge(mmfile_t *base, mmfile_t *our, mmfile_t *their, unsigned long *size) { mmbuffer_t res; xpparam_t xpp; int merge_status; memset(&xpp, 0, sizeof(xpp)); merge_status = xdl_merge(base, our, ".our", their, ".their", &xpp, XDL_MERGE_ZEALOUS, &res); if (merge_status < 0) return NULL; *size = res.size; return res.ptr; }
int git_merge_files( git_merge_file_result *out, git_merge_file_input *ancestor, git_merge_file_input *ours, git_merge_file_input *theirs, git_merge_automerge_flags flags) { xmparam_t xmparam; mmbuffer_t mmbuffer; int xdl_result; int error = 0; assert(out && ancestor && ours && theirs); memset(out, 0x0, sizeof(git_merge_file_result)); if (!GIT_MERGE_FILE_SIDE_EXISTS(ours) || !GIT_MERGE_FILE_SIDE_EXISTS(theirs)) return 0; memset(&xmparam, 0x0, sizeof(xmparam_t)); xmparam.ancestor = ancestor->label; xmparam.file1 = ours->label; xmparam.file2 = theirs->label; out->path = merge_file_best_path(ancestor, ours, theirs); out->mode = merge_file_best_mode(ancestor, ours, theirs); if (flags == GIT_MERGE_AUTOMERGE_FAVOR_OURS) xmparam.favor = XDL_MERGE_FAVOR_OURS; if (flags == GIT_MERGE_AUTOMERGE_FAVOR_THEIRS) xmparam.favor = XDL_MERGE_FAVOR_THEIRS; if ((xdl_result = xdl_merge(&ancestor->mmfile, &ours->mmfile, &theirs->mmfile, &xmparam, &mmbuffer)) < 0) { giterr_set(GITERR_MERGE, "Failed to merge files."); error = -1; goto done; } out->automergeable = (xdl_result == 0); out->data = (unsigned char *)mmbuffer.ptr; out->len = mmbuffer.size; done: return error; }
static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, mmbuffer_t *result, const char *path, mmfile_t *orig, const char *orig_name, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, const struct ll_merge_options *opts, int marker_size) { xmparam_t xmp; assert(opts); if (orig->size > MAX_XDIFF_SIZE || src1->size > MAX_XDIFF_SIZE || src2->size > MAX_XDIFF_SIZE || buffer_is_binary(orig->ptr, orig->size) || buffer_is_binary(src1->ptr, src1->size) || buffer_is_binary(src2->ptr, src2->size)) { return ll_binary_merge(drv_unused, result, path, orig, orig_name, src1, name1, src2, name2, opts, marker_size); } memset(&xmp, 0, sizeof(xmp)); xmp.level = XDL_MERGE_ZEALOUS; xmp.favor = opts->variant; xmp.mark_all = opts->mark_all_changes; xmp.xpp.flags = opts->xdl_opts; if (git_xmerge_style >= 0) xmp.style = git_xmerge_style; if (marker_size > 0) xmp.marker_size = marker_size; xmp.ancestor = orig_name; xmp.file1 = name1; xmp.file2 = name2; return xdl_merge(orig, src1, src2, &xmp, result); }
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; }
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 = {{XDF_NEED_MINIMAL}}; int ret = 0, i = 0, to_stdout = 0; int level = XDL_MERGE_ZEALOUS_ALNUM; int style = 0, quiet = 0; int favor = 0; int nongit; struct option options[] = { OPT_BOOLEAN('p', "stdout", &to_stdout, "send results to standard output"), OPT_SET_INT(0, "diff3", &style, "use a diff3 based merge", XDL_MERGE_DIFF3), OPT_SET_INT(0, "ours", &favor, "for conflicts, use our version", XDL_MERGE_FAVOR_OURS), OPT_SET_INT(0, "theirs", &favor, "for conflicts, use their version", XDL_MERGE_FAVOR_THEIRS), OPT__QUIET(&quiet), OPT_CALLBACK('L', NULL, names, "name", "set labels for file1/orig_file/file2", &label_cb), OPT_END(), }; prefix = setup_git_directory_gently(&nongit); if (!nongit) { /* Read the configuration file */ git_config(git_xmerge_config, NULL); if (0 <= git_xmerge_style) 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\n", strerror(errno)); } for (i = 0; i < 3; i++) { if (!names[i]) names[i] = argv[i]; if (read_mmfile(mmfs + i, argv[i])) return -1; if (buffer_is_binary(mmfs[i].ptr, mmfs[i].size)) return error("Cannot merge binary files: %s\n", argv[i]); } ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2], &xmp, XDL_MERGE_FLAGS(level, style, favor), &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; }