Merge branch 'nd/command-list'
authorJunio C Hamano <gitster@pobox.com>
Fri, 1 Jun 2018 06:06:37 +0000 (15:06 +0900)
committerJunio C Hamano <gitster@pobox.com>
Fri, 1 Jun 2018 06:06:37 +0000 (15:06 +0900)
The list of commands with their various attributes were spread
across a few places in the build procedure, but it now is getting a
bit more consolidated to allow more automation.

* nd/command-list:
completion: allow to customize the completable command list
completion: add and use --list-cmds=alias
completion: add and use --list-cmds=nohelpers
Move declaration for alias.c to alias.h
completion: reduce completable command list
completion: let git provide the completable command list
command-list.txt: documentation and guide line
help: use command-list.txt for the source of guides
help: add "-a --verbose" to list all commands with synopsis
git: support --list-cmds=list-<category>
completion: implement and use --list-cmds=main,others
git --list-cmds: collect command list in a string_list
git.c: convert --list-* to --list-cmds=*
Remove common-cmds.h
help: use command-list.h for common command list
generate-cmds.sh: export all commands to command-list.h
generate-cmds.sh: factor out synopsis extract code

25 files changed:
.gitignore
Documentation/config.txt
Documentation/git-help.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/gitmodules.txt
Documentation/gitrevisions.txt
Makefile
alias.c
alias.h [new file with mode: 0644]
builtin/help.c
builtin/merge.c
cache.h
command-list.txt
connect.c
contrib/completion/git-completion.bash
generate-cmdlist.sh
git.c
help.c
help.h
pager.c
sequencer.c
shell.c
t/t0012-help.sh
t/t9902-completion.sh
index b2a1ae4a1d6293004b10d14c33bb64fd9d14fe8b..388cc4beee54faf9f06e9cfae75e7a256d368739 100644 (file)
 /gitweb/gitweb.cgi
 /gitweb/static/gitweb.js
 /gitweb/static/gitweb.min.*
-/common-cmds.h
+/command-list.h
 *.tar.gz
 *.dsc
 *.deb
index 7d8383433ce9995c1950705fb9b345eff1bd652d..ab641bf5a9984b7ab2dfea787a0db5704f79a448 100644 (file)
@@ -1412,6 +1412,14 @@ credential.<url>.*::
 credentialCache.ignoreSIGHUP::
        Tell git-credential-cache--daemon to ignore SIGHUP, instead of quitting.
 
+completion.commands::
+       This is only used by git-completion.bash to add or remove
+       commands from the list of completed commands. Normally only
+       porcelain commands and a few select others are completed. You
+       can add more commands, separated by space, in this
+       variable. Prefixing the command with '-' will remove it from
+       the existing list.
+
 include::diff-config.txt[]
 
 difftool.<tool>.path::
index 40d328a4b3e7e03720cbefc5100ee8e752f6a586..a40fc38d8b425fae0a1ca074ecc8d603efc80f14 100644 (file)
@@ -8,7 +8,7 @@ git-help - Display help information about Git
 SYNOPSIS
 --------
 [verse]
-'git help' [-a|--all] [-g|--guide]
+'git help' [-a|--all [--verbose]] [-g|--guide]
           [-i|--info|-m|--man|-w|--web] [COMMAND|GUIDE]
 
 DESCRIPTION
@@ -42,6 +42,8 @@ OPTIONS
 --all::
        Prints all the available commands on the standard output. This
        option overrides any given command or guide name.
+       When used with `--verbose` print description for all recognized
+       commands.
 
 -g::
 --guides::
index c662f41c1dce8ee69113dbb35298bd5c97e831b7..dba7f0c18e33e7e26ca100992236e39b3d5b8a91 100644 (file)
@@ -164,6 +164,16 @@ foo.bar= ...`) sets `foo.bar` to the empty string which `git config
        Do not perform optional operations that require locks. This is
        equivalent to setting the `GIT_OPTIONAL_LOCKS` to `0`.
 
+--list-cmds=group[,group...]::
+       List commands by group. This is an internal/experimental
+       option and may change or be removed in the future. Supported
+       groups are: builtins, parseopt (builtin commands that use
+       parse-options), main (all commands in libexec directory),
+       others (all other commands in `$PATH` that have git- prefix),
+       list-<category> (see categories in command-list.txt),
+       nohelpers (exclude helper commands), alias and config
+       (retrieve command list from config variable completion.commands)
+
 GIT COMMANDS
 ------------
 
index b72936a885c9772d60c7105cb9e5ba2e27968fcc..92010b062e08678fcfb0a143f75bbd4b07bfcf4b 100644 (file)
@@ -3,7 +3,7 @@ gitattributes(5)
 
 NAME
 ----
-gitattributes - defining attributes per path
+gitattributes - Defining attributes per path
 
 SYNOPSIS
 --------
index db5d47eb19b8f2aa21c11a9d3eedf40b9d71e84e..4d63def2069a8358afa05154c18653175dda6703 100644 (file)
@@ -3,7 +3,7 @@ gitmodules(5)
 
 NAME
 ----
-gitmodules - defining submodule properties
+gitmodules - Defining submodule properties
 
 SYNOPSIS
 --------
index 27dec5b91d08bbdb114400dd3c86a8cf515e8774..1f6cceaefb028e5f96d802703a25a16e950a3e17 100644 (file)
@@ -3,7 +3,7 @@ gitrevisions(7)
 
 NAME
 ----
-gitrevisions - specifying revisions and ranges for Git
+gitrevisions - Specifying revisions and ranges for Git
 
 SYNOPSIS
 --------
index 4bca65383a784dca7da0092adb6c2eb754fa83cf..1d27f36365ae2485e3706548b2b0299436902cc6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -795,7 +795,7 @@ LIB_FILE = libgit.a
 XDIFF_LIB = xdiff/lib.a
 VCSSVN_LIB = vcs-svn/lib.a
 
