diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:34:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:34:27 +0000 |
commit | 4dbdc42d9e7c3968ff7f690d00680419c9b8cb0f (patch) | |
tree | 47c1d492e9c956c1cd2b74dbd3b9d8b0db44dc4e /merge-blobs.c | |
parent | Initial commit. (diff) | |
download | git-4dbdc42d9e7c3968ff7f690d00680419c9b8cb0f.tar.xz git-4dbdc42d9e7c3968ff7f690d00680419c9b8cb0f.zip |
Adding upstream version 1:2.43.0.upstream/1%2.43.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'merge-blobs.c')
-rw-r--r-- | merge-blobs.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/merge-blobs.c b/merge-blobs.c new file mode 100644 index 0000000..9293cbf --- /dev/null +++ b/merge-blobs.c @@ -0,0 +1,106 @@ +#include "git-compat-util.h" +#include "run-command.h" +#include "xdiff-interface.h" +#include "merge-ll.h" +#include "blob.h" +#include "merge-blobs.h" +#include "object-store-ll.h" + +static int fill_mmfile_blob(mmfile_t *f, struct blob *obj) +{ + void *buf; + unsigned long size; + enum object_type type; + + buf = repo_read_object_file(the_repository, &obj->object.oid, &type, + &size); + if (!buf) + return -1; + if (type != OBJ_BLOB) { + free(buf); + return -1; + } + f->ptr = buf; + f->size = size; + return 0; +} + +static void free_mmfile(mmfile_t *f) +{ + free(f->ptr); +} + +static void *three_way_filemerge(struct index_state *istate, + const char *path, + mmfile_t *base, + mmfile_t *our, + mmfile_t *their, + unsigned long *size) +{ + enum ll_merge_result merge_status; + mmbuffer_t res; + + /* + * This function is only used by cmd_merge_tree, which + * does not respect the merge.conflictstyle option. + * There is no need to worry about a label for the + * common ancestor. + */ + merge_status = ll_merge(&res, path, base, NULL, + our, ".our", their, ".their", + istate, NULL); + if (merge_status < 0) + return NULL; + if (merge_status == LL_MERGE_BINARY_CONFLICT) + warning("Cannot merge binary files: %s (%s vs. %s)", + path, ".our", ".their"); + + *size = res.size; + return res.ptr; +} + +void *merge_blobs(struct index_state *istate, const char *path, + struct blob *base, struct blob *our, + struct blob *their, unsigned long *size) +{ + void *res = NULL; + mmfile_t f1, f2, common; + + /* + * Removed in either branch? + * + * NOTE! This depends on the caller having done the + * proper warning about removing a file that got + * modified in the other branch! + */ + if (!our || !their) { + enum object_type type; + if (base) + return NULL; + if (!our) + our = their; + return repo_read_object_file(the_repository, &our->object.oid, + &type, size); + } + + if (fill_mmfile_blob(&f1, our) < 0) + goto out_no_mmfile; + if (fill_mmfile_blob(&f2, their) < 0) + goto out_free_f1; + + if (base) { + if (fill_mmfile_blob(&common, base) < 0) + goto out_free_f2_f1; + } else { + common.ptr = xstrdup(""); + common.size = 0; + } + res = three_way_filemerge(istate, path, &common, &f1, &f2, size); + free_mmfile(&common); +out_free_f2_f1: + free_mmfile(&f2); +out_free_f1: + free_mmfile(&f1); +out_no_mmfile: + return res; +} |