Git fork
at reftables-rust 700 lines 18 kB view raw
1#define USE_THE_REPOSITORY_VARIABLE 2 3#include "builtin.h" 4#include "environment.h" 5#include "tree-walk.h" 6#include "xdiff-interface.h" 7#include "help.h" 8#include "gettext.h" 9#include "hex.h" 10#include "commit.h" 11#include "commit-reach.h" 12#include "merge-ort.h" 13#include "object-name.h" 14#include "odb.h" 15#include "parse-options.h" 16#include "blob.h" 17#include "merge-blobs.h" 18#include "quote.h" 19#include "tree.h" 20#include "config.h" 21#include "strvec.h" 22#include "write-or-die.h" 23 24static int line_termination = '\n'; 25 26struct merge_list { 27 struct merge_list *next; 28 struct merge_list *link; /* other stages for this object */ 29 30 unsigned int stage : 2; 31 unsigned int mode; 32 const char *path; 33 struct blob *blob; 34}; 35 36static struct merge_list *merge_result, **merge_result_end = &merge_result; 37 38static void add_merge_entry(struct merge_list *entry) 39{ 40 *merge_result_end = entry; 41 merge_result_end = &entry->next; 42} 43 44static void trivial_merge_trees(struct tree_desc t[3], const char *base); 45 46static const char *explanation(struct merge_list *entry) 47{ 48 switch (entry->stage) { 49 case 0: 50 return "merged"; 51 case 3: 52 return "added in remote"; 53 case 2: 54 if (entry->link) 55 return "added in both"; 56 return "added in local"; 57 } 58 59 /* Existed in base */ 60 entry = entry->link; 61 if (!entry) 62 return "removed in both"; 63 64 if (entry->link) 65 return "changed in both"; 66 67 if (entry->stage == 3) 68 return "removed in local"; 69 return "removed in remote"; 70} 71 72static void *result(struct merge_list *entry, unsigned long *size) 73{ 74 enum object_type type; 75 struct blob *base, *our, *their; 76 const char *path = entry->path; 77 78 if (!entry->stage) 79 return odb_read_object(the_repository->objects, 80 &entry->blob->object.oid, &type, 81 size); 82 base = NULL; 83 if (entry->stage == 1) { 84 base = entry->blob; 85 entry = entry->link; 86 } 87 our = NULL; 88 if (entry && entry->stage == 2) { 89 our = entry->blob; 90 entry = entry->link; 91 } 92 their = NULL; 93 if (entry) 94 their = entry->blob; 95 return merge_blobs(the_repository->index, path, 96 base, our, their, size); 97} 98 99static void *origin(struct merge_list *entry, unsigned long *size) 100{ 101 enum object_type type; 102 while (entry) { 103 if (entry->stage == 2) 104 return odb_read_object(the_repository->objects, 105 &entry->blob->object.oid, 106 &type, size); 107 entry = entry->link; 108 } 109 return NULL; 110} 111 112static int show_outf(void *priv UNUSED, mmbuffer_t *mb, int nbuf) 113{ 114 int i; 115 for (i = 0; i < nbuf; i++) 116 printf("%.*s", (int) mb[i].size, mb[i].ptr); 117 return 0; 118} 119 120static void show_diff(struct merge_list *entry) 121{ 122 unsigned long size; 123 mmfile_t src, dst; 124 xpparam_t xpp; 125 xdemitconf_t xecfg; 126 xdemitcb_t ecb = { .out_line = show_outf }; 127 128 memset(&xpp, 0, sizeof(xpp)); 129 xpp.flags = 0; 130 memset(&xecfg, 0, sizeof(xecfg)); 131 xecfg.ctxlen = 3; 132 133 src.ptr = origin(entry, &size); 134 if (!src.ptr) 135 size = 0; 136 src.size = size; 137 dst.ptr = result(entry, &size); 138 if (!dst.ptr) 139 size = 0; 140 dst.size = size; 141 if (xdi_diff(&src, &dst, &xpp, &xecfg, &ecb)) 142 die("unable to generate diff"); 143 free(src.ptr); 144 free(dst.ptr); 145} 146 147static void show_result_list(struct merge_list *entry) 148{ 149 printf("%s\n", explanation(entry)); 150 do { 151 struct merge_list *link = entry->link; 152 static const char *desc[4] = { "result", "base", "our", "their" }; 153 printf(" %-6s %o %s %s\n", desc[entry->stage], entry->mode, oid_to_hex(&entry->blob->object.oid), entry->path); 154 entry = link; 155 } while (entry); 156} 157 158static void show_result(void) 159{ 160 struct merge_list *walk; 161 162 walk = merge_result; 163 while (walk) { 164 show_result_list(walk); 165 show_diff(walk); 166 walk = walk->next; 167 } 168} 169 170/* An empty entry never compares same, not even to another empty entry */ 171static int same_entry(struct name_entry *a, struct name_entry *b) 172{ 173 return !is_null_oid(&a->oid) && 174 !is_null_oid(&b->oid) && 175 oideq(&a->oid, &b->oid) && 176 a->mode == b->mode; 177} 178 179static int both_empty(struct name_entry *a, struct name_entry *b) 180{ 181 return is_null_oid(&a->oid) && is_null_oid(&b->oid); 182} 183 184static struct merge_list *create_entry(unsigned stage, unsigned mode, const struct object_id *oid, const char *path) 185{ 186 struct merge_list *res = xcalloc(1, sizeof(*res)); 187 188 res->stage = stage; 189 res->path = path; 190 res->mode = mode; 191 res->blob = lookup_blob(the_repository, oid); 192 return res; 193} 194 195static char *traverse_path(const struct traverse_info *info, const struct name_entry *n) 196{ 197 struct strbuf buf = STRBUF_INIT; 198 strbuf_make_traverse_path(&buf, info, n->path, n->pathlen); 199 return strbuf_detach(&buf, NULL); 200} 201 202static void resolve(const struct traverse_info *info, struct name_entry *ours, struct name_entry *result) 203{ 204 struct merge_list *orig, *final; 205 const char *path; 206 207 /* If it's already ours, don't bother showing it */ 208 if (!ours) 209 return; 210 211 path = traverse_path(info, result); 212 orig = create_entry(2, ours->mode, &ours->oid, path); 213 final = create_entry(0, result->mode, &result->oid, path); 214 215 final->link = orig; 216 217 add_merge_entry(final); 218} 219 220static void unresolved_directory(const struct traverse_info *info, 221 struct name_entry n[3]) 222{ 223 struct repository *r = the_repository; 224 char *newbase; 225 struct name_entry *p; 226 struct tree_desc t[3]; 227 void *buf0, *buf1, *buf2; 228 229 for (p = n; p < n + 3; p++) { 230 if (p->mode && S_ISDIR(p->mode)) 231 break; 232 } 233 if (n + 3 <= p) 234 return; /* there is no tree here */ 235 236 newbase = traverse_path(info, p); 237 238#define ENTRY_OID(e) (((e)->mode && S_ISDIR((e)->mode)) ? &(e)->oid : NULL) 239 buf0 = fill_tree_descriptor(r, t + 0, ENTRY_OID(n + 0)); 240 buf1 = fill_tree_descriptor(r, t + 1, ENTRY_OID(n + 1)); 241 buf2 = fill_tree_descriptor(r, t + 2, ENTRY_OID(n + 2)); 242#undef ENTRY_OID 243 244 trivial_merge_trees(t, newbase); 245 246 free(buf0); 247 free(buf1); 248 free(buf2); 249 free(newbase); 250} 251 252 253static struct merge_list *link_entry(unsigned stage, const struct traverse_info *info, struct name_entry *n, struct merge_list *entry) 254{ 255 const char *path; 256 struct merge_list *link; 257 258 if (!n->mode) 259 return entry; 260 if (entry) 261 path = entry->path; 262 else 263 path = traverse_path(info, n); 264 link = create_entry(stage, n->mode, &n->oid, path); 265 link->link = entry; 266 return link; 267} 268 269static void unresolved(const struct traverse_info *info, struct name_entry n[3]) 270{ 271 struct merge_list *entry = NULL; 272 int i; 273 unsigned dirmask = 0, mask = 0; 274 275 for (i = 0; i < 3; i++) { 276 mask |= (1 << i); 277 /* 278 * Treat missing entries as directories so that we return 279 * after unresolved_directory has handled this. 280 */ 281 if (!n[i].mode || S_ISDIR(n[i].mode)) 282 dirmask |= (1 << i); 283 } 284 285 unresolved_directory(info, n); 286 287 if (dirmask == mask) 288 return; 289 290 if (n[2].mode && !S_ISDIR(n[2].mode)) 291 entry = link_entry(3, info, n + 2, entry); 292 if (n[1].mode && !S_ISDIR(n[1].mode)) 293 entry = link_entry(2, info, n + 1, entry); 294 if (n[0].mode && !S_ISDIR(n[0].mode)) 295 entry = link_entry(1, info, n + 0, entry); 296 297 add_merge_entry(entry); 298} 299 300/* 301 * Merge two trees together (t[1] and t[2]), using a common base (t[0]) 302 * as the origin. 303 * 304 * This walks the (sorted) trees in lock-step, checking every possible 305 * name. Note that directories automatically sort differently from other 306 * files (see "base_name_compare"), so you'll never see file/directory 307 * conflicts, because they won't ever compare the same. 308 * 309 * IOW, if a directory changes to a filename, it will automatically be 310 * seen as the directory going away, and the filename being created. 311 * 312 * Think of this as a three-way diff. 313 * 314 * The output will be either: 315 * - successful merge 316 * "0 mode sha1 filename" 317 * NOTE NOTE NOTE! FIXME! We really really need to walk the index 318 * in parallel with this too! 319 * 320 * - conflict: 321 * "1 mode sha1 filename" 322 * "2 mode sha1 filename" 323 * "3 mode sha1 filename" 324 * where not all of the 1/2/3 lines may exist, of course. 325 * 326 * The successful merge rules are the same as for the three-way merge 327 * in git-read-tree. 328 */ 329static int threeway_callback(int n UNUSED, unsigned long mask, 330 unsigned long dirmask UNUSED, 331 struct name_entry *entry, struct traverse_info *info) 332{ 333 /* Same in both? */ 334 if (same_entry(entry+1, entry+2) || both_empty(entry+1, entry+2)) { 335 /* Modified, added or removed identically */ 336 resolve(info, NULL, entry+1); 337 return mask; 338 } 339 340 if (same_entry(entry+0, entry+1)) { 341 if (!is_null_oid(&entry[2].oid) && !S_ISDIR(entry[2].mode)) { 342 /* We did not touch, they modified -- take theirs */ 343 resolve(info, entry+1, entry+2); 344 return mask; 345 } 346 /* 347 * If we did not touch a directory but they made it 348 * into a file, we fall through and unresolved() 349 * recurses down. Likewise for the opposite case. 350 */ 351 } 352 353 if (same_entry(entry+0, entry+2) || both_empty(entry+0, entry+2)) { 354 /* We added, modified or removed, they did not touch -- take ours */ 355 resolve(info, NULL, entry+1); 356 return mask; 357 } 358 359 unresolved(info, entry); 360 return mask; 361} 362 363static void trivial_merge_trees(struct tree_desc t[3], const char *base) 364{ 365 struct traverse_info info; 366 367 setup_traverse_info(&info, base); 368 info.fn = threeway_callback; 369 traverse_trees(the_repository->index, 3, t, &info); 370} 371 372static void *get_tree_descriptor(struct repository *r, 373 struct tree_desc *desc, 374 const char *rev) 375{ 376 struct object_id oid; 377 void *buf; 378 379 if (repo_get_oid(r, rev, &oid)) 380 die("unknown rev %s", rev); 381 buf = fill_tree_descriptor(r, desc, &oid); 382 if (!buf) 383 die("%s is not a tree", rev); 384 return buf; 385} 386 387static int trivial_merge(const char *base, 388 const char *branch1, 389 const char *branch2) 390{ 391 struct repository *r = the_repository; 392 struct tree_desc t[3]; 393 void *buf1, *buf2, *buf3; 394 395 buf1 = get_tree_descriptor(r, t+0, base); 396 buf2 = get_tree_descriptor(r, t+1, branch1); 397 buf3 = get_tree_descriptor(r, t+2, branch2); 398 trivial_merge_trees(t, ""); 399 free(buf1); 400 free(buf2); 401 free(buf3); 402 403 show_result(); 404 return 0; 405} 406 407enum mode { 408 MODE_UNKNOWN, 409 MODE_TRIVIAL, 410 MODE_REAL, 411}; 412 413struct merge_tree_options { 414 int mode; 415 int allow_unrelated_histories; 416 int show_messages; 417 int name_only; 418 int use_stdin; 419 struct merge_options merge_options; 420}; 421 422static int real_merge(struct merge_tree_options *o, 423 const char *merge_base, 424 const char *branch1, const char *branch2, 425 const char *prefix) 426{ 427 struct commit *parent1, *parent2; 428 struct commit_list *merge_bases = NULL; 429 struct merge_result result = { 0 }; 430 int show_messages = o->show_messages; 431 struct merge_options opt; 432 433 copy_merge_options(&opt, &o->merge_options); 434 opt.show_rename_progress = 0; 435 436 opt.branch1 = branch1; 437 opt.branch2 = branch2; 438 439 if (merge_base) { 440 struct tree *base_tree, *parent1_tree, *parent2_tree; 441 442 /* 443 * We actually only need the trees because we already 444 * have a merge base. 445 */ 446 struct object_id base_oid, head_oid, merge_oid; 447 448 if (repo_get_oid_treeish(the_repository, merge_base, &base_oid)) 449 die(_("could not parse as tree '%s'"), merge_base); 450 base_tree = parse_tree_indirect(&base_oid); 451 if (!base_tree) 452 die(_("unable to read tree (%s)"), oid_to_hex(&base_oid)); 453 if (repo_get_oid_treeish(the_repository, branch1, &head_oid)) 454 die(_("could not parse as tree '%s'"), branch1); 455 parent1_tree = parse_tree_indirect(&head_oid); 456 if (!parent1_tree) 457 die(_("unable to read tree (%s)"), oid_to_hex(&head_oid)); 458 if (repo_get_oid_treeish(the_repository, branch2, &merge_oid)) 459 die(_("could not parse as tree '%s'"), branch2); 460 parent2_tree = parse_tree_indirect(&merge_oid); 461 if (!parent2_tree) 462 die(_("unable to read tree (%s)"), oid_to_hex(&merge_oid)); 463 464 opt.ancestor = merge_base; 465 merge_incore_nonrecursive(&opt, base_tree, parent1_tree, parent2_tree, &result); 466 } else { 467 parent1 = get_merge_parent(branch1); 468 if (!parent1) 469 help_unknown_ref(branch1, "merge-tree", 470 _("not something we can merge")); 471 472 parent2 = get_merge_parent(branch2); 473 if (!parent2) 474 help_unknown_ref(branch2, "merge-tree", 475 _("not something we can merge")); 476 477 /* 478 * Get the merge bases, in reverse order; see comment above 479 * merge_incore_recursive in merge-ort.h 480 */ 481 if (repo_get_merge_bases(the_repository, parent1, 482 parent2, &merge_bases) < 0) 483 exit(128); 484 if (!merge_bases && !o->allow_unrelated_histories) 485 die(_("refusing to merge unrelated histories")); 486 merge_bases = reverse_commit_list(merge_bases); 487 merge_incore_recursive(&opt, merge_bases, parent1, parent2, &result); 488 free_commit_list(merge_bases); 489 } 490 491 if (result.clean < 0) 492 die(_("failure to merge")); 493 494 if (o->merge_options.mergeability_only) 495 goto cleanup; 496 497 if (show_messages == -1) 498 show_messages = !result.clean; 499 500 if (o->use_stdin) 501 printf("%d%c", result.clean, line_termination); 502 printf("%s%c", oid_to_hex(&result.tree->object.oid), line_termination); 503 if (!result.clean) { 504 struct string_list conflicted_files = STRING_LIST_INIT_NODUP; 505 const char *last = NULL; 506 507 merge_get_conflicted_files(&result, &conflicted_files); 508 for (size_t i = 0; i < conflicted_files.nr; i++) { 509 const char *name = conflicted_files.items[i].string; 510 struct stage_info *c = conflicted_files.items[i].util; 511 if (!o->name_only) 512 printf("%06o %s %d\t", 513 c->mode, oid_to_hex(&c->oid), c->stage); 514 else if (last && !strcmp(last, name)) 515 continue; 516 write_name_quoted_relative( 517 name, prefix, stdout, line_termination); 518 last = name; 519 } 520 string_list_clear(&conflicted_files, 1); 521 } 522 if (show_messages) { 523 putchar(line_termination); 524 merge_display_update_messages(&opt, line_termination == '\0', 525 &result); 526 } 527 if (o->use_stdin) 528 putchar(line_termination); 529 530cleanup: 531 merge_finalize(&opt, &result); 532 clear_merge_options(&opt); 533 return !result.clean; /* result.clean < 0 handled above */ 534} 535 536int cmd_merge_tree(int argc, 537 const char **argv, 538 const char *prefix, 539 struct repository *repo UNUSED) 540{ 541 struct merge_tree_options o = { .show_messages = -1 }; 542 struct strvec xopts = STRVEC_INIT; 543 int expected_remaining_argc; 544 int original_argc; 545 const char *merge_base = NULL; 546 int ret; 547 int quiet = 0; 548 549 const char * const merge_tree_usage[] = { 550 N_("git merge-tree [--write-tree] [<options>] <branch1> <branch2>"), 551 N_("git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>"), 552 NULL 553 }; 554 struct option mt_options[] = { 555 OPT_CMDMODE(0, "write-tree", &o.mode, 556 N_("do a real merge instead of a trivial merge"), 557 MODE_REAL), 558 OPT_CMDMODE(0, "trivial-merge", &o.mode, 559 N_("do a trivial merge only"), MODE_TRIVIAL), 560 OPT_BOOL(0, "messages", &o.show_messages, 561 N_("also show informational/conflict messages")), 562 OPT_BOOL_F(0, "quiet", 563 &quiet, 564 N_("suppress all output; only exit status wanted"), 565 PARSE_OPT_NONEG), 566 OPT_SET_INT('z', NULL, &line_termination, 567 N_("separate paths with the NUL character"), '\0'), 568 OPT_BOOL_F(0, "name-only", 569 &o.name_only, 570 N_("list filenames without modes/oids/stages"), 571 PARSE_OPT_NONEG), 572 OPT_BOOL_F(0, "allow-unrelated-histories", 573 &o.allow_unrelated_histories, 574 N_("allow merging unrelated histories"), 575 PARSE_OPT_NONEG), 576 OPT_BOOL_F(0, "stdin", 577 &o.use_stdin, 578 N_("perform multiple merges, one per line of input"), 579 PARSE_OPT_NONEG), 580 OPT_STRING(0, "merge-base", 581 &merge_base, 582 N_("tree-ish"), 583 N_("specify a merge-base for the merge")), 584 OPT_STRVEC('X', "strategy-option", &xopts, N_("option=value"), 585 N_("option for selected merge strategy")), 586 OPT_END() 587 }; 588 589 /* Init merge options */ 590 init_basic_merge_options(&o.merge_options, the_repository); 591 592 /* Parse arguments */ 593 original_argc = argc - 1; /* ignoring argv[0] */ 594 argc = parse_options(argc, argv, prefix, mt_options, 595 merge_tree_usage, PARSE_OPT_STOP_AT_NON_OPTION); 596 597 if (quiet && o.show_messages == -1) 598 o.show_messages = 0; 599 o.merge_options.mergeability_only = quiet; 600 die_for_incompatible_opt2(quiet, "--quiet", o.show_messages, "--messages"); 601 die_for_incompatible_opt2(quiet, "--quiet", o.name_only, "--name-only"); 602 die_for_incompatible_opt2(quiet, "--quiet", o.use_stdin, "--stdin"); 603 die_for_incompatible_opt2(quiet, "--quiet", !line_termination, "-z"); 604 605 if (xopts.nr && o.mode == MODE_TRIVIAL) 606 die(_("--trivial-merge is incompatible with all other options")); 607 for (size_t x = 0; x < xopts.nr; x++) 608 if (parse_merge_opt(&o.merge_options, xopts.v[x])) 609 die(_("unknown strategy option: -X%s"), xopts.v[x]); 610 611 /* Handle --stdin */ 612 if (o.use_stdin) { 613 struct strbuf buf = STRBUF_INIT; 614 615 if (o.mode == MODE_TRIVIAL) 616 die(_("--trivial-merge is incompatible with all other options")); 617 if (merge_base) 618 die(_("options '%s' and '%s' cannot be used together"), 619 "--merge-base", "--stdin"); 620 line_termination = '\0'; 621 while (strbuf_getline_lf(&buf, stdin) != EOF) { 622 struct string_list split = STRING_LIST_INIT_NODUP; 623 const char *input_merge_base = NULL; 624 625 string_list_split_in_place_f(&split, buf.buf, " ", -1, 626 STRING_LIST_SPLIT_TRIM); 627 628 if (split.nr < 2) 629 die(_("malformed input line: '%s'."), buf.buf); 630 631 /* parse the merge-base */ 632 if (!strcmp(split.items[1].string, "--")) { 633 input_merge_base = split.items[0].string; 634 } 635 636 if (input_merge_base && split.nr == 4) { 637 real_merge(&o, input_merge_base, 638 split.items[2].string, split.items[3].string, 639 prefix); 640 } else if (!input_merge_base && split.nr == 2) { 641 real_merge(&o, NULL, 642 split.items[0].string, split.items[1].string, 643 prefix); 644 } else { 645 die(_("malformed input line: '%s'."), buf.buf); 646 } 647 maybe_flush_or_die(stdout, "stdout"); 648 649 string_list_clear(&split, 0); 650 } 651 strbuf_release(&buf); 652 653 ret = 0; 654 goto out; 655 } 656 657 /* Figure out which mode to use */ 658 switch (o.mode) { 659 default: 660 BUG("unexpected command mode %d", o.mode); 661 case MODE_UNKNOWN: 662 switch (argc) { 663 default: 664 usage_with_options(merge_tree_usage, mt_options); 665 case 2: 666 o.mode = MODE_REAL; 667 break; 668 case 3: 669 o.mode = MODE_TRIVIAL; 670 break; 671 } 672 expected_remaining_argc = argc; 673 break; 674 case MODE_REAL: 675 expected_remaining_argc = 2; 676 break; 677 case MODE_TRIVIAL: 678 expected_remaining_argc = 3; 679 /* Removal of `--trivial-merge` is expected */ 680 original_argc--; 681 break; 682 } 683 if (o.mode == MODE_TRIVIAL && argc < original_argc) 684 die(_("--trivial-merge is incompatible with all other options")); 685 686 if (argc != expected_remaining_argc) 687 usage_with_options(merge_tree_usage, mt_options); 688 689 repo_config(the_repository, git_default_config, NULL); 690 691 /* Do the relevant type of merge */ 692 if (o.mode == MODE_REAL) 693 ret = real_merge(&o, merge_base, argv[0], argv[1], prefix); 694 else 695 ret = trivial_merge(argv[0], argv[1], argv[2]); 696 697out: 698 strvec_clear(&xopts); 699 return ret; 700}