summaryrefslogtreecommitdiff
path: root/builtin/merge-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/merge-tree.c')
-rw-r--r--builtin/merge-tree.c57
1 files changed, 42 insertions, 15 deletions
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 828dc81c42..3bdec53fbe 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -3,16 +3,21 @@
#include "tree-walk.h"
#include "xdiff-interface.h"
#include "help.h"
+#include "gettext.h"
+#include "hex.h"
#include "commit.h"
#include "commit-reach.h"
#include "merge-ort.h"
-#include "object-store.h"
+#include "object-name.h"
+#include "object-store-ll.h"
#include "parse-options.h"
#include "repository.h"
#include "blob.h"
-#include "exec-cmd.h"
#include "merge-blobs.h"
#include "quote.h"
+#include "tree.h"
+#include "config.h"
+#include "strvec.h"
static int line_termination = '\n';
@@ -69,7 +74,9 @@ static void *result(struct merge_list *entry, unsigned long *size)
const char *path = entry->path;
if (!entry->stage)
- return read_object_file(&entry->blob->object.oid, &type, size);
+ return repo_read_object_file(the_repository,
+ &entry->blob->object.oid, &type,
+ size);
base = NULL;
if (entry->stage == 1) {
base = entry->blob;
@@ -92,8 +99,9 @@ static void *origin(struct merge_list *entry, unsigned long *size)
enum object_type type;
while (entry) {
if (entry->stage == 2)
- return read_object_file(&entry->blob->object.oid,
- &type, size);
+ return repo_read_object_file(the_repository,
+ &entry->blob->object.oid,
+ &type, size);
entry = entry->link;
}
return NULL;
@@ -316,7 +324,9 @@ static void unresolved(const struct traverse_info *info, struct name_entry n[3])
* The successful merge rules are the same as for the three-way merge
* in git-read-tree.
*/
-static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, struct traverse_info *info)
+static int threeway_callback(int n UNUSED, unsigned long mask,
+ unsigned long dirmask UNUSED,
+ struct name_entry *entry, struct traverse_info *info)
{
/* Same in both? */
if (same_entry(entry+1, entry+2) || both_empty(entry+1, entry+2)) {
@@ -404,6 +414,7 @@ struct merge_tree_options {
int show_messages;
int name_only;
int use_stdin;
+ struct merge_options merge_options;
};
static int real_merge(struct merge_tree_options *o,
@@ -413,10 +424,11 @@ static int real_merge(struct merge_tree_options *o,
{
struct commit *parent1, *parent2;
struct commit_list *merge_bases = NULL;
- struct merge_options opt;
struct merge_result result = { 0 };
int show_messages = o->show_messages;
+ struct merge_options opt;
+ copy_merge_options(&opt, &o->merge_options);
parent1 = get_merge_parent(branch1);
if (!parent1)
help_unknown_ref(branch1, "merge-tree",
@@ -427,8 +439,6 @@ static int real_merge(struct merge_tree_options *o,
help_unknown_ref(branch2, "merge-tree",
_("not something we can merge"));
- init_merge_options(&opt, the_repository);
-
opt.show_rename_progress = 0;
opt.branch1 = branch1;
@@ -440,19 +450,20 @@ static int real_merge(struct merge_tree_options *o,
base_commit = lookup_commit_reference_by_name(merge_base);
if (!base_commit)
- die(_("could not lookup commit %s"), merge_base);
+ die(_("could not lookup commit '%s'"), merge_base);
opt.ancestor = merge_base;
- base_tree = get_commit_tree(base_commit);
- parent1_tree = get_commit_tree(parent1);
- parent2_tree = get_commit_tree(parent2);
+ base_tree = repo_get_commit_tree(the_repository, base_commit);
+ parent1_tree = repo_get_commit_tree(the_repository, parent1);
+ parent2_tree = repo_get_commit_tree(the_repository, parent2);
merge_incore_nonrecursive(&opt, base_tree, parent1_tree, parent2_tree, &result);
} else {
/*
* Get the merge bases, in reverse order; see comment above
* merge_incore_recursive in merge-ort.h
*/
- merge_bases = get_merge_bases(parent1, parent2);
+ merge_bases = repo_get_merge_bases(the_repository, parent1,
+ parent2);
if (!merge_bases && !o->allow_unrelated_histories)
die(_("refusing to merge unrelated histories"));
merge_bases = reverse_commit_list(merge_bases);
@@ -496,12 +507,14 @@ static int real_merge(struct merge_tree_options *o,
if (o->use_stdin)
putchar(line_termination);
merge_finalize(&opt, &result);
+ clear_merge_options(&opt);
return !result.clean; /* result.clean < 0 handled above */
}
int cmd_merge_tree(int argc, const char **argv, const char *prefix)
{
struct merge_tree_options o = { .show_messages = -1 };
+ struct strvec xopts = STRVEC_INIT;
int expected_remaining_argc;
int original_argc;
const char *merge_base = NULL;
@@ -537,14 +550,25 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
&merge_base,
N_("commit"),
N_("specify a merge-base for the merge")),
+ OPT_STRVEC('X', "strategy-option", &xopts, N_("option=value"),
+ N_("option for selected merge strategy")),
OPT_END()
};
+ /* Init merge options */
+ init_merge_options(&o.merge_options, the_repository);
+
/* Parse arguments */
original_argc = argc - 1; /* ignoring argv[0] */
argc = parse_options(argc, argv, prefix, mt_options,
merge_tree_usage, PARSE_OPT_STOP_AT_NON_OPTION);
+ if (xopts.nr && o.mode == MODE_TRIVIAL)
+ die(_("--trivial-merge is incompatible with all other options"));
+ for (int x = 0; x < xopts.nr; x++)
+ if (parse_merge_opt(&o.merge_options, xopts.v[x]))
+ die(_("unknown strategy option: -X%s"), xopts.v[x]);
+
/* Handle --stdin */
if (o.use_stdin) {
struct strbuf buf = STRBUF_INIT;
@@ -552,7 +576,8 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
if (o.mode == MODE_TRIVIAL)
die(_("--trivial-merge is incompatible with all other options"));
if (merge_base)
- die(_("--merge-base is incompatible with --stdin"));
+ die(_("options '%s' and '%s' cannot be used together"),
+ "--merge-base", "--stdin");
line_termination = '\0';
while (strbuf_getline_lf(&buf, stdin) != EOF) {
struct strbuf **split;
@@ -620,6 +645,8 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
if (argc != expected_remaining_argc)
usage_with_options(merge_tree_usage, mt_options);
+ git_config(git_default_config, NULL);
+
/* Do the relevant type of merge */
if (o.mode == MODE_REAL)
return real_merge(&o, merge_base, argv[0], argv[1], prefix);