merge-blobs.con commit Merge branch 'mh/packed-ref-store-prep' into maint (6b89503)
   1#include "cache.h"
   2#include "run-command.h"
   3#include "xdiff-interface.h"
   4#include "ll-merge.h"
   5#include "blob.h"
   6#include "merge-blobs.h"
   7
   8static int fill_mmfile_blob(mmfile_t *f, struct blob *obj)
   9{
  10        void *buf;
  11        unsigned long size;
  12        enum object_type type;
  13
  14        buf = read_sha1_file(obj->object.oid.hash, &type, &size);
  15        if (!buf)
  16                return -1;
  17        if (type != OBJ_BLOB) {
  18                free(buf);
  19                return -1;
  20        }
  21        f->ptr = buf;
  22        f->size = size;
  23        return 0;
  24}
  25
  26static void free_mmfile(mmfile_t *f)
  27{
  28        free(f->ptr);
  29}
  30
  31static void *three_way_filemerge(const char *path, mmfile_t *base, mmfile_t *our, mmfile_t *their, unsigned long *size)
  32{
  33        int merge_status;
  34        mmbuffer_t res;
  35
  36        /*
  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
  40         * common ancestor.
  41         */
  42        merge_status = ll_merge(&res, path, base, NULL,
  43                                our, ".our", their, ".their", NULL);
  44        if (merge_status < 0)
  45                return NULL;
  46
  47        *size = res.size;
  48        return res.ptr;
  49}
  50
  51void *merge_blobs(const char *path, struct blob *base, struct blob *our, struct blob *their, unsigned long *size)
  52{
  53        void *res = NULL;
  54        mmfile_t f1, f2, common;
  55
  56        /*
  57         * Removed in either branch?
  58         *
  59         * NOTE! This depends on the caller having done the
  60         * proper warning about removing a file that got
  61         * modified in the other branch!
  62         */
  63        if (!our || !their) {
  64                enum object_type type;
  65                if (base)
  66                        return NULL;
  67                if (!our)
  68                        our = their;
  69                return read_sha1_file(our->object.oid.hash, &type, size);
  70        }
  71
  72        if (fill_mmfile_blob(&f1, our) < 0)
  73                goto out_no_mmfile;
  74        if (fill_mmfile_blob(&f2, their) < 0)
  75                goto out_free_f1;
  76
  77        if (base) {
  78                if (fill_mmfile_blob(&common, base) < 0)
  79                        goto out_free_f2_f1;
  80        } else {
  81                common.ptr = xstrdup("");
  82                common.size = 0;
  83        }
  84        res = three_way_filemerge(path, &common, &f1, &f2, size);
  85        free_mmfile(&common);
  86out_free_f2_f1:
  87        free_mmfile(&f2);
  88out_free_f1:
  89        free_mmfile(&f1);
  90out_no_mmfile:
  91        return res;
  92}