1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-28 10:26:25 +02:00

Merge branch 'nd/command-list'

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
This commit is contained in:
Junio C Hamano 2018-06-01 15:06:37 +09:00
commit 2289880f78
25 changed files with 597 additions and 321 deletions

2
.gitignore vendored
View File

@ -182,7 +182,7 @@
/gitweb/gitweb.cgi /gitweb/gitweb.cgi
/gitweb/static/gitweb.js /gitweb/static/gitweb.js
/gitweb/static/gitweb.min.* /gitweb/static/gitweb.min.*
/common-cmds.h /command-list.h
*.tar.gz *.tar.gz
*.dsc *.dsc
*.deb *.deb

View File

@ -1412,6 +1412,14 @@ credential.<url>.*::
credentialCache.ignoreSIGHUP:: credentialCache.ignoreSIGHUP::
Tell git-credential-cache--daemon to ignore SIGHUP, instead of quitting. 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[] include::diff-config.txt[]
difftool.<tool>.path:: difftool.<tool>.path::

View File

@ -8,7 +8,7 @@ git-help - Display help information about Git
SYNOPSIS SYNOPSIS
-------- --------
[verse] [verse]
'git help' [-a|--all] [-g|--guide] 'git help' [-a|--all [--verbose]] [-g|--guide]
[-i|--info|-m|--man|-w|--web] [COMMAND|GUIDE] [-i|--info|-m|--man|-w|--web] [COMMAND|GUIDE]
DESCRIPTION DESCRIPTION
@ -42,6 +42,8 @@ OPTIONS
--all:: --all::
Prints all the available commands on the standard output. This Prints all the available commands on the standard output. This
option overrides any given command or guide name. option overrides any given command or guide name.
When used with `--verbose` print description for all recognized
commands.
-g:: -g::
--guides:: --guides::

View 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 Do not perform optional operations that require locks. This is
equivalent to setting the `GIT_OPTIONAL_LOCKS` to `0`. 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 GIT COMMANDS
------------ ------------

View File

