fetch and pull: learn --progress
[gitweb.git] / rerere.c
index d92990a6bba01c321bb67bd07287772075f6994a..d1d3e753955146cadfaf6da274487a4a369f0521 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -1,11 +1,11 @@
 #include "cache.h"
 #include "string-list.h"
 #include "rerere.h"
-#include "xdiff/xdiff.h"
 #include "xdiff-interface.h"
 #include "dir.h"
 #include "resolve-undo.h"
 #include "ll-merge.h"
+#include "attr.h"
 
 /* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
 static int rerere_enabled = -1;
@@ -99,6 +99,28 @@ static void rerere_io_putstr(const char *str, struct rerere_io *io)
                ferr_puts(str, io->output, &io->wrerror);
 }
 
+static void rerere_io_putconflict(int ch, int size, struct rerere_io *io)
+{
+       char buf[64];
+
+       while (size) {
+               if (size < sizeof(buf) - 2) {
+                       memset(buf, ch, size);
+                       buf[size] = '\n';
+                       buf[size + 1] = '\0';
+                       size = 0;
+               } else {
+                       int sz = sizeof(buf) - 1;
+                       if (size <= sz)
+                               sz -= (sz - size) + 1;
+                       memset(buf, ch, sz);
+                       buf[sz] = '\0';
+                       size -= sz;
+               }
+               rerere_io_putstr(buf, io);
+       }
+}
+
 static void rerere_io_putmem(const char *mem, size_t sz, struct rerere_io *io)
 {
        if (io->output)
@@ -116,7 +138,17 @@ static int rerere_file_getline(struct strbuf *sb, struct rerere_io *io_)
        return strbuf_getwholeline(sb, io->input, '\n');
 }
 
-static int handle_path(unsigned char *sha1, struct rerere_io *io)
+static int is_cmarker(char *buf, int marker_char, int marker_size, int want_sp)
+{
+       while (marker_size--)
+               if (*buf++ != marker_char)
+                       return 0;
+       if (want_sp && *buf != ' ')
+               return 0;
+       return isspace(*buf);
+}
+
+static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_size)
 {
        git_SHA_CTX ctx;
        int hunk_no = 0;
@@ -130,30 +162,30 @@ static int handle_path(unsigned char *sha1, struct rerere_io *io)
                git_SHA1_Init(&ctx);
 
        while (!io->getline(&buf, io)) {
-               if (!prefixcmp(buf.buf, "<<<<<<< ")) {
+               if (is_cmarker(buf.buf, '<', marker_size, 1)) {
                        if (hunk != RR_CONTEXT)
                                goto bad;
                        hunk = RR_SIDE_1;
-               } else if (!prefixcmp(buf.buf, "|||||||") && isspace(buf.buf[7])) {
+               } else if (is_cmarker(buf.buf, '|', marker_size, 0)) {
                        if (hunk != RR_SIDE_1)
                                goto bad;
                        hunk = RR_ORIGINAL;
-               } else if (!prefixcmp(buf.buf, "=======") && isspace(buf.buf[7])) {
+               } else if (is_cmarker(buf.buf, '=', marker_size, 0)) {
                        if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL)
                                goto bad;
                        hunk = RR_SIDE_2;
-               } else if (!prefixcmp(buf.buf, ">>>>>>> ")) {
+               } else if (is_cmarker(buf.buf, '>', marker_size, 1)) {
                        if (hunk != RR_SIDE_2)
                                goto bad;
                        if (strbuf_cmp(&one, &two) > 0)
                                strbuf_swap(&one, &two);
                        hunk_no++;
                        hunk = RR_CONTEXT;
-                       rerere_io_putstr("<<<<<<<\n", io);
+                       rerere_io_putconflict('<', marker_size, io);
                        rerere_io_putmem(one.buf, one.len, io);
-                       rerere_io_putstr("=======\n", io);
+                       rerere_io_putconflict('=', marker_size, io);
                        rerere_io_putmem(two.buf, two.len, io);
-                       rerere_io_putstr(">>>>>>>\n", io);
+                       rerere_io_putconflict('>', marker_size, io);
                        if (sha1) {
                                git_SHA1_Update(&ctx, one.buf ? one.buf : "",
                                            one.len + 1);
@@ -190,6 +222,7 @@ static int handle_file(const char *path, unsigned char *sha1, const char *output
 {
        int hunk_no = 0;
        struct rerere_io_file io;
+       int marker_size = ll_merge_marker_size(path);
 
        memset(&io, 0, sizeof(io));
        io.io.getline = rerere_file_getline;
@@ -206,7 +239,7 @@ static int handle_file(const char *path, unsigned char *sha1, const char *output
                }
        }
 
-       hunk_no = handle_path(sha1, (struct rerere_io *)&io);
+       hunk_no = handle_path(sha1, (struct rerere_io *)&io, marker_size);
 
        fclose(io.input);
        if (io.io.wrerror)
@@ -256,6 +289,7 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu
        struct cache_entry *ce;
        int pos, len, i, hunk_no;
        struct rerere_io_mem io;
+       int marker_size = ll_merge_marker_size(path);
 
        /*
         * Reproduce the conflicted merge in-core
@@ -291,7 +325,7 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu
        for (i = 0; i < 3; i++)
                free(mmfile[i].ptr);
 
-       memset(&io, 0, sizeof(&io));
+       memset(&io, 0, sizeof(io));
        io.io.getline = rerere_mem_getline;
        if (output)
                io.io.output = fopen(output, "w");
@@ -300,7 +334,7 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu
        strbuf_init(&io.input, 0);
        strbuf_attach(&io.input, result.ptr, result.size, result.size);
 
-       hunk_no = handle_path(sha1, (struct rerere_io *)&io);
+       hunk_no = handle_path(sha1, (struct rerere_io *)&io, marker_size);
        strbuf_release(&io.input);
        if (io.io.output)
                fclose(io.io.output);
@@ -332,7 +366,6 @@ static int merge(const char *name, const char *path)
        int ret;
        mmfile_t cur, base, other;
        mmbuffer_t result = {NULL, 0};
-       xpparam_t xpp = {XDF_NEED_MINIMAL};
 
        if (handle_file(path, NULL, rerere_path(name, "thisimage")) < 0)
                return 1;
@@ -341,8 +374,7 @@ static int merge(const char *name, const char *path)
                        read_mmfile(&base, rerere_path(name, "preimage")) ||
                        read_mmfile(&other, rerere_path(name, "postimage")))
                return 1;
-       ret = xdl_merge(&base, &cur, "", &other, "",
-                       &xpp, XDL_MERGE_ZEALOUS, &result);
+       ret = ll_merge(&result, path, &base, &cur, "", &other, "", 0);
        if (!ret) {
                FILE *f = fopen(path, "w");
                if (!f)
@@ -493,7 +525,7 @@ static int is_rerere_enabled(void)
        return 1;
 }
 
-int setup_rerere(struct string_list *merge_rr)
+int setup_rerere(struct string_list *merge_rr, int flags)
 {
        int fd;
 
@@ -501,6 +533,8 @@ int setup_rerere(struct string_list *merge_rr)
        if (!is_rerere_enabled())
                return -1;
 
+       if (flags & (RERERE_AUTOUPDATE|RERERE_NOAUTOUPDATE))
+               rerere_autoupdate = !!(flags & RERERE_AUTOUPDATE);
        merge_rr_path = git_pathdup("MERGE_RR");
        fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
                                       LOCK_DIE_ON_ERROR);
@@ -508,12 +542,12 @@ int setup_rerere(struct string_list *merge_rr)
        return fd;
 }
 
-int rerere(void)
+int rerere(int flags)
 {
        struct string_list merge_rr = { NULL, 0, 0, 1 };
        int fd;
 
-       fd = setup_rerere(&merge_rr);
+       fd = setup_rerere(&merge_rr, flags);
        if (fd < 0)
                return 0;
        return do_plain_rerere(&merge_rr, fd);
@@ -554,7 +588,7 @@ int rerere_forget(const char **pathspec)
        if (read_cache() < 0)
                return error("Could not read index");
 
-       fd = setup_rerere(&merge_rr);
+       fd = setup_rerere(&merge_rr, RERERE_NOAUTOUPDATE);
 
        unmerge_cache(pathspec);
        find_conflict(&conflict);