From 1149ee214e6b9e2450f817a808f74e4e761e7295 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 28 Apr 2016 09:36:37 -0400 Subject: t5550: fix typo in $HTTPD_URL Commit 14111fc (git: submodule honor -c credential.* from command line, 2016-02-29) accidentally wrote $HTTP_URL. It happened to work because we ended up with "credential..helper", which we treat the same as "credential.helper", applying it to all URLs. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index 48e2ab6..81cc57f 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -103,7 +103,7 @@ test_expect_success 'cmdline credential config passes into submodules' ' test_must_fail git clone --recursive super super-clone && rm -rf super-clone && set_askpass wrong pass@host && - git -c "credential.$HTTP_URL.username=user@host" \ + git -c "credential.$HTTPD_URL.username=user@host" \ clone --recursive super super-clone && expect_askpass pass user@host ' -- cgit v0.10.2-6-g49f6 From 455d22c1c6abc19693beb8a25bc3d976290d6b84 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 28 Apr 2016 09:37:04 -0400 Subject: t5550: break submodule config test into multiple sub-tests Right now we test only the cloning case, but there are other interesting cases (e.g., fetching). Let's pull the setup bits into their own test, which will make things flow more logically once we start adding more tests which use the setup. Let's also introduce some whitespace to the clone-test to split the two parts: making sure it fails without our cmdline config, and that it succeeds with it. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index 81cc57f..e8e91bb 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -91,17 +91,21 @@ test_expect_success 'configured username does not override URL' ' expect_askpass pass user@host ' -test_expect_success 'cmdline credential config passes into submodules' ' +test_expect_success 'set up repo with http submodules' ' git init super && set_askpass user@host pass@host && ( cd super && git submodule add "$HTTPD_URL/auth/dumb/repo.git" sub && git commit -m "add submodule" - ) && + ) +' + +test_expect_success 'cmdline credential config passes to submodule via clone' ' set_askpass wrong pass@host && test_must_fail git clone --recursive super super-clone && rm -rf super-clone && + set_askpass wrong pass@host && git -c "credential.$HTTPD_URL.username=user@host" \ clone --recursive super super-clone && -- cgit v0.10.2-6-g49f6 From 860cba61a3eac38151fd203547df7515023303e9 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 28 Apr 2016 09:37:44 -0400 Subject: submodule: export sanitized GIT_CONFIG_PARAMETERS Commit 14111fc (git: submodule honor -c credential.* from command line, 2016-02-29) taught git-submodule.sh to save the sanitized value of $GIT_CONFIG_PARAMETERS when clearing the environment for a submodule. However, it failed to export the result, meaning that it had no effect for any sub-programs. We didn't catch this in our initial tests because we checked only the "clone" case, which does not go through the shell script at all. Provoking "git submodule update" to do a fetch demonstrates the bug. Noticed-by: Lars Schneider Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/git-submodule.sh b/git-submodule.sh index 1f132b4..91f5856 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -200,6 +200,7 @@ sanitize_submodule_env() sanitized_config=$(git submodule--helper sanitize-config) clear_local_git_env GIT_CONFIG_PARAMETERS=$sanitized_config + export GIT_CONFIG_PARAMETERS } # diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index e8e91bb..13ac788 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -112,6 +112,23 @@ test_expect_success 'cmdline credential config passes to submodule via clone' ' expect_askpass pass user@host ' +test_expect_success 'cmdline credential config passes submodule update' ' + # advance the submodule HEAD so that a fetch is required + git commit --allow-empty -m foo && + git push "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/repo.git" HEAD && + sha1=$(git rev-parse HEAD) && + git -C super-clone update-index --cacheinfo 160000,$sha1,sub && + + set_askpass wrong pass@host && + test_must_fail git -C super-clone submodule update && + + set_askpass wrong pass@host && + git -C super-clone \ + -c "credential.$HTTPD_URL.username=user@host" \ + submodule update && + expect_askpass pass user@host +' + test_expect_success 'fetch changes via http' ' echo content >>file && git commit -a -m two && -- cgit v0.10.2-6-g49f6 From 4638728c632e59715b7346ddeca83528d37a4894 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 28 Apr 2016 09:38:20 -0400 Subject: submodule--helper: move config-sanitizing to submodule.c These functions should be used by any code which spawns a submodule process, which may happen in submodule.c (e.g., for spawning fetch). Let's move them there and make them public so that submodule--helper can continue to use them. Since they're now public, let's also provide a basic overview of their intended use. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 3d37c3f..16d6432 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -125,54 +125,6 @@ static int module_name(int argc, const char **argv, const char *prefix) return 0; } -/* - * Rules to sanitize configuration variables that are Ok to be passed into - * submodule operations from the parent project using "-c". Should only - * include keys which are both (a) safe and (b) necessary for proper - * operation. - */ -static int submodule_config_ok(const char *var) -{ - if (starts_with(var, "credential.")) - return 1; - return 0; -} - -static int sanitize_submodule_config(const char *var, const char *value, void *data) -{ - struct strbuf *out = data; - - if (submodule_config_ok(var)) { - if (out->len) - strbuf_addch(out, ' '); - - if (value) - sq_quotef(out, "%s=%s", var, value); - else - sq_quote_buf(out, var); - } - - return 0; -} - -static void prepare_submodule_repo_env(struct argv_array *out) -{ - const char * const *var; - - for (var = local_repo_env; *var; var++) { - if (!strcmp(*var, CONFIG_DATA_ENVIRONMENT)) { - struct strbuf sanitized_config = STRBUF_INIT; - git_config_from_parameters(sanitize_submodule_config, - &sanitized_config); - argv_array_pushf(out, "%s=%s", *var, sanitized_config.buf); - strbuf_release(&sanitized_config); - } else { - argv_array_push(out, *var); - } - } - -} - static int clone_submodule(const char *path, const char *gitdir, const char *url, const char *depth, const char *reference, int quiet) { diff --git a/submodule.c b/submodule.c index b83939c..24e8182 100644 --- a/submodule.c +++ b/submodule.c @@ -13,6 +13,7 @@ #include "argv-array.h" #include "blob.h" #include "thread-utils.h" +#include "quote.h" static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND; static struct string_list changed_submodule_paths; @@ -1097,3 +1098,50 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir) strbuf_release(&rel_path); free((void *)real_work_tree); } +/* + * Rules to sanitize configuration variables that are Ok to be passed into + * submodule operations from the parent project using "-c". Should only + * include keys which are both (a) safe and (b) necessary for proper + * operation. + */ +static int submodule_config_ok(const char *var) +{ + if (starts_with(var, "credential.")) + return 1; + return 0; +} + +int sanitize_submodule_config(const char *var, const char *value, void *data) +{ + struct strbuf *out = data; + + if (submodule_config_ok(var)) { + if (out->len) + strbuf_addch(out, ' '); + + if (value) + sq_quotef(out, "%s=%s", var, value); + else + sq_quote_buf(out, var); + } + + return 0; +} + +void prepare_submodule_repo_env(struct argv_array *out) +{ + const char * const *var; + + for (var = local_repo_env; *var; var++) { + if (!strcmp(*var, CONFIG_DATA_ENVIRONMENT)) { + struct strbuf sanitized_config = STRBUF_INIT; + git_config_from_parameters(sanitize_submodule_config, + &sanitized_config); + argv_array_pushf(out, "%s=%s", *var, sanitized_config.buf); + strbuf_release(&sanitized_config); + } else { + argv_array_push(out, *var); + } + } + +} diff --git a/submodule.h b/submodule.h index e06eaa5..48690b1 100644 --- a/submodule.h +++ b/submodule.h @@ -43,4 +43,20 @@ int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_nam int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name); void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir); +/* + * This function is intended as a callback for use with + * git_config_from_parameters(). It ignores any config options which + * are not suitable for passing along to a submodule, and accumulates the rest + * in "data", which must be a pointer to a strbuf. The end result can + * be put into $GIT_CONFIG_PARAMETERS for passing to a sub-process. + */ +int sanitize_submodule_config(const char *var, const char *value, void *data); + +/* + * Prepare the "env_array" parameter of a "struct child_process" for executing + * a submodule by clearing any repo-specific envirionment variables, but + * retaining any config approved by sanitize_submodule_config(). + */ +void prepare_submodule_repo_env(struct argv_array *out); + #endif -- cgit v0.10.2-6-g49f6 From c12e8656700be6084aec49df66447e701fda1ecf Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 28 Apr 2016 09:39:15 -0400 Subject: submodule: use prepare_submodule_repo_env consistently Before 14111fc (git: submodule honor -c credential.* from command line, 2016-02-29), it was sufficient for code which spawned a process in a submodule to just set the child process's "env" field to "local_repo_env" to clear the environment of any repo-specific variables. That commit introduced a more complicated procedure, in which we clear most variables but allow through sanitized config. For C code, we used that procedure only for cloning, but not for any of the programs spawned by submodule.c. As a result, things like "git fetch --recurse-submodules" behave differently than "git clone --recursive"; the former will not pass through the sanitized config. We can fix this by using prepare_submodule_repo_env() everywhere in submodule.c. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/submodule.c b/submodule.c index 24e8182..c18ab9b 100644 --- a/submodule.c +++ b/submodule.c @@ -367,7 +367,7 @@ static int submodule_needs_pushing(const char *path, const unsigned char sha1[20 argv[1] = sha1_to_hex(sha1); cp.argv = argv; - cp.env = local_repo_env; + prepare_submodule_repo_env(&cp.env_array); cp.git_cmd = 1; cp.no_stdin = 1; cp.out = -1; @@ -454,7 +454,7 @@ static int push_submodule(const char *path) const char *argv[] = {"push", NULL}; cp.argv = argv; - cp.env = local_repo_env; + prepare_submodule_repo_env(&cp.env_array); cp.git_cmd = 1; cp.no_stdin = 1; cp.dir = path; @@ -500,7 +500,7 @@ static int is_submodule_commit_present(const char *path, unsigned char sha1[20]) argv[3] = sha1_to_hex(sha1); cp.argv = argv; - cp.env = local_repo_env; + prepare_submodule_repo_env(&cp.env_array); cp.git_cmd = 1; cp.no_stdin = 1; cp.dir = path; @@ -683,7 +683,7 @@ static int get_next_submodule(struct child_process *cp, if (is_directory(git_dir)) { child_process_init(cp); cp->dir = strbuf_detach(&submodule_path, NULL); - cp->env = local_repo_env; + prepare_submodule_repo_env(&cp->env_array); cp->git_cmd = 1; if (!spf->quiet) strbuf_addf(err, "Fetching submodule %s%s\n", @@ -796,7 +796,7 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked) argv[2] = "-uno"; cp.argv = argv; - cp.env = local_repo_env; + prepare_submodule_repo_env(&cp.env_array); cp.git_cmd = 1; cp.no_stdin = 1; cp.out = -1; @@ -857,7 +857,7 @@ int submodule_uses_gitfile(const char *path) /* Now test that all nested submodules use a gitfile too */ cp.argv = argv; - cp.env = local_repo_env; + prepare_submodule_repo_env(&cp.env_array); cp.git_cmd = 1; cp.no_stdin = 1; cp.no_stderr = 1; @@ -890,7 +890,7 @@ int ok_to_remove_submodule(const char *path) return 0; cp.argv = argv; - cp.env = local_repo_env; + prepare_submodule_repo_env(&cp.env_array); cp.git_cmd = 1; cp.no_stdin = 1; cp.out = -1; diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index 13ac788..3484b6f 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -112,6 +112,17 @@ test_expect_success 'cmdline credential config passes to submodule via clone' ' expect_askpass pass user@host ' +test_expect_success 'cmdline credential config passes submodule via fetch' ' + set_askpass wrong pass@host && + test_must_fail git -C super-clone fetch --recurse-submodules && + + set_askpass wrong pass@host && + git -C super-clone \ + -c "credential.$HTTPD_URL.username=user@host" \ + fetch --recurse-submodules && + expect_askpass pass user@host +' + test_expect_success 'cmdline credential config passes submodule update' ' # advance the submodule HEAD so that a fetch is required git commit --allow-empty -m foo && -- cgit v0.10.2-6-g49f6 From 89044baa8b8a14b48e78a42ebdc43cfcd144ce28 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 4 May 2016 21:22:19 -0400 Subject: submodule: stop sanitizing config options The point of having a whitelist of command-line config options to pass to submodules was two-fold: 1. It prevented obvious nonsense like using core.worktree for multiple repos. 2. It could prevent surprise when the user did not mean for the options to leak to the submodules (e.g., http.sslverify=false). For case 1, the answer is mostly "if it hurts, don't do that". For case 2, we can note that any such example has a matching inverted surprise (e.g., a user who meant http.sslverify=true to apply everywhere, but it didn't). So this whitelist is probably not giving us any benefit, and is already creating a hassle as people propose things to put on it. Let's just drop it entirely. Note that we still need to keep a special code path for "prepare the submodule environment", because we still have to take care to pass through $GIT_CONFIG_PARAMETERS (and block the rest of the repo-specific environment variables). We can do this easily from within the submodule shell script, which lets us drop the submodule--helper option entirely (and it's OK to do so because as a "--" program, it is entirely a private implementation detail). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 16d6432..89250f0 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -260,22 +260,6 @@ static int module_clone(int argc, const char **argv, const char *prefix) return 0; } -static int module_sanitize_config(int argc, const char **argv, const char *prefix) -{ - struct strbuf sanitized_config = STRBUF_INIT; - - if (argc > 1) - usage(_("git submodule--helper sanitize-config")); - - git_config_from_parameters(sanitize_submodule_config, &sanitized_config); - if (sanitized_config.len) - printf("%s\n", sanitized_config.buf); - - strbuf_release(&sanitized_config); - - return 0; -} - struct cmd_struct { const char *cmd; int (*fn)(int, const char **, const char *); @@ -285,7 +269,6 @@ static struct cmd_struct commands[] = { {"list", module_list}, {"name", module_name}, {"clone", module_clone}, - {"sanitize-config", module_sanitize_config}, }; int cmd_submodule__helper(int argc, const char **argv, const char *prefix) diff --git a/git-submodule.sh b/git-submodule.sh index 91f5856..b1c056c 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -197,9 +197,9 @@ isnumber() # of the settings from GIT_CONFIG_PARAMETERS. sanitize_submodule_env() { - sanitized_config=$(git submodule--helper sanitize-config) + save_config=$GIT_CONFIG_PARAMETERS clear_local_git_env - GIT_CONFIG_PARAMETERS=$sanitized_config + GIT_CONFIG_PARAMETERS=$save_config export GIT_CONFIG_PARAMETERS } diff --git a/submodule.c b/submodule.c index c18ab9b..d598881 100644 --- a/submodule.c +++ b/submodule.c @@ -1098,50 +1098,13 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir) strbuf_release(&rel_path); free((void *)real_work_tree); } -/* - * Rules to sanitize configuration variables that are Ok to be passed into - * submodule operations from the parent project using "-c". Should only - * include keys which are both (a) safe and (b) necessary for proper - * operation. - */ -static int submodule_config_ok(const char *var) -{ - if (starts_with(var, "credential.")) - return 1; - return 0; -} - -int sanitize_submodule_config(const char *var, const char *value, void *data) -{ - struct strbuf *out = data; - - if (submodule_config_ok(var)) { - if (out->len) - strbuf_addch(out, ' '); - - if (value) - sq_quotef(out, "%s=%s", var, value); - else - sq_quote_buf(out, var); - } - - return 0; -} void prepare_submodule_repo_env(struct argv_array *out) { const char * const *var; for (var = local_repo_env; *var; var++) { - if (!strcmp(*var, CONFIG_DATA_ENVIRONMENT)) { - struct strbuf sanitized_config = STRBUF_INIT; - git_config_from_parameters(sanitize_submodule_config, - &sanitized_config); - argv_array_pushf(out, "%s=%s", *var, sanitized_config.buf); - strbuf_release(&sanitized_config); - } else { + if (strcmp(*var, CONFIG_DATA_ENVIRONMENT)) argv_array_push(out, *var); - } } - } diff --git a/submodule.h b/submodule.h index 48690b1..869d259 100644 --- a/submodule.h +++ b/submodule.h @@ -44,18 +44,9 @@ int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_nam void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir); /* - * This function is intended as a callback for use with - * git_config_from_parameters(). It ignores any config options which - * are not suitable for passing along to a submodule, and accumulates the rest - * in "data", which must be a pointer to a strbuf. The end result can - * be put into $GIT_CONFIG_PARAMETERS for passing to a sub-process. - */ -int sanitize_submodule_config(const char *var, const char *value, void *data); - -/* * Prepare the "env_array" parameter of a "struct child_process" for executing * a submodule by clearing any repo-specific envirionment variables, but - * retaining any config approved by sanitize_submodule_config(). + * retaining any config in the environment. */ void prepare_submodule_repo_env(struct argv_array *out); diff --git a/t/t7412-submodule--helper.sh b/t/t7412-submodule--helper.sh deleted file mode 100755 index 149d428..0000000 --- a/t/t7412-submodule--helper.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2016 Jacob Keller -# - -test_description='Basic plumbing support of submodule--helper - -This test verifies the submodule--helper plumbing command used to implement -git-submodule. -' - -. ./test-lib.sh - -test_expect_success 'sanitize-config clears configuration' ' - git -c user.name="Some User" submodule--helper sanitize-config >actual && - test_must_be_empty actual -' - -sq="'" -test_expect_success 'sanitize-config keeps credential.helper' ' - git -c credential.helper=helper submodule--helper sanitize-config >actual && - echo "${sq}credential.helper=helper${sq}" >expect && - test_cmp expect actual -' - -test_done -- cgit v0.10.2-6-g49f6