|
21 | 21 | #include "tag.h" |
22 | 22 | #include "unpack-trees.h" |
23 | 23 | #include "path-list.h" |
| 24 | +#include "xdiff-interface.h" |
24 | 25 |
|
25 | 26 | /* |
26 | 27 | * A virtual commit has |
@@ -604,24 +605,15 @@ struct merge_file_info |
604 | 605 | merge:1; |
605 | 606 | }; |
606 | 607 |
|
607 | | -static char *git_unpack_file(const unsigned char *sha1, char *path) |
| 608 | +static void fill_mm(const unsigned char *sha1, mmfile_t *mm) |
608 | 609 | { |
609 | | - void *buf; |
610 | | - char type[20]; |
611 | 610 | unsigned long size; |
612 | | - int fd; |
| 611 | + char type[20]; |
613 | 612 |
|
614 | | - buf = read_sha1_file(sha1, type, &size); |
615 | | - if (!buf || strcmp(type, blob_type)) |
| 613 | + mm->ptr = read_sha1_file(sha1, type, &size); |
| 614 | + if (!mm->ptr || strcmp(type, blob_type)) |
616 | 615 | die("unable to read blob object %s", sha1_to_hex(sha1)); |
617 | | - |
618 | | - strcpy(path, ".merge_file_XXXXXX"); |
619 | | - fd = mkstemp(path); |
620 | | - if (fd < 0) |
621 | | - die("unable to create temp-file"); |
622 | | - flush_buffer(fd, buf, size); |
623 | | - close(fd); |
624 | | - return path; |
| 616 | + mm->size = size; |
625 | 617 | } |
626 | 618 |
|
627 | 619 | static struct merge_file_info merge_file(struct diff_filespec *o, |
@@ -652,49 +644,41 @@ static struct merge_file_info merge_file(struct diff_filespec *o, |
652 | 644 | else if (sha_eq(b->sha1, o->sha1)) |
653 | 645 | hashcpy(result.sha, a->sha1); |
654 | 646 | else if (S_ISREG(a->mode)) { |
655 | | - int code = 1, fd; |
656 | | - struct stat st; |
657 | | - char orig[PATH_MAX]; |
658 | | - char src1[PATH_MAX]; |
659 | | - char src2[PATH_MAX]; |
660 | | - const char *argv[] = { |
661 | | - "merge", "-L", NULL, "-L", NULL, "-L", NULL, |
662 | | - NULL, NULL, NULL, |
663 | | - NULL |
664 | | - }; |
665 | | - char *la, *lb, *lo; |
666 | | - |
667 | | - git_unpack_file(o->sha1, orig); |
668 | | - git_unpack_file(a->sha1, src1); |
669 | | - git_unpack_file(b->sha1, src2); |
670 | | - |
671 | | - argv[2] = la = xstrdup(mkpath("%s/%s", branch1, a->path)); |
672 | | - argv[6] = lb = xstrdup(mkpath("%s/%s", branch2, b->path)); |
673 | | - argv[4] = lo = xstrdup(mkpath("orig/%s", o->path)); |
674 | | - argv[7] = src1; |
675 | | - argv[8] = orig; |
676 | | - argv[9] = src2, |
677 | | - |
678 | | - code = run_command_v(10, argv); |
679 | | - |
680 | | - free(la); |
681 | | - free(lb); |
682 | | - free(lo); |
683 | | - if (code && code < -256) { |
684 | | - die("Failed to execute 'merge'. merge(1) is used as the " |
685 | | - "file-level merge tool. Is 'merge' in your path?"); |
686 | | - } |
687 | | - fd = open(src1, O_RDONLY); |
688 | | - if (fd < 0 || fstat(fd, &st) < 0 || |
689 | | - index_fd(result.sha, fd, &st, 1, |
690 | | - "blob")) |
691 | | - die("Unable to add %s to database", src1); |
692 | | - |
693 | | - unlink(orig); |
694 | | - unlink(src1); |
695 | | - unlink(src2); |
696 | | - |
697 | | - result.clean = WEXITSTATUS(code) == 0; |
| 647 | + mmfile_t orig, src1, src2; |
| 648 | + mmbuffer_t result_buf; |
| 649 | + xpparam_t xpp; |
| 650 | + char *name1, *name2; |
| 651 | + int merge_status; |
| 652 | + |
| 653 | + name1 = xstrdup(mkpath("%s/%s", branch1, a->path)); |
| 654 | + name2 = xstrdup(mkpath("%s/%s", branch2, b->path)); |
| 655 | + |
| 656 | + fill_mm(o->sha1, &orig); |
| 657 | + fill_mm(a->sha1, &src1); |
| 658 | + fill_mm(b->sha1, &src2); |
| 659 | + |
| 660 | + memset(&xpp, 0, sizeof(xpp)); |
| 661 | + merge_status = xdl_merge(&orig, |
| 662 | + &src1, name1, |
| 663 | + &src2, name2, |
| 664 | + &xpp, XDL_MERGE_ZEALOUS, |
| 665 | + &result_buf); |
| 666 | + free(name1); |
| 667 | + free(name2); |
| 668 | + free(orig.ptr); |
| 669 | + free(src1.ptr); |
| 670 | + free(src2.ptr); |
| 671 | + |
| 672 | + if ((merge_status < 0) || !result_buf.ptr) |
| 673 | + die("Failed to execute internal merge"); |
| 674 | + |
| 675 | + if (write_sha1_file(result_buf.ptr, result_buf.size, |
| 676 | + blob_type, result.sha)) |
| 677 | + die("Unable to add %s to database", |
| 678 | + a->path); |
| 679 | + |
| 680 | + free(result_buf.ptr); |
| 681 | + result.clean = (merge_status == 0); |
698 | 682 | } else { |
699 | 683 | if (!(S_ISLNK(a->mode) || S_ISLNK(b->mode))) |
700 | 684 | die("cannot merge modes?"); |
|
0 commit comments