]> git.ipfire.org Git - thirdparty/git.git/blobdiff - help.c
Merge branch 'jt/t5500-unflake'
[thirdparty/git.git] / help.c
diff --git a/help.c b/help.c
index 96f6d221edc30c3bb8241032b837114693b53a53..1de9c0d589cd9b615b1b20d60e06b9601d08fe8f 100644 (file)
--- a/help.c
+++ b/help.c
@@ -34,7 +34,7 @@ static struct category_description main_categories[] = {
        { 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_synchingrepositories, N_("Low-level Commands / Syncing Repositories") },
        { CAT_purehelpers, N_("Low-level Commands / Internal Helpers") },
        { 0, NULL }
 };
@@ -83,8 +83,10 @@ static void print_command_list(const struct cmdname_help *cmds,
 
        for (i = 0; cmds[i].name; i++) {
                if (cmds[i].category & mask) {
+                       size_t len = strlen(cmds[i].name);
                        printf("   %s   ", cmds[i].name);
-                       mput_char(' ', longest - strlen(cmds[i].name));
+                       if (longest > len)
+                               mput_char(' ', longest - len);
                        puts(_(cmds[i].help));
                }
        }
@@ -98,7 +100,8 @@ static int cmd_name_cmp(const void *elem1, const void *elem2)
        return strcmp(e1->name, e2->name);
 }
 
-static void print_cmd_by_category(const struct category_description *catdesc)
+static void print_cmd_by_category(const struct category_description *catdesc,
+                                 int *longest_p)
 {
        struct cmdname_help *cmds;
        int longest = 0;
@@ -124,6 +127,8 @@ static void print_cmd_by_category(const struct category_description *catdesc)
                print_command_list(cmds, mask, longest);
        }
        free(cmds);
+       if (longest_p)
+               *longest_p = longest;
 }
 
 void add_cmdname(struct cmdnames *cmds, const char *name, int len)
@@ -307,7 +312,7 @@ void list_commands(unsigned int colopts,
 void list_common_cmds_help(void)
 {
        puts(_("These are common Git commands used in various situations:"));
-       print_cmd_by_category(common_categories);
+       print_cmd_by_category(common_categories, NULL);
 }
 
 void list_all_main_cmds(struct string_list *list)
@@ -370,13 +375,6 @@ 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;
 
@@ -388,8 +386,8 @@ void list_cmds_by_config(struct string_list *list)
                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);
+               if (sb.buf[0] == '-')
+                       string_list_remove(list, sb.buf + 1, 0);
                else
                        string_list_insert(list, sb.buf);
                strbuf_release(&sb);
@@ -405,98 +403,59 @@ void list_common_guides_help(void)
                { CAT_guide, N_("The common Git guides are:") },
                { 0, NULL }
        };
-       print_cmd_by_category(catdesc);
+       print_cmd_by_category(catdesc, NULL);
        putchar('\n');
 }
 
