From: Junio C Hamano Date: Mon, 29 May 2017 03:34:48 +0000 (+0900) Subject: Merge branch 'ja/do-not-ask-needless-questions' X-Git-Tag: v2.14.0-rc0~158 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/e6381080a7dd44e14fba81b5e3714661343d8e62?ds=inline;hp=-c Merge branch 'ja/do-not-ask-needless-questions' Git sometimes gives an advice in a rhetorical question that does not require an answer, which can confuse new users and non native speakers. Attempt to rephrase them. * ja/do-not-ask-needless-questions: git-filter-branch: be more direct in an error message read-tree -m: make error message for merging 0 trees less smart aleck usability: don't ask questions if no reply is required --- e6381080a7dd44e14fba81b5e3714661343d8e62 diff --combined Documentation/git-read-tree.txt index ed9d63ef4a,6bb725bffb..02576d8c0a --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@@ -115,12 -115,6 +115,12 @@@ OPTION directories the index file and index output file are located in. +--[no-]recurse-submodules:: + Using --recurse-submodules will update the content of all initialized + submodules according to the commit recorded in the superproject by + calling read-tree recursively, also setting the submodules HEAD to be + detached at that commit. + --no-sparse-checkout:: Disable sparse checkout support even if `core.sparseCheckout` is true. @@@ -137,7 -131,7 +137,7 @@@ Mergin ------- If `-m` is specified, 'git read-tree' can perform 3 kinds of merge, a single tree merge if only 1 tree is given, a - fast-forward merge with 2 trees, or a 3-way merge if 3 trees are + fast-forward merge with 2 trees, or a 3-way merge if 3 or more trees are provided. diff --combined builtin/am.c index 8b218f9978,38944f7902..0f63dcab16 --- a/builtin/am.c +++ b/builtin/am.c @@@ -134,15 -134,17 +134,15 @@@ struct am_state }; /** - * Initializes am_state with the default values. The state directory is set to - * dir. + * Initializes am_state with the default values. */ -static void am_state_init(struct am_state *state, const char *dir) +static void am_state_init(struct am_state *state) { int gpgsign; memset(state, 0, sizeof(*state)); - assert(dir); - state->dir = xstrdup(dir); + state->dir = git_pathdup("rebase-apply"); state->prec = 4; @@@ -760,18 -762,14 +760,18 @@@ static int split_mail_conv(mail_conv_f mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1); out = fopen(mail, "w"); - if (!out) + if (!out) { + if (in != stdin) + fclose(in); return error_errno(_("could not open '%s' for writing"), mail); + } ret = fn(out, in, keep_cr); fclose(out); - fclose(in); + if (in != stdin) + fclose(in); if (ret) return error(_("could not parse patch '%s'"), *paths); @@@ -879,12 -877,12 +879,12 @@@ static int hg_patch_to_mail(FILE *out, if (skip_prefix(sb.buf, "# User ", &str)) fprintf(out, "From: %s\n", str); else if (skip_prefix(sb.buf, "# Date ", &str)) { - unsigned long timestamp; + timestamp_t timestamp; long tz, tz2; char *end; errno = 0; - timestamp = strtoul(str, &end, 10); + timestamp = parse_timestamp(str, &end, 10); if (errno) return error(_("invalid timestamp")); @@@ -1051,7 -1049,7 +1051,7 @@@ static void am_setup(struct am_state *s } else { write_state_text(state, "abort-safety", ""); if (!state->rebasing) - delete_ref("ORIG_HEAD", NULL, 0); + delete_ref(NULL, "ORIG_HEAD", NULL, 0); } /* @@@ -1145,7 -1143,7 +1145,7 @@@ static int index_has_changes(struct str DIFF_OPT_SET(&opt, EXIT_WITH_STATUS); if (!sb) DIFF_OPT_SET(&opt, QUICK); - do_diff_cache(head.hash, &opt); + do_diff_cache(&head, &opt); diffcore_std(&opt); for (i = 0; sb && i < diff_queued_diff.nr; i++) { if (i) @@@ -1183,39 -1181,42 +1183,39 @@@ static void NORETURN die_user_resolve(c exit(128); } -static void am_signoff(struct strbuf *sb) +/** + * Appends signoff to the "msg" field of the am_state. + */ +static void am_append_signoff(struct am_state *state) { char *cp; struct strbuf mine = STRBUF_INIT; + struct strbuf sb = STRBUF_INIT; + + strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len); - /* Does it end with our own sign-off? */ + /* our sign-off */ strbuf_addf(&mine, "\n%s%s\n", sign_off_header, fmt_name(getenv("GIT_COMMITTER_NAME"), getenv("GIT_COMMITTER_EMAIL"))); - if (mine.len < sb->len && - !strcmp(mine.buf, sb->buf + sb->len - mine.len)) + + /* Does sb end with it already? */ + if (mine.len < sb.len && + !strcmp(mine.buf, sb.buf + sb.len - mine.len)) goto exit; /* no need to duplicate */ /* Does it have any Signed-off-by: in the text */ - for (cp = sb->buf; + for (cp = sb.buf; cp && *cp && (cp = strstr(cp, sign_off_header)) != NULL; cp = strchr(cp, '\n')) { - if (sb->buf == cp || cp[-1] == '\n') + if (sb.buf == cp || cp[-1] == '\n') break; } - strbuf_addstr(sb, mine.buf + !!cp); + strbuf_addstr(&sb, mine.buf + !!cp); exit: strbuf_release(&mine); -} - -/** - * Appends signoff to the "msg" field of the am_state. - */ -static void am_append_signoff(struct am_state *state) -{ - struct strbuf sb = STRBUF_INIT; - - strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len); - am_signoff(&sb); state->msg = strbuf_detach(&sb, &state->msg_len); } @@@ -1312,7 -1313,7 +1312,7 @@@ static int parse_mail(struct am_state * } if (is_empty_file(am_path(state, "patch"))) { - printf_ln(_("Patch is empty. Was it split wrong?")); + printf_ln(_("Patch is empty.")); die_user_resolve(state); } @@@ -1320,6 -1321,9 +1320,6 @@@ strbuf_addbuf(&msg, &mi.log_message); strbuf_stripspace(&msg, 0); - if (state->signoff) - am_signoff(&msg); - assert(!state->author_name); state->author_name = strbuf_detach(&author_name, NULL); @@@ -1351,16 -1355,19 +1351,16 @@@ static int get_mail_commit_oid(struct o struct strbuf sb = STRBUF_INIT; FILE *fp = xfopen(mail, "r"); const char *x; + int ret = 0; - if (strbuf_getline_lf(&sb, fp)) - return -1; - - if (!skip_prefix(sb.buf, "From ", &x)) - return -1; - - if (get_oid_hex(x, commit_id) < 0) - return -1; + if (strbuf_getline_lf(&sb, fp) || + !skip_prefix(sb.buf, "From ", &x) || + get_oid_hex(x, commit_id) < 0) + ret = -1; strbuf_release(&sb); fclose(fp); - return 0; + return ret; } /** @@@ -1369,33 -1376,40 +1369,33 @@@ */ static void get_commit_info(struct am_state *state, struct commit *commit) { - const char *buffer, *ident_line, *author_date, *msg; + const char *buffer, *ident_line, *msg; size_t ident_len; - struct ident_split ident_split; - struct strbuf sb = STRBUF_INIT; + struct ident_split id; buffer = logmsg_reencode(commit, NULL, get_commit_output_encoding()); ident_line = find_commit_header(buffer, "author", &ident_len); - if (split_ident_line(&ident_split, ident_line, ident_len) < 0) { - strbuf_add(&sb, ident_line, ident_len); - die(_("invalid ident line: %s"), sb.buf); - } + if (split_ident_line(&id, ident_line, ident_len) < 0) + die(_("invalid ident line: %.*s"), (int)ident_len, ident_line); assert(!state->author_name); - if (ident_split.name_begin) { - strbuf_add(&sb, ident_split.name_begin, - ident_split.name_end - ident_split.name_begin); - state->author_name = strbuf_detach(&sb, NULL); - } else + if (id.name_begin) + state->author_name = + xmemdupz(id.name_begin, id.name_end - id.name_begin); + else state->author_name = xstrdup(""); assert(!state->author_email); - if (ident_split.mail_begin) { - strbuf_add(&sb, ident_split.mail_begin, - ident_split.mail_end - ident_split.mail_begin); - state->author_email = strbuf_detach(&sb, NULL); - } else + if (id.mail_begin) + state->author_email = + xmemdupz(id.mail_begin, id.mail_end - id.mail_begin); + else state->author_email = xstrdup(""); - author_date = show_ident_date(&ident_split, DATE_MODE(NORMAL)); - strbuf_addstr(&sb, author_date); assert(!state->author_date); - state->author_date = strbuf_detach(&sb, NULL); + state->author_date = xstrdup(show_ident_date(&id, DATE_MODE(NORMAL))); assert(!state->msg); msg = strstr(buffer, "\n\n"); @@@ -1403,7 -1417,6 +1403,7 @@@ die(_("unable to parse commit %s"), oid_to_hex(&commit->object.oid)); state->msg = xstrdup(msg + 2); state->msg_len = strlen(state->msg); + unuse_commit_buffer(commit, buffer); } /** @@@ -1444,9 -1457,9 +1444,9 @@@ static void write_index_patch(const str FILE *fp; if (!get_sha1_tree("HEAD", head.hash)) - tree = lookup_tree(head.hash); + tree = lookup_tree(&head); else - tree = lookup_tree(EMPTY_TREE_SHA1_BIN); + tree = lookup_tree(&empty_tree_oid); fp = xfopen(am_path(state, "patch"), "w"); init_revisions(&rev_info, NULL); @@@ -1479,7 -1492,7 +1479,7 @@@ static int parse_mail_rebase(struct am_ if (get_mail_commit_oid(&commit_oid, mail) < 0) die(_("could not parse %s"), mail); - commit = lookup_commit_or_die(commit_oid.hash, mail); + commit = lookup_commit_or_die(&commit_oid, mail); get_commit_info(state, commit); @@@ -1609,7 -1622,7 +1609,7 @@@ static int fall_back_threeway(const str 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.hash, 0); + add_pending_oid(&rev_info, "HEAD", &our_tree, 0); diff_setup_done(&rev_info.diffopt); run_diff_index(&rev_info, 1); } @@@ -1674,7 -1687,7 +1674,7 @@@ static void do_commit(const struct am_s if (!get_sha1_commit("HEAD", parent.hash)) { old_oid = &parent; - commit_list_insert(lookup_commit(parent.hash), &parents); + commit_list_insert(lookup_commit(&parent), &parents); } else { old_oid = NULL; say(state, stderr, _("applying to an empty history")); @@@ -1835,9 -1848,6 +1835,9 @@@ static void am_run(struct am_state *sta if (skip) goto next; /* mail should be skipped */ + if (state->signoff) + am_append_signoff(state); + write_author_script(state); write_commit_msg(state); } @@@ -1931,7 -1941,8 +1931,8 @@@ static void am_resolve(struct am_state if (unmerged_cache()) { printf_ln(_("You still have unmerged paths in your index.\n" - "Did you forget to use 'git add'?")); + "You should 'git add' each file with resolved conflicts to mark them as such.\n" + "You might run `git rm` on a file to accept \"deleted by them\" for it.")); die_user_resolve(state); } @@@ -2036,11 -2047,11 +2037,11 @@@ static int clean_index(const struct obj struct tree *head_tree, *remote_tree, *index_tree; struct object_id index; - head_tree = parse_tree_indirect(head->hash); + head_tree = parse_tree_indirect(head); if (!head_tree) return error(_("Could not parse object '%s'."), oid_to_hex(head)); - remote_tree = parse_tree_indirect(remote->hash); + remote_tree = parse_tree_indirect(remote); if (!remote_tree) return error(_("Could not parse object '%s'."), oid_to_hex(remote)); @@@ -2052,7 -2063,7 +2053,7 @@@ if (write_cache_as_tree(index.hash, 0, NULL)) return -1; - index_tree = parse_tree_indirect(index.hash); + index_tree = parse_tree_indirect(&index); if (!index_tree) return error(_("Could not parse object '%s'."), oid_to_hex(&index)); @@@ -2147,7 -2158,7 +2148,7 @@@ static void am_abort(struct am_state *s am_rerere_clear(); curr_branch = resolve_refdup("HEAD", 0, curr_head.hash, NULL); - has_curr_head = !is_null_oid(&curr_head); + has_curr_head = curr_branch && !is_null_oid(&curr_head); if (!has_curr_head) hashcpy(curr_head.hash, EMPTY_TREE_SHA1_BIN); @@@ -2162,7 -2173,7 +2163,7 @@@ has_curr_head ? &curr_head : NULL, 0, UPDATE_REFS_DIE_ON_ERR); else if (curr_branch) - delete_ref(curr_branch, NULL, REF_NODEREF); + delete_ref(NULL, curr_branch, NULL, REF_NODEREF); free(curr_branch); am_destroy(state); @@@ -2312,7 -2323,7 +2313,7 @@@ int cmd_am(int argc, const char **argv git_config(git_am_config, NULL); - am_state_init(&state, git_path("rebase-apply")); + am_state_init(&state); in_progress = am_in_progress(&state); if (in_progress) diff --combined builtin/checkout.c index b6249a3a39,8d313ceb52..a6b2af39d3 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@@ -21,31 -21,12 +21,31 @@@ #include "submodule-config.h" #include "submodule.h" +static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; + static const char * const checkout_usage[] = { N_("git checkout [] "), N_("git checkout [] [] -- ..."), NULL, }; +static int option_parse_recurse_submodules(const struct option *opt, + const char *arg, int unset) +{ + if (unset) { + recurse_submodules = RECURSE_SUBMODULES_OFF; + return 0; + } + if (arg) + recurse_submodules = + parse_update_recurse_submodules_arg(opt->long_name, + arg); + else + recurse_submodules = RECURSE_SUBMODULES_ON; + + return 0; +} + struct checkout_opts { int patch_mode; int quiet; @@@ -235,24 -216,22 +235,24 @@@ static int checkout_merged(int pos, con /* * NEEDSWORK: * There is absolutely no reason to write this as a blob object - * and create a phony cache entry just to leak. This hack is - * primarily to get to the write_entry() machinery that massages - * the contents to work-tree format and writes out which only - * allows it for a cache entry. The code in write_entry() needs - * to be refactored to allow us to feed a - * instead of a cache entry. Such a refactoring would help - * merge_recursive as well (it also writes the merge result to the - * object database even when it may contain conflicts). + * and create a phony cache entry. This hack is primarily to get + * to the write_entry() machinery that massages the contents to + * work-tree format and writes out which only allows it for a + * cache entry. The code in write_entry() needs to be refactored + * to allow us to feed a instead of a cache + * entry. Such a refactoring would help merge_recursive as well + * (it also writes the merge result to the object database even + * when it may contain conflicts). */ if (write_sha1_file(result_buf.ptr, result_buf.size, blob_type, oid.hash)) die(_("Unable to add merge result for '%s'"), path); + free(result_buf.ptr); ce = make_cache_entry(mode, oid.hash, path, 2, 0); if (!ce) die(_("make_cache_entry failed for path '%s'"), path); status = checkout_entry(ce, state, NULL); + free(ce); return status; } @@@ -395,7 -374,7 +395,7 @@@ static int checkout_paths(const struct die(_("unable to write new index file")); read_ref_full("HEAD", 0, rev.hash, NULL); - head = lookup_commit_reference_gently(rev.hash, 1); + head = lookup_commit_reference_gently(&rev, 1); errs |= post_checkout_hook(head, head, 0); return errs; @@@ -529,10 -508,10 +529,10 @@@ static int merge_working_tree(const str setup_standard_excludes(topts.dir); } tree = parse_tree_indirect(old->commit ? - old->commit->object.oid.hash : - EMPTY_TREE_SHA1_BIN); + &old->commit->object.oid : + &empty_tree_oid); init_tree_desc(&trees[0], tree->buffer, tree->size); - tree = parse_tree_indirect(new->commit->object.oid.hash); + tree = parse_tree_indirect(&new->commit->object.oid); init_tree_desc(&trees[1], tree->buffer, tree->size); ret = unpack_trees(2, trees, &topts); @@@ -723,7 -702,7 +723,7 @@@ static int add_pending_uninteresting_re const struct object_id *oid, int flags, void *cb_data) { - add_pending_sha1(cb_data, refname, oid->hash, UNINTERESTING); + add_pending_oid(cb_data, refname, oid, UNINTERESTING); return 0; } @@@ -809,7 -788,7 +809,7 @@@ static void orphaned_commit_warning(str add_pending_object(&revs, object, oid_to_hex(&object->oid)); for_each_ref(add_pending_uninteresting_ref, &revs); - add_pending_sha1(&revs, "HEAD", new->object.oid.hash, UNINTERESTING); + add_pending_oid(&revs, "HEAD", &new->object.oid, UNINTERESTING); refs = revs.pending; revs.leak_pending = 1; @@@ -835,8 -814,7 +835,8 @@@ static int switch_branches(const struc int flag, writeout_error = 0; memset(&old, 0, sizeof(old)); old.path = path_to_free = resolve_refdup("HEAD", 0, rev.hash, &flag); - old.commit = lookup_commit_reference_gently(rev.hash, 1); + if (old.path) + old.commit = lookup_commit_reference_gently(&rev, 1); if (!(flag & REF_ISSYMREF)) old.path = NULL; @@@ -911,10 -889,11 +911,10 @@@ static int check_tracking_name(struct r static const char *unique_tracking_name(const char *name, struct object_id *oid) { struct tracking_name_data cb_data = { NULL, NULL, NULL, 1 }; - char src_ref[PATH_MAX]; - snprintf(src_ref, PATH_MAX, "refs/heads/%s", name); - cb_data.src_ref = src_ref; + cb_data.src_ref = xstrfmt("refs/heads/%s", name); cb_data.dst_oid = oid; for_each_remote(check_tracking_name, &cb_data); + free(cb_data.src_ref); if (cb_data.unique) return cb_data.dst_ref; free(cb_data.dst_ref); @@@ -1050,10 -1029,10 +1050,10 @@@ static int parse_branchname_arg(int arg else new->path = NULL; /* not an existing branch */ - new->commit = lookup_commit_reference_gently(rev->hash, 1); + new->commit = lookup_commit_reference_gently(rev, 1); if (!new->commit) { /* not a commit */ - *source_tree = parse_tree_indirect(rev->hash); + *source_tree = parse_tree_indirect(rev); } else { parse_commit_or_die(new->commit); *source_tree = new->commit->tree; @@@ -1184,9 -1163,6 +1184,9 @@@ int cmd_checkout(int argc, const char * N_("second guess 'git checkout '")), OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees, N_("do not check if another worktree is holding the given ref")), + { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, + "checkout", "control recursive updating of submodules", + PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")), OPT_END(), }; @@@ -1217,12 -1193,6 +1217,12 @@@ git_xmerge_config("merge.conflictstyle", conflict_style, NULL); } + if (recurse_submodules != RECURSE_SUBMODULES_OFF) { + git_config(submodule_config, NULL); + if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT) + set_config_update_recurse_submodules(recurse_submodules); + } + if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1) die(_("-b, -B and --orphan are mutually exclusive")); @@@ -1289,9 -1259,8 +1289,8 @@@ * new_branch && argc > 1 will be caught later. */ if (opts.new_branch && argc == 1) - die(_("Cannot update paths and switch to branch '%s' at the same time.\n" - "Did you intend to checkout '%s' which can not be resolved as commit?"), - opts.new_branch, argv[0]); + die(_("'%s' is not a commit and a branch '%s' cannot be created from it"), + argv[0], opts.new_branch); if (opts.force_detach) die(_("git checkout: --detach does not take a path argument '%s'"), diff --combined builtin/read-tree.c index daf8d7795d,8eae1e88e8..78d3193659 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@@ -15,21 -15,18 +15,21 @@@ #include "builtin.h" #include "parse-options.h" #include "resolve-undo.h" +#include "submodule.h" +#include "submodule-config.h" static int nr_trees; static int read_empty; static struct tree *trees[MAX_UNPACK_TREES]; +static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; -static int list_tree(unsigned char *sha1) +static int list_tree(struct object_id *oid) { struct tree *tree; if (nr_trees >= MAX_UNPACK_TREES) die("I cannot read more than %d trees", MAX_UNPACK_TREES); - tree = parse_tree_indirect(sha1); + tree = parse_tree_indirect(oid); if (!tree) return -1; trees[nr_trees++] = tree; @@@ -99,29 -96,12 +99,29 @@@ static int debug_merge(const struct cac return 0; } +static int option_parse_recurse_submodules(const struct option *opt, + const char *arg, int unset) +{ + if (unset) { + recurse_submodules = RECURSE_SUBMODULES_OFF; + return 0; + } + if (arg) + recurse_submodules = + parse_update_recurse_submodules_arg(opt->long_name, + arg); + else + recurse_submodules = RECURSE_SUBMODULES_ON; + + return 0; +} + static struct lock_file lock_file; int cmd_read_tree(int argc, const char **argv, const char *unused_prefix) { int i, stage = 0; - unsigned char sha1[20]; + struct object_id oid; struct tree_desc t[MAX_UNPACK_TREES]; struct unpack_trees_options opts; int prefix_set = 0; @@@ -157,9 -137,6 +157,9 @@@ N_("skip applying sparse checkout filter")), OPT_BOOL(0, "debug-unpack", &opts.debug_unpack, N_("debug unpack-trees")), + { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, + "checkout", "control recursive updating of submodules", + PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_END() }; @@@ -175,12 -152,6 +175,12 @@@ hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); + if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT) { + gitmodules_config(); + git_config(submodule_config, NULL); + set_config_update_recurse_submodules(RECURSE_SUBMODULES_ON); + } + prefix_set = opts.prefix ? 1 : 0; if (1 < opts.merge + opts.reset + prefix_set) die("Which one? -m, --reset, or --prefix?"); @@@ -204,13 -175,13 +204,13 @@@ for (i = 0; i < argc; i++) { const char *arg = argv[i]; - if (get_sha1(arg, sha1)) + if (get_oid(arg, &oid)) die("Not a valid object name %s", arg); - if (list_tree(sha1) < 0) + if (list_tree(&oid) < 0) die("failed to unpack tree object %s", arg); stage++; } - if (nr_trees == 0 && !read_empty) + if (!nr_trees && !read_empty && !opts.merge) warning("read-tree: emptying the index with no arguments is deprecated; use --empty"); else if (nr_trees > 0 && read_empty) die("passing trees as arguments contradicts --empty"); @@@ -226,9 -197,10 +226,10 @@@ setup_work_tree(); if (opts.merge) { - if (stage < 2) - die("just how do you expect me to merge %d trees?", stage-1); switch (stage - 1) { + case 0: + die("you must specify at least one tree to merge"); + break; case 1: opts.fn = opts.prefix ? bind_merge : oneway_merge; break;