{"thread":{"id":"8250","subject":"[RFC] Third round of support for cloning submodules","startedAt":"2007-05-20T18:04:33Z","lastAt":"2007-05-24T15:56:16Z","messageCount":53,"participants":["skimo@liacs.nl","Frank Lichtenheld","Junio C Hamano","Sven Verdoolaege","Alex Riesen","Martin Waitz","Steven Grimm","Josef Weidendorfer"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"42736","messageId":"11796842882917-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":null,"subject":"[RFC] Third round of support for cloning submodules","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:33Z","receivedAt":"2007-05-20T18:04:33Z","isPatch":false,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nThis patch series implements a mechanism for cloning submodules.\nEach submodule is specified by a 'submodule.<submodule>.url'\nconfiguration option, e.g.,\n\nbash-3.00$ ./git-config --remote=http://www.liacs.nl/~sverdool/isa.git --get-regexp 'submodule\\..*\\.url' \nsubmodule.cloog.url /home/sverdool/public_html/cloog.git\nsubmodule.cloog.url http://www.liacs.nl/~sverdool/cloog.git\n\ngit-checkout will use the first url that works.\nE.g., a\n\ngit clone --submodules ssh://liacs/~/public_html/isa.git\n\nfollowed by\n\ngit checkout origin/submodule\n\n(which only works for me), will use the first url, while a\n\ngit clone --submodules http://www.liacs.nl/~sverdool/isa.git\n\nfollowed by\n\ngit checkout origin/submodule\n\nwill use the second.\n\nThe cloning of submodules is now handled inside git-checkout.\n\nI currently do not fetch after the initial clone, since\nI'm not sure what ref to use for the revision I need to\nfetch for the supermodule.\nSuggestions are welcome.\n\nNote that this is still WIP, so there is no need to remind\nme that I still need to write documentation and tests.\n\nskimo\n"},{"id":"42740","messageId":"11796842882228-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 01/15] Add dump-config","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:34Z","receivedAt":"2007-05-20T18:04:34Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nThis command dumps the config of a repository and will be used\nto read config options from a remote site.\n\nSigned-off-by: Sven Verdoolaege <skimo@kotnet.org>\n---\n .gitignore                        |    1 +\n Documentation/cmd-list.perl       |    1 +\n Documentation/git-dump-config.txt |   37 +++++++++++++++++++++++++++++++++++++\n Makefile                          |    1 +\n daemon.c                          |    7 +++++++\n dump-config.c                     |   29 +++++++++++++++++++++++++++++\n 6 files changed, 76 insertions(+), 0 deletions(-)\n create mode 100644 Documentation/git-dump-config.txt\n create mode 100644 dump-config.c\n\ndiff --git a/.gitignore b/.gitignore\nindex 4dc0c39..d4e5492 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -38,6 +38,7 @@ git-diff-files\n git-diff-index\n git-diff-tree\n git-describe\n+git-dump-config\n git-fast-import\n git-fetch\n git-fetch--tool\ndiff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl\nindex 443802a..fa04615 100755\n--- a/Documentation/cmd-list.perl\n+++ b/Documentation/cmd-list.perl\n@@ -103,6 +103,7 @@ git-diff-files                          plumbinginterrogators\n git-diff-index                          plumbinginterrogators\n git-diff                                mainporcelain\n git-diff-tree                           plumbinginterrogators\n+git-dump-config                         synchelpers\n git-fast-import\t\t\t\tancillarymanipulators\n git-fetch                               mainporcelain\n git-fetch-pack                          synchingrepositories\ndiff --git a/Documentation/git-dump-config.txt b/Documentation/git-dump-config.txt\nnew file mode 100644\nindex 0000000..370781c\n--- /dev/null\n+++ b/Documentation/git-dump-config.txt\n@@ -0,0 +1,37 @@\n+git-dump-config(1)\n+====================\n+\n+NAME\n+----\n+git-dump-config - Dump config options\n+\n+\n+SYNOPSIS\n+--------\n+'git-dump-config' <directory>\n+\n+DESCRIPTION\n+-----------\n+Invoked by 'git-config --remote' and dumps the config file to the\n+other end over the git protocol.\n+\n+This command is usually not invoked directly by the end user.  The UI\n+for the protocol is on the 'git-config' side, where it is used to get\n+options from a remote repository.\n+\n+OPTIONS\n+-------\n+<directory>::\n+\tThe repository to get the config options from.\n+\n+Author\n+------\n+Written by Sven Verdoolaege.\n+\n+Documentation\n+--------------\n+Documentation by Sven Verdoolaege.\n+\n+GIT\n+---\n+Part of the gitlink:git[7] suite\ndiff --git a/Makefile b/Makefile\nindex 29243c6..37eb861 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -240,6 +240,7 @@ PROGRAMS = \\\n \tgit-fast-import$X \\\n \tgit-merge-base$X \\\n \tgit-daemon$X \\\n+\tgit-dump-config$X \\\n \tgit-merge-index$X git-mktag$X git-mktree$X git-patch-id$X \\\n \tgit-peek-remote$X git-receive-pack$X \\\n \tgit-send-pack$X git-shell$X \\\ndiff --git a/daemon.c b/daemon.c\nindex e74ecac..3e5ebf3 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -378,10 +378,17 @@ static int receive_pack(void)\n \treturn -1;\n }\n \n+static int dump_config(void)\n+{\n+\texecl_git_cmd(\"dump-config\", \".\", NULL);\n+\treturn -1;\n+}\n+\n static struct daemon_service daemon_service[] = {\n \t{ \"upload-archive\", \"uploadarch\", upload_archive, 0, 1 },\n \t{ \"upload-pack\", \"uploadpack\", upload_pack, 1, 1 },\n \t{ \"receive-pack\", \"receivepack\", receive_pack, 0, 1 },\n+\t{ \"dump-config\", \"dumpconfig\", dump_config, 0, 1 },\n };\n \n static void enable_service(const char *name, int ena) {\ndiff --git a/dump-config.c b/dump-config.c\nnew file mode 100644\nindex 0000000..355920d\n--- /dev/null\n+++ b/dump-config.c\n@@ -0,0 +1,29 @@\n+#include \"git-compat-util.h\"\n+#include \"cache.h\"\n+#include \"pkt-line.h\"\n+\n+static const char dump_config_usage[] = \"git-dump-config <dir>\";\n+\n+static int dump_config(const char *var, const char *value)\n+{\n+\tpacket_write(1, \"%s\", var);\n+\tpacket_write(1, \"%s\", value);\n+\treturn 0;\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tchar *dir;\n+\n+\tif (argc != 2)\n+\t\tusage(dump_config_usage);\n+\n+\tdir = argv[1];\n+\tif (!enter_repo(dir, 0))\n+\t\tdie(\"'%s': unable to chdir or not a git archive\", dir);\n+\n+\tgit_config(dump_config);\n+\tpacket_flush(1);\n+\n+\treturn 0;\n+}\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42739","messageId":"11796842881646-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 02/15] git-config: add --remote option for reading config from remote repo","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:35Z","receivedAt":"2007-05-20T18:04:35Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nSigned-off-by: Sven Verdoolaege <skimo@kotnet.org>\n---\n Documentation/git-config.txt |   33 +++++++++++++++++++++---------\n builtin-config.c             |   44 ++++++++++++++++++++++++++++++++---------\n cache.h                      |    1 +\n config.c                     |   26 ++++++++++++++++++++++++\n 4 files changed, 84 insertions(+), 20 deletions(-)\n\ndiff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\nindex 280ef20..76398ab 100644\n--- a/Documentation/git-config.txt\n+++ b/Documentation/git-config.txt\n@@ -9,16 +9,25 @@ git-config - Get and set repository or global options\n SYNOPSIS\n --------\n [verse]\n-'git-config' [--system | --global] [type] name [value [value_regex]]\n-'git-config' [--system | --global] [type] --add name value\n-'git-config' [--system | --global] [type] --replace-all name [value [value_regex]]\n-'git-config' [--system | --global] [type] --get name [value_regex]\n-'git-config' [--system | --global] [type] --get-all name [value_regex]\n-'git-config' [--system | --global] [type] --unset name [value_regex]\n-'git-config' [--system | --global] [type] --unset-all name [value_regex]\n-'git-config' [--system | --global] [type] --rename-section old_name new_name\n-'git-config' [--system | --global] [type] --remove-section name\n-'git-config' [--system | --global] -l | --list\n+'git-config' [--system | --global | --remote=[<host>:]<directory ]\n+\t     [type] name [value [value_regex]]\n+'git-config' [--system | --global | --remote=[<host>:]<directory ]\n+\t     [type] --add name value\n+'git-config' [--system | --global | --remote=[<host>:]<directory ]\n+\t     [type] --replace-all name [value [value_regex]]\n+'git-config' [--system | --global | --remote=[<host>:]<directory ]\n+\t     [type] --get name [value_regex]\n+'git-config' [--system | --global | --remote=[<host>:]<directory ]\n+\t     [type] --get-all name [value_regex]\n+'git-config' [--system | --global | --remote=[<host>:]<directory ]\n+\t     [type] --unset name [value_regex]\n+'git-config' [--system | --global | --remote=[<host>:]<directory ]\n+\t     [type] --unset-all name [value_regex]\n+'git-config' [--system | --global | --remote=[<host>:]<directory ]\n+\t     [type] --rename-section old_name new_name\n+'git-config' [--system | --global | --remote=[<host>:]<directory ]\n+\t     [type] --remove-section name\n+'git-config' [--system | --global | --remote=[<host>:]<directory ] -l | --list\n \n DESCRIPTION\n -----------\n@@ -80,6 +89,10 @@ OPTIONS\n \tUse system-wide $(prefix)/etc/gitconfig rather than the repository\n \t.git/config.\n \n+--remote=[<host>:]<directory\n+\tUse remote config instead of the repository .git/config.\n+\tOnly available for reading options.\n+\n --remove-section::\n \tRemove the given section from the configuration file.\n \ndiff --git a/builtin-config.c b/builtin-config.c\nindex b2515f7..3a1e86c 100644\n--- a/builtin-config.c\n+++ b/builtin-config.c\n@@ -2,8 +2,10 @@\n #include \"cache.h\"\n \n static const char git_config_set_usage[] =\n-\"git-config [ --global | --system ] [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list\";\n+\"git-config [ --global | --system | --remote=[<host>:]<directory ] \"\n+\"[ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list\";\n \n+static char *dest;\n static char *key;\n static regex_t *key_regexp;\n static regex_t *regexp;\n@@ -104,15 +106,19 @@ static int get_value(const char* key_, const char* regex_)\n \t\t}\n \t}\n \n-\tif (do_all && system_wide)\n-\t\tgit_config_from_file(show_config, system_wide);\n-\tif (do_all && global)\n-\t\tgit_config_from_file(show_config, global);\n-\tgit_config_from_file(show_config, local);\n-\tif (!do_all && !seen && global)\n-\t\tgit_config_from_file(show_config, global);\n-\tif (!do_all && !seen && system_wide)\n-\t\tgit_config_from_file(show_config, system_wide);\n+\tif (dest)\n+\t\tgit_config_from_remote(show_config, dest);\n+\telse {\n+\t\tif (do_all && system_wide)\n+\t\t\tgit_config_from_file(show_config, system_wide);\n+\t\tif (do_all && global)\n+\t\t\tgit_config_from_file(show_config, global);\n+\t\tgit_config_from_file(show_config, local);\n+\t\tif (!do_all && !seen && global)\n+\t\t\tgit_config_from_file(show_config, global);\n+\t\tif (!do_all && !seen && system_wide)\n+\t\t\tgit_config_from_file(show_config, system_wide);\n+\t}\n \n \tfree(key);\n \tif (regexp) {\n@@ -155,8 +161,14 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t}\n \t\telse if (!strcmp(argv[1], \"--system\"))\n \t\t\tsetenv(\"GIT_CONFIG\", ETC_GITCONFIG, 1);\n+\t\telse if (!prefixcmp(argv[1], \"--remote=\"))\n+\t\t\tdest = xstrdup(argv[1]+9);\n \t\telse if (!strcmp(argv[1], \"--rename-section\")) {\n \t\t\tint ret;\n+\t\t\tif (dest) {\n+\t\t\t\tfprintf(stderr, \"Cannot rename on remote\\n\");\n+\t\t\t\treturn 1;\n+\t\t\t}\n \t\t\tif (argc != 4)\n \t\t\t\tusage(git_config_set_usage);\n \t\t\tret = git_config_rename_section(argv[2], argv[3]);\n@@ -170,6 +182,10 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t}\n \t\telse if (!strcmp(argv[1], \"--remove-section\")) {\n \t\t\tint ret;\n+\t\t\tif (dest) {\n+\t\t\t\tfprintf(stderr, \"Cannot remove on remote\\n\");\n+\t\t\t\treturn 1;\n+\t\t\t}\n \t\t\tif (argc != 3)\n \t\t\t\tusage(git_config_set_usage);\n \t\t\tret = git_config_rename_section(argv[2], NULL);\n@@ -191,6 +207,10 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \tcase 2:\n \t\treturn get_value(argv[1], NULL);\n \tcase 3:\n+\t\tif (dest && prefixcmp(argv[1], \"--get\")) {\n+\t\t\tfprintf(stderr, \"Cannot (un)set on remote\\n\");\n+\t\t\treturn 1;\n+\t\t}\n \t\tif (!strcmp(argv[1], \"--unset\"))\n \t\t\treturn git_config_set(argv[2], NULL);\n \t\telse if (!strcmp(argv[1], \"--unset-all\"))\n@@ -209,6 +229,10 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \n \t\t\treturn git_config_set(argv[1], argv[2]);\n \tcase 4:\n+\t\tif (dest && prefixcmp(argv[1], \"--get\")) {\n+\t\t\tfprintf(stderr, \"Cannot (un)set on remote\\n\");\n+\t\t\treturn 1;\n+\t\t}\n \t\tif (!strcmp(argv[1], \"--unset\"))\n \t\t\treturn git_config_set_multivar(argv[2], NULL, argv[3], 0);\n \t\telse if (!strcmp(argv[1], \"--unset-all\"))\ndiff --git a/cache.h b/cache.h\nindex 65b4685..452aa89 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -501,6 +501,7 @@ extern int update_server_info(int);\n typedef int (*config_fn_t)(const char *, const char *);\n extern int git_default_config(const char *, const char *);\n extern int git_config_from_file(config_fn_t fn, const char *);\n+extern int git_config_from_remote(config_fn_t fn, char *dest);\n extern int git_config(config_fn_t fn);\n extern int git_config_int(const char *, const char *);\n extern int git_config_bool(const char *, const char *);\ndiff --git a/config.c b/config.c\nindex 0614c2b..dbfae3f 100644\n--- a/config.c\n+++ b/config.c\n@@ -6,9 +6,12 @@\n  *\n  */\n #include \"cache.h\"\n+#include \"pkt-line.h\"\n \n #define MAXNAME (256)\n \n+static const char *dumpconfig = \"git-dump-config\";\n+\n static FILE *config_file;\n static const char *config_file_name;\n static int config_linenr;\n@@ -403,6 +406,29 @@ int git_config_from_file(config_fn_t fn, const char *filename)\n \treturn ret;\n }\n \n+int git_config_from_remote(config_fn_t fn, char *dest)\n+{\n+\tint ret;\n+\tint fd[2];\n+\tpid_t pid;\n+\tstatic char var[MAXNAME];\n+\tstatic char value[1024];\n+\n+\tpid = git_connect(fd, dest, dumpconfig);\n+\tif (pid < 0)\n+\t\treturn 1;\n+\tret = 0;\n+\twhile (packet_read_line(fd[0], var, sizeof(var))) {\n+\t\tif (!packet_read_line(fd[0], value, sizeof(value)))\n+\t\t\tdie(\"Missing value\");\n+\t\tfn(var, value);\n+\t}\n+\tclose(fd[0]);\n+\tclose(fd[1]);\n+\tret |= finish_connect(pid);\n+\treturn !!ret;\n+}\n+\n int git_config(config_fn_t fn)\n {\n \tint ret = 0;\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42745","messageId":"11796842881756-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 03/15] http.h: make fill_active_slots a function pointer","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:36Z","receivedAt":"2007-05-20T18:04:36Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nThis allows us to use the methods provided by http.c\nfrom within libgit, in particular config.c.\n\nSigned-off-by: Sven Verdoolaege <skimo@kotnet.org>\n---\n http-fetch.c |    5 ++++-\n http-push.c  |    5 ++++-\n http.h       |    2 +-\n 3 files changed, 9 insertions(+), 3 deletions(-)\n\ndiff --git a/http-fetch.c b/http-fetch.c\nindex 09baedc..53fb2a9 100644\n--- a/http-fetch.c\n+++ b/http-fetch.c\n@@ -317,7 +317,7 @@ static void release_object_request(struct object_request *obj_req)\n }\n \n #ifdef USE_CURL_MULTI\n-void fill_active_slots(void)\n+static void fetch_fill_active_slots(void)\n {\n \tstruct object_request *obj_req = object_queue_head;\n \tstruct active_request_slot *slot = active_queue_head;\n@@ -1031,6 +1031,9 @@ int main(int argc, const char **argv)\n \t}\n \turl = argv[arg];\n \n+#ifdef USE_CURL_MULTI\n+\tfill_active_slots = fetch_fill_active_slots;\n+#endif\n \thttp_init();\n \n \tno_pragma_header = curl_slist_append(no_pragma_header, \"Pragma:\");\ndiff --git a/http-push.c b/http-push.c\nindex e3f7675..d4c850b 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -794,7 +794,7 @@ static void finish_request(struct transfer_request *request)\n }\n \n #ifdef USE_CURL_MULTI\n-void fill_active_slots(void)\n+static void push_fill_active_slots(void)\n {\n \tstruct transfer_request *request = request_queue_head;\n \tstruct transfer_request *next;\n@@ -2355,6 +2355,9 @@ int main(int argc, char **argv)\n \n \tmemset(remote_dir_exists, -1, 256);\n \n+#ifdef USE_CURL_MULTI\n+\tfill_active_slots = push_fill_active_slots;\n+#endif\n \thttp_init();\n \n \tno_pragma_header = curl_slist_append(no_pragma_header, \"Pragma:\");\ndiff --git a/http.h b/http.h\nindex 69b6b66..7a41cde 100644\n--- a/http.h\n+++ b/http.h\n@@ -69,7 +69,7 @@ extern void finish_all_active_slots(void);\n extern void release_active_slot(struct active_request_slot *slot);\n \n #ifdef USE_CURL_MULTI\n-extern void fill_active_slots(void);\n+extern void (*fill_active_slots)(void);\n extern void step_active_slots(void);\n #endif\n \n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42742","messageId":"11796842881906-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 04/15] git-config: read remote config files over HTTP","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:37Z","receivedAt":"2007-05-20T18:04:37Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nSigned-off-by: Sven Verdoolaege <skimo@kotnet.org>\n---\n Makefile           |    7 ++++++-\n builtin-config.c   |    8 ++++++--\n config.c           |   16 +++++++++++++++-\n http.c             |   10 ++++++----\n http.h             |    2 +-\n http_config.h      |    1 +\n http_config_curl.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++++\n http_config_none.c |    6 ++++++\n 8 files changed, 93 insertions(+), 9 deletions(-)\n create mode 100644 http_config.h\n create mode 100644 http_config_curl.c\n create mode 100644 http_config_none.c\n\ndiff --git a/Makefile b/Makefile\nindex 37eb861..bce8514 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -319,7 +319,8 @@ LIB_OBJS = \\\n \twrite_or_die.o trace.o list-objects.o grep.o match-trees.o \\\n \talloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \\\n \tcolor.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \\\n-\tconvert.o attr.o decorate.o progress.o mailmap.o symlinks.o\n+\tconvert.o attr.o decorate.o progress.o mailmap.o symlinks.o \\\n+\t$(HTTP_CONFIG_OBJ)\n \n BUILTIN_OBJS = \\\n \tbuiltin-add.o \\\n@@ -526,6 +527,10 @@ ifndef NO_CURL\n \tifndef NO_EXPAT\n \t\tEXPAT_LIBEXPAT = -lexpat\n \tendif\n+\tHTTP_CONFIG_OBJ = http_config_curl.o http.o\n+\tEXTLIBS += $(CURL_LIBCURL)\n+else\n+\tHTTP_CONFIG_OBJ = http_config_none.o\n endif\n \n ifndef NO_OPENSSL\ndiff --git a/builtin-config.c b/builtin-config.c\nindex 3a1e86c..7e18f73 100644\n--- a/builtin-config.c\n+++ b/builtin-config.c\n@@ -147,8 +147,12 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\ttype = T_INT;\n \t\telse if (!strcmp(argv[1], \"--bool\"))\n \t\t\ttype = T_BOOL;\n-\t\telse if (!strcmp(argv[1], \"--list\") || !strcmp(argv[1], \"-l\"))\n-\t\t\treturn git_config(show_all_config);\n+\t\telse if (!strcmp(argv[1], \"--list\") || !strcmp(argv[1], \"-l\")) {\n+\t\t\tif (dest)\n+\t\t\t\treturn git_config_from_remote(show_all_config, dest);\n+\t\t\telse\n+\t\t\t\treturn git_config(show_all_config);\n+\t\t}\n \t\telse if (!strcmp(argv[1], \"--global\")) {\n \t\t\tchar *home = getenv(\"HOME\");\n \t\t\tif (home) {\ndiff --git a/config.c b/config.c\nindex dbfae3f..fc2162b 100644\n--- a/config.c\n+++ b/config.c\n@@ -7,6 +7,7 @@\n  */\n #include \"cache.h\"\n #include \"pkt-line.h\"\n+#include \"http_config.h\"\n \n #define MAXNAME (256)\n \n@@ -406,6 +407,16 @@ int git_config_from_file(config_fn_t fn, const char *filename)\n \treturn ret;\n }\n \n+static int config_from_http(config_fn_t fn, char *dest)\n+{\n+\tchar config_temp[50];\n+\tif (git_http_fetch_config(dest, config_temp, sizeof(config_temp)))\n+\t\treturn 1;\n+\tgit_config_from_file(fn, config_temp);\n+\tunlink(config_temp);\n+\treturn 0;\n+}\n+\n int git_config_from_remote(config_fn_t fn, char *dest)\n {\n \tint ret;\n@@ -414,7 +425,10 @@ int git_config_from_remote(config_fn_t fn, char *dest)\n \tstatic char var[MAXNAME];\n \tstatic char value[1024];\n \n-\tpid = git_connect(fd, dest, dumpconfig);\n+\tif (!prefixcmp(dest, \"http://\"))\n+\t\treturn config_from_http(fn, dest);\n+\n+\tpid = git_connect(fd, dest, dumpconfig, 0);\n \tif (pid < 0)\n \t\treturn 1;\n \tret = 0;\ndiff --git a/http.c b/http.c\nindex ae27e0c..c8237cb 100644\n--- a/http.c\n+++ b/http.c\n@@ -25,6 +25,8 @@ long curl_low_speed_limit = -1;\n long curl_low_speed_time = -1;\n int curl_ftp_no_epsv = 0;\n \n+void (*fill_active_slots)(void) = NULL;\n+\n struct curl_slist *pragma_header;\n \n struct active_request_slot *active_queue_head = NULL;\n@@ -394,7 +396,8 @@ void step_active_slots(void)\n \t} while (curlm_result == CURLM_CALL_MULTI_PERFORM);\n \tif (num_transfers < active_requests) {\n \t\tprocess_curl_messages();\n-\t\tfill_active_slots();\n+\t\tif (fill_active_slots)\n+\t\t\tfill_active_slots();\n \t}\n }\n #endif\n@@ -458,9 +461,8 @@ void release_active_slot(struct active_request_slot *slot)\n \t\tcurl_easy_cleanup(slot->curl);\n \t\tslot->curl = NULL;\n \t}\n-#ifdef USE_CURL_MULTI\n-\tfill_active_slots();\n-#endif\n+\tif (fill_active_slots)\n+\t\tfill_active_slots();\n }\n \n static void finish_active_slot(struct active_request_slot *slot)\ndiff --git a/http.h b/http.h\nindex 7a41cde..7f29ff8 100644\n--- a/http.h\n+++ b/http.h\n@@ -68,8 +68,8 @@ extern void run_active_slot(struct active_request_slot *slot);\n extern void finish_all_active_slots(void);\n extern void release_active_slot(struct active_request_slot *slot);\n \n-#ifdef USE_CURL_MULTI\n extern void (*fill_active_slots)(void);\n+#ifdef USE_CURL_MULTI\n extern void step_active_slots(void);\n #endif\n \ndiff --git a/http_config.h b/http_config.h\nnew file mode 100644\nindex 0000000..25f5c19\n--- /dev/null\n+++ b/http_config.h\n@@ -0,0 +1 @@\n+int git_http_fetch_config(const char *repo, char *config_file, int len);\ndiff --git a/http_config_curl.c b/http_config_curl.c\nnew file mode 100644\nindex 0000000..88317cf\n--- /dev/null\n+++ b/http_config_curl.c\n@@ -0,0 +1,52 @@\n+#include \"http_config.h\"\n+#include \"http.h\"\n+\n+int git_http_fetch_config(const char *repo, char *config, int config_len)\n+{\n+\tchar url[PATH_MAX];\n+\tint len = strlen(repo);\n+\n+\tint fd;\n+\tFILE *configfile;\n+\tstruct active_request_slot *slot;\n+\tstruct slot_results results;\n+\n+\tstrcpy(url, repo);\n+\twhile (len > 0 && url[len-1] == '/')\n+\t\t--len;\n+\tsnprintf(url+len, sizeof(url)-len, \"/config\");\n+\n+\tfd = git_mkstemp(config, config_len, \".config_XXXXXX\");\n+\tif (fd >= 0)\n+\t\tconfigfile = fdopen(fd, \"w\");\n+\tif (fd < 0 || !configfile)\n+\t\treturn error(\"Unable to open local file %s for config\",\n+\t\t\t     config);\n+\n+\thttp_init();\n+\n+\tslot = get_active_slot();\n+\tslot->results = &results;\n+\tcurl_easy_setopt(slot->curl, CURLOPT_FILE, configfile);\n+\tcurl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);\n+\tcurl_easy_setopt(slot->curl, CURLOPT_URL, url);\n+\tslot->local = configfile;\n+\n+\tif (start_active_slot(slot)) {\n+\t\trun_active_slot(slot);\n+\t\tif (results.curl_result != CURLE_OK) {\n+\t\t\tfclose(configfile);\n+\t\t\twarning(\"Unable to get config %s\\n%s\", url,\n+\t\t\t\t curl_errorstr);\n+\t\t}\n+\t} else {\n+\t\tfclose(configfile);\n+\t\treturn error(\"Unable to start request\");\n+\t}\n+\n+\thttp_cleanup();\n+\n+\tfclose(configfile);\n+\n+\treturn 0;\n+}\ndiff --git a/http_config_none.c b/http_config_none.c\nnew file mode 100644\nindex 0000000..860ae84\n--- /dev/null\n+++ b/http_config_none.c\n@@ -0,0 +1,6 @@\n+#include \"http_config.h\"\n+\n+int git_http_fetch_config(const char *repo, char *config_file, int len)\n+{\n+\treturn error(\"Reading http config files not supported\");\n+}\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42744","messageId":"11796842892135-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 05/15] unpack-trees.c: pass cache_entry * to verify_absent rather than just the name","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:38Z","receivedAt":"2007-05-20T18:04:38Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nWe will need the full cache_entry later to figure out if we are dealing\nwith a submodule.\n\nSigned-off-by: Sven Verdoolaege <skimo@kotnet.org>\n---\n unpack-trees.c |   32 ++++++++++++++++----------------\n 1 files changed, 16 insertions(+), 16 deletions(-)\n\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 906ce69..317f656 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -491,7 +491,7 @@ static int verify_clean_subdirectory(const char *path, const char *action,\n  * We do not want to remove or overwrite a working tree file that\n  * is not tracked, unless it is ignored.\n  */\n-static void verify_absent(const char *path, const char *action,\n+static void verify_absent(struct cache_entry *ce, const char *action,\n \t\tstruct unpack_trees_options *o)\n {\n \tstruct stat st;\n@@ -499,12 +499,12 @@ static void verify_absent(const char *path, const char *action,\n \tif (o->index_only || o->reset || !o->update)\n \t\treturn;\n \n-\tif (!lstat(path, &st)) {\n+\tif (!lstat(ce->name, &st)) {\n \t\tint cnt;\n \n-\t\tif (o->dir && excluded(o->dir, path))\n+\t\tif (o->dir && excluded(o->dir, ce->name))\n \t\t\t/*\n-\t\t\t * path is explicitly excluded, so it is Ok to\n+\t\t\t * ce->name is explicitly excluded, so it is Ok to\n \t\t\t * overwrite it.\n \t\t\t */\n \t\t\treturn;\n@@ -516,7 +516,7 @@ static void verify_absent(const char *path, const char *action,\n \t\t\t * files that are in \"foo/\" we would lose\n \t\t\t * it.\n \t\t\t */\n-\t\t\tcnt = verify_clean_subdirectory(path, action, o);\n+\t\t\tcnt = verify_clean_subdirectory(ce->name, action, o);\n \n \t\t\t/*\n \t\t\t * If this removed entries from the index,\n@@ -544,7 +544,7 @@ static void verify_absent(const char *path, const char *action,\n \t\t * delete this path, which is in a subdirectory that\n \t\t * is being replaced with a blob.\n \t\t */\n-\t\tcnt = cache_name_pos(path, strlen(path));\n+\t\tcnt = cache_name_pos(ce->name, strlen(ce->name));\n \t\tif (0 <= cnt) {\n \t\t\tstruct cache_entry *ce = active_cache[cnt];\n \t\t\tif (!ce_stage(ce) && !ce->ce_mode)\n@@ -552,7 +552,7 @@ static void verify_absent(const char *path, const char *action,\n \t\t}\n \n \t\tdie(\"Untracked working tree file '%s' \"\n-\t\t    \"would be %s by merge.\", path, action);\n+\t\t    \"would be %s by merge.\", ce->name, action);\n \t}\n }\n \n@@ -576,7 +576,7 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old,\n \t\t}\n \t}\n \telse {\n-\t\tverify_absent(merge->name, \"overwritten\", o);\n+\t\tverify_absent(merge, \"overwritten\", o);\n \t\tinvalidate_ce_path(merge);\n \t}\n \n@@ -591,7 +591,7 @@ static int deleted_entry(struct cache_entry *ce, struct cache_entry *old,\n \tif (old)\n \t\tverify_uptodate(old, o);\n \telse\n-\t\tverify_absent(ce->name, \"removed\", o);\n+\t\tverify_absent(ce, \"removed\", o);\n \tce->ce_mode = 0;\n \tadd_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);\n \tinvalidate_ce_path(ce);\n@@ -708,18 +708,18 @@ int threeway_merge(struct cache_entry **stages,\n \tif (o->aggressive) {\n \t\tint head_deleted = !head && !df_conflict_head;\n \t\tint remote_deleted = !remote && !df_conflict_remote;\n-\t\tconst char *path = NULL;\n+\t\tstruct cache_entry *ce = NULL;\n \n \t\tif (index)\n-\t\t\tpath = index->name;\n+\t\t\tce = index;\n \t\telse if (head)\n-\t\t\tpath = head->name;\n+\t\t\tce = head;\n \t\telse if (remote)\n-\t\t\tpath = remote->name;\n+\t\t\tce = remote;\n \t\telse {\n \t\t\tfor (i = 1; i < o->head_idx; i++) {\n \t\t\t\tif (stages[i] && stages[i] != o->df_conflict_entry) {\n-\t\t\t\t\tpath = stages[i]->name;\n+\t\t\t\t\tce = stages[i];\n \t\t\t\t\tbreak;\n \t\t\t\t}\n \t\t\t}\n@@ -734,8 +734,8 @@ int threeway_merge(struct cache_entry **stages,\n \t\t    (remote_deleted && head && head_match)) {\n \t\t\tif (index)\n \t\t\t\treturn deleted_entry(index, index, o);\n-\t\t\telse if (path && !head_deleted)\n-\t\t\t\tverify_absent(path, \"removed\", o);\n+\t\t\telse if (ce && !head_deleted)\n+\t\t\t\tverify_absent(ce, \"removed\", o);\n \t\t\treturn 0;\n \t\t}\n \t\t/*\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42741","messageId":"11796842893584-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 06/15] git-read-tree: take --submodules option","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:39Z","receivedAt":"2007-05-20T18:04:39Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nThis option currently has no effect.\n\nSigned-off-by: Sven Verdoolaege <skimo@kotnet.org>\n---\n Documentation/config.txt |    4 ++++\n builtin-read-tree.c      |   25 ++++++++++++++++++++++---\n cache.h                  |    3 ++-\n unpack-trees.c           |    1 +\n unpack-trees.h           |    1 +\n 5 files changed, 30 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex ee1c35e..5d891ac 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -256,6 +256,10 @@ You probably do not need to adjust this value.\n +\n Common unit suffixes of 'k', 'm', or 'g' are supported.\n \n+core.submodules\n+\tIf true, gitlink:git-checkout[1] also checks out submodules.\n+\tFalse by default.\n+\n alias.*::\n \tCommand aliases for the gitlink:git[1] command wrapper - e.g.\n \tafter defining \"alias.last = cat-file commit HEAD\", the invocation\ndiff --git a/builtin-read-tree.c b/builtin-read-tree.c\nindex 316fb0f..929dd95 100644\n--- a/builtin-read-tree.c\n+++ b/builtin-read-tree.c\n@@ -87,14 +87,23 @@ static void prime_cache_tree(void)\n static const char read_tree_usage[] = \"git-read-tree (<sha> | [[-m [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <sha1> [<sha2> [<sha3>]])\";\n \n static struct lock_file lock_file;\n+static struct unpack_trees_options opts;\n+\n+static int git_read_tree_config(const char *var, const char *value)\n+{\n+\tif (!strcmp(var, \"core.submodules\")) {\n+\t\topts.submodules = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n+\treturn git_default_config(var, value);\n+}\n \n int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n {\n \tint i, newfd, stage = 0;\n \tunsigned char sha1[20];\n-\tstruct unpack_trees_options opts;\n \n-\tmemset(&opts, 0, sizeof(opts));\n \topts.head_idx = -1;\n \n \tsetup_git_directory();\n@@ -102,7 +111,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \n \tnewfd = hold_locked_index(&lock_file, 1);\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_read_tree_config);\n \n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n@@ -172,6 +181,16 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \t\t\tcontinue;\n \t\t}\n \n+\t\tif (!strcmp(arg, \"--no-submodules\")) {\n+\t\t\topts.submodules = 0;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!strcmp(arg, \"--submodules\")) {\n+\t\t\topts.submodules = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\t/* \"-m\" stands for \"merge\", meaning we start in stage 1 */\n \t\tif (!strcmp(arg, \"-m\")) {\n \t\t\tif (stage || opts.merge || opts.prefix)\ndiff --git a/cache.h b/cache.h\nindex 452aa89..446030a 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -406,7 +406,8 @@ struct checkout {\n \tunsigned force:1,\n \t\t quiet:1,\n \t\t not_new:1,\n-\t\t refresh_cache:1;\n+\t\t refresh_cache:1,\n+\t\t submodules:1;\n };\n \n extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 317f656..4497a46 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -352,6 +352,7 @@ int unpack_trees(struct object_list *trees, struct unpack_trees_options *o)\n \tstate.force = 1;\n \tstate.quiet = 1;\n \tstate.refresh_cache = 1;\n+\tstate.submodules = o->submodules;\n \n \to->merge_size = len;\n \ndiff --git a/unpack-trees.h b/unpack-trees.h\nindex fee7da4..21005d9 100644\n--- a/unpack-trees.h\n+++ b/unpack-trees.h\n@@ -15,6 +15,7 @@ struct unpack_trees_options {\n \tint trivial_merges_only;\n \tint verbose_update;\n \tint aggressive;\n+\tint submodules;\n \tconst char *prefix;\n \tint pos;\n \tstruct dir_struct *dir;\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42748","messageId":"11796842892303-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 07/15] unpack-trees.c: assume submodules are clean","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:40Z","receivedAt":"2007-05-20T18:04:40Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nIf the submodules are not clean, then we will get an error\nwhen we actally do the checkout.\n\nSigned-off-by: Sven Verdoolaege <skimo@kotnet.org>\n---\n unpack-trees.c |   43 ++++++++++++++++++++++++++++++++++---------\n 1 files changed, 34 insertions(+), 9 deletions(-)\n\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 4497a46..f3fe2dd 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -5,6 +5,7 @@\n #include \"cache-tree.h\"\n #include \"unpack-trees.h\"\n #include \"progress.h\"\n+#include \"refs.h\"\n \n #define DBRT_DEBUG 1\n \n@@ -430,11 +431,24 @@ static void invalidate_ce_path(struct cache_entry *ce)\n \t\tcache_tree_invalidate_path(active_cache_tree, ce->name);\n }\n \n-static int verify_clean_subdirectory(const char *path, const char *action,\n+/* Check that checking out ce->sha1 in subdir ce->name is not\n+ * going to overwrite any working files.\n+ *\n+ * FIXME: implement this function, so we can detect problems\n+ *        early, rather than waiting until we actually try to checkout\n+ *        the submodules.\n+ */\n+static int verify_clean_submodule(struct cache_entry *ce, const char *action,\n+\t\t\t\t      struct unpack_trees_options *o)\n+{\n+\treturn 0;\n+}\n+\n+static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,\n \t\t\t\t      struct unpack_trees_options *o)\n {\n \t/*\n-\t * we are about to extract \"path\"; we would not want to lose\n+\t * we are about to extract \"ce->name\"; we would not want to lose\n \t * anything in the existing directory there.\n \t */\n \tint namelen;\n@@ -442,13 +456,24 @@ static int verify_clean_subdirectory(const char *path, const char *action,\n \tstruct dir_struct d;\n \tchar *pathbuf;\n \tint cnt = 0;\n+\tunsigned char sha1[20];\n+\n+\tif (S_ISDIRLNK(ntohl(ce->ce_mode)) &&\n+\t    resolve_gitlink_ref(ce->name, \"HEAD\", sha1) == 0) {\n+\t\t/* If we are not going to update the submodule, then\n+\t\t * we don't care.\n+\t\t */\n+\t\tif (!o->submodules || !hashcmp(sha1, ce->sha1))\n+\t\t\treturn 0;\n+\t\tverify_clean_submodule(ce, action, o);\n+\t}\n \n \t/*\n \t * First let's make sure we do not have a local modification\n \t * in that directory.\n \t */\n-\tnamelen = strlen(path);\n-\tpos = cache_name_pos(path, namelen);\n+\tnamelen = strlen(ce->name);\n+\tpos = cache_name_pos(ce->name, namelen);\n \tif (0 <= pos)\n \t\treturn cnt; /* we have it as nondirectory */\n \tpos = -pos - 1;\n@@ -456,7 +481,7 @@ static int verify_clean_subdirectory(const char *path, const char *action,\n \t\tstruct cache_entry *ce = active_cache[i];\n \t\tint len = ce_namelen(ce);\n \t\tif (len < namelen ||\n-\t\t    strncmp(path, ce->name, namelen) ||\n+\t\t    strncmp(ce->name, ce->name, namelen) ||\n \t\t    ce->name[namelen] != '/')\n \t\t\tbreak;\n \t\t/*\n@@ -474,16 +499,16 @@ static int verify_clean_subdirectory(const char *path, const char *action,\n \t * present file that is not ignored.\n \t */\n \tpathbuf = xmalloc(namelen + 2);\n-\tmemcpy(pathbuf, path, namelen);\n+\tmemcpy(pathbuf, ce->name, namelen);\n \tstrcpy(pathbuf+namelen, \"/\");\n \n \tmemset(&d, 0, sizeof(d));\n \tif (o->dir)\n \t\td.exclude_per_dir = o->dir->exclude_per_dir;\n-\ti = read_directory(&d, path, pathbuf, namelen+1, NULL);\n+\ti = read_directory(&d, ce->name, pathbuf, namelen+1, NULL);\n \tif (i)\n \t\tdie(\"Updating '%s' would lose untracked files in it\",\n-\t\t    path);\n+\t\t    ce->name);\n \tfree(pathbuf);\n \treturn cnt;\n }\n@@ -517,7 +542,7 @@ static void verify_absent(struct cache_entry *ce, const char *action,\n \t\t\t * files that are in \"foo/\" we would lose\n \t\t\t * it.\n \t\t\t */\n-\t\t\tcnt = verify_clean_subdirectory(ce->name, action, o);\n+\t\t\tcnt = verify_clean_subdirectory(ce, action, o);\n \n \t\t\t/*\n \t\t\t * If this removed entries from the index,\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42737","messageId":"1179684289307-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 08/15] Add run_command_v_opt_cd: chdir into a directory before exec","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:41Z","receivedAt":"2007-05-20T18:04:41Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Alex Riesen <raa.lkml@gmail.com>\n\nIt can make code simplier (no need to preserve cwd) and safer\n(no chance the cwd of the current process is accidentally forgotten).\n\nSigned-off-by: Alex Riesen <raa.lkml@gmail.com>\n---\n run-command.c |   27 ++++++++++++++++++++++-----\n run-command.h |    2 ++\n 2 files changed, 24 insertions(+), 5 deletions(-)\n\ndiff --git a/run-command.c b/run-command.c\nindex eff523e..043b570 100644\n--- a/run-command.c\n+++ b/run-command.c\n@@ -73,6 +73,9 @@ int start_command(struct child_process *cmd)\n \t\t\tclose(cmd->out);\n \t\t}\n \n+\t\tif (cmd->dir && chdir(cmd->dir))\n+\t\t\tdie(\"exec %s: cd to %s failed (%s)\", cmd->argv[0],\n+\t\t\t    cmd->dir, strerror(errno));\n \t\tif (cmd->git_cmd) {\n \t\t\texecv_git_cmd(cmd->argv);\n \t\t} else {\n@@ -133,13 +136,27 @@ int run_command(struct child_process *cmd)\n \treturn finish_command(cmd);\n }\n \n+static void prepare_run_command_v_opt(struct child_process *cmd,\n+\t\t\t\t      const char **argv, int opt)\n+{\n+\tmemset(cmd, 0, sizeof(*cmd));\n+\tcmd->argv = argv;\n+\tcmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;\n+\tcmd->git_cmd = opt & RUN_GIT_CMD ? 1 : 0;\n+\tcmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;\n+}\n+\n int run_command_v_opt(const char **argv, int opt)\n {\n \tstruct child_process cmd;\n-\tmemset(&cmd, 0, sizeof(cmd));\n-\tcmd.argv = argv;\n-\tcmd.no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;\n-\tcmd.git_cmd = opt & RUN_GIT_CMD ? 1 : 0;\n-\tcmd.stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;\n+\tprepare_run_command_v_opt(&cmd, argv, opt);\n+\treturn run_command(&cmd);\n+}\n+\n+int run_command_v_opt_cd(const char **argv, int opt, const char *dir)\n+{\n+\tstruct child_process cmd;\n+\tprepare_run_command_v_opt(&cmd, argv, opt);\n+\tcmd.dir = dir;\n \treturn run_command(&cmd);\n }\ndiff --git a/run-command.h b/run-command.h\nindex 3680ef9..cbd7484 100644\n--- a/run-command.h\n+++ b/run-command.h\n@@ -16,6 +16,7 @@ struct child_process {\n \tpid_t pid;\n \tint in;\n \tint out;\n+\tconst char *dir;\n \tunsigned close_in:1;\n \tunsigned close_out:1;\n \tunsigned no_stdin:1;\n@@ -32,5 +33,6 @@ int run_command(struct child_process *);\n #define RUN_GIT_CMD\t     2\t/*If this is to be git sub-command */\n #define RUN_COMMAND_STDOUT_TO_STDERR 4\n int run_command_v_opt(const char **argv, int opt);\n+int run_command_v_opt_cd(const char **argv, int opt, const char *dir);\n \n #endif\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42738","messageId":"11796842892490-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 09/15] entry.c: optionally checkout submodules","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:42Z","receivedAt":"2007-05-20T18:04:42Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nUse run_command_v_opt_cd, as proposed by Alex Riesen.\n\nSigned-off-by: Sven Verdoolaege <skimo@kotnet.org>\n---\n entry.c |   32 ++++++++++++++++++++++++++++++--\n 1 files changed, 30 insertions(+), 2 deletions(-)\n\ndiff --git a/entry.c b/entry.c\nindex 82bf725..8c70a47 100644\n--- a/entry.c\n+++ b/entry.c\n@@ -1,5 +1,6 @@\n #include \"cache.h\"\n #include \"blob.h\"\n+#include \"run-command.h\"\n \n static void create_directories(const char *path, const struct checkout *state)\n {\n@@ -75,6 +76,34 @@ static void *read_blob_entry(struct cache_entry *ce, const char *path, unsigned\n \treturn NULL;\n }\n \n+static int checkout_submodule(struct cache_entry *ce, const char *path, const struct checkout *state)\n+{\n+\tconst char *gitdirenv;\n+\tconst char *args[10];\n+\tint argc;\n+\tint err;\n+\n+\tif (!state->submodules)\n+\t\treturn 0;\n+\n+\targc = 0;\n+\targs[argc++] = \"checkout\";\n+\tif (state->force)\n+\t    args[argc++] = \"-f\";\n+\targs[argc++] = sha1_to_hex(ce->sha1);\n+\targs[argc] = NULL;\n+\n+\tgitdirenv = getenv(GIT_DIR_ENVIRONMENT);\n+\tunsetenv(GIT_DIR_ENVIRONMENT);\n+\terr = run_command_v_opt_cd(args, RUN_GIT_CMD, path);\n+\tsetenv(GIT_DIR_ENVIRONMENT, gitdirenv, 1);\n+\n+\tif (err)\n+\t\treturn error(\"failed to run git-checkout in submodule '%s'\", path);\n+\n+\treturn 0;\n+}\n+\n static int write_entry(struct cache_entry *ce, char *path, const struct checkout *state, int to_tempfile)\n {\n \tint fd;\n@@ -193,9 +222,8 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t\n \t\t */\n \t\tunlink(path);\n \t\tif (S_ISDIR(st.st_mode)) {\n-\t\t\t/* If it is a gitlink, leave it alone! */\n \t\t\tif (S_ISDIRLNK(ntohl(ce->ce_mode)))\n-\t\t\t\treturn 0;\n+\t\t\t\treturn checkout_submodule(ce, path, state);\n \t\t\tif (!state->force)\n \t\t\t\treturn error(\"%s is a directory\", path);\n \t\t\tremove_subtree(path);\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42743","messageId":"11796842892738-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 10/15] git-checkout: pass --submodules option to git-read-tree","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:43Z","receivedAt":"2007-05-20T18:04:43Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nSigned-off-by: Sven Verdoolaege <skimo@kotnet.org>\n---\n git-checkout.sh |   20 +++++++++++++++-----\n 1 files changed, 15 insertions(+), 5 deletions(-)\n\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 6b6facf..162cef4 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -1,6 +1,6 @@\n #!/bin/sh\n \n-USAGE='[-q] [-f] [-b <new_branch>] [-m] [<branch>] [<paths>...]'\n+USAGE='[-q] [-f] [--submodules] [--no-submodules] [-b <new_branch>] [-m] [<branch>] [<paths>...]'\n SUBDIRECTORY_OK=Sometimes\n . git-sh-setup\n require_work_tree\n@@ -16,6 +16,7 @@ track=\n newbranch=\n newbranch_log=\n merge=\n+submodules=\n quiet=\n v=-v\n LF='\n@@ -46,6 +47,15 @@ while [ \"$#\" != \"0\" ]; do\n \t-m)\n \t\tmerge=1\n \t\t;;\n+\t--su|--sub|--subm|--submo|--submod|--submodu|--submodul|\\\n+\t--submodule|--submodules)\n+\t\tsubmodules=\"--submodules\"\n+\t\t;;\n+\t--no-su|--no-sub|--no-subm|--no-submo|--no-submod|\\\n+\t--no-submodu|--no-submodul|\\\n+\t--no-submodule|--no-submodules)\n+\t\tsubmodules=\"--no-submodules\"\n+\t\t;;\n \t\"-q\")\n \t\tquiet=1\n \t\tv=\n@@ -199,10 +209,10 @@ fi\n \n if [ \"$force\" ]\n then\n-    git-read-tree $v --reset -u $new\n+    git-read-tree $v $submodules --reset -u $new\n else\n     git-update-index --refresh >/dev/null\n-    merge_error=$(git-read-tree -m -u --exclude-per-directory=.gitignore $old $new 2>&1) || (\n+    merge_error=$(git-read-tree $submodules -m -u --exclude-per-directory=.gitignore $old $new 2>&1) || (\n \tcase \"$merge\" in\n \t'')\n \t\techo >&2 \"$merge_error\"\n@@ -212,7 +222,7 @@ else\n \t# Match the index to the working tree, and do a three-way.\n     \tgit diff-files --name-only | git update-index --remove --stdin &&\n \twork=`git write-tree` &&\n-\tgit read-tree $v --reset -u $new || exit\n+\tgit read-tree $v $submodules --reset -u $new || exit\n \n \teval GITHEAD_$new='${new_name:-${branch:-$new}}' &&\n \teval GITHEAD_$work=local &&\n@@ -223,7 +233,7 @@ else\n \t# this is not a real merge before committing, but just carrying\n \t# the working tree changes along.\n \tunmerged=`git ls-files -u`\n-\tgit read-tree $v --reset $new\n+\tgit read-tree $v $submodules --reset $new\n \tcase \"$unmerged\" in\n \t'')\t;;\n \t*)\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42749","messageId":"1179684289777-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 11/15] git-read-tree: treat null commit as empty tree","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:44Z","receivedAt":"2007-05-20T18:04:44Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\n---\n builtin-read-tree.c |    9 ++++++---\n unpack-trees.c      |    3 +++\n 2 files changed, 9 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin-read-tree.c b/builtin-read-tree.c\nindex 929dd95..b9fcff7 100644\n--- a/builtin-read-tree.c\n+++ b/builtin-read-tree.c\n@@ -17,9 +17,12 @@ static struct object_list *trees;\n \n static int list_tree(unsigned char *sha1)\n {\n-\tstruct tree *tree = parse_tree_indirect(sha1);\n-\tif (!tree)\n-\t\treturn -1;\n+\tstruct tree *tree = NULL;\n+\tif (!is_null_sha1(sha1)) {\n+\t\ttree = parse_tree_indirect(sha1);\n+\t\tif (!tree)\n+\t\t\treturn -1;\n+\t}\n \tobject_list_append(&tree->object, &trees);\n \treturn 0;\n }\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex f3fe2dd..3dadebb 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -26,6 +26,9 @@ static struct tree_entry_list *create_tree_entry_list(struct tree *tree)\n \tstruct tree_entry_list *ret = NULL;\n \tstruct tree_entry_list **list_p = &ret;\n \n+\tif (!tree)\n+\t\treturn ret;\n+\n \tif (!tree->object.parsed)\n \t\tparse_tree(tree);\n \n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42750","messageId":"11796842893963-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 12/15] git_config: add void * for callback data","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:45Z","receivedAt":"2007-05-20T18:04:45Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\n---\n archive-tar.c            |    6 +++---\n builtin-add.c            |    6 +++---\n builtin-apply.c          |    6 +++---\n builtin-blame.c          |    6 +++---\n builtin-branch.c         |   10 +++++-----\n builtin-cat-file.c       |    2 +-\n builtin-checkout-index.c |    2 +-\n builtin-commit-tree.c    |    2 +-\n builtin-config.c         |   21 +++++++++++----------\n builtin-diff-files.c     |    2 +-\n builtin-diff-index.c     |    2 +-\n builtin-diff-tree.c      |    2 +-\n builtin-diff.c           |    2 +-\n builtin-fmt-merge-msg.c  |    5 +++--\n builtin-gc.c             |    6 +++---\n builtin-init-db.c        |    4 ++--\n builtin-log.c            |   18 +++++++++---------\n builtin-ls-files.c       |    2 +-\n builtin-ls-tree.c        |    2 +-\n builtin-mailinfo.c       |    2 +-\n builtin-merge-base.c     |    2 +-\n builtin-mv.c             |    2 +-\n builtin-name-rev.c       |    2 +-\n builtin-pack-objects.c   |    6 +++---\n builtin-push.c           |    4 ++--\n builtin-read-tree.c      |    9 +++++----\n builtin-reflog.c         |    7 ++++---\n builtin-rerere.c         |    6 +++---\n builtin-rev-list.c       |    2 +-\n builtin-rev-parse.c      |    2 +-\n builtin-revert.c         |    2 +-\n builtin-rm.c             |    2 +-\n builtin-runstatus.c      |    2 +-\n builtin-show-branch.c    |    7 ++++---\n builtin-symbolic-ref.c   |    2 +-\n builtin-unpack-objects.c |    2 +-\n builtin-update-index.c   |    2 +-\n builtin-update-ref.c     |    2 +-\n builtin-verify-pack.c    |    2 +-\n cache.h                  |   13 +++++++------\n config.c                 |   36 ++++++++++++++++++------------------\n connect.c                |    7 ++++---\n convert.c                |    5 +++--\n daemon.c                 |    4 ++--\n diff.c                   |    6 +++---\n diff.h                   |    2 +-\n dump-config.c            |    4 ++--\n fast-import.c            |    2 +-\n fetch-pack.c             |    6 +++---\n git.c                    |    4 ++--\n http-fetch.c             |    2 +-\n http.c                   |    6 +++---\n imap-send.c              |    4 ++--\n local-fetch.c            |    2 +-\n merge-recursive.c        |   10 +++++-----\n receive-pack.c           |    6 +++---\n send-pack.c              |    2 +-\n setup.c                  |    5 +++--\n ssh-fetch.c              |    2 +-\n unpack-file.c            |    2 +-\n var.c                    |    8 ++++----\n wt-status.c              |    4 ++--\n wt-status.h              |    2 +-\n 63 files changed, 163 insertions(+), 154 deletions(-)\n\ndiff --git a/archive-tar.c b/archive-tar.c\nindex 33e7657..595c153 100644\n--- a/archive-tar.c\n+++ b/archive-tar.c\n@@ -242,7 +242,7 @@ static void write_global_extended_header(const unsigned char *sha1)\n \tfree(ext_header.buf);\n }\n \n-static int git_tar_config(const char *var, const char *value)\n+static int git_tar_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcmp(var, \"tar.umask\")) {\n \t\tif (!strcmp(value, \"user\")) {\n@@ -253,7 +253,7 @@ static int git_tar_config(const char *var, const char *value)\n \t\t}\n \t\treturn 0;\n \t}\n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n static int write_tar_entry(const unsigned char *sha1,\n@@ -300,7 +300,7 @@ int write_tar_archive(struct archiver_args *args)\n {\n \tint plen = args->base ? strlen(args->base) : 0;\n \n-\tgit_config(git_tar_config);\n+\tgit_config(git_tar_config, NULL);\n \n \tarchive_time = args->time;\n \tverbose = args->verbose;\ndiff --git a/builtin-add.c b/builtin-add.c\nindex 1591171..1b24c56 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -136,7 +136,7 @@ static void update(int verbose, const char **files)\n \trun_diff_files(&rev, 0);\n }\n \n-static int git_add_config(const char *var, const char *value)\n+static int git_add_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcmp(var, \"core.excludesfile\")) {\n \t\tif (!value)\n@@ -145,7 +145,7 @@ static int git_add_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n static struct lock_file lock_file;\n@@ -175,7 +175,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t\texit(1);\n \t}\n \n-\tgit_config(git_add_config);\n+\tgit_config(git_add_config, NULL);\n \n \tnewfd = hold_locked_index(&lock_file, 1);\n \ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex 0399743..deae199 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -2707,13 +2707,13 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)\n \treturn 0;\n }\n \n-static int git_apply_config(const char *var, const char *value)\n+static int git_apply_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcmp(var, \"apply.whitespace\")) {\n \t\tapply_default_whitespace = xstrdup(value);\n \t\treturn 0;\n \t}\n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n \n@@ -2729,7 +2729,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)\n \n \tprefix = setup_git_directory_gently(&is_not_gitdir);\n \tprefix_length = prefix ? strlen(prefix) : 0;\n-\tgit_config(git_apply_config);\n+\tgit_config(git_apply_config, NULL);\n \tif (apply_default_whitespace)\n \t\tparse_whitespace_option(apply_default_whitespace);\n \ndiff --git a/builtin-blame.c b/builtin-blame.c\nindex 35471fc..0fb76ee 100644\n--- a/builtin-blame.c\n+++ b/builtin-blame.c\n@@ -1973,7 +1973,7 @@ static void prepare_blame_range(struct scoreboard *sb,\n \t\tusage(blame_usage);\n }\n \n-static int git_blame_config(const char *var, const char *value)\n+static int git_blame_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcmp(var, \"blame.showroot\")) {\n \t\tshow_root = git_config_bool(var, value);\n@@ -1983,7 +1983,7 @@ static int git_blame_config(const char *var, const char *value)\n \t\tblank_boundary = git_config_bool(var, value);\n \t\treturn 0;\n \t}\n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n static struct commit *fake_working_tree_commit(const char *path, const char *contents_from)\n@@ -2136,7 +2136,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \n \tcmd_is_annotate = !strcmp(argv[0], \"annotate\");\n \n-\tgit_config(git_blame_config);\n+\tgit_config(git_blame_config, NULL);\n \tsave_commit_buffer = 0;\n \n \topt = 0;\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 6bd5843..a0f4c23 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -55,7 +55,7 @@ static int parse_branch_color_slot(const char *var, int ofs)\n \tdie(\"bad config variable '%s'\", var);\n }\n \n-int git_branch_config(const char *var, const char *value)\n+int git_branch_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcmp(var, \"color.branch\")) {\n \t\tbranch_use_color = git_config_colorbool(var, value);\n@@ -69,7 +69,7 @@ int git_branch_config(const char *var, const char *value)\n \tif (!strcmp(var, \"branch.autosetupmerge\"))\n \t\tbranch_track_remotes = git_config_bool(var, value);\n \n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n const char *branch_get_color(enum color_branch ix)\n@@ -356,7 +356,7 @@ static int get_remote_branch_name(const char *value)\n \treturn 0;\n }\n \n-static int get_remote_config(const char *key, const char *value)\n+static int get_remote_config(const char *key, const char *value, void *cb_data)\n {\n \tconst char *var;\n \tif (prefixcmp(key, \"remote.\"))\n@@ -400,7 +400,7 @@ static void set_branch_defaults(const char *name, const char *real_ref)\n \tstart_ref = real_ref;\n \tstart_len = strlen(real_ref);\n \tbase_len = slash - real_ref;\n-\tgit_config(get_remote_config);\n+\tgit_config(get_remote_config, NULL);\n \tif (!config_repo && !config_remote &&\n \t    !prefixcmp(real_ref, \"refs/heads/\")) {\n \t\tset_branch_merge(name, \".\", real_ref);\n@@ -538,7 +538,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tint kinds = REF_LOCAL_BRANCH;\n \tint i;\n \n-\tgit_config(git_branch_config);\n+\tgit_config(git_branch_config, NULL);\n \ttrack = branch_track_remotes;\n \n \tfor (i = 1; i < argc; i++) {\ndiff --git a/builtin-cat-file.c b/builtin-cat-file.c\nindex f132d58..b488fad 100644\n--- a/builtin-cat-file.c\n+++ b/builtin-cat-file.c\n@@ -85,7 +85,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n \tint opt;\n \tconst char *exp_type, *obj_name;\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \tif (argc != 3)\n \t\tusage(\"git-cat-file [-t|-s|-e|-p|<type>] <sha1>\");\n \texp_type = argv[1];\ndiff --git a/builtin-checkout-index.c b/builtin-checkout-index.c\nindex 8460f97..47a8b1b 100644\n--- a/builtin-checkout-index.c\n+++ b/builtin-checkout-index.c\n@@ -168,7 +168,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)\n \tint read_from_stdin = 0;\n \tint prefix_length;\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \tstate.base_dir = \"\";\n \tprefix_length = prefix ? strlen(prefix) : 0;\n \ndiff --git a/builtin-commit-tree.c b/builtin-commit-tree.c\nindex ccbcbe3..3439321 100644\n--- a/builtin-commit-tree.c\n+++ b/builtin-commit-tree.c\n@@ -92,7 +92,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)\n \tunsigned int size;\n \tint encoding_is_utf8;\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \tif (argc < 2)\n \t\tusage(commit_tree_usage);\ndiff --git a/builtin-config.c b/builtin-config.c\nindex 7e18f73..7834e19 100644\n--- a/builtin-config.c\n+++ b/builtin-config.c\n@@ -16,7 +16,7 @@ static int do_not_match;\n static int seen;\n static enum { T_RAW, T_INT, T_BOOL } type = T_RAW;\n \n-static int show_all_config(const char *key_, const char *value_)\n+static int show_all_config(const char *key_, const char *value_, void *cb_data)\n {\n \tif (value_)\n \t\tprintf(\"%s=%s\\n\", key_, value_);\n@@ -25,7 +25,7 @@ static int show_all_config(const char *key_, const char *value_)\n \treturn 0;\n }\n \n-static int show_config(const char* key_, const char* value_)\n+static int show_config(const char* key_, const char* value_, void *cb_data)\n {\n \tchar value[256];\n \tconst char *vptr = value;\n@@ -107,17 +107,17 @@ static int get_value(const char* key_, const char* regex_)\n \t}\n \n \tif (dest)\n-\t\tgit_config_from_remote(show_config, dest);\n+\t\tgit_config_from_remote(show_config, dest, NULL);\n \telse {\n \t\tif (do_all && system_wide)\n-\t\t\tgit_config_from_file(show_config, system_wide);\n+\t\t\tgit_config_from_file(show_config, system_wide, NULL);\n \t\tif (do_all && global)\n-\t\t\tgit_config_from_file(show_config, global);\n-\t\tgit_config_from_file(show_config, local);\n+\t\t\tgit_config_from_file(show_config, global, NULL);\n+\t\tgit_config_from_file(show_config, local, NULL);\n \t\tif (!do_all && !seen && global)\n-\t\t\tgit_config_from_file(show_config, global);\n+\t\t\tgit_config_from_file(show_config, global, NULL);\n \t\tif (!do_all && !seen && system_wide)\n-\t\t\tgit_config_from_file(show_config, system_wide);\n+\t\t\tgit_config_from_file(show_config, system_wide, NULL);\n \t}\n \n \tfree(key);\n@@ -149,9 +149,10 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\ttype = T_BOOL;\n \t\telse if (!strcmp(argv[1], \"--list\") || !strcmp(argv[1], \"-l\")) {\n \t\t\tif (dest)\n-\t\t\t\treturn git_config_from_remote(show_all_config, dest);\n+\t\t\t\treturn git_config_from_remote(show_all_config,\n+\t\t\t\t\t\t\t\tdest, NULL);\n \t\t\telse\n-\t\t\t\treturn git_config(show_all_config);\n+\t\t\t\treturn git_config(show_all_config, NULL);\n \t\t}\n \t\telse if (!strcmp(argv[1], \"--global\")) {\n \t\t\tchar *home = getenv(\"HOME\");\ndiff --git a/builtin-diff-files.c b/builtin-diff-files.c\nindex 6cb30c8..017f4b9 100644\n--- a/builtin-diff-files.c\n+++ b/builtin-diff-files.c\n@@ -21,7 +21,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)\n \n \tprefix = setup_git_directory_gently(&nongit);\n \tinit_revisions(&rev, prefix);\n-\tgit_config(git_default_config); /* no \"diff\" UI options */\n+\tgit_config(git_default_config, NULL); /* no \"diff\" UI options */\n \trev.abbrev = 0;\n \n \tif (!setup_diff_no_index(&rev, argc, argv, nongit, prefix))\ndiff --git a/builtin-diff-index.c b/builtin-diff-index.c\nindex d90eba9..6e92b78 100644\n--- a/builtin-diff-index.c\n+++ b/builtin-diff-index.c\n@@ -17,7 +17,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)\n \tint result;\n \n \tinit_revisions(&rev, prefix);\n-\tgit_config(git_default_config); /* no \"diff\" UI options */\n+\tgit_config(git_default_config, NULL); /* no \"diff\" UI options */\n \trev.abbrev = 0;\n \n \targc = setup_revisions(argc, argv, &rev, NULL);\ndiff --git a/builtin-diff-tree.c b/builtin-diff-tree.c\nindex 0b591c8..341edad 100644\n--- a/builtin-diff-tree.c\n+++ b/builtin-diff-tree.c\n@@ -68,7 +68,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)\n \tint read_stdin = 0;\n \n \tinit_revisions(opt, prefix);\n-\tgit_config(git_default_config); /* no \"diff\" UI options */\n+\tgit_config(git_default_config, NULL); /* no \"diff\" UI options */\n \tnr_sha1 = 0;\n \topt->abbrev = 0;\n \topt->diff = 1;\ndiff --git a/builtin-diff.c b/builtin-diff.c\nindex 7f367b6..906b698 100644\n--- a/builtin-diff.c\n+++ b/builtin-diff.c\n@@ -220,7 +220,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n \t */\n \n \tprefix = setup_git_directory_gently(&nongit);\n-\tgit_config(git_diff_ui_config);\n+\tgit_config(git_diff_ui_config, NULL);\n \tinit_revisions(&rev, prefix);\n \n \tif (!setup_diff_no_index(&rev, argc, argv, nongit, prefix))\ndiff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c\nindex 5c145d2..a156548 100644\n--- a/builtin-fmt-merge-msg.c\n+++ b/builtin-fmt-merge-msg.c\n@@ -10,7 +10,8 @@ static const char *fmt_merge_msg_usage =\n \n static int merge_summary;\n \n-static int fmt_merge_msg_config(const char *key, const char *value)\n+static int fmt_merge_msg_config(const char *key, const char *value,\n+\t\t\t\tvoid *cb_data)\n {\n \tif (!strcmp(\"merge.summary\", key))\n \t\tmerge_summary = git_config_bool(key, value);\n@@ -251,7 +252,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)\n \tunsigned char head_sha1[20];\n \tconst char *current_branch;\n \n-\tgit_config(fmt_merge_msg_config);\n+\tgit_config(fmt_merge_msg_config, NULL);\n \n \twhile (argc > 1) {\n \t\tif (!strcmp(argv[1], \"--summary\"))\ndiff --git a/builtin-gc.c b/builtin-gc.c\nindex 8ea165a..164fe71 100644\n--- a/builtin-gc.c\n+++ b/builtin-gc.c\n@@ -27,7 +27,7 @@ static const char *argv_repack[MAX_ADD] = {\"repack\", \"-a\", \"-d\", \"-l\", NULL};\n static const char *argv_prune[] = {\"prune\", NULL};\n static const char *argv_rerere[] = {\"rerere\", \"gc\", NULL};\n \n-static int gc_config(const char *var, const char *value)\n+static int gc_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcmp(var, \"gc.packrefs\")) {\n \t\tif (!strcmp(value, \"notbare\"))\n@@ -40,7 +40,7 @@ static int gc_config(const char *var, const char *value)\n \t\taggressive_window = git_config_int(var, value);\n \t\treturn 0;\n \t}\n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n static void append_option(const char **cmd, const char *opt, int max_length)\n@@ -62,7 +62,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)\n \tint prune = 0;\n \tchar buf[80];\n \n-\tgit_config(gc_config);\n+\tgit_config(gc_config, NULL);\n \n \tif (pack_refs < 0)\n \t\tpack_refs = !is_bare_repository();\ndiff --git a/builtin-init-db.c b/builtin-init-db.c\nindex 4df9fd0..11460b6 100644\n--- a/builtin-init-db.c\n+++ b/builtin-init-db.c\n@@ -152,7 +152,7 @@ static void copy_templates(const char *git_dir, int len, const char *template_di\n \tstrcpy(template_path + template_len, \"config\");\n \trepository_format_version = 0;\n \tgit_config_from_file(check_repository_format_version,\n-\t\t\t     template_path);\n+\t\t\t     template_path, NULL);\n \ttemplate_path[template_len] = 0;\n \n \tif (repository_format_version &&\n@@ -207,7 +207,7 @@ static int create_default_files(const char *git_dir, const char *template_path)\n \tpath[len] = 0;\n \tcopy_templates(path, len, template_path);\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \t/*\n \t * We would have created the above under user's umask -- under\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 3744712..2581ce4 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -93,20 +93,20 @@ static int cmd_log_walk(struct rev_info *rev)\n \treturn 0;\n }\n \n-static int git_log_config(const char *var, const char *value)\n+static int git_log_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcmp(var, \"log.showroot\")) {\n \t\tdefault_show_root = git_config_bool(var, value);\n \t\treturn 0;\n \t}\n-\treturn git_diff_ui_config(var, value);\n+\treturn git_diff_ui_config(var, value, NULL);\n }\n \n int cmd_whatchanged(int argc, const char **argv, const char *prefix)\n {\n \tstruct rev_info rev;\n \n-\tgit_config(git_log_config);\n+\tgit_config(git_log_config, NULL);\n \tinit_revisions(&rev, prefix);\n \trev.diff = 1;\n \trev.diffopt.recursive = 1;\n@@ -155,7 +155,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)\n \tstruct object_array_entry *objects;\n \tint i, count, ret = 0;\n \n-\tgit_config(git_log_config);\n+\tgit_config(git_log_config, NULL);\n \tinit_revisions(&rev, prefix);\n \trev.diff = 1;\n \trev.diffopt.recursive = 1;\n@@ -220,7 +220,7 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix)\n {\n \tstruct rev_info rev;\n \n-\tgit_config(git_log_config);\n+\tgit_config(git_log_config, NULL);\n \tinit_revisions(&rev, prefix);\n \tinit_reflog_walk(&rev.reflog_info);\n \trev.abbrev_commit = 1;\n@@ -248,7 +248,7 @@ int cmd_log(int argc, const char **argv, const char *prefix)\n {\n \tstruct rev_info rev;\n \n-\tgit_config(git_log_config);\n+\tgit_config(git_log_config, NULL);\n \tinit_revisions(&rev, prefix);\n \trev.always_show_header = 1;\n \tcmd_log_init(argc, argv, prefix, &rev);\n@@ -268,7 +268,7 @@ static char *extra_headers = NULL;\n static int extra_headers_size = 0;\n static const char *fmt_patch_suffix = \".patch\";\n \n-static int git_format_config(const char *var, const char *value)\n+static int git_format_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcmp(var, \"format.headers\")) {\n \t\tint len;\n@@ -291,7 +291,7 @@ static int git_format_config(const char *var, const char *value)\n \tif (!strcmp(var, \"diff.color\") || !strcmp(var, \"color.diff\")) {\n \t\treturn 0;\n \t}\n-\treturn git_log_config(var, value);\n+\treturn git_log_config(var, value, NULL);\n }\n \n \n@@ -440,7 +440,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \tchar message_id[1024];\n \tchar ref_message_id[1024];\n \n-\tgit_config(git_format_config);\n+\tgit_config(git_format_config, NULL);\n \tinit_revisions(&rev, prefix);\n \trev.commit_format = CMIT_FMT_EMAIL;\n \trev.verbose_header = 1;\ndiff --git a/builtin-ls-files.c b/builtin-ls-files.c\nindex f7c066b..9bdadc4 100644\n--- a/builtin-ls-files.c\n+++ b/builtin-ls-files.c\n@@ -347,7 +347,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)\n \tmemset(&dir, 0, sizeof(dir));\n \tif (prefix)\n \t\tprefix_offset = strlen(prefix);\n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\ndiff --git a/builtin-ls-tree.c b/builtin-ls-tree.c\nindex 1cb4dca..104e98f 100644\n--- a/builtin-ls-tree.c\n+++ b/builtin-ls-tree.c\n@@ -108,7 +108,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)\n \tunsigned char sha1[20];\n \tstruct tree *tree;\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \tls_tree_prefix = prefix;\n \tif (prefix && *prefix)\n \t\tchomp_prefix = strlen(prefix);\ndiff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\nindex c95e477..82f7a6e 100644\n--- a/builtin-mailinfo.c\n+++ b/builtin-mailinfo.c\n@@ -894,7 +894,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)\n \t/* NEEDSWORK: might want to do the optional .git/ directory\n \t * discovery\n \t */\n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \tdef_charset = (git_commit_encoding ? git_commit_encoding : \"utf-8\");\n \tmetainfo_charset = def_charset;\ndiff --git a/builtin-merge-base.c b/builtin-merge-base.c\nindex e35d362..9f766c5 100644\n--- a/builtin-merge-base.c\n+++ b/builtin-merge-base.c\n@@ -27,7 +27,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)\n \tunsigned char rev1key[20], rev2key[20];\n \tint show_all = 0;\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \twhile (1 < argc && argv[1][0] == '-') {\n \t\tconst char *arg = argv[1];\ndiff --git a/builtin-mv.c b/builtin-mv.c\nindex 3563216..7d01203 100644\n--- a/builtin-mv.c\n+++ b/builtin-mv.c\n@@ -75,7 +75,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \tstruct path_list deleted = {NULL, 0, 0, 0};\n \tstruct path_list changed = {NULL, 0, 0, 0};\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \tnewfd = hold_locked_index(&lock_file, 1);\n \tif (read_cache() < 0)\ndiff --git a/builtin-name-rev.c b/builtin-name-rev.c\nindex ef16385..988426c 100644\n--- a/builtin-name-rev.c\n+++ b/builtin-name-rev.c\n@@ -151,7 +151,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)\n \tint as_is = 0, all = 0, transform_stdin = 0;\n \tstruct name_ref_data data = { 0, NULL };\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \tif (argc < 2)\n \t\tusage(name_rev_usage);\ndiff --git a/builtin-pack-objects.c b/builtin-pack-objects.c\nindex d165f10..e6ce67a 100644\n--- a/builtin-pack-objects.c\n+++ b/builtin-pack-objects.c\n@@ -1419,7 +1419,7 @@ static void prepare_pack(int window, int depth)\n \tfree(delta_list);\n }\n \n-static int git_pack_config(const char *k, const char *v)\n+static int git_pack_config(const char *k, const char *v, void *cb_data)\n {\n \tif(!strcmp(k, \"pack.window\")) {\n \t\twindow = git_config_int(k, v);\n@@ -1439,7 +1439,7 @@ static int git_pack_config(const char *k, const char *v)\n \t\tpack_compression_seen = 1;\n \t\treturn 0;\n \t}\n-\treturn git_default_config(k, v);\n+\treturn git_default_config(k, v, NULL);\n }\n \n static void read_object_list_from_stdin(void)\n@@ -1549,7 +1549,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)\n \trp_av[1] = \"--objects\"; /* --thin will make it --objects-edge */\n \trp_ac = 2;\n \n-\tgit_config(git_pack_config);\n+\tgit_config(git_pack_config, NULL);\n \tif (!pack_compression_seen && core_compression_seen)\n \t\tpack_compression_level = core_compression_level;\n \ndiff --git a/builtin-push.c b/builtin-push.c\nindex cb78401..a19be32 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -193,7 +193,7 @@ static int config_current_uri;\n static int config_get_refspecs;\n static int config_get_receivepack;\n \n-static int get_remote_config(const char* key, const char* value)\n+static int get_remote_config(const char* key, const char* value, void *cb_data)\n {\n \tif (!prefixcmp(key, \"remote.\") &&\n \t    !strncmp(key + 7, config_repo, config_repo_len)) {\n@@ -230,7 +230,7 @@ static int get_config_remotes_uri(const char *repo, const char *uri[MAX_URI])\n \tconfig_get_refspecs = !(refspec_nr || all || tags);\n \tconfig_get_receivepack = (receivepack == NULL);\n \n-\tgit_config(get_remote_config);\n+\tgit_config(get_remote_config, NULL);\n \treturn config_current_uri;\n }\n \ndiff --git a/builtin-read-tree.c b/builtin-read-tree.c\nindex b9fcff7..cec2021 100644\n--- a/builtin-read-tree.c\n+++ b/builtin-read-tree.c\n@@ -92,14 +92,15 @@ static const char read_tree_usage[] = \"git-read-tree (<sha> | [[-m [--aggressive\n static struct lock_file lock_file;\n static struct unpack_trees_options opts;\n \n-static int git_read_tree_config(const char *var, const char *value)\n+static int git_read_tree_config(const char *var, const char *value,\n+\t\t\t\tvoid *cb_data)\n {\n \tif (!strcmp(var, \"core.submodules\")) {\n \t\topts.submodules = git_config_bool(var, value);\n \t\treturn 0;\n \t}\n \n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n@@ -110,11 +111,11 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \topts.head_idx = -1;\n \n \tsetup_git_directory();\n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \tnewfd = hold_locked_index(&lock_file, 1);\n \n-\tgit_config(git_read_tree_config);\n+\tgit_config(git_read_tree_config, NULL);\n \n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\ndiff --git a/builtin-reflog.c b/builtin-reflog.c\nindex ce093ca..c616a0a 100644\n--- a/builtin-reflog.c\n+++ b/builtin-reflog.c\n@@ -281,14 +281,15 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,\n \treturn status;\n }\n \n-static int reflog_expire_config(const char *var, const char *value)\n+static int reflog_expire_config(const char *var, const char *value,\n+\t\t\t\tvoid *cb_data)\n {\n \tif (!strcmp(var, \"gc.reflogexpire\"))\n \t\tdefault_reflog_expire = approxidate(value);\n \telse if (!strcmp(var, \"gc.reflogexpireunreachable\"))\n \t\tdefault_reflog_expire_unreachable = approxidate(value);\n \telse\n-\t\treturn git_default_config(var, value);\n+\t\treturn git_default_config(var, value, NULL);\n \treturn 0;\n }\n \n@@ -298,7 +299,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \tunsigned long now = time(NULL);\n \tint i, status, do_all;\n \n-\tgit_config(reflog_expire_config);\n+\tgit_config(reflog_expire_config, NULL);\n \n \tsave_commit_buffer = 0;\n \tdo_all = status = 0;\ndiff --git a/builtin-rerere.c b/builtin-rerere.c\nindex 8c2c8bd..5d1fe12 100644\n--- a/builtin-rerere.c\n+++ b/builtin-rerere.c\n@@ -380,14 +380,14 @@ tail_optimization:\n \treturn write_rr(rr, fd);\n }\n \n-static int git_rerere_config(const char *var, const char *value)\n+static int git_rerere_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcmp(var, \"gc.rerereresolved\"))\n \t\tcutoff_resolve = git_config_int(var, value);\n \telse if (!strcmp(var, \"gc.rerereunresolved\"))\n \t\tcutoff_noresolve = git_config_int(var, value);\n \telse\n-\t\treturn git_default_config(var, value);\n+\t\treturn git_default_config(var, value, NULL);\n \treturn 0;\n }\n \n@@ -400,7 +400,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)\n \tif (stat(git_path(\"rr-cache\"), &st) || !S_ISDIR(st.st_mode))\n \t\treturn 0;\n \n-\tgit_config(git_rerere_config);\n+\tgit_config(git_rerere_config, NULL);\n \n \tmerge_rr_path = xstrdup(git_path(\"rr-cache/MERGE_RR\"));\n \tfd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1);\ndiff --git a/builtin-rev-list.c b/builtin-rev-list.c\nindex ebf53f5..8700d37 100644\n--- a/builtin-rev-list.c\n+++ b/builtin-rev-list.c\n@@ -468,7 +468,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \tint read_from_stdin = 0;\n \tint bisect_show_vars = 0;\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \tinit_revisions(&revs, prefix);\n \trevs.abbrev = 0;\n \trevs.commit_format = CMIT_FMT_UNSPECIFIED;\ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex 37addb2..8e868c3 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -214,7 +214,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \tint i, as_is = 0, verify = 0;\n \tunsigned char sha1[20];\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\ndiff --git a/builtin-revert.c b/builtin-revert.c\nindex ea2f15b..aa26c27 100644\n--- a/builtin-revert.c\n+++ b/builtin-revert.c\n@@ -239,7 +239,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)\n \tconst char *message, *encoding;\n \tconst char *defmsg = xstrdup(git_path(\"MERGE_MSG\"));\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \tme = action == REVERT ? \"revert\" : \"cherry-pick\";\n \tsetenv(GIT_REFLOG_ACTION, me, 0);\n \tparse_options(argc, argv);\ndiff --git a/builtin-rm.c b/builtin-rm.c\nindex 4a0bd93..7f03735 100644\n--- a/builtin-rm.c\n+++ b/builtin-rm.c\n@@ -109,7 +109,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)\n \tconst char **pathspec;\n \tchar *seen;\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \tnewfd = hold_locked_index(&lock_file, 1);\n \ndiff --git a/builtin-runstatus.c b/builtin-runstatus.c\nindex 4b489b1..d365d7d 100644\n--- a/builtin-runstatus.c\n+++ b/builtin-runstatus.c\n@@ -11,7 +11,7 @@ int cmd_runstatus(int argc, const char **argv, const char *prefix)\n \tstruct wt_status s;\n \tint i;\n \n-\tgit_config(git_status_config);\n+\tgit_config(git_status_config, NULL);\n \twt_status_prepare(&s);\n \n \tfor (i = 1; i < argc; i++) {\ndiff --git a/builtin-show-branch.c b/builtin-show-branch.c\nindex c892f1f..73565c8 100644\n--- a/builtin-show-branch.c\n+++ b/builtin-show-branch.c\n@@ -531,7 +531,8 @@ static void append_one_rev(const char *av)\n \tdie(\"bad sha1 reference %s\", av);\n }\n \n-static int git_show_branch_config(const char *var, const char *value)\n+static int git_show_branch_config(const char *var, const char *value,\n+\t\t\t\t  void *cb_data)\n {\n \tif (!strcmp(var, \"showbranch.default\")) {\n \t\tif (default_alloc <= default_num + 1) {\n@@ -543,7 +544,7 @@ static int git_show_branch_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n static int omit_in_dense(struct commit *commit, struct commit **rev, int n)\n@@ -607,7 +608,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)\n \tint reflog = 0;\n \tconst char *reflog_base = NULL;\n \n-\tgit_config(git_show_branch_config);\n+\tgit_config(git_show_branch_config, NULL);\n \n \t/* If nothing is specified, try the default first */\n \tif (ac == 1 && default_num) {\ndiff --git a/builtin-symbolic-ref.c b/builtin-symbolic-ref.c\nindex d41b406..114c473 100644\n--- a/builtin-symbolic-ref.c\n+++ b/builtin-symbolic-ref.c\n@@ -27,7 +27,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)\n \tint quiet = 0;\n \tconst char *msg = NULL;\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \twhile (1 < argc) {\n \t\tconst char *arg = argv[1];\ndiff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c\nindex a6ff62f..73dd79f 100644\n--- a/builtin-unpack-objects.c\n+++ b/builtin-unpack-objects.c\n@@ -341,7 +341,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)\n \tint i;\n \tunsigned char sha1[20];\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \tquiet = !isatty(2);\n \ndiff --git a/builtin-update-index.c b/builtin-update-index.c\nindex 8f98991..023c2dc 100644\n--- a/builtin-update-index.c\n+++ b/builtin-update-index.c\n@@ -570,7 +570,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \tint lock_error = 0;\n \tstruct lock_file *lock_file;\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \t/* We can't free this memory, it becomes part of a linked list parsed atexit() */\n \tlock_file = xcalloc(1, sizeof(struct lock_file));\ndiff --git a/builtin-update-ref.c b/builtin-update-ref.c\nindex feac2ed..782d4aa 100644\n--- a/builtin-update-ref.c\n+++ b/builtin-update-ref.c\n@@ -14,7 +14,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)\n \n \tdelete = 0;\n \tref_flags = 0;\n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \tfor (i = 1; i < argc; i++) {\n \t\tif (!strcmp(\"-m\", argv[i])) {\ndiff --git a/builtin-verify-pack.c b/builtin-verify-pack.c\nindex 4e31c27..8a59d14 100644\n--- a/builtin-verify-pack.c\n+++ b/builtin-verify-pack.c\n@@ -55,7 +55,7 @@ int cmd_verify_pack(int argc, const char **argv, const char *prefix)\n \tint no_more_options = 0;\n \tint nothing_done = 1;\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \twhile (1 < argc) {\n \t\tif (!no_more_options && argv[1][0] == '-') {\n \t\t\tif (!strcmp(\"-v\", argv[1]))\ndiff --git a/cache.h b/cache.h\nindex 446030a..d56db20 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -499,17 +499,18 @@ extern const char *packed_object_info_detail(struct packed_git *, off_t, unsigne\n /* Dumb servers support */\n extern int update_server_info(int);\n \n-typedef int (*config_fn_t)(const char *, const char *);\n-extern int git_default_config(const char *, const char *);\n-extern int git_config_from_file(config_fn_t fn, const char *);\n-extern int git_config_from_remote(config_fn_t fn, char *dest);\n-extern int git_config(config_fn_t fn);\n+typedef int (*config_fn_t)(const char *, const char *, void *cb_data);\n+extern int git_default_config(const char *, const char *, void *cb_data);\n+extern int git_config_from_file(config_fn_t fn, const char *, void *cb_data);\n+extern int git_config_from_remote(config_fn_t fn, char *dest, void *cb_data);\n+extern int git_config(config_fn_t fn, void *cb_data);\n extern int git_config_int(const char *, const char *);\n extern int git_config_bool(const char *, const char *);\n extern int git_config_set(const char *, const char *);\n extern int git_config_set_multivar(const char *, const char *, const char *, int);\n extern int git_config_rename_section(const char *, const char *);\n-extern int check_repository_format_version(const char *var, const char *value);\n+extern int check_repository_format_version(const char *var, const char *value,\n+\t\t\t\t\t   void *cb_data);\n \n #define MAX_GITNAME (1000)\n extern char git_default_email[MAX_GITNAME];\ndiff --git a/config.c b/config.c\nindex fc2162b..cab6f29 100644\n--- a/config.c\n+++ b/config.c\n@@ -113,7 +113,7 @@ static inline int iskeychar(int c)\n \treturn isalnum(c) || c == '-';\n }\n \n-static int get_value(config_fn_t fn, char *name, unsigned int len)\n+static int get_value(config_fn_t fn, char *name, unsigned int len, void *cb_data)\n {\n \tint c;\n \tchar *value;\n@@ -141,7 +141,7 @@ static int get_value(config_fn_t fn, char *name, unsigned int len)\n \t\tif (!value)\n \t\t\treturn -1;\n \t}\n-\treturn fn(name, value);\n+\treturn fn(name, value, cb_data);\n }\n \n static int get_extended_base_var(char *name, int baselen, int c)\n@@ -199,7 +199,7 @@ static int get_base_var(char *name)\n \t}\n }\n \n-static int git_parse_file(config_fn_t fn)\n+static int git_parse_file(config_fn_t fn, void *cb_data)\n {\n \tint comment = 0;\n \tint baselen = 0;\n@@ -231,7 +231,7 @@ static int git_parse_file(config_fn_t fn)\n \t\tif (!isalpha(c))\n \t\t\tbreak;\n \t\tvar[baselen] = tolower(c);\n-\t\tif (get_value(fn, var, baselen+1) < 0)\n+\t\tif (get_value(fn, var, baselen+1, cb_data) < 0)\n \t\t\tbreak;\n \t}\n \tdie(\"bad config file line %d in %s\", config_linenr, config_file_name);\n@@ -267,7 +267,7 @@ int git_config_bool(const char *name, const char *value)\n \treturn git_config_int(name, value) != 0;\n }\n \n-int git_default_config(const char *var, const char *value)\n+int git_default_config(const char *var, const char *value, void *cb_data)\n {\n \t/* This needs a better name */\n \tif (!strcmp(var, \"core.filemode\")) {\n@@ -390,7 +390,7 @@ int git_default_config(const char *var, const char *value)\n \treturn 0;\n }\n \n-int git_config_from_file(config_fn_t fn, const char *filename)\n+int git_config_from_file(config_fn_t fn, const char *filename, void *cb_data)\n {\n \tint ret;\n \tFILE *f = fopen(filename, \"r\");\n@@ -400,24 +400,24 @@ int git_config_from_file(config_fn_t fn, const char *filename)\n \t\tconfig_file = f;\n \t\tconfig_file_name = filename;\n \t\tconfig_linenr = 1;\n-\t\tret = git_parse_file(fn);\n+\t\tret = git_parse_file(fn, cb_data);\n \t\tfclose(f);\n \t\tconfig_file_name = NULL;\n \t}\n \treturn ret;\n }\n \n-static int config_from_http(config_fn_t fn, char *dest)\n+static int config_from_http(config_fn_t fn, char *dest, void *cb_data)\n {\n \tchar config_temp[50];\n \tif (git_http_fetch_config(dest, config_temp, sizeof(config_temp)))\n \t\treturn 1;\n-\tgit_config_from_file(fn, config_temp);\n+\tgit_config_from_file(fn, config_temp, cb_data);\n \tunlink(config_temp);\n \treturn 0;\n }\n \n-int git_config_from_remote(config_fn_t fn, char *dest)\n+int git_config_from_remote(config_fn_t fn, char *dest, void *cb_data)\n {\n \tint ret;\n \tint fd[2];\n@@ -426,7 +426,7 @@ int git_config_from_remote(config_fn_t fn, char *dest)\n \tstatic char value[1024];\n \n \tif (!prefixcmp(dest, \"http://\"))\n-\t\treturn config_from_http(fn, dest);\n+\t\treturn config_from_http(fn, dest, cb_data);\n \n \tpid = git_connect(fd, dest, dumpconfig, 0);\n \tif (pid < 0)\n@@ -435,7 +435,7 @@ int git_config_from_remote(config_fn_t fn, char *dest)\n \twhile (packet_read_line(fd[0], var, sizeof(var))) {\n \t\tif (!packet_read_line(fd[0], value, sizeof(value)))\n \t\t\tdie(\"Missing value\");\n-\t\tfn(var, value);\n+\t\tfn(var, value, cb_data);\n \t}\n \tclose(fd[0]);\n \tclose(fd[1]);\n@@ -443,7 +443,7 @@ int git_config_from_remote(config_fn_t fn, char *dest)\n \treturn !!ret;\n }\n \n-int git_config(config_fn_t fn)\n+int git_config(config_fn_t fn, void *cb_data)\n {\n \tint ret = 0;\n \tchar *repo_config = NULL;\n@@ -456,7 +456,7 @@ int git_config(config_fn_t fn)\n \tfilename = getenv(CONFIG_ENVIRONMENT);\n \tif (!filename) {\n \t\tif (!access(ETC_GITCONFIG, R_OK))\n-\t\t\tret += git_config_from_file(fn, ETC_GITCONFIG);\n+\t\t\tret += git_config_from_file(fn, ETC_GITCONFIG, cb_data);\n \t\thome = getenv(\"HOME\");\n \t\tfilename = getenv(CONFIG_LOCAL_ENVIRONMENT);\n \t\tif (!filename)\n@@ -466,11 +466,11 @@ int git_config(config_fn_t fn)\n \tif (home) {\n \t\tchar *user_config = xstrdup(mkpath(\"%s/.gitconfig\", home));\n \t\tif (!access(user_config, R_OK))\n-\t\t\tret = git_config_from_file(fn, user_config);\n+\t\t\tret = git_config_from_file(fn, user_config, cb_data);\n \t\tfree(user_config);\n \t}\n \n-\tret += git_config_from_file(fn, filename);\n+\tret += git_config_from_file(fn, filename, cb_data);\n \tfree(repo_config);\n \treturn ret;\n }\n@@ -500,7 +500,7 @@ static int matches(const char* key, const char* value)\n \t\t  !regexec(store.value_regex, value, 0, NULL, 0)));\n }\n \n-static int store_aux(const char* key, const char* value)\n+static int store_aux(const char* key, const char* value, void *cb_data)\n {\n \tconst char *ep;\n \tsize_t section_len;\n@@ -836,7 +836,7 @@ int git_config_set_multivar(const char* key, const char* value,\n \t\t * As a side effect, we make sure to transform only a valid\n \t\t * existing config file.\n \t\t */\n-\t\tif (git_config_from_file(store_aux, config_filename)) {\n+\t\tif (git_config_from_file(store_aux, config_filename, NULL)) {\n \t\t\tfprintf(stderr, \"invalid config file\\n\");\n \t\t\tfree(store.key);\n \t\t\tif (store.value_regex != NULL) {\ndiff --git a/connect.c b/connect.c\nindex 2a26fdb..08cfac0 100644\n--- a/connect.c\n+++ b/connect.c\n@@ -558,7 +558,8 @@ static char *git_proxy_command;\n static const char *rhost_name;\n static int rhost_len;\n \n-static int git_proxy_command_options(const char *var, const char *value)\n+static int git_proxy_command_options(const char *var, const char *value,\n+\t\t\t\t     void *cb_data)\n {\n \tif (!strcmp(var, \"core.gitproxy\")) {\n \t\tconst char *for_pos;\n@@ -602,7 +603,7 @@ static int git_proxy_command_options(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n static int git_use_proxy(const char *host)\n@@ -610,7 +611,7 @@ static int git_use_proxy(const char *host)\n \trhost_name = host;\n \trhost_len = strlen(host);\n \tgit_proxy_command = getenv(\"GIT_PROXY_COMMAND\");\n-\tgit_config(git_proxy_command_options);\n+\tgit_config(git_proxy_command_options, NULL);\n \trhost_name = NULL;\n \treturn (git_proxy_command && *git_proxy_command);\n }\ndiff --git a/convert.c b/convert.c\nindex 4b26b1a..6dde5fa 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -335,7 +335,8 @@ static struct convert_driver {\n \tchar *clean;\n } *user_convert, **user_convert_tail;\n \n-static int read_convert_config(const char *var, const char *value)\n+static int read_convert_config(const char *var, const char *value,\n+\t\t\t\tvoid *cb_data)\n {\n \tconst char *ep, *name;\n \tint namelen;\n@@ -402,7 +403,7 @@ static void setup_convert_check(struct git_attr_check *check)\n \t\tattr_ident = git_attr(\"ident\", 5);\n \t\tattr_filter = git_attr(\"filter\", 6);\n \t\tuser_convert_tail = &user_convert;\n-\t\tgit_config(read_convert_config);\n+\t\tgit_config(read_convert_config, NULL);\n \t}\n \tcheck[0].attr = attr_crlf;\n \tcheck[1].attr = attr_ident;\ndiff --git a/daemon.c b/daemon.c\nindex 3e5ebf3..2d6302f 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -284,7 +284,7 @@ struct daemon_service {\n static struct daemon_service *service_looking_at;\n static int service_enabled;\n \n-static int git_daemon_config(const char *var, const char *value)\n+static int git_daemon_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!prefixcmp(var, \"daemon.\") &&\n \t    !strcmp(var + 7, service_looking_at->config_name)) {\n@@ -334,7 +334,7 @@ static int run_service(struct interp *itable, struct daemon_service *service)\n \tif (service->overridable) {\n \t\tservice_looking_at = service;\n \t\tservice_enabled = -1;\n-\t\tgit_config(git_daemon_config);\n+\t\tgit_config(git_daemon_config, NULL);\n \t\tif (0 <= service_enabled)\n \t\t\tenabled = service_enabled;\n \t}\ndiff --git a/diff.c b/diff.c\nindex 33297aa..8edfcc5 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -99,7 +99,7 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val\n  * never be affected by the setting of diff.renames\n  * the user happens to have in the configuration file.\n  */\n-int git_diff_ui_config(const char *var, const char *value)\n+int git_diff_ui_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcmp(var, \"diff.renamelimit\")) {\n \t\tdiff_rename_limit_default = git_config_int(var, value);\n@@ -131,7 +131,7 @@ int git_diff_ui_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n static char *quote_one(const char *str)\n@@ -1762,7 +1762,7 @@ static const char *external_diff_attr(const char *name)\n \n \t\t\tif (!user_diff_tail) {\n \t\t\t\tuser_diff_tail = &user_diff;\n-\t\t\t\tgit_config(git_diff_ui_config);\n+\t\t\t\tgit_config(git_diff_ui_config, NULL);\n \t\t\t}\n \t\t\tfor (drv = user_diff; drv; drv = drv->next)\n \t\t\t\tif (!strcmp(drv->name, value))\ndiff --git a/diff.h b/diff.h\nindex 63738c1..a715dff 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -161,7 +161,7 @@ extern int diff_scoreopt_parse(const char *opt);\n #define DIFF_SETUP_USE_CACHE\t\t2\n #define DIFF_SETUP_USE_SIZE_CACHE\t4\n \n-extern int git_diff_ui_config(const char *var, const char *value);\n+extern int git_diff_ui_config(const char *var, const char *value, void *cb_data);\n extern void diff_setup(struct diff_options *);\n extern int diff_opt_parse(struct diff_options *, const char **, int);\n extern int diff_setup_done(struct diff_options *);\ndiff --git a/dump-config.c b/dump-config.c\nindex 355920d..99dbeb6 100644\n--- a/dump-config.c\n+++ b/dump-config.c\n@@ -4,7 +4,7 @@\n \n static const char dump_config_usage[] = \"git-dump-config <dir>\";\n \n-static int dump_config(const char *var, const char *value)\n+static int dump_config(const char *var, const char *value, void *cb_data)\n {\n \tpacket_write(1, \"%s\", var);\n \tpacket_write(1, \"%s\", value);\n@@ -22,7 +22,7 @@ int main(int argc, char **argv)\n \tif (!enter_repo(dir, 0))\n \t\tdie(\"'%s': unable to chdir or not a git archive\", dir);\n \n-\tgit_config(dump_config);\n+\tgit_config(dump_config, NULL);\n \tpacket_flush(1);\n \n \treturn 0;\ndiff --git a/fast-import.c b/fast-import.c\nindex ffa00fd..599d045 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -2009,7 +2009,7 @@ int main(int argc, const char **argv)\n {\n \tint i, show_stats = 1;\n \n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \talloc_objects(object_entry_alloc);\n \tstrbuf_init(&command_buf);\n \tatom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*));\ndiff --git a/fetch-pack.c b/fetch-pack.c\nindex aa59043..c7d24fe 100644\n--- a/fetch-pack.c\n+++ b/fetch-pack.c\n@@ -646,7 +646,7 @@ static int remove_duplicates(int nr_heads, char **heads)\n \treturn dst;\n }\n \n-static int fetch_pack_config(const char *var, const char *value)\n+static int fetch_pack_config(const char *var, const char *value, void *cb_data)\n {\n \tif (strcmp(var, \"fetch.unpacklimit\") == 0) {\n \t\tfetch_unpack_limit = git_config_int(var, value);\n@@ -658,7 +658,7 @@ static int fetch_pack_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n static struct lock_file lock;\n@@ -672,7 +672,7 @@ int main(int argc, char **argv)\n \tstruct stat st;\n \n \tsetup_git_directory();\n-\tgit_config(fetch_pack_config);\n+\tgit_config(fetch_pack_config, NULL);\n \n \tif (0 <= transfer_unpack_limit)\n \t\tunpack_limit = transfer_unpack_limit;\ndiff --git a/git.c b/git.c\nindex f200907..bbe09d5 100644\n--- a/git.c\n+++ b/git.c\n@@ -87,7 +87,7 @@ static int handle_options(const char*** argv, int* argc)\n static const char *alias_command;\n static char *alias_string;\n \n-static int git_alias_config(const char *var, const char *value)\n+static int git_alias_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!prefixcmp(var, \"alias.\") && !strcmp(var + 6, alias_command)) {\n \t\talias_string = xstrdup(value);\n@@ -158,7 +158,7 @@ static int handle_alias(int *argcp, const char ***argv)\n \tsubdir = setup_git_directory_gently(&nongit);\n \n \talias_command = (*argv)[0];\n-\tgit_config(git_alias_config);\n+\tgit_config(git_alias_config, NULL);\n \tif (alias_string) {\n \t\tif (alias_string[0] == '!') {\n \t\t\ttrace_printf(\"trace: alias to shell cmd: %s => %s\\n\",\ndiff --git a/http-fetch.c b/http-fetch.c\nindex 53fb2a9..bc87d4b 100644\n--- a/http-fetch.c\n+++ b/http-fetch.c\n@@ -996,7 +996,7 @@ int main(int argc, const char **argv)\n \tint rc = 0;\n \n \tsetup_git_directory();\n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \twhile (arg < argc && argv[arg][0] == '-') {\n \t\tif (argv[arg][1] == 't') {\ndiff --git a/http.c b/http.c\nindex c8237cb..fd359bf 100644\n--- a/http.c\n+++ b/http.c\n@@ -97,7 +97,7 @@ static void process_curl_messages(void)\n }\n #endif\n \n-static int http_options(const char *var, const char *value)\n+static int http_options(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcmp(\"http.sslverify\", var)) {\n \t\tif (curl_ssl_verify == -1) {\n@@ -164,7 +164,7 @@ static int http_options(const char *var, const char *value)\n \t}\n \n \t/* Fall back on the default ones */\n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n static CURL* get_curl_handle(void)\n@@ -252,7 +252,7 @@ void http_init(void)\n \tif (low_speed_time != NULL)\n \t\tcurl_low_speed_time = strtol(low_speed_time, NULL, 10);\n \n-\tgit_config(http_options);\n+\tgit_config(http_options, NULL);\n \n \tif (curl_ssl_verify == -1)\n \t\tcurl_ssl_verify = 1;\ndiff --git a/imap-send.c b/imap-send.c\nindex 4283a4a..129776c 100644\n--- a/imap-send.c\n+++ b/imap-send.c\n@@ -1255,7 +1255,7 @@ static imap_server_conf_t server =\n static char *imap_folder;\n \n static int\n-git_imap_config(const char *key, const char *val)\n+git_imap_config(const char *key, const char *val, void *cb_data)\n {\n \tchar imap_key[] = \"imap.\";\n \n@@ -1300,7 +1300,7 @@ main(int argc, char **argv)\n \t/* init the random number generator */\n \tarc4_init();\n \n-\tgit_config( git_imap_config );\n+\tgit_config(git_imap_config, NULL);\n \n \tif (!imap_folder) {\n \t\tfprintf( stderr, \"no imap store specified\\n\" );\ndiff --git a/local-fetch.c b/local-fetch.c\nindex 4b650ef..23d2cbe 100644\n--- a/local-fetch.c\n+++ b/local-fetch.c\n@@ -204,7 +204,7 @@ int main(int argc, const char **argv)\n \tint arg = 1;\n \n \tsetup_git_directory();\n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \twhile (arg < argc && argv[arg][0] == '-') {\n \t\tif (argv[arg][1] == 't')\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 8f72b2c..f774342 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -851,7 +851,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,\n static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail;\n static const char *default_ll_merge;\n \n-static int read_merge_config(const char *var, const char *value)\n+static int read_merge_config(const char *var, const char *value, void *cb_data)\n {\n \tstruct ll_merge_driver *fn;\n \tconst char *ep, *name;\n@@ -940,7 +940,7 @@ static void initialize_ll_merge(void)\n \tif (ll_user_merge_tail)\n \t\treturn;\n \tll_user_merge_tail = &ll_user_merge;\n-\tgit_config(read_merge_config);\n+\tgit_config(read_merge_config, NULL);\n }\n \n static const struct ll_merge_driver *find_ll_merge_driver(const char *merge_attr)\n@@ -1696,13 +1696,13 @@ static struct commit *get_ref(const char *ref)\n \treturn (struct commit *)object;\n }\n \n-static int merge_config(const char *var, const char *value)\n+static int merge_config(const char *var, const char *value, void *cb_data)\n {\n \tif (!strcasecmp(var, \"merge.verbosity\")) {\n \t\tverbosity = git_config_int(var, value);\n \t\treturn 0;\n \t}\n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n int main(int argc, char *argv[])\n@@ -1723,7 +1723,7 @@ int main(int argc, char *argv[])\n \t\t\tsubtree_merge = 1;\n \t}\n \n-\tgit_config(merge_config);\n+\tgit_config(merge_config, NULL);\n \tif (getenv(\"GIT_MERGE_VERBOSITY\"))\n \t\tverbosity = strtol(getenv(\"GIT_MERGE_VERBOSITY\"), NULL, 10);\n \ndiff --git a/receive-pack.c b/receive-pack.c\nindex d3c422b..feab9a4 100644\n--- a/receive-pack.c\n+++ b/receive-pack.c\n@@ -18,7 +18,7 @@ static int report_status;\n static char capabilities[] = \" report-status delete-refs \";\n static int capabilities_sent;\n \n-static int receive_pack_config(const char *var, const char *value)\n+static int receive_pack_config(const char *var, const char *value, void *cb_data)\n {\n \tif (strcmp(var, \"receive.denynonfastforwards\") == 0) {\n \t\tdeny_non_fast_forwards = git_config_bool(var, value);\n@@ -35,7 +35,7 @@ static int receive_pack_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)\n@@ -484,7 +484,7 @@ int main(int argc, char **argv)\n \tif (is_repository_shallow())\n \t\tdie(\"attempt to push into a shallow repository\");\n \n-\tgit_config(receive_pack_config);\n+\tgit_config(receive_pack_config, NULL);\n \n \tif (0 <= transfer_unpack_limit)\n \t\tunpack_limit = transfer_unpack_limit;\ndiff --git a/send-pack.c b/send-pack.c\nindex 83ee87d..7895520 100644\n--- a/send-pack.c\n+++ b/send-pack.c\n@@ -346,7 +346,7 @@ int main(int argc, char **argv)\n \tpid_t pid;\n \n \tsetup_git_directory();\n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \targv++;\n \tfor (i = 1; i < argc; i++, argv++) {\ndiff --git a/setup.c b/setup.c\nindex a45ea83..d3487aa 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -270,7 +270,8 @@ int git_config_perm(const char *var, const char *value)\n \treturn git_config_bool(var, value);\n }\n \n-int check_repository_format_version(const char *var, const char *value)\n+int check_repository_format_version(const char *var, const char *value,\n+\t\t\t\t    void *cb_data)\n {\n        if (strcmp(var, \"core.repositoryformatversion\") == 0)\n                repository_format_version = git_config_int(var, value);\n@@ -281,7 +282,7 @@ int check_repository_format_version(const char *var, const char *value)\n \n int check_repository_format(void)\n {\n-\tgit_config(check_repository_format_version);\n+\tgit_config(check_repository_format_version, NULL);\n \tif (GIT_REPO_VERSION < repository_format_version)\n \t\tdie (\"Expected git repo version <= %d, found %d\",\n \t\t     GIT_REPO_VERSION, repository_format_version);\ndiff --git a/ssh-fetch.c b/ssh-fetch.c\nindex bdf51a7..ceb8b7d 100644\n--- a/ssh-fetch.c\n+++ b/ssh-fetch.c\n@@ -125,7 +125,7 @@ int main(int argc, char **argv)\n \tif (!prog) prog = \"git-ssh-upload\";\n \n \tsetup_git_directory();\n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \twhile (arg < argc && argv[arg][0] == '-') {\n \t\tif (argv[arg][1] == 't') {\ndiff --git a/unpack-file.c b/unpack-file.c\nindex 25c56b3..ade9926 100644\n--- a/unpack-file.c\n+++ b/unpack-file.c\n@@ -33,7 +33,7 @@ int main(int argc, char **argv)\n \t\tdie(\"Not a valid object name %s\", argv[1]);\n \n \tsetup_git_directory();\n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \n \tputs(create_temp_file(sha1));\n \treturn 0;\ndiff --git a/var.c b/var.c\nindex e585e59..8ec0fdd 100644\n--- a/var.c\n+++ b/var.c\n@@ -39,13 +39,13 @@ static const char *read_var(const char *var)\n \treturn val;\n }\n \n-static int show_config(const char *var, const char *value)\n+static int show_config(const char *var, const char *value, void *cb_data)\n {\n \tif (value)\n \t\tprintf(\"%s=%s\\n\", var, value);\n \telse\n \t\tprintf(\"%s\\n\", var);\n-\treturn git_default_config(var, value);\n+\treturn git_default_config(var, value, NULL);\n }\n \n int main(int argc, char **argv)\n@@ -59,11 +59,11 @@ int main(int argc, char **argv)\n \tval = NULL;\n \n \tif (strcmp(argv[1], \"-l\") == 0) {\n-\t\tgit_config(show_config);\n+\t\tgit_config(show_config, NULL);\n \t\tlist_vars();\n \t\treturn 0;\n \t}\n-\tgit_config(git_default_config);\n+\tgit_config(git_default_config, NULL);\n \tval = read_var(argv[1]);\n \tif (!val)\n \t\tusage(var_usage);\ndiff --git a/wt-status.c b/wt-status.c\nindex a055990..6e40870 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -346,7 +346,7 @@ void wt_status_print(struct wt_status *s)\n \t}\n }\n \n-int git_status_config(const char *k, const char *v)\n+int git_status_config(const char *k, const char *v, void *cb_data)\n {\n \tif (!strcmp(k, \"status.color\") || !strcmp(k, \"color.status\")) {\n \t\twt_status_use_color = git_config_colorbool(k, v);\n@@ -356,5 +356,5 @@ int git_status_config(const char *k, const char *v)\n \t\tint slot = parse_status_slot(k, 13);\n \t\tcolor_parse(v, k, wt_status_colors[slot]);\n \t}\n-\treturn git_default_config(k, v);\n+\treturn git_default_config(k, v, NULL);\n }\ndiff --git a/wt-status.h b/wt-status.h\nindex cfea4ae..242e9c5 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -21,7 +21,7 @@ struct wt_status {\n \tint workdir_untracked;\n };\n \n-int git_status_config(const char *var, const char *value);\n+int git_status_config(const char *var, const char *value, void *cb_data);\n void wt_status_prepare(struct wt_status *s);\n void wt_status_print(struct wt_status *s);\n \n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42746","messageId":"11796842904194-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 13/15] unpack-trees.c: optionally clone submodules for later checkout","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:46Z","receivedAt":"2007-05-20T18:04:46Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nWhen the --submodules option is specified and a submodule\nto be checked out is not available locally, git-checkout will\nsearch for submodule.<submodule>.url options in the remote\nconfiguration and clone each submodule using the first url that\nit can use from the local site.\n\nSigned-off-by: Sven Verdoolaege <skimo@kotnet.org>\n---\n Documentation/config.txt |    3 +\n Makefile                 |    5 +-\n submodules.c             |  209 ++++++++++++++++++++++++++++++++++++++++++++++\n submodules.h             |    6 ++\n unpack-trees.c           |   51 +++++++++++\n 5 files changed, 272 insertions(+), 2 deletions(-)\n create mode 100644 submodules.c\n create mode 100644 submodules.h\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 5d891ac..cee9e40 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -610,6 +610,9 @@ showbranch.default::\n \tThe default set of branches for gitlink:git-show-branch[1].\n \tSee gitlink:git-show-branch[1].\n \n+submodule.<submodule>.url\n+\tThe URL of a submodule.  See gitlink:git-clone[1].\n+\n tar.umask::\n \tBy default, gitlink:git-tar-tree[1] sets file and directories modes\n \tto 0666 or 0777. While this is both useful and acceptable for projects\ndiff --git a/Makefile b/Makefile\nindex bce8514..c79e636 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -297,7 +297,8 @@ LIB_H = \\\n \tdiff.h object.h pack.h pkt-line.h quote.h refs.h list-objects.h sideband.h \\\n \trun-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \\\n \ttree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \\\n-\tutf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h mailmap.h\n+\tutf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h mailmap.h \\\n+\tsubmodules.h\n \n DIFF_OBJS = \\\n \tdiff.o diff-lib.o diffcore-break.o diffcore-order.o \\\n@@ -320,7 +321,7 @@ LIB_OBJS = \\\n \talloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \\\n \tcolor.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \\\n \tconvert.o attr.o decorate.o progress.o mailmap.o symlinks.o \\\n-\t$(HTTP_CONFIG_OBJ)\n+\t$(HTTP_CONFIG_OBJ) submodules.o\n \n BUILTIN_OBJS = \\\n \tbuiltin-add.o \\\ndiff --git a/submodules.c b/submodules.c\nnew file mode 100644\nindex 0000000..5035a05\n--- /dev/null\n+++ b/submodules.c\n@@ -0,0 +1,209 @@\n+#include \"cache.h\"\n+#include \"submodules.h\"\n+#include \"run-command.h\"\n+\n+struct key_val_list {\n+\tstruct key_val_list *next;\n+\tchar *key;\n+\tchar *val;\n+};\n+\n+static void free_key_val_list(struct key_val_list *list)\n+{\n+\tstruct key_val_list *next;\n+\tfor (; list; list = next) {\n+\t\tnext = list->next;\n+\t\tfree(list->key);\n+\t\tfree(list->val);\n+\t\tfree(list);\n+\t}\n+}\n+\n+static struct key_val_list *find_key_val_list(struct key_val_list *list,\n+\t\t\t\t\t\tconst char *key)\n+{\n+\twhile (list && strcmp(list->key, key))\n+\t\tlist = list->next;\n+\treturn list;\n+}\n+\n+struct collect_urls_data {\n+\tstruct key_val_list **next;\n+\n+\tconst char *type;\n+};\n+\n+static int collect_urls(const char *var, const char *value, void *cb_data)\n+{\n+\tstruct collect_urls_data *cb = (struct collect_urls_data*)cb_data;\n+\tint typelen = strlen(cb->type);\n+\tint len;\n+\tchar *doturl;\n+\tstruct key_val_list *item;\n+\n+\tif (prefixcmp(var, cb->type))\n+\t\treturn 0;\n+\n+\tif (var[typelen] != '.')\n+\t\treturn 0;\n+\n+\tvar += typelen+1;\n+\n+\tdoturl = strrchr(var, '.');\n+\tif (!doturl || strcmp(doturl, \".url\"))\n+\t\treturn 0;\n+\n+\tlen = doturl-var;\n+\tif (len <= 0)\n+\t\treturn 0;\n+\n+\titem = xmalloc(sizeof(struct key_val_list));\n+\titem->key = xmalloc(len+1);\n+\tmemcpy(item->key, var, len);\n+\titem->key[len] = 0;\n+\titem->val = xstrdup(value);\n+\titem->next = NULL;\n+\t*cb->next = item;\n+\tcb->next = &item->next;\n+\n+\treturn 0;\n+}\n+\n+static const char *local_URL(const char *remote, const char *url)\n+{\n+\tstatic char local_url[PATH_MAX];\n+\n+\tif (!prefixcmp(url, \"https://\"))\n+\t\treturn url;\n+\n+\tif (!prefixcmp(url, \"http://\"))\n+\t\treturn url;\n+\n+\tif (!prefixcmp(url, \"ftp://\"))\n+\t\treturn url;\n+\n+\tif (!prefixcmp(remote, \"/\"))\n+\t\treturn url;\n+\n+\tif (!prefixcmp(remote, \"ssh://\") && !prefixcmp(url, \"/\")) {\n+\t\tchar *slash;\n+\t\tint len = strlen(url);\n+\n+\t\tslash = strchr(remote+6, '/');\n+\t\tif (!slash || (slash-remote)+len+1 > sizeof(local_url))\n+\t\t\treturn NULL;\n+\t\tmemcpy(local_url, remote, slash-remote);\n+\t\tmemcpy(local_url+(slash-remote), url, len+1);\n+\t\treturn local_url;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+static int fetch_submodule_urls(struct key_val_list **next_url)\n+{\n+\tstruct key_val_list *remotes = NULL;\n+\tstruct collect_urls_data remotes_data = { &remotes, \"remote\" };\n+\tstruct key_val_list *remote;\n+\tstatic char key[1024];\n+\n+\tgit_config(collect_urls, &remotes_data);\n+\tfor (remote = remotes; remote; remote = remote->next) {\n+\t\tstruct key_val_list *submodules = NULL;\n+\t\tstruct collect_urls_data submodules_data =\n+\t\t\t{ &submodules, \"submodule\" };\n+\t\tstruct key_val_list *submodule;\n+\t\tchar *dest;\n+\n+\t\tdest = xstrdup(remote->val);\n+\t\tgit_config_from_remote(collect_urls, dest, &submodules_data);\n+\t\tfree(dest);\n+\t\tfor (submodule = submodules; submodule; submodule = submodule->next) {\n+\t\t\tconst char *local_url;\n+\t\t\tstruct key_val_list *item;\n+\n+\t\t\tlocal_url = local_URL(remote->val, submodule->val);\n+\t\t\tif (!local_url)\n+\t\t\t\tcontinue;\n+\n+\t\t\tif (snprintf(key, sizeof(key),\n+\t\t\t    \"submodule.%s.url\", submodule->key) > sizeof(key))\n+\t\t\t\treturn error(\"submodule name too long\");\n+\n+\t\t\tgit_config_set(key, local_url);\n+\n+\t\t\titem = xmalloc(sizeof(struct key_val_list));\n+\t\t\titem->key = xstrdup(submodule->key);\n+\t\t\titem->val = xstrdup(local_url);\n+\t\t\titem->next = NULL;\n+\t\t\t*next_url = item;\n+\t\t\tnext_url = &item->next;\n+\t\t}\n+\n+\t\tfree_key_val_list(submodules);\n+\t}\n+\n+\tfree_key_val_list(remotes);\n+\n+\treturn 0;\n+}\n+\n+int clone_submodule(const char *submodule)\n+{\n+\tstruct key_val_list *submodules = NULL;\n+\tstruct collect_urls_data submodules_data = { &submodules, \"submodule\" };\n+\tstruct key_val_list *item;\n+\tchar *path;\n+\tint err;\n+\tconst char *gitdirenv;\n+\tconst char *args[10];\n+\tint argc;\n+\n+\tgit_config(collect_urls, &submodules_data);\n+\titem = find_key_val_list(submodules, submodule);\n+\tif (!item) {\n+\t\terr = fetch_submodule_urls(submodules_data.next);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t\titem = find_key_val_list(*submodules_data.next, submodule);\n+\t\tif (!item)\n+\t\t\treturn error(\"don't know where to get submodule '%s'\",\n+\t\t\t\t\tsubmodule);\n+\t}\n+\n+\tpath = git_path(\"submodules/%s\", submodule);\n+\n+\targc = 0;\n+\targs[argc++] = \"clone\";\n+\targs[argc++] = \"--submodules\";\n+\targs[argc++] = \"-n\";\n+\targs[argc++] = item->val;\n+\targs[argc++] = path;\n+\targs[argc] = NULL;\n+\n+\tgitdirenv = getenv(GIT_DIR_ENVIRONMENT);\n+\tunsetenv(GIT_DIR_ENVIRONMENT);\n+\terr = run_command_v_opt(args, RUN_GIT_CMD);\n+\n+\tsetenv(GIT_DIR_ENVIRONMENT,\n+\t\tgit_path(\"submodules/%s/.git\", submodule), 1);\n+\n+\targc = 0;\n+\targs[argc++] = \"update-ref\";\n+\targs[argc++] = \"--no-deref\";\n+\targs[argc++] = \"HEAD\";\n+\targs[argc++] = \"0000000000000000000000000000000000000000\";\n+\targs[argc] = NULL;\n+\n+\tif (!err)\n+\t\terr = run_command_v_opt(args, RUN_GIT_CMD);\n+\n+\tsetenv(GIT_DIR_ENVIRONMENT, gitdirenv, 1);\n+\n+\tif (err)\n+\t\treturn error(\"failed to clone submodule '%s'\", submodule);\n+\n+\tfree_key_val_list(submodules);\n+\n+\treturn 0;\n+}\ndiff --git a/submodules.h b/submodules.h\nnew file mode 100644\nindex 0000000..56590e7\n--- /dev/null\n+++ b/submodules.h\n@@ -0,0 +1,6 @@\n+#ifndef SUBMODULES_H\n+#define SUBMODULES_H\n+\n+int clone_submodule(const char *submodule);\n+\n+#endif\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 3dadebb..f9865b9 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -6,6 +6,7 @@\n #include \"unpack-trees.h\"\n #include \"progress.h\"\n #include \"refs.h\"\n+#include \"submodules.h\"\n \n #define DBRT_DEBUG 1\n \n@@ -808,6 +809,36 @@ int threeway_merge(struct cache_entry **stages,\n \treturn count;\n }\n \n+static int ensure_submodule(struct cache_entry *ce,\n+\t\t\t    struct unpack_trees_options *o)\n+{\n+\tstruct stat st;\n+\tchar *path;\n+\n+\tif (!ce)\n+\t\treturn 0;\n+\n+\tif (!S_ISDIRLNK(ntohl(ce->ce_mode)))\n+\t\treturn 0;\n+\n+\tpath = mkpath(\"%s/.git\", ce->name);\n+\tfprintf(stderr, \"path: %s\\n\", path);\n+\tif (lstat(path, &st)) {\n+\t\tpath = git_path(\"submodules/%s/.git\", ce->name);\n+\t\tfprintf(stderr, \"path: %s\\n\", path);\n+\t\tif (lstat(path, &st)) {\n+\t\t\tint err;\n+\t\t\terr = clone_submodule(ce->name);\n+\t\t\tif (err)\n+\t\t\t\treturn err;\n+\t\t}\n+\t}\n+\n+\t/* Now check that the commit is available and fetch if needed */\n+\n+\treturn 0;\n+}\n+\n /*\n  * Two-way merge.\n  *\n@@ -833,6 +864,17 @@ int twoway_merge(struct cache_entry **src,\n \tif (newtree == o->df_conflict_entry)\n \t\tnewtree = NULL;\n \n+\tif (o->submodules && o->update) {\n+\t\tint err;\n+\t\terr = ensure_submodule(current, o);\n+\t\tif (!err)\n+\t\t\terr = ensure_submodule(oldtree, o);\n+\t\tif (!err)\n+\t\t\terr = ensure_submodule(newtree, o);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t}\n+\n \tif (current) {\n \t\tif ((!oldtree && !newtree) || /* 4 and 5 */\n \t\t    (!oldtree && newtree &&\n@@ -909,6 +951,15 @@ int oneway_merge(struct cache_entry **src,\n \t\treturn error(\"Cannot do a oneway merge of %d trees\",\n \t\t\t     o->merge_size);\n \n+\tif (o->submodules && o->update) {\n+\t\tint err;\n+\t\terr = ensure_submodule(old, o);\n+\t\tif (!err)\n+\t\t\terr = ensure_submodule(a, o);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t}\n+\n \tif (!a)\n \t\treturn deleted_entry(old, old, o);\n \tif (old && same(old, a)) {\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42747","messageId":"1179684290298-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 14/15] entry.c: optionall checkout newly cloned submodules","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:47Z","receivedAt":"2007-05-20T18:04:47Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\n---\n entry.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--\n 1 files changed, 56 insertions(+), 2 deletions(-)\n\ndiff --git a/entry.c b/entry.c\nindex 8c70a47..24bf161 100644\n--- a/entry.c\n+++ b/entry.c\n@@ -104,10 +104,63 @@ static int checkout_submodule(struct cache_entry *ce, const char *path, const st\n \treturn 0;\n }\n \n+static const char *relativize_path(const char *path, const char *dest)\n+{\n+\tstatic char relative_path[PATH_MAX];\n+\tint slashes;\n+\tconst char *cp;\n+\tchar *rp;\n+\n+\tif (path[0] == '/')\n+\t\treturn path;\n+\n+\tfor (slashes = 0, cp = strchr(dest, '/'); cp; cp = strchr(cp, '/')) {\n+\t\t++slashes;\n+\t\twhile (*cp == '/')\n+\t\t\t++cp;\n+\t}\n+\tif (3 * slashes + strlen(path) + 1 > sizeof(relative_path))\n+\t\tdie(\"path too long\");\n+\n+\trp = relative_path;\n+\twhile (slashes--) {\n+\t\tmemcpy(rp, \"../\", 3);\n+\t\trp += 3;\n+\t}\n+\tstrcpy(rp, path);\n+\n+\treturn relative_path;\n+}\n+\n+static int write_submodule(struct cache_entry *ce, char *path, const struct checkout *state)\n+{\n+\tstruct stat st;\n+\tconst char *submodule_dir, *dest;\n+\n+\tif (mkdir(path, 0777) < 0)\n+\t\treturn error(\"git-checkout-index: cannot create subproject directory %s\", path);\n+\n+\tif (!state->submodules)\n+\t\treturn 0;\n+\n+\tsubmodule_dir = git_path(\"submodules/%s/.git\", ce->name);\n+\tif (lstat(submodule_dir, &st))\n+\t\treturn error(\"submodule '%s' unavailable\", ce->name);\n+\n+\tdest = mkpath(\"%s/.git\", ce->name);\n+\tsubmodule_dir = relativize_path(submodule_dir, dest);\n+\n+\tif (symlink(submodule_dir, dest))\n+\t\treturn -1;\n+\n+\treturn checkout_submodule(ce, path, state);\n+}\n+\n static int write_entry(struct cache_entry *ce, char *path, const struct checkout *state, int to_tempfile)\n {\n \tint fd;\n \tlong wrote;\n+\tint err;\n \n \tswitch (ntohl(ce->ce_mode) & S_IFMT) {\n \t\tchar *buf, *new;\n@@ -177,8 +230,9 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout\n \tcase S_IFDIRLNK:\n \t\tif (to_tempfile)\n \t\t\treturn error(\"git-checkout-index: cannot create temporary subproject %s\", path);\n-\t\tif (mkdir(path, 0777) < 0)\n-\t\t\treturn error(\"git-checkout-index: cannot create subproject directory %s\", path);\n+\t\terr = write_submodule(ce, path, state);\n+\t\tif (err)\n+\t\t\treturn err;\n \t\tbreak;\n \tdefault:\n \t\treturn error(\"git-checkout-index: unknown file mode for %s\", path);\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42751","messageId":"11796842904153-git-send-email-skimo@liacs.nl","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"[PATCH 15/15] git-clone: add --submodules for cloning submodules","fromName":"","fromEmail":"skimo@liacs.nl","sentAt":"2007-05-20T18:04:48Z","receivedAt":"2007-05-20T18:04:48Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"From: Sven Verdoolaege <skimo@kotnet.org>\n\nWhen the --submodules option is specified, git-clone will search\nfor submodule.<submodule>.url options in the remote configuration\nand clone each submodule using the first url that it can use from\nthe local site.\n\nSigned-off-by: Sven Verdoolaege <skimo@kotnet.org>\n---\n Documentation/git-clone.txt |    6 +++++-\n git-clone.sh                |   16 ++++++++++++++--\n 2 files changed, 19 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\nindex 644bf12..565155b 100644\n--- a/Documentation/git-clone.txt\n+++ b/Documentation/git-clone.txt\n@@ -11,7 +11,7 @@ SYNOPSIS\n [verse]\n 'git-clone' [--template=<template_directory>] [-l [-s]] [-q] [-n] [--bare]\n \t  [-o <name>] [-u <upload-pack>] [--reference <repository>]\n-\t  [--depth <depth>] <repository> [<directory>]\n+\t  [--depth <depth>] [--submodules] <repository> [<directory>]\n \n DESCRIPTION\n -----------\n@@ -105,6 +105,10 @@ OPTIONS\n \twith a long history, and would want to send in a fixes\n \tas patches.\n \n+--submodules::\n+\tClone submodules specified in (remote) configuration parameters\n+\tsubmodule.<submodule>.url.\n+\n <repository>::\n \tThe (possibly remote) repository to clone from.  It can\n \tbe any URL git-fetch supports.\ndiff --git a/git-clone.sh b/git-clone.sh\nindex fdd354f..a51b887 100755\n--- a/git-clone.sh\n+++ b/git-clone.sh\n@@ -14,7 +14,7 @@ die() {\n }\n \n usage() {\n-\tdie \"Usage: $0 [--template=<template_directory>] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [--depth <n>] [-n] <repo> [<dir>]\"\n+\tdie \"Usage: $0 [--template=<template_directory>] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [--depth <n>] [-n] [--submodules] <repo> [<dir>]\"\n }\n \n get_repo_base() {\n@@ -88,6 +88,7 @@ origin_override=\n use_separate_remote=t\n depth=\n no_progress=\n+submodules=\n test -t 1 || no_progress=--no-progress\n while\n \tcase \"$#,$1\" in\n@@ -138,6 +139,8 @@ while\n \t*,--depth)\n \t\tshift\n \t\tdepth=\"--depth=$1\";;\n+\t*,--su|*,--sub|*,--subm|*,--submo|*,--submod|*,--submodu|*,--submodul|\\\n+\t*,--submodule|*,--submodules) submodules=\"--submodules\" ;;\n \t*,-*) usage ;;\n \t*) break ;;\n \tesac\n@@ -156,6 +159,10 @@ then\n \tthen\n \t\tdie '--bare and --origin $origin options are incompatible.'\n \tfi\n+\tif test -n \"$submodules\"\n+\tthen\n+\t\tdie '--bare and --submodules origin options are incompatible.'\n+\tfi\n \tno_checkout=yes\n \tuse_separate_remote=\n fi\n@@ -401,10 +408,15 @@ then\n \t\tgit-config branch.\"$head_points_at\".merge \"refs/heads/$head_points_at\"\n \tesac\n \n+\tif test -n \"$submodules\"\n+\tthen\n+\t\tgit-config core.submodules true\n+\tfi\n+\n \tcase \"$no_checkout\" in\n \t'')\n \t\ttest \"z$quiet\" = z -a \"z$no_progress\" = z && v=-v || v=\n-\t\tgit-read-tree -m -u $v HEAD HEAD\n+\t\tgit-read-tree -m -u $v $submodules HEAD HEAD\n \tesac\n fi\n rm -f \"$GIT_DIR/CLONE_HEAD\" \"$GIT_DIR/REMOTE_HEAD\"\n-- \n1.5.2.rc3.815.g8fc2\n"},{"id":"42752","messageId":"20070520181155.GH4085@planck.djpig.de","threadId":"8250","inReplyTo":"11796842881646-git-send-email-skimo@liacs.nl","subject":"Re: [PATCH 02/15] git-config: add --remote option for reading config from remote repo","fromName":"Frank Lichtenheld","fromEmail":"frank@lichtenheld.de","sentAt":"2007-05-20T18:11:55Z","receivedAt":"2007-05-20T18:11:55Z","isPatch":true,"sender":{"key":"frank@lichtenheld.de","avatar":"https://gravatar.com/avatar/b9f1d4b120e138f157c9e480d0818197c474628923786adb98f30017cdb99c3c?d=mp&s=160"},"body":"On Sun, May 20, 2007 at 08:04:35PM +0200, skimo@liacs.nl wrote:\n> From: Sven Verdoolaege <skimo@kotnet.org>\n> \n> Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>\n> ---\n>  Documentation/git-config.txt |   33 +++++++++++++++++++++---------\n\nAll my old suggestions and corrections for the documentation\npart still apply... should I repeat them?\n\nGruesse,\n-- \nFrank Lichtenheld <frank@lichtenheld.de>\nwww: http://www.djpig.de/\n"},{"id":"42765","messageId":"7vhcq7l3ar.fsf@assigned-by-dhcp.cox.net","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-05-20T19:10:04Z","receivedAt":"2007-05-20T19:10:04Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"skimo@liacs.nl writes:\n\n> This patch series implements a mechanism for cloning submodules.\n\nLet me start by asking a few stupid questions.\n\n> Each submodule is specified by a 'submodule.<submodule>.url'\n> configuration option, e.g.,\n>\n> bash-3.00$ ./git-config --remote=http://www.liacs.nl/~sverdool/isa.git --get-regexp 'submodule\\..*\\.url' \n> submodule.cloog.url /home/sverdool/public_html/cloog.git\n> submodule.cloog.url http://www.liacs.nl/~sverdool/cloog.git\n\nYou are priming the process by having these configuration\nvariables in the superproject to be cloned (i.e. this is done by\nthe owner of the superproject).\n\n> git-checkout will use the first url that works.\n> E.g., a\n>\n> git clone --submodules ssh://liacs/~/public_html/isa.git\n>\n> followed by\n>\n> git checkout origin/submodule\n>\n> (which only works for me), will use the first url, while a\n>\n> git clone --submodules http://www.liacs.nl/~sverdool/isa.git\n>\n> followed by\n>\n> git checkout origin/submodule\n>\n> will use the second.\n\nWhat's the design like to make clone and checkout work together?\nWhen you run the first clone with -n (\"do not checkout\"), what\nshould happen (I am not asking what your code does, but what the\ndesired behaviour should be)?  My take on that question is\n\"subproject cloning is done by checkout, not clone\".\n\n> The cloning of submodules is now handled inside git-checkout.\n\nwhich I guess means your answer is the same as mine, which\nis fine.\n\nI am very worried about this big red switch that says \"all\nsubprojects to be cloned and checked out, or nothing\".  I think\nthis would not work well with projects that truly need\nsuperproject support (i.e. very large ones, where most people\nwould not want to clone and check out every single subproject).\n\n> I currently do not fetch after the initial clone, since\n> I'm not sure what ref to use for the revision I need to\n> fetch for the supermodule.\n\nI think fetching inside the subproject can be safely done with\nthe default (i.e. refs/heads/*:refs/remotes/origin/*) of 1.5.0\nor later, as long as we tell the users of the feature that they\nshould make sure that the commit referenced by superproject tree\nentries are available with such a fetch, which is a sane thing\nto require anyway.\n\nThe more important issue I think is at what point in the\nsuperproject operation does a recursive checkout in a subproject\nshould happen, and how we should do the checkout.  Issues I can\nthink of offhand are (no way exhaustive):\n\n - Do we checkout a branch? if so which one?\n\n - Do we detach HEAD if the commit named by the superproject\n   tree is not at the tip of the current branch of subproject?\n   do we detach always even if the commit is at the tip?\n\n - What would we do when the subproject working tree is not\n   clean?\n\n - How can a user decide which subproject to descend into and\n   which subproject to ignore, and how does git remember the\n   earlier decision made by the user without asking the same\n   again, and how does a user express \"now I want to also track\n   that subproject I've ignored so far\" and \"now I am not\n   interested in following that subproject anymore\"?\n\nSo I tend to disagree with not having the indirection we\ndiscussed on the other thread about .gitmodules, but I consider\nit a minor detail of cloning, and it is not a major deal to me.\n\nHowever, I agree with Alex that checkout semantics is a much\nbigger deal, and would expect people (brighter than myself,\nhopefully) to offer ideas.\n"},{"id":"42771","messageId":"20070520194448.GW942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"20070520181155.GH4085@planck.djpig.de","subject":"Re: [PATCH 02/15] git-config: add --remote option for reading config from remote repo","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-20T19:44:48Z","receivedAt":"2007-05-20T19:44:48Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Sun, May 20, 2007 at 08:11:55PM +0200, Frank Lichtenheld wrote:\n> On Sun, May 20, 2007 at 08:04:35PM +0200, skimo@liacs.nl wrote:\n> > From: Sven Verdoolaege <skimo@kotnet.org>\n> > \n> > Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>\n> > ---\n> >  Documentation/git-config.txt |   33 +++++++++++++++++++++---------\n> \n> All my old suggestions and corrections for the documentation\n> part still apply... should I repeat them?\n\nI did the [scope] thing, but it seems I inadvertedly threw it out.\nI guess I'll have to do it again.\n\nWas there anything else?\n\nskimo\n"},{"id":"42772","messageId":"20070520195930.GX942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"7vhcq7l3ar.fsf@assigned-by-dhcp.cox.net","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-20T19:59:30Z","receivedAt":"2007-05-20T19:59:30Z","isPatch":false,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Sun, May 20, 2007 at 12:10:04PM -0700, Junio C Hamano wrote:\n> > bash-3.00$ ./git-config --remote=http://www.liacs.nl/~sverdool/isa.git --get-regexp 'submodule\\..*\\.url' \n> > submodule.cloog.url /home/sverdool/public_html/cloog.git\n> > submodule.cloog.url http://www.liacs.nl/~sverdool/cloog.git\n> \n> You are priming the process by having these configuration\n> variables in the superproject to be cloned (i.e. this is done by\n> the owner of the superproject).\n\nIs that a question?\nThe answer would be that if the user didn't put this information\nin a config file, then git will try to get the information from\nany remote it can get its hands on.\n\n> What's the design like to make clone and checkout work together?\n> When you run the first clone with -n (\"do not checkout\"), what\n> should happen (I am not asking what your code does, but what the\n> desired behaviour should be)?  My take on that question is\n> \"subproject cloning is done by checkout, not clone\".\n\nThen I guess you are not asking me.\nI took the suggestion of doing the subproject cloning during checkout\nfrom you.\n\n> I am very worried about this big red switch that says \"all\n> subprojects to be cloned and checked out, or nothing\".  I think\n> this would not work well with projects that truly need\n> superproject support (i.e. very large ones, where most people\n> would not want to clone and check out every single subproject).\n\nIt's pretty easy to add a \"submodule.*.skip\" or \"submodule.*.ignore\".\nSince the subcloning only happens at checkout, you could set these\nbefore doing a checkout.\n\n> > I currently do not fetch after the initial clone, since\n> > I'm not sure what ref to use for the revision I need to\n> > fetch for the supermodule.\n> \n> I think fetching inside the subproject can be safely done with\n> the default (i.e. refs/heads/*:refs/remotes/origin/*) of 1.5.0\n> or later, as long as we tell the users of the feature that they\n> should make sure that the commit referenced by superproject tree\n> entries are available with such a fetch, which is a sane thing\n> to require anyway.\n\nSeems like a pretty strict requirement, but it's easy to implement,\nso I guess I can do that in the fourth version.\n\n> The more important issue I think is at what point in the\n> superproject operation does a recursive checkout in a subproject\n> should happen, and how we should do the checkout.  Issues I can\n> think of offhand are (no way exhaustive):\n> \n>  - Do we checkout a branch? if so which one?\n> \n>  - Do we detach HEAD if the commit named by the superproject\n>    tree is not at the tip of the current branch of subproject?\n>    do we detach always even if the commit is at the tip?\n\nI thought there was a consensus to detach the HEAD.\nI don't have a strong opinion on this issue, but a detached\nHEAD seems the most appropriate to me.\n\n>  - What would we do when the subproject working tree is not\n>    clean?\n\nI was planning on adding a --dry-run to git-checkout.\nThe superproject would run this in each subproject before\ndoing the actual checkout of the superproject.\n\n>  - How can a user decide which subproject to descend into and\n>    which subproject to ignore, and how does git remember the\n>    earlier decision made by the user without asking the same\n>    again, and how does a user express \"now I want to also track\n>    that subproject I've ignored so far\" and \"now I am not\n>    interested in following that subproject anymore\"?\n\nJust twiddle the \"submodule.*.skip\" option.\n\n> So I tend to disagree with not having the indirection we\n> discussed on the other thread about .gitmodules, but I consider\n> it a minor detail of cloning, and it is not a major deal to me.\n\nSome form of indirection is definitely required (although\nnot for my use of submodules) and I'll probably add it in a future round.\n\nskimo\n"},{"id":"42789","messageId":"20070520205444.GC25462@steel.home","threadId":"8250","inReplyTo":"20070520195930.GX942MdfPADPa@greensroom.kotnet.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-20T20:54:44Z","receivedAt":"2007-05-20T20:54:44Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Sven Verdoolaege, Sun, May 20, 2007 21:59:30 +0200:\n> > I am very worried about this big red switch that says \"all\n> > subprojects to be cloned and checked out, or nothing\".  I think\n> > this would not work well with projects that truly need\n> > superproject support (i.e. very large ones, where most people\n> > would not want to clone and check out every single subproject).\n> \n> It's pretty easy to add a \"submodule.*.skip\" or \"submodule.*.ignore\".\n> Since the subcloning only happens at checkout, you could set these\n> before doing a checkout.\n\nAnd set them back after doing the checkout? And so for each and every\ncheckout operation? I suggest you try checkout something like KDE a\nfew times (well, assuming KDE is split in submodules. It isn't yet).\nThe point is - it is annoying. And if it is annoying, it wont be used\n(as branches in CVS and merging in SVN).\n\n> > The more important issue I think is at what point in the\n> > superproject operation does a recursive checkout in a subproject\n> > should happen, and how we should do the checkout.  Issues I can\n> > think of offhand are (no way exhaustive):\n> > \n> >  - Do we checkout a branch? if so which one?\n> > \n> >  - Do we detach HEAD if the commit named by the superproject\n> >    tree is not at the tip of the current branch of subproject?\n> >    do we detach always even if the commit is at the tip?\n> \n> I thought there was a consensus to detach the HEAD.\n> I don't have a strong opinion on this issue, but a detached\n> HEAD seems the most appropriate to me.\n\nMe too. I actually believe it is the only way to do it. How can you\ncheckout a subproject to something else (to what a branch may point)\nand to what the tree of superproject has? On the other side (in\nsubproject) - why are you, the superproject, allowed to screw the\nreferences of the subproject?! It is independent, isn't it?!\n\n> >  - What would we do when the subproject working tree is not\n> >    clean?\n> \n> I was planning on adding a --dry-run to git-checkout.\n> The superproject would run this in each subproject before\n> doing the actual checkout of the superproject.\n\nWhy not do exactly what we do now? Pass \"-m\" down to it, if it was\ngiven to the top-level git-checkout.\n"},{"id":"42794","messageId":"20070520210954.GB942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"20070520205444.GC25462@steel.home","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-20T21:09:54Z","receivedAt":"2007-05-20T21:09:54Z","isPatch":false,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Sun, May 20, 2007 at 10:54:44PM +0200, Alex Riesen wrote:\n> Sven Verdoolaege, Sun, May 20, 2007 21:59:30 +0200:\n> > > I am very worried about this big red switch that says \"all\n> > > subprojects to be cloned and checked out, or nothing\".  I think\n> > > this would not work well with projects that truly need\n> > > superproject support (i.e. very large ones, where most people\n> > > would not want to clone and check out every single subproject).\n> > \n> > It's pretty easy to add a \"submodule.*.skip\" or \"submodule.*.ignore\".\n> > Since the subcloning only happens at checkout, you could set these\n> > before doing a checkout.\n> \n> And set them back after doing the checkout?\n\nWhat do you mean?  Why would you set them back?\nI guess I'm missing something.\n\n> Me too. I actually believe it is the only way to do it. How can you\n> checkout a subproject to something else (to what a branch may point)\n> and to what the tree of superproject has? On the other side (in\n> subproject) - why are you, the superproject, allowed to screw the\n> references of the subproject?! It is independent, isn't it?!\n\nWell... the subproject as a whole is independent of the superproject,\nbut the checkout in the superproject is not entirely independent.\n\n> > >  - What would we do when the subproject working tree is not\n> > >    clean?\n> > \n> > I was planning on adding a --dry-run to git-checkout.\n> > The superproject would run this in each subproject before\n> > doing the actual checkout of the superproject.\n> \n> Why not do exactly what we do now? Pass \"-m\" down to it, if it was\n> given to the top-level git-checkout.\n\nWe want to be sure that all (selected) subprojects can be updated before\nupdating any, no?\n\nskimo\n"},{"id":"42796","messageId":"20070520211850.GJ5412@admingilde.org","threadId":"8250","inReplyTo":"11796842892490-git-send-email-skimo@liacs.nl","subject":"Re: [PATCH 09/15] entry.c: optionally checkout submodules","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-20T21:18:50Z","receivedAt":"2007-05-20T21:18:50Z","isPatch":true,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nhave you seen my patch to checkout submodules?\n\nThe submodule checkout should really check that the requested commit\nis really available and have some other path for creating submodules\nwhich are not currently checked out / able to be checked out.\n\n-- \nMartin Waitz\n"},{"id":"42798","messageId":"20070520212404.GK5412@admingilde.org","threadId":"8250","inReplyTo":"11796842893584-git-send-email-skimo@liacs.nl","subject":"Re: [PATCH 06/15] git-read-tree: take --submodules option","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-20T21:24:04Z","receivedAt":"2007-05-20T21:24:04Z","isPatch":true,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nwhat really is the motivation to suppress submodule checkout at this\nlevel?  I can see that we need some per-submodule option for checkout,\nbut this should influence the actual checkout process and not\nread-tree.\n\nAt least we really want to always update the index correctly and a\nread-tree --no-submodules  which updates the index for submodules but\ndoesn't go into existing submodules just feels wrong.\n\n-- \nMartin Waitz\n"},{"id":"42799","messageId":"20070520212432.GE25462@steel.home","threadId":"8250","inReplyTo":"20070520210954.GB942MdfPADPa@greensroom.kotnet.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-20T21:24:32Z","receivedAt":"2007-05-20T21:24:32Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Sven Verdoolaege, Sun, May 20, 2007 23:09:54 +0200:\n> On Sun, May 20, 2007 at 10:54:44PM +0200, Alex Riesen wrote:\n> > Sven Verdoolaege, Sun, May 20, 2007 21:59:30 +0200:\n> > > > I am very worried about this big red switch that says \"all\n> > > > subprojects to be cloned and checked out, or nothing\".  I think\n> > > > this would not work well with projects that truly need\n> > > > superproject support (i.e. very large ones, where most people\n> > > > would not want to clone and check out every single subproject).\n> > > \n> > > It's pretty easy to add a \"submodule.*.skip\" or \"submodule.*.ignore\".\n> > > Since the subcloning only happens at checkout, you could set these\n> > > before doing a checkout.\n> > \n> > And set them back after doing the checkout?\n> \n> What do you mean?  Why would you set them back?\n\nWhy should I set them before doing a checkout?\n\n> I guess I'm missing something.\n\n\"checkout\" is an operation which is done often. It never had to be\nconfigured before.\n\n> > Me too. I actually believe it is the only way to do it. How can you\n> > checkout a subproject to something else (to what a branch may point)\n> > and to what the tree of superproject has? On the other side (in\n> > subproject) - why are you, the superproject, allowed to screw the\n> > references of the subproject?! It is independent, isn't it?!\n> \n> Well... the subproject as a whole is independent of the superproject,\n> but the checkout in the superproject is not entirely independent.\n>\n\nJunio was talking about branch in subproject, wasn't he?\n\n> > > >  - What would we do when the subproject working tree is not\n> > > >    clean?\n> > > \n> > > I was planning on adding a --dry-run to git-checkout.\n> > > The superproject would run this in each subproject before\n> > > doing the actual checkout of the superproject.\n> > \n> > Why not do exactly what we do now? Pass \"-m\" down to it, if it was\n> > given to the top-level git-checkout.\n> \n> We want to be sure that all (selected) subprojects can be updated before\n> updating any, no?\n> \n\nI guess passing \"-m\" to git-checkout _is_ an explicit permission from\nthe operator to perform a merge. Besides, it's visible: merge prints\nsomething, user sees the \"-m\" in command history (or in script code).\nCalling git-checkout twice even if we don't have to... it is kind of\nugly. Still need some dry-run this for normal case (checkout can be\nmodified to do this by default, I think).\n"},{"id":"42802","messageId":"20070520214026.GL5412@admingilde.org","threadId":"8250","inReplyTo":"20070520205444.GC25462@steel.home","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-20T21:40:26Z","receivedAt":"2007-05-20T21:40:26Z","isPatch":false,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Sun, May 20, 2007 at 10:54:44PM +0200, Alex Riesen wrote:\n> Me too. I actually believe it is the only way to do it. How can you\n> checkout a subproject to something else (to what a branch may point)\n> and to what the tree of superproject has? On the other side (in\n> subproject) - why are you, the superproject, allowed to screw the\n> references of the subproject?! It is independent, isn't it?!\n\nright.  except when you have some managed-by-superproject branch\nwhich is known to be special ;-)\n\nAfter all the submodule checkout is independent from its parent\nrepository, too -- so you don't screw anything *g*.\n\n\n> > >  - What would we do when the subproject working tree is not\n> > >    clean?\n> > \n> > I was planning on adding a --dry-run to git-checkout.\n> > The superproject would run this in each subproject before\n> > doing the actual checkout of the superproject.\n> \n> Why not do exactly what we do now? Pass \"-m\" down to it, if it was\n> given to the top-level git-checkout.\n\nsounds good.\nWith submodules we have to consider one extra level of merging.\n-m in the supermodule also means that an automatic merge of the\ndirlink entry should be done.  Which would execute git-merge in the\nsubmodule.  And merging in a dirty tree is a challenge of its own.\n\nSo if local changes conflict with the checkout we should just error out.\n\n-- \nMartin Waitz\n"},{"id":"42804","messageId":"20070520214732.GC942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"20070520212432.GE25462@steel.home","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-20T21:47:32Z","receivedAt":"2007-05-20T21:47:32Z","isPatch":false,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Sun, May 20, 2007 at 11:24:32PM +0200, Alex Riesen wrote:\n> Sven Verdoolaege, Sun, May 20, 2007 23:09:54 +0200:\n> > On Sun, May 20, 2007 at 10:54:44PM +0200, Alex Riesen wrote:\n> > > Sven Verdoolaege, Sun, May 20, 2007 21:59:30 +0200:\n> > > > > I am very worried about this big red switch that says \"all\n> > > > > subprojects to be cloned and checked out, or nothing\".  I think\n> > > > > this would not work well with projects that truly need\n> > > > > superproject support (i.e. very large ones, where most people\n> > > > > would not want to clone and check out every single subproject).\n> > > > \n> > > > It's pretty easy to add a \"submodule.*.skip\" or \"submodule.*.ignore\".\n> > > > Since the subcloning only happens at checkout, you could set these\n> > > > before doing a checkout.\n> > > \n> > > And set them back after doing the checkout?\n> > \n> > What do you mean?  Why would you set them back?\n> \n> Why should I set them before doing a checkout?\n> \n> > I guess I'm missing something.\n> \n> \"checkout\" is an operation which is done often. It never had to be\n> configured before.\n\nThere is going to have to be *some* way of selecting which\nsubprojects you want to check out.  A config option that you\nhave to set only once (or not at all if you are happy with\nthe default) seems to be the easiest way.  You can have git-gui\nset them for you if you want.\n\nHow would _you_ specify which subprojects to checkout ?\n\n> > Well... the subproject as a whole is independent of the superproject,\n> > but the checkout in the superproject is not entirely independent.\n> >\n> \n> Junio was talking about branch in subproject, wasn't he?\n\nThat's a local thing.\n\nskimo\n"},{"id":"42805","messageId":"20070520215024.GD942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"20070520212404.GK5412@admingilde.org","subject":"Re: [PATCH 06/15] git-read-tree: take --submodules option","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-20T21:50:24Z","receivedAt":"2007-05-20T21:50:24Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Sun, May 20, 2007 at 11:24:04PM +0200, Martin Waitz wrote:\n> hoi :)\n> \n> what really is the motivation to suppress submodule checkout at this\n> level?  I can see that we need some per-submodule option for checkout,\n> but this should influence the actual checkout process and not\n> read-tree.\n\nIt's only used with update is set.\n\n> At least we really want to always update the index correctly and a\n> read-tree --no-submodules  which updates the index for submodules but\n> doesn't go into existing submodules just feels wrong.\n\nIt doesn't do that.\n\nskimo\n"},{"id":"42806","messageId":"20070520215120.GE942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"20070520211850.GJ5412@admingilde.org","subject":"Re: [PATCH 09/15] entry.c: optionally checkout submodules","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-20T21:51:20Z","receivedAt":"2007-05-20T21:51:20Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Sun, May 20, 2007 at 11:18:50PM +0200, Martin Waitz wrote:\n> hoi :)\n> \n> have you seen my patch to checkout submodules?\n\nNot yet.  I'll look for it in the morning.\n\nskimo\n"},{"id":"42807","messageId":"20070520220337.GJ4085@planck.djpig.de","threadId":"8250","inReplyTo":"20070520194448.GW942MdfPADPa@greensroom.kotnet.org","subject":"Re: [PATCH 02/15] git-config: add --remote option for reading config from remote repo","fromName":"Frank Lichtenheld","fromEmail":"frank@lichtenheld.de","sentAt":"2007-05-20T22:03:38Z","receivedAt":"2007-05-20T22:03:38Z","isPatch":true,"sender":{"key":"frank@lichtenheld.de","avatar":"https://gravatar.com/avatar/b9f1d4b120e138f157c9e480d0818197c474628923786adb98f30017cdb99c3c?d=mp&s=160"},"body":"On Sun, May 20, 2007 at 09:44:48PM +0200, Sven Verdoolaege wrote:\n> On Sun, May 20, 2007 at 08:11:55PM +0200, Frank Lichtenheld wrote:\n> > On Sun, May 20, 2007 at 08:04:35PM +0200, skimo@liacs.nl wrote:\n> > > From: Sven Verdoolaege <skimo@kotnet.org>\n> > > \n> > > Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>\n> > > ---\n> > >  Documentation/git-config.txt |   33 +++++++++++++++++++++---------\n> > \n> > All my old suggestions and corrections for the documentation\n> > part still apply... should I repeat them?\n> \n> I did the [scope] thing, but it seems I inadvertedly threw it out.\n> I guess I'll have to do it again.\n> \n> Was there anything else?\n\nYou list --remote for all variants while it is not really supported for\nthem. Although this problem probably implicetly goes away if you use\nscope and later explain what that means.\n\nGruesse,\n-- \nFrank Lichtenheld <frank@lichtenheld.de>\nwww: http://www.djpig.de/\n"},{"id":"42811","messageId":"20070520221455.GN5412@admingilde.org","threadId":"8250","inReplyTo":"7vhcq7l3ar.fsf@assigned-by-dhcp.cox.net","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-20T22:14:55Z","receivedAt":"2007-05-20T22:14:55Z","isPatch":false,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Sun, May 20, 2007 at 12:10:04PM -0700, Junio C Hamano wrote:\n> The more important issue I think is at what point in the\n> superproject operation does a recursive checkout in a subproject\n> should happen, and how we should do the checkout.\n\nwe should really move from our big clone thing to a simple\nfetch+checkout wrapper.\n\nAnd then integrate all the submodule logic into the actual checkout\nstep where it belongs.\n\nWe might also want to expand fetch to also fetch newly reachable\nsubmodule commits (of a configurable subset of modules).\n\n> Issues I can think of offhand are (no way exhaustive):\n> \n>  - Do we checkout a branch? if so which one?\n\nAt least no off-the-shelf branch from the upstream repository of\nthe submodule.\n\nTo use some special branch allows to use normal git methods in\nthe submodule, too -- but I haven't been able to convince everybody\nyet...  So let's get it to a state where people can play with it\nin real projects and let's see.\n\n\n>  - Do we detach HEAD if the commit named by the superproject\n>    tree is not at the tip of the current branch of subproject?\n>    do we detach always even if the commit is at the tip?\n\nWe must not mess with random upstream branches of the submodule\njust because they happen to reference the same tip.\nThat would be too confusing.\nEither use one special branch or detach.\n\n>  - What would we do when the subproject working tree is not\n>    clean?\n\nThe same as with normal files:\nerror out if something is changed which conflicts with the requested\nupdate.\n\nWhen we have a special managed-by-supermodule branch and the submodule\nhas another branch currently checked out we can entirely ignore this\nissue.\nThis really allows the user to deliberately keep one module in an\nunclean state.\n\n>  - How can a user decide which subproject to descend into and\n>    which subproject to ignore, and how does git remember the\n>    earlier decision made by the user without asking the same\n>    again, and how does a user express \"now I want to also track\n>    that subproject I've ignored so far\" and \"now I am not\n>    interested in following that subproject anymore\"?\n\nI'd simply use explicit checkout of a submodule and removal of\nthe submodule to be a fine way to express the user's wish.\nOf course we also need some way to say: populate everything\nbelow \"src/target\" or similar.  But that is independent from\nthe rest.\n\n-- \nMartin Waitz\n"},{"id":"42812","messageId":"20070520222410.GF25462@steel.home","threadId":"8250","inReplyTo":"20070520214026.GL5412@admingilde.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-20T22:24:10Z","receivedAt":"2007-05-20T22:24:10Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Martin Waitz, Sun, May 20, 2007 23:40:26 +0200:\n> > > >  - What would we do when the subproject working tree is not\n> > > >    clean?\n> > > \n> > > I was planning on adding a --dry-run to git-checkout.\n> > > The superproject would run this in each subproject before\n> > > doing the actual checkout of the superproject.\n> > \n> > Why not do exactly what we do now? Pass \"-m\" down to it, if it was\n> > given to the top-level git-checkout.\n> \n> sounds good.\n> With submodules we have to consider one extra level of merging.\n> -m in the supermodule also means that an automatic merge of the\n> dirlink entry should be done.  Which would execute git-merge in the\n> submodule.  And merging in a dirty tree is a challenge of its own.\n\nBut it is not a merge. It is a checkout. Being another operation it\nmay even be disallow merges of subprojects. Just plainly tell user\nthat this checkout is not possible because there are changes in\nsubprojects and in the pointer to this subproject in the upper level\nsuperproject, and that the user should think about committing in\nsubproject first.\n\n> So if local changes conflict with the checkout we should just error out.\n\nOn account of it being too complex. Always a good reason.\n"},{"id":"42813","messageId":"20070520222621.GG25462@steel.home","threadId":"8250","inReplyTo":"20070520214732.GC942MdfPADPa@greensroom.kotnet.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-20T22:26:21Z","receivedAt":"2007-05-20T22:26:21Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Sven Verdoolaege, Sun, May 20, 2007 23:47:32 +0200:\n> \n> How would _you_ specify which subprojects to checkout ?\n> \n\nAren't the ones which already have .git in them are kind of specified?\n"},{"id":"42817","messageId":"20070520225252.GO5412@admingilde.org","threadId":"8250","inReplyTo":"11796842882917-git-send-email-skimo@liacs.nl","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-20T22:52:53Z","receivedAt":"2007-05-20T22:52:53Z","isPatch":false,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Sun, May 20, 2007 at 08:04:33PM +0200, skimo@liacs.nl wrote:\n> This patch series implements a mechanism for cloning submodules.\n> Each submodule is specified by a 'submodule.<submodule>.url'\n> configuration option, e.g.,\n> \n> bash-3.00$ ./git-config --remote=http://www.liacs.nl/~sverdool/isa.git --get-regexp 'submodule\\..*\\.url' \n> submodule.cloog.url /home/sverdool/public_html/cloog.git\n> submodule.cloog.url http://www.liacs.nl/~sverdool/cloog.git\n\nI really think we should try to find one standard method to\nautomatically find the right parent repository for a submodule,\nbased on the supermodules parent repository.\n\nSo e.g. that the submodule repository should stay in the same directory\nor in some special subdirectory of the supermodule or even in the\nsame object store.\nThen we can add a configuration layor on top, but there should always\nbe a sane default.\n\n\nThings we have to think about:\n * we have to cope with moving / disappearing repositories.\n * we should support bare repositories even for superprojects.\n   This can be done either by including the submodule objects in\n   the bare repository directly or by linking them (e.g. with your\n   config implementation)\n * we have to keep old submodules around forever,\n   at least when we want to be able to recover old versions.\n   Of course this is not required for all working copies as people\n   only want to have a subset of needed modules.\n   But for central synchronization repositories (probably the bare ones)\n   this is really important.\n * If you remove the whole working directory I don't want to loose any\n   data which is already committed, including submodules.\n\nThat leads to submodules which store their objects within the\nsupermodule .git directory, which would automatically obsolete the\nneed to specify explicit submodule URLs.  But I'm not quite sure\non how to really do this, despite having experimented a bit with it\n(my module3 branch should still contain some brainstorming and code).\n\n\nSo back to your code: I don't like absolute URLs in the cloneable part\nof the repository.  We should try to stay with relative ones which\ncan stay the same everywhere.\n\n-- \nMartin Waitz\n"},{"id":"42818","messageId":"20070520225521.GP5412@admingilde.org","threadId":"8250","inReplyTo":"20070520222410.GF25462@steel.home","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-20T22:55:22Z","receivedAt":"2007-05-20T22:55:22Z","isPatch":false,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Mon, May 21, 2007 at 12:24:10AM +0200, Alex Riesen wrote:\n> But it is not a merge. It is a checkout. Being another operation it\n> may even be disallow merges of subprojects. Just plainly tell user\n> that this checkout is not possible because there are changes in\n> subprojects and in the pointer to this subproject in the upper level\n> superproject, and that the user should think about committing in\n> subproject first.\n\nIf the user did commit and then you do a supermodule checkout -m you\nwill get a merge.\n\n-- \nMartin Waitz\n"},{"id":"42819","messageId":"20070520225810.GH25462@steel.home","threadId":"8250","inReplyTo":"20070520221455.GN5412@admingilde.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-20T22:58:10Z","receivedAt":"2007-05-20T22:58:10Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Martin Waitz, Mon, May 21, 2007 00:14:55 +0200:\n> >  - Do we detach HEAD if the commit named by the superproject\n> >    tree is not at the tip of the current branch of subproject?\n> >    do we detach always even if the commit is at the tip?\n> \n> We must not mess with random upstream branches of the submodule\n> just because they happen to reference the same tip.\n> That would be too confusing.\n\nStrange. The very same reason I heard when I tried to explain why\nbranches are good. The people found them confusing, just like you now.\nThey preach Perforce, too.\n\n> Either use one special branch or detach.\n\nWhy not just detach always?\n\n> >  - What would we do when the subproject working tree is not\n> >    clean?\n> \n> The same as with normal files:\n> error out if something is changed which conflicts with the requested\n> update.\n\nThis is called tree-level merge. Done by -m option (it does more than\nthat, yes, but this one too). While at it we can do file-level merge\nas well, why not?\n\n> When we have a special managed-by-supermodule branch and the submodule\n> has another branch currently checked out we can entirely ignore this\n> issue.\n\nDetached head isn't special enough?\n\n> >  - How can a user decide which subproject to descend into and\n> >    which subproject to ignore, and how does git remember the\n> >    earlier decision made by the user without asking the same\n> >    again, and how does a user express \"now I want to also track\n> >    that subproject I've ignored so far\" and \"now I am not\n> >    interested in following that subproject anymore\"?\n> \n> I'd simply use explicit checkout of a submodule and removal of\n> the submodule to be a fine way to express the user's wish.\n\nThe directory of the submodule will be back by the next\ngit-checkout-index (in the current implementation).\nNot the .git's, so yes it is a fine way to express user's wish: he\njust initialize the subprojects he wants (by whatever way).\n"},{"id":"42822","messageId":"20070520230248.GI25462@steel.home","threadId":"8250","inReplyTo":"20070520225521.GP5412@admingilde.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-20T23:02:48Z","receivedAt":"2007-05-20T23:02:48Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Martin Waitz, Mon, May 21, 2007 00:55:22 +0200:\n> hoi :)\n> \n> On Mon, May 21, 2007 at 12:24:10AM +0200, Alex Riesen wrote:\n> > But it is not a merge. It is a checkout. Being another operation it\n> > may even be disallow merges of subprojects. Just plainly tell user\n> > that this checkout is not possible because there are changes in\n> > subprojects and in the pointer to this subproject in the upper level\n> > superproject, and that the user should think about committing in\n> > subproject first.\n> \n> If the user did commit and then you do a supermodule checkout -m you\n> will get a merge.\n> \n\nOnly if the user continue to use the last branch (or the detached\nhead) the subproject was on. He don't have to, he can even return to\nthe commit which does not conflict, unless he have to complicate\nthings.\n"},{"id":"42825","messageId":"20070520231200.GR5412@admingilde.org","threadId":"8250","inReplyTo":"20070520230248.GI25462@steel.home","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-20T23:12:01Z","receivedAt":"2007-05-20T23:12:01Z","isPatch":false,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Mon, May 21, 2007 at 01:02:48AM +0200, Alex Riesen wrote:\n> > If the user did commit and then you do a supermodule checkout -m you\n> > will get a merge.\n> \n> Only if the user continue to use the last branch (or the detached\n> head) the subproject was on. He don't have to, he can even return to\n> the commit which does not conflict, unless he have to complicate\n> things.\n\njust curious:\nso you want to differenciate between a subproject HEAD which was\nset by the superproject and other ones?\n\n-- \nMartin Waitz\n"},{"id":"42828","messageId":"20070520233651.GS5412@admingilde.org","threadId":"8250","inReplyTo":"20070520225810.GH25462@steel.home","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-20T23:36:51Z","receivedAt":"2007-05-20T23:36:51Z","isPatch":false,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Mon, May 21, 2007 at 12:58:10AM +0200, Alex Riesen wrote:\n> Martin Waitz, Mon, May 21, 2007 00:14:55 +0200:\n> > >  - Do we detach HEAD if the commit named by the superproject\n> > >    tree is not at the tip of the current branch of subproject?\n> > >    do we detach always even if the commit is at the tip?\n> > \n> > We must not mess with random upstream branches of the submodule\n> > just because they happen to reference the same tip.\n> > That would be too confusing.\n> \n> Strange. The very same reason I heard when I tried to explain why\n> branches are good. The people found them confusing, just like you now.\n> They preach Perforce, too.\n\nSorry, you lost me.\n\nI didn't say that branches are bad but that guessing branch names based on\ntheir tip is bad.\n\n\n> > Either use one special branch or detach.\n> \n> Why not just detach always?\n\nWhich is just another name for \"unnamed special branch\" ;-)\nWhen you give it a name you can actually use it even after you switched\nto another one.\n\n> > >  - What would we do when the subproject working tree is not\n> > >    clean?\n> > \n> > The same as with normal files:\n> > error out if something is changed which conflicts with the requested\n> > update.\n> \n> This is called tree-level merge. Done by -m option (it does more than\n> that, yes, but this one too). While at it we can do file-level merge\n> as well, why not?\n\nIt's not that easy, for submodules we have different levels of dirty:\n * submodule HEAD matches supermodule index, but submodule working\n   directory is dirty.\n   If the submodule update would touch any modified file then it should\n   fail.\n   If used with -m (or perhaps another option? after all this merge\n   is in a submodule) then it could do the file-level merge for dirty\n   files.\n * submodule HEAD does not match supermodule index\n   normal checkout should error out if it would touch the submodule.\n   checkout -m has to merge submodule HEAD\nAnd of course:\n * index entry of submodule does not match the entry in supermodule HEAD.\n   Same as for files.\n\n\n> > When we have a special managed-by-supermodule branch and the submodule\n> > has another branch currently checked out we can entirely ignore this\n> > issue.\n> \n> Detached head isn't special enough?\n\nit's too special ;-)\n\n-- \nMartin Waitz\n"},{"id":"42830","messageId":"4650EA2E.7070204@midwinter.com","threadId":"8250","inReplyTo":"20070520195930.GX942MdfPADPa@greensroom.kotnet.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Steven Grimm","fromEmail":"koreth@midwinter.com","sentAt":"2007-05-21T00:39:10Z","receivedAt":"2007-05-21T00:39:10Z","isPatch":false,"sender":{"key":"koreth@midwinter.com","avatar":"https://gravatar.com/avatar/71b4d2e8b62f168bdc9e9205341159e3567003b4f9e2127c617c5fa0a1f5bad2?d=mp&s=160"},"body":"Sven Verdoolaege wrote:\n> It's pretty easy to add a \"submodule.*.skip\" or \"submodule.*.ignore\".\n> Since the subcloning only happens at checkout, you could set these\n> before doing a checkout.\n>   \n\nCan I take this to mean that you intend the default behavior to be to \ncheck out all subprojects, with individual ones suppressed via \nconfiguration as needed?\n\nPicture a corporate development environment with a common build system, \na couple common libraries, and a bunch of separate products. Product \ndevelopers will want to check out the build system (which would perhaps \nbe in the superproject), the libraries they need, and their own product. \nThey will rarely want to check out the other products, which could \naccount for the vast majority of the subprojects, and certainly won't \nwant to have to keep track of which new subprojects are appearing so \nthey can add those to the exclude list.\n\nIn other words, \"I want the superproject and these four subprojects and \nnothing else\" should be a well-supported mode of operation. In many \ncases developers will already know at clone time exactly what they want.\n\nIf I'm misunderstanding your intent, then never mind. :)\n\n-Steve\n"},{"id":"42869","messageId":"20070521085419.GG942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"20070520225252.GO5412@admingilde.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-21T08:54:19Z","receivedAt":"2007-05-21T08:54:19Z","isPatch":false,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Mon, May 21, 2007 at 12:52:53AM +0200, Martin Waitz wrote:\n> That leads to submodules which store their objects within the\n> supermodule .git directory,\n\nMy code clones submodules in .git/submodules/<submodule>, so\nthat could be a good default.\n\n> which would automatically obsolete the\n> need to specify explicit submodule URLs.\n\nAbsolutely not.  The subproject will likely have a life of its own.\nIf you export it on the same machine, then why would you have two\ndifferent URLs for the same project?\nAlso, the subproject will typically not even be on the same site,\nso you _have_ to be able to specify a submodule URL.\n(I noticed that I forgot the \"git://\" protocol; I'll add that in\nthe next round.)\n\n> So back to your code: I don't like absolute URLs in the cloneable part\n> of the repository.  We should try to stay with relative ones which\n> can stay the same everywhere.\n\nThe problem with relative paths is that you don't know if the\nURL the user gave you points to the working directory or the\ngit directory of the project, but I guess I can let dump-config\ntell you where it found the config file.\n\nskimo\n"},{"id":"42877","messageId":"20070521095749.GI942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"20070520222621.GG25462@steel.home","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-21T09:57:49Z","receivedAt":"2007-05-21T09:57:49Z","isPatch":false,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Mon, May 21, 2007 at 12:26:21AM +0200, Alex Riesen wrote:\n> Sven Verdoolaege, Sun, May 20, 2007 23:47:32 +0200:\n> > \n> > How would _you_ specify which subprojects to checkout ?\n> > \n> \n> Aren't the ones which already have .git in them are kind of specified?\n> \n\nWould you always recurse into these submodules, regardless of\nany option?\nOr would you want two options, one for handling the submodules\nyou have explicitly marked someway and one for getting all submodules?\n\nskimo\n"},{"id":"42878","messageId":"20070521100146.GJ942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"4650EA2E.7070204@midwinter.com","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-21T10:01:46Z","receivedAt":"2007-05-21T10:01:46Z","isPatch":false,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Sun, May 20, 2007 at 05:39:10PM -0700, Steven Grimm wrote:\n> Sven Verdoolaege wrote:\n> >It's pretty easy to add a \"submodule.*.skip\" or \"submodule.*.ignore\".\n> >Since the subcloning only happens at checkout, you could set these\n> >before doing a checkout.\n> >  \n> \n> Can I take this to mean that you intend the default behavior to be to \n> check out all subprojects, with individual ones suppressed via \n> configuration as needed?\n\nOr we could have a tri-state variable, with \"yes\" meaning handle\nthe submodule, \"no\" don't, and undefined meaning do whatever is\nspecified by the global submodules option.\nExplicitly checking out a submodule could then set the variable to \"yes\".\n\nskimo\n"},{"id":"42879","messageId":"20070521100716.GX5412@admingilde.org","threadId":"8250","inReplyTo":"20070521085419.GG942MdfPADPa@greensroom.kotnet.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-21T10:07:16Z","receivedAt":"2007-05-21T10:07:16Z","isPatch":false,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Mon, May 21, 2007 at 10:54:19AM +0200, Sven Verdoolaege wrote:\n> On Mon, May 21, 2007 at 12:52:53AM +0200, Martin Waitz wrote:\n> > That leads to submodules which store their objects within the\n> > supermodule .git directory,\n> \n> My code clones submodules in .git/submodules/<submodule>, so\n> that could be a good default.\n\ngood.\n\n> > which would automatically obsolete the\n> > need to specify explicit submodule URLs.\n> \n> Absolutely not.  The subproject will likely have a life of its own.\n> If you export it on the same machine, then why would you have two\n> different URLs for the same project?\n> Also, the subproject will typically not even be on the same site,\n> so you _have_ to be able to specify a submodule URL.\n> (I noticed that I forgot the \"git://\" protocol; I'll add that in\n> the next round.)\n\nTypically, you have to keep it on the same site because you have\nsome local adaptions which are only ment to be included within the\nsuperproject.  Think about distributions which seldomly use upstream\nsoftware completely unmodified.\nBeing able to configure it for other URLs is nice but by default it\nshould work without.\n\n> > So back to your code: I don't like absolute URLs in the cloneable part\n> > of the repository.  We should try to stay with relative ones which\n> > can stay the same everywhere.\n> \n> The problem with relative paths is that you don't know if the\n> URL the user gave you points to the working directory or the\n> git directory of the project, but I guess I can let dump-config\n> tell you where it found the config file.\n\nWe have already solved that in clone & fetch so I don't think this is a\nreal problem.\n\n-- \nMartin Waitz\n"},{"id":"42880","messageId":"20070521101455.GK942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"20070521100716.GX5412@admingilde.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-21T10:14:55Z","receivedAt":"2007-05-21T10:14:55Z","isPatch":false,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Mon, May 21, 2007 at 12:07:16PM +0200, Martin Waitz wrote:\n> > The problem with relative paths is that you don't know if the\n> > URL the user gave you points to the working directory or the\n> > git directory of the project, but I guess I can let dump-config\n> > tell you where it found the config file.\n> \n> We have already solved that in clone & fetch so I don't think this is a\n> real problem.\n\nHow?  AFAICS, it's upload-pack of the *clonee* that determines\nwhere the actual git dir is.  The cloner has no clue.\n\nskimo\n"},{"id":"42882","messageId":"200705211244.16374.Josef.Weidendorfer@gmx.de","threadId":"8250","inReplyTo":"20070521095749.GI942MdfPADPa@greensroom.kotnet.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Josef Weidendorfer","fromEmail":"josef.weidendorfer@gmx.de","sentAt":"2007-05-21T10:44:16Z","receivedAt":"2007-05-21T10:44:16Z","isPatch":false,"sender":{"key":"josef.weidendorfer@gmx.de","avatar":null},"body":"On Monday 21 May 2007, Sven Verdoolaege wrote:\n> On Mon, May 21, 2007 at 12:26:21AM +0200, Alex Riesen wrote:\n> > Sven Verdoolaege, Sun, May 20, 2007 23:47:32 +0200:\n> > > \n> > > How would _you_ specify which subprojects to checkout ?\n> > > \n> > \n> > Aren't the ones which already have .git in them are kind of specified?\n> > \n> \n> Would you always recurse into these submodules, regardless of\n> any option?\n> Or would you want two options, one for handling the submodules\n> you have explicitly marked someway and one for getting all submodules?\n\nThere should be a way for a superproject to specify useful sets of\nsubprojects for different developer roles, and these sets should be\nversioned. It is also useful for a superproject to be able to say\n\"for this subproject to work, that other subprojects needs to be\nchecked out\".\n\nBoth issues could be supported with a \"dependson\" setting in .gitmodules\n(or better call this file \".gitprojects\"?)\n\n [subproject \"german-translation\"]\n    path = lang/german\n    dependson = docbuilds\n\n [subproject \"all-translations\"]\n    dependson = german-translation france-translation japanese-translation \n\nThe syntax here only is RFC, including the fact that this example\nputs the subproject identifier into the key, and the path as config.\nIf we do not go the .gitattributes way, IMHO this is more logical.\n\nWhen cloning, one should be allowed to specify the subprojects one wants\nto track, e.g.\n\n git-clone --subproject=all-translations ...\n\nJosef\n"},{"id":"42884","messageId":"20070521113415.GY5412@admingilde.org","threadId":"8250","inReplyTo":"20070521101455.GK942MdfPADPa@greensroom.kotnet.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-21T11:34:15Z","receivedAt":"2007-05-21T11:34:15Z","isPatch":false,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Mon, May 21, 2007 at 12:14:55PM +0200, Sven Verdoolaege wrote:\n> How?  AFAICS, it's upload-pack of the *clonee* that determines\n> where the actual git dir is.  The cloner has no clue.\n\nwe can just store the link to the workdir-or-gitdir and then try\nit out every time we access it.  When clone stores the location\nof the parent repository it doesn't know what it points to, but\nfetch works, too.\n\n-- \nMartin Waitz\n"},{"id":"42886","messageId":"20070521114157.GZ5412@admingilde.org","threadId":"8250","inReplyTo":"200705211244.16374.Josef.Weidendorfer@gmx.de","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-21T11:41:57Z","receivedAt":"2007-05-21T11:41:57Z","isPatch":false,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Mon, May 21, 2007 at 12:44:16PM +0200, Josef Weidendorfer wrote:\n> There should be a way for a superproject to specify useful sets of\n> subprojects for different developer roles, and these sets should be\n> versioned. It is also useful for a superproject to be able to say\n> \"for this subproject to work, that other subprojects needs to be\n> checked out\".\n\nWhat subprojects to use is the responsibility of the build system and\nwe should not step on its shoes too much.\nWe should provide a simple way to populate a submodule, but all the\ndependency handling should really be done in the build system /\npackage handling system on top of git, IMHO.\n\nPerhaps we can simply provide \"cd $subproject && git clone\" to\nautomatically fetch all needed stuff from a default location and\ncheckout that subproject.\nThen we can integrate that command in bitbake and whatnot or start\na new configuration management system on top of git which uses\ndependencies from Makefiles etc. to automatically check out the\nright set of subprojects.  But that should really be on top of git.\n\n-- \nMartin Waitz\n"},{"id":"42889","messageId":"20070521121929.GM942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"20070521113415.GY5412@admingilde.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-21T12:19:29Z","receivedAt":"2007-05-21T12:19:29Z","isPatch":false,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Mon, May 21, 2007 at 01:34:15PM +0200, Martin Waitz wrote:\n> hoi :)\n> \n> On Mon, May 21, 2007 at 12:14:55PM +0200, Sven Verdoolaege wrote:\n> > How?  AFAICS, it's upload-pack of the *clonee* that determines\n> > where the actual git dir is.  The cloner has no clue.\n> \n> we can just store the link to the workdir-or-gitdir and then try\n> it out every time we access it.  When clone stores the location\n> of the parent repository it doesn't know what it points to, but\n> fetch works, too.\n\nclone is just init + fetch (well, almost).\nThe comment above applies to fetching as well.\n\nskimo\n"},{"id":"42998","messageId":"20070522215423.GI30871@steel.home","threadId":"8250","inReplyTo":"20070520231200.GR5412@admingilde.org","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-22T21:54:23Z","receivedAt":"2007-05-22T21:54:23Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Martin Waitz, Mon, May 21, 2007 01:12:01 +0200:\n> On Mon, May 21, 2007 at 01:02:48AM +0200, Alex Riesen wrote:\n> > > If the user did commit and then you do a supermodule checkout -m you\n> > > will get a merge.\n> > \n> > Only if the user continue to use the last branch (or the detached\n> > head) the subproject was on. He don't have to, he can even return to\n> > the commit which does not conflict, unless he have to complicate\n> > things.\n> \n> just curious:\n> so you want to differenciate between a subproject HEAD which was\n> set by the superproject and other ones?\n\nNo. Why do you think that I want to do that?\n"},{"id":"42999","messageId":"20070522215659.GJ30871@steel.home","threadId":"8250","inReplyTo":"4650EA2E.7070204@midwinter.com","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-22T21:56:59Z","receivedAt":"2007-05-22T21:56:59Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Steven Grimm, Mon, May 21, 2007 02:39:10 +0200:\n> Sven Verdoolaege wrote:\n> >It's pretty easy to add a \"submodule.*.skip\" or \"submodule.*.ignore\".\n> >Since the subcloning only happens at checkout, you could set these\n> >before doing a checkout.\n> >  \n> \n> Can I take this to mean that you intend the default behavior to be to \n> check out all subprojects, with individual ones suppressed via \n> configuration as needed?\n\nNeither fetch nor checkout none of them and leave the subproject\nfetch+checkout as exercise to the user?\n"},{"id":"43136","messageId":"20070524132909.GR942MdfPADPa@greensroom.kotnet.org","threadId":"8250","inReplyTo":"20070520211850.GJ5412@admingilde.org","subject":"Re: [PATCH 09/15] entry.c: optionally checkout submodules","fromName":"Sven Verdoolaege","fromEmail":"skimo@kotnet.org","sentAt":"2007-05-24T13:29:09Z","receivedAt":"2007-05-24T13:29:09Z","isPatch":true,"sender":{"key":"skimo@kotnet.org","avatar":null},"body":"On Sun, May 20, 2007 at 11:18:50PM +0200, Martin Waitz wrote:\n> hoi :)\n> \n> have you seen my patch to checkout submodules?\n> \n> The submodule checkout should really check that the requested commit\n> is really available and have some other path for creating submodules\n> which are not currently checked out / able to be checked out.\n\nIf you are talking about your May 5th patch, then you weren't doing\nthat either.  You just checked if it _looked_ like a SHA1.\n\nI check for the presence of the commit by calling git-cat-file.\nOf course, this doesn't guarantee that the whole tree is available.\n\nskimo\n"},{"id":"43148","messageId":"20070524155616.GM5412@admingilde.org","threadId":"8250","inReplyTo":"20070522215423.GI30871@steel.home","subject":"Re: [RFC] Third round of support for cloning submodules","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2007-05-24T15:56:16Z","receivedAt":"2007-05-24T15:56:16Z","isPatch":false,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Tue, May 22, 2007 at 11:54:23PM +0200, Alex Riesen wrote:\n> Martin Waitz, Mon, May 21, 2007 01:12:01 +0200:\n> > On Mon, May 21, 2007 at 01:02:48AM +0200, Alex Riesen wrote:\n> > > > If the user did commit and then you do a supermodule checkout -m you\n> > > > will get a merge.\n> > > \n> > > Only if the user continue to use the last branch (or the detached\n> > > head) the subproject was on. He don't have to, he can even return to\n> > > the commit which does not conflict, unless he have to complicate\n> > > things.\n> > \n> > just curious:\n> > so you want to differenciate between a subproject HEAD which was\n> > set by the superproject and other ones?\n> \n> No. Why do you think that I want to do that?\n\nI think I simply was too tired to read. ;-)\n\nYour 'Only if the user continues to use...' suggested that he has a\ndifferent option, namely going to a branch which is not controlled\nby the superproject.\n\nAnd of course the user can go back to another commit, after checkout -m\ncreated a merge... ;-)\n\n-- \nMartin Waitz\n"}]}