-GENERATED_H += common-cmds.h
+GENERATED_H += command-list.h
 
 LIB_H = $(shell $(FIND) . \
        -name .git -prune -o \
@@ -2006,9 +2006,9 @@ git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
                $(filter %.o,$^) $(LIBS)
 
-help.sp help.s help.o: common-cmds.h
+help.sp help.s help.o: command-list.h
 
-builtin/help.sp builtin/help.s builtin/help.o: common-cmds.h GIT-PREFIX
+builtin/help.sp builtin/help.s builtin/help.o: command-list.h GIT-PREFIX
 builtin/help.sp builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
        '-DGIT_HTML_PATH="$(htmldir_relative_SQ)"' \
        '-DGIT_MAN_PATH="$(mandir_relative_SQ)"' \
@@ -2027,9 +2027,9 @@ $(BUILT_INS): git$X
        ln -s $< $@ 2>/dev/null || \
        cp $< $@
 
-common-cmds.h: generate-cmdlist.sh command-list.txt
+command-list.h: generate-cmdlist.sh command-list.txt
 
-common-cmds.h: $(wildcard Documentation/git-*.txt)
+command-list.h: $(wildcard Documentation/git*.txt)
        $(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh command-list.txt >$@+ && mv $@+ $@
 
 SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
@@ -2273,7 +2273,7 @@ else
 # Dependencies on header files, for platforms that do not support
 # the gcc -MMD option.
 #
-# Dependencies on automatically generated headers such as common-cmds.h
+# Dependencies on automatically generated headers such as command-list.h
 # should _not_ be included here, since they are necessary even when
 # building an object for the first time.
 
@@ -2653,7 +2653,7 @@ sparse: $(SP_OBJ)
 style:
        git clang-format --style file --diff --extensions c,h
 
-check: common-cmds.h
+check: command-list.h
        @if sparse; \
        then \
                echo >&2 "Use 'make sparse' instead"; \
@@ -2901,7 +2901,7 @@ clean: profile-clean coverage-clean
        $(RM) $(TEST_PROGRAMS) $(NO_INSTALL)
        $(RM) -r bin-wrappers $(dep_dirs)
        $(RM) -r po/build/
-       $(RM) *.pyc *.pyo */*.pyc */*.pyo common-cmds.h $(ETAGS_TARGET) tags cscope*
+       $(RM) *.pyc *.pyo */*.pyc */*.pyo command-list.h $(ETAGS_TARGET) tags cscope*
        $(RM) -r $(GIT_TARNAME) .doc-tmp-dir
        $(RM) $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
        $(RM) $(htmldocs).tar.gz $(manpages).tar.gz
diff --git a/alias.c b/alias.c
index bf146e526329309df360b9f1028ca2f767743efa..a7e4e57130d46188a4a0ee93871375218041344c 100644 (file)
--- a/alias.c
+++ b/alias.c
@@ -1,9 +1,12 @@
 #include "cache.h"
+#include "alias.h"
 #include "config.h"
+#include "string-list.h"
 
 struct config_alias_data {
        const char *alias;
        char *v;
+       struct string_list *list;
 };
 
 static int config_alias_cb(const char *key, const char *value, void *d)
@@ -11,8 +14,16 @@ static int config_alias_cb(const char *key, const char *value, void *d)
        struct config_alias_data *data = d;
        const char *p;
 
-       if (skip_prefix(key, "alias.", &p) && !strcasecmp(p, data->alias))
-               return git_config_string((const char **)&data->v, key, value);
+       if (!skip_prefix(key, "alias.", &p))
+               return 0;
+
+       if (data->alias) {
+               if (!strcasecmp(p, data->alias))
+                       return git_config_string((const char **)&data->v,
+                                                key, value);
+       } else if (data->list) {
+               string_list_append(data->list, p);
+       }
 
        return 0;
 }
@@ -26,6 +37,13 @@ char *alias_lookup(const char *alias)
        return data.v;
 }
 
+void list_aliases(struct string_list *list)
+{
+       struct config_alias_data data = { NULL, NULL, list };
+
+       read_early_config(config_alias_cb, &data);
+}
+
 #define SPLIT_CMDLINE_BAD_ENDING 1
 #define SPLIT_CMDLINE_UNCLOSED_QUOTE 2
 static const char *split_cmdline_errors[] = {
diff --git a/alias.h b/alias.h
new file mode 100644 (file)
index 0000000..79933f2
--- /dev/null
+++ b/alias.h
@@ -0,0 +1,12 @@
+#ifndef __ALIAS_H__
+#define __ALIAS_H__
+
+struct string_list;
+
+char *alias_lookup(const char *alias);
+int split_cmdline(char *cmdline, const char ***argv);
+/* Takes a negative value returned by split_cmdline */
+const char *split_cmdline_strerror(int cmdline_errno);
+void list_aliases(struct string_list *list);
+
+#endif
index 2d5107142926d46230d17715211338c1aa171e69..58e0a5507f10365b43eaa2698da2c8bba18b12ed 100644 (file)
@@ -9,6 +9,7 @@
 #include "run-command.h"
 #include "column.h"
 #include "help.h"
+#include "alias.h"
 
 #ifndef DEFAULT_HELP_FORMAT
 #define DEFAULT_HELP_FORMAT "man"
@@ -36,6 +37,7 @@ static const char *html_path;
 
 static int show_all = 0;
 static int show_guides = 0;
+static int verbose;
 static unsigned int colopts;
 static enum help_format help_format = HELP_FORMAT_NONE;
 static int exclude_guides;
@@ -48,6 +50,7 @@ static struct option builtin_help_options[] = {
                        HELP_FORMAT_WEB),
        OPT_SET_INT('i', "info", &help_format, N_("show info page"),
                        HELP_FORMAT_INFO),
+       OPT__VERBOSE(&verbose, N_("print command description")),
        OPT_END(),
 };
 
@@ -400,38 +403,6 @@ static void show_html_page(const char *git_cmd)
        open_html(page_path.buf);
 }
 
