};
static const char * const builtin_help_usage[] = {
- "git-help [--all] [--man|--web|--info] [command]",
+ "git help [--all] [--man|--web|--info] [command]",
NULL
};
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)
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) */
}
}
+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)
{
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;
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);
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)
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);
+}
+
+/*
+ * 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)
{
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)
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);
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;
}