Merge branch 'ja/do-not-ask-needless-questions' into maint
authorJunio C Hamano <gitster@pobox.com>
Sun, 4 Jun 2017 01:20:58 +0000 (10:20 +0900)
committerJunio C Hamano <gitster@pobox.com>
Sun, 4 Jun 2017 01:20:59 +0000 (10:20 +0900)
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

1  2 
Documentation/git-read-tree.txt
builtin/am.c
builtin/checkout.c
builtin/read-tree.c
index ed9d63ef4a35fa5ba70b1b7f1ffd393f517be030,6bb725bffb3be59b65d9513e720efc9ee7f866d5..02576d8c0ae6008fc22d7c7c706909efde5856da
@@@ -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 a95dd8b4e6c793d9e51658e2ccbe535cf5a5af45,38944f79022f9dbc0805a529b83b5c6b2307cbcd..dd60fad1e664d2ab066e561f332b3e2583234c44
@@@ -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);
@@@ -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);
        }
  
        /*
@@@ -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;
  
 -      /* Does it end with our own sign-off? */
 +      strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len);
 +
 +      /* 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);
        }
  
        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);
  
@@@ -1844,9 -1848,6 +1844,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);
                }
@@@ -1940,7 -1941,8 +1940,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);
        }
  
@@@ -2171,7 -2173,7 +2172,7 @@@ static void am_abort(struct am_state *s
                                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);
@@@ -2321,7 -2323,7 +2322,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 bfa5419f335dc1db98059869de24f152cffb9aa6,8d313ceb523ea8c4b1126f47631b48dfb4e3d747..85c04d252ce9b7c6d608b3c989783d1b8d9f85ec
  #include "submodule-config.h"
  #include "submodule.h"
  
 +static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
 +
  static const char * const checkout_usage[] = {
        N_("git checkout [<options>] <branch>"),
        N_("git checkout [<options>] [<branch>] -- <file>..."),
        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;
@@@ -908,10 -889,11 +908,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);
@@@ -1181,9 -1163,6 +1181,9 @@@ int cmd_checkout(int argc, const char *
                                N_("second guess 'git checkout <no-such-branch>'")),
                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(),
        };
                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"));
  
                 * 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 23e212ee8c5b2d26f03ac6be2b822a87ad06c233,8eae1e88e86895fd8578a6e0cb39b4e8eba9a131..38344256791a1232963f6153bea3bbfcf94481e7
  #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)
  {
@@@ -99,23 -96,6 +99,23 @@@ 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)
                         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()
        };
  
  
        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?");
                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;