-static struct {
-       const char *name;
-       const char *help;
-} common_guides[] = {
-       { "attributes", N_("Defining attributes per path") },
-       { "everyday", N_("Everyday Git With 20 Commands Or So") },
-       { "glossary", N_("A Git glossary") },
-       { "ignore", N_("Specifies intentionally untracked files to ignore") },
-       { "modules", N_("Defining submodule properties") },
-       { "revisions", N_("Specifying revisions and ranges for Git") },
-       { "tutorial", N_("A tutorial introduction to Git (for version 1.5.1 or newer)") },
-       { "workflows", N_("An overview of recommended workflows with Git") },
-};
-
-static void list_common_guides_help(void)
-{
-       int i, longest = 0;
-
-       for (i = 0; i < ARRAY_SIZE(common_guides); i++) {
-               if (longest < strlen(common_guides[i].name))
-                       longest = strlen(common_guides[i].name);
-       }
-
-       puts(_("The common Git guides are:\n"));
-       for (i = 0; i < ARRAY_SIZE(common_guides); i++) {
-               printf("   %s   ", common_guides[i].name);
-               mput_char(' ', longest - strlen(common_guides[i].name));
-               puts(_(common_guides[i].help));
-       }
-       putchar('\n');
-}
-
 static const char *check_git_cmd(const char* cmd)
 {
        char *alias;
@@ -463,6 +434,11 @@ int cmd_help(int argc, const char **argv, const char *prefix)
 
        if (show_all) {
                git_config(git_help_config, NULL);
+               if (verbose) {
+                       setup_pager();
+                       list_all_cmds_help();
+                       return 0;
+               }
                printf(_("usage: %s%s"), _(git_usage_string), "\n\n");
                load_command_list("git-", &main_cmds, &other_cmds);
                list_commands(colopts, &main_cmds, &other_cmds);
index d85f99b7817d7b536d2749ee38f2d7c434286478..6d7bbe8c9f34827c97f23e9beaffb19708db016c 100644 (file)
@@ -35,6 +35,7 @@
 #include "string-list.h"
 #include "packfile.h"
 #include "tag.h"
+#include "alias.h"
 
 #define DEFAULT_TWOHEAD (1<<0)
 #define DEFAULT_OCTOPUS (1<<1)
diff --git a/cache.h b/cache.h
index 08a48263b52b621aa9f1db1a5f5abab39c31e36a..89a107a7f79175c600eb2a9689982912541ae4e7 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -1826,11 +1826,6 @@ extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
 void overlay_tree_on_index(struct index_state *istate,
                           const char *tree_name, const char *prefix);
 
-char *alias_lookup(const char *alias);
-int split_cmdline(char *cmdline, const char ***argv);
-/* Takes a negative value returned by split_cmdline */
-const char *split_cmdline_strerror(int cmdline_errno);
-
 /* setup.c */
 struct startup_info {
        int have_repository;
index 835c5890be93abc1852dd0e1e19dbb627fee6041..e1c26c1bb7e618f6f372d9a568e7cab75612d2db 100644 (file)
@@ -1,23 +1,58 @@
-# common commands are grouped by themes
-# these groups are output by 'git help' in the order declared here.
-# map each common command in the command list to one of these groups.
-### common groups (do not change this line)
-init         start a working area (see also: git help tutorial)
-worktree     work on the current change (see also: git help everyday)
-info         examine the history and state (see also: git help revisions)
-history      grow, mark and tweak your common history
-remote       collaborate (see also: git help workflows)
-
-### command list (do not change this line)
-# command name                          category [deprecated] [common]
+# Command classification list
+# ---------------------------
+# All supported commands, builtin or external, must be described in
+# here. This info is used to list commands in various places. Each
+# command is on one line followed by one or more attributes.
+#
+# The first attribute group is mandatory and indicates the command
+# type. This group includes:
+#
+#   mainporcelain
+#   ancillarymanipulators
+#   ancillaryinterrogators
+#   foreignscminterface
+#   plumbingmanipulators
+#   plumbinginterrogators
+#   synchingrepositories
+#   synchelpers
+#   purehelpers
+#
+# The type names are self explanatory. But if you want to see what
+# command belongs to what group to get a better picture, have a look
+# at "git" man page, "GIT COMMANDS" section.
+#
+# Commands of type mainporcelain can also optionally have one of these
+# attributes:
+#
+#   init
+#   worktree
+#   info
+#   history
+#   remote
+#
+# These commands are considered "common" and will show up in "git
+# help" output in groups. Uncommon porcelain commands must not
+# specify any of these attributes.
+#
+# "complete" attribute is used to mark that the command should be
+# completable by git-completion.bash. Note that by default,
+# mainporcelain commands are completable so you don't need this
+# attribute.
+#
+# As part of the Git man page list, the man(5/7) guides are also
+# specified here, which can only have "guide" attribute and nothing
+# else.
+#
+### command list (do not change this line, also do not change alignment)
+# command name                          category [category] [category]
 git-add                                 mainporcelain           worktree
 git-am                                  mainporcelain
 git-annotate                            ancillaryinterrogators
-git-apply                               plumbingmanipulators
+git-apply                               plumbingmanipulators            complete
 git-archimport                          foreignscminterface
 git-archive                             mainporcelain
 git-bisect                              mainporcelain           info
-git-blame                               ancillaryinterrogators
+git-blame                               ancillaryinterrogators          complete
 git-branch                              mainporcelain           history
 git-bundle                              mainporcelain
 git-cat-file                            plumbinginterrogators
@@ -27,7 +62,7 @@ git-check-mailmap                       purehelpers
 git-checkout                            mainporcelain           history
 git-checkout-index                      plumbingmanipulators
 git-check-ref-format                    purehelpers
-git-cherry                              ancillaryinterrogators
+git-cherry                              ancillaryinterrogators          complete
 git-cherry-pick                         mainporcelain
 git-citool                              mainporcelain
 git-clean                               mainporcelain
@@ -36,7 +71,7 @@ git-column                              purehelpers
 git-commit                              mainporcelain           history
 git-commit-graph                        plumbingmanipulators
 git-commit-tree                         plumbingmanipulators
-git-config                              ancillarymanipulators
+git-config                              ancillarymanipulators           complete
 git-count-objects                       ancillaryinterrogators
 git-credential                          purehelpers
 git-credential-cache                    purehelpers
@@ -50,7 +85,7 @@ git-diff                                mainporcelain           history
 git-diff-files                          plumbinginterrogators
 git-diff-index                          plumbinginterrogators
 git-diff-tree                           plumbinginterrogators
-git-difftool                            ancillaryinterrogators
+git-difftool                            ancillaryinterrogators          complete
 git-fast-export                         ancillarymanipulators
 git-fast-import                         ancillarymanipulators
 git-fetch                               mainporcelain           remote
@@ -59,20 +94,20 @@ git-filter-branch                       ancillarymanipulators
 git-fmt-merge-msg                       purehelpers
 git-for-each-ref                        plumbinginterrogators
 git-format-patch                        mainporcelain
-git-fsck                                ancillaryinterrogators
+git-fsck                                ancillaryinterrogators          complete
 git-gc                                  mainporcelain
 git-get-tar-commit-id                   ancillaryinterrogators
 git-grep                                mainporcelain           info
 git-gui                                 mainporcelain
 git-hash-object                         plumbingmanipulators
-git-help                                ancillaryinterrogators
+git-help                                ancillaryinterrogators          complete
 git-http-backend                        synchingrepositories
 git-http-fetch                          synchelpers
 git-http-push                           synchelpers
 git-imap-send                           foreignscminterface
 git-index-pack                          plumbingmanipulators
 git-init                                mainporcelain           init
-git-instaweb                            ancillaryinterrogators
+git-instaweb                            ancillaryinterrogators          complete
 git-interpret-trailers                  purehelpers
 gitk                                    mainporcelain
 git-log                                 mainporcelain           info
@@ -86,7 +121,7 @@ git-merge-base                          plumbinginterrogators
 git-merge-file                          plumbingmanipulators
 git-merge-index                         plumbingmanipulators
 git-merge-one-file                      purehelpers
-git-mergetool                           ancillarymanipulators
+git-mergetool                           ancillarymanipulators           complete
 git-merge-tree                          ancillaryinterrogators
 git-mktag                               plumbingmanipulators
 git-mktree                              plumbingmanipulators
@@ -107,28 +142,29 @@ git-quiltimport                         foreignscminterface
 git-read-tree                           plumbingmanipulators
 git-rebase                              mainporcelain           history
 git-receive-pack                        synchelpers
-git-reflog                              ancillarymanipulators
-git-remote                              ancillarymanipulators
-git-repack                              ancillarymanipulators
-git-replace                             ancillarymanipulators
-git-request-pull                        foreignscminterface
+git-reflog                              ancillarymanipulators           complete
+git-remote                              ancillarymanipulators           complete
+git-repack                              ancillarymanipulators           complete
+git-replace                             ancillarymanipulators           complete
+git-request-pull                        foreignscminterface             complete
 git-rerere                              ancillaryinterrogators
 git-reset                               mainporcelain           worktree
 git-revert                              mainporcelain
 git-rev-list                            plumbinginterrogators
 git-rev-parse                           ancillaryinterrogators
 git-rm                                  mainporcelain           worktree
-git-send-email                          foreignscminterface
+git-send-email                          foreignscminterface             complete
 git-send-pack                           synchingrepositories
 git-shell                               synchelpers
 git-shortlog                            mainporcelain
 git-show                                mainporcelain           info
-git-show-branch                         ancillaryinterrogators
+git-show-branch                         ancillaryinterrogators          complete
 git-show-index                          plumbinginterrogators
 git-show-ref                            plumbinginterrogators
 git-sh-i18n                             purehelpers
 git-sh-setup                            purehelpers
 git-stash                               mainporcelain
+git-stage                                                               complete
 git-status                              mainporcelain           info
 git-stripspace                          purehelpers
 git-submodule                           mainporcelain
@@ -147,6 +183,22 @@ git-verify-commit                       ancillaryinterrogators
 git-verify-pack                         plumbinginterrogators
 git-verify-tag                          ancillaryinterrogators
 gitweb                                  ancillaryinterrogators
-git-whatchanged                         ancillaryinterrogators
+git-whatchanged                         ancillaryinterrogators          complete
 git-worktree                            mainporcelain
 git-write-tree                          plumbingmanipulators
+gitattributes                           guide
+gitcli                                  guide
+gitcore-tutorial                        guide
+gitcvs-migration                        guide
+gitdiffcore                             guide
+giteveryday                             guide
+gitglossary                             guide
+githooks                                guide
+gitignore                               guide
+gitmodules                              guide
+gitnamespaces                           guide
+gitrepository-layout                    guide
+gitrevisions                            guide
+gittutorial-2                           guide
+gittutorial                             guide
+gitworkflows                            guide
index 31aa9c843311b4e0b01e7378a85709083b071311..968e91b18c09e5ac814328e0f833e2d4aa91cf2c 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -14,6 +14,7 @@
 #include "strbuf.h"
 #include "version.h"
 #include "protocol.h"
+#include "alias.h"
 
 static char *server_capabilities_v1;
 static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT;
index 1491b7239be11cd04c257aabc42944569b806f70..12814e9bbf6be5ff0d1608c71554c2b4bb14c87d 100644 (file)
@@ -989,127 +989,11 @@ __git_complete_strategy ()
        return 1
 }
 
-__git_commands () {
-       if test -n "${GIT_TESTING_COMMAND_COMPLETION:-}"
-       then
-               printf "%s" "${GIT_TESTING_COMMAND_COMPLETION}"
-       else
-               git help -a|egrep '^  [a-zA-Z0-9]'
-       fi
-}
-
-__git_list_all_commands ()
-{
-       local i IFS=" "$'\n'
-       for i in $(__git_commands)
-       do
-               case $i in
-               *--*)             : helper pattern;;
-               *) echo $i;;
-               esac
-       done
-}
-
 __git_all_commands=
 __git_compute_all_commands ()
 {
        test -n "$__git_all_commands" ||
-       __git_all_commands=$(__git_list_all_commands)
-}
-
-__git_list_porcelain_commands ()
-{
-       local i IFS=" "$'\n'
-       __git_compute_all_commands
-       for i in $__git_all_commands
-       do
-               case $i in
-               *--*)             : helper pattern;;
-               applymbox)        : ask gittus;;
-               applypatch)       : ask gittus;;
-               archimport)       : import;;
-               cat-file)         : plumbing;;
-               check-attr)       : plumbing;;
-               check-ignore)     : plumbing;;
-               check-mailmap)    : plumbing;;
-               check-ref-format) : plumbing;;
-               checkout-index)   : plumbing;;
-               column)           : internal helper;;
-               commit-graph)     : plumbing;;
-               commit-tree)      : plumbing;;
-               count-objects)    : infrequent;;
-               credential)       : credentials;;
-               credential-*)     : credentials helper;;
-               cvsexportcommit)  : export;;
-               cvsimport)        : import;;
-               cvsserver)        : daemon;;
-               daemon)           : daemon;;
-               diff-files)       : plumbing;;
-               diff-index)       : plumbing;;
-               diff-tree)        : plumbing;;
-               fast-import)      : import;;
-               fast-export)      : export;;
-               fsck-objects)     : plumbing;;
-               fetch-pack)       : plumbing;;
-               fmt-merge-msg)    : plumbing;;
-               for-each-ref)     : plumbing;;
-               hash-object)      : plumbing;;
-               http-*)           : transport;;
-               index-pack)       : plumbing;;
-               init-db)          : deprecated;;
-               local-fetch)      : plumbing;;
-               ls-files)         : plumbing;;
-               ls-remote)        : plumbing;;
-               ls-tree)          : plumbing;;
-               mailinfo)         : plumbing;;
-               mailsplit)        : plumbing;;
-               merge-*)          : plumbing;;
-               mktree)           : plumbing;;
-               mktag)            : plumbing;;
-               pack-objects)     : plumbing;;
-               pack-redundant)   : plumbing;;
-               pack-refs)        : plumbing;;
-               parse-remote)     : plumbing;;
-               patch-id)         : plumbing;;
-               prune)            : plumbing;;
-               prune-packed)     : plumbing;;
-               quiltimport)      : import;;
-               read-tree)        : plumbing;;
-               receive-pack)     : plumbing;;
-               remote-*)         : transport;;
-               rerere)           : plumbing;;
-               rev-list)         : plumbing;;
-               rev-parse)        : plumbing;;
-               runstatus)        : plumbing;;
-               sh-setup)         : internal;;
-               shell)            : daemon;;
-               show-ref)         : plumbing;;
-               send-pack)        : plumbing;;
-               show-index)       : plumbing;;
-               ssh-*)            : transport;;
-               stripspace)       : plumbing;;
-               symbolic-ref)     : plumbing;;
-               unpack-file)      : plumbing;;
-               unpack-objects)   : plumbing;;
-               update-index)     : plumbing;;
-               update-ref)       : plumbing;;
-               update-server-info) : daemon;;
-               upload-archive)   : plumbing;;
-               upload-pack)      : plumbing;;
-               write-tree)       : plumbing;;
-               var)              : infrequent;;
-               verify-pack)      : infrequent;;
-               verify-tag)       : plumbing;;
-               *) echo $i;;
-               esac
-       done
-}
-
-__git_porcelain_commands=
-__git_compute_porcelain_commands ()
-{
-       test -n "$__git_porcelain_commands" ||
-       __git_porcelain_commands=$(__git_list_porcelain_commands)
+       __git_all_commands=$(git --list-cmds=main,others,alias,nohelpers)
 }
 
 # Lists all set config variables starting with the given section prefix,
