2 #include "run-command.h"
3 #include "xdiff-interface.h"
6 #include "merge-blobs.h"
8 static int fill_mmfile_blob(mmfile_t
*f
, struct blob
*obj
)
12 enum object_type type
;
14 buf
= read_sha1_file(obj
->object
.sha1
, &type
, &size
);
17 if (type
!= OBJ_BLOB
) {
26 static void free_mmfile(mmfile_t
*f
)
31 static void *three_way_filemerge(const char *path
, mmfile_t
*base
, mmfile_t
*our
, mmfile_t
*their
, unsigned long *size
)
37 * This function is only used by cmd_merge_tree, which
38 * does not respect the merge.conflictstyle option.
39 * There is no need to worry about a label for the
42 merge_status
= ll_merge(&res
, path
, base
, NULL
,
43 our
, ".our", their
, ".their", NULL
);
51 static int common_outf(void *priv_
, mmbuffer_t
*mb
, int nbuf
)
54 mmfile_t
*dst
= priv_
;
56 for (i
= 0; i
< nbuf
; i
++) {
57 memcpy(dst
->ptr
+ dst
->size
, mb
[i
].ptr
, mb
[i
].size
);
58 dst
->size
+= mb
[i
].size
;
63 static int generate_common_file(mmfile_t
*res
, mmfile_t
*f1
, mmfile_t
*f2
)
65 unsigned long size
= f1
->size
< f2
->size
? f1
->size
: f2
->size
;
66 void *ptr
= xmalloc(size
);
71 memset(&xpp
, 0, sizeof(xpp
));
73 memset(&xecfg
, 0, sizeof(xecfg
));
75 xecfg
.flags
= XDL_EMIT_COMMON
;
76 ecb
.outf
= common_outf
;
82 return xdi_diff(f1
, f2
, &xpp
, &xecfg
, &ecb
);
85 void *merge_blobs(const char *path
, struct blob
*base
, struct blob
*our
, struct blob
*their
, unsigned long *size
)
88 mmfile_t f1
, f2
, common
;
91 * Removed in either branch?
93 * NOTE! This depends on the caller having done the
94 * proper warning about removing a file that got
95 * modified in the other branch!
98 enum object_type type
;
103 return read_sha1_file(our
->object
.sha1
, &type
, size
);
106 if (fill_mmfile_blob(&f1
, our
) < 0)
108 if (fill_mmfile_blob(&f2
, their
) < 0)
112 if (fill_mmfile_blob(&common
, base
) < 0)
115 if (generate_common_file(&common
, &f1
, &f2
) < 0)
118 res
= three_way_filemerge(path
, &common
, &f1
, &f2
, size
);
119 free_mmfile(&common
);