@ -3,7 +3,7 @@ gitattributes(5)
NAME NAME
---- ----
gitattributes - defining attributes per path gitattributes - Defining attributes per path
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ gitmodules(5)
NAME NAME
---- ----
gitmodules - defining submodule properties gitmodules - Defining submodule properties
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ gitrevisions(7)
NAME NAME
---- ----
gitrevisions - specifying revisions and ranges for Git gitrevisions - Specifying revisions and ranges for Git
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -795,7 +795,7 @@ LIB_FILE = libgit.a
XDIFF_LIB = xdiff/lib.a XDIFF_LIB = xdiff/lib.a
VCSSVN_LIB = vcs-svn/lib.a VCSSVN_LIB = vcs-svn/lib.a
GENERATED_H += common-cmds.h GENERATED_H += command-list.h
LIB_H = $(shell $(FIND) . \ LIB_H = $(shell $(FIND) . \
-name .git -prune -o \ -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) \ $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
$(filter %.o,$^) $(LIBS) $(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 = \ builtin/help.sp builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
'-DGIT_HTML_PATH="$(htmldir_relative_SQ)"' \ '-DGIT_HTML_PATH="$(htmldir_relative_SQ)"' \
'-DGIT_MAN_PATH="$(mandir_relative_SQ)"' \ '-DGIT_MAN_PATH="$(mandir_relative_SQ)"' \
@ -2027,9 +2027,9 @@ $(BUILT_INS): git$X
ln -s $< $@ 2>/dev/null || \ ln -s $< $@ 2>/dev/null || \
cp $< $@ 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 $@+ $@ $(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh command-list.txt >$@+ && mv $@+ $@
SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\ SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
@ -2273,7 +2273,7 @@ else
# Dependencies on header files, for platforms that do not support # Dependencies on header files, for platforms that do not support
# the gcc -MMD option. # 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 # should _not_ be included here, since they are necessary even when
# building an object for the first time. # building an object for the first time.
@ -2653,7 +2653,7 @@ sparse: $(SP_OBJ)
style: style:
git clang-format --style file --diff --extensions c,h git clang-format --style file --diff --extensions c,h
check: common-cmds.h check: command-list.h
@if sparse; \ @if sparse; \
then \ then \
echo >&2 "Use 'make sparse' instead"; \ echo >&2 "Use 'make sparse' instead"; \
@ -2901,7 +2901,7 @@ clean: profile-clean coverage-clean
$(RM) $(TEST_PROGRAMS) $(NO_INSTALL) $(RM) $(TEST_PROGRAMS) $(NO_INSTALL)
$(RM) -r bin-wrappers $(dep_dirs) $(RM) -r bin-wrappers $(dep_dirs)
$(RM) -r po/build/ $(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) -r $(GIT_TARNAME) .doc-tmp-dir
$(RM) $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz $(RM) $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
$(RM) $(htmldocs).tar.gz $(manpages).tar.gz $(RM) $(htmldocs).tar.gz $(manpages).tar.gz

22
alias.c
View File

@ -1,9 +1,12 @@
#include "cache.h" #include "cache.h"
#include "alias.h"
#include "config.h" #include "config.h"
#include "string-list.h"
struct config_alias_data { struct config_alias_data {
const char *alias; const char *alias;
char *v; char *v;
struct string_list *list;
}; };
static int config_alias_cb(const char *key, const char *value, void *d) 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; struct config_alias_data *data = d;
const char *p; const char *p;
if (skip_prefix(key, "alias.", &p) && !strcasecmp(p, data->alias)) if (!skip_prefix(key, "alias.", &p))
return git_config_string((const char **)&data->v, key, value); 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; return 0;
} }
@ -26,6 +37,13 @@ char *alias_lookup(const char *alias)
return data.v; 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_BAD_ENDING 1
#define SPLIT_CMDLINE_UNCLOSED_QUOTE 2 #define SPLIT_CMDLINE_UNCLOSED_QUOTE 2
static const char *split_cmdline_errors[] = { static const char *split_cmdline_errors[] = {

12
alias.h Normal file
View File

@ -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

View File

@ -9,6 +9,7 @@
#include "run-command.h" #include "run-command.h"
#include "column.h" #include "column.h"
#include "help.h" #include "help.h"
#include "alias.h"
#ifndef DEFAULT_HELP_FORMAT #ifndef DEFAULT_HELP_FORMAT
#define DEFAULT_HELP_FORMAT "man" #define DEFAULT_HELP_FORMAT "man"
@ -36,6 +37,7 @@ static const char *html_path;
static int show_all = 0; static int show_all = 0;
static int show_guides = 0; static int show_guides = 0;
static int verbose;
static unsigned int colopts; static unsigned int colopts;
static enum help_format help_format = HELP_FORMAT_NONE; static enum help_format help_format = HELP_FORMAT_NONE;
static int exclude_guides; static int exclude_guides;
@ -48,6 +50,7 @@ static struct option builtin_help_options[] = {
HELP_FORMAT_WEB), HELP_FORMAT_WEB),
OPT_SET_INT('i', "info", &help_format, N_("show info page"), OPT_SET_INT('i', "info", &help_format, N_("show info page"),
HELP_FORMAT_INFO), HELP_FORMAT_INFO),
OPT__VERBOSE(&verbose, N_("print command description")),
OPT_END(), OPT_END(),
}; };
@ -400,38 +403,6 @@ static void show_html_page(const char *git_cmd)
open_html(page_path.buf); 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) static const char *check_git_cmd(const char* cmd)
{ {
char *alias; char *alias;
@ -463,6 +434,11 @@ int cmd_help(int argc, const char **argv, const char *prefix)
if (show_all) { if (show_all) {
git_config(git_help_config, NULL); 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"); printf(_("usage: %s%s"), _(git_usage_string), "\n\n");
load_command_list("git-", &main_cmds, &other_cmds); load_command_list("git-", &main_cmds, &other_cmds);
list_commands(colopts, &main_cmds, &other_cmds); list_commands(colopts, &main_cmds, &other_cmds);

View File

@ -35,6 +35,7 @@
#include "string-list.h" #include "string-list.h"
#include "packfile.h" #include "packfile.h"
#include "tag.h" #include "tag.h"
#include "alias.h"
#define DEFAULT_TWOHEAD (1<<0) #define DEFAULT_TWOHEAD (1<<0)
#define DEFAULT_OCTOPUS (1<<1) #define DEFAULT_OCTOPUS (1<<1)

View File

@ -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, void overlay_tree_on_index(struct index_state *istate,
const char *tree_name, const char *prefix); 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 */ /* setup.c */
struct startup_info { struct startup_info {
int have_repository; int have_repository;

View File

@ -1,23 +1,58 @@
# common commands are grouped by themes # Command classification list
# 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. # All supported commands, builtin or external, must be described in
### common groups (do not change this line) # here. This info is used to list commands in various places. Each
init start a working area (see also: git help tutorial) # command is on one line followed by one or more attributes.
worktree work on the current change (see also: git help everyday) #
info examine the history and state (see also: git help revisions) # The first attribute group is mandatory and indicates the command
history grow, mark and tweak your common history # type. This group includes:
remote collaborate (see also: git help workflows) #
# mainporcelain
### command list (do not change this line) # ancillarymanipulators
# command name category [deprecated] [common] # 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-add mainporcelain worktree
git-am mainporcelain git-am mainporcelain
git-annotate ancillaryinterrogators git-annotate ancillaryinterrogators
git-apply plumbingmanipulators git-apply plumbingmanipulators complete
git-archimport foreignscminterface git-archimport foreignscminterface
git-archive mainporcelain git-archive mainporcelain
git-bisect mainporcelain info git-bisect mainporcelain info
git-blame ancillaryinterrogators git-blame ancillaryinterrogators complete
git-branch mainporcelain history git-branch mainporcelain history
git-bundle mainporcelain git-bundle mainporcelain
git-cat-file plumbinginterrogators git-cat-file plumbinginterrogators
@ -27,7 +62,7 @@ git-check-mailmap purehelpers
git-checkout mainporcelain history git-checkout mainporcelain history
git-checkout-index plumbingmanipulators git-checkout-index plumbingmanipulators
git-check-ref-format purehelpers git-check-ref-format purehelpers
git-cherry ancillaryinterrogators git-cherry ancillaryinterrogators complete
git-cherry-pick mainporcelain git-cherry-pick mainporcelain
git-citool mainporcelain git-citool mainporcelain
git-clean mainporcelain git-clean mainporcelain
@ -36,7 +71,7 @@ git-column purehelpers
git-commit mainporcelain history git-commit mainporcelain history
git-commit-graph plumbingmanipulators git-commit-graph plumbingmanipulators
git-commit-tree plumbingmanipulators git-commit-tree plumbingmanipulators
git-config ancillarymanipulators git-config ancillarymanipulators complete
git-count-objects ancillaryinterrogators git-count-objects ancillaryinterrogators
git-credential purehelpers git-credential purehelpers
git-credential-cache purehelpers git-credential-cache purehelpers
@ -50,7 +85,7 @@ git-diff mainporcelain history
git-diff-files plumbinginterrogators git-diff-files plumbinginterrogators
git-diff-index plumbinginterrogators git-diff-index plumbinginterrogators
git-diff-tree plumbinginterrogators git-diff-tree plumbinginterrogators
git-difftool ancillaryinterrogators git-difftool ancillaryinterrogators complete
git-fast-export ancillarymanipulators git-fast-export ancillarymanipulators
git-fast-import ancillarymanipulators git-fast-import ancillarymanipulators
git-fetch mainporcelain remote git-fetch mainporcelain remote
@ -59,20 +94,20 @@ git-filter-branch ancillarymanipulators
git-fmt-merge-msg purehelpers git-fmt-merge-msg purehelpers
git-for-each-ref plumbinginterrogators git-for-each-ref plumbinginterrogators
git-format-patch mainporcelain git-format-patch mainporcelain
git-fsck ancillaryinterrogators git-fsck ancillaryinterrogators complete
git-gc mainporcelain git-gc mainporcelain
git-get-tar-commit-id ancillaryinterrogators git-get-tar-commit-id ancillaryinterrogators
git-grep mainporcelain info git-grep mainporcelain info
git-gui mainporcelain git-gui mainporcelain
git-hash-object plumbingmanipulators git-hash-object plumbingmanipulators
git-help ancillaryinterrogators git-help ancillaryinterrogators complete
git-http-backend synchingrepositories git-http-backend synchingrepositories
git-http-fetch synchelpers git-http-fetch synchelpers
git-http-push synchelpers git-http-push synchelpers
git-imap-send foreignscminterface git-imap-send foreignscminterface
git-index-pack plumbingmanipulators git-index-pack plumbingmanipulators
git-init mainporcelain init git-init mainporcelain init
git-instaweb ancillaryinterrogators git-instaweb ancillaryinterrogators complete
git-interpret-trailers purehelpers git-interpret-trailers purehelpers
gitk mainporcelain gitk mainporcelain
git-log mainporcelain info git-log mainporcelain info
@ -86,7 +121,7 @@ git-merge-base plumbinginterrogators
git-merge-file plumbingmanipulators git-merge-file plumbingmanipulators
git-merge-index plumbingmanipulators git-merge-index plumbingmanipulators
git-merge-one-file purehelpers git-merge-one-file purehelpers
git-mergetool ancillarymanipulators git-mergetool ancillarymanipulators complete
git-merge-tree ancillaryinterrogators git-merge-tree ancillaryinterrogators
git-mktag plumbingmanipulators git-mktag plumbingmanipulators
git-mktree plumbingmanipulators git-mktree plumbingmanipulators
@ -107,28 +142,29 @@ git-quiltimport foreignscminterface
git-read-tree plumbingmanipulators git-read-tree plumbingmanipulators
git-rebase mainporcelain history git-rebase mainporcelain history
git-receive-pack synchelpers git-receive-pack synchelpers
git-reflog ancillarymanipulators git-reflog ancillarymanipulators complete
git-remote ancillarymanipulators git-remote ancillarymanipulators complete
git-repack ancillarymanipulators git-repack ancillarymanipulators complete
git-replace ancillarymanipulators git-replace ancillarymanipulators complete
git-request-pull foreignscminterface git-request-pull foreignscminterface complete
git-rerere ancillaryinterrogators git-rerere ancillaryinterrogators
git-reset mainporcelain worktree git-reset mainporcelain worktree
git-revert mainporcelain git-revert mainporcelain
git-rev-list plumbinginterrogators git-rev-list plumbinginterrogators
git-rev-parse ancillaryinterrogators git-rev-parse ancillaryinterrogators
git-rm mainporcelain worktree git-rm mainporcelain worktree
git-send-email foreignscminterface git-send-email foreignscminterface complete
git-send-pack synchingrepositories git-send-pack synchingrepositories
git-shell synchelpers git-shell synchelpers
git-shortlog mainporcelain git-shortlog mainporcelain
git-show mainporcelain info git-show mainporcelain info
git-show-branch ancillaryinterrogators git-show-branch ancillaryinterrogators complete
git-show-index plumbinginterrogators git-show-index plumbinginterrogators
git-show-ref plumbinginterrogators git-show-ref plumbinginterrogators
git-sh-i18n purehelpers git-sh-i18n purehelpers
git-sh-setup purehelpers git-sh-setup purehelpers
git-stash mainporcelain git-stash mainporcelain
git-stage complete
git-status mainporcelain info git-status mainporcelain info
git-stripspace purehelpers git-stripspace purehelpers
git-submodule mainporcelain git-submodule mainporcelain
@ -147,6 +183,22 @@ git-verify-commit ancillaryinterrogators
git-verify-pack plumbinginterrogators git-verify-pack plumbinginterrogators
git-verify-tag ancillaryinterrogators git-verify-tag ancillaryinterrogators
gitweb ancillaryinterrogators gitweb ancillaryinterrogators
git-whatchanged ancillaryinterrogators git-whatchanged ancillaryinterrogators complete
git-worktree mainporcelain git-worktree mainporcelain
git-write-tree plumbingmanipulators 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

View File

@ -14,6 +14,7 @@
#include "strbuf.h" #include "strbuf.h"
#include "version.h" #include "version.h"
#include "protocol.h" #include "protocol.h"
#include "alias.h"
static char *server_capabilities_v1; static char *server_capabilities_v1;
static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT; static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT;

View File

@ -989,127 +989,11 @@ __git_complete_strategy ()
return 1 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_all_commands=
__git_compute_all_commands () __git_compute_all_commands ()
{ {
test -n "$__git_all_commands" || test -n "$__git_all_commands" ||
__git_all_commands=$(__git_list_all_commands) __git_all_commands=$(git --list-cmds=main,others,alias,nohelpers)
}
__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)
} }
# Lists all set config variables starting with the given section prefix, # Lists all set config variables starting with the given section prefix,
@ -1127,11 +1011,6 @@ __git_pretty_aliases ()
__git_get_config_variables "pretty" __git_get_config_variables "pretty"
} }
__git_aliases ()
{
__git_get_config_variables "alias"
}
# __git_aliased_command requires 1 argument # __git_aliased_command requires 1 argument
__git_aliased_command () __git_aliased_command ()
{ {
@ -1739,13 +1618,12 @@ _git_help ()
return return
;; ;;
esac esac
__git_compute_all_commands if test -n "$GIT_TESTING_ALL_COMMAND_LIST"
__gitcomp "$__git_all_commands $(__git_aliases) then
attributes cli core-tutorial cvs-migration __gitcomp "$GIT_TESTING_ALL_COMMAND_LIST $(git --list-cmds=alias,list-guide) gitk"
diffcore everyday gitk glossary hooks ignore modules else
namespaces repository-layout revisions tutorial tutorial-2 __gitcomp "$(git --list-cmds=main,nohelpers,alias,list-guide) gitk"
workflows fi
"
} }
_git_init () _git_init ()
@ -3214,7 +3092,7 @@ __git_complete_common () {
__git_cmds_with_parseopt_helper= __git_cmds_with_parseopt_helper=
__git_support_parseopt_helper () { __git_support_parseopt_helper () {
test -n "$__git_cmds_with_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 case " $__git_cmds_with_parseopt_helper " in
*" $1 "*) *" $1 "*)
@ -3300,8 +3178,14 @@ __git_main ()
--help --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 esac
return return
fi fi

View File

@ -1,50 +1,90 @@
#!/bin/sh #!/bin/sh
die () {
echo "$@" >&2
exit 1
}
command_list () {
grep -v '^#' "$1"
}
get_categories () {
tr ' ' '\n'|
grep -v '^$' |
sort |
uniq
}
category_list () {
command_list "$1" |
cut -c 40- |
get_categories
}
get_synopsis () {
sed -n '
/^NAME/,/'"$1"'/H
${
x
s/.*'"$1"' - \(.*\)/N_("\1")/
p
}' "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 */ echo "/* Automatically generated by generate-cmdlist.sh */
struct cmdname_help { struct cmdname_help {
char name[16]; const char *name;
char help[80]; const char *help;
unsigned char group; uint32_t category;
}; };
"
static const char *common_cmd_groups[] = {" define_categories "$1"
echo
grps=grps$$.tmp define_category_names "$1"
match=match$$.tmp echo
trap "rm -f '$grps' '$match'" 0 1 2 3 15 print_command_list "$1"
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")
sed -n '
/^NAME/,/git-'"$cmd"'/H
${
x
s/.*git-'"$cmd"' - \(.*\)/ {"'"$cmd"'", N_("\1"), '$tag'},/
p
}' "Documentation/git-$cmd.txt"
done
echo "};"

85
git.c
View File

@ -3,6 +3,7 @@
#include "exec-cmd.h" #include "exec-cmd.h"
#include "help.h" #include "help.h"
#include "run-command.h" #include "run-command.h"
#include "alias.h"
#define RUN_SETUP (1<<0) #define RUN_SETUP (1<<0)
#define RUN_SETUP_GENTLY (1<<1) #define RUN_SETUP_GENTLY (1<<1)
@ -36,7 +37,66 @@ const char git_more_info_string[] =
static int use_pager = -1; 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) { static void commit_pager_choice(void) {
switch (use_pager) { switch (use_pager) {
@ -223,12 +283,19 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
} }
(*argv)++; (*argv)++;
(*argc)--; (*argc)--;
} else if (!strcmp(cmd, "--list-builtins")) { } else if (skip_prefix(cmd, "--list-cmds=", &cmd)) {
list_builtins(0, '\n'); if (!strcmp(cmd, "parseopt")) {
exit(0); struct string_list list = STRING_LIST_INIT_DUP;
} else if (!strcmp(cmd, "--list-parseopt-builtins")) { int i;
list_builtins(NO_PARSEOPT, ' ');
exit(0); 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 { } else {
fprintf(stderr, _("unknown option: %s\n"), cmd); fprintf(stderr, _("unknown option: %s\n"), cmd);
usage(git_usage_string); usage(git_usage_string);
@ -511,14 +578,14 @@ int is_builtin(const char *s)
return !!get_builtin(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; int i;
for (i = 0; i < ARRAY_SIZE(commands); i++) { for (i = 0; i < ARRAY_SIZE(commands); i++) {
if (exclude_option && if (exclude_option &&
(commands[i].option & exclude_option)) (commands[i].option & exclude_option))
continue; continue;
printf("%s%c", commands[i].cmd, sep); string_list_append(out, commands[i].cmd);
} }
} }

256
help.c
View File

@ -5,13 +5,127 @@
#include "run-command.h" #include "run-command.h"
#include "levenshtein.h" #include "levenshtein.h"
#include "help.h" #include "help.h"
#include "common-cmds.h" #include "command-list.h"
#include "string-list.h" #include "string-list.h"
#include "column.h" #include "column.h"
#include "version.h" #include "version.h"
#include "refs.h" #include "refs.h"
#include "parse-options.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) void add_cmdname(struct cmdnames *cmds, const char *name, int len)
{ {
struct cmdname *ent; struct cmdname *ent;
@ -190,42 +304,114 @@ void list_commands(unsigned int colopts,
} }
} }
static int cmd_group_cmp(const void *elem1, const void *elem2)
{
const struct cmdname_help *e1 = elem1;
const struct cmdname_help *e2 = elem2;
if (e1->group < e2->group)
return -1;
if (e1->group > e2->group)
return 1;
return strcmp(e1->name, e2->name);
}
void list_common_cmds_help(void) void list_common_cmds_help(void)
{ {
int i, longest = 0;
int current_grp = -1;
for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
if (longest < strlen(common_cmds[i].name))
longest = strlen(common_cmds[i].name);
}
QSORT(common_cmds, ARRAY_SIZE(common_cmds), cmd_group_cmp);
puts(_("These are common Git commands used in various situations:")); puts(_("These are common Git commands used in various situations:"));
print_cmd_by_category(common_categories);
}
for (i = 0; i < ARRAY_SIZE(common_cmds); i++) { void list_all_main_cmds(struct string_list *list)
if (common_cmds[i].group != current_grp) { {
printf("\n%s\n", _(common_cmd_groups[common_cmds[i].group])); struct cmdnames main_cmds, other_cmds;
current_grp = common_cmds[i].group; 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_all_other_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 < other_cmds.cnt; i++)
string_list_append(list, other_cmds.names[i]->name);
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; category_names[i]; i++) {
if (!strcmp(cat, category_names[i])) {
cat_id = 1UL << i;
break;
} }
printf(" %s ", common_cmds[i].name);
mput_char(' ', longest - strlen(common_cmds[i].name));
puts(_(common_cmds[i].help));
} }
if (!cat_id)
die(_("unsupported command listing type '%s'"), cat);
for (i = 0; i < n; i++) {
struct cmdname_help *cmd = command_list + i;
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 is_in_cmdlist(struct cmdnames *c, const char *s)
@ -285,6 +471,7 @@ const char *help_unknown_cmd(const char *cmd)
{ {
int i, n, best_similarity = 0; int i, n, best_similarity = 0;
struct cmdnames main_cmds, other_cmds; struct cmdnames main_cmds, other_cmds;
struct cmdname_help *common_cmds;
memset(&main_cmds, 0, sizeof(main_cmds)); memset(&main_cmds, 0, sizeof(main_cmds));
memset(&other_cmds, 0, sizeof(other_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); QSORT(main_cmds.names, main_cmds.cnt, cmdname_compare);
uniq(&main_cmds); uniq(&main_cmds);
extract_cmds(&common_cmds, common_mask);
/* This abuses cmdname->len for levenshtein distance */ /* This abuses cmdname->len for levenshtein distance */
for (i = 0, n = 0; i < main_cmds.cnt; i++) { for (i = 0, n = 0; i < main_cmds.cnt; i++) {
int cmp = 0; /* avoid compiler stupidity */ int cmp = 0; /* avoid compiler stupidity */
@ -313,10 +502,10 @@ const char *help_unknown_cmd(const char *cmd)
die(_(bad_interpreter_advice), cmd, cmd); die(_(bad_interpreter_advice), cmd, cmd);
/* Does the candidate appear in common_cmds list? */ /* 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) (cmp = strcmp(common_cmds[n].name, candidate)) < 0)
n++; n++;
if ((n < ARRAY_SIZE(common_cmds)) && !cmp) { if (common_cmds[n].name && !cmp) {
/* Yes, this is one of the common commands */ /* Yes, this is one of the common commands */
n++; /* use the entry from common_cmds[] */ n++; /* use the entry from common_cmds[] */
if (starts_with(candidate, cmd)) { if (starts_with(candidate, cmd)) {
@ -329,6 +518,7 @@ const char *help_unknown_cmd(const char *cmd)
main_cmds.names[i]->len = main_cmds.names[i]->len =
levenshtein(cmd, candidate, 0, 2, 1, 3) + 1; levenshtein(cmd, candidate, 0, 2, 1, 3) + 1;
} }
FREE_AND_NULL(common_cmds);
QSORT(main_cmds.names, main_cmds.cnt, levenshtein_compare); QSORT(main_cmds.names, main_cmds.cnt, levenshtein_compare);

10
help.h
View File

@ -1,6 +1,8 @@
#ifndef HELP_H #ifndef HELP_H
#define HELP_H #define HELP_H
struct string_list;
struct cmdnames { struct cmdnames {
int alloc; int alloc;
int cnt; 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_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 const char *help_unknown_cmd(const char *cmd);
extern void load_command_list(const char *prefix, extern void load_command_list(const char *prefix,
struct cmdnames *main_cmds, struct cmdnames *main_cmds,

View File

@ -2,6 +2,7 @@
#include "config.h" #include "config.h"
#include "run-command.h" #include "run-command.h"
#include "sigchain.h" #include "sigchain.h"
#include "alias.h"
#ifndef DEFAULT_PAGER #ifndef DEFAULT_PAGER
#define DEFAULT_PAGER "less" #define DEFAULT_PAGER "less"

View File

@ -27,6 +27,7 @@
#include "worktree.h" #include "worktree.h"
#include "oidmap.h" #include "oidmap.h"
#include "oidset.h" #include "oidset.h"
#include "alias.h"
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION" #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"

View File

@ -3,6 +3,7 @@
#include "exec-cmd.h" #include "exec-cmd.h"
#include "strbuf.h" #include "strbuf.h"
#include "run-command.h" #include "run-command.h"
#include "alias.h"
#define COMMAND_DIR "git-shell-commands" #define COMMAND_DIR "git-shell-commands"
#define HELP_COMMAND COMMAND_DIR "/help" #define HELP_COMMAND COMMAND_DIR "/help"

View File

@ -25,6 +25,15 @@ test_expect_success "setup" '
EOF 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" ' test_expect_success "works for commands and guides by default" '
configure_help && configure_help &&
git help status && git help status &&
@ -49,8 +58,23 @@ test_expect_success "--help does not work for guides" "
test_i18ncmp expect actual 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' ' test_expect_success 'generate builtin list' '
git --list-builtins >builtins git --list-cmds=builtins >builtins
' '
while read builtin while read builtin

View File

@ -13,7 +13,7 @@ complete ()
return 0 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 # (1) The build tree may have build artifact from different branch, or
# the user's $PATH may have a random executable that may begin # 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", # completion for "git <TAB>", and a plumbing is excluded. "add",
# "filter-branch" and "ls-files" are listed for this. # "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" . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash"
@ -1350,17 +1351,6 @@ test_expect_success '__git_pretty_aliases' '
test_cmp expect actual 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' ' test_expect_success 'basic' '
run_completion "git " && run_completion "git " &&
# built-in # built-in
@ -1670,13 +1660,6 @@ test_expect_success 'sourcing the completion script clears cached commands' '
verbose test -z "$__git_all_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' ' test_expect_success !GETTEXT_POISON 'sourcing the completion script clears cached merge strategies' '
__git_compute_merge_strategies && __git_compute_merge_strategies &&
verbose test -n "$__git_merge_strategies" && verbose test -n "$__git_merge_strategies" &&