@@ -1127,11 +1011,6 @@ __git_pretty_aliases ()
        __git_get_config_variables "pretty"
 }
 
-__git_aliases ()
-{
-       __git_get_config_variables "alias"
-}
-
 # __git_aliased_command requires 1 argument
 __git_aliased_command ()
 {
@@ -1739,13 +1618,12 @@ _git_help ()
                return
                ;;
        esac
-       __git_compute_all_commands
-       __gitcomp "$__git_all_commands $(__git_aliases)
-               attributes cli core-tutorial cvs-migration
-               diffcore everyday gitk glossary hooks ignore modules
-               namespaces repository-layout revisions tutorial tutorial-2
-               workflows
-               "
+       if test -n "$GIT_TESTING_ALL_COMMAND_LIST"
+       then
+               __gitcomp "$GIT_TESTING_ALL_COMMAND_LIST $(git --list-cmds=alias,list-guide) gitk"
+       else
+               __gitcomp "$(git --list-cmds=main,nohelpers,alias,list-guide) gitk"
+       fi
 }
 
 _git_init ()
@@ -3214,7 +3092,7 @@ __git_complete_common () {
 __git_cmds_with_parseopt_helper=
 __git_support_parseopt_helper () {
        test -n "$__git_cmds_with_parseopt_helper" ||
-               __git_cmds_with_parseopt_helper="$(__git --list-parseopt-builtins)"
+               __git_cmds_with_parseopt_helper="$(__git --list-cmds=parseopt)"
 
        case " $__git_cmds_with_parseopt_helper " in
        *" $1 "*)
@@ -3300,8 +3178,14 @@ __git_main ()
                        --help
                        "
                        ;;
-               *)     __git_compute_porcelain_commands
-                      __gitcomp "$__git_porcelain_commands $(__git_aliases)" ;;
+               *)
+                       if test -n "$GIT_TESTING_PORCELAIN_COMMAND_LIST"
+                       then
+                               __gitcomp "$GIT_TESTING_PORCELAIN_COMMAND_LIST"
+                       else
+                               __gitcomp "$(git --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config)"
+                       fi
+                       ;;
                esac
                return
        fi
