Skip to content

Commit ae46d5f

Browse files
committed
Merge branch 'js/merge-tree-3-trees'
"git merge-tree" has learned that the three trees involved in the 3-way merge only need to be trees, not necessarily commits. * js/merge-tree-3-trees: fill_tree_descriptor(): mark error message for translation cache-tree: avoid an unnecessary check Always check `parse_tree*()`'s return value t4301: verify that merge-tree fails on missing blob objects merge-ort: do check `parse_tree()`'s return value merge-tree: fail with a non-zero exit code on missing tree objects merge-tree: accept 3 trees as arguments
2 parents 76d1cd8 + 342990c commit ae46d5f

16 files changed

+124
-35
lines changed

Documentation/git-merge-tree.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,13 @@ OPTIONS
6464
share no common history. This flag can be given to override that
6565
check and make the merge proceed anyway.
6666

67-
--merge-base=<commit>::
67+
--merge-base=<tree-ish>::
6868
Instead of finding the merge-bases for <branch1> and <branch2>,
6969
specify a merge-base for the merge, and specifying multiple bases is
7070
currently not supported. This option is incompatible with `--stdin`.
71+
+
72+
As the merge-base is provided directly, <branch1> and <branch2> do not need
73+
to specify commits; trees are enough.
7174

7275
[[OUTPUT]]
7376
OUTPUT

builtin/checkout.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,8 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
704704
init_checkout_metadata(&opts.meta, info->refname,
705705
info->commit ? &info->commit->object.oid : null_oid(),
706706
NULL);
707-
parse_tree(tree);
707+
if (parse_tree(tree) < 0)
708+
return 128;
708709
init_tree_desc(&tree_desc, tree->buffer, tree->size);
709710
switch (unpack_trees(1, &tree_desc, &opts)) {
710711
case -2:
@@ -783,9 +784,15 @@ static int merge_working_tree(const struct checkout_opts *opts,
783784
if (new_branch_info->commit)
784785
BUG("'switch --orphan' should never accept a commit as starting point");
785786
new_tree = parse_tree_indirect(the_hash_algo->empty_tree);
786-
} else
787+
if (!new_tree)
788+
BUG("unable to read empty tree");
789+
} else {
787790
new_tree = repo_get_commit_tree(the_repository,
788791
new_branch_info->commit);
792+
if (!new_tree)
793+
return error(_("unable to read tree (%s)"),
794+
oid_to_hex(&new_branch_info->commit->object.oid));
795+
}
789796
if (opts->discard_changes) {
790797
ret = reset_tree(new_tree, opts, 1, writeout_error, new_branch_info);
791798
if (ret)
@@ -820,7 +827,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
820827
oid_to_hex(old_commit_oid));
821828

822829
init_tree_desc(&trees[0], tree->buffer, tree->size);
823-
parse_tree(new_tree);
830+
if (parse_tree(new_tree) < 0)
831+
exit(128);
824832
tree = new_tree;
825833
init_tree_desc(&trees[1], tree->buffer, tree->size);
826834

@@ -1240,10 +1248,15 @@ static void setup_new_branch_info_and_source_tree(
12401248
if (!new_branch_info->commit) {
12411249
/* not a commit */
12421250
*source_tree = parse_tree_indirect(rev);
1251+
if (!*source_tree)
1252+
die(_("unable to read tree (%s)"), oid_to_hex(rev));
12431253
} else {
12441254
parse_commit_or_die(new_branch_info->commit);
12451255
*source_tree = repo_get_commit_tree(the_repository,
12461256
new_branch_info->commit);
1257+
if (!*source_tree)
1258+
die(_("unable to read tree (%s)"),
1259+
oid_to_hex(&new_branch_info->commit->object.oid));
12471260
}
12481261
}
12491262

