The sixteenth batch
[git/gitster.git] / merge-ort-wrappers.c
blobc54d56b34465bf322f99ccc859193f8ab515ebaa
1 #include "git-compat-util.h"
2 #include "gettext.h"
3 #include "hash.h"
4 #include "hex.h"
5 #include "lockfile.h"
6 #include "merge-ort.h"
7 #include "merge-ort-wrappers.h"
8 #include "read-cache-ll.h"
9 #include "repository.h"
10 #include "tag.h"
11 #include "tree.h"
13 #include "commit.h"
15 static int unclean(struct merge_options *opt, struct tree *head)
17 /* Sanity check on repo state; index must match head */
18 struct strbuf sb = STRBUF_INIT;
20 if (head && repo_index_has_changes(opt->repo, head, &sb)) {
21 error(_("Your local changes to the following files would be overwritten by merge:\n %s"),
22 sb.buf);
23 strbuf_release(&sb);
24 return -1;
27 return 0;
30 int merge_ort_nonrecursive(struct merge_options *opt,
31 struct tree *head,
32 struct tree *merge,
33 struct tree *merge_base)
35 struct merge_result result;
36 int show_msgs;
38 if (unclean(opt, head))
39 return -1;
41 if (oideq(&merge_base->object.oid, &merge->object.oid)) {
42 printf_ln(_("Already up to date."));
43 return 1;
46 show_msgs = !!opt->verbosity;
47 memset(&result, 0, sizeof(result));
48 merge_incore_nonrecursive(opt, merge_base, head, merge, &result);
49 merge_switch_to_result(opt, head, &result, 1, show_msgs);
51 return result.clean;
54 int merge_ort_recursive(struct merge_options *opt,
55 struct commit *side1,
56 struct commit *side2,
57 const struct commit_list *merge_bases,
58 struct commit **result)
60 struct tree *head = repo_get_commit_tree(opt->repo, side1);
61 struct merge_result tmp;
62 int show_msgs;
64 if (unclean(opt, head))
65 return -1;
67 show_msgs = !!opt->verbosity;
68 memset(&tmp, 0, sizeof(tmp));
69 merge_incore_recursive(opt, merge_bases, side1, side2, &tmp);
70 merge_switch_to_result(opt, head, &tmp, 1, show_msgs);
71 *result = NULL;
73 return tmp.clean;
76 static struct commit *get_ref(struct repository *repo,
77 const struct object_id *oid,
78 const char *name)
80 struct object *object;
82 object = deref_tag(repo, parse_object(repo, oid),
83 name, strlen(name));
84 if (!object)
85 return NULL;
86 if (object->type == OBJ_TREE)
87 return make_virtual_commit(repo, (struct tree*)object, name);
88 if (object->type != OBJ_COMMIT)
89 return NULL;
90 if (repo_parse_commit(repo, (struct commit *)object))
91 return NULL;
92 return (struct commit *)object;
95 int merge_ort_generic(struct merge_options *opt,
96 const struct object_id *head,
97 const struct object_id *merge,
98 int num_merge_bases,
99 const struct object_id *merge_bases,
100 struct commit **result)
102 int clean;
103 struct lock_file lock = LOCK_INIT;
104 struct commit *head_commit = get_ref(opt->repo, head, opt->branch1);
105 struct commit *next_commit = get_ref(opt->repo, merge, opt->branch2);
106 struct commit_list *ca = NULL;
108 if (merge_bases) {
109 int i;
110 for (i = 0; i < num_merge_bases; ++i) {
111 struct commit *base;
112 if (!(base = get_ref(opt->repo, &merge_bases[i],
113 oid_to_hex(&merge_bases[i]))))
114 return error(_("Could not parse object '%s'"),
115 oid_to_hex(&merge_bases[i]));
116 commit_list_insert(base, &ca);
120 repo_hold_locked_index(opt->repo, &lock, LOCK_DIE_ON_ERROR);
121 clean = merge_ort_recursive(opt, head_commit, next_commit, ca,
122 result);
123 free_commit_list(ca);
124 if (clean < 0) {
125 rollback_lock_file(&lock);
126 return clean;
129 if (write_locked_index(opt->repo->index, &lock,
130 COMMIT_LOCK | SKIP_IF_UNCHANGED))
131 return error(_("Unable to write index."));
133 return clean ? 0 : 1;