index eeea4b67ea7f1ccee1770c18a36d018b5f3b32b0..8d6d8b45ceb0138797eb7e54b15f7546925598ed 100755 (executable)
@@ -1,50 +1,90 @@
 #!/bin/sh
 
-echo "/* Automatically generated by generate-cmdlist.sh */
-struct cmdname_help {
-       char name[16];
-       char help[80];
-       unsigned char group;
-};
+die () {
+       echo "$@" >&2
+       exit 1
+}
+
+command_list () {
+       grep -v '^#' "$1"
+}
 
-static const char *common_cmd_groups[] = {"
-
-grps=grps$$.tmp
-match=match$$.tmp
-trap "rm -f '$grps' '$match'" 0 1 2 3 15
-
-sed -n '
-       1,/^### common groups/b
-       /^### command list/q
-       /^#/b
-       /^[     ]*$/b
-       h;s/^[^         ][^     ]*[     ][      ]*\(.*\)/       N_("\1"),/p
-       g;s/^\([^       ][^     ]*\)[   ].*/\1/w '$grps'
-       ' "$1"
-printf '};\n\n'
-
-n=0
-substnum=
-while read grp
-do
-       echo "^git-..*[         ]$grp"
-       substnum="$substnum${substnum:+;}s/[    ]$grp/$n/"
-       n=$(($n+1))
-done <"$grps" >"$match"
-
-printf 'static struct cmdname_help common_cmds[] = {\n'
-grep -f "$match" "$1" |
-sed 's/^git-//' |
-sort |
-while read cmd tags
-do
-       tag=$(echo "$tags" | sed "$substnum; s/[^0-9]//g")
+get_categories () {
+       tr ' ' '\n'|
+       grep -v '^$' |
+       sort |
+       uniq
+}
+
+category_list () {
+       command_list "$1" |
+       cut -c 40- |
+       get_categories
+}
+
+get_synopsis () {
        sed -n '
-               /^NAME/,/git-'"$cmd"'/H
+               /^NAME/,/'"$1"'/H
                ${
                        x
-                       s/.*git-'"$cmd"' - \(.*\)/      {"'"$cmd"'", N_("\1"), '$tag'},/
+                       s/.*'"$1"' - \(.*\)/N_("\1")/
                        p
-               }' "Documentation/git-$cmd.txt"
-done
-echo "};"
+               }' "Documentation/$1.txt"
+}
+
+define_categories () {
+       echo
+       echo "/* Command categories */"
+       bit=0
+       category_list "$1" |
+       while read cat
+       do
+               echo "#define CAT_$cat (1UL << $bit)"
+               bit=$(($bit+1))
+       done
+       test "$bit" -gt 32 && die "Urgh.. too many categories?"
+}
+
+define_category_names () {
+       echo
+       echo "/* Category names */"
+       echo "static const char *category_names[] = {"
+       bit=0
+       category_list "$1" |
+       while read cat
+       do
+               echo "  \"$cat\", /* (1UL << $bit) */"
+               bit=$(($bit+1))
+       done
+       echo "  NULL"
+       echo "};"
+}
+
+print_command_list () {
+       echo "static struct cmdname_help command_list[] = {"
+
+       command_list "$1" |
+       while read cmd rest
+       do
+               printf "        { \"$cmd\", $(get_synopsis $cmd), 0"
+               for cat in $(echo "$rest" | get_categories)
+               do
+                       printf " | CAT_$cat"
+               done
+               echo " },"
+       done
+       echo "};"
+}
+
+echo "/* Automatically generated by generate-cmdlist.sh */
+struct cmdname_help {
+       const char *name;
+       const char *help;
+       uint32_t category;
+};
+"
+define_categories "$1"
+echo
+define_category_names "$1"
+echo
+print_command_list "$1"
diff --git a/git.c b/git.c
index 5771d62a328d69692291674c7ed0f9050efac3ca..c2f48d53dd4aaba0752aa5f2e6633242d320b248 100644 (file)
--- a/git.c
+++ b/git.c
@@ -3,6 +3,7 @@
 #include "exec-cmd.h"
 #include "help.h"
 #include "run-command.h"
+#include "alias.h"
 
 #define RUN_SETUP              (1<<0)
 #define RUN_SETUP_GENTLY       (1<<1)
@@ -36,7 +37,66 @@ const char git_more_info_string[] =
 
 static int use_pager = -1;
 
