Skip to content

Commit abd3b0f

Browse files
committed
Merge commit 'extra-http-headers'
Signed-off-by: Johannes Schindelin <[email protected]>
2 parents 696b363 + f25905b commit abd3b0f

15 files changed

+242
-28
lines changed

Documentation/config.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,6 +1675,12 @@ http.emptyAuth::
16751675
a username in the URL, as libcurl normally requires a username for
16761676
authentication.
16771677

1678+
http.extraHeader::
1679+
Pass an additional HTTP header when communicating with a server. If
1680+
more than one such entry exists, all of them are added as extra
1681+
headers. To allow overriding the settings inherited from the system
1682+
config, an empty value will reset the extra headers to the empty list.
1683+
16781684
http.cookieFile::
16791685
File containing previously stored cookie lines which should be used
16801686
in the Git http session, if they match the server. The file format

builtin/submodule--helper.c

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,56 @@ static int module_name(int argc, const char **argv, const char *prefix)
118118

119119
return 0;
120120
}
121+
122+
/*
123+
* Rules to sanitize configuration variables that are Ok to be passed into
124+
* submodule operations from the parent project using "-c". Should only
125+
* include keys which are both (a) safe and (b) necessary for proper
126+
* operation.
127+
*/
128+
static int submodule_config_ok(const char *var)
129+
{
130+
if (starts_with(var, "credential.") ||
131+
(starts_with(var, "http.") && ends_with(var, ".extraheader")))
132+
return 1;
133+
return 0;
134+
}
135+
136+
static int sanitize_submodule_config(const char *var, const char *value, void *data)
137+
{
138+
struct strbuf *out = data;
139+
140+
if (submodule_config_ok(var)) {
141+
if (out->len)
142+
strbuf_addch(out, ' ');
143+
144+
if (value)
145+
sq_quotef(out, "%s=%s", var, value);
146+
else
147+
sq_quote_buf(out, var);
148+
}
149+
150+
return 0;
151+
}
152+
153+
static void prepare_submodule_repo_env(struct argv_array *out)
154+
{
155+
const char * const *var;
156+
157+
for (var = local_repo_env; *var; var++) {
158+
if (!strcmp(*var, CONFIG_DATA_ENVIRONMENT)) {
159+
struct strbuf sanitized_config = STRBUF_INIT;
160+
git_config_from_parameters(sanitize_submodule_config,
161+
&sanitized_config);
162+
argv_array_pushf(out, "%s=%s", *var, sanitized_config.buf);
163+
strbuf_release(&sanitized_config);
164+
} else {
165+
argv_array_push(out, *var);
166+
}
167+
}
168+
169+
}
170+
121171
static int clone_submodule(const char *path, const char *gitdir, const char *url,
122172
const char *depth, const char *reference, int quiet)
123173
{
@@ -139,7 +189,7 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
139189
argv_array_push(&cp.args, path);
140190

141191
cp.git_cmd = 1;
142-
cp.env = local_repo_env;
192+
prepare_submodule_repo_env(&cp.env_array);
143193
cp.no_stdin = 1;
144194

145195
return run_command(&cp);
@@ -180,14 +230,18 @@ static int module_clone(int argc, const char **argv, const char *prefix)
180230

181231
const char *const git_submodule_helper_usage[] = {
182232
N_("git submodule--helper clone [--prefix=<path>] [--quiet] "
183-
"[--reference <repository>] [--name <name>] [--url <url>]"
184-
"[--depth <depth>] [--] [<path>...]"),
233+
"[--reference <repository>] [--name <name>] [--depth <depth>] "
234+
"--url <url> --path <path>"),
185235
NULL
186236
};
187237

188238
argc = parse_options(argc, argv, prefix, module_clone_options,
189239
git_submodule_helper_usage, 0);
190240

