From 482cce820554809c02bc639bb33462f9905e4342 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 2 Feb 2008 07:32:33 +0100 Subject: help: make 'git-help--browse' usable outside 'git-help'. "git-help--browse" helper is to launch a browser of the user's choice to view the HTML version of git documentation for a given command. It used to take the name of a command, convert it to the path of the documentation by prefixing the directory name and appending the ".html" suffix, and start the browser on the path. This updates the division of labor between the caller in help.c and git-help--browser helper. The helper is now responsible for launching a browser of the user's choice on given URLs, and it is the caller's responsibility to tell it the paths to documentation files. This is in preparation to reuse the logic to choose user's preferred browser in instaweb. The helper had a provision for running it without any command name, in which case it showed the toplevel "git(7)" documentation, but the caller in help.c never makes such a call. The helper now exits with a usage message when no path is given. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- help.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'help.c') diff --git a/help.c b/help.c index 1302a61c8..b929899e6 100644 --- a/help.c +++ b/help.c @@ -328,10 +328,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("help--browse", page_path.buf, NULL); } void help_unknown_cmd(const char *cmd) -- cgit v1.2.1 From caa87713bca77c441c09282aa5b18b179bcfa90d Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 2 Feb 2008 07:32:41 +0100 Subject: help--browse: add '--config' option to check a config option for a browser. The value of this new command line option will be used as a key to check the configuration for an help browser. This should remove the last bit in 'git-help--browse' that was specific to 'git-help', so that other git command can use 'git-help--browse'. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- help.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'help.c') diff --git a/help.c b/help.c index b929899e6..058a39753 100644 --- a/help.c +++ b/help.c @@ -347,7 +347,7 @@ static void show_html_page(const char *git_cmd) get_html_page_path(&page_path, page); - execl_git_cmd("help--browse", page_path.buf, NULL); + execl_git_cmd("help--browse", "-c", "help.browser", page_path.buf, NULL); } void help_unknown_cmd(const char *cmd) -- cgit v1.2.1 From 5884f1fe96b33d9666a78e660042b1e3e5f9f4d9 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 2 Feb 2008 07:32:53 +0100 Subject: Rename 'git-help--browse.sh' to 'git-web--browse.sh'. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- help.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'help.c') diff --git a/help.c b/help.c index 058a39753..c35912bc5 100644 --- a/help.c +++ b/help.c @@ -347,7 +347,7 @@ static void show_html_page(const char *git_cmd) get_html_page_path(&page_path, page); - execl_git_cmd("help--browse", "-c", "help.browser", page_path.buf, NULL); + execl_git_cmd("web--browse", "-c", "help.browser", page_path.buf, NULL); } void help_unknown_cmd(const char *cmd) -- cgit v1.2.1 From b51b2bb4c3da805727fd43219e3f817475ae52d3 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 11 Feb 2008 10:56:26 -0800 Subject: help.c: guard config parser from value=NULL help.format configuration expects a string value Signed-off-by: Junio C Hamano --- help.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'help.c') diff --git a/help.c b/help.c index 1302a61c8..95e7640fe 100644 --- a/help.c +++ b/help.c @@ -40,6 +40,8 @@ static void parse_help_format(const char *format) 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); return 0; } -- cgit v1.2.1 From 9886ea417b7da9722c95630b5980ac174e04c71c Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sun, 17 Feb 2008 20:52:50 +0100 Subject: help.c: use 'git_config_string' to get 'help_default_format'. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- help.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'help.c') diff --git a/help.c b/help.c index 6e28ad9e7..8143dcdd3 100644 --- a/help.c +++ b/help.c @@ -39,12 +39,8 @@ static void parse_help_format(const char *format) 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); - return 0; - } + if (!strcmp(var, "help.format")) + return git_config_string(&help_default_format, var, value); return git_default_config(var, value); } -- cgit v1.2.1 From 41eb33bd0cbecf1b441ada91ab186ee49fb086cc Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 24 Feb 2008 17:16:55 -0500 Subject: help: use parseopt This patch converts cmd_help to use parseopt, along with a few style cleanups, including: - enum constants are now ALL_CAPS - parse_help_format returns an enum value rather than setting a global as a side effect Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- help.c | 123 +++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 59 insertions(+), 64 deletions(-) (limited to 'help.c') diff --git a/help.c b/help.c index 8143dcdd3..5feb8491b 100644 --- a/help.c +++ b/help.c @@ -7,40 +7,49 @@ #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); } static int git_help_config(const char *var, const char *value) { - if (!strcmp(var, "help.format")) - return git_config_string(&help_default_format, var, value); + if (!strcmp(var, "help.format")) { + if (!value) + return config_error_nonbool(var); + help_format = parse_help_format(value); + return 0; + } return git_default_config(var, value); } @@ -362,50 +371,36 @@ 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; - 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); - } - - else if (!strcmp(help_cmd, "--man") || !strcmp(help_cmd, "-m")) { - show_man_page(argc > 2 ? argv[2] : NULL); + if (!argv[0]) { + printf("usage: %s\n\n", git_usage_string); + list_common_cmds_help(); + 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; -- cgit v1.2.1 From 2156435ff22437909cda825f1901dceb198fef19 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 24 Feb 2008 17:17:37 -0500 Subject: help: respect aliases If we have an alias "foo" defined, then the help text for "foo" (via "git help foo" or "git foo --help") now shows the definition of the alias. Before showing an alias definition, we make sure that there is no git command which would override the alias (so that even though you may have a "log" alias, even though it will not work, we don't want to it supersede "git help log"). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- help.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'help.c') diff --git a/help.c b/help.c index 5feb8491b..e57a50ed5 100644 --- a/help.c +++ b/help.c @@ -210,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; @@ -250,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("----------------------------"); @@ -284,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) @@ -372,6 +396,7 @@ int cmd_version(int argc, const char **argv, const char *prefix) int cmd_help(int argc, const char **argv, const char *prefix) { int nongit; + const char *alias; setup_git_directory_gently(&nongit); git_config(git_help_config); @@ -391,6 +416,12 @@ int cmd_help(int argc, const char **argv, const char *prefix) return 0; } + 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; + } + switch (help_format) { case HELP_FORMAT_MAN: show_man_page(argv[0]); -- cgit v1.2.1 From 649499845c274dc15809fe3c9162408c334fec57 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 7 Mar 2008 08:46:28 +0100 Subject: help: add "man.viewer" config var to use "woman" or "konqueror" This patch makes it possible to view man pages using other tools than the "man" program. It also implements support for emacs' "woman" and konqueror with the man KIO slave to view man pages. Note that "emacsclient" is used with option "-e" to launch "woman" on emacs and this works only on versions >= 22. Signed-off-by: Christian Couder Tested-by: Xavier Maillard Signed-off-by: Junio C Hamano --- help.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) (limited to 'help.c') diff --git a/help.c b/help.c index e57a50ed5..2cb152d2e 100644 --- a/help.c +++ b/help.c @@ -8,6 +8,9 @@ #include "exec_cmd.h" #include "common-cmds.h" #include "parse-options.h" +#include "run-command.h" + +static const char *man_viewer; enum help_format { HELP_FORMAT_MAN, @@ -50,6 +53,8 @@ static int git_help_config(const char *var, const char *value) help_format = parse_help_format(value); return 0; } + if (!strcmp(var, "man.viewer")) + return git_config_string(&man_viewer, var, value); return git_default_config(var, value); } @@ -345,11 +350,85 @@ static void setup_man_path(void) strbuf_release(&new_path); } +static int check_emacsclient_version(void) +{ + struct strbuf buffer = STRBUF_INIT; + struct child_process ec_process; + const char *argv_ec[] = { "emacsclient", "--version", NULL }; + int version; + + /* emacsclient prints its version number on stderr */ + memset(&ec_process, 0, sizeof(ec_process)); + ec_process.argv = argv_ec; + ec_process.err = -1; + ec_process.stdout_to_stderr = 1; + if (start_command(&ec_process)) { + fprintf(stderr, "Failed to start emacsclient.\n"); + return -1; + } + strbuf_read(&buffer, ec_process.err, 20); + close(ec_process.err); + + /* + * Don't bother checking return value, because "emacsclient --version" + * seems to always exits with code 1. + */ + finish_command(&ec_process); + + if (prefixcmp(buffer.buf, "emacsclient")) { + fprintf(stderr, "Failed to parse emacsclient version.\n"); + strbuf_release(&buffer); + return -1; + } + + strbuf_remove(&buffer, 0, strlen("emacsclient")); + version = atoi(buffer.buf); + + if (version < 22) { + fprintf(stderr, + "emacsclient version '%d' too old (< 22).\n", + version); + strbuf_release(&buffer); + return -1; + } + + strbuf_release(&buffer); + return 0; +} + +static void exec_woman_emacs(const char *page) +{ + if (!check_emacsclient_version()) { + /* This works only with emacsclient version >= 22. */ + struct strbuf man_page = STRBUF_INIT; + strbuf_addf(&man_page, "(woman \"%s\")", page); + execlp("emacsclient", "emacsclient", "-e", man_page.buf, NULL); + } else + execlp("man", "man", page, NULL); +} + +static void exec_man_konqueror(const char *page) +{ + const char *display = getenv("DISPLAY"); + if (display && *display) { + struct strbuf man_page = STRBUF_INIT; + strbuf_addf(&man_page, "man:%s(1)", page); + execlp("kfmclient", "kfmclient", "newTab", man_page.buf, NULL); + } else + execlp("man", "man", page, NULL); +} + static void show_man_page(const char *git_cmd) { const char *page = cmd_to_page(git_cmd); setup_man_path(); - execlp("man", "man", page, NULL); + if (!man_viewer || !strcmp(man_viewer, "man")) + execlp("man", "man", page, NULL); + if (!strcmp(man_viewer, "woman")) + exec_woman_emacs(page); + if (!strcmp(man_viewer, "konqueror")) + exec_man_konqueror(page); + die("'%s': unsupported man viewer.", man_viewer); } static void show_info_page(const char *git_cmd) -- cgit v1.2.1 From 69099d6bedb0217d7c35f7202acd6185551d762f Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 11 Mar 2008 08:51:12 +0100 Subject: help: implement multi-valued "man.viewer" config option This allows multiple viewer candidates to be listed in the configuration file, like this: [man] viewer = woman viewer = konqueror viewer = man The candidates are tried in the order listed in the configuration file, and the first suitable one (e.g. konqueror cannot be used outside windowed environment) is used. Signed-off-by: Christian Couder Tested-by: Xavier Maillard Signed-off-by: Junio C Hamano --- help.c | 191 ++++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 113 insertions(+), 78 deletions(-) (limited to 'help.c') diff --git a/help.c b/help.c index 2cb152d2e..5da8c9c41 100644 --- a/help.c +++ b/help.c @@ -10,7 +10,10 @@ #include "parse-options.h" #include "run-command.h" -static const char *man_viewer; +static struct man_viewer_list { + void (*exec)(const char *); + struct man_viewer_list *next; +} *man_viewer_list; enum help_format { HELP_FORMAT_MAN, @@ -45,6 +48,102 @@ static enum help_format parse_help_format(const char *format) die("unrecognized help format '%s'", format); } +static int check_emacsclient_version(void) +{ + struct strbuf buffer = STRBUF_INIT; + struct child_process ec_process; + const char *argv_ec[] = { "emacsclient", "--version", NULL }; + int version; + + /* emacsclient prints its version number on stderr */ + memset(&ec_process, 0, sizeof(ec_process)); + ec_process.argv = argv_ec; + ec_process.err = -1; + ec_process.stdout_to_stderr = 1; + if (start_command(&ec_process)) { + fprintf(stderr, "Failed to start emacsclient.\n"); + return -1; + } + strbuf_read(&buffer, ec_process.err, 20); + close(ec_process.err); + + /* + * Don't bother checking return value, because "emacsclient --version" + * seems to always exits with code 1. + */ + finish_command(&ec_process); + + if (prefixcmp(buffer.buf, "emacsclient")) { + fprintf(stderr, "Failed to parse emacsclient version.\n"); + strbuf_release(&buffer); + return -1; + } + + strbuf_remove(&buffer, 0, strlen("emacsclient")); + version = atoi(buffer.buf); + + if (version < 22) { + fprintf(stderr, + "emacsclient version '%d' too old (< 22).\n", + version); + strbuf_release(&buffer); + return -1; + } + + strbuf_release(&buffer); + return 0; +} + +static void exec_woman_emacs(const char *page) +{ + if (!check_emacsclient_version()) { + /* This works only with emacsclient version >= 22. */ + struct strbuf man_page = STRBUF_INIT; + strbuf_addf(&man_page, "(woman \"%s\")", page); + execlp("emacsclient", "emacsclient", "-e", man_page.buf, NULL); + } +} + +static void exec_man_konqueror(const char *page) +{ + const char *display = getenv("DISPLAY"); + if (display && *display) { + struct strbuf man_page = STRBUF_INIT; + strbuf_addf(&man_page, "man:%s(1)", page); + execlp("kfmclient", "kfmclient", "newTab", man_page.buf, NULL); + } +} + +static void exec_man_man(const char *page) +{ + execlp("man", "man", page, NULL); +} + +static void do_add_man_viewer(void (*exec)(const char *)) +{ + struct man_viewer_list **p = &man_viewer_list; + + while (*p) + p = &((*p)->next); + *p = xmalloc(sizeof(**p)); + (*p)->next = NULL; + (*p)->exec = exec; +} + +static int add_man_viewer(const char *value) +{ + if (!strcasecmp(value, "man")) + do_add_man_viewer(exec_man_man); + else if (!strcasecmp(value, "woman")) + do_add_man_viewer(exec_woman_emacs); + else if (!strcasecmp(value, "konqueror")) + do_add_man_viewer(exec_man_konqueror); + else + return error("'%s': unsupported man viewer.", value); + + return 0; +} + static int git_help_config(const char *var, const char *value) { if (!strcmp(var, "help.format")) { @@ -53,8 +152,11 @@ static int git_help_config(const char *var, const char *value) help_format = parse_help_format(value); return 0; } - if (!strcmp(var, "man.viewer")) - return git_config_string(&man_viewer, var, value); + if (!strcmp(var, "man.viewer")) { + if (!value) + return config_error_nonbool(var); + return add_man_viewer(value); + } return git_default_config(var, value); } @@ -350,85 +452,18 @@ static void setup_man_path(void) strbuf_release(&new_path); } -static int check_emacsclient_version(void) -{ - struct strbuf buffer = STRBUF_INIT; - struct child_process ec_process; - const char *argv_ec[] = { "emacsclient", "--version", NULL }; - int version; - - /* emacsclient prints its version number on stderr */ - memset(&ec_process, 0, sizeof(ec_process)); - ec_process.argv = argv_ec; - ec_process.err = -1; - ec_process.stdout_to_stderr = 1; - if (start_command(&ec_process)) { - fprintf(stderr, "Failed to start emacsclient.\n"); - return -1; - } - strbuf_read(&buffer, ec_process.err, 20); - close(ec_process.err); - - /* - * Don't bother checking return value, because "emacsclient --version" - * seems to always exits with code 1. - */ - finish_command(&ec_process); - - if (prefixcmp(buffer.buf, "emacsclient")) { - fprintf(stderr, "Failed to parse emacsclient version.\n"); - strbuf_release(&buffer); - return -1; - } - - strbuf_remove(&buffer, 0, strlen("emacsclient")); - version = atoi(buffer.buf); - - if (version < 22) { - fprintf(stderr, - "emacsclient version '%d' too old (< 22).\n", - version); - strbuf_release(&buffer); - return -1; - } - - strbuf_release(&buffer); - return 0; -} - -static void exec_woman_emacs(const char *page) -{ - if (!check_emacsclient_version()) { - /* This works only with emacsclient version >= 22. */ - struct strbuf man_page = STRBUF_INIT; - strbuf_addf(&man_page, "(woman \"%s\")", page); - execlp("emacsclient", "emacsclient", "-e", man_page.buf, NULL); - } else - execlp("man", "man", page, NULL); -} - -static void exec_man_konqueror(const char *page) -{ - const char *display = getenv("DISPLAY"); - if (display && *display) { - struct strbuf man_page = STRBUF_INIT; - strbuf_addf(&man_page, "man:%s(1)", page); - execlp("kfmclient", "kfmclient", "newTab", man_page.buf, NULL); - } else - execlp("man", "man", page, NULL); -} - static void show_man_page(const char *git_cmd) { + struct man_viewer_list *viewer; const char *page = cmd_to_page(git_cmd); + setup_man_path(); - if (!man_viewer || !strcmp(man_viewer, "man")) - execlp("man", "man", page, NULL); - if (!strcmp(man_viewer, "woman")) - exec_woman_emacs(page); - if (!strcmp(man_viewer, "konqueror")) - exec_man_konqueror(page); - die("'%s': unsupported man viewer.", man_viewer); + for (viewer = man_viewer_list; viewer; viewer = viewer->next) + { + viewer->exec(page); /* will return when unable */ + } + exec_man_man(page); + die("no man viewer handled the request"); } static void show_info_page(const char *git_cmd) -- cgit v1.2.1 From 5fb0b3e007d6465af99d08121d46be82c649df5a Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Thu, 13 Mar 2008 07:10:40 +0100 Subject: help: warn if specified 'man.viewer' is unsupported, instead of erroring out When a document viewer that is unknown to the current version of git is specified in the .git/config file, instead of erroring out the process entirely, just issue a warning. It might be that the user usually is using a newer git that supports it (and the configuration is written for that version) but is temporarily using an older git that does not know the viewer. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- help.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'help.c') diff --git a/help.c b/help.c index 5da8c9c41..ecaca770d 100644 --- a/help.c +++ b/help.c @@ -139,7 +139,7 @@ static int add_man_viewer(const char *value) else if (!strcasecmp(value, "konqueror")) do_add_man_viewer(exec_man_konqueror); else - return error("'%s': unsupported man viewer.", value); + warning("'%s': unsupported man viewer.", value); return 0; } -- cgit v1.2.1 From 4637e47accc43479bd779a354e839f898ecd1b84 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 2 Apr 2008 05:47:41 +0200 Subject: help: Add a missing OPT_END(). Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- help.c | 1 + 1 file changed, 1 insertion(+) (limited to 'help.c') diff --git a/help.c b/help.c index ecaca770d..10298fb0a 100644 --- a/help.c +++ b/help.c @@ -30,6 +30,7 @@ static struct option builtin_help_options[] = { HELP_FORMAT_WEB), OPT_SET_INT('i', "info", &help_format, "show info page", HELP_FORMAT_INFO), + OPT_END(), }; static const char * const builtin_help_usage[] = { -- cgit v1.2.1 From 7b15f872f23855de59bd06b0ebdbbc47b27b781b Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 25 Apr 2008 08:24:22 +0200 Subject: help: use man viewer path from "man..path" config var This patch implements reading values from "man..path" configuration variables, and using these values as pathes to the man viewer s when lauching them. This makes it possible to use different version of the tools than the one on the current PATH, or maybe a custom script. In this patch we also try to launch "konqueror" using "kfmclient" even if a path to a konqueror binary is given in "man.konqueror.path". The "man_viewer_list" becomes a simple string list to simplify things for the following patches. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- help.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 124 insertions(+), 19 deletions(-) (limited to 'help.c') diff --git a/help.c b/help.c index 10298fb0a..483e1e9c3 100644 --- a/help.c +++ b/help.c @@ -11,10 +11,16 @@ #include "run-command.h" static struct man_viewer_list { - void (*exec)(const char *); struct man_viewer_list *next; + char name[FLEX_ARRAY]; } *man_viewer_list; +static struct man_viewer_info_list { + struct man_viewer_info_list *next; + const char *info; + char name[FLEX_ARRAY]; +} *man_viewer_info_list; + enum help_format { HELP_FORMAT_MAN, HELP_FORMAT_INFO, @@ -49,6 +55,18 @@ static enum help_format parse_help_format(const char *format) die("unrecognized help format '%s'", format); } +static const char *get_man_viewer_info(const char *name) +{ + struct man_viewer_info_list *viewer; + + for (viewer = man_viewer_info_list; viewer; viewer = viewer->next) + { + if (!strcasecmp(name, viewer->name)) + return viewer->info; + } + return NULL; +} + static int check_emacsclient_version(void) { struct strbuf buffer = STRBUF_INIT; @@ -95,56 +113,126 @@ static int check_emacsclient_version(void) return 0; } -static void exec_woman_emacs(const char *page) +static void exec_woman_emacs(const char* path, const char *page) { if (!check_emacsclient_version()) { /* This works only with emacsclient version >= 22. */ struct strbuf man_page = STRBUF_INIT; + + if (!path) + path = "emacsclient"; strbuf_addf(&man_page, "(woman \"%s\")", page); - execlp("emacsclient", "emacsclient", "-e", man_page.buf, NULL); + execlp(path, "emacsclient", "-e", man_page.buf, NULL); + warning("failed to exec '%s': %s", path, strerror(errno)); } } -static void exec_man_konqueror(const char *page) +static void exec_man_konqueror(const char* path, const char *page) { const char *display = getenv("DISPLAY"); if (display && *display) { struct strbuf man_page = STRBUF_INIT; + const char *filename = "kfmclient"; + + /* It's simpler to launch konqueror using kfmclient. */ + if (path) { + const char *file = strrchr(path, '/'); + if (file && !strcmp(file + 1, "konqueror")) { + char *new = xstrdup(path); + char *dest = strrchr(new, '/'); + + /* strlen("konqueror") == strlen("kfmclient") */ + strcpy(dest + 1, "kfmclient"); + path = new; + } + if (file) + filename = file; + } else + path = "kfmclient"; strbuf_addf(&man_page, "man:%s(1)", page); - execlp("kfmclient", "kfmclient", "newTab", man_page.buf, NULL); + execlp(path, filename, "newTab", man_page.buf, NULL); + warning("failed to exec '%s': %s", path, strerror(errno)); } } -static void exec_man_man(const char *page) +static void exec_man_man(const char* path, const char *page) { - execlp("man", "man", page, NULL); + if (!path) + path = "man"; + execlp(path, "man", page, NULL); + warning("failed to exec '%s': %s", path, strerror(errno)); } -static void do_add_man_viewer(void (*exec)(const char *)) +static void do_add_man_viewer(const char *name) { struct man_viewer_list **p = &man_viewer_list; + size_t len = strlen(name); while (*p) p = &((*p)->next); - *p = xmalloc(sizeof(**p)); - (*p)->next = NULL; - (*p)->exec = exec; + *p = xcalloc(1, (sizeof(**p) + len + 1)); + strncpy((*p)->name, name, len); +} + +static int supported_man_viewer(const char *name, size_t len) +{ + return (!strncasecmp("man", name, len) || + !strncasecmp("woman", name, len) || + !strncasecmp("konqueror", name, len)); } static int add_man_viewer(const char *value) { - if (!strcasecmp(value, "man")) - do_add_man_viewer(exec_man_man); - else if (!strcasecmp(value, "woman")) - do_add_man_viewer(exec_woman_emacs); - else if (!strcasecmp(value, "konqueror")) - do_add_man_viewer(exec_man_konqueror); + if (supported_man_viewer(value, strlen(value))) + do_add_man_viewer(value); else warning("'%s': unsupported man viewer.", value); return 0; } +static void do_add_man_viewer_info(const char *name, + size_t len, + const char *value) +{ + struct man_viewer_info_list *new = xcalloc(1, sizeof(*new) + len + 1); + + strncpy(new->name, name, len); + new->info = xstrdup(value); + new->next = man_viewer_info_list; + man_viewer_info_list = new; +} + +static int add_man_viewer_path(const char *name, + size_t len, + const char *value) +{ + if (supported_man_viewer(name, len)) + do_add_man_viewer_info(name, len, value); + else + warning("'%s': path for unsupported man viewer.", name); + + return 0; +} + +static int add_man_viewer_info(const char *var, const char *value) +{ + const char *name = var + 4; + const char *subkey = strrchr(name, '.'); + + if (!subkey) + return error("Config with no key for man viewer: %s", name); + + if (!strcmp(subkey, ".path")) { + if (!value) + return config_error_nonbool(var); + return add_man_viewer_path(name, subkey - name, value); + } + + warning("'%s': unsupported man viewer sub key.", subkey); + return 0; +} + static int git_help_config(const char *var, const char *value) { if (!strcmp(var, "help.format")) { @@ -158,6 +246,9 @@ static int git_help_config(const char *var, const char *value) return config_error_nonbool(var); return add_man_viewer(value); } + if (!prefixcmp(var, "man.")) + return add_man_viewer_info(var, value); + return git_default_config(var, value); } @@ -453,6 +544,20 @@ static void setup_man_path(void) strbuf_release(&new_path); } +static void exec_viewer(const char *name, const char *page) +{ + const char *path = get_man_viewer_info(name); + + if (!strcasecmp(name, "man")) + exec_man_man(path, page); + else if (!strcasecmp(name, "woman")) + exec_woman_emacs(path, page); + else if (!strcasecmp(name, "konqueror")) + exec_man_konqueror(path, page); + else + warning("'%s': unsupported man viewer.", name); +} + static void show_man_page(const char *git_cmd) { struct man_viewer_list *viewer; @@ -461,9 +566,9 @@ static void show_man_page(const char *git_cmd) setup_man_path(); for (viewer = man_viewer_list; viewer; viewer = viewer->next) { - viewer->exec(page); /* will return when unable */ + exec_viewer(viewer->name, page); /* will return when unable */ } - exec_man_man(page); + exec_viewer("man", page); die("no man viewer handled the request"); } -- cgit v1.2.1 From a26a06afed783cb7cf7207c1bcb2d1781d623d1e Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 25 Apr 2008 08:24:58 +0200 Subject: help: use "man..cmd" as custom man viewer command Currently "git help -m GITCMD" is restricted to a set of man viewers defined at compile time. You can subvert the "man..path" to force "git help -m" to use a different man, viewer, but if you have a man viewer whose invocation syntax does not match one of the current tools then you would have to write a wrapper script for it. This patch adds a git config variable "man..cmd" which allows a more flexible man viewer choice. If you run "git help -m GITCMD" with the "man.viewer" config variable set to an unrecognized tool then it will query the "man..cmd" config variable. If this variable exists, then the specified tool will be treated as a custom man viewer and it will be run in a shell with the man page name of the GITCMD added as extra parameter. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- help.c | 58 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 18 deletions(-) (limited to 'help.c') diff --git a/help.c b/help.c index 483e1e9c3..af80979fc 100644 --- a/help.c +++ b/help.c @@ -163,7 +163,15 @@ static void exec_man_man(const char* path, const char *page) warning("failed to exec '%s': %s", path, strerror(errno)); } -static void do_add_man_viewer(const char *name) +static void exec_man_cmd(const char *cmd, const char *page) +{ + struct strbuf shell_cmd = STRBUF_INIT; + strbuf_addf(&shell_cmd, "%s %s", cmd, page); + execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL); + warning("failed to exec '%s': %s", cmd, strerror(errno)); +} + +static void add_man_viewer(const char *name) { struct man_viewer_list **p = &man_viewer_list; size_t len = strlen(name); @@ -181,16 +189,6 @@ static int supported_man_viewer(const char *name, size_t len) !strncasecmp("konqueror", name, len)); } -static int add_man_viewer(const char *value) -{ - if (supported_man_viewer(value, strlen(value))) - do_add_man_viewer(value); - else - warning("'%s': unsupported man viewer.", value); - - return 0; -} - static void do_add_man_viewer_info(const char *name, size_t len, const char *value) @@ -210,7 +208,23 @@ static int add_man_viewer_path(const char *name, if (supported_man_viewer(name, len)) do_add_man_viewer_info(name, len, value); else - warning("'%s': path for unsupported man viewer.", name); + warning("'%s': path for unsupported man viewer.\n" + "Please consider using 'man..cmd' instead.", + name); + + return 0; +} + +static int add_man_viewer_cmd(const char *name, + size_t len, + const char *value) +{ + if (supported_man_viewer(name, len)) + warning("'%s': cmd for supported man viewer.\n" + "Please consider using 'man..path' instead.", + name); + else + do_add_man_viewer_info(name, len, value); return 0; } @@ -228,6 +242,11 @@ static int add_man_viewer_info(const char *var, const char *value) return config_error_nonbool(var); return add_man_viewer_path(name, subkey - name, value); } + if (!strcmp(subkey, ".cmd")) { + if (!value) + return config_error_nonbool(var); + return add_man_viewer_cmd(name, subkey - name, value); + } warning("'%s': unsupported man viewer sub key.", subkey); return 0; @@ -244,7 +263,8 @@ static int git_help_config(const char *var, const char *value) if (!strcmp(var, "man.viewer")) { if (!value) return config_error_nonbool(var); - return add_man_viewer(value); + add_man_viewer(value); + return 0; } if (!prefixcmp(var, "man.")) return add_man_viewer_info(var, value); @@ -546,16 +566,18 @@ static void setup_man_path(void) static void exec_viewer(const char *name, const char *page) { - const char *path = get_man_viewer_info(name); + const char *info = get_man_viewer_info(name); if (!strcasecmp(name, "man")) - exec_man_man(path, page); + exec_man_man(info, page); else if (!strcasecmp(name, "woman")) - exec_woman_emacs(path, page); + exec_woman_emacs(info, page); else if (!strcasecmp(name, "konqueror")) - exec_man_konqueror(path, page); + exec_man_konqueror(info, page); + else if (info) + exec_man_cmd(info, page); else - warning("'%s': unsupported man viewer.", name); + warning("'%s': unknown man viewer.", name); } static void show_man_page(const char *git_cmd) -- cgit v1.2.1 From ef90d6d4208a5130185b04f06e5f90a5f9959fe3 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 14 May 2008 18:46:53 +0100 Subject: Provide git_config with a callback-data parameter git_config() only had a function parameter, but no callback data parameter. This assumes that all callback functions only modify global variables. With this patch, every callback gets a void * parameter, and it is hoped that this will help the libification effort. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- help.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'help.c') diff --git a/help.c b/help.c index af80979fc..d89d43796 100644 --- a/help.c +++ b/help.c @@ -252,7 +252,7 @@ static int add_man_viewer_info(const char *var, const char *value) return 0; } -static int git_help_config(const char *var, const char *value) +static int git_help_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "help.format")) { if (!value) @@ -269,7 +269,7 @@ static int git_help_config(const char *var, const char *value) if (!prefixcmp(var, "man.")) return add_man_viewer_info(var, value); - return git_default_config(var, value); + return git_default_config(var, value, cb); } /* most GUI terminals set COLUMNS (although some don't export it) */ @@ -641,7 +641,7 @@ int cmd_help(int argc, const char **argv, const char *prefix) const char *alias; setup_git_directory_gently(&nongit); - git_config(git_help_config); + git_config(git_help_config, NULL); argc = parse_options(argc, argv, builtin_help_options, builtin_help_usage, 0); -- cgit v1.2.1 From b7d9681974e61959f10c7b2c1063b7781c5b904e Mon Sep 17 00:00:00 2001 From: Teemu Likonen Date: Fri, 6 Jun 2008 00:15:36 +0300 Subject: Print info about "git help COMMAND" on git's main usage pages Git's main usage pages did not show "git help" as a way to get more information on a specific subcommand. This patch adds an info line after the list of git commands currently printed by "git", "git help", "git --help" and "git help --all". Signed-off-by: Teemu Likonen Signed-off-by: Junio C Hamano --- help.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'help.c') diff --git a/help.c b/help.c index d89d43796..8aff94c64 100644 --- a/help.c +++ b/help.c @@ -649,12 +649,14 @@ int cmd_help(int argc, const char **argv, const char *prefix) if (show_all) { printf("usage: %s\n\n", git_usage_string); list_commands(); + printf("%s\n", git_more_info_string); return 0; } if (!argv[0]) { printf("usage: %s\n\n", git_usage_string); list_common_cmds_help(); + printf("\n%s\n", git_more_info_string); return 0; } -- cgit v1.2.1 From cc3b7a9732f940cb0249a12cb3c02e3d83723eb0 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Mon, 14 Jan 2008 14:05:33 +0100 Subject: Windows: Make 'git help -a' work. git help -a scans the PATH for git commands. On Windows it failed for two reasons: - The PATH separator is ';', not ':' on Windows. - stat() does not set the executable bit. We now open the file and guess whether it is executable. The result of the guess is good enough for the list of git commands, but it is of no use for a general stat() implementation because (1) it is a guess, (2) the user has no way to influence the outcome (via chmod or similar), and (3) it would reduce stat() performance by an unacceptable amount. Therefore, this strategy is a special-case local to help.c. Signed-off-by: Johannes Sixt --- help.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'help.c') diff --git a/help.c b/help.c index 8aff94c64..6c16fb4aa 100644 --- a/help.c +++ b/help.c @@ -391,6 +391,32 @@ static void pretty_print_string_list(struct cmdnames *cmds, int longest) } } +static int is_executable(const char *name) +{ + struct stat st; + + if (stat(name, &st) || /* stat, not lstat */ + !S_ISREG(st.st_mode)) + return 0; + +#ifdef __MINGW32__ + /* cannot trust the executable bit, peek into the file instead */ + char buf[3] = { 0 }; + int n; + int fd = open(name, O_RDONLY); + st.st_mode &= ~S_IXUSR; + if (fd >= 0) { + n = read(fd, buf, 2); + if (n == 2) + /* DOS executables start with "MZ" */ + if (!strcmp(buf, "#!") || !strcmp(buf, "MZ")) + st.st_mode |= S_IXUSR; + close(fd); + } +#endif + return st.st_mode & S_IXUSR; +} + static unsigned int list_commands_in_dir(struct cmdnames *cmds, const char *path) { @@ -404,15 +430,12 @@ static unsigned int list_commands_in_dir(struct cmdnames *cmds, return 0; while ((de = readdir(dir)) != NULL) { - struct stat st; int entlen; if (prefixcmp(de->d_name, prefix)) continue; - if (stat(de->d_name, &st) || /* stat, not lstat */ - !S_ISREG(st.st_mode) || - !(st.st_mode & S_IXUSR)) + if (!is_executable(de->d_name)) continue; entlen = strlen(de->d_name) - prefix_len; @@ -447,7 +470,7 @@ static unsigned int load_command_list(void) path = paths = xstrdup(env_path); while (1) { - if ((colon = strchr(path, ':'))) + if ((colon = strchr(path, PATH_SEP))) *colon = 0; len = list_commands_in_dir(&other_cmds, path); -- cgit v1.2.1 From 2dce956e397be8a769624e8693565b8a30056060 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 28 Jun 2008 06:35:03 +0200 Subject: help: check early if we have a command, if not try a documentation topic Before this patch, something like "git help tutorial" did not work, people had to use "git help gittutorial" which is not very intuitive. This patch uses the "is_git_command" function to test early if the argument passed to "git help" is a git command, and if this is not the case then we prefix the argument with "git" instead of "git-". This way, things like "git help tutorial" or "git help glossary" will work fine. The little downside of this patch is that the "is_git_command" is a little bit slow. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- help.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'help.c') diff --git a/help.c b/help.c index 8aff94c64..5d1a773ad 100644 --- a/help.c +++ b/help.c @@ -527,20 +527,26 @@ static int is_git_command(const char *s) is_in_cmdlist(&other_cmds, s); } +static const char *prepend(const char *prefix, const char *cmd) +{ + size_t pre_len = strlen(prefix); + size_t cmd_len = strlen(cmd); + char *p = xmalloc(pre_len + cmd_len + 1); + memcpy(p, prefix, pre_len); + strcpy(p + pre_len, cmd); + return p; +} + static const char *cmd_to_page(const char *git_cmd) { if (!git_cmd) return "git"; else if (!prefixcmp(git_cmd, "git")) return git_cmd; - else { - int page_len = strlen(git_cmd) + 4; - char *p = xmalloc(page_len + 1); - strcpy(p, "git-"); - strcpy(p + 4, git_cmd); - p[page_len] = 0; - return p; - } + else if (is_git_command(git_cmd)) + return prepend("git-", git_cmd); + else + return prepend("git", git_cmd); } static void setup_man_path(void) -- cgit v1.2.1 From 1b1dd23f2d6a707b7077cdf6bc6d4055bd0bfb7d Mon Sep 17 00:00:00 2001 From: Stephan Beyer Date: Sun, 13 Jul 2008 15:36:15 +0200 Subject: Make usage strings dash-less When you misuse a git command, you are shown the usage string. But this is currently shown in the dashed form. So if you just copy what you see, it will not work, when the dashed form is no longer supported. This patch makes git commands show the dash-less version. For shell scripts that do not specify OPTIONS_SPEC, git-sh-setup.sh generates a dash-less usage string now. Signed-off-by: Stephan Beyer Signed-off-by: Junio C Hamano --- help.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'help.c') diff --git a/help.c b/help.c index ca9632b6c..ee15955b0 100644 --- a/help.c +++ b/help.c @@ -40,7 +40,7 @@ static struct option builtin_help_options[] = { }; static const char * const builtin_help_usage[] = { - "git-help [--all] [--man|--web|--info] [command]", + "git help [--all] [--man|--web|--info] [command]", NULL }; -- cgit v1.2.1 From 868da8d5e329c951f0d0cd049a8f9fecda64d388 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Sun, 13 Jul 2008 22:31:19 +0200 Subject: help.c: Add support for htmldir relative to git_exec_path() If htmldir (in the Makefile) is a relative path, this path will now be interpreted relative to git_exec_path. This can be used to create an installation that can be moved to a different directory without re-compiling. The Windows installer (msysgit) is an example for such a setup. Note that the Makefile maps htmldir to the define GIT_HTML_PATH. Signed-off-by: Steffen Prohaska Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- help.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'help.c') diff --git a/help.c b/help.c index ca9632b6c..0f055bf9a 100644 --- a/help.c +++ b/help.c @@ -633,13 +633,15 @@ static void show_info_page(const char *git_cmd) static void get_html_page_path(struct strbuf *page_path, const char *page) { struct stat st; + const char *html_path = system_path(GIT_HTML_PATH); /* 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); + if (stat(mkpath("%s/git.html", html_path), &st) + || !S_ISREG(st.st_mode)) + die("'%s': not a documentation directory.", html_path); strbuf_init(page_path, 0); - strbuf_addf(page_path, GIT_HTML_PATH "/%s.html", page); + strbuf_addf(page_path, "%s/%s.html", html_path, page); } static void show_html_page(const char *git_cmd) -- cgit v1.2.1 From 4804aabcdbffb41dba96825ca2693ea45830a108 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Sun, 13 Jul 2008 22:31:20 +0200 Subject: help (Windows): Display HTML in default browser using Windows' shell API The system's default browser for displaying HTML help pages is now used directly on Windows, instead of launching git-web--browser, which requires a Unix shell. Avoiding MSYS' bash when possible is good because it avoids potential path translation issues. In this case it is not too hard to avoid launching a shell, so let's avoid it. The Windows-specific code is implemented in compat/mingw.c to avoid platform-specific code in the main code base. On Windows, open_html is provided as a define. If open_html is not defined, git-web--browse is used. This approach avoids platform-specific ifdefs by using per-function ifdefs. The "ifndef open_html" together with the introductory comment should sufficiently warn developers, so that they hopefully will not break this mechanism. Signed-off-by: Steffen Prohaska Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- help.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'help.c') diff --git a/help.c b/help.c index 0f055bf9a..52d39b88a 100644 --- a/help.c +++ b/help.c @@ -644,6 +644,18 @@ static void get_html_page_path(struct strbuf *page_path, const char *page) strbuf_addf(page_path, "%s/%s.html", html_path, page); } +/* + * If open_html is not defined in a platform-specific way (see for + * example compat/mingw.h), we use the script web--browse to display + * HTML. + */ +#ifndef open_html +void open_html(const char *path) +{ + execl_git_cmd("web--browse", "-c", "help.browser", path, NULL); +} +#endif + static void show_html_page(const char *git_cmd) { const char *page = cmd_to_page(git_cmd); @@ -651,7 +663,7 @@ static void show_html_page(const char *git_cmd) get_html_page_path(&page_path, page); - execl_git_cmd("web--browse", "-c", "help.browser", page_path.buf, NULL); + open_html(page_path.buf); } void help_unknown_cmd(const char *cmd) -- cgit v1.2.1 From f5d600e2dd8721d7b9177f1c82fe54822d9f1d62 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 27 Jul 2008 22:34:14 +0200 Subject: Avoid chdir() in list_commands_in_dir() The function list_commands_in_dir() tried to be lazy and just chdir() to the directory which entries it listed, so that the check if the file is executable could be done on dir->d_name. However, there is no good reason to jump around wildly just to find all Git commands. Instead, have a strbuf and construct the full path dynamically. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- help.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'help.c') diff --git a/help.c b/help.c index bfc84aed1..3cb196289 100644 --- a/help.c +++ b/help.c @@ -425,17 +425,24 @@ static unsigned int list_commands_in_dir(struct cmdnames *cmds, int prefix_len = strlen(prefix); DIR *dir = opendir(path); struct dirent *de; + struct strbuf buf = STRBUF_INIT; + int len; - if (!dir || chdir(path)) + if (!dir) return 0; + strbuf_addf(&buf, "%s/", path); + len = buf.len; + while ((de = readdir(dir)) != NULL) { int entlen; if (prefixcmp(de->d_name, prefix)) continue; - if (!is_executable(de->d_name)) + strbuf_setlen(&buf, len); + strbuf_addstr(&buf, de->d_name); + if (!is_executable(buf.buf)) continue; entlen = strlen(de->d_name) - prefix_len; @@ -448,6 +455,7 @@ static unsigned int list_commands_in_dir(struct cmdnames *cmds, add_cmdname(cmds, de->d_name + prefix_len, entlen); } closedir(dir); + strbuf_release(&buf); return longest; } -- cgit v1.2.1