-static void list_builtins(unsigned int exclude_option, char sep);
+static void list_builtins(struct string_list *list, unsigned int exclude_option);
+
+static void exclude_helpers_from_list(struct string_list *list)
+{
+       int i = 0;
+
+       while (i < list->nr) {
+               if (strstr(list->items[i].string, "--"))
+                       unsorted_string_list_delete_item(list, i, 0);
+               else
+                       i++;
+       }
+}
+
+static int match_token(const char *spec, int len, const char *token)
+{
+       int token_len = strlen(token);
+
+       return len == token_len && !strncmp(spec, token, token_len);
+}
+
+static int list_cmds(const char *spec)
+{
+       struct string_list list = STRING_LIST_INIT_DUP;
+       int i;
+
+       while (*spec) {
+               const char *sep = strchrnul(spec, ',');
+               int len = sep - spec;
+
+               if (match_token(spec, len, "builtins"))
+                       list_builtins(&list, 0);
+               else if (match_token(spec, len, "main"))
+                       list_all_main_cmds(&list);
+               else if (match_token(spec, len, "others"))
+                       list_all_other_cmds(&list);
+               else if (match_token(spec, len, "nohelpers"))
+                       exclude_helpers_from_list(&list);
+               else if (match_token(spec, len, "alias"))
+                       list_aliases(&list);
+               else if (match_token(spec, len, "config"))
+                       list_cmds_by_config(&list);
+               else if (len > 5 && !strncmp(spec, "list-", 5)) {
+                       struct strbuf sb = STRBUF_INIT;
+
+                       strbuf_add(&sb, spec + 5, len - 5);
+                       list_cmds_by_category(&list, sb.buf);
+                       strbuf_release(&sb);
+               }
+               else
+                       die(_("unsupported command listing type '%s'"), spec);
+               spec += len;
+               if (*spec == ',')
+                       spec++;
+       }
+       for (i = 0; i < list.nr; i++)
+               puts(list.items[i].string);
+       string_list_clear(&list, 0);
+       return 0;
+}
 
 static void commit_pager_choice(void) {
        switch (use_pager) {
@@ -223,12 +283,19 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
                        }
                        (*argv)++;
                        (*argc)--;
-               } else if (!strcmp(cmd, "--list-builtins")) {
-                       list_builtins(0, '\n');
-                       exit(0);
-               } else if (!strcmp(cmd, "--list-parseopt-builtins")) {
-                       list_builtins(NO_PARSEOPT, ' ');
-                       exit(0);
+               } else if (skip_prefix(cmd, "--list-cmds=", &cmd)) {
+                       if (!strcmp(cmd, "parseopt")) {
+                               struct string_list list = STRING_LIST_INIT_DUP;
+                               int i;
+
+                               list_builtins(&list, NO_PARSEOPT);
+                               for (i = 0; i < list.nr; i++)
+                                       printf("%s ", list.items[i].string);
+                               string_list_clear(&list, 0);
+                               exit(0);
+                       } else {
+                               exit(list_cmds(cmd));
+                       }
                } else {
                        fprintf(stderr, _("unknown option: %s\n"), cmd);
                        usage(git_usage_string);
@@ -511,14 +578,14 @@ int is_builtin(const char *s)
        return !!get_builtin(s);
 }
 
-static void list_builtins(unsigned int exclude_option, char sep)
+static void list_builtins(struct string_list *out, unsigned int exclude_option)
 {
        int i;
        for (i = 0; i < ARRAY_SIZE(commands); i++) {
                if (exclude_option &&
                    (commands[i].option & exclude_option))
                        continue;
-               printf("%s%c", commands[i].cmd, sep);
+               string_list_append(out, commands[i].cmd);
        }
 }
 
diff --git a/help.c b/help.c
index a4feef2ffe90ae853c220b9368642c4edb503e5e..dd35fcc133094e4dc89898463868e89162637076 100644 (file)
--- a/help.c
+++ b/help.c
 #include "run-command.h"
 #include "levenshtein.h"
 #include "help.h"
-#include "common-cmds.h"
+#include "command-list.h"
 #include "string-list.h"
 #include "column.h"
 #include "version.h"
 #include "refs.h"
 #include "parse-options.h"
 
+struct category_description {
+       uint32_t category;
+       const char *desc;
+};
+static uint32_t common_mask =
+       CAT_init | CAT_worktree | CAT_info |
+       CAT_history | CAT_remote;
+static struct category_description common_categories[] = {
+       { CAT_init, N_("start a working area (see also: git help tutorial)") },
+       { CAT_worktree, N_("work on the current change (see also: git help everyday)") },
+       { CAT_info, N_("examine the history and state (see also: git help revisions)") },
+       { CAT_history, N_("grow, mark and tweak your common history") },
+       { CAT_remote, N_("collaborate (see also: git help workflows)") },
+       { 0, NULL }
+};
+static struct category_description main_categories[] = {
+       { CAT_mainporcelain, N_("Main Porcelain Commands") },
+       { CAT_ancillarymanipulators, N_("Ancillary Commands / Manipulators") },
+       { CAT_ancillaryinterrogators, N_("Ancillary Commands / Interrogators") },
+       { CAT_foreignscminterface, N_("Interacting with Others") },
+       { CAT_plumbingmanipulators, N_("Low-level Commands / Manipulators") },
+       { CAT_plumbinginterrogators, N_("Low-level Commands / Interrogators") },
+       { CAT_synchingrepositories, N_("Low-level Commands / Synching Repositories") },
+       { CAT_purehelpers, N_("Low-level Commands / Internal Helpers") },
+       { 0, NULL }
+};
+
+static const char *drop_prefix(const char *name, uint32_t category)
+{
+       const char *new_name;
+
+       if (skip_prefix(name, "git-", &new_name))
+               return new_name;
+       if (category == CAT_guide && skip_prefix(name, "git", &new_name))
+               return new_name;
+       return name;
+
+}
+
+static void extract_cmds(struct cmdname_help **p_cmds, uint32_t mask)
+{
+       int i, nr = 0;
+       struct cmdname_help *cmds;
+
+       if (ARRAY_SIZE(command_list) == 0)
+               BUG("empty command_list[] is a sign of broken generate-cmdlist.sh");
+
+       ALLOC_ARRAY(cmds, ARRAY_SIZE(command_list) + 1);
+
+       for (i = 0; i < ARRAY_SIZE(command_list); i++) {
+               const struct cmdname_help *cmd = command_list + i;
+
+               if (!(cmd->category & mask))
+                       continue;
+
+               cmds[nr] = *cmd;
+               cmds[nr].name = drop_prefix(cmd->name, cmd->category);
+
+               nr++;
+       }
+       cmds[nr].name = NULL;
+       *p_cmds = cmds;
+}
+
+static void print_command_list(const struct cmdname_help *cmds,
+                              uint32_t mask, int longest)
+{
+       int i;
+
+       for (i = 0; cmds[i].name; i++) {
+               if (cmds[i].category & mask) {
+                       printf("   %s   ", cmds[i].name);
+                       mput_char(' ', longest - strlen(cmds[i].name));
+                       puts(_(cmds[i].help));
+               }
+       }
+}
+
+static int cmd_name_cmp(const void *elem1, const void *elem2)
+{
+       const struct cmdname_help *e1 = elem1;
+       const struct cmdname_help *e2 = elem2;
+
+       return strcmp(e1->name, e2->name);
+}
+
+static void print_cmd_by_category(const struct category_description *catdesc)
+{
+       struct cmdname_help *cmds;
+       int longest = 0;
+       int i, nr = 0;
+       uint32_t mask = 0;
+
+       for (i = 0; catdesc[i].desc; i++)
+               mask |= catdesc[i].category;
+
+       extract_cmds(&cmds, mask);
+
+       for (i = 0; cmds[i].name; i++, nr++) {
+               if (longest < strlen(cmds[i].name))
+                       longest = strlen(cmds[i].name);
+       }
+       QSORT(cmds, nr, cmd_name_cmp);
+
+       for (i = 0; catdesc[i].desc; i++) {
+               uint32_t mask = catdesc[i].category;
+               const char *desc = catdesc[i].desc;
+
+               printf("\n%s\n", _(desc));
+               print_command_list(cmds, mask, longest);
+       }
+       free(cmds);
+}
+
 void add_cmdname(struct cmdnames *cmds, const char *name, int len)
 {
        struct cmdname *ent;
@@ -190,44 +304,116 @@ void list_commands(unsigned int colopts,
        }
 }
 
