rerere.con commit rerere: use ll_merge() instead of using xdl_merge() (88533f6)
   1#include "cache.h"
   2#include "string-list.h"
   3#include "rerere.h"
   4#include "xdiff-interface.h"
   5#include "dir.h"
   6#include "resolve-undo.h"
   7#include "ll-merge.h"
   8
   9/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
  10static int rerere_enabled = -1;
  11
  12/* automatically update cleanly resolved paths to the index */
  13static int rerere_autoupdate;
  14
  15static char *merge_rr_path;
  16
  17const char *rerere_path(const char *hex, const char *file)
  18{
  19        return git_path("rr-cache/%s/%s", hex, file);
  20}
  21
  22int has_rerere_resolution(const char *hex)
  23{
  24        struct stat st;
  25        return !stat(rerere_path(hex, "postimage"), &st);
  26}
  27
  28static void read_rr(struct string_list *rr)
  29{
  30        unsigned char sha1[20];
  31        char buf[PATH_MAX];
  32        FILE *in = fopen(merge_rr_path, "r");
  33        if (!in)
  34                return;
  35        while (fread(buf, 40, 1, in) == 1) {
  36                int i;
  37                char *name;
  38                if (get_sha1_hex(buf, sha1))
  39                        die("corrupt MERGE_RR");
  40                buf[40] = '\0';
  41                name = xstrdup(buf);
  42                if (fgetc(in) != '\t')
  43                        die("corrupt MERGE_RR");
  44                for (i = 0; i < sizeof(buf) && (buf[i] = fgetc(in)); i++)
  45                        ; /* do nothing */
  46                if (i == sizeof(buf))
  47                        die("filename too long");
  48                string_list_insert(buf, rr)->util = name;
  49        }
  50        fclose(in);
  51}
  52
  53static struct lock_file write_lock;
  54
  55static int write_rr(struct string_list *rr, int out_fd)
  56{
  57        int i;
  58        for (i = 0; i < rr->nr; i++) {
  59                const char *path;
  60                int length;
  61                if (!rr->items[i].util)
  62                        continue;
  63                path = rr->items[i].string;
  64                length = strlen(path) + 1;
  65                if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
  66                    write_str_in_full(out_fd, "\t") != 1 ||
  67                    write_in_full(out_fd, path, length) != length)
  68                        die("unable to write rerere record");
  69        }
  70        if (commit_lock_file(&write_lock) != 0)
  71                die("unable to write rerere record");
  72        return 0;
  73}
  74
  75static void ferr_write(const void *p, size_t count, FILE *fp, int *err)
  76{
  77        if (!count || *err)
  78                return;
  79        if (fwrite(p, count, 1, fp) != 1)
  80                *err = errno;
  81}
  82
  83static inline void ferr_puts(const char *s, FILE *fp, int *err)
  84{
  85        ferr_write(s, strlen(s), fp, err);
  86}
  87
  88struct rerere_io {
  89        int (*getline)(struct strbuf *, struct rerere_io *);
  90        FILE *output;
  91        int wrerror;
  92        /* some more stuff */
  93};
  94
  95static void rerere_io_putstr(const char *str, struct rerere_io *io)
  96{
  97        if (io->output)
  98                ferr_puts(str, io->output, &io->wrerror);
  99}
 100
 101static void rerere_io_putmem(const char *mem, size_t sz, struct rerere_io *io)
 102{
 103        if (io->output)
 104                ferr_write(mem, sz, io->output, &io->wrerror);
 105}
 106
 107struct rerere_io_file {
 108        struct rerere_io io;
 109        FILE *input;
 110};
 111
 112static int rerere_file_getline(struct strbuf *sb, struct rerere_io *io_)
 113{
 114        struct rerere_io_file *io = (struct rerere_io_file *)io_;
 115        return strbuf_getwholeline(sb, io->input, '\n');
 116}
 117
 118static int handle_path(unsigned char *sha1, struct rerere_io *io)
 119{
 120        git_SHA_CTX ctx;
 121        int hunk_no = 0;
 122        enum {
 123                RR_CONTEXT = 0, RR_SIDE_1, RR_SIDE_2, RR_ORIGINAL,
 124        } hunk = RR_CONTEXT;
 125        struct strbuf one = STRBUF_INIT, two = STRBUF_INIT;
 126        struct strbuf buf = STRBUF_INIT;
 127
 128        if (sha1)
 129                git_SHA1_Init(&ctx);
 130
 131        while (!io->getline(&buf, io)) {
 132                if (!prefixcmp(buf.buf, "<<<<<<< ")) {
 133                        if (hunk != RR_CONTEXT)
 134                                goto bad;
 135                        hunk = RR_SIDE_1;
 136                } else if (!prefixcmp(buf.buf, "|||||||") && isspace(buf.buf[7])) {
 137                        if (hunk != RR_SIDE_1)
 138                                goto bad;
 139                        hunk = RR_ORIGINAL;
 140                } else if (!prefixcmp(buf.buf, "=======") && isspace(buf.buf[7])) {
 141                        if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL)
 142                                goto bad;
 143                        hunk = RR_SIDE_2;
 144                } else if (!prefixcmp(buf.buf, ">>>>>>> ")) {
 145                        if (hunk != RR_SIDE_2)
 146                                goto bad;
 147                        if (strbuf_cmp(&one, &two) > 0)
 148                                strbuf_swap(&one, &two);
 149                        hunk_no++;
 150                        hunk = RR_CONTEXT;
 151                        rerere_io_putstr("<<<<<<<\n", io);
 152                        rerere_io_putmem(one.buf, one.len, io);
 153                        rerere_io_putstr("=======\n", io);
 154                        rerere_io_putmem(two.buf, two.len, io);
 155                        rerere_io_putstr(">>>>>>>\n", io);
 156                        if (sha1) {
 157                                git_SHA1_Update(&ctx, one.buf ? one.buf : "",
 158                                            one.len + 1);
 159                                git_SHA1_Update(&ctx, two.buf ? two.buf : "",
 160                                            two.len + 1);
 161                        }
 162                        strbuf_reset(&one);
 163                        strbuf_reset(&two);
 164                } else if (hunk == RR_SIDE_1)
 165                        strbuf_addstr(&one, buf.buf);
 166                else if (hunk == RR_ORIGINAL)
 167                        ; /* discard */
 168                else if (hunk == RR_SIDE_2)
 169                        strbuf_addstr(&two, buf.buf);
 170                else
 171                        rerere_io_putstr(buf.buf, io);
 172                continue;
 173        bad:
 174                hunk = 99; /* force error exit */
 175                break;
 176        }
 177        strbuf_release(&one);
 178        strbuf_release(&two);
 179        strbuf_release(&buf);
 180
 181        if (sha1)
 182                git_SHA1_Final(sha1, &ctx);
 183        if (hunk != RR_CONTEXT)
 184                return -1;
 185        return hunk_no;
 186}
 187
 188static int handle_file(const char *path, unsigned char *sha1, const char *output)
 189{
 190        int hunk_no = 0;
 191        struct rerere_io_file io;
 192
 193        memset(&io, 0, sizeof(io));
 194        io.io.getline = rerere_file_getline;
 195        io.input = fopen(path, "r");
 196        io.io.wrerror = 0;
 197        if (!io.input)
 198                return error("Could not open %s", path);
 199
 200        if (output) {
 201                io.io.output = fopen(output, "w");
 202                if (!io.io.output) {
 203                        fclose(io.input);
 204                        return error("Could not write %s", output);
 205                }
 206        }
 207
 208        hunk_no = handle_path(sha1, (struct rerere_io *)&io);
 209
 210        fclose(io.input);
 211        if (io.io.wrerror)
 212                error("There were errors while writing %s (%s)",
 213                      path, strerror(io.io.wrerror));
 214        if (io.io.output && fclose(io.io.output))
 215                io.io.wrerror = error("Failed to flush %s: %s",
 216                                      path, strerror(errno));
 217
 218        if (hunk_no < 0) {
 219                if (output)
 220                        unlink_or_warn(output);
 221                return error("Could not parse conflict hunks in %s", path);
 222        }
 223        if (io.io.wrerror)
 224                return -1;
 225        return hunk_no;
 226}
 227
 228struct rerere_io_mem {
 229        struct rerere_io io;
 230        struct strbuf input;
 231};
 232
 233static int rerere_mem_getline(struct strbuf *sb, struct rerere_io *io_)
 234{
 235        struct rerere_io_mem *io = (struct rerere_io_mem *)io_;
 236        char *ep;
 237        size_t len;
 238
 239        strbuf_release(sb);
 240        if (!io->input.len)
 241                return -1;
 242        ep = strchrnul(io->input.buf, '\n');
 243        if (*ep == '\n')
 244                ep++;
 245        len = ep - io->input.buf;
 246        strbuf_add(sb, io->input.buf, len);
 247        strbuf_remove(&io->input, 0, len);
 248        return 0;
 249}
 250
 251static int handle_cache(const char *path, unsigned char *sha1, const char *output)
 252{
 253        mmfile_t mmfile[3];
 254        mmbuffer_t result = {NULL, 0};
 255        struct cache_entry *ce;
 256        int pos, len, i, hunk_no;
 257        struct rerere_io_mem io;
 258
 259        /*
 260         * Reproduce the conflicted merge in-core
 261         */
 262        len = strlen(path);
 263        pos = cache_name_pos(path, len);
 264        if (0 <= pos)
 265                return -1;
 266        pos = -pos - 1;
 267
 268        for (i = 0; i < 3; i++) {
 269                enum object_type type;
 270                unsigned long size;
 271
 272                mmfile[i].size = 0;
 273                mmfile[i].ptr = NULL;
 274                if (active_nr <= pos)
 275                        break;
 276                ce = active_cache[pos++];
 277                if (ce_namelen(ce) != len || memcmp(ce->name, path, len)
 278                    || ce_stage(ce) != i + 1)
 279                        break;
 280                mmfile[i].ptr = read_sha1_file(ce->sha1, &type, &size);
 281                mmfile[i].size = size;
 282        }
 283        for (i = 0; i < 3; i++) {
 284                if (!mmfile[i].ptr && !mmfile[i].size)
 285                        mmfile[i].ptr = xstrdup("");
 286        }
 287        ll_merge(&result, path, &mmfile[0],
 288                 &mmfile[1], "ours",
 289                 &mmfile[2], "theirs", 0);
 290        for (i = 0; i < 3; i++)
 291                free(mmfile[i].ptr);
 292
 293        memset(&io, 0, sizeof(&io));
 294        io.io.getline = rerere_mem_getline;
 295        if (output)
 296                io.io.output = fopen(output, "w");
 297        else
 298                io.io.output = NULL;
 299        strbuf_init(&io.input, 0);
 300        strbuf_attach(&io.input, result.ptr, result.size, result.size);
 301
 302        hunk_no = handle_path(sha1, (struct rerere_io *)&io);
 303        strbuf_release(&io.input);
 304        if (io.io.output)
 305                fclose(io.io.output);
 306        return hunk_no;
 307}
 308
 309static int find_conflict(struct string_list *conflict)
 310{
 311        int i;
 312        if (read_cache() < 0)
 313                return error("Could not read index");
 314        for (i = 0; i+1 < active_nr; i++) {
 315                struct cache_entry *e2 = active_cache[i];
 316                struct cache_entry *e3 = active_cache[i+1];
 317                if (ce_stage(e2) == 2 &&
 318                    ce_stage(e3) == 3 &&
 319                    ce_same_name(e2, e3) &&
 320                    S_ISREG(e2->ce_mode) &&
 321                    S_ISREG(e3->ce_mode)) {
 322                        string_list_insert((const char *)e2->name, conflict);
 323                        i++; /* skip over both #2 and #3 */
 324                }
 325        }
 326        return 0;
 327}
 328
 329static int merge(const char *name, const char *path)
 330{
 331        int ret;
 332        mmfile_t cur, base, other;
 333        mmbuffer_t result = {NULL, 0};
 334
 335        if (handle_file(path, NULL, rerere_path(name, "thisimage")) < 0)
 336                return 1;
 337
 338        if (read_mmfile(&cur, rerere_path(name, "thisimage")) ||
 339                        read_mmfile(&base, rerere_path(name, "preimage")) ||
 340                        read_mmfile(&other, rerere_path(name, "postimage")))
 341                return 1;
 342        ret = ll_merge(&result, path, &base, &cur, "", &other, "", 0);
 343        if (!ret) {
 344                FILE *f = fopen(path, "w");
 345                if (!f)
 346                        return error("Could not open %s: %s", path,
 347                                     strerror(errno));
 348                if (fwrite(result.ptr, result.size, 1, f) != 1)
 349                        error("Could not write %s: %s", path, strerror(errno));
 350                if (fclose(f))
 351                        return error("Writing %s failed: %s", path,
 352                                     strerror(errno));
 353        }
 354
 355        free(cur.ptr);
 356        free(base.ptr);
 357        free(other.ptr);
 358        free(result.ptr);
 359
 360        return ret;
 361}
 362
 363static struct lock_file index_lock;
 364
 365static int update_paths(struct string_list *update)
 366{
 367        int i;
 368        int fd = hold_locked_index(&index_lock, 0);
 369        int status = 0;
 370
 371        if (fd < 0)
 372                return -1;
 373
 374        for (i = 0; i < update->nr; i++) {
 375                struct string_list_item *item = &update->items[i];
 376                if (add_file_to_cache(item->string, ADD_CACHE_IGNORE_ERRORS))
 377                        status = -1;
 378        }
 379
 380        if (!status && active_cache_changed) {
 381                if (write_cache(fd, active_cache, active_nr) ||
 382                    commit_locked_index(&index_lock))
 383                        die("Unable to write new index file");
 384        } else if (fd >= 0)
 385                rollback_lock_file(&index_lock);
 386        return status;
 387}
 388
 389static int do_plain_rerere(struct string_list *rr, int fd)
 390{
 391        struct string_list conflict = { NULL, 0, 0, 1 };
 392        struct string_list update = { NULL, 0, 0, 1 };
 393        int i;
 394
 395        find_conflict(&conflict);
 396
 397        /*
 398         * MERGE_RR records paths with conflicts immediately after merge
 399         * failed.  Some of the conflicted paths might have been hand resolved
 400         * in the working tree since then, but the initial run would catch all
 401         * and register their preimages.
 402         */
 403
 404        for (i = 0; i < conflict.nr; i++) {
 405                const char *path = conflict.items[i].string;
 406                if (!string_list_has_string(rr, path)) {
 407                        unsigned char sha1[20];
 408                        char *hex;
 409                        int ret;
 410                        ret = handle_file(path, sha1, NULL);
 411                        if (ret < 1)
 412                                continue;
 413                        hex = xstrdup(sha1_to_hex(sha1));
 414                        string_list_insert(path, rr)->util = hex;
 415                        if (mkdir(git_path("rr-cache/%s", hex), 0755))
 416                                continue;
 417                        handle_file(path, NULL, rerere_path(hex, "preimage"));
 418                        fprintf(stderr, "Recorded preimage for '%s'\n", path);
 419                }
 420        }
 421
 422        /*
 423         * Now some of the paths that had conflicts earlier might have been
 424         * hand resolved.  Others may be similar to a conflict already that
 425         * was resolved before.
 426         */
 427
 428        for (i = 0; i < rr->nr; i++) {
 429                int ret;
 430                const char *path = rr->items[i].string;
 431                const char *name = (const char *)rr->items[i].util;
 432
 433                if (has_rerere_resolution(name)) {
 434                        if (!merge(name, path)) {
 435                                if (rerere_autoupdate)
 436                                        string_list_insert(path, &update);
 437                                fprintf(stderr,
 438                                        "%s '%s' using previous resolution.\n",
 439                                        rerere_autoupdate
 440                                        ? "Staged" : "Resolved",
 441                                        path);
 442                                goto mark_resolved;
 443                        }
 444                }
 445
 446                /* Let's see if we have resolved it. */
 447                ret = handle_file(path, NULL, NULL);
 448                if (ret)
 449                        continue;
 450
 451                fprintf(stderr, "Recorded resolution for '%s'.\n", path);
 452                copy_file(rerere_path(name, "postimage"), path, 0666);
 453        mark_resolved:
 454                rr->items[i].util = NULL;
 455        }
 456
 457        if (update.nr)
 458                update_paths(&update);
 459
 460        return write_rr(rr, fd);
 461}
 462
 463static int git_rerere_config(const char *var, const char *value, void *cb)
 464{
 465        if (!strcmp(var, "rerere.enabled"))
 466                rerere_enabled = git_config_bool(var, value);
 467        else if (!strcmp(var, "rerere.autoupdate"))
 468                rerere_autoupdate = git_config_bool(var, value);
 469        else
 470                return git_default_config(var, value, cb);
 471        return 0;
 472}
 473
 474static int is_rerere_enabled(void)
 475{
 476        const char *rr_cache;
 477        int rr_cache_exists;
 478
 479        if (!rerere_enabled)
 480                return 0;
 481
 482        rr_cache = git_path("rr-cache");
 483        rr_cache_exists = is_directory(rr_cache);
 484        if (rerere_enabled < 0)
 485                return rr_cache_exists;
 486
 487        if (!rr_cache_exists &&
 488            (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
 489                die("Could not create directory %s", rr_cache);
 490        return 1;
 491}
 492
 493int setup_rerere(struct string_list *merge_rr)
 494{
 495        int fd;
 496
 497        git_config(git_rerere_config, NULL);
 498        if (!is_rerere_enabled())
 499                return -1;
 500
 501        merge_rr_path = git_pathdup("MERGE_RR");
 502        fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
 503                                       LOCK_DIE_ON_ERROR);
 504        read_rr(merge_rr);
 505        return fd;
 506}
 507
 508int rerere(void)
 509{
 510        struct string_list merge_rr = { NULL, 0, 0, 1 };
 511        int fd;
 512
 513        fd = setup_rerere(&merge_rr);
 514        if (fd < 0)
 515                return 0;
 516        return do_plain_rerere(&merge_rr, fd);
 517}
 518
 519static int rerere_forget_one_path(const char *path, struct string_list *rr)
 520{
 521        const char *filename;
 522        char *hex;
 523        unsigned char sha1[20];
 524        int ret;
 525
 526        ret = handle_cache(path, sha1, NULL);
 527        if (ret < 1)
 528                return error("Could not parse conflict hunks in '%s'", path);
 529        hex = xstrdup(sha1_to_hex(sha1));
 530        filename = rerere_path(hex, "postimage");
 531        if (unlink(filename))
 532                return (errno == ENOENT
 533                        ? error("no remembered resolution for %s", path)
 534                        : error("cannot unlink %s: %s", filename, strerror(errno)));
 535
 536        handle_cache(path, sha1, rerere_path(hex, "preimage"));
 537        fprintf(stderr, "Updated preimage for '%s'\n", path);
 538
 539
 540        string_list_insert(path, rr)->util = hex;
 541        fprintf(stderr, "Forgot resolution for %s\n", path);
 542        return 0;
 543}
 544
 545int rerere_forget(const char **pathspec)
 546{
 547        int i, fd;
 548        struct string_list conflict = { NULL, 0, 0, 1 };
 549        struct string_list merge_rr = { NULL, 0, 0, 1 };
 550
 551        if (read_cache() < 0)
 552                return error("Could not read index");
 553
 554        fd = setup_rerere(&merge_rr);
 555
 556        unmerge_cache(pathspec);
 557        find_conflict(&conflict);
 558        for (i = 0; i < conflict.nr; i++) {
 559                struct string_list_item *it = &conflict.items[i];
 560                if (!match_pathspec(pathspec, it->string, strlen(it->string),
 561                                    0, NULL))
 562                        continue;
 563                rerere_forget_one_path(it->string, &merge_rr);
 564        }
 565        return write_rr(&merge_rr, fd);
 566}