diff options
Diffstat (limited to 'builtin/merge.c')
-rw-r--r-- | builtin/merge.c | 415 |
1 files changed, 278 insertions, 137 deletions
diff --git a/builtin/merge.c b/builtin/merge.c index 37ce4f589f..ab4077f272 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -25,6 +25,7 @@ #include "help.h" #include "merge-recursive.h" #include "resolve-undo.h" +#include "remote.h" #define DEFAULT_TWOHEAD (1<<0) #define DEFAULT_OCTOPUS (1<<1) @@ -37,12 +38,13 @@ struct strategy { }; static const char * const builtin_merge_usage[] = { - "git merge [options] <remote>...", - "git merge [options] <msg> HEAD <remote>", + "git merge [options] [<commit>...]", + "git merge [options] <msg> HEAD <commit>", + "git merge --abort", NULL }; -static int show_diffstat = 1, option_log, squash; +static int show_diffstat = 1, shortlog_len, squash; static int option_commit = 1, allow_fast_forward = 1; static int fast_forward_only; static int allow_trivial = 1, have_message; @@ -54,8 +56,13 @@ static size_t use_strategies_nr, use_strategies_alloc; static const char **xopts; static size_t xopts_nr, xopts_alloc; static const char *branch; +static char *branch_mergeoptions; +static int option_renormalize; static int verbosity; static int allow_rerere_auto; +static int abort_current_merge; +static int show_progress = -1; +static int default_to_upstream; static struct strategy all_strategy[] = { { "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL }, @@ -78,7 +85,7 @@ static int option_parse_message(const struct option *opt, strbuf_addf(buf, "%s%s", buf->len ? "\n\n" : "", arg); have_message = 1; } else - return error("switch `m' requires a value"); + return error(_("switch `m' requires a value")); return 0; } @@ -115,13 +122,13 @@ static struct strategy *get_strategy(const char *name) exclude_cmds(&main_cmds, ¬_strategies); } if (!is_in_cmdlist(&main_cmds, name) && !is_in_cmdlist(&other_cmds, name)) { - fprintf(stderr, "Could not find merge strategy '%s'.\n", name); - fprintf(stderr, "Available strategies are:"); + fprintf(stderr, _("Could not find merge strategy '%s'.\n"), name); + fprintf(stderr, _("Available strategies are:")); for (i = 0; i < main_cmds.cnt; i++) fprintf(stderr, " %s", main_cmds.names[i]->name); fprintf(stderr, ".\n"); if (other_cmds.cnt) { - fprintf(stderr, "Available custom strategies are:"); + fprintf(stderr, _("Available custom strategies are:")); for (i = 0; i < other_cmds.cnt; i++) fprintf(stderr, " %s", other_cmds.names[i]->name); fprintf(stderr, ".\n"); @@ -131,6 +138,7 @@ static struct strategy *get_strategy(const char *name) ret = xcalloc(1, sizeof(struct strategy)); ret->name = xstrdup(name); + ret->attr = NO_TRIVIAL; return ret; } @@ -175,8 +183,9 @@ static struct option builtin_merge_options[] = { OPT_BOOLEAN(0, "stat", &show_diffstat, "show a diffstat at the end of the merge"), OPT_BOOLEAN(0, "summary", &show_diffstat, "(synonym to --stat)"), - OPT_BOOLEAN(0, "log", &option_log, - "add list of one-line log to merge commit message"), + { OPTION_INTEGER, 0, "log", &shortlog_len, "n", + "add (at most <n>) entries from shortlog to merge commit message", + PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN }, OPT_BOOLEAN(0, "squash", &squash, "create a single commit instead of doing a merge"), OPT_BOOLEAN(0, "commit", &option_commit, @@ -191,9 +200,12 @@ static struct option builtin_merge_options[] = { OPT_CALLBACK('X', "strategy-option", &xopts, "option=value", "option for selected merge strategy", option_parse_x), OPT_CALLBACK('m', "message", &merge_msg, "message", - "message to be used for the merge commit (if any)", + "merge commit message (for a non-fast-forward merge)", option_parse_message), OPT__VERBOSITY(&verbosity), + OPT_BOOLEAN(0, "abort", &abort_current_merge, + "abort the current in-progress merge"), + OPT_SET_INT(0, "progress", &show_progress, "force progress reporting", 1), OPT_END() }; @@ -218,17 +230,35 @@ static void save_state(void) cp.git_cmd = 1; if (start_command(&cp)) - die("could not run stash."); + die(_("could not run stash.")); len = strbuf_read(&buffer, cp.out, 1024); close(cp.out); if (finish_command(&cp) || len < 0) - die("stash failed"); + die(_("stash failed")); else if (!len) return; strbuf_setlen(&buffer, buffer.len-1); if (get_sha1(buffer.buf, stash)) - die("not a valid object: %s", buffer.buf); + die(_("not a valid object: %s"), buffer.buf); +} + +static void read_empty(unsigned const char *sha1, int verbose) +{ + int i = 0; + const char *args[7]; + + args[i++] = "read-tree"; + if (verbose) + args[i++] = "-v"; + args[i++] = "-m"; + args[i++] = "-u"; + args[i++] = EMPTY_TREE_SHA1_HEX; + args[i++] = sha1_to_hex(sha1); + args[i] = NULL; + + if (run_command_v_opt(args, RUN_GIT_CMD)) + die(_("read-tree failed")); } static void reset_hard(unsigned const char *sha1, int verbose) @@ -245,7 +275,7 @@ static void reset_hard(unsigned const char *sha1, int verbose) args[i] = NULL; if (run_command_v_opt(args, RUN_GIT_CMD)) - die("read-tree failed"); + die(_("read-tree failed")); } static void restore_state(void) @@ -274,7 +304,7 @@ static void restore_state(void) static void finish_up_to_date(const char *msg) { if (verbosity >= 0) - printf("%s%s\n", squash ? " (nothing to squash)" : "", msg); + printf("%s%s\n", squash ? _(" (nothing to squash)") : "", msg); drop_save(); } @@ -287,10 +317,10 @@ static void squash_message(void) int fd; struct pretty_print_context ctx = {0}; - printf("Squash commit -- not updating HEAD\n"); + printf(_("Squash commit -- not updating HEAD\n")); fd = open(git_path("SQUASH_MSG"), O_WRONLY | O_CREAT, 0666); if (fd < 0) - die_errno("Could not write to '%s'", git_path("SQUASH_MSG")); + die_errno(_("Could not write to '%s'"), git_path("SQUASH_MSG")); init_revisions(&rev, NULL); rev.ignore_merges = 1; @@ -305,22 +335,23 @@ static void squash_message(void) setup_revisions(0, NULL, &rev, NULL); if (prepare_revision_walk(&rev)) - die("revision walk setup failed"); + die(_("revision walk setup failed")); ctx.abbrev = rev.abbrev; ctx.date_mode = rev.date_mode; + ctx.fmt = rev.commit_format; strbuf_addstr(&out, "Squashed commit of the following:\n"); while ((commit = get_revision(&rev)) != NULL) { strbuf_addch(&out, '\n'); strbuf_addf(&out, "commit %s\n", sha1_to_hex(commit->object.sha1)); - pretty_print_commit(rev.commit_format, commit, &out, &ctx); + pretty_print_commit(&ctx, commit, &out); } if (write(fd, out.buf, out.len) < 0) - die_errno("Writing SQUASH_MSG"); + die_errno(_("Writing SQUASH_MSG")); if (close(fd)) - die_errno("Finishing SQUASH_MSG"); + die_errno(_("Finishing SQUASH_MSG")); strbuf_release(&out); } @@ -340,7 +371,7 @@ static void finish(const unsigned char *new_head, const char *msg) squash_message(); } else { if (verbosity >= 0 && !merge_msg.len) - printf("No merge message -- not updating HEAD\n"); + printf(_("No merge message -- not updating HEAD\n")); else { const char *argv_gc_auto[] = { "gc", "--auto", NULL }; update_ref(reflog_message.buf, "HEAD", @@ -359,10 +390,8 @@ static void finish(const unsigned char *new_head, const char *msg) opts.output_format |= DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT; opts.detect_rename = DIFF_DETECT_RENAME; - if (diff_use_color_default > 0) - DIFF_OPT_SET(&opts, COLOR_DIFF); if (diff_setup_done(&opts) < 0) - die("diff_setup_done failed"); + die(_("diff_setup_done failed")); diff_tree_sha1(head, new_head, "", &opts); diffcore_std(&opts); diff_flush(&opts); @@ -391,7 +420,7 @@ static void merge_name(const char *remote, struct strbuf *msg) memset(branch_head, 0, sizeof(branch_head)); remote_head = peel_to_type(remote, 0, NULL, OBJ_COMMIT); if (!remote_head) - die("'%s' does not point to a commit", remote); + die(_("'%s' does not point to a commit"), remote); if (dwim_ref(remote, strlen(remote), branch_head, &found_ref) > 0) { if (!prefixcmp(found_ref, "refs/heads/")) { @@ -400,7 +429,7 @@ static void merge_name(const char *remote, struct strbuf *msg) goto cleanup; } if (!prefixcmp(found_ref, "refs/remotes/")) { - strbuf_addf(msg, "%s\t\tremote branch '%s' of .\n", + strbuf_addf(msg, "%s\t\tremote-tracking branch '%s' of .\n", sha1_to_hex(branch_head), remote); goto cleanup; } @@ -437,7 +466,7 @@ static void merge_name(const char *remote, struct strbuf *msg) strbuf_addstr(&truname, "refs/heads/"); strbuf_addstr(&truname, remote); strbuf_setlen(&truname, truname.len - len); - if (resolve_ref(truname.buf, buf_sha, 0, NULL)) { + if (resolve_ref(truname.buf, buf_sha, 1, NULL)) { strbuf_addf(msg, "%s\t\tbranch '%s'%s of .\n", sha1_to_hex(remote_head->sha1), @@ -456,7 +485,7 @@ static void merge_name(const char *remote, struct strbuf *msg) fp = fopen(git_path("FETCH_HEAD"), "r"); if (!fp) - die_errno("could not open '%s' for reading", + die_errno(_("could not open '%s' for reading"), git_path("FETCH_HEAD")); strbuf_getline(&line, fp, '\n'); fclose(fp); @@ -474,25 +503,34 @@ cleanup: strbuf_release(&bname); } +static void parse_branch_merge_options(char *bmo) +{ + const char **argv; + int argc; + + if (!bmo) + return; + argc = split_cmdline(bmo, &argv); + if (argc < 0) + die(_("Bad branch.%s.mergeoptions string: %s"), branch, + split_cmdline_strerror(argc)); + argv = xrealloc(argv, sizeof(*argv) * (argc + 2)); + memmove(argv + 1, argv, sizeof(*argv) * (argc + 1)); + argc++; + argv[0] = "branch.*.mergeoptions"; + parse_options(argc, argv, NULL, builtin_merge_options, + builtin_merge_usage, 0); + free(argv); +} + static int git_merge_config(const char *k, const char *v, void *cb) { if (branch && !prefixcmp(k, "branch.") && !prefixcmp(k + 7, branch) && !strcmp(k + 7 + strlen(branch), ".mergeoptions")) { - const char **argv; - int argc; - char *buf; - - buf = xstrdup(v); - argc = split_cmdline(buf, &argv); - if (argc < 0) - die("Bad branch.%s.mergeoptions string", branch); - argv = xrealloc(argv, sizeof(*argv) * (argc + 2)); - memmove(argv + 1, argv, sizeof(*argv) * (argc + 1)); - argc++; - parse_options(argc, argv, NULL, builtin_merge_options, - builtin_merge_usage, 0); - free(buf); + free(branch_mergeoptions); + branch_mergeoptions = xstrdup(v); + return 0; } if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat")) @@ -501,8 +539,29 @@ static int git_merge_config(const char *k, const char *v, void *cb) return git_config_string(&pull_twohead, k, v); else if (!strcmp(k, "pull.octopus")) return git_config_string(&pull_octopus, k, v); - else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary")) - option_log = git_config_bool(k, v); + else if (!strcmp(k, "merge.renormalize")) + option_renormalize = git_config_bool(k, v); + else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary")) { + int is_bool; + shortlog_len = git_config_bool_or_int(k, v, &is_bool); + if (!is_bool && shortlog_len < 0) + return error(_("%s: negative length %s"), k, v); + if (is_bool && shortlog_len) + shortlog_len = DEFAULT_MERGE_LOG_LEN; + return 0; + } else if (!strcmp(k, "merge.ff")) { + int boolval = git_config_maybe_bool(k, v); + if (0 <= boolval) { + allow_fast_forward = boolval; + } else if (v && !strcmp(v, "only")) { + allow_fast_forward = 1; + fast_forward_only = 1; + } /* do not barf on values from future versions of git */ + return 0; + } else if (!strcmp(k, "merge.defaulttoupstream")) { + default_to_upstream = git_config_bool(k, v); + return 0; + } return git_diff_ui_config(k, v, cb); } @@ -545,10 +604,19 @@ static int read_tree_trivial(unsigned char *common, unsigned char *head, static void write_tree_trivial(unsigned char *sha1) { if (write_cache_as_tree(sha1, 0, NULL)) - die("git write-tree failed to write a tree"); + die(_("git write-tree failed to write a tree")); } -int try_merge_command(const char *strategy, struct commit_list *common, +static const char *merge_argument(struct commit *commit) +{ + if (commit) + return sha1_to_hex(commit->object.sha1); + else + return EMPTY_TREE_SHA1_HEX; +} + +int try_merge_command(const char *strategy, size_t xopts_nr, + const char **xopts, struct commit_list *common, const char *head_arg, struct commit_list *remotes) { const char **args; @@ -567,11 +635,11 @@ int try_merge_command(const char *strategy, struct commit_list *common, args[i++] = s; } for (j = common; j; j = j->next) - args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1)); + args[i++] = xstrdup(merge_argument(j->item)); args[i++] = "--"; args[i++] = head_arg; for (j = remotes; j; j = j->next) - args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1)); + args[i++] = xstrdup(merge_argument(j->item)); args[i] = NULL; ret = run_command_v_opt(args, RUN_GIT_CMD); strbuf_release(&buf); @@ -586,7 +654,7 @@ int try_merge_command(const char *strategy, struct commit_list *common, free(args); discard_cache(); if (read_cache() < 0) - die("failed to read the cache"); + die(_("failed to read the cache")); resolve_undo_clear(); return ret; @@ -603,7 +671,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, if (active_cache_changed && (write_cache(index_fd, active_cache, active_nr) || commit_locked_index(lock))) - return error("Unable to write index."); + return error(_("Unable to write index.")); rollback_lock_file(lock); if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree")) { @@ -616,7 +684,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, struct commit_list *j; if (remoteheads->next) { - error("Not handling anything other than two heads merge."); + error(_("Not handling anything other than two heads merge.")); return 2; } @@ -624,18 +692,13 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, if (!strcmp(strategy, "subtree")) o.subtree_shift = ""; - for (x = 0; x < xopts_nr; x++) { - if (!strcmp(xopts[x], "ours")) - o.recursive_variant = MERGE_RECURSIVE_OURS; - else if (!strcmp(xopts[x], "theirs")) - o.recursive_variant = MERGE_RECURSIVE_THEIRS; - else if (!strcmp(xopts[x], "subtree")) - o.subtree_shift = ""; - else if (!prefixcmp(xopts[x], "subtree=")) - o.subtree_shift = xopts[x]+8; - else - die("Unknown option for merge-recursive: -X%s", xopts[x]); - } + o.renormalize = option_renormalize; + o.show_rename_progress = + show_progress == -1 ? isatty(2) : show_progress; + + for (x = 0; x < xopts_nr; x++) + if (parse_merge_opt(&o, xopts[x])) + die(_("Unknown option for merge-recursive: -X%s"), xopts[x]); o.branch1 = head_arg; o.branch2 = remoteheads->item->util; @@ -649,11 +712,12 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, if (active_cache_changed && (write_cache(index_fd, active_cache, active_nr) || commit_locked_index(lock))) - die ("unable to write %s", get_index_file()); + die (_("unable to write %s"), get_index_file()); rollback_lock_file(lock); return clean ? 0 : 1; } else { - return try_merge_command(strategy, common, head_arg, remoteheads); + return try_merge_command(strategy, xopts_nr, xopts, + common, head_arg, remoteheads); } } @@ -704,7 +768,7 @@ int checkout_fast_forward(const unsigned char *head, const unsigned char *remote opts.verbose_update = 1; opts.merge = 1; opts.fn = twoway_merge; - opts.msgs = get_porcelain_error_msgs(); + setup_unpack_trees_porcelain(&opts, "merge"); trees[nr_trees] = parse_tree_indirect(head); if (!trees[nr_trees++]) @@ -720,7 +784,7 @@ int checkout_fast_forward(const unsigned char *head, const unsigned char *remote return -1; if (write_cache(fd, active_cache, active_nr) || commit_locked_index(lock_file)) - die("unable to write new index file"); + die(_("unable to write new index file")); return 0; } @@ -768,17 +832,44 @@ static void add_strategies(const char *string, unsigned attr) } +static void write_merge_msg(void) +{ + int fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666); + if (fd < 0) + die_errno(_("Could not open '%s' for writing"), + git_path("MERGE_MSG")); + if (write_in_full(fd, merge_msg.buf, merge_msg.len) != merge_msg.len) + die_errno(_("Could not write to '%s'"), git_path("MERGE_MSG")); + close(fd); +} + +static void read_merge_msg(void) +{ + strbuf_reset(&merge_msg); + if (strbuf_read_file(&merge_msg, git_path("MERGE_MSG"), 0) < 0) + die_errno(_("Could not read from '%s'"), git_path("MERGE_MSG")); +} + +static void run_prepare_commit_msg(void) +{ + write_merge_msg(); + run_hook(get_index_file(), "prepare-commit-msg", + git_path("MERGE_MSG"), "merge", NULL, NULL); + read_merge_msg(); +} + static int merge_trivial(void) { unsigned char result_tree[20], result_commit[20]; struct commit_list *parent = xmalloc(sizeof(*parent)); write_tree_trivial(result_tree); - printf("Wonderful.\n"); + printf(_("Wonderful.\n")); parent->item = lookup_commit(head); parent->next = xmalloc(sizeof(*parent->next)); parent->next->item = remoteheads->item; parent->next->next = NULL; + run_prepare_commit_msg(); commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL); finish(result_commit, "In-index merge"); drop_save(); @@ -808,22 +899,23 @@ static int finish_automerge(struct commit_list *common, } free_commit_list(remoteheads); strbuf_addch(&merge_msg, '\n'); + run_prepare_commit_msg(); commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL); - strbuf_addf(&buf, "Merge made by %s.", wt_strategy); + strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy); finish(result_commit, buf.buf); strbuf_release(&buf); drop_save(); return 0; } -static int suggest_conflicts(void) +static int suggest_conflicts(int renormalizing) { FILE *fp; int pos; fp = fopen(git_path("MERGE_MSG"), "a"); if (!fp) - die_errno("Could not open '%s' for writing", + die_errno(_("Could not open '%s' for writing"), git_path("MERGE_MSG")); fprintf(fp, "\nConflicts:\n"); for (pos = 0; pos < active_nr; pos++) { @@ -839,8 +931,8 @@ static int suggest_conflicts(void) } fclose(fp); rerere(allow_rerere_auto); - printf("Automatic merge failed; " - "fix conflicts and then commit the result.\n"); + printf(_("Automatic merge failed; " + "fix conflicts and then commit the result.\n")); return 1; } @@ -854,7 +946,7 @@ static struct commit *is_old_style_invocation(int argc, const char **argv) return NULL; second_token = lookup_commit_reference_gently(second_sha1, 0); if (!second_token) - die("'%s' is not a commit", argv[1]); + die(_("'%s' is not a commit"), argv[1]); if (hashcmp(second_token->object.sha1, head)) return NULL; } @@ -884,6 +976,35 @@ static int evaluate_result(void) return cnt; } +/* + * Pretend as if the user told us to merge with the tracking + * branch we have for the upstream of the current branch + */ +static int setup_with_upstream(const char ***argv) +{ + struct branch *branch = branch_get(NULL); + int i; + const char **args; + + if (!branch) + die(_("No current branch.")); + if (!branch->remote) + die(_("No remote for the current branch.")); + if (!branch->merge_nr) + die(_("No default upstream defined for the current branch.")); + + args = xcalloc(branch->merge_nr + 1, sizeof(char *)); + for (i = 0; i < branch->merge_nr; i++) { + if (!branch->merge[i]->dst) + die(_("No remote tracking branch for %s from %s"), + branch->merge[i]->src, branch->remote_name); + args[i] = branch->merge[i]->dst; + } + args[i] = NULL; + *argv = args; + return i; +} + int cmd_merge(int argc, const char **argv, const char *prefix) { unsigned char result_tree[20]; @@ -895,22 +1016,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix) const char *best_strategy = NULL, *wt_strategy = NULL; struct commit_list **remotes = &remoteheads; - if (read_cache_unmerged()) { - die_resolve_conflict("merge"); - } - if (file_exists(git_path("MERGE_HEAD"))) { - /* - * There is no unmerged entry, don't advise 'git - * add/rm <file>', just 'git commit'. - */ - if (advice_resolve_conflict) - die("You have not concluded your merge (MERGE_HEAD exists).\n" - "Please, commit your changes before you can merge."); - else - die("You have not concluded your merge (MERGE_HEAD exists)."); - } + if (argc == 2 && !strcmp(argv[1], "-h")) + usage_with_options(builtin_merge_usage, builtin_merge_options); - resolve_undo_clear(); /* * Check if we are _not_ on a detached HEAD, i.e. if there is a * current branch. @@ -923,24 +1031,66 @@ int cmd_merge(int argc, const char **argv, const char *prefix) git_config(git_merge_config, NULL); - /* for color.ui */ - if (diff_use_color_default == -1) - diff_use_color_default = git_use_color_default; - + if (branch_mergeoptions) + parse_branch_merge_options(branch_mergeoptions); argc = parse_options(argc, argv, prefix, builtin_merge_options, builtin_merge_usage, 0); + + if (verbosity < 0 && show_progress == -1) + show_progress = 0; + + if (abort_current_merge) { + int nargc = 2; + const char *nargv[] = {"reset", "--merge", NULL}; + + if (!file_exists(git_path("MERGE_HEAD"))) + die(_("There is no merge to abort (MERGE_HEAD missing).")); + + /* Invoke 'git reset --merge' */ + return cmd_reset(nargc, nargv, prefix); + } + + if (read_cache_unmerged()) + die_resolve_conflict("merge"); + + if (file_exists(git_path("MERGE_HEAD"))) { + /* + * There is no unmerged entry, don't advise 'git + * add/rm <file>', just 'git commit'. + */ + if (advice_resolve_conflict) + die(_("You have not concluded your merge (MERGE_HEAD exists).\n" + "Please, commit your changes before you can 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.")); + else + die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).")); + } + resolve_undo_clear(); + if (verbosity < 0) show_diffstat = 0; if (squash) { if (!allow_fast_forward) - die("You cannot combine --squash with --no-ff."); + die(_("You cannot combine --squash with --no-ff.")); option_commit = 0; } if (!allow_fast_forward && fast_forward_only) - die("You cannot combine --no-ff with --ff-only."); + die(_("You cannot combine --no-ff with --ff-only.")); + if (!abort_current_merge) { + if (!argc && default_to_upstream) + argc = setup_with_upstream(&argv); + else if (argc == 1 && !strcmp(argv[0], "-")) + argv[0] = "@{-1}"; + } if (!argc) usage_with_options(builtin_merge_usage, builtin_merge_options); @@ -967,19 +1117,19 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * We do the same for "git pull". */ if (argc != 1) - die("Can merge only exactly one commit into " - "empty head"); + die(_("Can merge only exactly one commit into " + "empty head")); if (squash) - die("Squash commit into empty head not supported yet"); + die(_("Squash commit into empty head not supported yet")); if (!allow_fast_forward) - die("Non-fast-forward commit does not make sense into " - "an empty head"); + die(_("Non-fast-forward commit does not make sense into " + "an empty head")); remote_head = peel_to_type(argv[0], 0, NULL, OBJ_COMMIT); if (!remote_head) - die("%s - not something we can merge", argv[0]); + die(_("%s - not something we can merge"), argv[0]); + read_empty(remote_head->sha1, 0); update_ref("initial pull", "HEAD", remote_head->sha1, NULL, 0, DIE_ON_ERR); - reset_hard(remote_head->sha1, 0); return 0; } else { struct strbuf merge_names = STRBUF_INIT; @@ -998,14 +1148,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix) for (i = 0; i < argc; i++) merge_name(argv[i], &merge_names); - if (have_message && option_log) - fmt_merge_msg_shortlog(&merge_names, &merge_msg); - else if (!have_message) - fmt_merge_msg(option_log, &merge_names, &merge_msg); - - - if (!(have_message && !option_log) && merge_msg.len) - strbuf_setlen(&merge_msg, merge_msg.len-1); + if (!have_message || shortlog_len) { + fmt_merge_msg(&merge_names, &merge_msg, !have_message, + shortlog_len); + if (merge_msg.len) + strbuf_setlen(&merge_msg, merge_msg.len - 1); + } } if (head_invalid || !argc) @@ -1024,7 +1172,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) o = peel_to_type(argv[i], 0, NULL, OBJ_COMMIT); if (!o) - die("%s - not something we can merge", argv[i]); + die(_("%s - not something we can merge"), argv[i]); commit = lookup_commit(o->sha1); commit->util = (void *)argv[i]; remotes = &commit_list_insert(commit, remotes)->next; @@ -1082,7 +1230,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) strcpy(hex, find_unique_abbrev(head, DEFAULT_ABBREV)); if (verbosity >= 0) - printf("Updating %s..%s\n", + printf(_("Updating %s..%s\n"), hex, find_unique_abbrev(remoteheads->item->object.sha1, DEFAULT_ABBREV)); @@ -1116,11 +1264,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix) if (allow_trivial && !fast_forward_only) { /* See if it is really trivial. */ git_committer_info(IDENT_ERROR_ON_NO_NAME); - printf("Trying really trivial in-index merge...\n"); + printf(_("Trying really trivial in-index merge...\n")); if (!read_tree_trivial(common->item->object.sha1, head, remoteheads->item->object.sha1)) return merge_trivial(); - printf("Nope.\n"); + printf(_("Nope.\n")); } } else { /* @@ -1153,7 +1301,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) } if (fast_forward_only) - die("Not possible to fast-forward, aborting."); + die(_("Not possible to fast-forward, aborting.")); /* We are going to make a new commit. */ git_committer_info(IDENT_ERROR_ON_NO_NAME); @@ -1179,11 +1327,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix) for (i = 0; i < use_strategies_nr; i++) { int ret; if (i) { - printf("Rewinding the tree to pristine...\n"); + printf(_("Rewinding the tree to pristine...\n")); restore_state(); } if (use_strategies_nr != 1) - printf("Trying merge strategy %s...\n", + printf(_("Trying merge strategy %s...\n"), use_strategies[i]->name); /* * Remember which strategy left the state in the working @@ -1244,17 +1392,17 @@ int cmd_merge(int argc, const char **argv, const char *prefix) restore_state(); if (use_strategies_nr > 1) fprintf(stderr, - "No merge strategy handled the merge.\n"); + _("No merge strategy handled the merge.\n")); else - fprintf(stderr, "Merge with strategy %s failed.\n", + fprintf(stderr, _("Merge with strategy %s failed.\n"), use_strategies[0]->name); return 2; } else if (best_strategy == wt_strategy) ; /* We already have its result in the working tree. */ else { - printf("Rewinding the tree to pristine...\n"); + printf(_("Rewinding the tree to pristine...\n")); restore_state(); - printf("Using the %s to prepare resolving by hand.\n", + printf(_("Using the %s to prepare resolving by hand.\n"), best_strategy); try_merge_strategy(best_strategy, common, head_arg); } @@ -1270,36 +1418,29 @@ int cmd_merge(int argc, const char **argv, const char *prefix) sha1_to_hex(j->item->object.sha1)); fd = open(git_path("MERGE_HEAD"), O_WRONLY | O_CREAT, 0666); if (fd < 0) - die_errno("Could not open '%s' for writing", + die_errno(_("Could not open '%s' for writing"), git_path("MERGE_HEAD")); if (write_in_full(fd, buf.buf, buf.len) != buf.len) - die_errno("Could not write to '%s'", git_path("MERGE_HEAD")); + die_errno(_("Could not write to '%s'"), git_path("MERGE_HEAD")); close(fd); strbuf_addch(&merge_msg, '\n'); - fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666); - if (fd < 0) - die_errno("Could not open '%s' for writing", - git_path("MERGE_MSG")); - if (write_in_full(fd, merge_msg.buf, merge_msg.len) != - merge_msg.len) - die_errno("Could not write to '%s'", git_path("MERGE_MSG")); - close(fd); + write_merge_msg(); fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) - die_errno("Could not open '%s' for writing", + die_errno(_("Could not open '%s' for writing"), git_path("MERGE_MODE")); strbuf_reset(&buf); if (!allow_fast_forward) strbuf_addf(&buf, "no-ff"); if (write_in_full(fd, buf.buf, buf.len) != buf.len) - die_errno("Could not write to '%s'", git_path("MERGE_MODE")); + die_errno(_("Could not write to '%s'"), git_path("MERGE_MODE")); close(fd); } if (merge_was_ok) { - fprintf(stderr, "Automatic merge went well; " - "stopped before committing as requested\n"); + fprintf(stderr, _("Automatic merge went well; " + "stopped before committing as requested\n")); return 0; } else - return suggest_conflicts(); + return suggest_conflicts(option_renormalize); } |