-struct slot_expansion {
-       const char *prefix;
-       const char *placeholder;
-       void (*fn)(struct string_list *list, const char *prefix);
-       int found;
-};
-
-void list_config_help(int for_human)
-{
-       struct slot_expansion slot_expansions[] = {
-               { "advice", "*", list_config_advices },
-               { "color.branch", "<slot>", list_config_color_branch_slots },
-               { "color.decorate", "<slot>", list_config_color_decorate_slots },
-               { "color.diff", "<slot>", list_config_color_diff_slots },
-               { "color.grep", "<slot>", list_config_color_grep_slots },
-               { "color.interactive", "<slot>", list_config_color_interactive_slots },
-               { "color.remote", "<slot>", list_config_color_sideband_slots },
-               { "color.status", "<slot>", list_config_color_status_slots },
-               { "fsck", "<msg-id>", list_config_fsck_msg_ids },
-               { "receive.fsck", "<msg-id>", list_config_fsck_msg_ids },
-               { NULL, NULL, NULL }
-       };
-       const char **p;
-       struct slot_expansion *e;
-       struct string_list keys = STRING_LIST_INIT_DUP;
-       int i;
+static int get_alias(const char *var, const char *value, void *data)
+{
+       struct string_list *list = data;
 
-       for (p = config_name_list; *p; p++) {
-               const char *var = *p;
-               struct strbuf sb = STRBUF_INIT;
+       if (skip_prefix(var, "alias.", &var))
+               string_list_append(list, var)->util = xstrdup(value);
 
-               for (e = slot_expansions; e->prefix; e++) {
+       return 0;
+}
 
-                       strbuf_reset(&sb);
-                       strbuf_addf(&sb, "%s.%s", e->prefix, e->placeholder);
-                       if (!strcasecmp(var, sb.buf)) {
-                               e->fn(&keys, e->prefix);
-                               e->found++;
-                               break;
-                       }
-               }
-               strbuf_release(&sb);
-               if (!e->prefix)
-                       string_list_append(&keys, var);
+void list_all_cmds_help(void)
+{
+       struct string_list others = STRING_LIST_INIT_DUP;
+       struct string_list alias_list = STRING_LIST_INIT_DUP;
+       struct cmdname_help *aliases;
+       int i, longest;
+
+       printf_ln(_("See 'git help <command>' to read about a specific subcommand"));
+       print_cmd_by_category(main_categories, &longest);
+
+       list_all_other_cmds(&others);
+       if (others.nr)
+               printf("\n%s\n", _("External commands"));
+       for (i = 0; i < others.nr; i++)
+               printf("   %s\n", others.items[i].string);
+       string_list_clear(&others, 0);
+
+       git_config(get_alias, &alias_list);
+       string_list_sort(&alias_list);
+
+       for (i = 0; i < alias_list.nr; i++) {
+               size_t len = strlen(alias_list.items[i].string);
+               if (longest < len)
+                       longest = len;
        }
 
-       for (e = slot_expansions; e->prefix; e++)
-               if (!e->found)
-                       BUG("slot_expansion %s.%s is not used",
-                           e->prefix, e->placeholder);
-
-       string_list_sort(&keys);
-       for (i = 0; i < keys.nr; i++) {
-               const char *var = keys.items[i].string;
-               const char *wildcard, *tag, *cut;
-
-               if (for_human) {
-                       puts(var);
-                       continue;
-               }
-
-               wildcard = strchr(var, '*');
-               tag = strchr(var, '<');
-
-               if (!wildcard && !tag) {
-                       puts(var);
-                       continue;
+       if (alias_list.nr) {
+               printf("\n%s\n", _("Command aliases"));
+               ALLOC_ARRAY(aliases, alias_list.nr + 1);
+               for (i = 0; i < alias_list.nr; i++) {
+                       aliases[i].name = alias_list.items[i].string;
+                       aliases[i].help = alias_list.items[i].util;
+                       aliases[i].category = 1;
                }
-
-               if (wildcard && !tag)
-                       cut = wildcard;
-               else if (!wildcard && tag)
-                       cut = tag;
-               else
-                       cut = wildcard < tag ? wildcard : tag;
-
-               /*
-                * We may produce duplicates, but that's up to
-                * git-completion.bash to handle
-                */
-               printf("%.*s\n", (int)(cut - var), var);
+               aliases[alias_list.nr].name = NULL;
+               print_command_list(aliases, 1, longest);
+               free(aliases);
        }
-       string_list_clear(&keys, 0);
-}
-
-void list_all_cmds_help(void)
-{
-       print_cmd_by_category(main_categories);
+       string_list_clear(&alias_list, 1);
 }
 
 int is_in_cmdlist(struct cmdnames *c, const char *s)
@@ -663,8 +622,32 @@ const char *help_unknown_cmd(const char *cmd)
        exit(1);
 }
 
+void get_version_info(struct strbuf *buf, int show_build_options)
+{
+       /*
+        * The format of this string should be kept stable for compatibility
+        * with external projects that rely on the output of "git version".
+        *
+        * Always show the version, even if other options are given.
+        */
+       strbuf_addf(buf, "git version %s\n", git_version_string);
+
+       if (show_build_options) {
+               strbuf_addf(buf, "cpu: %s\n", GIT_HOST_CPU);
+               if (git_built_from_commit_string[0])
+                       strbuf_addf(buf, "built from commit: %s\n",
+                              git_built_from_commit_string);
+               else
+                       strbuf_addstr(buf, "no commit associated with this build\n");
+               strbuf_addf(buf, "sizeof-long: %d\n", (int)sizeof(long));
+               strbuf_addf(buf, "sizeof-size_t: %d\n", (int)sizeof(size_t));
+               /* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */
+       }
+}
+
 int cmd_version(int argc, const char **argv, const char *prefix)
 {
+       struct strbuf buf = STRBUF_INIT;
        int build_options = 0;
        const char * const usage[] = {
                N_("git version [<options>]"),
@@ -678,25 +661,11 @@ int cmd_version(int argc, const char **argv, const char *prefix)
 
        argc = parse_options(argc, argv, prefix, options, usage, 0);
 
-       /*
-        * The format of this string should be kept stable for compatibility
-        * with external projects that rely on the output of "git version".
-        *
-        * Always show the version, even if other options are given.
-        */
-       printf("git version %s\n", git_version_string);
+       get_version_info(&buf, build_options);
+       printf("%s", buf.buf);
+
+       strbuf_release(&buf);
 
-       if (build_options) {
-               printf("cpu: %s\n", GIT_HOST_CPU);
-               if (git_built_from_commit_string[0])
-                       printf("built from commit: %s\n",
-                              git_built_from_commit_string);
-               else
-                       printf("no commit associated with this build\n");
-               printf("sizeof-long: %d\n", (int)sizeof(long));
-               printf("sizeof-size_t: %d\n", (int)sizeof(size_t));
-               /* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */
-       }
        return 0;
 }
 
@@ -710,19 +679,19 @@ static int append_similar_ref(const char *refname, const struct object_id *oid,
 {
        struct similar_ref_cb *cb = (struct similar_ref_cb *)(cb_data);
        char *branch = strrchr(refname, '/') + 1;
-       const char *remote;
 
        /* A remote branch of the same name is deemed similar */
-       if (skip_prefix(refname, "refs/remotes/", &remote) &&
+       if (starts_with(refname, "refs/remotes/") &&
            !strcmp(branch, cb->base_ref))
-               string_list_append(cb->similar_refs, remote);
+               string_list_append_nodup(cb->similar_refs,
+                                        shorten_unambiguous_ref(refname, 1));
        return 0;
 }
 
 static struct string_list guess_refs(const char *ref)
 {
        struct similar_ref_cb ref_cb;
-       struct string_list similar_refs = STRING_LIST_INIT_NODUP;
+       struct string_list similar_refs = STRING_LIST_INIT_DUP;
 
        ref_cb.base_ref = ref;
        ref_cb.similar_refs = &similar_refs;
@@ -730,7 +699,8 @@ static struct string_list guess_refs(const char *ref)
        return similar_refs;
 }
 
-void help_unknown_ref(const char *ref, const char *cmd, const char *error)
+NORETURN void help_unknown_ref(const char *ref, const char *cmd,
+                              const char *error)
 {
        int i;
        struct string_list suggested_refs = guess_refs(ref);