Merge branch 'jg/status-config'
authorJunio C Hamano <gitster@pobox.com>
Thu, 11 Jul 2013 20:05:34 +0000 (13:05 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 11 Jul 2013 20:05:34 +0000 (13:05 -0700)
"git status" learned status.branch and status.short configuration
variables to use --branch and --short options by default (override
with --no-branch and --no-short options from the command line).

* jg/status-config:
status/commit: make sure --porcelain is not affected by user-facing config
commit: make it work with status.short
status: introduce status.branch to enable --branch by default
status: introduce status.short to enable --short by default

1  2 
Documentation/config.txt
builtin/commit.c
wt-status.c
diff --combined Documentation/config.txt
index 8d6859fa65febc0054bbf6434e63e8dc6692214a,ecdcd6dd99f8720375240d28b3c7b2a686b9e06d..81856dd5a2559149b9dcdf263ed5c3212a07d480
@@@ -199,9 -199,6 +199,9 @@@ advice.*:
        amWorkDir::
                Advice that shows the location of the patch file when
                linkgit:git-am[1] fails to apply it.
 +      rmHints::
 +              In case of failure in the output of linkgit:git-rm[1],
 +              show directions on how to proceed from the current state.
  --
  
  core.fileMode::
@@@ -922,21 -919,17 +922,21 @@@ color.ui:
        as `color.diff` and `color.grep` that control the use of color
        per command family. Its scope will expand as more commands learn
        configuration to set a default for the `--color` option.  Set it
 -      to `always` if you want all output not intended for machine
 -      consumption to use color, to `true` or `auto` if you want such
 -      output to use color when written to the terminal, or to `false` or
 -      `never` if you prefer Git commands not to use color unless enabled
 -      explicitly with some other configuration or the `--color` option.
 +      to `false` or `never` if you prefer Git commands not to use
 +      color unless enabled explicitly with some other configuration
 +      or the `--color` option. Set it to `always` if you want all
 +      output not intended for machine consumption to use color, to
 +      `true` or `auto` (this is the default since Git 1.8.4) if you
 +      want such output to use color when written to the terminal.
  
  column.ui::
        Specify whether supported commands should output in columns.
        This variable consists of a list of tokens separated by spaces
        or commas:
  +
 +These options control when the feature should be enabled
 +(defaults to 'never'):
 ++
  --
  `always`;;
        always show in columns
        never show in columns
  `auto`;;
        show in columns if the output is to the terminal
 +--
 ++
 +These options control layout (defaults to 'column').  Setting any
 +of these implies 'always' if none of 'always', 'never', or 'auto' are
 +specified.
 ++
 +--
  `column`;;
 -      fill columns before rows (default)
 +      fill columns before rows
  `row`;;
        fill rows before columns
  `plain`;;
        show in one column
 +--
 ++
 +Finally, these options can be combined with a layout option (defaults
 +to 'nodense'):
 ++
 +--
  `dense`;;
        make unequal size columns to utilize more space
  `nodense`;;
        make equal size columns
  --
 -+
 -This option defaults to 'never'.
  
  column.branch::
        Specify whether to output branch listing in `git branch` in columns.
@@@ -1844,59 -1826,39 +1844,59 @@@ pull.twohead:
        The default merge strategy to use when pulling a single branch.
  
  push.default::
 -      Defines the action `git push` should take if no refspec is given
 -      on the command line, no refspec is configured in the remote, and
 -      no refspec is implied by any of the options given on the command
 -      line. Possible values are:
 +      Defines the action `git push` should take if no refspec is
 +      explicitly given.  Different values are well-suited for
 +      specific workflows; for instance, in a purely central workflow
 +      (i.e. the fetch source is equal to the push destination),
 +      `upstream` is probably what you want.  Possible values are:
  +
  --
 -* `nothing` - do not push anything.
 -* `matching` - push all branches having the same name in both ends.
 -  This is for those who prepare all the branches into a publishable
 -  shape and then push them out with a single command.  It is not
 -  appropriate for pushing into a repository shared by multiple users,
 -  since locally stalled branches will attempt a non-fast forward push
 -  if other users updated the branch.
 -  +
 -  This is currently the default, but Git 2.0 will change the default
 -  to `simple`.
 -* `upstream` - push the current branch to its upstream branch
 -  (`tracking` is a deprecated synonym for this).
 -  With this, `git push` will update the same remote ref as the one which
 -  is merged by `git pull`, making `push` and `pull` symmetrical.
 -  See "branch.<name>.merge" for how to configure the upstream branch.
 -* `simple` - like `upstream`, but refuses to push if the upstream
 -  branch's name is different from the local one. This is the safest
 -  option and is well-suited for beginners. It will become the default
 -  in Git 2.0.
 -* `current` - push the current branch to a branch of the same name.
 ---
 +
 +* `nothing` - do not push anything (error out) unless a refspec is
 +  explicitly given. This is primarily meant for people who want to
 +  avoid mistakes by always being explicit.
 +
 +* `current` - push the current branch to update a branch with the same
 +  name on the receiving end.  Works in both central and non-central
 +  workflows.
 +
 +* `upstream` - push the current branch back to the branch whose
 +  changes are usually integrated into the current branch (which is
 +  called `@{upstream}`).  This mode only makes sense if you are
 +  pushing to the same repository you would normally pull from
 +  (i.e. central workflow).
 +
 +* `simple` - in centralized workflow, work like `upstream` with an
 +  added safety to refuse to push if the upstream branch's name is
 +  different from the local one.
 ++
 +When pushing to a remote that is different from the remote you normally
 +pull from, work as `current`.  This is the safest option and is suited
 +for beginners.
 ++
 +This mode will become the default in Git 2.0.
 +
 +* `matching` - push all branches having the same name on both ends.
 +  This makes the repository you are pushing to remember the set of
 +  branches that will be pushed out (e.g. if you always push 'maint'
 +  and 'master' there and no other branches, the repository you push
 +  to will have these two branches, and your local 'maint' and
 +  'master' will be pushed there).
  +
 -The `simple`, `current` and `upstream` modes are for those who want to
 -push out a single branch after finishing work, even when the other
 -branches are not yet ready to be pushed out. If you are working with
 -other people to push into the same shared repository, you would want
 -to use one of these.
 +To use this mode effectively, you have to make sure _all_ the
 +branches you would push out are ready to be pushed out before
 +running 'git push', as the whole point of this mode is to allow you
 +to push all of the branches in one go.  If you usually finish work
 +on only one branch and push out the result, while other branches are
 +unfinished, this mode is not for you.  Also this mode is not
 +suitable for pushing into a shared central repository, as other
 +people may add new branches there, or update the tip of existing
 +branches outside your control.
 ++
 +This is currently the default, but Git 2.0 will change the default
 +to `simple`.
 +
 +--
  
  rebase.stat::
        Whether to show a diffstat of what changed upstream since the last
  rebase.autosquash::
        If set to true enable '--autosquash' option by default.
  
 +rebase.autostash::
 +      When set to true, automatically create a temporary stash
 +      before the operation begins, and apply it after the operation
 +      ends.  This means that you can run rebase on a dirty worktree.
 +      However, use with care: the final stash application after a
 +      successful rebase might result in non-trivial conflicts.
 +      Defaults to false.
 +
  receive.autogc::
        By default, git-receive-pack will run "git-gc --auto" after
        receiving data from git-push and updating refs.  You can stop
@@@ -2112,6 -2066,14 +2112,14 @@@ status.relativePaths:
        relative to the repository root (this was the default for Git
        prior to v1.5.4).
  
+ status.short::
+       Set to true to enable --short by default in linkgit:git-status[1].
+       The option --no-short takes precedence over this variable.
+ status.branch::
+       Set to true to enable --branch by default in linkgit:git-status[1].
+       The option --no-branch takes precedence over this variable.
  status.showUntrackedFiles::
        By default, linkgit:git-status[1] and linkgit:git-commit[1] show
        files which are not currently tracked by Git. Directories which
diff --combined builtin/commit.c
index 6b693c16d8842b70b0e1c7bd7df5095947ed0a64,6f8cb04c0835f026708d44e047e5533fd9c524dc..790e5ab5cfee7b0f5760aafed7bf6f3f5927871e
@@@ -29,7 -29,6 +29,7 @@@
  #include "gpg-interface.h"
  #include "column.h"
  #include "sequencer.h"
 +#include "notes-utils.h"
  
  static const char * const builtin_commit_usage[] = {
        N_("git commit [options] [--] <pathspec>..."),
@@@ -108,25 -107,25 +108,27 @@@ static const char *cleanup_arg
  
  static enum commit_whence whence;
  static int use_editor = 1, include_status = 1;
 -static int show_ignored_in_status;
 +static int show_ignored_in_status, have_option_m;
  static const char *only_include_assumed;
  static struct strbuf message = STRBUF_INIT;
  
- static enum {
+ static enum status_format {
        STATUS_FORMAT_NONE = 0,
        STATUS_FORMAT_LONG,
        STATUS_FORMAT_SHORT,
-       STATUS_FORMAT_PORCELAIN
- } status_format;
+       STATUS_FORMAT_PORCELAIN,
+       STATUS_FORMAT_UNSPECIFIED
+ } status_format = STATUS_FORMAT_UNSPECIFIED;
  
  static int opt_parse_m(const struct option *opt, const char *arg, int unset)
  {
        struct strbuf *buf = opt->value;
 -      if (unset)
 +      if (unset) {
 +              have_option_m = 0;
                strbuf_setlen(buf, 0);
 -      else {
 +      } else {
 +              have_option_m = 1;
                if (buf->len)
                        strbuf_addch(buf, '\n');
                strbuf_addstr(buf, arg);
@@@ -460,6 -459,9 +462,9 @@@ static int run_status(FILE *fp, const c
        case STATUS_FORMAT_PORCELAIN:
                wt_porcelain_print(s);
                break;
+       case STATUS_FORMAT_UNSPECIFIED:
+               die("BUG: finalize_deferred_config() should have been called");
+               break;
        case STATUS_FORMAT_NONE:
        case STATUS_FORMAT_LONG:
                wt_status_print(s);
@@@ -961,6 -963,42 +966,42 @@@ static const char *read_commit_message(
        return logmsg_reencode(commit, NULL, out_enc);
  }
  
+ /*
+  * Enumerate what needs to be propagated when --porcelain
+  * is not in effect here.
+  */
+ static struct status_deferred_config {
+       enum status_format status_format;
+       int show_branch;
+ } status_deferred_config = {
+       STATUS_FORMAT_UNSPECIFIED,
+       -1 /* unspecified */
+ };
+ static void finalize_deferred_config(struct wt_status *s)
+ {
+       int use_deferred_config = (status_format != STATUS_FORMAT_PORCELAIN &&
+                                  !s->null_termination);
+       if (s->null_termination) {
+               if (status_format == STATUS_FORMAT_NONE ||
+                   status_format == STATUS_FORMAT_UNSPECIFIED)
+                       status_format = STATUS_FORMAT_PORCELAIN;
+               else if (status_format == STATUS_FORMAT_LONG)
+                       die(_("--long and -z are incompatible"));
+       }
+       if (use_deferred_config && status_format == STATUS_FORMAT_UNSPECIFIED)
+               status_format = status_deferred_config.status_format;
+       if (status_format == STATUS_FORMAT_UNSPECIFIED)
+               status_format = STATUS_FORMAT_NONE;
+       if (use_deferred_config && s->show_branch < 0)
+               s->show_branch = status_deferred_config.show_branch;
+       if (s->show_branch < 0)
+               s->show_branch = 0;
+ }
  static int parse_and_validate_options(int argc, const char *argv[],
                                      const struct option *options,
                                      const char * const usage[],
        int f = 0;
  
        argc = parse_options(argc, argv, prefix, options, usage, 0);
+       finalize_deferred_config(s);
  
        if (force_author && !strchr(force_author, '>'))
                force_author = find_author_by_nickname(force_author);
        if (force_author && renew_authorship)
                die(_("Using both --reset-author and --author does not make sense"));
  
 -      if (logfile || message.len || use_message || fixup_message)
 +      if (logfile || have_option_m || use_message || fixup_message)
                use_editor = 0;
        if (0 <= edit_flag)
                use_editor = edit_flag;
        if (all && argc > 0)
                die(_("Paths with -a does not make sense."));
  
-       if (s->null_termination) {
-               if (status_format == STATUS_FORMAT_NONE)
-                       status_format = STATUS_FORMAT_PORCELAIN;
-               else if (status_format == STATUS_FORMAT_LONG)
-                       die(_("--long and -z are incompatible"));
-       }
        if (status_format != STATUS_FORMAT_NONE)
                dry_run = 1;
  
@@@ -1113,6 -1146,17 +1149,17 @@@ static int git_status_config(const cha
                        s->submodule_summary = -1;
                return 0;
        }
+       if (!strcmp(k, "status.short")) {
+               if (git_config_bool(k, v))
+                       status_deferred_config.status_format = STATUS_FORMAT_SHORT;
+               else
+                       status_deferred_config.status_format = STATUS_FORMAT_NONE;
+               return 0;
+       }
+       if (!strcmp(k, "status.branch")) {
+               status_deferred_config.show_branch = git_config_bool(k, v);
+               return 0;
+       }
        if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
                s->use_color = git_config_colorbool(k, v);
                return 0;
@@@ -1155,8 -1199,8 +1202,8 @@@ int cmd_status(int argc, const char **a
                OPT__VERBOSE(&verbose, N_("be verbose")),
                OPT_SET_INT('s', "short", &status_format,
                            N_("show status concisely"), STATUS_FORMAT_SHORT),
-               OPT_BOOLEAN('b', "branch", &s.show_branch,
-                           N_("show branch information")),
+               OPT_BOOL('b', "branch", &s.show_branch,
+                        N_("show branch information")),
                OPT_SET_INT(0, "porcelain", &status_format,
                            N_("machine-readable output"),
                            STATUS_FORMAT_PORCELAIN),
                             builtin_status_options,
                             builtin_status_usage, 0);
        finalize_colopts(&s.colopts, -1);
-       if (s.null_termination) {
-               if (status_format == STATUS_FORMAT_NONE)
-                       status_format = STATUS_FORMAT_PORCELAIN;
-               else if (status_format == STATUS_FORMAT_LONG)
-                       die(_("--long and -z are incompatible"));
-       }
+       finalize_deferred_config(&s);
  
        handle_untracked_files_arg(&s);
        if (show_ignored_in_status)
        case STATUS_FORMAT_PORCELAIN:
                wt_porcelain_print(&s);
                break;
+       case STATUS_FORMAT_UNSPECIFIED:
+               die("BUG: finalize_deferred_config() should have been called");
+               break;
        case STATUS_FORMAT_NONE:
        case STATUS_FORMAT_LONG:
                s.verbose = verbose;
@@@ -1392,7 -1433,7 +1436,7 @@@ int cmd_commit(int argc, const char **a
                OPT_BOOLEAN(0, "dry-run", &dry_run, N_("show what would be committed")),
                OPT_SET_INT(0, "short", &status_format, N_("show status concisely"),
                            STATUS_FORMAT_SHORT),
-               OPT_BOOLEAN(0, "branch", &s.show_branch, N_("show branch information")),
+               OPT_BOOL(0, "branch", &s.show_branch, N_("show branch information")),
                OPT_SET_INT(0, "porcelain", &status_format,
                            N_("machine-readable output"), STATUS_FORMAT_PORCELAIN),
                OPT_SET_INT(0, "long", &status_format,
        wt_status_prepare(&s);
        gitmodules_config();
        git_config(git_commit_config, &s);
+       status_format = STATUS_FORMAT_NONE; /* Ignore status.short */
        determine_whence(&s);
        s.colopts = 0;
  
                if (cfg) {
                        /* we are amending, so current_head is not NULL */
                        copy_note_for_rewrite(cfg, current_head->object.sha1, sha1);
 -                      finish_copy_notes_for_rewrite(cfg);
 +                      finish_copy_notes_for_rewrite(cfg, "Notes added by 'git commit --amend'");
                }
                run_rewrite_hook(current_head->object.sha1, sha1);
        }
diff --combined wt-status.c
index 72db2900b407239dba0ce426818a69fa1835f47e,6778755d76a681abe24449f16513443e9ec992bc..9c4d086b51364ff42a044be95e6ea55dffe7b79e
@@@ -127,6 -127,7 +127,7 @@@ void wt_status_prepare(struct wt_statu
        s->change.strdup_strings = 1;
        s->untracked.strdup_strings = 1;
        s->ignored.strdup_strings = 1;
+       s->show_branch = -1;  /* unspecified */
  }
  
  static void wt_status_print_unmerged_header(struct wt_status *s)
@@@ -826,7 -827,7 +827,7 @@@ static void show_am_in_progress(struct 
        if (advice_status_hints) {
                if (!state->am_empty_patch)
                        status_printf_ln(s, color,
 -                              _("  (fix conflicts and then run \"git am --resolved\")"));
 +                              _("  (fix conflicts and then run \"git am --continue\")"));
                status_printf_ln(s, color,
                        _("  (use \"git am --skip\" to skip this patch)"));
                status_printf_ln(s, color,
@@@ -955,12 -956,10 +956,12 @@@ static void show_cherry_pick_in_progres
        if (advice_status_hints) {
                if (has_unmerged(s))
                        status_printf_ln(s, color,
 -                              _("  (fix conflicts and run \"git commit\")"));
 +                              _("  (fix conflicts and run \"git cherry-pick --continue\")"));
                else
                        status_printf_ln(s, color,
 -                              _("  (all conflicts fixed: run \"git commit\")"));
 +                              _("  (all conflicts fixed: run \"git cherry-pick --continue\")"));
 +              status_printf_ln(s, color,
 +                      _("  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"));
        }
        wt_status_print_trailer(s);
  }
@@@ -1037,6 -1036,7 +1038,6 @@@ got_nothing
  }
  
  struct grab_1st_switch_cbdata {
 -      int found;
        struct strbuf buf;
        unsigned char nsha1[20];
  };
@@@ -1060,6 -1060,7 +1061,6 @@@ static int grab_1st_switch(unsigned cha
        for (end = target; *end && *end != '\n'; end++)
                ;
        strbuf_add(&cb->buf, target, end - target);
 -      cb->found = 1;
        return 1;
  }
  
@@@ -1176,10 -1177,7 +1177,10 @@@ void wt_status_print(struct wt_status *
                        branch_name += 11;
                else if (!strcmp(branch_name, "HEAD")) {
                        branch_status_color = color(WT_STATUS_NOBRANCH, s);
 -                      if (state.detached_from) {
 +                      if (state.rebase_in_progress || state.rebase_interactive_in_progress) {
 +                              on_what = _("rebase in progress; onto ");
 +                              branch_name = state.onto;
 +                      } else if (state.detached_from) {
                                unsigned char sha1[20];
                                branch_name = state.detached_from;
                                if (!get_sha1("HEAD", sha1) &&