]> git.ipfire.org Git - thirdparty/git.git/blobdiff - ll-merge.c
treewide: remove cache.h inclusion due to object.h changes
[thirdparty/git.git] / ll-merge.c
index 9a8a2c365c7a33fbf1fb4b1a50505ea19fe5558d..28bc94c45d63015bd6eb7f971d4e78bf55a4deba 100644 (file)
@@ -6,15 +6,17 @@
 
 #include "cache.h"
 #include "config.h"
+#include "convert.h"
 #include "attr.h"
 #include "xdiff-interface.h"
 #include "run-command.h"
 #include "ll-merge.h"
 #include "quote.h"
+#include "wrapper.h"
 
 struct ll_merge_driver;
 
-typedef int (*ll_merge_fn)(const struct ll_merge_driver *,
+typedef enum ll_merge_result (*ll_merge_fn)(const struct ll_merge_driver *,
                           mmbuffer_t *result,
                           const char *path,
                           mmfile_t *orig, const char *orig_name,
@@ -49,15 +51,16 @@ void reset_merge_attributes(void)
 /*
  * Built-in low-levels
  */
-static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
+static enum ll_merge_result ll_binary_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 char *path UNUSED,
+                          mmfile_t *orig, const char *orig_name UNUSED,
+                          mmfile_t *src1, const char *name1 UNUSED,
+                          mmfile_t *src2, const char *name2 UNUSED,
                           const struct ll_merge_options *opts,
-                          int marker_size)
+                          int marker_size UNUSED)
 {
+       enum ll_merge_result ret;
        mmfile_t *stolen;
        assert(opts);
 
@@ -68,16 +71,19 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
         */
        if (opts->virtual_ancestor) {
                stolen = orig;
+               ret = LL_MERGE_OK;
        } else {
                switch (opts->variant) {
                default:
-                       warning("Cannot merge binary files: %s (%s vs. %s)",
-                               path, name1, name2);
-                       /* fallthru */
+                       ret = LL_MERGE_BINARY_CONFLICT;
+                       stolen = src1;
+                       break;
                case XDL_MERGE_FAVOR_OURS:
+                       ret = LL_MERGE_OK;
                        stolen = src1;
                        break;
                case XDL_MERGE_FAVOR_THEIRS:
+                       ret = LL_MERGE_OK;
                        stolen = src2;
                        break;
                }
@@ -87,14 +93,10 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
        result->size = stolen->size;
        stolen->ptr = NULL;
 
-       /*
-        * With -Xtheirs or -Xours, we have cleanly merged;
-        * otherwise we got a conflict.
-        */
-       return (opts->variant ? 0 : 1);
+       return ret;
 }
 
-static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
+static enum ll_merge_result ll_xdl_merge(const struct ll_merge_driver *drv_unused,
                        mmbuffer_t *result,
                        const char *path,
                        mmfile_t *orig, const char *orig_name,
@@ -103,7 +105,9 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
                        const struct ll_merge_options *opts,
                        int marker_size)
 {
+       enum ll_merge_result ret;
        xmparam_t xmp;
+       int status;
        assert(opts);
 
        if (orig->size > MAX_XDIFF_SIZE ||
@@ -131,12 +135,14 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
        xmp.ancestor = orig_name;
        xmp.file1 = name1;
        xmp.file2 = name2;
-       return xdl_merge(orig, src1, src2, &xmp, result);
+       status = xdl_merge(orig, src1, src2, &xmp, result);
+       ret = (status > 0) ? LL_MERGE_CONFLICT : status;
+       return ret;
 }
 
-static int ll_union_merge(const struct ll_merge_driver *drv_unused,
+static enum ll_merge_result ll_union_merge(const struct ll_merge_driver *drv_unused,
                          mmbuffer_t *result,
-                         const char *path_unused,
+                         const char *path,
                          mmfile_t *orig, const char *orig_name,
                          mmfile_t *src1, const char *name1,
                          mmfile_t *src2, const char *name2,
@@ -148,8 +154,8 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused,
        assert(opts);
        o = *opts;
        o.variant = XDL_MERGE_FAVOR_UNION;
-       return ll_xdl_merge(drv_unused, result, path_unused,
-                           orig, NULL, src1, NULL, src2, NULL,
+       return ll_xdl_merge(drv_unused, result, path,
+                           orig, orig_name, src1, name1, src2, name2,
                            &o, marker_size);
 }
 
@@ -176,12 +182,12 @@ static void create_temp(mmfile_t *src, char *path, size_t len)
 /*
  * User defined low-level merge driver support.
  */
-static int ll_ext_merge(const struct ll_merge_driver *fn,
+static enum ll_merge_result ll_ext_merge(const struct ll_merge_driver *fn,
                        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,
+                       mmfile_t *orig, const char *orig_name UNUSED,
+                       mmfile_t *src1, const char *name1 UNUSED,
+                       mmfile_t *src2, const char *name2 UNUSED,
                        const struct ll_merge_options *opts,
                        int marker_size)
 {
@@ -189,9 +195,10 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
        struct strbuf cmd = STRBUF_INIT;
        struct strbuf_expand_dict_entry dict[6];
        struct strbuf path_sq = STRBUF_INIT;
-       const char *args[] = { NULL, NULL };
+       struct child_process child = CHILD_PROCESS_INIT;
        int status, fd, i;
        struct stat st;
+       enum ll_merge_result ret;
        assert(opts);
 
        sq_quote_buf(&path_sq, path);
@@ -202,7 +209,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
        dict[4].placeholder = "P"; dict[4].value = path_sq.buf;
        dict[5].placeholder = NULL; dict[5].value = NULL;
 
-       if (fn->cmdline == NULL)
+       if (!fn->cmdline)
                die("custom merge driver %s lacks command line.", fn->name);
 
        result->ptr = NULL;
@@ -214,8 +221,9 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
 
        strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict);
 
-       args[0] = cmd.buf;
-       status = run_command_v_opt(args, RUN_USING_SHELL);
+       child.use_shell = 1;
+       strvec_push(&child.args, cmd.buf);
+       status = run_command(&child);
        fd = open(temp[1], O_RDONLY);
        if (fd < 0)
                goto bad;
@@ -234,7 +242,8 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
                unlink_or_warn(temp[i]);
        strbuf_release(&cmd);
        strbuf_release(&path_sq);
-       return status;
+       ret = (status > 0) ? LL_MERGE_CONFLICT : status;
+       return ret;
 }
 
 /*
@@ -243,7 +252,8 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
 static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail;
 static const char *default_ll_merge;
 
-static int read_merge_config(const char *var, const char *value, void *cb)
+static int read_merge_config(const char *var, const char *value,
+                            void *cb UNUSED)
 {
        struct ll_merge_driver *fn;
        const char *key, *name;
@@ -360,7 +370,7 @@ static void normalize_file(mmfile_t *mm, const char *path, struct index_state *i
        }
 }
 
-int ll_merge(mmbuffer_t *result_buf,
+enum ll_merge_result ll_merge(mmbuffer_t *result_buf,
             const char *path,
             mmfile_t *ancestor, const char *ancestor_label,
             mmfile_t *ours, const char *our_label,
@@ -383,7 +393,7 @@ int ll_merge(mmbuffer_t *result_buf,
                normalize_file(theirs, path, istate);
        }
 
-       git_check_attr(istate, path, check);
+       git_check_attr(istate, NULL, path, check);
        ll_driver_name = check->items[0].value;
        if (check->items[1].value) {
                marker_size = atoi(check->items[1].value);
@@ -411,7 +421,7 @@ int ll_merge_marker_size(struct index_state *istate, const char *path)
 
        if (!check)
                check = attr_check_initl("conflict-marker-size", NULL);
-       git_check_attr(istate, path, check);
+       git_check_attr(istate, NULL, path, check);
        if (check->items[0].value) {
                marker_size = atoi(check->items[0].value);
                if (marker_size <= 0)