-static int cmd_group_cmp(const void *elem1, const void *elem2)
+void list_common_cmds_help(void)
 {
-       const struct cmdname_help *e1 = elem1;
-       const struct cmdname_help *e2 = elem2;
+       puts(_("These are common Git commands used in various situations:"));
+       print_cmd_by_category(common_categories);
+}
 
-       if (e1->group < e2->group)
-               return -1;
-       if (e1->group > e2->group)
-               return 1;
-       return strcmp(e1->name, e2->name);
+void list_all_main_cmds(struct string_list *list)
+{
+       struct cmdnames main_cmds, other_cmds;
+       int i;
+
+       memset(&main_cmds, 0, sizeof(main_cmds));
+       memset(&other_cmds, 0, sizeof(other_cmds));
+       load_command_list("git-", &main_cmds, &other_cmds);
+
+       for (i = 0; i < main_cmds.cnt; i++)
+               string_list_append(list, main_cmds.names[i]->name);
+
+       clean_cmdnames(&main_cmds);
+       clean_cmdnames(&other_cmds);
 }
 
-void list_common_cmds_help(void)
+void list_all_other_cmds(struct string_list *list)
 {
-       int i, longest = 0;
-       int current_grp = -1;
+       struct cmdnames main_cmds, other_cmds;
+       int i;
 
-       for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
-               if (longest < strlen(common_cmds[i].name))
-                       longest = strlen(common_cmds[i].name);
-       }
+       memset(&main_cmds, 0, sizeof(main_cmds));
+       memset(&other_cmds, 0, sizeof(other_cmds));
+       load_command_list("git-", &main_cmds, &other_cmds);
 
-       QSORT(common_cmds, ARRAY_SIZE(common_cmds), cmd_group_cmp);
+       for (i = 0; i < other_cmds.cnt; i++)
+               string_list_append(list, other_cmds.names[i]->name);
 