241+
if (argc || !url || !path)
242+
usage_with_options(git_submodule_helper_usage,
243+
module_clone_options);
244+
191245
strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name);
192246
sm_gitdir = strbuf_detach(&sb, NULL);
193247

@@ -249,6 +303,22 @@ static int module_clone(int argc, const char **argv, const char *prefix)
249303
return 0;
250304
}
251305

306+
static int module_sanitize_config(int argc, const char **argv, const char *prefix)
307+
{
308+
struct strbuf sanitized_config = STRBUF_INIT;
309+
310+
if (argc > 1)
311+
usage(_("git submodule--helper sanitize-config"));
312+
313+
git_config_from_parameters(sanitize_submodule_config, &sanitized_config);
314+
if (sanitized_config.len)
315+
printf("%s\n", sanitized_config.buf);
316+
317+
strbuf_release(&sanitized_config);
318+
319+
return 0;
320+
}
321+
252322
struct cmd_struct {
253323
const char *cmd;
254324
int (*fn)(int, const char **, const char *);
@@ -258,6 +328,7 @@ static struct cmd_struct commands[] = {
258328
{"list", module_list},
259329
{"name", module_name},
260330
{"clone", module_clone},
331+
{"sanitize-config", module_sanitize_config},
261332
};
262333

263334
int cmd_submodule__helper(int argc, const char **argv, const char *prefix)

config.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ void git_config_push_parameter(const char *text)
162162
{
163163
struct strbuf env = STRBUF_INIT;
164164
const char *old = getenv(CONFIG_DATA_ENVIRONMENT);
165-
if (old) {
165+
if (old && *old) {
166166
strbuf_addstr(&env, old);
167167
strbuf_addch(&env, ' ');
168168
}

git-submodule.sh

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,16 @@ isnumber()
192192
n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
193193
}
194194

195+
# Sanitize the local git environment for use within a submodule. We
196+
# can't simply use clear_local_git_env since we want to preserve some
197+
# of the settings from GIT_CONFIG_PARAMETERS.
198+
sanitize_submodule_env()
199+
{
200+
sanitized_config=$(git submodule--helper sanitize-config)
201+
clear_local_git_env
202+
GIT_CONFIG_PARAMETERS=$sanitized_config
203+
}
204+
195205
#
196206
# Add a new submodule to the working tree, .gitmodules and the index
197207
#
@@ -347,9 +357,9 @@ Use -f if you really want to add it." >&2
347357
echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
348358
fi
349359
fi
350-
git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" "$reference" "$depth" || exit
360+
git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${depth:+"$depth"} || exit
351361
(
352-
clear_local_git_env
362+
sanitize_submodule_env
353363
cd "$sm_path" &&
354364
# ash fails to wordsplit ${branch:+-b "$branch"...}
355365
case "$branch" in
@@ -418,7 +428,7 @@ cmd_foreach()
418428
name=$(git submodule--helper name "$sm_path")
419429
(
420430
prefix="$prefix$sm_path/"
421-
clear_local_git_env
431+
sanitize_submodule_env
422432
cd "$sm_path" &&
423433
sm_path=$(relative_path "$sm_path") &&
424434
# we make $path available to scripts ...
@@ -727,11 +737,11 @@ Maybe you want to use 'update --init'?")"
727737

728738
if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git
729739
then
730-
git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" "$reference" "$depth" || exit
740+
git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" ${reference:+"$reference"} ${depth:+"$depth"} || exit
731741
cloned_modules="$cloned_modules;$name"
732742
subsha1=
733743
else
734-
subsha1=$(clear_local_git_env; cd "$sm_path" &&
744+
subsha1=$(sanitize_submodule_env; cd "$sm_path" &&
735745
git rev-parse --verify HEAD) ||
736746
die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
737747
fi
@@ -741,11 +751,11 @@ Maybe you want to use 'update --init'?")"
741751
if test -z "$nofetch"
742752
then
743753
# Fetch remote before determining tracking $sha1
744-
(clear_local_git_env; cd "$sm_path" && git-fetch) ||
754+
(sanitize_submodule_env; cd "$sm_path" && git-fetch) ||
745755
die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
746756
fi
747-
remote_name=$(clear_local_git_env; cd "$sm_path" && get_default_remote)
748-
sha1=$(clear_local_git_env; cd "$sm_path" &&
757+
remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote)
758+
sha1=$(sanitize_submodule_env; cd "$sm_path" &&
749759
git rev-parse --verify "${remote_name}/${branch}") ||
750760
die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
751761
fi
@@ -810,7 +820,7 @@ Maybe you want to use 'update --init'?")"
810820
die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
811821
esac
812822

813-
if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
823+
if (sanitize_submodule_env; cd "$sm_path" && $command "$sha1")
814824
then
815825
say "$say_msg"
816826
elif test -n "$must_die_on_failure"
@@ -826,7 +836,7 @@ Maybe you want to use 'update --init'?")"
826836
then
827837
(
828838
prefix="$prefix$sm_path/"
829-
clear_local_git_env
839+
sanitize_submodule_env
830840
cd "$sm_path" &&
831841
eval cmd_update
832842
)
@@ -864,7 +874,7 @@ Maybe you want to use 'update --init'?")"
864874

865875
set_name_rev () {
866876
revname=$( (
867-
clear_local_git_env
877+
sanitize_submodule_env
868878
cd "$1" && {
869879
git describe "$2" 2>/dev/null ||
870880
git describe --tags "$2" 2>/dev/null ||
@@ -1148,7 +1158,7 @@ cmd_status()
11481158
else
11491159
if test -z "$cached"
11501160
then
1151-
sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD)
1161+
sha1=$(sanitize_submodule_env; cd "$sm_path" && git rev-parse --verify HEAD)
11521162
fi
11531163
set_name_rev "$sm_path" "$sha1"
11541164
say "+$sha1 $displaypath$revname"
@@ -1158,7 +1168,7 @@ cmd_status()
11581168
then
11591169
(
11601170
prefix="$displaypath/"
1161-
clear_local_git_env
1171+
sanitize_submodule_env
11621172
cd "$sm_path" &&
11631173
eval cmd_status
11641174
) ||
@@ -1232,7 +1242,7 @@ cmd_sync()
12321242
if test -e "$sm_path"/.git
12331243
then
12341244
(
1235-
clear_local_git_env
1245+
sanitize_submodule_env
12361246
cd "$sm_path"
12371247
remote=$(get_default_remote)
12381248
git config remote."$remote".url "$sub_origin_url"

http-push.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ static void curl_setup_http(CURL *curl, const char *url,
211211
static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options)
212212
{
213213
struct strbuf buf = STRBUF_INIT;
214-
struct curl_slist *dav_headers = NULL;
214+
struct curl_slist *dav_headers = http_copy_default_headers();
215215

216216
if (options & DAV_HEADER_IF) {
217217
strbuf_addf(&buf, "If: (<%s>)", lock->token);
@@ -417,7 +417,7 @@ static void start_put(struct transfer_request *request)
417417
static void start_move(struct transfer_request *request)
418418
{
419419
struct active_request_slot *slot;
420-
struct curl_slist *dav_headers = NULL;
420+
struct curl_slist *dav_headers = http_copy_default_headers();
421421

422422
slot = get_active_slot();
423423
slot->callback_func = process_response;
@@ -845,7 +845,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
845845
char *ep;
846846
char timeout_header[25];
847847
struct remote_lock *lock = NULL;
848-
struct curl_slist *dav_headers = NULL;
848+
struct curl_slist *dav_headers = http_copy_default_headers();
849849
struct xml_ctx ctx;
850850
char *escaped;
851851

@@ -1126,7 +1126,7 @@ static void remote_ls(const char *path, int flags,
11261126
struct slot_results results;
11271127
struct strbuf in_buffer = STRBUF_INIT;
11281128
struct buffer out_buffer = { STRBUF_INIT, 0 };
1129-
struct curl_slist *dav_headers = NULL;
1129+
struct curl_slist *dav_headers = http_copy_default_headers();
11301130
struct xml_ctx ctx;
11311131
struct remote_ls_ctx ls;
11321132

@@ -1204,7 +1204,7 @@ static int locking_available(void)
12041204
struct slot_results results;
12051205
struct strbuf in_buffer = STRBUF_INIT;
12061206
struct buffer out_buffer = { STRBUF_INIT, 0 };
1207-
struct curl_slist *dav_headers = NULL;
1207+
struct curl_slist *dav_headers = http_copy_default_headers();
12081208
struct xml_ctx ctx;
12091209
int lock_flags = 0;
12101210
char *escaped;

http.c

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ static unsigned long http_auth_methods = CURLAUTH_ANY;
114114

115115
static struct curl_slist *pragma_header;
116116
static struct curl_slist *no_pragma_header;
117+
static struct curl_slist *extra_http_headers;
117118

118119
static struct active_request_slot *active_queue_head;
119120

@@ -323,6 +324,19 @@ static int http_options(const char *var, const char *value, void *cb)
323324
#endif
324325
}
325326

327+
if (!strcmp("http.extraheader", var)) {
328+
if (!value) {
329+
return config_error_nonbool(var);
330+
} else if (!*value) {
331+
curl_slist_free_all(extra_http_headers);
332+
extra_http_headers = NULL;
333+
} else {
334+
extra_http_headers =
335+
curl_slist_append(extra_http_headers, value);
336+
}
337+
return 0;
338+
}
339+
326340
/* Fall back on the default ones */
327341
return git_default_config(var, value, cb);
328342
}
@@ -675,8 +689,10 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
675689
if (remote)
676690
var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);
677691

678-
pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
679-
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
692+
pragma_header = curl_slist_append(http_copy_default_headers(),
693+
"Pragma: no-cache");
694+
no_pragma_header = curl_slist_append(http_copy_default_headers(),
695+
"Pragma:");
680696

681697
#ifdef USE_CURL_MULTI
682698
{
@@ -762,6 +778,9 @@ void http_cleanup(void)
762778
#endif
763779
curl_global_cleanup();
764780

781+
curl_slist_free_all(extra_http_headers);
782+
extra_http_headers = NULL;
783+
765784
curl_slist_free_all(pragma_header);
766785
pragma_header = NULL;
767786

@@ -1160,6 +1179,16 @@ int run_one_slot(struct active_request_slot *slot,
11601179
return handle_curl_result(results);
11611180
}
11621181

1182+
struct curl_slist *http_copy_default_headers(void)
1183+
{
1184+
struct curl_slist *headers = NULL, *h;
1185+
1186+
for (h = extra_http_headers; h; h = h->next)
1187+
headers = curl_slist_append(headers, h->data);
1188+
1189+
return headers;
1190+
}
1191+
11631192
static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf)
11641193
{
11651194
char *ptr;
@@ -1377,7 +1406,7 @@ static int http_request(const char *url,
13771406
{
13781407
struct active_request_slot *slot;
13791408
struct slot_results results;
1380-
struct curl_slist *headers = NULL;
1409+
struct curl_slist *headers = http_copy_default_headers();
13811410
struct strbuf buf = STRBUF_INIT;
13821411
const char *accept_language;
13831412
int ret;

http.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ extern void step_active_slots(void);
106106
extern void http_init(struct remote *remote, const char *url,
107107
int proactive_auth);
108108
extern void http_cleanup(void);
109+
extern struct curl_slist *http_copy_default_headers(void);
109110

110111
extern long int git_curl_ipresolve;
111112
extern int active_requests;

0 commit comments

Comments
 (0)