41fb92edfbd0512542f277b7e7e4af30e25283be
   1#include "cache.h"
   2#include "xdiff/xdiff.h"
   3
   4static const char merge_file_usage[] =
   5"git merge-file [-L name1 [-L orig [-L name2]]] file1 orig_file file2";
   6
   7static int read_file(mmfile_t *ptr, const char *filename)
   8{
   9        struct stat st;
  10        FILE *f;
  11
  12        if (stat(filename, &st))
  13                return error("Could not stat %s", filename);
  14        if ((f = fopen(filename, "rb")) == NULL)
  15                return error("Could not open %s", filename);
  16        ptr->ptr = xmalloc(st.st_size);
  17        if (fread(ptr->ptr, st.st_size, 1, f) != 1)
  18                return error("Could not read %s", filename);
  19        fclose(f);
  20        ptr->size = st.st_size;
  21        return 0;
  22}
  23
  24int cmd_merge_file(int argc, char **argv, char **envp)
  25{
  26        char *names[3];
  27        mmfile_t mmfs[3];
  28        mmbuffer_t result = {NULL, 0};
  29        xpparam_t xpp = {XDF_NEED_MINIMAL};
  30        int ret = 0, i = 0;
  31
  32        while (argc > 4) {
  33                if (!strcmp(argv[1], "-L")) {
  34                        names[i++] = argv[2];
  35                        argc -= 2;
  36                        argv += 2;
  37                        continue;
  38                }
  39                usage(merge_file_usage);
  40        }
  41
  42        if (argc != 4)
  43                usage(merge_file_usage);
  44
  45        for (; i < 3; i++)
  46                names[i] = argv[i + 1];
  47
  48        for (i = 0; i < 3; i++)
  49                if (read_file(mmfs + i, argv[i + 1]))
  50                        return -1;
  51
  52        ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],
  53                        &xpp, XDL_MERGE_ZEALOUS, &result);
  54
  55        for (i = 0; i < 3; i++)
  56                free(mmfs[i].ptr);
  57
  58        if (ret >= 0) {
  59                char *filename = argv[1];
  60                FILE *f = fopen(filename, "wb");
  61
  62                if (!f)
  63                        ret = error("Could not open %s for writing", filename);
  64                else if (fwrite(result.ptr, result.size, 1, f) != 1)
  65                        ret = error("Could not write to %s", filename);
  66                else if (fclose(f))
  67                        ret = error("Could not close %s", filename);
  68                free(result.ptr);
  69        }
  70
  71        return ret;
  72}