-       puts(_("These are common Git commands used in various situations:"));
+       clean_cmdnames(&main_cmds);
+       clean_cmdnames(&other_cmds);
+}
+
+void list_cmds_by_category(struct string_list *list,
+                          const char *cat)
+{
+       int i, n = ARRAY_SIZE(command_list);
+       uint32_t cat_id = 0;
 
-       for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
-               if (common_cmds[i].group != current_grp) {
-                       printf("\n%s\n", _(common_cmd_groups[common_cmds[i].group]));
-                       current_grp = common_cmds[i].group;
+       for (i = 0; category_names[i]; i++) {
+               if (!strcmp(cat, category_names[i])) {
+                       cat_id = 1UL << i;
+                       break;
                }
+       }
+       if (!cat_id)
+               die(_("unsupported command listing type '%s'"), cat);
+
+       for (i = 0; i < n; i++) {
+               struct cmdname_help *cmd = command_list + i;
 
-               printf("   %s   ", common_cmds[i].name);
-               mput_char(' ', longest - strlen(common_cmds[i].name));
-               puts(_(common_cmds[i].help));
+               if (!(cmd->category & cat_id))
+                       continue;
+               string_list_append(list, drop_prefix(cmd->name, cmd->category));
        }
 }
 
+void list_cmds_by_config(struct string_list *list)
+{
+       const char *cmd_list;
+
+       /*
+        * There's no actual repository setup at this point (and even
+        * if there is, we don't really care; only global config
+        * matters). If we accidentally set up a repository, it's ok
+        * too since the caller (git --list-cmds=) should exit shortly
+        * anyway.
+        */
+       if (git_config_get_string_const("completion.commands", &cmd_list))
+               return;
+
+       string_list_sort(list);
+       string_list_remove_duplicates(list, 0);
+
+       while (*cmd_list) {
+               struct strbuf sb = STRBUF_INIT;
+               const char *p = strchrnul(cmd_list, ' ');
+
+               strbuf_add(&sb, cmd_list, p - cmd_list);
+               if (*cmd_list == '-')
+                       string_list_remove(list, cmd_list + 1, 0);
+               else
+                       string_list_insert(list, sb.buf);
+               strbuf_release(&sb);
+               while (*p == ' ')
+                       p++;
+               cmd_list = p;
+       }
+}
+
+void list_common_guides_help(void)
+{
+       struct category_description catdesc[] = {
+               { CAT_guide, N_("The common Git guides are:") },
+               { 0, NULL }
+       };
+       print_cmd_by_category(catdesc);
+       putchar('\n');
+}
+
+void list_all_cmds_help(void)
+{
+       print_cmd_by_category(main_categories);
+}
+
 int is_in_cmdlist(struct cmdnames *c, const char *s)
 {
        int i;
@@ -285,6 +471,7 @@ const char *help_unknown_cmd(const char *cmd)
 {
        int i, n, best_similarity = 0;
        struct cmdnames main_cmds, other_cmds;
+       struct cmdname_help *common_cmds;
 
        memset(&main_cmds, 0, sizeof(main_cmds));
        memset(&other_cmds, 0, sizeof(other_cmds));
@@ -299,6 +486,8 @@ const char *help_unknown_cmd(const char *cmd)
        QSORT(main_cmds.names, main_cmds.cnt, cmdname_compare);
        uniq(&main_cmds);
 
+       extract_cmds(&common_cmds, common_mask);
+
        /* This abuses cmdname->len for levenshtein distance */
        for (i = 0, n = 0; i < main_cmds.cnt; i++) {
                int cmp = 0; /* avoid compiler stupidity */
@@ -313,10 +502,10 @@ const char *help_unknown_cmd(const char *cmd)
                        die(_(bad_interpreter_advice), cmd, cmd);
 
                /* Does the candidate appear in common_cmds list? */
-               while (n < ARRAY_SIZE(common_cmds) &&
+               while (common_cmds[n].name &&
                       (cmp = strcmp(common_cmds[n].name, candidate)) < 0)
                        n++;
-               if ((n < ARRAY_SIZE(common_cmds)) && !cmp) {
+               if (common_cmds[n].name && !cmp) {
                        /* Yes, this is one of the common commands */
                        n++; /* use the entry from common_cmds[] */
                        if (starts_with(candidate, cmd)) {
@@ -329,6 +518,7 @@ const char *help_unknown_cmd(const char *cmd)
                main_cmds.names[i]->len =
                        levenshtein(cmd, candidate, 0, 2, 1, 3) + 1;
        }
+       FREE_AND_NULL(common_cmds);
 
        QSORT(main_cmds.names, main_cmds.cnt, levenshtein_compare);
 
diff --git a/help.h b/help.h
index b21d7c94e8ce429ac1f58bd566c69e154d84d6a0..3b38292a1b317ba32d934be6006cb86e0e7d0d94 100644 (file)
--- a/help.h
+++ b/help.h
@@ -1,6 +1,8 @@
 #ifndef HELP_H
 #define HELP_H
 
+struct string_list;
+
 struct cmdnames {
        int alloc;
        int cnt;
@@ -17,6 +19,14 @@ static inline void mput_char(char c, unsigned int num)
 }
 
 extern void list_common_cmds_help(void);
+extern void list_all_cmds_help(void);
+extern void list_common_guides_help(void);
+
+extern void list_all_main_cmds(struct string_list *list);
+extern void list_all_other_cmds(struct string_list *list);
+extern void list_cmds_by_category(struct string_list *list,
+                                 const char *category);
+extern void list_cmds_by_config(struct string_list *list);
 extern const char *help_unknown_cmd(const char *cmd);
 extern void load_command_list(const char *prefix,
                              struct cmdnames *main_cmds,
diff --git a/pager.c b/pager.c
index 226828f178a0c1a876710326634e83288863af3d..a768797fcfcc44de4dbe4d983a45ade8c81b2e1c 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -2,6 +2,7 @@
 #include "config.h"
 #include "run-command.h"
 #include "sigchain.h"
+#include "alias.h"
 
 #ifndef DEFAULT_PAGER
 #define DEFAULT_PAGER "less"
index 72b4d8ecae3b07e2259cf05c4a8f4acdb46eae0a..560fc9b67d480069328d379421c606d800e82135 100644 (file)
@@ -27,6 +27,7 @@
 #include "worktree.h"
 #include "oidmap.h"
 #include "oidset.h"
+#include "alias.h"
 
 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
 
diff --git a/shell.c b/shell.c
index 0200d10796c43d6ea1249c314ee158f2b57a481f..40084a30130ef844899bc1f3321285afdda82607 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -3,6 +3,7 @@
 #include "exec-cmd.h"
 #include "strbuf.h"
 #include "run-command.h"
+#include "alias.h"
 
 #define COMMAND_DIR "git-shell-commands"
 #define HELP_COMMAND COMMAND_DIR "/help"
index 487b92a5de3238821ed3d8aadadb1f07d35e0609..bc27df7f383d14fb5fea6266591469c32e562c4e 100755 (executable)
@@ -25,6 +25,15 @@ test_expect_success "setup" '
        EOF
 '
 
+# make sure to exercise these code paths, the output is a bit tricky
+# to verify
+test_expect_success 'basic help commands' '
+       git help >/dev/null &&
+       git help -a >/dev/null &&
+       git help -g >/dev/null &&
+       git help -av >/dev/null
+'
+
 test_expect_success "works for commands and guides by default" '
        configure_help &&
        git help status &&
@@ -49,8 +58,23 @@ test_expect_success "--help does not work for guides" "
        test_i18ncmp expect actual
 "
 
+test_expect_success 'git help' '
+       git help >help.output &&
+       test_i18ngrep "^   clone  " help.output &&
+       test_i18ngrep "^   add    " help.output &&
+       test_i18ngrep "^   log    " help.output &&
+       test_i18ngrep "^   commit " help.output &&
+       test_i18ngrep "^   fetch  " help.output
+'
+test_expect_success 'git help -g' '
+       git help -g >help.output &&
+       test_i18ngrep "^   attributes " help.output &&
+       test_i18ngrep "^   everyday   " help.output &&
+       test_i18ngrep "^   tutorial   " help.output
+'
+
 test_expect_success 'generate builtin list' '
-       git --list-builtins >builtins
+       git --list-cmds=builtins >builtins
 '
 
 while read builtin
index 1b6d27525454a1d14da91f53d45e39a659e48e36..36deb0b123cf501d4acd2c9ec26ff3acef21bc87 100755 (executable)
@@ -13,7 +13,7 @@ complete ()
        return 0
 }
 
-# Be careful when updating this list:
+# Be careful when updating these lists:
 #
 # (1) The build tree may have build artifact from different branch, or
 #     the user's $PATH may have a random executable that may begin
@@ -30,7 +30,8 @@ complete ()
 #     completion for "git <TAB>", and a plumbing is excluded.  "add",
 #     "filter-branch" and "ls-files" are listed for this.
 
-GIT_TESTING_COMMAND_COMPLETION='add checkout check-attr filter-branch ls-files'
+GIT_TESTING_ALL_COMMAND_LIST='add checkout check-attr filter-branch ls-files'
+GIT_TESTING_PORCELAIN_COMMAND_LIST='add checkout filter-branch'
 
 . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash"
 
@@ -1350,17 +1351,6 @@ test_expect_success '__git_pretty_aliases' '
        test_cmp expect actual
 '
 
-test_expect_success '__git_aliases' '
-       cat >expect <<-EOF &&
-       ci
-       co
-       EOF
-       test_config alias.ci commit &&
-       test_config alias.co checkout &&
-       __git_aliases >actual &&
-       test_cmp expect actual
-'
-
 test_expect_success 'basic' '
        run_completion "git " &&
        # built-in
@@ -1670,13 +1660,6 @@ test_expect_success 'sourcing the completion script clears cached commands' '
        verbose test -z "$__git_all_commands"
 '
 
-test_expect_success 'sourcing the completion script clears cached porcelain commands' '
-       __git_compute_porcelain_commands &&
-       verbose test -n "$__git_porcelain_commands" &&
-       . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
-       verbose test -z "$__git_porcelain_commands"
-'
-
 test_expect_success !GETTEXT_POISON 'sourcing the completion script clears cached merge strategies' '
        __git_compute_merge_strategies &&
        verbose test -n "$__git_merge_strategies" &&