Code

Merge branch 'cr/reset-parseopt'
[git.git] / help.c
diff --git a/help.c b/help.c
index 95e7640fedebb1574a4259d85d7b95d5220f0e6f..e57a50ed59badbb968ce508b6c1802f1fcb68903 100644 (file)
--- a/help.c
+++ b/help.c
@@ -7,33 +7,38 @@
 #include "builtin.h"
 #include "exec_cmd.h"
 #include "common-cmds.h"
-
-static const char *help_default_format;
-
-static enum help_format {
-       man_format,
-       info_format,
-       web_format,
-} help_format = man_format;
-
-static void parse_help_format(const char *format)
+#include "parse-options.h"
+
+enum help_format {
+       HELP_FORMAT_MAN,
+       HELP_FORMAT_INFO,
+       HELP_FORMAT_WEB,
+};
+
+static int show_all = 0;
+static enum help_format help_format = HELP_FORMAT_MAN;
+static struct option builtin_help_options[] = {
+       OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
+       OPT_SET_INT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
+       OPT_SET_INT('w', "web", &help_format, "show manual in web browser",
+                       HELP_FORMAT_WEB),
+       OPT_SET_INT('i', "info", &help_format, "show info page",
+                       HELP_FORMAT_INFO),
+};
+
+static const char * const builtin_help_usage[] = {
+       "git-help [--all] [--man|--web|--info] [command]",
+       NULL
+};
+
+static enum help_format parse_help_format(const char *format)
 {
-       if (!format) {
-               help_format = man_format;
-               return;
-       }
-       if (!strcmp(format, "man")) {
-               help_format = man_format;
-               return;
-       }
-       if (!strcmp(format, "info")) {
-               help_format = info_format;
-               return;
-       }
-       if (!strcmp(format, "web") || !strcmp(format, "html")) {
-               help_format = web_format;
-               return;
-       }
+       if (!strcmp(format, "man"))
+               return HELP_FORMAT_MAN;
+       if (!strcmp(format, "info"))
+               return HELP_FORMAT_INFO;
+       if (!strcmp(format, "web") || !strcmp(format, "html"))
+               return HELP_FORMAT_WEB;
        die("unrecognized help format '%s'", format);
 }
 
@@ -42,7 +47,7 @@ static int git_help_config(const char *var, const char *value)
        if (!strcmp(var, "help.format")) {
                if (!value)
                        return config_error_nonbool(var);
-               help_default_format = xstrdup(value);
+               help_format = parse_help_format(value);
                return 0;
        }
        return git_default_config(var, value);
@@ -205,7 +210,7 @@ static unsigned int list_commands_in_dir(struct cmdnames *cmds,
        return longest;
 }
 
-static void list_commands(void)
+static unsigned int load_command_list(void)
 {
        unsigned int longest = 0;
        unsigned int len;
@@ -245,6 +250,14 @@ static void list_commands(void)
        uniq(&other_cmds);
        exclude_cmds(&other_cmds, &main_cmds);
 
+       return longest;
+}
+
+static void list_commands(void)
+{
+       unsigned int longest = load_command_list();
+       const char *exec_path = git_exec_path();
+
        if (main_cmds.cnt) {
                printf("available git commands in '%s'\n", exec_path);
                printf("----------------------------");
@@ -279,6 +292,22 @@ void list_common_cmds_help(void)
        }
 }
 
+static int is_in_cmdlist(struct cmdnames *c, const char *s)
+{
+       int i;
+       for (i = 0; i < c->cnt; i++)
+               if (!strcmp(s, c->names[i]->name))
+                       return 1;
+       return 0;
+}
+
+static int is_git_command(const char *s)
+{
+       load_command_list();
+       return is_in_cmdlist(&main_cmds, s) ||
+               is_in_cmdlist(&other_cmds, s);
+}
+
 static const char *cmd_to_page(const char *git_cmd)
 {
        if (!git_cmd)
@@ -330,10 +359,26 @@ static void show_info_page(const char *git_cmd)
        execlp("info", "info", "gitman", page, NULL);
 }
 
+static void get_html_page_path(struct strbuf *page_path, const char *page)
+{
+       struct stat st;
+
+       /* Check that we have a git documentation directory. */
+       if (stat(GIT_HTML_PATH "/git.html", &st) || !S_ISREG(st.st_mode))
+               die("'%s': not a documentation directory.", GIT_HTML_PATH);
+
+       strbuf_init(page_path, 0);
+       strbuf_addf(page_path, GIT_HTML_PATH "/%s.html", page);
+}
+
 static void show_html_page(const char *git_cmd)
 {
        const char *page = cmd_to_page(git_cmd);
-       execl_git_cmd("help--browse", page, NULL);
+       struct strbuf page_path; /* it leaks but we exec bellow */
+
+       get_html_page_path(&page_path, page);
+
+       execl_git_cmd("web--browse", "-c", "help.browser", page_path.buf, NULL);
 }
 
 void help_unknown_cmd(const char *cmd)
@@ -350,50 +395,43 @@ int cmd_version(int argc, const char **argv, const char *prefix)
 
 int cmd_help(int argc, const char **argv, const char *prefix)
 {
-       const char *help_cmd = argv[1];
+       int nongit;
+       const char *alias;
 
-       if (argc < 2) {
-               printf("usage: %s\n\n", git_usage_string);
-               list_common_cmds_help();
-               exit(0);
-       }
+       setup_git_directory_gently(&nongit);
+       git_config(git_help_config);
 
-       if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a")) {
+       argc = parse_options(argc, argv, builtin_help_options,
+                       builtin_help_usage, 0);
+
+       if (show_all) {
                printf("usage: %s\n\n", git_usage_string);
                list_commands();
+               return 0;
        }
 
-       else if (!strcmp(help_cmd, "--web") || !strcmp(help_cmd, "-w")) {
-               show_html_page(argc > 2 ? argv[2] : NULL);
-       }
-
-       else if (!strcmp(help_cmd, "--info") || !strcmp(help_cmd, "-i")) {
-               show_info_page(argc > 2 ? argv[2] : NULL);
+       if (!argv[0]) {
+               printf("usage: %s\n\n", git_usage_string);
+               list_common_cmds_help();
+               return 0;
        }
 
-       else if (!strcmp(help_cmd, "--man") || !strcmp(help_cmd, "-m")) {
-               show_man_page(argc > 2 ? argv[2] : NULL);
+       alias = alias_lookup(argv[0]);
+       if (alias && !is_git_command(argv[0])) {
+               printf("`git %s' is aliased to `%s'\n", argv[0], alias);
+               return 0;
        }
 
-       else {
-               int nongit;
-
-               setup_git_directory_gently(&nongit);
-               git_config(git_help_config);
-               if (help_default_format)
-                       parse_help_format(help_default_format);
-
-               switch (help_format) {
-               case man_format:
-                       show_man_page(help_cmd);
-                       break;
-               case info_format:
-                       show_info_page(help_cmd);
-                       break;
-               case web_format:
-                       show_html_page(help_cmd);
-                       break;
-               }
+       switch (help_format) {
+       case HELP_FORMAT_MAN:
+               show_man_page(argv[0]);
+               break;
+       case HELP_FORMAT_INFO:
+               show_info_page(argv[0]);
+               break;
+       case HELP_FORMAT_WEB:
+               show_html_page(argv[0]);
+               break;
        }
 
        return 0;