{"thread":{"id":"35595","subject":"[PATCH v2 0/4]","startedAt":"2014-01-02T16:12:07Z","lastAt":"2014-01-22T21:08:45Z","messageCount":16,"participants":["Sebastian Schuberth","Junio C Hamano","Jonathan Nieder","Jeff King","Kent R. Spillner"],"isPatch":true,"patchVersion":2,"patchTotal":4},"messages":[{"id":"232557","messageId":"52C58FD7.6010608@gmail.com","threadId":"35595","inReplyTo":null,"subject":"[PATCH v2 0/4]","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2014-01-02T16:12:07Z","receivedAt":"2014-01-02T16:12:07Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"This is the second iteration of the patches in\n\nhttp://www.spinics.net/lists/git/msg222428.html\nhttp://www.spinics.net/lists/git/msg222429.html\n\nwhich\n\n* adds a commit to use the term \"builtin\" instead of \"internal command\",\n* also modifies the docs accordingly,\n* moves the is_builtin() declaration to the existing builtin.h,\n* finally moves all builtin-related definitions to a new builtin.c file.\n\nSebastian Schuberth (4):\n  Consistently use the term \"builtin\" instead of \"internal command\"\n  Call load_command_list() only when it is needed\n  Speed up is_git_command() by checking early for internal commands\n  Move builtin-related implementations to a new builtin.c file\n\n Documentation/technical/api-builtin.txt |   4 +-\n Makefile                                |   1 +\n builtin.c                               | 225 ++++++++++++++++++++++++++++++\n builtin.h                               |  23 +++\n builtin/help.c                          |   6 +-\n git.c                                   | 238 +-------------------------------\n 6 files changed, 262 insertions(+), 235 deletions(-)\n create mode 100644 builtin.c\n\n-- \n1.8.3-mingw-1\n"},{"id":"232558","messageId":"52C590B0.1020702@gmail.com","threadId":"35595","inReplyTo":"52C58FD7.6010608@gmail.com","subject":"[PATCH v2 1/4] Consistently use the term \"builtin\" instead of \"internal command\"","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2014-01-02T16:15:44Z","receivedAt":"2014-01-02T16:15:44Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"\nSigned-off-by: Sebastian Schuberth <sschuberth@gmail.com>\n---\n Documentation/technical/api-builtin.txt |  2 +-\n git.c                                   | 14 +++++++-------\n 2 files changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/technical/api-builtin.txt b/Documentation/technical/api-builtin.txt\nindex f3c1357..150a02a 100644\n--- a/Documentation/technical/api-builtin.txt\n+++ b/Documentation/technical/api-builtin.txt\n@@ -14,7 +14,7 @@ Git:\n \n . Add the external declaration for the function to `builtin.h`.\n \n-. Add the command to `commands[]` table in `handle_internal_command()`,\n+. Add the command to `commands[]` table in `handle_builtin()`,\n   defined in `git.c`.  The entry should look like:\n \n \t{ \"foo\", cmd_foo, <options> },\ndiff --git a/git.c b/git.c\nindex 3799514..89ab5d7 100644\n--- a/git.c\n+++ b/git.c\n@@ -332,7 +332,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n \treturn 0;\n }\n \n-static void handle_internal_command(int argc, const char **argv)\n+static void handle_builtin(int argc, const char **argv)\n {\n \tconst char *cmd = argv[0];\n \tstatic struct cmd_struct commands[] = {\n@@ -517,8 +517,8 @@ static int run_argv(int *argcp, const char ***argv)\n \tint done_alias = 0;\n \n \twhile (1) {\n-\t\t/* See if it's an internal command */\n-\t\thandle_internal_command(*argcp, *argv);\n+\t\t/* See if it's a builtin */\n+\t\thandle_builtin(*argcp, *argv);\n \n \t\t/* .. then try the external ones */\n \t\texecv_dashed_external(*argv);\n@@ -563,14 +563,14 @@ int main(int argc, char **av)\n \t *  - cannot execute it externally (since it would just do\n \t *    the same thing over again)\n \t *\n-\t * So we just directly call the internal command handler, and\n-\t * die if that one cannot handle it.\n+\t * So we just directly call the builtin handler, and die if\n+\t * that one cannot handle it.\n \t */\n \tif (starts_with(cmd, \"git-\")) {\n \t\tcmd += 4;\n \t\targv[0] = cmd;\n-\t\thandle_internal_command(argc, argv);\n-\t\tdie(\"cannot handle %s internally\", cmd);\n+\t\thandle_builtin(argc, argv);\n+\t\tdie(\"cannot handle %s as a builtin\", cmd);\n \t}\n \n \t/* Look for flags.. */\n-- \n1.8.3-mingw-1\n"},{"id":"232559","messageId":"52C590DE.6030305@gmail.com","threadId":"35595","inReplyTo":"52C58FD7.6010608@gmail.com","subject":"[PATCH v2 2/4] Call load_command_list() only when it is needed","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2014-01-02T16:16:30Z","receivedAt":"2014-01-02T16:16:30Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"This avoids list_commands_in_dir() being called when not needed which is\nquite slow due to file I/O in order to list matching files in a directory.\n\nSigned-off-by: Sebastian Schuberth <sschuberth@gmail.com>\n---\n builtin/help.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/help.c b/builtin/help.c\nindex cc17e67..b6fc15e 100644\n--- a/builtin/help.c\n+++ b/builtin/help.c\n@@ -288,6 +288,7 @@ static struct cmdnames main_cmds, other_cmds;\n \n static int is_git_command(const char *s)\n {\n+\tload_command_list(\"git-\", &main_cmds, &other_cmds);\n \treturn is_in_cmdlist(&main_cmds, s) ||\n \t\tis_in_cmdlist(&other_cmds, s);\n }\n@@ -449,7 +450,6 @@ int cmd_help(int argc, const char **argv, const char *prefix)\n \tint nongit;\n \tconst char *alias;\n \tenum help_format parsed_help_format;\n-\tload_command_list(\"git-\", &main_cmds, &other_cmds);\n \n \targc = parse_options(argc, argv, prefix, builtin_help_options,\n \t\t\tbuiltin_help_usage, 0);\n@@ -458,6 +458,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)\n \tif (show_all) {\n \t\tgit_config(git_help_config, NULL);\n \t\tprintf(_(\"usage: %s%s\"), _(git_usage_string), \"\\n\\n\");\n+\t\tload_command_list(\"git-\", &main_cmds, &other_cmds);\n \t\tlist_commands(colopts, &main_cmds, &other_cmds);\n \t}\n \n-- \n1.8.3-mingw-1\n"},{"id":"232560","messageId":"52C59107.6080005@gmail.com","threadId":"35595","inReplyTo":"52C58FD7.6010608@gmail.com","subject":"[PATCH v2 3/4] Speed up is_git_command() by checking early for internal commands","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2014-01-02T16:17:11Z","receivedAt":"2014-01-02T16:17:11Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"Since 2dce956 is_git_command() is a bit slow as it does file I/O in the\ncall to list_commands_in_dir(). Avoid the file I/O by adding an early\ncheck for internal commands.\n\nSigned-off-by: Sebastian Schuberth <sschuberth@gmail.com>\n---\n Documentation/technical/api-builtin.txt |   4 +-\n builtin.h                               |   2 +\n builtin/help.c                          |   3 +\n git.c                                   | 242 +++++++++++++++++---------------\n 4 files changed, 134 insertions(+), 117 deletions(-)\n\ndiff --git a/Documentation/technical/api-builtin.txt b/Documentation/technical/api-builtin.txt\nindex 150a02a..e3d6e7a 100644\n--- a/Documentation/technical/api-builtin.txt\n+++ b/Documentation/technical/api-builtin.txt\n@@ -14,8 +14,8 @@ Git:\n \n . Add the external declaration for the function to `builtin.h`.\n \n-. Add the command to `commands[]` table in `handle_builtin()`,\n-  defined in `git.c`.  The entry should look like:\n+. Add the command to the `commands[]` table defined in `git.c`.\n+  The entry should look like:\n \n \t{ \"foo\", cmd_foo, <options> },\n +\ndiff --git a/builtin.h b/builtin.h\nindex d4afbfe..c47c110 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -27,6 +27,8 @@ extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,\n \n extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size);\n \n+extern int is_builtin(const char *s);\n+\n extern int cmd_add(int argc, const char **argv, const char *prefix);\n extern int cmd_annotate(int argc, const char **argv, const char *prefix);\n extern int cmd_apply(int argc, const char **argv, const char *prefix);\ndiff --git a/builtin/help.c b/builtin/help.c\nindex b6fc15e..1fdefeb 100644\n--- a/builtin/help.c\n+++ b/builtin/help.c\n@@ -288,6 +288,9 @@ static struct cmdnames main_cmds, other_cmds;\n \n static int is_git_command(const char *s)\n {\n+\tif (is_builtin(s))\n+\t\treturn 1;\n+\n \tload_command_list(\"git-\", &main_cmds, &other_cmds);\n \treturn is_in_cmdlist(&main_cmds, s) ||\n \t\tis_in_cmdlist(&other_cmds, s);\ndiff --git a/git.c b/git.c\nindex 89ab5d7..bba4378 100644\n--- a/git.c\n+++ b/git.c\n@@ -332,124 +332,136 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n \treturn 0;\n }\n \n+static struct cmd_struct commands[] = {\n+\t{ \"add\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"annotate\", cmd_annotate, RUN_SETUP },\n+\t{ \"apply\", cmd_apply, RUN_SETUP_GENTLY },\n+\t{ \"archive\", cmd_archive },\n+\t{ \"bisect--helper\", cmd_bisect__helper, RUN_SETUP },\n+\t{ \"blame\", cmd_blame, RUN_SETUP },\n+\t{ \"branch\", cmd_branch, RUN_SETUP },\n+\t{ \"bundle\", cmd_bundle, RUN_SETUP_GENTLY },\n+\t{ \"cat-file\", cmd_cat_file, RUN_SETUP },\n+\t{ \"check-attr\", cmd_check_attr, RUN_SETUP },\n+\t{ \"check-ignore\", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"check-mailmap\", cmd_check_mailmap, RUN_SETUP },\n+\t{ \"check-ref-format\", cmd_check_ref_format },\n+\t{ \"checkout\", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"checkout-index\", cmd_checkout_index,\n+\t\tRUN_SETUP | NEED_WORK_TREE},\n+\t{ \"cherry\", cmd_cherry, RUN_SETUP },\n+\t{ \"cherry-pick\", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"clean\", cmd_clean, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"clone\", cmd_clone },\n+\t{ \"column\", cmd_column, RUN_SETUP_GENTLY },\n+\t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n+\t{ \"config\", cmd_config, RUN_SETUP_GENTLY },\n+\t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n+\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY },\n+\t{ \"describe\", cmd_describe, RUN_SETUP },\n+\t{ \"diff\", cmd_diff },\n+\t{ \"diff-files\", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"diff-index\", cmd_diff_index, RUN_SETUP },\n+\t{ \"diff-tree\", cmd_diff_tree, RUN_SETUP },\n+\t{ \"fast-export\", cmd_fast_export, RUN_SETUP },\n+\t{ \"fetch\", cmd_fetch, RUN_SETUP },\n+\t{ \"fetch-pack\", cmd_fetch_pack, RUN_SETUP },\n+\t{ \"fmt-merge-msg\", cmd_fmt_merge_msg, RUN_SETUP },\n+\t{ \"for-each-ref\", cmd_for_each_ref, RUN_SETUP },\n+\t{ \"format-patch\", cmd_format_patch, RUN_SETUP },\n+\t{ \"fsck\", cmd_fsck, RUN_SETUP },\n+\t{ \"fsck-objects\", cmd_fsck, RUN_SETUP },\n+\t{ \"gc\", cmd_gc, RUN_SETUP },\n+\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id },\n+\t{ \"grep\", cmd_grep, RUN_SETUP_GENTLY },\n+\t{ \"hash-object\", cmd_hash_object },\n+\t{ \"help\", cmd_help },\n+\t{ \"index-pack\", cmd_index_pack, RUN_SETUP_GENTLY },\n+\t{ \"init\", cmd_init_db },\n+\t{ \"init-db\", cmd_init_db },\n+\t{ \"log\", cmd_log, RUN_SETUP },\n+\t{ \"ls-files\", cmd_ls_files, RUN_SETUP },\n+\t{ \"ls-remote\", cmd_ls_remote, RUN_SETUP_GENTLY },\n+\t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n+\t{ \"mailinfo\", cmd_mailinfo },\n+\t{ \"mailsplit\", cmd_mailsplit },\n+\t{ \"merge\", cmd_merge, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"merge-base\", cmd_merge_base, RUN_SETUP },\n+\t{ \"merge-file\", cmd_merge_file, RUN_SETUP_GENTLY },\n+\t{ \"merge-index\", cmd_merge_index, RUN_SETUP },\n+\t{ \"merge-ours\", cmd_merge_ours, RUN_SETUP },\n+\t{ \"merge-recursive\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"merge-recursive-ours\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"merge-recursive-theirs\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"merge-subtree\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"merge-tree\", cmd_merge_tree, RUN_SETUP },\n+\t{ \"mktag\", cmd_mktag, RUN_SETUP },\n+\t{ \"mktree\", cmd_mktree, RUN_SETUP },\n+\t{ \"mv\", cmd_mv, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n+\t{ \"notes\", cmd_notes, RUN_SETUP },\n+\t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\n+\t{ \"pack-redundant\", cmd_pack_redundant, RUN_SETUP },\n+\t{ \"pack-refs\", cmd_pack_refs, RUN_SETUP },\n+\t{ \"patch-id\", cmd_patch_id },\n+\t{ \"pickaxe\", cmd_blame, RUN_SETUP },\n+\t{ \"prune\", cmd_prune, RUN_SETUP },\n+\t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n+\t{ \"push\", cmd_push, RUN_SETUP },\n+\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n+\t{ \"receive-pack\", cmd_receive_pack },\n+\t{ \"reflog\", cmd_reflog, RUN_SETUP },\n+\t{ \"remote\", cmd_remote, RUN_SETUP },\n+\t{ \"remote-ext\", cmd_remote_ext },\n+\t{ \"remote-fd\", cmd_remote_fd },\n+\t{ \"repack\", cmd_repack, RUN_SETUP },\n+\t{ \"replace\", cmd_replace, RUN_SETUP },\n+\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n+\t{ \"reset\", cmd_reset, RUN_SETUP },\n+\t{ \"rev-list\", cmd_rev_list, RUN_SETUP },\n+\t{ \"rev-parse\", cmd_rev_parse },\n+\t{ \"revert\", cmd_revert, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"rm\", cmd_rm, RUN_SETUP },\n+\t{ \"send-pack\", cmd_send_pack, RUN_SETUP },\n+\t{ \"shortlog\", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },\n+\t{ \"show\", cmd_show, RUN_SETUP },\n+\t{ \"show-branch\", cmd_show_branch, RUN_SETUP },\n+\t{ \"show-ref\", cmd_show_ref, RUN_SETUP },\n+\t{ \"stage\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"status\", cmd_status, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"stripspace\", cmd_stripspace },\n+\t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n+\t{ \"tag\", cmd_tag, RUN_SETUP },\n+\t{ \"unpack-file\", cmd_unpack_file, RUN_SETUP },\n+\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP },\n+\t{ \"update-index\", cmd_update_index, RUN_SETUP },\n+\t{ \"update-ref\", cmd_update_ref, RUN_SETUP },\n+\t{ \"update-server-info\", cmd_update_server_info, RUN_SETUP },\n+\t{ \"upload-archive\", cmd_upload_archive },\n+\t{ \"upload-archive--writer\", cmd_upload_archive_writer },\n+\t{ \"var\", cmd_var, RUN_SETUP_GENTLY },\n+\t{ \"verify-pack\", cmd_verify_pack },\n+\t{ \"verify-tag\", cmd_verify_tag, RUN_SETUP },\n+\t{ \"version\", cmd_version },\n+\t{ \"whatchanged\", cmd_whatchanged, RUN_SETUP },\n+\t{ \"write-tree\", cmd_write_tree, RUN_SETUP },\n+};\n+\n+int is_builtin(const char *s)\n+{\n+\tint i;\n+\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n+\t\tstruct cmd_struct *p = commands+i;\n+\t\tif (!strcmp(s, p->cmd))\n+\t\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n static void handle_builtin(int argc, const char **argv)\n {\n \tconst char *cmd = argv[0];\n-\tstatic struct cmd_struct commands[] = {\n-\t\t{ \"add\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"annotate\", cmd_annotate, RUN_SETUP },\n-\t\t{ \"apply\", cmd_apply, RUN_SETUP_GENTLY },\n-\t\t{ \"archive\", cmd_archive },\n-\t\t{ \"bisect--helper\", cmd_bisect__helper, RUN_SETUP },\n-\t\t{ \"blame\", cmd_blame, RUN_SETUP },\n-\t\t{ \"branch\", cmd_branch, RUN_SETUP },\n-\t\t{ \"bundle\", cmd_bundle, RUN_SETUP_GENTLY },\n-\t\t{ \"cat-file\", cmd_cat_file, RUN_SETUP },\n-\t\t{ \"check-attr\", cmd_check_attr, RUN_SETUP },\n-\t\t{ \"check-ignore\", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"check-mailmap\", cmd_check_mailmap, RUN_SETUP },\n-\t\t{ \"check-ref-format\", cmd_check_ref_format },\n-\t\t{ \"checkout\", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"checkout-index\", cmd_checkout_index,\n-\t\t\tRUN_SETUP | NEED_WORK_TREE},\n-\t\t{ \"cherry\", cmd_cherry, RUN_SETUP },\n-\t\t{ \"cherry-pick\", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"clean\", cmd_clean, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"clone\", cmd_clone },\n-\t\t{ \"column\", cmd_column, RUN_SETUP_GENTLY },\n-\t\t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n-\t\t{ \"config\", cmd_config, RUN_SETUP_GENTLY },\n-\t\t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n-\t\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY },\n-\t\t{ \"describe\", cmd_describe, RUN_SETUP },\n-\t\t{ \"diff\", cmd_diff },\n-\t\t{ \"diff-files\", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"diff-index\", cmd_diff_index, RUN_SETUP },\n-\t\t{ \"diff-tree\", cmd_diff_tree, RUN_SETUP },\n-\t\t{ \"fast-export\", cmd_fast_export, RUN_SETUP },\n-\t\t{ \"fetch\", cmd_fetch, RUN_SETUP },\n-\t\t{ \"fetch-pack\", cmd_fetch_pack, RUN_SETUP },\n-\t\t{ \"fmt-merge-msg\", cmd_fmt_merge_msg, RUN_SETUP },\n-\t\t{ \"for-each-ref\", cmd_for_each_ref, RUN_SETUP },\n-\t\t{ \"format-patch\", cmd_format_patch, RUN_SETUP },\n-\t\t{ \"fsck\", cmd_fsck, RUN_SETUP },\n-\t\t{ \"fsck-objects\", cmd_fsck, RUN_SETUP },\n-\t\t{ \"gc\", cmd_gc, RUN_SETUP },\n-\t\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id },\n-\t\t{ \"grep\", cmd_grep, RUN_SETUP_GENTLY },\n-\t\t{ \"hash-object\", cmd_hash_object },\n-\t\t{ \"help\", cmd_help },\n-\t\t{ \"index-pack\", cmd_index_pack, RUN_SETUP_GENTLY },\n-\t\t{ \"init\", cmd_init_db },\n-\t\t{ \"init-db\", cmd_init_db },\n-\t\t{ \"log\", cmd_log, RUN_SETUP },\n-\t\t{ \"ls-files\", cmd_ls_files, RUN_SETUP },\n-\t\t{ \"ls-remote\", cmd_ls_remote, RUN_SETUP_GENTLY },\n-\t\t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n-\t\t{ \"mailinfo\", cmd_mailinfo },\n-\t\t{ \"mailsplit\", cmd_mailsplit },\n-\t\t{ \"merge\", cmd_merge, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"merge-base\", cmd_merge_base, RUN_SETUP },\n-\t\t{ \"merge-file\", cmd_merge_file, RUN_SETUP_GENTLY },\n-\t\t{ \"merge-index\", cmd_merge_index, RUN_SETUP },\n-\t\t{ \"merge-ours\", cmd_merge_ours, RUN_SETUP },\n-\t\t{ \"merge-recursive\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"merge-recursive-ours\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"merge-recursive-theirs\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"merge-subtree\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"merge-tree\", cmd_merge_tree, RUN_SETUP },\n-\t\t{ \"mktag\", cmd_mktag, RUN_SETUP },\n-\t\t{ \"mktree\", cmd_mktree, RUN_SETUP },\n-\t\t{ \"mv\", cmd_mv, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n-\t\t{ \"notes\", cmd_notes, RUN_SETUP },\n-\t\t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\n-\t\t{ \"pack-redundant\", cmd_pack_redundant, RUN_SETUP },\n-\t\t{ \"pack-refs\", cmd_pack_refs, RUN_SETUP },\n-\t\t{ \"patch-id\", cmd_patch_id },\n-\t\t{ \"pickaxe\", cmd_blame, RUN_SETUP },\n-\t\t{ \"prune\", cmd_prune, RUN_SETUP },\n-\t\t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n-\t\t{ \"push\", cmd_push, RUN_SETUP },\n-\t\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n-\t\t{ \"receive-pack\", cmd_receive_pack },\n-\t\t{ \"reflog\", cmd_reflog, RUN_SETUP },\n-\t\t{ \"remote\", cmd_remote, RUN_SETUP },\n-\t\t{ \"remote-ext\", cmd_remote_ext },\n-\t\t{ \"remote-fd\", cmd_remote_fd },\n-\t\t{ \"repack\", cmd_repack, RUN_SETUP },\n-\t\t{ \"replace\", cmd_replace, RUN_SETUP },\n-\t\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n-\t\t{ \"reset\", cmd_reset, RUN_SETUP },\n-\t\t{ \"rev-list\", cmd_rev_list, RUN_SETUP },\n-\t\t{ \"rev-parse\", cmd_rev_parse },\n-\t\t{ \"revert\", cmd_revert, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"rm\", cmd_rm, RUN_SETUP },\n-\t\t{ \"send-pack\", cmd_send_pack, RUN_SETUP },\n-\t\t{ \"shortlog\", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },\n-\t\t{ \"show\", cmd_show, RUN_SETUP },\n-\t\t{ \"show-branch\", cmd_show_branch, RUN_SETUP },\n-\t\t{ \"show-ref\", cmd_show_ref, RUN_SETUP },\n-\t\t{ \"stage\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"status\", cmd_status, RUN_SETUP | NEED_WORK_TREE },\n-\t\t{ \"stripspace\", cmd_stripspace },\n-\t\t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n-\t\t{ \"tag\", cmd_tag, RUN_SETUP },\n-\t\t{ \"unpack-file\", cmd_unpack_file, RUN_SETUP },\n-\t\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP },\n-\t\t{ \"update-index\", cmd_update_index, RUN_SETUP },\n-\t\t{ \"update-ref\", cmd_update_ref, RUN_SETUP },\n-\t\t{ \"update-server-info\", cmd_update_server_info, RUN_SETUP },\n-\t\t{ \"upload-archive\", cmd_upload_archive },\n-\t\t{ \"upload-archive--writer\", cmd_upload_archive_writer },\n-\t\t{ \"var\", cmd_var, RUN_SETUP_GENTLY },\n-\t\t{ \"verify-pack\", cmd_verify_pack },\n-\t\t{ \"verify-tag\", cmd_verify_tag, RUN_SETUP },\n-\t\t{ \"version\", cmd_version },\n-\t\t{ \"whatchanged\", cmd_whatchanged, RUN_SETUP },\n-\t\t{ \"write-tree\", cmd_write_tree, RUN_SETUP },\n-\t};\n \tint i;\n \tstatic const char ext[] = STRIP_EXTENSION;\n \n-- \n1.8.3-mingw-1\n"},{"id":"232561","messageId":"52C59130.4050003@gmail.com","threadId":"35595","inReplyTo":"52C58FD7.6010608@gmail.com","subject":"[PATCH v2 4/4] Move builtin-related implementations to a new builtin.c file","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2014-01-02T16:17:52Z","receivedAt":"2014-01-02T16:17:52Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"Signed-off-by: Sebastian Schuberth <sschuberth@gmail.com>\n---\n Documentation/technical/api-builtin.txt |   2 +-\n Makefile                                |   1 +\n builtin.c                               | 225 ++++++++++++++++++++++++++++++\n builtin.h                               |  21 +++\n git.c                                   | 238 --------------------------------\n 5 files changed, 248 insertions(+), 239 deletions(-)\n create mode 100644 builtin.c\n\ndiff --git a/Documentation/technical/api-builtin.txt b/Documentation/technical/api-builtin.txt\nindex e3d6e7a..d1d946c 100644\n--- a/Documentation/technical/api-builtin.txt\n+++ b/Documentation/technical/api-builtin.txt\n@@ -14,7 +14,7 @@ Git:\n \n . Add the external declaration for the function to `builtin.h`.\n \n-. Add the command to the `commands[]` table defined in `git.c`.\n+. Add the command to the `commands[]` table defined in `builtin.c`.\n   The entry should look like:\n \n \t{ \"foo\", cmd_foo, <options> },\ndiff --git a/Makefile b/Makefile\nindex b4af1e2..2d947e8 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -763,6 +763,7 @@ LIB_OBJS += base85.o\n LIB_OBJS += bisect.o\n LIB_OBJS += blob.o\n LIB_OBJS += branch.o\n+LIB_OBJS += builtin.o\n LIB_OBJS += bulk-checkin.o\n LIB_OBJS += bundle.o\n LIB_OBJS += cache-tree.o\ndiff --git a/builtin.c b/builtin.c\nnew file mode 100644\nindex 0000000..6bdeb7c\n--- /dev/null\n+++ b/builtin.c\n@@ -0,0 +1,225 @@\n+#include \"builtin.h\"\n+\n+static struct cmd_struct commands[] = {\n+\t{ \"add\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"annotate\", cmd_annotate, RUN_SETUP },\n+\t{ \"apply\", cmd_apply, RUN_SETUP_GENTLY },\n+\t{ \"archive\", cmd_archive },\n+\t{ \"bisect--helper\", cmd_bisect__helper, RUN_SETUP },\n+\t{ \"blame\", cmd_blame, RUN_SETUP },\n+\t{ \"branch\", cmd_branch, RUN_SETUP },\n+\t{ \"bundle\", cmd_bundle, RUN_SETUP_GENTLY },\n+\t{ \"cat-file\", cmd_cat_file, RUN_SETUP },\n+\t{ \"check-attr\", cmd_check_attr, RUN_SETUP },\n+\t{ \"check-ignore\", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"check-mailmap\", cmd_check_mailmap, RUN_SETUP },\n+\t{ \"check-ref-format\", cmd_check_ref_format },\n+\t{ \"checkout\", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"checkout-index\", cmd_checkout_index,\n+\t\tRUN_SETUP | NEED_WORK_TREE},\n+\t{ \"cherry\", cmd_cherry, RUN_SETUP },\n+\t{ \"cherry-pick\", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"clean\", cmd_clean, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"clone\", cmd_clone },\n+\t{ \"column\", cmd_column, RUN_SETUP_GENTLY },\n+\t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n+\t{ \"config\", cmd_config, RUN_SETUP_GENTLY },\n+\t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n+\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY },\n+\t{ \"describe\", cmd_describe, RUN_SETUP },\n+\t{ \"diff\", cmd_diff },\n+\t{ \"diff-files\", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"diff-index\", cmd_diff_index, RUN_SETUP },\n+\t{ \"diff-tree\", cmd_diff_tree, RUN_SETUP },\n+\t{ \"fast-export\", cmd_fast_export, RUN_SETUP },\n+\t{ \"fetch\", cmd_fetch, RUN_SETUP },\n+\t{ \"fetch-pack\", cmd_fetch_pack, RUN_SETUP },\n+\t{ \"fmt-merge-msg\", cmd_fmt_merge_msg, RUN_SETUP },\n+\t{ \"for-each-ref\", cmd_for_each_ref, RUN_SETUP },\n+\t{ \"format-patch\", cmd_format_patch, RUN_SETUP },\n+\t{ \"fsck\", cmd_fsck, RUN_SETUP },\n+\t{ \"fsck-objects\", cmd_fsck, RUN_SETUP },\n+\t{ \"gc\", cmd_gc, RUN_SETUP },\n+\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id },\n+\t{ \"grep\", cmd_grep, RUN_SETUP_GENTLY },\n+\t{ \"hash-object\", cmd_hash_object },\n+\t{ \"help\", cmd_help },\n+\t{ \"index-pack\", cmd_index_pack, RUN_SETUP_GENTLY },\n+\t{ \"init\", cmd_init_db },\n+\t{ \"init-db\", cmd_init_db },\n+\t{ \"log\", cmd_log, RUN_SETUP },\n+\t{ \"ls-files\", cmd_ls_files, RUN_SETUP },\n+\t{ \"ls-remote\", cmd_ls_remote, RUN_SETUP_GENTLY },\n+\t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n+\t{ \"mailinfo\", cmd_mailinfo },\n+\t{ \"mailsplit\", cmd_mailsplit },\n+\t{ \"merge\", cmd_merge, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"merge-base\", cmd_merge_base, RUN_SETUP },\n+\t{ \"merge-file\", cmd_merge_file, RUN_SETUP_GENTLY },\n+\t{ \"merge-index\", cmd_merge_index, RUN_SETUP },\n+\t{ \"merge-ours\", cmd_merge_ours, RUN_SETUP },\n+\t{ \"merge-recursive\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"merge-recursive-ours\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"merge-recursive-theirs\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"merge-subtree\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"merge-tree\", cmd_merge_tree, RUN_SETUP },\n+\t{ \"mktag\", cmd_mktag, RUN_SETUP },\n+\t{ \"mktree\", cmd_mktree, RUN_SETUP },\n+\t{ \"mv\", cmd_mv, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n+\t{ \"notes\", cmd_notes, RUN_SETUP },\n+\t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\n+\t{ \"pack-redundant\", cmd_pack_redundant, RUN_SETUP },\n+\t{ \"pack-refs\", cmd_pack_refs, RUN_SETUP },\n+\t{ \"patch-id\", cmd_patch_id },\n+\t{ \"pickaxe\", cmd_blame, RUN_SETUP },\n+\t{ \"prune\", cmd_prune, RUN_SETUP },\n+\t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n+\t{ \"push\", cmd_push, RUN_SETUP },\n+\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n+\t{ \"receive-pack\", cmd_receive_pack },\n+\t{ \"reflog\", cmd_reflog, RUN_SETUP },\n+\t{ \"remote\", cmd_remote, RUN_SETUP },\n+\t{ \"remote-ext\", cmd_remote_ext },\n+\t{ \"remote-fd\", cmd_remote_fd },\n+\t{ \"repack\", cmd_repack, RUN_SETUP },\n+\t{ \"replace\", cmd_replace, RUN_SETUP },\n+\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n+\t{ \"reset\", cmd_reset, RUN_SETUP },\n+\t{ \"rev-list\", cmd_rev_list, RUN_SETUP },\n+\t{ \"rev-parse\", cmd_rev_parse },\n+\t{ \"revert\", cmd_revert, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"rm\", cmd_rm, RUN_SETUP },\n+\t{ \"send-pack\", cmd_send_pack, RUN_SETUP },\n+\t{ \"shortlog\", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },\n+\t{ \"show\", cmd_show, RUN_SETUP },\n+\t{ \"show-branch\", cmd_show_branch, RUN_SETUP },\n+\t{ \"show-ref\", cmd_show_ref, RUN_SETUP },\n+\t{ \"stage\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"status\", cmd_status, RUN_SETUP | NEED_WORK_TREE },\n+\t{ \"stripspace\", cmd_stripspace },\n+\t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n+\t{ \"tag\", cmd_tag, RUN_SETUP },\n+\t{ \"unpack-file\", cmd_unpack_file, RUN_SETUP },\n+\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP },\n+\t{ \"update-index\", cmd_update_index, RUN_SETUP },\n+\t{ \"update-ref\", cmd_update_ref, RUN_SETUP },\n+\t{ \"update-server-info\", cmd_update_server_info, RUN_SETUP },\n+\t{ \"upload-archive\", cmd_upload_archive },\n+\t{ \"upload-archive--writer\", cmd_upload_archive_writer },\n+\t{ \"var\", cmd_var, RUN_SETUP_GENTLY },\n+\t{ \"verify-pack\", cmd_verify_pack },\n+\t{ \"verify-tag\", cmd_verify_tag, RUN_SETUP },\n+\t{ \"version\", cmd_version },\n+\t{ \"whatchanged\", cmd_whatchanged, RUN_SETUP },\n+\t{ \"write-tree\", cmd_write_tree, RUN_SETUP },\n+};\n+\n+int use_pager = -1;\n+\n+void commit_pager_choice(void) {\n+\tswitch (use_pager) {\n+\tcase 0:\n+\t\tsetenv(\"GIT_PAGER\", \"cat\", 1);\n+\t\tbreak;\n+\tcase 1:\n+\t\tsetup_pager();\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+int is_builtin(const char *s)\n+{\n+\tint i;\n+\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n+\t\tstruct cmd_struct *p = commands+i;\n+\t\tif (!strcmp(s, p->cmd))\n+\t\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n+void handle_builtin(int argc, const char **argv)\n+{\n+\tconst char *cmd = argv[0];\n+\tint i;\n+\tstatic const char ext[] = STRIP_EXTENSION;\n+\n+\tif (sizeof(ext) > 1) {\n+\t\ti = strlen(argv[0]) - strlen(ext);\n+\t\tif (i > 0 && !strcmp(argv[0] + i, ext)) {\n+\t\t\tchar *argv0 = xstrdup(argv[0]);\n+\t\t\targv[0] = cmd = argv0;\n+\t\t\targv0[i] = '\\0';\n+\t\t}\n+\t}\n+\n+\t/* Turn \"git cmd --help\" into \"git help cmd\" */\n+\tif (argc > 1 && !strcmp(argv[1], \"--help\")) {\n+\t\targv[1] = argv[0];\n+\t\targv[0] = cmd = \"help\";\n+\t}\n+\n+\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n+\t\tstruct cmd_struct *p = commands+i;\n+\t\tif (strcmp(p->cmd, cmd))\n+\t\t\tcontinue;\n+\t\texit(run_builtin(p, argc, argv));\n+\t}\n+}\n+\n+int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n+{\n+\tint status, help;\n+\tstruct stat st;\n+\tconst char *prefix;\n+\n+\tprefix = NULL;\n+\thelp = argc == 2 && !strcmp(argv[1], \"-h\");\n+\tif (!help) {\n+\t\tif (p->option & RUN_SETUP)\n+\t\t\tprefix = setup_git_directory();\n+\t\tif (p->option & RUN_SETUP_GENTLY) {\n+\t\t\tint nongit_ok;\n+\t\t\tprefix = setup_git_directory_gently(&nongit_ok);\n+\t\t}\n+\n+\t\tif (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY))\n+\t\t\tuse_pager = check_pager_config(p->cmd);\n+\t\tif (use_pager == -1 && p->option & USE_PAGER)\n+\t\t\tuse_pager = 1;\n+\n+\t\tif ((p->option & (RUN_SETUP | RUN_SETUP_GENTLY)) &&\n+\t\t    startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */\n+\t\t\ttrace_repo_setup(prefix);\n+\t}\n+\tcommit_pager_choice();\n+\n+\tif (!help && p->option & NEED_WORK_TREE)\n+\t\tsetup_work_tree();\n+\n+\ttrace_argv_printf(argv, \"trace: built-in: git\");\n+\n+\tstatus = p->fn(argc, argv, prefix);\n+\tif (status)\n+\t\treturn status;\n+\n+\t/* Somebody closed stdout? */\n+\tif (fstat(fileno(stdout), &st))\n+\t\treturn 0;\n+\t/* Ignore write errors for pipes and sockets.. */\n+\tif (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))\n+\t\treturn 0;\n+\n+\t/* Check for ENOSPC and EIO errors.. */\n+\tif (fflush(stdout))\n+\t\tdie_errno(\"write failure on standard output\");\n+\tif (ferror(stdout))\n+\t\tdie(\"unknown write failure on standard output\");\n+\tif (fclose(stdout))\n+\t\tdie_errno(\"close failed on standard output\");\n+\treturn 0;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex c47c110..9388505 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -27,7 +27,28 @@ extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,\n \n extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size);\n \n+#define RUN_SETUP\t\t(1<<0)\n+#define RUN_SETUP_GENTLY\t(1<<1)\n+#define USE_PAGER\t\t(1<<2)\n+/*\n+ * require working tree to be present -- anything uses this needs\n+ * RUN_SETUP for reading from the configuration file.\n+ */\n+#define NEED_WORK_TREE\t\t(1<<3)\n+\n+struct cmd_struct {\n+\tconst char *cmd;\n+\tint (*fn)(int, const char **, const char *);\n+\tint option;\n+};\n+\n+extern int use_pager;\n+\n+extern void commit_pager_choice(void);\n+\n extern int is_builtin(const char *s);\n+extern void handle_builtin(int argc, const char **argv);\n+extern int run_builtin(struct cmd_struct *p, int argc, const char **argv);\n \n extern int cmd_add(int argc, const char **argv, const char *prefix);\n extern int cmd_annotate(int argc, const char **argv, const char *prefix);\ndiff --git a/git.c b/git.c\nindex bba4378..c93e545 100644\n--- a/git.c\n+++ b/git.c\n@@ -19,20 +19,6 @@ const char git_more_info_string[] =\n \t   \"to read about a specific subcommand or concept.\");\n \n static struct startup_info git_startup_info;\n-static int use_pager = -1;\n-\n-static void commit_pager_choice(void) {\n-\tswitch (use_pager) {\n-\tcase 0:\n-\t\tsetenv(\"GIT_PAGER\", \"cat\", 1);\n-\t\tbreak;\n-\tcase 1:\n-\t\tsetup_pager();\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-}\n \n static int handle_options(const char ***argv, int *argc, int *envchanged)\n {\n@@ -264,230 +250,6 @@ static int handle_alias(int *argcp, const char ***argv)\n \treturn ret;\n }\n \n-#define RUN_SETUP\t\t(1<<0)\n-#define RUN_SETUP_GENTLY\t(1<<1)\n-#define USE_PAGER\t\t(1<<2)\n-/*\n- * require working tree to be present -- anything uses this needs\n- * RUN_SETUP for reading from the configuration file.\n- */\n-#define NEED_WORK_TREE\t\t(1<<3)\n-\n-struct cmd_struct {\n-\tconst char *cmd;\n-\tint (*fn)(int, const char **, const char *);\n-\tint option;\n-};\n-\n-static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n-{\n-\tint status, help;\n-\tstruct stat st;\n-\tconst char *prefix;\n-\n-\tprefix = NULL;\n-\thelp = argc == 2 && !strcmp(argv[1], \"-h\");\n-\tif (!help) {\n-\t\tif (p->option & RUN_SETUP)\n-\t\t\tprefix = setup_git_directory();\n-\t\tif (p->option & RUN_SETUP_GENTLY) {\n-\t\t\tint nongit_ok;\n-\t\t\tprefix = setup_git_directory_gently(&nongit_ok);\n-\t\t}\n-\n-\t\tif (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY))\n-\t\t\tuse_pager = check_pager_config(p->cmd);\n-\t\tif (use_pager == -1 && p->option & USE_PAGER)\n-\t\t\tuse_pager = 1;\n-\n-\t\tif ((p->option & (RUN_SETUP | RUN_SETUP_GENTLY)) &&\n-\t\t    startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */\n-\t\t\ttrace_repo_setup(prefix);\n-\t}\n-\tcommit_pager_choice();\n-\n-\tif (!help && p->option & NEED_WORK_TREE)\n-\t\tsetup_work_tree();\n-\n-\ttrace_argv_printf(argv, \"trace: built-in: git\");\n-\n-\tstatus = p->fn(argc, argv, prefix);\n-\tif (status)\n-\t\treturn status;\n-\n-\t/* Somebody closed stdout? */\n-\tif (fstat(fileno(stdout), &st))\n-\t\treturn 0;\n-\t/* Ignore write errors for pipes and sockets.. */\n-\tif (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))\n-\t\treturn 0;\n-\n-\t/* Check for ENOSPC and EIO errors.. */\n-\tif (fflush(stdout))\n-\t\tdie_errno(\"write failure on standard output\");\n-\tif (ferror(stdout))\n-\t\tdie(\"unknown write failure on standard output\");\n-\tif (fclose(stdout))\n-\t\tdie_errno(\"close failed on standard output\");\n-\treturn 0;\n-}\n-\n-static struct cmd_struct commands[] = {\n-\t{ \"add\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"annotate\", cmd_annotate, RUN_SETUP },\n-\t{ \"apply\", cmd_apply, RUN_SETUP_GENTLY },\n-\t{ \"archive\", cmd_archive },\n-\t{ \"bisect--helper\", cmd_bisect__helper, RUN_SETUP },\n-\t{ \"blame\", cmd_blame, RUN_SETUP },\n-\t{ \"branch\", cmd_branch, RUN_SETUP },\n-\t{ \"bundle\", cmd_bundle, RUN_SETUP_GENTLY },\n-\t{ \"cat-file\", cmd_cat_file, RUN_SETUP },\n-\t{ \"check-attr\", cmd_check_attr, RUN_SETUP },\n-\t{ \"check-ignore\", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"check-mailmap\", cmd_check_mailmap, RUN_SETUP },\n-\t{ \"check-ref-format\", cmd_check_ref_format },\n-\t{ \"checkout\", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"checkout-index\", cmd_checkout_index,\n-\t\tRUN_SETUP | NEED_WORK_TREE},\n-\t{ \"cherry\", cmd_cherry, RUN_SETUP },\n-\t{ \"cherry-pick\", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"clean\", cmd_clean, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"clone\", cmd_clone },\n-\t{ \"column\", cmd_column, RUN_SETUP_GENTLY },\n-\t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n-\t{ \"config\", cmd_config, RUN_SETUP_GENTLY },\n-\t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n-\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY },\n-\t{ \"describe\", cmd_describe, RUN_SETUP },\n-\t{ \"diff\", cmd_diff },\n-\t{ \"diff-files\", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"diff-index\", cmd_diff_index, RUN_SETUP },\n-\t{ \"diff-tree\", cmd_diff_tree, RUN_SETUP },\n-\t{ \"fast-export\", cmd_fast_export, RUN_SETUP },\n-\t{ \"fetch\", cmd_fetch, RUN_SETUP },\n-\t{ \"fetch-pack\", cmd_fetch_pack, RUN_SETUP },\n-\t{ \"fmt-merge-msg\", cmd_fmt_merge_msg, RUN_SETUP },\n-\t{ \"for-each-ref\", cmd_for_each_ref, RUN_SETUP },\n-\t{ \"format-patch\", cmd_format_patch, RUN_SETUP },\n-\t{ \"fsck\", cmd_fsck, RUN_SETUP },\n-\t{ \"fsck-objects\", cmd_fsck, RUN_SETUP },\n-\t{ \"gc\", cmd_gc, RUN_SETUP },\n-\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id },\n-\t{ \"grep\", cmd_grep, RUN_SETUP_GENTLY },\n-\t{ \"hash-object\", cmd_hash_object },\n-\t{ \"help\", cmd_help },\n-\t{ \"index-pack\", cmd_index_pack, RUN_SETUP_GENTLY },\n-\t{ \"init\", cmd_init_db },\n-\t{ \"init-db\", cmd_init_db },\n-\t{ \"log\", cmd_log, RUN_SETUP },\n-\t{ \"ls-files\", cmd_ls_files, RUN_SETUP },\n-\t{ \"ls-remote\", cmd_ls_remote, RUN_SETUP_GENTLY },\n-\t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n-\t{ \"mailinfo\", cmd_mailinfo },\n-\t{ \"mailsplit\", cmd_mailsplit },\n-\t{ \"merge\", cmd_merge, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"merge-base\", cmd_merge_base, RUN_SETUP },\n-\t{ \"merge-file\", cmd_merge_file, RUN_SETUP_GENTLY },\n-\t{ \"merge-index\", cmd_merge_index, RUN_SETUP },\n-\t{ \"merge-ours\", cmd_merge_ours, RUN_SETUP },\n-\t{ \"merge-recursive\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"merge-recursive-ours\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"merge-recursive-theirs\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"merge-subtree\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"merge-tree\", cmd_merge_tree, RUN_SETUP },\n-\t{ \"mktag\", cmd_mktag, RUN_SETUP },\n-\t{ \"mktree\", cmd_mktree, RUN_SETUP },\n-\t{ \"mv\", cmd_mv, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n-\t{ \"notes\", cmd_notes, RUN_SETUP },\n-\t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\n-\t{ \"pack-redundant\", cmd_pack_redundant, RUN_SETUP },\n-\t{ \"pack-refs\", cmd_pack_refs, RUN_SETUP },\n-\t{ \"patch-id\", cmd_patch_id },\n-\t{ \"pickaxe\", cmd_blame, RUN_SETUP },\n-\t{ \"prune\", cmd_prune, RUN_SETUP },\n-\t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n-\t{ \"push\", cmd_push, RUN_SETUP },\n-\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n-\t{ \"receive-pack\", cmd_receive_pack },\n-\t{ \"reflog\", cmd_reflog, RUN_SETUP },\n-\t{ \"remote\", cmd_remote, RUN_SETUP },\n-\t{ \"remote-ext\", cmd_remote_ext },\n-\t{ \"remote-fd\", cmd_remote_fd },\n-\t{ \"repack\", cmd_repack, RUN_SETUP },\n-\t{ \"replace\", cmd_replace, RUN_SETUP },\n-\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n-\t{ \"reset\", cmd_reset, RUN_SETUP },\n-\t{ \"rev-list\", cmd_rev_list, RUN_SETUP },\n-\t{ \"rev-parse\", cmd_rev_parse },\n-\t{ \"revert\", cmd_revert, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"rm\", cmd_rm, RUN_SETUP },\n-\t{ \"send-pack\", cmd_send_pack, RUN_SETUP },\n-\t{ \"shortlog\", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },\n-\t{ \"show\", cmd_show, RUN_SETUP },\n-\t{ \"show-branch\", cmd_show_branch, RUN_SETUP },\n-\t{ \"show-ref\", cmd_show_ref, RUN_SETUP },\n-\t{ \"stage\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"status\", cmd_status, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"stripspace\", cmd_stripspace },\n-\t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n-\t{ \"tag\", cmd_tag, RUN_SETUP },\n-\t{ \"unpack-file\", cmd_unpack_file, RUN_SETUP },\n-\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP },\n-\t{ \"update-index\", cmd_update_index, RUN_SETUP },\n-\t{ \"update-ref\", cmd_update_ref, RUN_SETUP },\n-\t{ \"update-server-info\", cmd_update_server_info, RUN_SETUP },\n-\t{ \"upload-archive\", cmd_upload_archive },\n-\t{ \"upload-archive--writer\", cmd_upload_archive_writer },\n-\t{ \"var\", cmd_var, RUN_SETUP_GENTLY },\n-\t{ \"verify-pack\", cmd_verify_pack },\n-\t{ \"verify-tag\", cmd_verify_tag, RUN_SETUP },\n-\t{ \"version\", cmd_version },\n-\t{ \"whatchanged\", cmd_whatchanged, RUN_SETUP },\n-\t{ \"write-tree\", cmd_write_tree, RUN_SETUP },\n-};\n-\n-int is_builtin(const char *s)\n-{\n-\tint i;\n-\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n-\t\tstruct cmd_struct *p = commands+i;\n-\t\tif (!strcmp(s, p->cmd))\n-\t\t\treturn 1;\n-\t}\n-\treturn 0;\n-}\n-\n-static void handle_builtin(int argc, const char **argv)\n-{\n-\tconst char *cmd = argv[0];\n-\tint i;\n-\tstatic const char ext[] = STRIP_EXTENSION;\n-\n-\tif (sizeof(ext) > 1) {\n-\t\ti = strlen(argv[0]) - strlen(ext);\n-\t\tif (i > 0 && !strcmp(argv[0] + i, ext)) {\n-\t\t\tchar *argv0 = xstrdup(argv[0]);\n-\t\t\targv[0] = cmd = argv0;\n-\t\t\targv0[i] = '\\0';\n-\t\t}\n-\t}\n-\n-\t/* Turn \"git cmd --help\" into \"git help cmd\" */\n-\tif (argc > 1 && !strcmp(argv[1], \"--help\")) {\n-\t\targv[1] = argv[0];\n-\t\targv[0] = cmd = \"help\";\n-\t}\n-\n-\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n-\t\tstruct cmd_struct *p = commands+i;\n-\t\tif (strcmp(p->cmd, cmd))\n-\t\t\tcontinue;\n-\t\texit(run_builtin(p, argc, argv));\n-\t}\n-}\n-\n static void execv_dashed_external(const char **argv)\n {\n \tstruct strbuf cmd = STRBUF_INIT;\n-- \n1.8.3-mingw-1\n"},{"id":"232570","messageId":"xmqq38l6qii6.fsf@gitster.dls.corp.google.com","threadId":"35595","inReplyTo":"52C59107.6080005@gmail.com","subject":"Re: [PATCH v2 3/4] Speed up is_git_command() by checking early for internal commands","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-02T19:41:05Z","receivedAt":"2014-01-02T19:41:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sebastian Schuberth <sschuberth@gmail.com> writes:\n\n> Since 2dce956 is_git_command() is a bit slow as it does file I/O in the\n> call to list_commands_in_dir(). Avoid the file I/O by adding an early\n> check for internal commands.\n\nI think it is a good thing to check with the list of built-in's\nfirst, but in order to see if one name we already have at hand is a\ngit command, I have to wonder if it is the best we can do to collect\nall the possible command names with load_command_list() and check\nthe membership.\n\nThere are two callers of is_in_cmdlist(), and the way they use the\nfunction looks both very backwards.\n\n - builtin/help.c has a user supplied string that it wants to see if\n   it is a git command (either on-disk in exec-path or a builtin),\n   either to see if an alias in a config is really in effect, or to\n   see if it is a command (i.e. invoke 'man' with git-<string>) or a\n   concept (i.e. invoke 'man' with git<string>).  It feels that it\n   should be a lot less work to just check with the builtin table\n   and stat(<exec-path> + <string>) for either of these purposes (on\n   Windows you may have to append .exe before checking and may also\n   have to check with .com so you may have to do more than one\n   stat(), but still).\n\n   Even though help is not a performance critical codepath,\n   optimizing this further so that we do not load the full set of\n   commands unnecessarily may be in line with the theme of your\n   series, I think.\n\n - builtin/merge.c is the same, but it is conceptually even worse.\n   It has the end-user supplied string and wants to see if it is a\n   valid strategy.  If the user wants to use a custom strategy, a\n   single stat() to make sure if it exists should suffice, and the\n   error codepath should load the command list to present the names\n   of available ones in the error message.\n\nBased on the above observation, I have a feeling that we will be\nbetter off to aim for getting rid of is_in_cmdlist(), reimplement\nis_git_command() to check with builtin and then do a stat (or two)\ninside the exec-path, and update builtin/merge.c codepath to use\nis_git_command() to see if the given name is indeed a strategy.\n\nSo in short, I very much like the part that moves the built-in\ncommand list out of the main() function and makes is_git_command()\nuse it, but I think the primary implementation of is_git_command()\nto check if the given string names an on-disk command is still not\nvery nice.\n\nThanks.\n\n> Signed-off-by: Sebastian Schuberth <sschuberth@gmail.com>\n> ---\n>  Documentation/technical/api-builtin.txt |   4 +-\n>  builtin.h                               |   2 +\n>  builtin/help.c                          |   3 +\n>  git.c                                   | 242 +++++++++++++++++---------------\n>  4 files changed, 134 insertions(+), 117 deletions(-)\n>\n> diff --git a/Documentation/technical/api-builtin.txt b/Documentation/technical/api-builtin.txt\n> index 150a02a..e3d6e7a 100644\n> --- a/Documentation/technical/api-builtin.txt\n> +++ b/Documentation/technical/api-builtin.txt\n> @@ -14,8 +14,8 @@ Git:\n>  \n>  . Add the external declaration for the function to `builtin.h`.\n>  \n> -. Add the command to `commands[]` table in `handle_builtin()`,\n> -  defined in `git.c`.  The entry should look like:\n> +. Add the command to the `commands[]` table defined in `git.c`.\n> +  The entry should look like:\n>  \n>  \t{ \"foo\", cmd_foo, <options> },\n>  +\n> diff --git a/builtin.h b/builtin.h\n> index d4afbfe..c47c110 100644\n> --- a/builtin.h\n> +++ b/builtin.h\n> @@ -27,6 +27,8 @@ extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,\n>  \n>  extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size);\n>  \n> +extern int is_builtin(const char *s);\n> +\n>  extern int cmd_add(int argc, const char **argv, const char *prefix);\n>  extern int cmd_annotate(int argc, const char **argv, const char *prefix);\n>  extern int cmd_apply(int argc, const char **argv, const char *prefix);\n> diff --git a/builtin/help.c b/builtin/help.c\n> index b6fc15e..1fdefeb 100644\n> --- a/builtin/help.c\n> +++ b/builtin/help.c\n> @@ -288,6 +288,9 @@ static struct cmdnames main_cmds, other_cmds;\n>  \n>  static int is_git_command(const char *s)\n>  {\n> +\tif (is_builtin(s))\n> +\t\treturn 1;\n> +\n>  \tload_command_list(\"git-\", &main_cmds, &other_cmds);\n>  \treturn is_in_cmdlist(&main_cmds, s) ||\n>  \t\tis_in_cmdlist(&other_cmds, s);\n> diff --git a/git.c b/git.c\n> index 89ab5d7..bba4378 100644\n> --- a/git.c\n> +++ b/git.c\n> @@ -332,124 +332,136 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n>  \treturn 0;\n>  }\n>  \n> +static struct cmd_struct commands[] = {\n> +\t{ \"add\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"annotate\", cmd_annotate, RUN_SETUP },\n> +\t{ \"apply\", cmd_apply, RUN_SETUP_GENTLY },\n> +\t{ \"archive\", cmd_archive },\n> +\t{ \"bisect--helper\", cmd_bisect__helper, RUN_SETUP },\n> +\t{ \"blame\", cmd_blame, RUN_SETUP },\n> +\t{ \"branch\", cmd_branch, RUN_SETUP },\n> +\t{ \"bundle\", cmd_bundle, RUN_SETUP_GENTLY },\n> +\t{ \"cat-file\", cmd_cat_file, RUN_SETUP },\n> +\t{ \"check-attr\", cmd_check_attr, RUN_SETUP },\n> +\t{ \"check-ignore\", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"check-mailmap\", cmd_check_mailmap, RUN_SETUP },\n> +\t{ \"check-ref-format\", cmd_check_ref_format },\n> +\t{ \"checkout\", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"checkout-index\", cmd_checkout_index,\n> +\t\tRUN_SETUP | NEED_WORK_TREE},\n> +\t{ \"cherry\", cmd_cherry, RUN_SETUP },\n> +\t{ \"cherry-pick\", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"clean\", cmd_clean, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"clone\", cmd_clone },\n> +\t{ \"column\", cmd_column, RUN_SETUP_GENTLY },\n> +\t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n> +\t{ \"config\", cmd_config, RUN_SETUP_GENTLY },\n> +\t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n> +\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY },\n> +\t{ \"describe\", cmd_describe, RUN_SETUP },\n> +\t{ \"diff\", cmd_diff },\n> +\t{ \"diff-files\", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"diff-index\", cmd_diff_index, RUN_SETUP },\n> +\t{ \"diff-tree\", cmd_diff_tree, RUN_SETUP },\n> +\t{ \"fast-export\", cmd_fast_export, RUN_SETUP },\n> +\t{ \"fetch\", cmd_fetch, RUN_SETUP },\n> +\t{ \"fetch-pack\", cmd_fetch_pack, RUN_SETUP },\n> +\t{ \"fmt-merge-msg\", cmd_fmt_merge_msg, RUN_SETUP },\n> +\t{ \"for-each-ref\", cmd_for_each_ref, RUN_SETUP },\n> +\t{ \"format-patch\", cmd_format_patch, RUN_SETUP },\n> +\t{ \"fsck\", cmd_fsck, RUN_SETUP },\n> +\t{ \"fsck-objects\", cmd_fsck, RUN_SETUP },\n> +\t{ \"gc\", cmd_gc, RUN_SETUP },\n> +\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id },\n> +\t{ \"grep\", cmd_grep, RUN_SETUP_GENTLY },\n> +\t{ \"hash-object\", cmd_hash_object },\n> +\t{ \"help\", cmd_help },\n> +\t{ \"index-pack\", cmd_index_pack, RUN_SETUP_GENTLY },\n> +\t{ \"init\", cmd_init_db },\n> +\t{ \"init-db\", cmd_init_db },\n> +\t{ \"log\", cmd_log, RUN_SETUP },\n> +\t{ \"ls-files\", cmd_ls_files, RUN_SETUP },\n> +\t{ \"ls-remote\", cmd_ls_remote, RUN_SETUP_GENTLY },\n> +\t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n> +\t{ \"mailinfo\", cmd_mailinfo },\n> +\t{ \"mailsplit\", cmd_mailsplit },\n> +\t{ \"merge\", cmd_merge, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"merge-base\", cmd_merge_base, RUN_SETUP },\n> +\t{ \"merge-file\", cmd_merge_file, RUN_SETUP_GENTLY },\n> +\t{ \"merge-index\", cmd_merge_index, RUN_SETUP },\n> +\t{ \"merge-ours\", cmd_merge_ours, RUN_SETUP },\n> +\t{ \"merge-recursive\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"merge-recursive-ours\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"merge-recursive-theirs\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"merge-subtree\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"merge-tree\", cmd_merge_tree, RUN_SETUP },\n> +\t{ \"mktag\", cmd_mktag, RUN_SETUP },\n> +\t{ \"mktree\", cmd_mktree, RUN_SETUP },\n> +\t{ \"mv\", cmd_mv, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n> +\t{ \"notes\", cmd_notes, RUN_SETUP },\n> +\t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\n> +\t{ \"pack-redundant\", cmd_pack_redundant, RUN_SETUP },\n> +\t{ \"pack-refs\", cmd_pack_refs, RUN_SETUP },\n> +\t{ \"patch-id\", cmd_patch_id },\n> +\t{ \"pickaxe\", cmd_blame, RUN_SETUP },\n> +\t{ \"prune\", cmd_prune, RUN_SETUP },\n> +\t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n> +\t{ \"push\", cmd_push, RUN_SETUP },\n> +\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n> +\t{ \"receive-pack\", cmd_receive_pack },\n> +\t{ \"reflog\", cmd_reflog, RUN_SETUP },\n> +\t{ \"remote\", cmd_remote, RUN_SETUP },\n> +\t{ \"remote-ext\", cmd_remote_ext },\n> +\t{ \"remote-fd\", cmd_remote_fd },\n> +\t{ \"repack\", cmd_repack, RUN_SETUP },\n> +\t{ \"replace\", cmd_replace, RUN_SETUP },\n> +\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n> +\t{ \"reset\", cmd_reset, RUN_SETUP },\n> +\t{ \"rev-list\", cmd_rev_list, RUN_SETUP },\n> +\t{ \"rev-parse\", cmd_rev_parse },\n> +\t{ \"revert\", cmd_revert, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"rm\", cmd_rm, RUN_SETUP },\n> +\t{ \"send-pack\", cmd_send_pack, RUN_SETUP },\n> +\t{ \"shortlog\", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },\n> +\t{ \"show\", cmd_show, RUN_SETUP },\n> +\t{ \"show-branch\", cmd_show_branch, RUN_SETUP },\n> +\t{ \"show-ref\", cmd_show_ref, RUN_SETUP },\n> +\t{ \"stage\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"status\", cmd_status, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"stripspace\", cmd_stripspace },\n> +\t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n> +\t{ \"tag\", cmd_tag, RUN_SETUP },\n> +\t{ \"unpack-file\", cmd_unpack_file, RUN_SETUP },\n> +\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP },\n> +\t{ \"update-index\", cmd_update_index, RUN_SETUP },\n> +\t{ \"update-ref\", cmd_update_ref, RUN_SETUP },\n> +\t{ \"update-server-info\", cmd_update_server_info, RUN_SETUP },\n> +\t{ \"upload-archive\", cmd_upload_archive },\n> +\t{ \"upload-archive--writer\", cmd_upload_archive_writer },\n> +\t{ \"var\", cmd_var, RUN_SETUP_GENTLY },\n> +\t{ \"verify-pack\", cmd_verify_pack },\n> +\t{ \"verify-tag\", cmd_verify_tag, RUN_SETUP },\n> +\t{ \"version\", cmd_version },\n> +\t{ \"whatchanged\", cmd_whatchanged, RUN_SETUP },\n> +\t{ \"write-tree\", cmd_write_tree, RUN_SETUP },\n> +};\n> +\n> +int is_builtin(const char *s)\n> +{\n> +\tint i;\n> +\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n> +\t\tstruct cmd_struct *p = commands+i;\n> +\t\tif (!strcmp(s, p->cmd))\n> +\t\t\treturn 1;\n> +\t}\n> +\treturn 0;\n> +}\n> +\n>  static void handle_builtin(int argc, const char **argv)\n>  {\n>  \tconst char *cmd = argv[0];\n> -\tstatic struct cmd_struct commands[] = {\n> -\t\t{ \"add\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"annotate\", cmd_annotate, RUN_SETUP },\n> -\t\t{ \"apply\", cmd_apply, RUN_SETUP_GENTLY },\n> -\t\t{ \"archive\", cmd_archive },\n> -\t\t{ \"bisect--helper\", cmd_bisect__helper, RUN_SETUP },\n> -\t\t{ \"blame\", cmd_blame, RUN_SETUP },\n> -\t\t{ \"branch\", cmd_branch, RUN_SETUP },\n> -\t\t{ \"bundle\", cmd_bundle, RUN_SETUP_GENTLY },\n> -\t\t{ \"cat-file\", cmd_cat_file, RUN_SETUP },\n> -\t\t{ \"check-attr\", cmd_check_attr, RUN_SETUP },\n> -\t\t{ \"check-ignore\", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"check-mailmap\", cmd_check_mailmap, RUN_SETUP },\n> -\t\t{ \"check-ref-format\", cmd_check_ref_format },\n> -\t\t{ \"checkout\", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"checkout-index\", cmd_checkout_index,\n> -\t\t\tRUN_SETUP | NEED_WORK_TREE},\n> -\t\t{ \"cherry\", cmd_cherry, RUN_SETUP },\n> -\t\t{ \"cherry-pick\", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"clean\", cmd_clean, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"clone\", cmd_clone },\n> -\t\t{ \"column\", cmd_column, RUN_SETUP_GENTLY },\n> -\t\t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n> -\t\t{ \"config\", cmd_config, RUN_SETUP_GENTLY },\n> -\t\t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n> -\t\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY },\n> -\t\t{ \"describe\", cmd_describe, RUN_SETUP },\n> -\t\t{ \"diff\", cmd_diff },\n> -\t\t{ \"diff-files\", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"diff-index\", cmd_diff_index, RUN_SETUP },\n> -\t\t{ \"diff-tree\", cmd_diff_tree, RUN_SETUP },\n> -\t\t{ \"fast-export\", cmd_fast_export, RUN_SETUP },\n> -\t\t{ \"fetch\", cmd_fetch, RUN_SETUP },\n> -\t\t{ \"fetch-pack\", cmd_fetch_pack, RUN_SETUP },\n> -\t\t{ \"fmt-merge-msg\", cmd_fmt_merge_msg, RUN_SETUP },\n> -\t\t{ \"for-each-ref\", cmd_for_each_ref, RUN_SETUP },\n> -\t\t{ \"format-patch\", cmd_format_patch, RUN_SETUP },\n> -\t\t{ \"fsck\", cmd_fsck, RUN_SETUP },\n> -\t\t{ \"fsck-objects\", cmd_fsck, RUN_SETUP },\n> -\t\t{ \"gc\", cmd_gc, RUN_SETUP },\n> -\t\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id },\n> -\t\t{ \"grep\", cmd_grep, RUN_SETUP_GENTLY },\n> -\t\t{ \"hash-object\", cmd_hash_object },\n> -\t\t{ \"help\", cmd_help },\n> -\t\t{ \"index-pack\", cmd_index_pack, RUN_SETUP_GENTLY },\n> -\t\t{ \"init\", cmd_init_db },\n> -\t\t{ \"init-db\", cmd_init_db },\n> -\t\t{ \"log\", cmd_log, RUN_SETUP },\n> -\t\t{ \"ls-files\", cmd_ls_files, RUN_SETUP },\n> -\t\t{ \"ls-remote\", cmd_ls_remote, RUN_SETUP_GENTLY },\n> -\t\t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n> -\t\t{ \"mailinfo\", cmd_mailinfo },\n> -\t\t{ \"mailsplit\", cmd_mailsplit },\n> -\t\t{ \"merge\", cmd_merge, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"merge-base\", cmd_merge_base, RUN_SETUP },\n> -\t\t{ \"merge-file\", cmd_merge_file, RUN_SETUP_GENTLY },\n> -\t\t{ \"merge-index\", cmd_merge_index, RUN_SETUP },\n> -\t\t{ \"merge-ours\", cmd_merge_ours, RUN_SETUP },\n> -\t\t{ \"merge-recursive\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"merge-recursive-ours\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"merge-recursive-theirs\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"merge-subtree\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"merge-tree\", cmd_merge_tree, RUN_SETUP },\n> -\t\t{ \"mktag\", cmd_mktag, RUN_SETUP },\n> -\t\t{ \"mktree\", cmd_mktree, RUN_SETUP },\n> -\t\t{ \"mv\", cmd_mv, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n> -\t\t{ \"notes\", cmd_notes, RUN_SETUP },\n> -\t\t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\n> -\t\t{ \"pack-redundant\", cmd_pack_redundant, RUN_SETUP },\n> -\t\t{ \"pack-refs\", cmd_pack_refs, RUN_SETUP },\n> -\t\t{ \"patch-id\", cmd_patch_id },\n> -\t\t{ \"pickaxe\", cmd_blame, RUN_SETUP },\n> -\t\t{ \"prune\", cmd_prune, RUN_SETUP },\n> -\t\t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n> -\t\t{ \"push\", cmd_push, RUN_SETUP },\n> -\t\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n> -\t\t{ \"receive-pack\", cmd_receive_pack },\n> -\t\t{ \"reflog\", cmd_reflog, RUN_SETUP },\n> -\t\t{ \"remote\", cmd_remote, RUN_SETUP },\n> -\t\t{ \"remote-ext\", cmd_remote_ext },\n> -\t\t{ \"remote-fd\", cmd_remote_fd },\n> -\t\t{ \"repack\", cmd_repack, RUN_SETUP },\n> -\t\t{ \"replace\", cmd_replace, RUN_SETUP },\n> -\t\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n> -\t\t{ \"reset\", cmd_reset, RUN_SETUP },\n> -\t\t{ \"rev-list\", cmd_rev_list, RUN_SETUP },\n> -\t\t{ \"rev-parse\", cmd_rev_parse },\n> -\t\t{ \"revert\", cmd_revert, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"rm\", cmd_rm, RUN_SETUP },\n> -\t\t{ \"send-pack\", cmd_send_pack, RUN_SETUP },\n> -\t\t{ \"shortlog\", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },\n> -\t\t{ \"show\", cmd_show, RUN_SETUP },\n> -\t\t{ \"show-branch\", cmd_show_branch, RUN_SETUP },\n> -\t\t{ \"show-ref\", cmd_show_ref, RUN_SETUP },\n> -\t\t{ \"stage\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"status\", cmd_status, RUN_SETUP | NEED_WORK_TREE },\n> -\t\t{ \"stripspace\", cmd_stripspace },\n> -\t\t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n> -\t\t{ \"tag\", cmd_tag, RUN_SETUP },\n> -\t\t{ \"unpack-file\", cmd_unpack_file, RUN_SETUP },\n> -\t\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP },\n> -\t\t{ \"update-index\", cmd_update_index, RUN_SETUP },\n> -\t\t{ \"update-ref\", cmd_update_ref, RUN_SETUP },\n> -\t\t{ \"update-server-info\", cmd_update_server_info, RUN_SETUP },\n> -\t\t{ \"upload-archive\", cmd_upload_archive },\n> -\t\t{ \"upload-archive--writer\", cmd_upload_archive_writer },\n> -\t\t{ \"var\", cmd_var, RUN_SETUP_GENTLY },\n> -\t\t{ \"verify-pack\", cmd_verify_pack },\n> -\t\t{ \"verify-tag\", cmd_verify_tag, RUN_SETUP },\n> -\t\t{ \"version\", cmd_version },\n> -\t\t{ \"whatchanged\", cmd_whatchanged, RUN_SETUP },\n> -\t\t{ \"write-tree\", cmd_write_tree, RUN_SETUP },\n> -\t};\n>  \tint i;\n>  \tstatic const char ext[] = STRIP_EXTENSION;\n"},{"id":"232571","messageId":"xmqqy52yp3tm.fsf@gitster.dls.corp.google.com","threadId":"35595","inReplyTo":"52C59130.4050003@gmail.com","subject":"Re: [PATCH v2 4/4] Move builtin-related implementations to a new builtin.c file","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-02T19:43:33Z","receivedAt":"2014-01-02T19:43:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sebastian Schuberth <sschuberth@gmail.com> writes:\n\n> Signed-off-by: Sebastian Schuberth <sschuberth@gmail.com>\n> ---\n>  Documentation/technical/api-builtin.txt |   2 +-\n>  Makefile                                |   1 +\n>  builtin.c                               | 225 ++++++++++++++++++++++++++++++\n>  builtin.h                               |  21 +++\n>  git.c                                   | 238 --------------------------------\n>  5 files changed, 248 insertions(+), 239 deletions(-)\n>  create mode 100644 builtin.c\n\nI'm sorry but I do not see a point in this.\n\nIt is not like builtin.c can be used outside the context of the main\nGit program, and many helper functions you moved out of git.c that\nused to be static want to be called from other places.\n\n> diff --git a/Documentation/technical/api-builtin.txt b/Documentation/technical/api-builtin.txt\n> index e3d6e7a..d1d946c 100644\n> --- a/Documentation/technical/api-builtin.txt\n> +++ b/Documentation/technical/api-builtin.txt\n> @@ -14,7 +14,7 @@ Git:\n>  \n>  . Add the external declaration for the function to `builtin.h`.\n>  \n> -. Add the command to the `commands[]` table defined in `git.c`.\n> +. Add the command to the `commands[]` table defined in `builtin.c`.\n>    The entry should look like:\n>  \n>  \t{ \"foo\", cmd_foo, <options> },\n> diff --git a/Makefile b/Makefile\n> index b4af1e2..2d947e8 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -763,6 +763,7 @@ LIB_OBJS += base85.o\n>  LIB_OBJS += bisect.o\n>  LIB_OBJS += blob.o\n>  LIB_OBJS += branch.o\n> +LIB_OBJS += builtin.o\n>  LIB_OBJS += bulk-checkin.o\n>  LIB_OBJS += bundle.o\n>  LIB_OBJS += cache-tree.o\n> diff --git a/builtin.c b/builtin.c\n> new file mode 100644\n> index 0000000..6bdeb7c\n> --- /dev/null\n> +++ b/builtin.c\n> @@ -0,0 +1,225 @@\n> +#include \"builtin.h\"\n> +\n> +static struct cmd_struct commands[] = {\n> +\t{ \"add\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"annotate\", cmd_annotate, RUN_SETUP },\n> +\t{ \"apply\", cmd_apply, RUN_SETUP_GENTLY },\n> +\t{ \"archive\", cmd_archive },\n> +\t{ \"bisect--helper\", cmd_bisect__helper, RUN_SETUP },\n> +\t{ \"blame\", cmd_blame, RUN_SETUP },\n> +\t{ \"branch\", cmd_branch, RUN_SETUP },\n> +\t{ \"bundle\", cmd_bundle, RUN_SETUP_GENTLY },\n> +\t{ \"cat-file\", cmd_cat_file, RUN_SETUP },\n> +\t{ \"check-attr\", cmd_check_attr, RUN_SETUP },\n> +\t{ \"check-ignore\", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"check-mailmap\", cmd_check_mailmap, RUN_SETUP },\n> +\t{ \"check-ref-format\", cmd_check_ref_format },\n> +\t{ \"checkout\", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"checkout-index\", cmd_checkout_index,\n> +\t\tRUN_SETUP | NEED_WORK_TREE},\n> +\t{ \"cherry\", cmd_cherry, RUN_SETUP },\n> +\t{ \"cherry-pick\", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"clean\", cmd_clean, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"clone\", cmd_clone },\n> +\t{ \"column\", cmd_column, RUN_SETUP_GENTLY },\n> +\t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n> +\t{ \"config\", cmd_config, RUN_SETUP_GENTLY },\n> +\t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n> +\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY },\n> +\t{ \"describe\", cmd_describe, RUN_SETUP },\n> +\t{ \"diff\", cmd_diff },\n> +\t{ \"diff-files\", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"diff-index\", cmd_diff_index, RUN_SETUP },\n> +\t{ \"diff-tree\", cmd_diff_tree, RUN_SETUP },\n> +\t{ \"fast-export\", cmd_fast_export, RUN_SETUP },\n> +\t{ \"fetch\", cmd_fetch, RUN_SETUP },\n> +\t{ \"fetch-pack\", cmd_fetch_pack, RUN_SETUP },\n> +\t{ \"fmt-merge-msg\", cmd_fmt_merge_msg, RUN_SETUP },\n> +\t{ \"for-each-ref\", cmd_for_each_ref, RUN_SETUP },\n> +\t{ \"format-patch\", cmd_format_patch, RUN_SETUP },\n> +\t{ \"fsck\", cmd_fsck, RUN_SETUP },\n> +\t{ \"fsck-objects\", cmd_fsck, RUN_SETUP },\n> +\t{ \"gc\", cmd_gc, RUN_SETUP },\n> +\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id },\n> +\t{ \"grep\", cmd_grep, RUN_SETUP_GENTLY },\n> +\t{ \"hash-object\", cmd_hash_object },\n> +\t{ \"help\", cmd_help },\n> +\t{ \"index-pack\", cmd_index_pack, RUN_SETUP_GENTLY },\n> +\t{ \"init\", cmd_init_db },\n> +\t{ \"init-db\", cmd_init_db },\n> +\t{ \"log\", cmd_log, RUN_SETUP },\n> +\t{ \"ls-files\", cmd_ls_files, RUN_SETUP },\n> +\t{ \"ls-remote\", cmd_ls_remote, RUN_SETUP_GENTLY },\n> +\t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n> +\t{ \"mailinfo\", cmd_mailinfo },\n> +\t{ \"mailsplit\", cmd_mailsplit },\n> +\t{ \"merge\", cmd_merge, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"merge-base\", cmd_merge_base, RUN_SETUP },\n> +\t{ \"merge-file\", cmd_merge_file, RUN_SETUP_GENTLY },\n> +\t{ \"merge-index\", cmd_merge_index, RUN_SETUP },\n> +\t{ \"merge-ours\", cmd_merge_ours, RUN_SETUP },\n> +\t{ \"merge-recursive\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"merge-recursive-ours\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"merge-recursive-theirs\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"merge-subtree\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"merge-tree\", cmd_merge_tree, RUN_SETUP },\n> +\t{ \"mktag\", cmd_mktag, RUN_SETUP },\n> +\t{ \"mktree\", cmd_mktree, RUN_SETUP },\n> +\t{ \"mv\", cmd_mv, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n> +\t{ \"notes\", cmd_notes, RUN_SETUP },\n> +\t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\n> +\t{ \"pack-redundant\", cmd_pack_redundant, RUN_SETUP },\n> +\t{ \"pack-refs\", cmd_pack_refs, RUN_SETUP },\n> +\t{ \"patch-id\", cmd_patch_id },\n> +\t{ \"pickaxe\", cmd_blame, RUN_SETUP },\n> +\t{ \"prune\", cmd_prune, RUN_SETUP },\n> +\t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n> +\t{ \"push\", cmd_push, RUN_SETUP },\n> +\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n> +\t{ \"receive-pack\", cmd_receive_pack },\n> +\t{ \"reflog\", cmd_reflog, RUN_SETUP },\n> +\t{ \"remote\", cmd_remote, RUN_SETUP },\n> +\t{ \"remote-ext\", cmd_remote_ext },\n> +\t{ \"remote-fd\", cmd_remote_fd },\n> +\t{ \"repack\", cmd_repack, RUN_SETUP },\n> +\t{ \"replace\", cmd_replace, RUN_SETUP },\n> +\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n> +\t{ \"reset\", cmd_reset, RUN_SETUP },\n> +\t{ \"rev-list\", cmd_rev_list, RUN_SETUP },\n> +\t{ \"rev-parse\", cmd_rev_parse },\n> +\t{ \"revert\", cmd_revert, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"rm\", cmd_rm, RUN_SETUP },\n> +\t{ \"send-pack\", cmd_send_pack, RUN_SETUP },\n> +\t{ \"shortlog\", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },\n> +\t{ \"show\", cmd_show, RUN_SETUP },\n> +\t{ \"show-branch\", cmd_show_branch, RUN_SETUP },\n> +\t{ \"show-ref\", cmd_show_ref, RUN_SETUP },\n> +\t{ \"stage\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"status\", cmd_status, RUN_SETUP | NEED_WORK_TREE },\n> +\t{ \"stripspace\", cmd_stripspace },\n> +\t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n> +\t{ \"tag\", cmd_tag, RUN_SETUP },\n> +\t{ \"unpack-file\", cmd_unpack_file, RUN_SETUP },\n> +\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP },\n> +\t{ \"update-index\", cmd_update_index, RUN_SETUP },\n> +\t{ \"update-ref\", cmd_update_ref, RUN_SETUP },\n> +\t{ \"update-server-info\", cmd_update_server_info, RUN_SETUP },\n> +\t{ \"upload-archive\", cmd_upload_archive },\n> +\t{ \"upload-archive--writer\", cmd_upload_archive_writer },\n> +\t{ \"var\", cmd_var, RUN_SETUP_GENTLY },\n> +\t{ \"verify-pack\", cmd_verify_pack },\n> +\t{ \"verify-tag\", cmd_verify_tag, RUN_SETUP },\n> +\t{ \"version\", cmd_version },\n> +\t{ \"whatchanged\", cmd_whatchanged, RUN_SETUP },\n> +\t{ \"write-tree\", cmd_write_tree, RUN_SETUP },\n> +};\n> +\n> +int use_pager = -1;\n> +\n> +void commit_pager_choice(void) {\n> +\tswitch (use_pager) {\n> +\tcase 0:\n> +\t\tsetenv(\"GIT_PAGER\", \"cat\", 1);\n> +\t\tbreak;\n> +\tcase 1:\n> +\t\tsetup_pager();\n> +\t\tbreak;\n> +\tdefault:\n> +\t\tbreak;\n> +\t}\n> +}\n> +\n> +int is_builtin(const char *s)\n> +{\n> +\tint i;\n> +\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n> +\t\tstruct cmd_struct *p = commands+i;\n> +\t\tif (!strcmp(s, p->cmd))\n> +\t\t\treturn 1;\n> +\t}\n> +\treturn 0;\n> +}\n> +\n> +void handle_builtin(int argc, const char **argv)\n> +{\n> +\tconst char *cmd = argv[0];\n> +\tint i;\n> +\tstatic const char ext[] = STRIP_EXTENSION;\n> +\n> +\tif (sizeof(ext) > 1) {\n> +\t\ti = strlen(argv[0]) - strlen(ext);\n> +\t\tif (i > 0 && !strcmp(argv[0] + i, ext)) {\n> +\t\t\tchar *argv0 = xstrdup(argv[0]);\n> +\t\t\targv[0] = cmd = argv0;\n> +\t\t\targv0[i] = '\\0';\n> +\t\t}\n> +\t}\n> +\n> +\t/* Turn \"git cmd --help\" into \"git help cmd\" */\n> +\tif (argc > 1 && !strcmp(argv[1], \"--help\")) {\n> +\t\targv[1] = argv[0];\n> +\t\targv[0] = cmd = \"help\";\n> +\t}\n> +\n> +\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n> +\t\tstruct cmd_struct *p = commands+i;\n> +\t\tif (strcmp(p->cmd, cmd))\n> +\t\t\tcontinue;\n> +\t\texit(run_builtin(p, argc, argv));\n> +\t}\n> +}\n> +\n> +int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n> +{\n> +\tint status, help;\n> +\tstruct stat st;\n> +\tconst char *prefix;\n> +\n> +\tprefix = NULL;\n> +\thelp = argc == 2 && !strcmp(argv[1], \"-h\");\n> +\tif (!help) {\n> +\t\tif (p->option & RUN_SETUP)\n> +\t\t\tprefix = setup_git_directory();\n> +\t\tif (p->option & RUN_SETUP_GENTLY) {\n> +\t\t\tint nongit_ok;\n> +\t\t\tprefix = setup_git_directory_gently(&nongit_ok);\n> +\t\t}\n> +\n> +\t\tif (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY))\n> +\t\t\tuse_pager = check_pager_config(p->cmd);\n> +\t\tif (use_pager == -1 && p->option & USE_PAGER)\n> +\t\t\tuse_pager = 1;\n> +\n> +\t\tif ((p->option & (RUN_SETUP | RUN_SETUP_GENTLY)) &&\n> +\t\t    startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */\n> +\t\t\ttrace_repo_setup(prefix);\n> +\t}\n> +\tcommit_pager_choice();\n> +\n> +\tif (!help && p->option & NEED_WORK_TREE)\n> +\t\tsetup_work_tree();\n> +\n> +\ttrace_argv_printf(argv, \"trace: built-in: git\");\n> +\n> +\tstatus = p->fn(argc, argv, prefix);\n> +\tif (status)\n> +\t\treturn status;\n> +\n> +\t/* Somebody closed stdout? */\n> +\tif (fstat(fileno(stdout), &st))\n> +\t\treturn 0;\n> +\t/* Ignore write errors for pipes and sockets.. */\n> +\tif (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))\n> +\t\treturn 0;\n> +\n> +\t/* Check for ENOSPC and EIO errors.. */\n> +\tif (fflush(stdout))\n> +\t\tdie_errno(\"write failure on standard output\");\n> +\tif (ferror(stdout))\n> +\t\tdie(\"unknown write failure on standard output\");\n> +\tif (fclose(stdout))\n> +\t\tdie_errno(\"close failed on standard output\");\n> +\treturn 0;\n> +}\n> diff --git a/builtin.h b/builtin.h\n> index c47c110..9388505 100644\n> --- a/builtin.h\n> +++ b/builtin.h\n> @@ -27,7 +27,28 @@ extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,\n>  \n>  extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size);\n>  \n> +#define RUN_SETUP\t\t(1<<0)\n> +#define RUN_SETUP_GENTLY\t(1<<1)\n> +#define USE_PAGER\t\t(1<<2)\n> +/*\n> + * require working tree to be present -- anything uses this needs\n> + * RUN_SETUP for reading from the configuration file.\n> + */\n> +#define NEED_WORK_TREE\t\t(1<<3)\n> +\n> +struct cmd_struct {\n> +\tconst char *cmd;\n> +\tint (*fn)(int, const char **, const char *);\n> +\tint option;\n> +};\n> +\n> +extern int use_pager;\n> +\n> +extern void commit_pager_choice(void);\n> +\n>  extern int is_builtin(const char *s);\n> +extern void handle_builtin(int argc, const char **argv);\n> +extern int run_builtin(struct cmd_struct *p, int argc, const char **argv);\n>  \n>  extern int cmd_add(int argc, const char **argv, const char *prefix);\n>  extern int cmd_annotate(int argc, const char **argv, const char *prefix);\n> diff --git a/git.c b/git.c\n> index bba4378..c93e545 100644\n> --- a/git.c\n> +++ b/git.c\n> @@ -19,20 +19,6 @@ const char git_more_info_string[] =\n>  \t   \"to read about a specific subcommand or concept.\");\n>  \n>  static struct startup_info git_startup_info;\n> -static int use_pager = -1;\n> -\n> -static void commit_pager_choice(void) {\n> -\tswitch (use_pager) {\n> -\tcase 0:\n> -\t\tsetenv(\"GIT_PAGER\", \"cat\", 1);\n> -\t\tbreak;\n> -\tcase 1:\n> -\t\tsetup_pager();\n> -\t\tbreak;\n> -\tdefault:\n> -\t\tbreak;\n> -\t}\n> -}\n>  \n>  static int handle_options(const char ***argv, int *argc, int *envchanged)\n>  {\n> @@ -264,230 +250,6 @@ static int handle_alias(int *argcp, const char ***argv)\n>  \treturn ret;\n>  }\n>  \n> -#define RUN_SETUP\t\t(1<<0)\n> -#define RUN_SETUP_GENTLY\t(1<<1)\n> -#define USE_PAGER\t\t(1<<2)\n> -/*\n> - * require working tree to be present -- anything uses this needs\n> - * RUN_SETUP for reading from the configuration file.\n> - */\n> -#define NEED_WORK_TREE\t\t(1<<3)\n> -\n> -struct cmd_struct {\n> -\tconst char *cmd;\n> -\tint (*fn)(int, const char **, const char *);\n> -\tint option;\n> -};\n> -\n> -static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n> -{\n> -\tint status, help;\n> -\tstruct stat st;\n> -\tconst char *prefix;\n> -\n> -\tprefix = NULL;\n> -\thelp = argc == 2 && !strcmp(argv[1], \"-h\");\n> -\tif (!help) {\n> -\t\tif (p->option & RUN_SETUP)\n> -\t\t\tprefix = setup_git_directory();\n> -\t\tif (p->option & RUN_SETUP_GENTLY) {\n> -\t\t\tint nongit_ok;\n> -\t\t\tprefix = setup_git_directory_gently(&nongit_ok);\n> -\t\t}\n> -\n> -\t\tif (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY))\n> -\t\t\tuse_pager = check_pager_config(p->cmd);\n> -\t\tif (use_pager == -1 && p->option & USE_PAGER)\n> -\t\t\tuse_pager = 1;\n> -\n> -\t\tif ((p->option & (RUN_SETUP | RUN_SETUP_GENTLY)) &&\n> -\t\t    startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */\n> -\t\t\ttrace_repo_setup(prefix);\n> -\t}\n> -\tcommit_pager_choice();\n> -\n> -\tif (!help && p->option & NEED_WORK_TREE)\n> -\t\tsetup_work_tree();\n> -\n> -\ttrace_argv_printf(argv, \"trace: built-in: git\");\n> -\n> -\tstatus = p->fn(argc, argv, prefix);\n> -\tif (status)\n> -\t\treturn status;\n> -\n> -\t/* Somebody closed stdout? */\n> -\tif (fstat(fileno(stdout), &st))\n> -\t\treturn 0;\n> -\t/* Ignore write errors for pipes and sockets.. */\n> -\tif (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))\n> -\t\treturn 0;\n> -\n> -\t/* Check for ENOSPC and EIO errors.. */\n> -\tif (fflush(stdout))\n> -\t\tdie_errno(\"write failure on standard output\");\n> -\tif (ferror(stdout))\n> -\t\tdie(\"unknown write failure on standard output\");\n> -\tif (fclose(stdout))\n> -\t\tdie_errno(\"close failed on standard output\");\n> -\treturn 0;\n> -}\n> -\n> -static struct cmd_struct commands[] = {\n> -\t{ \"add\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"annotate\", cmd_annotate, RUN_SETUP },\n> -\t{ \"apply\", cmd_apply, RUN_SETUP_GENTLY },\n> -\t{ \"archive\", cmd_archive },\n> -\t{ \"bisect--helper\", cmd_bisect__helper, RUN_SETUP },\n> -\t{ \"blame\", cmd_blame, RUN_SETUP },\n> -\t{ \"branch\", cmd_branch, RUN_SETUP },\n> -\t{ \"bundle\", cmd_bundle, RUN_SETUP_GENTLY },\n> -\t{ \"cat-file\", cmd_cat_file, RUN_SETUP },\n> -\t{ \"check-attr\", cmd_check_attr, RUN_SETUP },\n> -\t{ \"check-ignore\", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"check-mailmap\", cmd_check_mailmap, RUN_SETUP },\n> -\t{ \"check-ref-format\", cmd_check_ref_format },\n> -\t{ \"checkout\", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"checkout-index\", cmd_checkout_index,\n> -\t\tRUN_SETUP | NEED_WORK_TREE},\n> -\t{ \"cherry\", cmd_cherry, RUN_SETUP },\n> -\t{ \"cherry-pick\", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"clean\", cmd_clean, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"clone\", cmd_clone },\n> -\t{ \"column\", cmd_column, RUN_SETUP_GENTLY },\n> -\t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n> -\t{ \"config\", cmd_config, RUN_SETUP_GENTLY },\n> -\t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n> -\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY },\n> -\t{ \"describe\", cmd_describe, RUN_SETUP },\n> -\t{ \"diff\", cmd_diff },\n> -\t{ \"diff-files\", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"diff-index\", cmd_diff_index, RUN_SETUP },\n> -\t{ \"diff-tree\", cmd_diff_tree, RUN_SETUP },\n> -\t{ \"fast-export\", cmd_fast_export, RUN_SETUP },\n> -\t{ \"fetch\", cmd_fetch, RUN_SETUP },\n> -\t{ \"fetch-pack\", cmd_fetch_pack, RUN_SETUP },\n> -\t{ \"fmt-merge-msg\", cmd_fmt_merge_msg, RUN_SETUP },\n> -\t{ \"for-each-ref\", cmd_for_each_ref, RUN_SETUP },\n> -\t{ \"format-patch\", cmd_format_patch, RUN_SETUP },\n> -\t{ \"fsck\", cmd_fsck, RUN_SETUP },\n> -\t{ \"fsck-objects\", cmd_fsck, RUN_SETUP },\n> -\t{ \"gc\", cmd_gc, RUN_SETUP },\n> -\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id },\n> -\t{ \"grep\", cmd_grep, RUN_SETUP_GENTLY },\n> -\t{ \"hash-object\", cmd_hash_object },\n> -\t{ \"help\", cmd_help },\n> -\t{ \"index-pack\", cmd_index_pack, RUN_SETUP_GENTLY },\n> -\t{ \"init\", cmd_init_db },\n> -\t{ \"init-db\", cmd_init_db },\n> -\t{ \"log\", cmd_log, RUN_SETUP },\n> -\t{ \"ls-files\", cmd_ls_files, RUN_SETUP },\n> -\t{ \"ls-remote\", cmd_ls_remote, RUN_SETUP_GENTLY },\n> -\t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n> -\t{ \"mailinfo\", cmd_mailinfo },\n> -\t{ \"mailsplit\", cmd_mailsplit },\n> -\t{ \"merge\", cmd_merge, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"merge-base\", cmd_merge_base, RUN_SETUP },\n> -\t{ \"merge-file\", cmd_merge_file, RUN_SETUP_GENTLY },\n> -\t{ \"merge-index\", cmd_merge_index, RUN_SETUP },\n> -\t{ \"merge-ours\", cmd_merge_ours, RUN_SETUP },\n> -\t{ \"merge-recursive\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"merge-recursive-ours\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"merge-recursive-theirs\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"merge-subtree\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"merge-tree\", cmd_merge_tree, RUN_SETUP },\n> -\t{ \"mktag\", cmd_mktag, RUN_SETUP },\n> -\t{ \"mktree\", cmd_mktree, RUN_SETUP },\n> -\t{ \"mv\", cmd_mv, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n> -\t{ \"notes\", cmd_notes, RUN_SETUP },\n> -\t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\n> -\t{ \"pack-redundant\", cmd_pack_redundant, RUN_SETUP },\n> -\t{ \"pack-refs\", cmd_pack_refs, RUN_SETUP },\n> -\t{ \"patch-id\", cmd_patch_id },\n> -\t{ \"pickaxe\", cmd_blame, RUN_SETUP },\n> -\t{ \"prune\", cmd_prune, RUN_SETUP },\n> -\t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n> -\t{ \"push\", cmd_push, RUN_SETUP },\n> -\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n> -\t{ \"receive-pack\", cmd_receive_pack },\n> -\t{ \"reflog\", cmd_reflog, RUN_SETUP },\n> -\t{ \"remote\", cmd_remote, RUN_SETUP },\n> -\t{ \"remote-ext\", cmd_remote_ext },\n> -\t{ \"remote-fd\", cmd_remote_fd },\n> -\t{ \"repack\", cmd_repack, RUN_SETUP },\n> -\t{ \"replace\", cmd_replace, RUN_SETUP },\n> -\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n> -\t{ \"reset\", cmd_reset, RUN_SETUP },\n> -\t{ \"rev-list\", cmd_rev_list, RUN_SETUP },\n> -\t{ \"rev-parse\", cmd_rev_parse },\n> -\t{ \"revert\", cmd_revert, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"rm\", cmd_rm, RUN_SETUP },\n> -\t{ \"send-pack\", cmd_send_pack, RUN_SETUP },\n> -\t{ \"shortlog\", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },\n> -\t{ \"show\", cmd_show, RUN_SETUP },\n> -\t{ \"show-branch\", cmd_show_branch, RUN_SETUP },\n> -\t{ \"show-ref\", cmd_show_ref, RUN_SETUP },\n> -\t{ \"stage\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"status\", cmd_status, RUN_SETUP | NEED_WORK_TREE },\n> -\t{ \"stripspace\", cmd_stripspace },\n> -\t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n> -\t{ \"tag\", cmd_tag, RUN_SETUP },\n> -\t{ \"unpack-file\", cmd_unpack_file, RUN_SETUP },\n> -\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP },\n> -\t{ \"update-index\", cmd_update_index, RUN_SETUP },\n> -\t{ \"update-ref\", cmd_update_ref, RUN_SETUP },\n> -\t{ \"update-server-info\", cmd_update_server_info, RUN_SETUP },\n> -\t{ \"upload-archive\", cmd_upload_archive },\n> -\t{ \"upload-archive--writer\", cmd_upload_archive_writer },\n> -\t{ \"var\", cmd_var, RUN_SETUP_GENTLY },\n> -\t{ \"verify-pack\", cmd_verify_pack },\n> -\t{ \"verify-tag\", cmd_verify_tag, RUN_SETUP },\n> -\t{ \"version\", cmd_version },\n> -\t{ \"whatchanged\", cmd_whatchanged, RUN_SETUP },\n> -\t{ \"write-tree\", cmd_write_tree, RUN_SETUP },\n> -};\n> -\n> -int is_builtin(const char *s)\n> -{\n> -\tint i;\n> -\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n> -\t\tstruct cmd_struct *p = commands+i;\n> -\t\tif (!strcmp(s, p->cmd))\n> -\t\t\treturn 1;\n> -\t}\n> -\treturn 0;\n> -}\n> -\n> -static void handle_builtin(int argc, const char **argv)\n> -{\n> -\tconst char *cmd = argv[0];\n> -\tint i;\n> -\tstatic const char ext[] = STRIP_EXTENSION;\n> -\n> -\tif (sizeof(ext) > 1) {\n> -\t\ti = strlen(argv[0]) - strlen(ext);\n> -\t\tif (i > 0 && !strcmp(argv[0] + i, ext)) {\n> -\t\t\tchar *argv0 = xstrdup(argv[0]);\n> -\t\t\targv[0] = cmd = argv0;\n> -\t\t\targv0[i] = '\\0';\n> -\t\t}\n> -\t}\n> -\n> -\t/* Turn \"git cmd --help\" into \"git help cmd\" */\n> -\tif (argc > 1 && !strcmp(argv[1], \"--help\")) {\n> -\t\targv[1] = argv[0];\n> -\t\targv[0] = cmd = \"help\";\n> -\t}\n> -\n> -\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n> -\t\tstruct cmd_struct *p = commands+i;\n> -\t\tif (strcmp(p->cmd, cmd))\n> -\t\t\tcontinue;\n> -\t\texit(run_builtin(p, argc, argv));\n> -\t}\n> -}\n> -\n>  static void execv_dashed_external(const char **argv)\n>  {\n>  \tstruct strbuf cmd = STRBUF_INIT;\n"},{"id":"232575","messageId":"20140102203132.GQ20443@google.com","threadId":"35595","inReplyTo":"52C590B0.1020702@gmail.com","subject":"Re: [PATCH v2 1/4] Consistently use the term \"builtin\" instead of \"internal command\"","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2014-01-02T20:31:32Z","receivedAt":"2014-01-02T20:31:32Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi,\n\nSebastian Schuberth wrote:\n\n[...]\n> --- a/Documentation/technical/api-builtin.txt\n> +++ b/Documentation/technical/api-builtin.txt\n> @@ -14,7 +14,7 @@ Git:\n>  \n>  . Add the external declaration for the function to `builtin.h`.\n>  \n> -. Add the command to `commands[]` table in `handle_internal_command()`,\n> +. Add the command to `commands[]` table in `handle_builtin()`,\n\nMakes sense.  Using consistent jargon makes for easier reading.\n\n[...]\n> +++ b/git.c\n[...]\n> @@ -563,14 +563,14 @@ int main(int argc, char **av)\n[...]\n>  \tif (starts_with(cmd, \"git-\")) {\n>  \t\tcmd += 4;\n>  \t\targv[0] = cmd;\n> -\t\thandle_internal_command(argc, argv);\n> +\t\thandle_builtin(argc, argv);\n> -\t\tdie(\"cannot handle %s internally\", cmd);\n> +\t\tdie(\"cannot handle %s as a builtin\", cmd);\n\nI think this makes the user-visible message less clear.\n\nBefore when the user had a stale git-whatever link lingering in\ngitexecdir, git would say\n\n\tfatal: cannot handle whatever internally\n\nwhich tells me git was asked to handle the whatever command internally\nand was unable to.  Afterward, it becomes\n\n\tfatal: cannot handle whatever as a builtin\n\nwhich requires that I learn the jargon use of \"builtin\" as a noun.\nbusybox's analogous message is \"applet not found\".  It's less likely\nto come up when using git because it requires having a stray link to\n\"git\".  A message like\n\n\t$ git whatever\n\tfatal: whatever: no such built-in command\n\nwould just leave me wondering \"I never claimed it was built-in; what's\ngoing on?\"  I think it would be simplest to keep it as\n\n\t$ git whatever\n\tfatal: cannot handle \"whatever\" internally\n\nwhich at least makes it clear that this is a low-level error.\n\nThe rest of the patch looks good.\n\nThanks,\nJonathan\n"},{"id":"232582","messageId":"CAHGBnuMathrjUt10AqnEP=d4b306=+D4DFhPeDX0zmpsniA-rg@mail.gmail.com","threadId":"35595","inReplyTo":"xmqqy52yp3tm.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v2 4/4] Move builtin-related implementations to a new builtin.c file","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2014-01-02T20:58:48Z","receivedAt":"2014-01-02T20:58:48Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"On Thu, Jan 2, 2014 at 8:43 PM, Junio C Hamano <gitster@pobox.com> wrote:\n\n>>  Documentation/technical/api-builtin.txt |   2 +-\n>>  Makefile                                |   1 +\n>>  builtin.c                               | 225 ++++++++++++++++++++++++++++++\n>>  builtin.h                               |  21 +++\n>>  git.c                                   | 238 --------------------------------\n>>  5 files changed, 248 insertions(+), 239 deletions(-)\n>>  create mode 100644 builtin.c\n>\n> I'm sorry but I do not see a point in this.\n>\n> It is not like builtin.c can be used outside the context of the main\n> Git program, and many helper functions you moved out of git.c that\n> used to be static want to be called from other places.\n\nI've added this commit because Christian suggested so in [1], and also\nbecause it has always bothered me that the Git project does not define\na function in a file named after the header file that declares the\nfunction. Anyway, I've made this the last commit in the series on\npurpose, I can just drop it in the next re-roll.\n\n[1] http://www.spinics.net/lists/git/msg222452.html.\n\n-- \nSebastian Schuberth\n"},{"id":"232583","messageId":"CAHGBnuO+MT4pZHD8AiQ5mFU8bDwoFSgaCyxUzL572YVstCerqA@mail.gmail.com","threadId":"35595","inReplyTo":"20140102203132.GQ20443@google.com","subject":"Re: [PATCH v2 1/4] Consistently use the term \"builtin\" instead of \"internal command\"","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2014-01-02T21:05:42Z","receivedAt":"2014-01-02T21:05:42Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"On Thu, Jan 2, 2014 at 9:31 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n\n> would just leave me wondering \"I never claimed it was built-in; what's\n> going on?\"  I think it would be simplest to keep it as\n>\n>         $ git whatever\n>         fatal: cannot handle \"whatever\" internally\n>\n> which at least makes it clear that this is a low-level error.\n\nRight, I'll change this in a re-roll (using single-quotes for the command name).\n\n> The rest of the patch looks good.\n\nThanks for the review.\n\n-- \nSebastian Schuberth\n"},{"id":"232616","messageId":"20140103154426.GA23534@sigill.intra.peff.net","threadId":"35595","inReplyTo":"xmqq38l6qii6.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v2 3/4] Speed up is_git_command() by checking early for internal commands","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-03T15:44:26Z","receivedAt":"2014-01-03T15:44:26Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Jan 02, 2014 at 11:41:05AM -0800, Junio C Hamano wrote:\n\n>  - builtin/merge.c is the same, but it is conceptually even worse.\n>    It has the end-user supplied string and wants to see if it is a\n>    valid strategy.  If the user wants to use a custom strategy, a\n>    single stat() to make sure if it exists should suffice, and the\n>    error codepath should load the command list to present the names\n>    of available ones in the error message.\n\nIs it a single stat()? I think we would need to check each element of\n$PATH. Though in practice, the exec-dir would be the first thing we\ncheck, and where we would find the majority of hits. So it would still\nbe a win, as we would avoid touching anything but the exec-dir in the\ncommon case.\n\n-Peff\n"},{"id":"232617","messageId":"371D58A5-4640-4125-9B69-E9A7B03B347F@acm.org","threadId":"35595","inReplyTo":"52C59107.6080005@gmail.com","subject":"Re: [PATCH v2 3/4] Speed up is_git_command() by checking early for internal commands","fromName":"Kent R. Spillner","fromEmail":"kspillner@acm.org","sentAt":"2014-01-03T16:49:26Z","receivedAt":"2014-01-03T16:49:26Z","isPatch":true,"sender":{"key":"kspillner@acm.org","avatar":"https://gravatar.com/avatar/050ad1f9bbca4ec2de093b251f225080467f6d8180227caf25b591bd123d140a?d=mp&s=160"},"body":"\n> Since 2dce956 is_git_command() is a bit slow as it does file I/O in the\n> call to list_commands_in_dir(). Avoid the file I/O by adding an early\n> check for internal commands.\n\nConsidering the purpose of the series is it better to say \"builtin\" instead of \"internal\" in the commit message?"},{"id":"232622","messageId":"xmqqob3tlzco.fsf@gitster.dls.corp.google.com","threadId":"35595","inReplyTo":"20140103154426.GA23534@sigill.intra.peff.net","subject":"Re: [PATCH v2 3/4] Speed up is_git_command() by checking early for internal commands","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-03T18:00:39Z","receivedAt":"2014-01-03T18:00:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Thu, Jan 02, 2014 at 11:41:05AM -0800, Junio C Hamano wrote:\n>\n>>  - builtin/merge.c is the same, but it is conceptually even worse.\n>>    It has the end-user supplied string and wants to see if it is a\n>>    valid strategy.  If the user wants to use a custom strategy, a\n>>    single stat() to make sure if it exists should suffice, and the\n>>    error codepath should load the command list to present the names\n>>    of available ones in the error message.\n>\n> Is it a single stat()? I think we would need to check each element of\n> $PATH. \n\nYeah, load_command_list() iterates over the members of env_path.\n\n> Though in practice, the exec-dir would be the first thing we\n> check, and where we would find the majority of hits. So it would still\n> be a win, as we would avoid touching anything but the exec-dir in the\n> common case.\n\nExactly.\n"},{"id":"232668","messageId":"CAHGBnuNNaKNx7FzjoNhorryR5eO2c0VvbUgRc_p01mabOVr+EA@mail.gmail.com","threadId":"35595","inReplyTo":"371D58A5-4640-4125-9B69-E9A7B03B347F@acm.org","subject":"Re: [PATCH v2 3/4] Speed up is_git_command() by checking early for internal commands","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2014-01-05T13:42:08Z","receivedAt":"2014-01-05T13:42:08Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"On Fri, Jan 3, 2014 at 5:49 PM, Kent R. Spillner <kspillner@acm.org> wrote:\n\n>> Since 2dce956 is_git_command() is a bit slow as it does file I/O in the\n>> call to list_commands_in_dir(). Avoid the file I/O by adding an early\n>> check for internal commands.\n>\n> Considering the purpose of the series is it better to say \"builtin\" instead of \"internal\" in the commit message?\n\nTrue, I'll fix this in a re-rool.\n\n-- \nSebastian Schuberth\n"},{"id":"233543","messageId":"52E03285.2070305@gmail.com","threadId":"35595","inReplyTo":"CAHGBnuNNaKNx7FzjoNhorryR5eO2c0VvbUgRc_p01mabOVr+EA@mail.gmail.com","subject":"Re: [PATCH v2 3/4] Speed up is_git_command() by checking early for internal commands","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2014-01-22T21:05:09Z","receivedAt":"2014-01-22T21:05:09Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"On 05.01.2014 14:42, Sebastian Schuberth wrote:\n\n>>> Since 2dce956 is_git_command() is a bit slow as it does file I/O in the\n>>> call to list_commands_in_dir(). Avoid the file I/O by adding an early\n>>> check for internal commands.\n>>\n>> Considering the purpose of the series is it better to say \"builtin\" instead of \"internal\" in the commit message?\n>\n> True, I'll fix this in a re-rool.\n\nSorry for not coming up with the re-roll until now, but lucky Junio has \nfixed this himself in c6127fa which already is on master.\n\n-- \nSebastian Schuberth\n"},{"id":"233544","messageId":"52E0335D.3090408@gmail.com","threadId":"35595","inReplyTo":"CAHGBnuO+MT4pZHD8AiQ5mFU8bDwoFSgaCyxUzL572YVstCerqA@mail.gmail.com","subject":"Re: [PATCH v2 1/4] Consistently use the term \"builtin\" instead of \"internal command\"","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2014-01-22T21:08:45Z","receivedAt":"2014-01-22T21:08:45Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"On 02.01.2014 22:05, Sebastian Schuberth wrote:\n\n>> would just leave me wondering \"I never claimed it was built-in; what's\n>> going on?\"  I think it would be simplest to keep it as\n>>\n>>          $ git whatever\n>>          fatal: cannot handle \"whatever\" internally\n>>\n>> which at least makes it clear that this is a low-level error.\n>\n> Right, I'll change this in a re-roll (using single-quotes for the command name).\n\nSorry for not coming up with the re-roll until now, and now it's too \nlate to fixup the commit as it's already on master (3f784a4). Since this \nis just a minor wording issue I'll not follow this up anymore.\n\n-- \nSebastian Schuberth\n"}]}