From: Junio C Hamano Date: Wed, 10 Aug 2016 19:33:20 +0000 (-0700) Subject: Merge branch 'js/am-3-merge-recursive-direct' X-Git-Tag: v2.10.0-rc0~21 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/1a5f1a3f256a53014e5b832e1281d952ec5f9ef7?hp=-c Merge branch 'js/am-3-merge-recursive-direct' "git am -3" calls "git merge-recursive" when it needs to fall back to a three-way merge; this call has been turned into an internal subroutine call instead of spawning a separate subprocess. * js/am-3-merge-recursive-direct: merge-recursive: flush output buffer even when erroring out merge_trees(): ensure that the callers release output buffer merge-recursive: offer an option to retain the output in 'obuf' merge-recursive: write the commit title in one go merge-recursive: flush output buffer before printing error messages am -3: use merge_recursive() directly again merge-recursive: switch to returning errors instead of dying merge-recursive: handle return values indicating errors merge-recursive: allow write_tree_from_memory() to error out merge-recursive: avoid returning a wholesale struct merge_recursive: abort properly upon errors prepare the builtins for a libified merge_recursive() merge-recursive: clarify code in was_tracked() die(_("BUG")): avoid translating bug messages die("bug"): report bugs consistently t5520: verify that `pull --rebase` shows the helpful advice when failing --- 1a5f1a3f256a53014e5b832e1281d952ec5f9ef7 diff --combined builtin/am.c index 8aa9b5b936,cfb79ea906..739b34dcf2 --- a/builtin/am.c +++ b/builtin/am.c @@@ -1578,48 -1578,19 +1578,19 @@@ static int build_fake_ancestor(const st return 0; } - /** - * Do the three-way merge using fake ancestor, their tree constructed - * from the fake ancestor and the postimage of the patch, and our - * state. - */ - static int run_fallback_merge_recursive(const struct am_state *state, - unsigned char *orig_tree, - unsigned char *our_tree, - unsigned char *their_tree) - { - struct child_process cp = CHILD_PROCESS_INIT; - int status; - - cp.git_cmd = 1; - - argv_array_pushf(&cp.env_array, "GITHEAD_%s=%.*s", - sha1_to_hex(their_tree), linelen(state->msg), state->msg); - if (state->quiet) - argv_array_push(&cp.env_array, "GIT_MERGE_VERBOSITY=0"); - - argv_array_push(&cp.args, "merge-recursive"); - argv_array_push(&cp.args, sha1_to_hex(orig_tree)); - argv_array_push(&cp.args, "--"); - argv_array_push(&cp.args, sha1_to_hex(our_tree)); - argv_array_push(&cp.args, sha1_to_hex(their_tree)); - - status = run_command(&cp) ? (-1) : 0; - discard_cache(); - read_cache(); - return status; - } - /** * Attempt a threeway merge, using index_path as the temporary index. */ static int fall_back_threeway(const struct am_state *state, const char *index_path) { - unsigned char orig_tree[GIT_SHA1_RAWSZ], their_tree[GIT_SHA1_RAWSZ], - our_tree[GIT_SHA1_RAWSZ]; + struct object_id orig_tree, their_tree, our_tree; + const struct object_id *bases[1] = { &orig_tree }; + struct merge_options o; + struct commit *result; + char *their_tree_name; - if (get_sha1("HEAD", our_tree) < 0) - hashcpy(our_tree, EMPTY_TREE_SHA1_BIN); + if (get_oid("HEAD", &our_tree) < 0) + hashcpy(our_tree.hash, EMPTY_TREE_SHA1_BIN); if (build_fake_ancestor(state, index_path)) return error("could not build fake ancestor"); @@@ -1627,7 -1598,7 +1598,7 @@@ discard_cache(); read_cache_from(index_path); - if (write_index_as_tree(orig_tree, &the_index, index_path, 0, NULL)) + if (write_index_as_tree(orig_tree.hash, &the_index, index_path, 0, NULL)) return error(_("Repository lacks necessary blobs to fall back on 3-way merge.")); say(state, stdout, _("Using index info to reconstruct a base tree...")); @@@ -1643,7 -1614,7 +1614,7 @@@ init_revisions(&rev_info, NULL); rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS; diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix); - add_pending_sha1(&rev_info, "HEAD", our_tree, 0); + add_pending_sha1(&rev_info, "HEAD", our_tree.hash, 0); diff_setup_done(&rev_info.diffopt); run_diff_index(&rev_info, 1); } @@@ -1652,7 -1623,7 +1623,7 @@@ return error(_("Did you hand edit your patch?\n" "It does not apply to blobs recorded in its index.")); - if (write_index_as_tree(their_tree, &the_index, index_path, 0, NULL)) + if (write_index_as_tree(their_tree.hash, &the_index, index_path, 0, NULL)) return error("could not write tree"); say(state, stdout, _("Falling back to patching base and 3-way merge...")); @@@ -1668,11 -1639,22 +1639,22 @@@ * changes. */ - if (run_fallback_merge_recursive(state, orig_tree, our_tree, their_tree)) { + init_merge_options(&o); + + o.branch1 = "HEAD"; + their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg); + o.branch2 = their_tree_name; + + if (state->quiet) + o.verbosity = 0; + + if (merge_recursive_generic(&o, &our_tree, &their_tree, 1, bases, &result)) { rerere(state->allow_rerere_autoupdate); + free(their_tree_name); return error(_("Failed to merge in the changes.")); } + free(their_tree_name); return 0; } @@@ -1840,8 -1822,6 +1822,8 @@@ static void am_run(struct am_state *sta const char *mail = am_path(state, msgnum(state)); int apply_status; + reset_ident_date(); + if (!file_exists(mail)) goto next; diff --combined grep.c index 58d599e647,22cbb73f26..d7d00b87cb --- a/grep.c +++ b/grep.c @@@ -163,7 -163,17 +163,7 @@@ void grep_init(struct grep_opt *opt, co color_set(opt->color_sep, def->color_sep); } -void grep_commit_pattern_type(enum grep_pattern_type pattern_type, struct grep_opt *opt) -{ - if (pattern_type != GREP_PATTERN_TYPE_UNSPECIFIED) - grep_set_pattern_type_option(pattern_type, opt); - else if (opt->pattern_type_option != GREP_PATTERN_TYPE_UNSPECIFIED) - grep_set_pattern_type_option(opt->pattern_type_option, opt); - else if (opt->extended_regexp_option) - grep_set_pattern_type_option(GREP_PATTERN_TYPE_ERE, opt); -} - -void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt) +static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt) { switch (pattern_type) { case GREP_PATTERN_TYPE_UNSPECIFIED: @@@ -195,16 -205,6 +195,16 @@@ } } +void grep_commit_pattern_type(enum grep_pattern_type pattern_type, struct grep_opt *opt) +{ + if (pattern_type != GREP_PATTERN_TYPE_UNSPECIFIED) + grep_set_pattern_type_option(pattern_type, opt); + else if (opt->pattern_type_option != GREP_PATTERN_TYPE_UNSPECIFIED) + grep_set_pattern_type_option(opt->pattern_type_option, opt); + else if (opt->extended_regexp_option) + grep_set_pattern_type_option(GREP_PATTERN_TYPE_ERE, opt); +} + static struct grep_pat *create_grep_pat(const char *pat, size_t patlen, const char *origin, int no, enum grep_pat_token t, @@@ -693,10 -693,10 +693,10 @@@ static struct grep_expr *prep_header_pa for (p = opt->header_list; p; p = p->next) { if (p->token != GREP_PATTERN_HEAD) - die("bug: a non-header pattern in grep header list."); + die("BUG: a non-header pattern in grep header list."); if (p->field < GREP_HEADER_FIELD_MIN || GREP_HEADER_FIELD_MAX <= p->field) - die("bug: unknown header field %d", p->field); + die("BUG: unknown header field %d", p->field); compile_regexp(p, opt); } @@@ -709,7 -709,7 +709,7 @@@ h = compile_pattern_atom(&pp); if (!h || pp != p->next) - die("bug: malformed header expr"); + die("BUG: malformed header expr"); if (!header_group[p->field]) { header_group[p->field] = h; continue; @@@ -1514,7 -1514,7 +1514,7 @@@ static int grep_source_1(struct grep_op case GREP_BINARY_TEXT: break; default: - die("bug: unknown binary handling mode"); + die("BUG: unknown binary handling mode"); } } diff --combined sequencer.c index 7b1eb14645,ec50519df9..2e9c7d0f03 --- a/sequencer.c +++ b/sequencer.c @@@ -112,7 -112,7 +112,7 @@@ static void remove_sequencer_state(void { struct strbuf seq_dir = STRBUF_INIT; - strbuf_addf(&seq_dir, "%s", git_path(SEQ_DIR)); + strbuf_addstr(&seq_dir, git_path(SEQ_DIR)); remove_dir_recursively(&seq_dir, 0); strbuf_release(&seq_dir); } @@@ -293,6 -293,9 +293,9 @@@ static int do_recursive_merge(struct co clean = merge_trees(&o, head_tree, next_tree, base_tree, &result); + strbuf_release(&o.obuf); + if (clean < 0) + return clean; if (active_cache_changed && write_locked_index(&the_index, &index_lock, COMMIT_LOCK)) @@@ -559,6 -562,8 +562,8 @@@ static int do_pick_commit(struct commi if (!opts->strategy || !strcmp(opts->strategy, "recursive") || opts->action == REPLAY_REVERT) { res = do_recursive_merge(base, next, base_label, next_label, head, &msgbuf, opts); + if (res < 0) + return res; write_message(&msgbuf, git_path_merge_msg()); } else { struct commit_list *common = NULL; diff --combined sha1_file.c index 3066b5f71c,5085fe03f1..02940f1920 --- a/sha1_file.c +++ b/sha1_file.c @@@ -23,7 -23,6 +23,7 @@@ #include "bulk-checkin.h" #include "streaming.h" #include "dir.h" +#include "mru.h" #ifndef O_NOATIME #if defined(__linux__) && (defined(__i386__) || defined(__PPC__)) @@@ -60,6 -59,14 +60,6 @@@ static struct cached_object empty_tree 0 }; -/* - * A pointer to the last packed_git in which an object was found. - * When an object is sought, we look in this packfile first, because - * objects that are looked up at similar times are often in the same - * packfile as one another. - */ -static struct packed_git *last_found_pack; - static struct cached_object *find_cached_object(const unsigned char *sha1) { int i; @@@ -515,9 -522,6 +515,9 @@@ static size_t peak_pack_mapped static size_t pack_mapped; struct packed_git *packed_git; +static struct mru packed_git_mru_storage; +struct mru *packed_git_mru = &packed_git_mru_storage; + void pack_report(void) { fprintf(stderr, @@@ -791,7 -795,7 +791,7 @@@ void close_all_packs(void for (p = packed_git; p; p = p->next) if (p->do_not_close) - die("BUG! Want to close pack marked 'do-not-close'"); + die("BUG: want to close pack marked 'do-not-close'"); else close_pack(p); } @@@ -887,6 -891,36 +887,6 @@@ void close_pack_index(struct packed_gi } } -/* - * This is used by git-repack in case a newly created pack happens to - * contain the same set of objects as an existing one. In that case - * the resulting file might be different even if its name would be the - * same. It is best to close any reference to the old pack before it is - * replaced on disk. Of course no index pointers or windows for given pack - * must subsist at this point. If ever objects from this pack are requested - * again, the new version of the pack will be reinitialized through - * reprepare_packed_git(). - */ -void free_pack_by_name(const char *pack_name) -{ - struct packed_git *p, **pp = &packed_git; - - while (*pp) { - p = *pp; - if (strcmp(pack_name, p->pack_name) == 0) { - clear_delta_base_cache(); - close_pack(p); - free(p->bad_object_sha1); - *pp = p->next; - if (last_found_pack == p) - last_found_pack = NULL; - free(p); - return; - } - pp = &p->next; - } -} - static unsigned int get_max_fd_limit(void) { #ifdef RLIMIT_NOFILE @@@ -1351,15 -1385,6 +1351,15 @@@ static void rearrange_packed_git(void free(ary); } +static void prepare_packed_git_mru(void) +{ + struct packed_git *p; + + mru_clear(packed_git_mru); + for (p = packed_git; p; p = p->next) + mru_append(packed_git_mru, p); +} + static int prepare_packed_git_run_once = 0; void prepare_packed_git(void) { @@@ -1375,7 -1400,6 +1375,7 @@@ alt->name[-1] = '/'; } rearrange_packed_git(); + prepare_packed_git_mru(); prepare_packed_git_run_once = 1; } @@@ -2257,7 -2281,7 +2257,7 @@@ void *unpack_entry(struct packed_git *p if (do_check_packed_object_crc && p->index_version > 1) { struct revindex_entry *revidx = find_pack_revindex(p, obj_offset); - unsigned long len = revidx[1].offset - obj_offset; + off_t len = revidx[1].offset - obj_offset; if (check_pack_crc(p, &w_curs, obj_offset, len, revidx->nr)) { const unsigned char *sha1 = nth_packed_object_sha1(p, revidx->nr); @@@ -2306,7 -2330,7 +2306,7 @@@ case OBJ_OFS_DELTA: case OBJ_REF_DELTA: if (data) - die("BUG in unpack_entry: left loop at a valid delta"); + die("BUG: unpack_entry: left loop at a valid delta"); break; case OBJ_COMMIT: case OBJ_TREE: @@@ -2580,15 -2604,21 +2580,15 @@@ static int fill_pack_entry(const unsign */ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e) { - struct packed_git *p; + struct mru_entry *p; prepare_packed_git(); if (!packed_git) return 0; - if (last_found_pack && fill_pack_entry(sha1, e, last_found_pack)) - return 1; - - for (p = packed_git; p; p = p->next) { - if (p == last_found_pack) - continue; /* we already checked this one */ - - if (fill_pack_entry(sha1, e, p)) { - last_found_pack = p; + for (p = packed_git_mru->head; p; p = p->next) { + if (fill_pack_entry(sha1, e, p->item)) { + mru_mark(packed_git_mru, p); return 1; } } diff --combined transport.c index 4ba48b0596,04d945425a..c5772a14ee --- a/transport.c +++ b/transport.c @@@ -513,7 -513,6 +513,7 @@@ static int git_transport_push(struct tr args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN); args.porcelain = !!(flags & TRANSPORT_PUSH_PORCELAIN); args.atomic = !!(flags & TRANSPORT_PUSH_ATOMIC); + args.push_options = transport->push_options; args.url = transport->url; if (flags & TRANSPORT_PUSH_CERT_ALWAYS) @@@ -567,7 -566,7 +567,7 @@@ void transport_take_over(struct transpo struct git_transport_data *data; if (!transport->smart_options) - die("Bug detected: Taking over transport requires non-NULL " + die("BUG: taking over transport requires non-NULL " "smart_options field."); data = xcalloc(1, sizeof(*data)); diff --combined wt-status.c index 3175ec6ddb,f8ae0c2dd0..6225a2d89f --- a/wt-status.c +++ b/wt-status.c @@@ -263,7 -263,7 +263,7 @@@ static const char *wt_status_unmerged_s case 7: return _("both modified:"); default: - die("bug: unhandled unmerged status %x", stagemask); + die("BUG: unhandled unmerged status %x", stagemask); } } @@@ -388,7 -388,7 +388,7 @@@ static void wt_status_print_change_data status_printf(s, color(WT_STATUS_HEADER, s), "\t"); what = wt_status_diff_status_string(status); if (!what) - die("bug: unhandled diff status %c", status); + die("BUG: unhandled diff status %c", status); len = label_width - utf8_strwidth(what); assert(len >= 0); if (status == DIFF_STATUS_COPIED || status == DIFF_STATUS_RENAMED) @@@ -948,12 -948,9 +948,12 @@@ static void show_merge_in_progress(stru { if (has_unmerged(s)) { status_printf_ln(s, color, _("You have unmerged paths.")); - if (s->hints) + if (s->hints) { status_printf_ln(s, color, - _(" (fix conflicts and run \"git commit\")")); + _(" (fix conflicts and run \"git commit\")")); + status_printf_ln(s, color, + _(" (use \"git merge --abort\" to abort the merge)")); + } } else { s-> commitable = 1; status_printf_ln(s, color,