summaryrefslogtreecommitdiff
path: root/builtin/merge.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/merge.c')
-rw-r--r--builtin/merge.c85
1 files changed, 34 insertions, 51 deletions
diff --git a/builtin/merge.c b/builtin/merge.c
index 8763b2efa2..3b0f8f96d4 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -9,6 +9,7 @@
#include "cache.h"
#include "parse-options.h"
#include "builtin.h"
+#include "lockfile.h"
#include "run-command.h"
#include "diff.h"
#include "refs.h"
@@ -28,6 +29,7 @@
#include "remote.h"
#include "fmt-merge-msg.h"
#include "gpg-interface.h"
+#include "sequencer.h"
#define DEFAULT_TWOHEAD (1<<0)
#define DEFAULT_OCTOPUS (1<<1)
@@ -40,8 +42,8 @@ struct strategy {
};
static const char * const builtin_merge_usage[] = {
- N_("git merge [options] [<commit>...]"),
- N_("git merge [options] <msg> HEAD <commit>"),
+ N_("git merge [<options>] [<commit>...]"),
+ N_("git merge [<options>] <msg> HEAD <commit>"),
N_("git merge --abort"),
NULL
};
@@ -63,7 +65,7 @@ static int verbosity;
static int allow_rerere_auto;
static int abort_current_merge;
static int show_progress = -1;
-static int default_to_upstream;
+static int default_to_upstream = 1;
static const char *sign_commit;
static struct strategy all_strategy[] = {
@@ -237,11 +239,10 @@ static void drop_save(void)
static int save_state(unsigned char *stash)
{
int len;
- struct child_process cp;
+ struct child_process cp = CHILD_PROCESS_INIT;
struct strbuf buffer = STRBUF_INIT;
const char *argv[] = {"stash", "create", NULL};
- memset(&cp, 0, sizeof(cp));
cp.argv = argv;
cp.out = -1;
cp.git_cmd = 1;
@@ -398,7 +399,7 @@ static void finish(struct commit *head_commit,
const char *argv_gc_auto[] = { "gc", "--auto", NULL };
update_ref(reflog_message.buf, "HEAD",
new_head, head, 0,
- DIE_ON_ERR);
+ UPDATE_REFS_DIE_ON_ERR);
/*
* We ignore errors in 'gc --auto', since the
* user should see them.
@@ -557,7 +558,7 @@ static void parse_branch_merge_options(char *bmo)
if (argc < 0)
die(_("Bad branch.%s.mergeoptions string: %s"), branch,
split_cmdline_strerror(argc));
- argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
+ REALLOC_ARRAY(argv, argc + 2);
memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
argc++;
argv[0] = "branch.*.mergeoptions";
@@ -657,22 +658,18 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
struct commit_list *remoteheads,
struct commit *head, const char *head_arg)
{
- int index_fd;
- struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
+ static struct lock_file lock;
- index_fd = hold_locked_index(lock, 1);
+ hold_locked_index(&lock, 1);
refresh_cache(REFRESH_QUIET);
if (active_cache_changed &&
- (write_cache(index_fd, active_cache, active_nr) ||
- commit_locked_index(lock)))
+ write_locked_index(&the_index, &lock, COMMIT_LOCK))
return error(_("Unable to write index."));
- rollback_lock_file(lock);
+ rollback_lock_file(&lock);
if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree")) {
int clean, x;
struct commit *result;
- struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
- int index_fd;
struct commit_list *reversed = NULL;
struct merge_options o;
struct commit_list *j;
@@ -700,14 +697,13 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
for (j = common; j; j = j->next)
commit_list_insert(j->item, &reversed);
- index_fd = hold_locked_index(lock, 1);
+ hold_locked_index(&lock, 1);
clean = merge_recursive(&o, head,
remoteheads->item, reversed, &result);
if (active_cache_changed &&
- (write_cache(index_fd, active_cache, active_nr) ||
- commit_locked_index(lock)))
+ write_locked_index(&the_index, &lock, COMMIT_LOCK))
die (_("unable to write %s"), get_index_file());
- rollback_lock_file(lock);
+ rollback_lock_file(&lock);
return clean ? 0 : 1;
} else {
return try_merge_command(strategy, xopts_nr, xopts,
@@ -843,16 +839,14 @@ static void prepare_to_commit(struct commit_list *remoteheads)
static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
{
unsigned char result_tree[20], result_commit[20];
- struct commit_list *parent = xmalloc(sizeof(*parent));
+ struct commit_list *parents, **pptr = &parents;
write_tree_trivial(result_tree);
printf(_("Wonderful.\n"));
- parent->item = head;
- parent->next = xmalloc(sizeof(*parent->next));
- parent->next->item = remoteheads->item;
- parent->next->next = NULL;
+ pptr = commit_list_append(head, pptr);
+ pptr = commit_list_append(remoteheads->item, pptr);
prepare_to_commit(remoteheads);
- if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parent,
+ if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents,
result_commit, NULL, sign_commit))
die(_("failed to write commit object"));
finish(head, remoteheads, result_commit, "In-index merge");
@@ -887,28 +881,20 @@ static int finish_automerge(struct commit *head,
return 0;
}
-static int suggest_conflicts(int renormalizing)
+static int suggest_conflicts(void)
{
const char *filename;
FILE *fp;
- int pos;
+ struct strbuf msgbuf = STRBUF_INIT;
filename = git_path("MERGE_MSG");
fp = fopen(filename, "a");
if (!fp)
die_errno(_("Could not open '%s' for writing"), filename);
- fprintf(fp, "\nConflicts:\n");
- for (pos = 0; pos < active_nr; pos++) {
- const struct cache_entry *ce = active_cache[pos];
-
- if (ce_stage(ce)) {
- fprintf(fp, "\t%s\n", ce->name);
- while (pos + 1 < active_nr &&
- !strcmp(ce->name,
- active_cache[pos + 1]->name))
- pos++;
- }
- }
+
+ append_conflicts_hint(&msgbuf);
+ fputs(msgbuf.buf, fp);
+ strbuf_release(&msgbuf);
fclose(fp);
rerere(allow_rerere_auto);
printf(_("Automatic merge failed; "
@@ -1108,7 +1094,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
* Check if we are _not_ on a detached HEAD, i.e. if there is a
* current branch.
*/
- branch = branch_to_free = resolve_refdup("HEAD", head_sha1, 0, &flag);
+ branch = branch_to_free = resolve_refdup("HEAD", 0, head_sha1, &flag);
if (branch && starts_with(branch, "refs/heads/"))
branch += 11;
if (!branch || is_null_sha1(head_sha1))
@@ -1150,14 +1136,14 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
*/
if (advice_resolve_conflict)
die(_("You have not concluded your merge (MERGE_HEAD exists).\n"
- "Please, commit your changes before you can merge."));
+ "Please, commit your changes before you merge."));
else
die(_("You have not concluded your merge (MERGE_HEAD exists)."));
}
if (file_exists(git_path("CHERRY_PICK_HEAD"))) {
if (advice_resolve_conflict)
die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
- "Please, commit your changes before you can merge."));
+ "Please, commit your changes before you merge."));
else
die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."));
}
@@ -1222,7 +1208,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
die(_("%s - not something we can merge"), argv[0]);
read_empty(remote_head->object.sha1, 0);
update_ref("initial pull", "HEAD", remote_head->object.sha1,
- NULL, 0, DIE_ON_ERR);
+ NULL, 0, UPDATE_REFS_DIE_ON_ERR);
goto done;
} else {
struct strbuf merge_names = STRBUF_INIT;
@@ -1282,10 +1268,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
printf(_("Commit %s has a good GPG signature by %s\n"),
hex, signature_check.signer);
- free(signature_check.gpg_output);
- free(signature_check.gpg_status);
- free(signature_check.signer);
- free(signature_check.key);
+ signature_check_clear(&signature_check);
}
}
@@ -1330,7 +1313,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
if (!remoteheads)
; /* already up-to-date */
else if (!remoteheads->next)
- common = get_merge_bases(head_commit, remoteheads->item, 1);
+ common = get_merge_bases(head_commit, remoteheads->item);
else {
struct commit_list *list = remoteheads;
commit_list_insert(head_commit, &list);
@@ -1339,7 +1322,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
}
update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.sha1,
- NULL, 0, DIE_ON_ERR);
+ NULL, 0, UPDATE_REFS_DIE_ON_ERR);
if (remoteheads && !common)
; /* No common ancestors found. We need a real merge. */
@@ -1427,7 +1410,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
* merge_bases again, otherwise "git merge HEAD^
* HEAD^^" would be missed.
*/
- common_one = get_merge_bases(head_commit, j->item, 1);
+ common_one = get_merge_bases(head_commit, j->item);
if (hashcmp(common_one->item->object.sha1,
j->item->object.sha1)) {
up_to_date = 0;
@@ -1560,7 +1543,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
fprintf(stderr, _("Automatic merge went well; "
"stopped before committing as requested\n"));
else
- ret = suggest_conflicts(option_renormalize);
+ ret = suggest_conflicts();
done:
free(branch_to_free);