builtin/clone.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,8 @@ static int checkout(int submodule_progress, int filter_submodules)
738738
tree = parse_tree_indirect(&oid);
739739
if (!tree)
740740
die(_("unable to parse commit %s"), oid_to_hex(&oid));
741-
parse_tree(tree);
741+
if (parse_tree(tree) < 0)
742+
exit(128);
742743
init_tree_desc(&t, tree->buffer, tree->size);
743744
if (unpack_trees(1, &t, &opts) < 0)
744745
die(_("unable to checkout working tree"));

builtin/commit.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,8 @@ static void create_base_index(const struct commit *current_head)
331331
tree = parse_tree_indirect(&current_head->object.oid);
332332
if (!tree)
333333
die(_("failed to unpack HEAD tree object"));
334-
parse_tree(tree);
334+
if (parse_tree(tree) < 0)
335+
exit(128);
335336
init_tree_desc(&t, tree->buffer, tree->size);
336337
if (unpack_trees(1, &t, &opts))
337338
exit(128); /* We've already reported the error, finish dying */

builtin/merge-tree.c

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -429,35 +429,49 @@ static int real_merge(struct merge_tree_options *o,
429429
struct merge_options opt;
430430

431431
copy_merge_options(&opt, &o->merge_options);
432-
parent1 = get_merge_parent(branch1);
433-
if (!parent1)
434-
help_unknown_ref(branch1, "merge-tree",
435-
_("not something we can merge"));
436-
437-
parent2 = get_merge_parent(branch2);
438-
if (!parent2)
439-
help_unknown_ref(branch2, "merge-tree",
440-
_("not something we can merge"));
441-
442432
opt.show_rename_progress = 0;
443433

444434
opt.branch1 = branch1;
445435
opt.branch2 = branch2;
446436

447437
if (merge_base) {
448-
struct commit *base_commit;
449438
struct tree *base_tree, *parent1_tree, *parent2_tree;
450439

451-
base_commit = lookup_commit_reference_by_name(merge_base);
452-
if (!base_commit)
453-
die(_("could not lookup commit '%s'"), merge_base);
440+
/*
441+
* We actually only need the trees because we already
442+
* have a merge base.
443+
*/
444+
struct object_id base_oid, head_oid, merge_oid;
445+
446+
if (repo_get_oid_treeish(the_repository, merge_base, &base_oid))
447+
die(_("could not parse as tree '%s'"), merge_base);
448+
base_tree = parse_tree_indirect(&base_oid);
449+
if (!base_tree)
450+
die(_("unable to read tree (%s)"), oid_to_hex(&base_oid));
451+
if (repo_get_oid_treeish(the_repository, branch1, &head_oid))
452+
die(_("could not parse as tree '%s'"), branch1);
453+
parent1_tree = parse_tree_indirect(&head_oid);
454+
if (!parent1_tree)
455+
die(_("unable to read tree (%s)"), oid_to_hex(&head_oid));
456+
if (repo_get_oid_treeish(the_repository, branch2, &merge_oid))
457+
die(_("could not parse as tree '%s'"), branch2);
458+
parent2_tree = parse_tree_indirect(&merge_oid);
459+
if (!parent2_tree)
460+
die(_("unable to read tree (%s)"), oid_to_hex(&merge_oid));
454461

455462
opt.ancestor = merge_base;
456-
base_tree = repo_get_commit_tree(the_repository, base_commit);
457-
parent1_tree = repo_get_commit_tree(the_repository, parent1);
458-
parent2_tree = repo_get_commit_tree(the_repository, parent2);
459463
merge_incore_nonrecursive(&opt, base_tree, parent1_tree, parent2_tree, &result);
460464
} else {
465+
parent1 = get_merge_parent(branch1);
466+
if (!parent1)
467+
help_unknown_ref(branch1, "merge-tree",
468+
_("not something we can merge"));
469+
470+
parent2 = get_merge_parent(branch2);
471+
if (!parent2)
472+
help_unknown_ref(branch2, "merge-tree",
473+
_("not something we can merge"));
474+
461475
/*
462476
* Get the merge bases, in reverse order; see comment above
463477
* merge_incore_recursive in merge-ort.h

builtin/read-tree.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
261261
cache_tree_free(&the_index.cache_tree);
262262
for (i = 0; i < nr_trees; i++) {
263263
struct tree *tree = trees[i];
264-
parse_tree(tree);
264+
if (parse_tree(tree) < 0)
265+
return 128;
265266
init_tree_desc(t+i, tree->buffer, tree->size);
266267
}
267268
if (unpack_trees(nr_trees, t, &opts))

builtin/reset.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ static int reset_index(const char *ref, const struct object_id *oid, int reset_t
116116

117117
if (reset_type == MIXED || reset_type == HARD) {
118118
tree = parse_tree_indirect(oid);
119+
if (!tree) {
120+
error(_("unable to read tree (%s)"), oid_to_hex(oid));
121+
goto out;
122+
}
119123
prime_cache_tree(the_repository, the_repository->index, tree);
120124
}
121125

cache-tree.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -778,8 +778,8 @@ static void prime_cache_tree_rec(struct repository *r,
778778
struct cache_tree_sub *sub;
779779
struct tree *subtree = lookup_tree(r, &entry.oid);
780780

781-
if (!subtree->object.parsed)
782-
parse_tree(subtree);
781+
if (parse_tree(subtree) < 0)
782+
exit(128);
783783
sub = cache_tree_sub(it, entry.path);
784784
sub->cache_tree = cache_tree();
785785

merge-ort.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,9 +1658,10 @@ static int collect_merge_info(struct merge_options *opt,
16581658
info.data = opt;
16591659
info.show_all_errors = 1;
16601660

1661-
parse_tree(merge_base);
1662-
parse_tree(side1);
1663-
parse_tree(side2);
1661+
if (parse_tree(merge_base) < 0 ||
1662+
parse_tree(side1) < 0 ||
1663+
parse_tree(side2) < 0)
1664+
return -1;
16641665
init_tree_desc(t + 0, merge_base->buffer, merge_base->size);
16651666
init_tree_desc(t + 1, side1->buffer, side1->size);
16661667
init_tree_desc(t + 2, side2->buffer, side2->size);
@@ -4377,9 +4378,11 @@ static int checkout(struct merge_options *opt,
43774378
unpack_opts.verbose_update = (opt->verbosity > 2);
43784379
unpack_opts.fn = twoway_merge;
43794380
unpack_opts.preserve_ignored = 0; /* FIXME: !opts->overwrite_ignore */
4380-
parse_tree(prev);
4381+
if (parse_tree(prev) < 0)
4382+
return -1;
43814383
init_tree_desc(&trees[0], prev->buffer, prev->size);
4382-
parse_tree(next);
4384+
if (parse_tree(next) < 0)
4385+
return -1;
43834386
init_tree_desc(&trees[1], next->buffer, next->size);
43844387

43854388
ret = unpack_trees(2, trees, &unpack_opts);
@@ -4983,6 +4986,9 @@ static void merge_ort_nonrecursive_internal(struct merge_options *opt,
49834986

49844987
if (result->clean >= 0) {
49854988
result->tree = parse_tree_indirect(&working_tree_oid);
4989+
if (!result->tree)
4990+
die(_("unable to read tree (%s)"),
4991+
oid_to_hex(&working_tree_oid));
49864992
/* existence of conflicted entries implies unclean */
49874993
result->clean &= strmap_empty(&opt->priv->conflicted);
49884994
}

merge-recursive.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,8 @@ static inline int merge_detect_rename(struct merge_options *opt)
405405

406406
static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree)
407407
{
408-
parse_tree(tree);
408+
if (parse_tree(tree) < 0)
409+
exit(128);
409410
init_tree_desc(desc, tree->buffer, tree->size);
410411
}
411412

0 commit comments

Comments
 (0)