Merge branch 'sb/parseopt-boolean-removal'
authorJunio C Hamano <gitster@pobox.com>
Wed, 4 Sep 2013 19:39:02 +0000 (12:39 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 4 Sep 2013 19:39:03 +0000 (12:39 -0700)
Convert most uses of OPT_BOOLEAN/OPTION_BOOLEAN that can use
OPT_BOOL/OPTION_BOOLEAN which have much saner semantics, and turn
remaining ones into OPT_SET_INT, OPT_COUNTUP, etc. as necessary.

* sb/parseopt-boolean-removal:
revert: use the OPT_CMDMODE for parsing, reducing code
checkout-index: fix negations of even numbers of -n
config parsing options: allow one flag multiple times
hash-object: replace stdin parsing OPT_BOOLEAN by OPT_COUNTUP
branch, commit, name-rev: ease up boolean conditions
checkout: remove superfluous local variable
log, format-patch: parsing uses OPT__QUIET
Replace deprecated OPT_BOOLEAN by OPT_BOOL
Remove deprecated OPTION_BOOLEAN for parsing arguments

1  2 
builtin/check-attr.c
builtin/check-ignore.c
builtin/clean.c
builtin/commit.c
builtin/fast-export.c
builtin/gc.c
builtin/push.c
builtin/rev-parse.c
builtin/rm.c
parse-options.h
diff --combined builtin/check-attr.c
index cd46690ec71531cf5fd475814e3423d3f428025d,6e5cd886af286f6f8dcb80c2d041181f8c0a51c8..e9af7b2bfb932d75cdface880be9814885068a50
@@@ -13,14 -13,14 +13,14 @@@ N_("git check-attr --stdin [-z] [-a | -
  NULL
  };
  
 -static int null_term_line;
 +static int nul_term_line;
  
  static const struct option check_attr_options[] = {
-       OPT_BOOLEAN('a', "all", &all_attrs, N_("report all attributes set on file")),
-       OPT_BOOLEAN(0,  "cached", &cached_attrs, N_("use .gitattributes only from the index")),
-       OPT_BOOLEAN(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
-       OPT_BOOLEAN('z', NULL, &nul_term_line,
-                   N_("terminate input and output records by a NUL character")),
+       OPT_BOOL('a', "all", &all_attrs, N_("report all attributes set on file")),
+       OPT_BOOL(0,  "cached", &cached_attrs, N_("use .gitattributes only from the index")),
+       OPT_BOOL(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
 -      OPT_BOOL('z', NULL, &null_term_line,
 -              N_("input paths are terminated by a null character")),
++      OPT_BOOL('z', NULL, &nul_term_line,
++               N_("terminate input and output records by a NUL character")),
        OPT_END()
  };
  
@@@ -38,16 -38,8 +38,16 @@@ static void output_attr(int cnt, struc
                else if (ATTR_UNSET(value))
                        value = "unspecified";
  
 -              quote_c_style(file, NULL, stdout, 0);
 -              printf(": %s: %s\n", git_attr_name(check[j].attr), value);
 +              if (nul_term_line) {
 +                      printf("%s%c" /* path */
 +                             "%s%c" /* attrname */
 +                             "%s%c" /* attrvalue */,
 +                             file, 0, git_attr_name(check[j].attr), 0, value, 0);
 +              } else {
 +                      quote_c_style(file, NULL, stdout, 0);
 +                      printf(": %s: %s\n", git_attr_name(check[j].attr), value);
 +              }
 +
        }
  }
  
@@@ -73,7 -65,7 +73,7 @@@ static void check_attr_stdin_paths(cons
        struct git_attr_check *check)
  {
        struct strbuf buf, nbuf;
 -      int line_termination = null_term_line ? 0 : '\n';
 +      int line_termination = nul_term_line ? 0 : '\n';
  
        strbuf_init(&buf, 0);
        strbuf_init(&nbuf, 0);
diff --combined builtin/check-ignore.c
index 503a559b18bf03aa7d78c2b408289da6297e0cff,c9f0c9bd6ad59384f01edf1d58b21bbbc5e501dc..25aa2a5f4c7ff0d0394e4df8e5e761ae916055f6
@@@ -12,18 -12,18 +12,18 @@@ static const char * const check_ignore_
  NULL
  };
  
 -static int null_term_line;
 +static int nul_term_line;
  
  static const struct option check_ignore_options[] = {
        OPT__QUIET(&quiet, N_("suppress progress reporting")),
        OPT__VERBOSE(&verbose, N_("be verbose")),
        OPT_GROUP(""),
-       OPT_BOOLEAN(0, "stdin", &stdin_paths,
-                   N_("read file names from stdin")),
-       OPT_BOOLEAN('z', NULL, &nul_term_line,
-                   N_("terminate input and output records by a NUL character")),
-       OPT_BOOLEAN('n', "non-matching", &show_non_matching,
-                   N_("show non-matching input paths")),
+       OPT_BOOL(0, "stdin", &stdin_paths,
+                N_("read file names from stdin")),
 -      OPT_BOOL('z', NULL, &null_term_line,
 -               N_("input paths are terminated by a null character")),
++      OPT_BOOL('z', NULL, &nul_term_line,
++               N_("terminate input and output records by a NUL character")),
+       OPT_BOOL('n', "non-matching", &show_non_matching,
+                N_("show non-matching input paths")),
        OPT_END()
  };
  
@@@ -31,7 -31,7 +31,7 @@@ static void output_exclude(const char *
  {
        char *bang  = (exclude && exclude->flags & EXC_FLAG_NEGATIVE)  ? "!" : "";
        char *slash = (exclude && exclude->flags & EXC_FLAG_MUSTBEDIR) ? "/" : "";
 -      if (!null_term_line) {
 +      if (!nul_term_line) {
                if (!verbose) {
                        write_name_quoted(path, stdout, '\n');
                } else {
@@@ -107,7 -107,7 +107,7 @@@ static int check_ignore_stdin_paths(str
  {
        struct strbuf buf, nbuf;
        char *pathspec[2] = { NULL, NULL };
 -      int line_termination = null_term_line ? 0 : '\n';
 +      int line_termination = nul_term_line ? 0 : '\n';
        int num_ignored = 0;
  
        strbuf_init(&buf, 0);
@@@ -142,7 -142,7 +142,7 @@@ int cmd_check_ignore(int argc, const ch
                if (argc > 0)
                        die(_("cannot specify pathnames with --stdin"));
        } else {
 -              if (null_term_line)
 +              if (nul_term_line)
                        die(_("-z only makes sense with --stdin"));
                if (argc == 0)
                        die(_("no path specified"));
diff --combined builtin/clean.c
index 3c85e152e140741855590f422c599407b6d6ae55,df0f61e74eb0682d7b07e6eef1a5e9ade502d62c..4b6fd42be7aeae55c71c7b79ee45fb73973ec0d5
@@@ -365,56 -365,6 +365,56 @@@ static void print_highlight_menu_stuff(
        string_list_clear(&menu_list, 0);
  }
  
 +static int find_unique(const char *choice, struct menu_stuff *menu_stuff)
 +{
 +      struct menu_item *menu_item;
 +      struct string_list_item *string_list_item;
 +      int i, len, found = 0;
 +
 +      len = strlen(choice);
 +      switch (menu_stuff->type) {
 +      default:
 +              die("Bad type of menu_stuff when parse choice");
 +      case MENU_STUFF_TYPE_MENU_ITEM:
 +
 +              menu_item = (struct menu_item *)menu_stuff->stuff;
 +              for (i = 0; i < menu_stuff->nr; i++, menu_item++) {
 +                      if (len == 1 && *choice == menu_item->hotkey) {
 +                              found = i + 1;
 +                              break;
 +                      }
 +                      if (!strncasecmp(choice, menu_item->title, len)) {
 +                              if (found) {
 +                                      if (len == 1) {
 +                                              /* continue for hotkey matching */
 +                                              found = -1;
 +                                      } else {
 +                                              found = 0;
 +                                              break;
 +                                      }
 +                              } else {
 +                                      found = i + 1;
 +                              }
 +                      }
 +              }
 +              break;
 +      case MENU_STUFF_TYPE_STRING_LIST:
 +              string_list_item = ((struct string_list *)menu_stuff->stuff)->items;
 +              for (i = 0; i < menu_stuff->nr; i++, string_list_item++) {
 +                      if (!strncasecmp(choice, string_list_item->string, len)) {
 +                              if (found) {
 +                                      found = 0;
 +                                      break;
 +                              }
 +                              found = i + 1;
 +                      }
 +              }
 +              break;
 +      }
 +      return found;
 +}
 +
 +
  /*
   * Parse user input, and return choice(s) for menu (menu_stuff).
   *
@@@ -442,6 -392,8 +442,6 @@@ static int parse_choice(struct menu_stu
                        int **chosen)
  {
        struct strbuf **choice_list, **ptr;
 -      struct menu_item *menu_item;
 -      struct string_list_item *string_list_item;
        int nr = 0;
        int i;
  
                        bottom = 1;
                        top = menu_stuff->nr;
                } else {
 -                      switch (menu_stuff->type) {
 -                      default:
 -                              die("Bad type of menu_stuff when parse choice");
 -                      case MENU_STUFF_TYPE_MENU_ITEM:
 -                              menu_item = (struct menu_item *)menu_stuff->stuff;
 -                              for (i = 0; i < menu_stuff->nr; i++, menu_item++) {
 -                                      if (((*ptr)->len == 1 &&
 -                                           *(*ptr)->buf == menu_item->hotkey) ||
 -                                          !strcasecmp((*ptr)->buf, menu_item->title)) {
 -                                              bottom = i + 1;
 -                                              top = bottom;
 -                                              break;
 -                                      }
 -                              }
 -                              break;
 -                      case MENU_STUFF_TYPE_STRING_LIST:
 -                              string_list_item = ((struct string_list *)menu_stuff->stuff)->items;
 -                              for (i = 0; i < menu_stuff->nr; i++, string_list_item++) {
 -                                      if (!strcasecmp((*ptr)->buf, string_list_item->string)) {
 -                                              bottom = i + 1;
 -                                              top = bottom;
 -                                              break;
 -                                      }
 -                              }
 -                              break;
 -                      }
 +                      bottom = find_unique((*ptr)->buf, menu_stuff);
 +                      top = bottom;
                }
  
                if (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||
@@@ -875,12 -851,12 +875,12 @@@ int cmd_clean(int argc, const char **ar
                OPT__DRY_RUN(&dry_run, N_("dry run")),
                OPT__FORCE(&force, N_("force")),
                OPT_BOOL('i', "interactive", &interactive, N_("interactive cleaning")),
-               OPT_BOOLEAN('d', NULL, &remove_directories,
+               OPT_BOOL('d', NULL, &remove_directories,
                                N_("remove whole directories")),
                { OPTION_CALLBACK, 'e', "exclude", &exclude_list, N_("pattern"),
                  N_("add <pattern> to ignore rules"), PARSE_OPT_NONEG, exclude_cb },
-               OPT_BOOLEAN('x', NULL, &ignored, N_("remove ignored files, too")),
-               OPT_BOOLEAN('X', NULL, &ignored_only,
+               OPT_BOOL('x', NULL, &ignored, N_("remove ignored files, too")),
+               OPT_BOOL('X', NULL, &ignored_only,
                                N_("remove only ignored files")),
                OPT_END()
        };
diff --combined builtin/commit.c
index 10acc53f8012f53b6a15a3d006b622bda3409b17,b0f86c872b04df40296da86d1b44b1ab7790ab8e..60812b5b4b0a7215c1d5c441799b9d0857c51dce
@@@ -63,18 -63,8 +63,18 @@@ N_("The previous cherry-pick is now emp
  "If you wish to commit it anyway, use:\n"
  "\n"
  "    git commit --allow-empty\n"
 +"\n");
 +
 +static const char empty_cherry_pick_advice_single[] =
 +N_("Otherwise, please use 'git reset'\n");
 +
 +static const char empty_cherry_pick_advice_multi[] =
 +N_("If you wish to skip this commit, use:\n"
  "\n"
 -"Otherwise, please use 'git reset'\n");
 +"    git reset\n"
 +"\n"
 +"Then \"git cherry-pick --continue\" will resume cherry-picking\n"
 +"the remaining commits.\n");
  
  static const char *use_message_buffer;
  static const char commit_editmsg[] = "COMMIT_EDITMSG";
@@@ -117,7 -107,6 +117,7 @@@ static enum 
  static const char *cleanup_arg;
  
  static enum commit_whence whence;
 +static int sequencer_in_use;
  static int use_editor = 1, include_status = 1;
  static int show_ignored_in_status, have_option_m;
  static const char *only_include_assumed;
@@@ -152,11 -141,8 +152,11 @@@ static void determine_whence(struct wt_
  {
        if (file_exists(git_path("MERGE_HEAD")))
                whence = FROM_MERGE;
 -      else if (file_exists(git_path("CHERRY_PICK_HEAD")))
 +      else if (file_exists(git_path("CHERRY_PICK_HEAD"))) {
                whence = FROM_CHERRY_PICK;
 +              if (file_exists(git_path("sequencer")))
 +                      sequencer_in_use = 1;
 +      }
        else
                whence = FROM_COMMIT;
        if (s)
@@@ -824,13 -810,8 +824,13 @@@ static int prepare_to_commit(const cha
                run_status(stdout, index_file, prefix, 0, s);
                if (amend)
                        fputs(_(empty_amend_advice), stderr);
 -              else if (whence == FROM_CHERRY_PICK)
 +              else if (whence == FROM_CHERRY_PICK) {
                        fputs(_(empty_cherry_pick_advice), stderr);
 +                      if (!sequencer_in_use)
 +                              fputs(_(empty_cherry_pick_advice_single), stderr);
 +                      else
 +                              fputs(_(empty_cherry_pick_advice_multi), stderr);
 +              }
                return 0;
        }
  
@@@ -1091,7 -1072,7 +1091,7 @@@ static int parse_and_validate_options(i
        if (patch_interactive)
                interactive = 1;
  
-       if (!!also + !!only + !!all + !!interactive > 1)
+       if (also + only + all + interactive > 1)
                die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
        if (argc == 0 && (also || (only && !amend)))
                die(_("No paths with --include/--only does not make sense."));
@@@ -1228,14 -1209,14 +1228,14 @@@ int cmd_status(int argc, const char **a
                OPT_SET_INT(0, "long", &status_format,
                            N_("show status in long format (default)"),
                            STATUS_FORMAT_LONG),
-               OPT_BOOLEAN('z', "null", &s.null_termination,
-                           N_("terminate entries with NUL")),
+               OPT_BOOL('z', "null", &s.null_termination,
+                        N_("terminate entries with NUL")),
                { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg,
                  N_("mode"),
                  N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
                  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
-               OPT_BOOLEAN(0, "ignored", &show_ignored_in_status,
-                           N_("show ignored files")),
+               OPT_BOOL(0, "ignored", &show_ignored_in_status,
+                        N_("show ignored files")),
                { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),
                  N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
                  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
@@@ -1434,24 -1415,24 +1434,24 @@@ int cmd_commit(int argc, const char **a
                OPT_STRING('C', "reuse-message", &use_message, N_("commit"), N_("reuse message from specified commit")),
                OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
                OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
-               OPT_BOOLEAN(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
-               OPT_BOOLEAN('s', "signoff", &signoff, N_("add Signed-off-by:")),
+               OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
+               OPT_BOOL('s', "signoff", &signoff, N_("add Signed-off-by:")),
                OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
                OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
                OPT_STRING(0, "cleanup", &cleanup_arg, N_("default"), N_("how to strip spaces and #comments from message")),
-               OPT_BOOLEAN(0, "status", &include_status, N_("include status in commit message template")),
+               OPT_BOOL(0, "status", &include_status, N_("include status in commit message template")),
                { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key id"),
                  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
                /* end commit message options */
  
                OPT_GROUP(N_("Commit contents options")),
-               OPT_BOOLEAN('a', "all", &all, N_("commit all changed files")),
-               OPT_BOOLEAN('i', "include", &also, N_("add specified files to index for commit")),
-               OPT_BOOLEAN(0, "interactive", &interactive, N_("interactively add files")),
-               OPT_BOOLEAN('p', "patch", &patch_interactive, N_("interactively add changes")),
-               OPT_BOOLEAN('o', "only", &only, N_("commit only specified files")),
-               OPT_BOOLEAN('n', "no-verify", &no_verify, N_("bypass pre-commit hook")),
-               OPT_BOOLEAN(0, "dry-run", &dry_run, N_("show what would be committed")),
+               OPT_BOOL('a', "all", &all, N_("commit all changed files")),
+               OPT_BOOL('i', "include", &also, N_("add specified files to index for commit")),
+               OPT_BOOL(0, "interactive", &interactive, N_("interactively add files")),
+               OPT_BOOL('p', "patch", &patch_interactive, N_("interactively add changes")),
+               OPT_BOOL('o', "only", &only, N_("commit only specified files")),
+               OPT_BOOL('n', "no-verify", &no_verify, N_("bypass pre-commit hook")),
+               OPT_BOOL(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_BOOL(0, "branch", &s.show_branch, N_("show branch information")),
                OPT_SET_INT(0, "long", &status_format,
                            N_("show status in long format (default)"),
                            STATUS_FORMAT_LONG),
-               OPT_BOOLEAN('z', "null", &s.null_termination,
-                           N_("terminate entries with NUL")),
-               OPT_BOOLEAN(0, "amend", &amend, N_("amend previous commit")),
-               OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
+               OPT_BOOL('z', "null", &s.null_termination,
+                        N_("terminate entries with NUL")),
+               OPT_BOOL(0, "amend", &amend, N_("amend previous commit")),
+               OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
                { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
                /* end commit contents options */
  
-               { OPTION_BOOLEAN, 0, "allow-empty", &allow_empty, NULL,
-                 N_("ok to record an empty change"),
-                 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
-               { OPTION_BOOLEAN, 0, "allow-empty-message", &allow_empty_message, NULL,
-                 N_("ok to record a change with an empty message"),
-                 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
+               OPT_HIDDEN_BOOL(0, "allow-empty", &allow_empty,
+                               N_("ok to record an empty change")),
+               OPT_HIDDEN_BOOL(0, "allow-empty-message", &allow_empty_message,
+                               N_("ok to record a change with an empty message")),
  
                OPT_END()
        };
diff --combined builtin/fast-export.c
index 8e19058744756e9978eac6244156ed1c27f1e20e,32b0c3fd24c375f4653a643c0c1e452fe6ff28e8..b1b9b5e52aa57b62d5edb5c55f818411e64d9c90
@@@ -379,7 -379,7 +379,7 @@@ static void handle_tag(const char *name
        int tagged_mark;
        struct commit *p;
  
 -      /* Trees have no identifer in fast-export output, thus we have no way
 +      /* Trees have no identifier in fast-export output, thus we have no way
         * to output tags of trees, tags of tags of trees, etc.  Simply omit
         * such tags.
         */
@@@ -674,11 -674,11 +674,11 @@@ int cmd_fast_export(int argc, const cha
                             N_("Dump marks to this file")),
                OPT_STRING(0, "import-marks", &import_filename, N_("file"),
                             N_("Import marks from this file")),
-               OPT_BOOLEAN(0, "fake-missing-tagger", &fake_missing_tagger,
-                            N_("Fake a tagger when tags lack one")),
-               OPT_BOOLEAN(0, "full-tree", &full_tree,
-                            N_("Output full tree for each commit")),
-               OPT_BOOLEAN(0, "use-done-feature", &use_done_feature,
+               OPT_BOOL(0, "fake-missing-tagger", &fake_missing_tagger,
+                        N_("Fake a tagger when tags lack one")),
+               OPT_BOOL(0, "full-tree", &full_tree,
+                        N_("Output full tree for each commit")),
+               OPT_BOOL(0, "use-done-feature", &use_done_feature,
                             N_("Use the done feature to terminate the stream")),
                OPT_BOOL(0, "no-data", &no_data, N_("Skip output of blob data")),
                OPT_END()
diff --combined builtin/gc.c
index 6e0d81ab32aa691d24dc86ba30f3bc282bdc2890,c4f7390bcf8a6a86feaa6eab678a24403da6b56a..891a2c2ecb046dc29b2d9ce8b9d2982084bf9b19
@@@ -167,78 -167,19 +167,78 @@@ static int need_to_gc(void
        return 1;
  }
  
 +/* return NULL on success, else hostname running the gc */
 +static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
 +{
 +      static struct lock_file lock;
 +      static char locking_host[128];
 +      char my_host[128];
 +      struct strbuf sb = STRBUF_INIT;
 +      struct stat st;
 +      uintmax_t pid;
 +      FILE *fp;
 +      int fd, should_exit;
 +
 +      if (gethostname(my_host, sizeof(my_host)))
 +              strcpy(my_host, "unknown");
 +
 +      fd = hold_lock_file_for_update(&lock, git_path("gc.pid"),
 +                                     LOCK_DIE_ON_ERROR);
 +      if (!force) {
 +              fp = fopen(git_path("gc.pid"), "r");
 +              memset(locking_host, 0, sizeof(locking_host));
 +              should_exit =
 +                      fp != NULL &&
 +                      !fstat(fileno(fp), &st) &&
 +                      /*
 +                       * 12 hour limit is very generous as gc should
 +                       * never take that long. On the other hand we
 +                       * don't really need a strict limit here,
 +                       * running gc --auto one day late is not a big
 +                       * problem. --force can be used in manual gc
 +                       * after the user verifies that no gc is
 +                       * running.
 +                       */
 +                      time(NULL) - st.st_mtime <= 12 * 3600 &&
 +                      fscanf(fp, "%"PRIuMAX" %127c", &pid, locking_host) == 2 &&
 +                      /* be gentle to concurrent "gc" on remote hosts */
 +                      (strcmp(locking_host, my_host) || !kill(pid, 0));
 +              if (fp != NULL)
 +                      fclose(fp);
 +              if (should_exit) {
 +                      if (fd >= 0)
 +                              rollback_lock_file(&lock);
 +                      *ret_pid = pid;
 +                      return locking_host;
 +              }
 +      }
 +
 +      strbuf_addf(&sb, "%"PRIuMAX" %s",
 +                  (uintmax_t) getpid(), my_host);
 +      write_in_full(fd, sb.buf, sb.len);
 +      strbuf_release(&sb);
 +      commit_lock_file(&lock);
 +
 +      return NULL;
 +}
 +
  int cmd_gc(int argc, const char **argv, const char *prefix)
  {
        int aggressive = 0;
        int auto_gc = 0;
        int quiet = 0;
 +      int force = 0;
 +      const char *name;
 +      pid_t pid;
  
        struct option builtin_gc_options[] = {
                OPT__QUIET(&quiet, N_("suppress progress reporting")),
                { OPTION_STRING, 0, "prune", &prune_expire, N_("date"),
                        N_("prune unreferenced objects"),
                        PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
-               OPT_BOOLEAN(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
-               OPT_BOOLEAN(0, "auto", &auto_gc, N_("enable auto-gc mode")),
+               OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
+               OPT_BOOL(0, "auto", &auto_gc, N_("enable auto-gc mode")),
 +              OPT_BOOL(0, "force", &force, N_("force running gc even if there may be another gc running")),
                OPT_END()
        };
  
        } else
                add_repack_all_option();
  
 +      name = lock_repo_for_gc(force, &pid);
 +      if (name) {
 +              if (auto_gc)
 +                      return 0; /* be quiet on --auto */
 +              die(_("gc is already running on machine '%s' pid %"PRIuMAX" (use --force if not)"),
 +                  name, (uintmax_t)pid);
 +      }
 +
        if (pack_refs && run_command_v_opt(pack_refs_cmd.argv, RUN_GIT_CMD))
                return error(FAILED_RUN, pack_refs_cmd.argv[0]);
  
diff --combined builtin/push.c
index 04f0eaf179044dce1e87137978bcbecca18f3527,bebaf3df1d197cc243416463b17eeb2773f00980..aff507c9f601f4c783ee16a08621695edd9b5ecb
@@@ -92,7 -92,7 +92,7 @@@ static NORETURN int die_push_simple(str
        if (!short_upstream)
                short_upstream = branch->merge[0]->src;
        /*
 -       * Don't show advice for people who explicitely set
 +       * Don't show advice for people who explicitly set
         * push.default.
         */
        if (push_default == PUSH_DEFAULT_UNSPECIFIED)
@@@ -446,15 -446,15 +446,15 @@@ int cmd_push(int argc, const char **arg
                OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
                OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
                            (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
-               OPT_BOOLEAN( 0, "delete", &deleterefs, N_("delete refs")),
-               OPT_BOOLEAN( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
+               OPT_BOOL( 0, "delete", &deleterefs, N_("delete refs")),
+               OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
                OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
                OPT_BIT( 0,  "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
                OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
                { OPTION_CALLBACK, 0, "recurse-submodules", &flags, N_("check"),
                        N_("control recursive pushing of submodules"),
                        PARSE_OPT_OPTARG, option_parse_recurse_submodules },
-               OPT_BOOLEAN( 0 , "thin", &thin, N_("use thin pack")),
+               OPT_BOOL( 0 , "thin", &thin, N_("use thin pack")),
                OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", N_("receive pack program")),
                OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")),
                OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"),
diff --combined builtin/rev-parse.c
index c9aa28fd75c6e4f995906c584ec185617ec76856,67e8ccfd9fb6d6814dd6b7c86b14fc261df8b877..c76b89dc5bcccb42f7c2613072b1093a58c7d21c
@@@ -346,9 -346,9 +346,9 @@@ static int cmd_parseopt(int argc, cons
                NULL
        };
        static struct option parseopt_opts[] = {
-               OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash,
+               OPT_BOOL(0, "keep-dashdash", &keep_dashdash,
                                        N_("keep the `--` passed as an arg")),
-               OPT_BOOLEAN(0, "stop-at-non-option", &stop_at_non_option,
+               OPT_BOOL(0, "stop-at-non-option", &stop_at_non_option,
                                        N_("stop parsing after the "
                                           "first non-option argument")),
                OPT_END(),
@@@ -486,6 -486,21 +486,6 @@@ int cmd_rev_parse(int argc, const char 
        if (argc > 1 && !strcmp("--sq-quote", argv[1]))
                return cmd_sq_quote(argc - 2, argv + 2);
  
 -      if (argc == 2 && !strcmp("--local-env-vars", argv[1])) {
 -              int i;
 -              for (i = 0; local_repo_env[i]; i++)
 -                      printf("%s\n", local_repo_env[i]);
 -              return 0;
 -      }
 -
 -      if (argc > 2 && !strcmp(argv[1], "--resolve-git-dir")) {
 -              const char *gitdir = resolve_gitdir(argv[2]);
 -              if (!gitdir)
 -                      die("not a gitdir '%s'", argv[2]);
 -              puts(gitdir);
 -              return 0;
 -      }
 -
        if (argc > 1 && !strcmp("-h", argv[1]))
                usage(builtin_rev_parse_usage);
  
                                for_each_remote_ref(show_reference, NULL);
                                continue;
                        }
 +                      if (!strcmp(arg, "--local-env-vars")) {
 +                              int i;
 +                              for (i = 0; local_repo_env[i]; i++)
 +                                      printf("%s\n", local_repo_env[i]);
 +                              continue;
 +                      }
                        if (!strcmp(arg, "--show-toplevel")) {
                                const char *work_tree = get_git_work_tree();
                                if (work_tree)
                                printf("%s%s.git\n", cwd, len && cwd[len-1] != '/' ? "/" : "");
                                continue;
                        }
 +                      if (!strcmp(arg, "--resolve-git-dir")) {
 +                              const char *gitdir = resolve_gitdir(argv[i+1]);
 +                              if (!gitdir)
 +                                      die("not a gitdir '%s'", argv[i+1]);
 +                              puts(gitdir);
 +                              continue;
 +                      }
                        if (!strcmp(arg, "--is-inside-git-dir")) {
                                printf("%s\n", is_inside_git_dir() ? "true"
                                                : "false");
diff --combined builtin/rm.c
index d00eaf86d56c9efbd436458d46937b8b2c855ce4,ce28fa9ac910913b8e373386cd25a64dbf16c0f3..18bf2189992439caafb66b103df9fbe3e76c4e37
@@@ -58,21 -58,6 +58,21 @@@ static void print_error_files(struct st
        }
  }
  
 +static void error_removing_concrete_submodules(struct string_list *files, int *errs)
 +{
 +      print_error_files(files,
 +                        Q_("the following submodule (or one of its nested "
 +                           "submodules)\n"
 +                           "uses a .git directory:",
 +                           "the following submodules (or one of its nested "
 +                           "submodules)\n"
 +                           "use a .git directory:", files->nr),
 +                        _("\n(use 'rm -rf' if you really want to remove "
 +                          "it including all of its history)"),
 +                        errs);
 +      string_list_clear(files, 0);
 +}
 +
  static int check_submodules_use_gitfiles(void)
  {
        int i;
                if (!submodule_uses_gitfile(name))
                        string_list_append(&files, name);
        }
 -      print_error_files(&files,
 -                        Q_("the following submodule (or one of its nested "
 -                           "submodules)\n uses a .git directory:",
 -                           "the following submodules (or one of its nested "
 -                           "submodules)\n use a .git directory:",
 -                           files.nr),
 -                        _("\n(use 'rm -rf' if you really want to remove "
 -                          "it including all of its history)"),
 -                        &errs);
 -      string_list_clear(&files, 0);
 +
 +      error_removing_concrete_submodules(&files, &errs);
  
        return errs;
  }
@@@ -244,9 -237,17 +244,9 @@@ static int check_local_mod(unsigned cha
                            " or -f to force removal)"),
                          &errs);
        string_list_clear(&files_cached, 0);
 -      print_error_files(&files_submodule,
 -                        Q_("the following submodule (or one of its nested "
 -                           "submodule)\nuses a .git directory:",
 -                           "the following submodules (or one of its nested "
 -                           "submodule)\nuse a .git directory:",
 -                           files_submodule.nr),
 -                        _("\n(use 'rm -rf' if you really "
 -                          "want to remove it including all "
 -                          "of its history)"),
 -                        &errs);
 -      string_list_clear(&files_submodule, 0);
 +
 +      error_removing_concrete_submodules(&files_submodule, &errs);
 +
        print_error_files(&files_local,
                          Q_("the following file has local modifications:",
                             "the following files have local modifications:",
@@@ -267,18 -268,18 +267,18 @@@ static int ignore_unmatch = 0
  static struct option builtin_rm_options[] = {
        OPT__DRY_RUN(&show_only, N_("dry run")),
        OPT__QUIET(&quiet, N_("do not list removed files")),
-       OPT_BOOLEAN( 0 , "cached",         &index_only, N_("only remove from the index")),
+       OPT_BOOL( 0 , "cached",         &index_only, N_("only remove from the index")),
        OPT__FORCE(&force, N_("override the up-to-date check")),
-       OPT_BOOLEAN('r', NULL,             &recursive,  N_("allow recursive removal")),
-       OPT_BOOLEAN( 0 , "ignore-unmatch", &ignore_unmatch,
+       OPT_BOOL('r', NULL,             &recursive,  N_("allow recursive removal")),
+       OPT_BOOL( 0 , "ignore-unmatch", &ignore_unmatch,
                                N_("exit with a zero status even if nothing matched")),
        OPT_END(),
  };
  
  int cmd_rm(int argc, const char **argv, const char *prefix)
  {
 -      int i, newfd;
 -      const char **pathspec;
 +      int i, newfd, seen_any;
 +      const char **pathspec, *match;
        char *seen;
  
        git_config(git_default_config, NULL);
        pathspec = get_pathspec(prefix, argv);
        refresh_index(&the_index, REFRESH_QUIET, pathspec, NULL, NULL);
  
 -      seen = NULL;
        for (i = 0; pathspec[i] ; i++)
                /* nothing */;
        seen = xcalloc(i, 1);
                list.entry[list.nr++].is_submodule = S_ISGITLINK(ce->ce_mode);
        }
  
 -      if (pathspec) {
 -              const char *match;
 -              int seen_any = 0;
 -              for (i = 0; (match = pathspec[i]) != NULL ; i++) {
 -                      if (!seen[i]) {
 -                              if (!ignore_unmatch) {
 -                                      die(_("pathspec '%s' did not match any files"),
 -                                          match);
 -                              }
 -                      }
 -                      else {
 -                              seen_any = 1;
 +
 +      seen_any = 0;
 +      for (i = 0; (match = pathspec[i]) != NULL ; i++) {
 +              if (!seen[i]) {
 +                      if (!ignore_unmatch) {
 +                              die(_("pathspec '%s' did not match any files"),
 +                                  match);
                        }
 -                      if (!recursive && seen[i] == MATCHED_RECURSIVELY)
 -                              die(_("not removing '%s' recursively without -r"),
 -                                  *match ? match : ".");
                }
 -
 -              if (! seen_any)
 -                      exit(0);
 +              else {
 +                      seen_any = 1;
 +              }
 +              if (!recursive && seen[i] == MATCHED_RECURSIVELY)
 +                      die(_("not removing '%s' recursively without -r"),
 +                          *match ? match : ".");
        }
 +      if (!seen_any)
 +              exit(0);
  
        /*
         * If not forced, the file, the index and the HEAD (if exists)
diff --combined parse-options.h
index f37fc88143f0cc0277b33d55ec92cc43034774cf,aeab9aa103faa88a9cdff98db62a586c97298012..8736006ed73560ebb05abac2debb04d5117dc114
@@@ -22,9 -22,6 +22,6 @@@ enum parse_opt_type 
        OPTION_FILENAME
  };
  
- /* Deprecated synonym */
- #define OPTION_BOOLEAN OPTION_COUNTUP
  enum parse_opt_flags {
        PARSE_OPT_KEEP_DASHDASH = 1,
        PARSE_OPT_STOP_AT_NON_OPTION = 2,
@@@ -129,6 -126,8 +126,8 @@@ struct option 
  #define OPT_SET_INT(s, l, v, h, i)  { OPTION_SET_INT, (s), (l), (v), NULL, \
                                      (h), PARSE_OPT_NOARG, NULL, (i) }
  #define OPT_BOOL(s, l, v, h)        OPT_SET_INT(s, l, v, h, 1)
+ #define OPT_HIDDEN_BOOL(s, l, v, h) { OPTION_SET_INT, (s), (l), (v), NULL, \
+                                     (h), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1}
  #define OPT_SET_PTR(s, l, v, h, p)  { OPTION_SET_PTR, (s), (l), (v), NULL, \
                                      (h), PARSE_OPT_NOARG, NULL, (p) }
  #define OPT_CMDMODE(s, l, v, h, i) { OPTION_CMDMODE, (s), (l), (v), NULL, \
@@@ -183,7 -182,7 +182,7 @@@ extern NORETURN void usage_msg_opt(cons
  
  extern int optbug(const struct option *opt, const char *reason);
  extern int opterror(const struct option *opt, const char *reason, int flags);
 -#if defined(__GNUC__) && ! defined(clang)
 +#if defined(__GNUC__) && ! defined(__clang__)
  #define opterror(o,r,f) (opterror((o),(r),(f)), -1)
  #endif