Skip to content

Commit

Permalink
Merge commit 'extra-http-headers'
Browse files Browse the repository at this point in the history
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
  • Loading branch information
dscho committed Apr 30, 2016
2 parents 696b363 + f25905b commit abd3b0f
Show file tree
Hide file tree
Showing 15 changed files with 242 additions and 28 deletions.
6 changes: 6 additions & 0 deletions Documentation/config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1675,6 +1675,12 @@ http.emptyAuth::
a username in the URL, as libcurl normally requires a username for
authentication.

http.extraHeader::
Pass an additional HTTP header when communicating with a server. If
more than one such entry exists, all of them are added as extra
headers. To allow overriding the settings inherited from the system
config, an empty value will reset the extra headers to the empty list.

http.cookieFile::
File containing previously stored cookie lines which should be used
in the Git http session, if they match the server. The file format
Expand Down
77 changes: 74 additions & 3 deletions builtin/submodule--helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,56 @@ 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.") ||
(starts_with(var, "http.") && ends_with(var, ".extraheader")))
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)
{
Expand All @@ -139,7 +189,7 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
argv_array_push(&cp.args, path);

cp.git_cmd = 1;
cp.env = local_repo_env;
prepare_submodule_repo_env(&cp.env_array);
cp.no_stdin = 1;

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

const char *const git_submodule_helper_usage[] = {
N_("git submodule--helper clone [--prefix=<path>] [--quiet] "
"[--reference <repository>] [--name <name>] [--url <url>]"
"[--depth <depth>] [--] [<path>...]"),
"[--reference <repository>] [--name <name>] [--depth <depth>] "
"--url <url> --path <path>"),
NULL
};

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

if (argc || !url || !path)
usage_with_options(git_submodule_helper_usage,
module_clone_options);

strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name);
sm_gitdir = strbuf_detach(&sb, NULL);

Expand Down Expand Up @@ -249,6 +303,22 @@ 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 *);
Expand All @@ -258,6 +328,7 @@ 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)
Expand Down
2 changes: 1 addition & 1 deletion config.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ void git_config_push_parameter(const char *text)
{
struct strbuf env = STRBUF_INIT;
const char *old = getenv(CONFIG_DATA_ENVIRONMENT);
if (old) {
if (old && *old) {
strbuf_addstr(&env, old);
strbuf_addch(&env, ' ');
}
Expand Down
38 changes: 24 additions & 14 deletions git-submodule.sh
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,16 @@ isnumber()
n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
}

# Sanitize the local git environment for use within a submodule. We
# can't simply use clear_local_git_env since we want to preserve some
# of the settings from GIT_CONFIG_PARAMETERS.
sanitize_submodule_env()
{
sanitized_config=$(git submodule--helper sanitize-config)
clear_local_git_env
GIT_CONFIG_PARAMETERS=$sanitized_config
}

#
# Add a new submodule to the working tree, .gitmodules and the index
#
Expand Down Expand Up @@ -347,9 +357,9 @@ Use -f if you really want to add it." >&2
echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
fi
fi
git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" "$reference" "$depth" || exit
git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${depth:+"$depth"} || exit
(
clear_local_git_env
sanitize_submodule_env
cd "$sm_path" &&
# ash fails to wordsplit ${branch:+-b "$branch"...}
case "$branch" in
Expand Down Expand Up @@ -418,7 +428,7 @@ cmd_foreach()
name=$(git submodule--helper name "$sm_path")
(
prefix="$prefix$sm_path/"
clear_local_git_env
sanitize_submodule_env
cd "$sm_path" &&
sm_path=$(relative_path "$sm_path") &&
# we make $path available to scripts ...
Expand Down Expand Up @@ -727,11 +737,11 @@ Maybe you want to use 'update --init'?")"

if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git
then
git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" "$reference" "$depth" || exit
git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" ${reference:+"$reference"} ${depth:+"$depth"} || exit
cloned_modules="$cloned_modules;$name"
subsha1=
else
subsha1=$(clear_local_git_env; cd "$sm_path" &&
subsha1=$(sanitize_submodule_env; cd "$sm_path" &&
git rev-parse --verify HEAD) ||
die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
fi
Expand All @@ -741,11 +751,11 @@ Maybe you want to use 'update --init'?")"
if test -z "$nofetch"
then
# Fetch remote before determining tracking $sha1
(clear_local_git_env; cd "$sm_path" && git-fetch) ||
(sanitize_submodule_env; cd "$sm_path" && git-fetch) ||
die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
fi
remote_name=$(clear_local_git_env; cd "$sm_path" && get_default_remote)
sha1=$(clear_local_git_env; cd "$sm_path" &&
remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote)
sha1=$(sanitize_submodule_env; cd "$sm_path" &&
git rev-parse --verify "${remote_name}/${branch}") ||
die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
fi
Expand Down Expand Up @@ -810,7 +820,7 @@ Maybe you want to use 'update --init'?")"
die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
esac

if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
if (sanitize_submodule_env; cd "$sm_path" && $command "$sha1")
then
say "$say_msg"
elif test -n "$must_die_on_failure"
Expand All @@ -826,7 +836,7 @@ Maybe you want to use 'update --init'?")"
then
(
prefix="$prefix$sm_path/"
clear_local_git_env
sanitize_submodule_env
cd "$sm_path" &&
eval cmd_update
)
Expand Down Expand Up @@ -864,7 +874,7 @@ Maybe you want to use 'update --init'?")"

set_name_rev () {
revname=$( (
clear_local_git_env
sanitize_submodule_env
cd "$1" && {
git describe "$2" 2>/dev/null ||
git describe --tags "$2" 2>/dev/null ||
Expand Down Expand Up @@ -1148,7 +1158,7 @@ cmd_status()
else
if test -z "$cached"
then
sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD)
sha1=$(sanitize_submodule_env; cd "$sm_path" && git rev-parse --verify HEAD)
fi
set_name_rev "$sm_path" "$sha1"
say "+$sha1 $displaypath$revname"
Expand All @@ -1158,7 +1168,7 @@ cmd_status()
then
(
prefix="$displaypath/"
clear_local_git_env
sanitize_submodule_env
cd "$sm_path" &&
eval cmd_status
) ||
Expand Down Expand Up @@ -1232,7 +1242,7 @@ cmd_sync()
if test -e "$sm_path"/.git
then
(
clear_local_git_env
sanitize_submodule_env
cd "$sm_path"
remote=$(get_default_remote)
git config remote."$remote".url "$sub_origin_url"
Expand Down
10 changes: 5 additions & 5 deletions http-push.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ static void curl_setup_http(CURL *curl, const char *url,
static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options)
{
struct strbuf buf = STRBUF_INIT;
struct curl_slist *dav_headers = NULL;
struct curl_slist *dav_headers = http_copy_default_headers();

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

slot = get_active_slot();
slot->callback_func = process_response;
Expand Down Expand Up @@ -845,7 +845,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
char *ep;
char timeout_header[25];
struct remote_lock *lock = NULL;
struct curl_slist *dav_headers = NULL;
struct curl_slist *dav_headers = http_copy_default_headers();
struct xml_ctx ctx;
char *escaped;

Expand Down Expand Up @@ -1126,7 +1126,7 @@ static void remote_ls(const char *path, int flags,
struct slot_results results;
struct strbuf in_buffer = STRBUF_INIT;
struct buffer out_buffer = { STRBUF_INIT, 0 };
struct curl_slist *dav_headers = NULL;
struct curl_slist *dav_headers = http_copy_default_headers();
struct xml_ctx ctx;
struct remote_ls_ctx ls;

Expand Down Expand Up @@ -1204,7 +1204,7 @@ static int locking_available(void)
struct slot_results results;
struct strbuf in_buffer = STRBUF_INIT;
struct buffer out_buffer = { STRBUF_INIT, 0 };
struct curl_slist *dav_headers = NULL;
struct curl_slist *dav_headers = http_copy_default_headers();
struct xml_ctx ctx;
int lock_flags = 0;
char *escaped;
Expand Down
35 changes: 32 additions & 3 deletions http.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ static unsigned long http_auth_methods = CURLAUTH_ANY;

static struct curl_slist *pragma_header;
static struct curl_slist *no_pragma_header;
static struct curl_slist *extra_http_headers;

static struct active_request_slot *active_queue_head;

Expand Down Expand Up @@ -323,6 +324,19 @@ static int http_options(const char *var, const char *value, void *cb)
#endif
}

if (!strcmp("http.extraheader", var)) {
if (!value) {
return config_error_nonbool(var);
} else if (!*value) {
curl_slist_free_all(extra_http_headers);
extra_http_headers = NULL;
} else {
extra_http_headers =
curl_slist_append(extra_http_headers, value);
}
return 0;
}

/* Fall back on the default ones */
return git_default_config(var, value, cb);
}
Expand Down Expand Up @@ -675,8 +689,10 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
if (remote)
var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);

pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
pragma_header = curl_slist_append(http_copy_default_headers(),
"Pragma: no-cache");
no_pragma_header = curl_slist_append(http_copy_default_headers(),
"Pragma:");

#ifdef USE_CURL_MULTI
{
Expand Down Expand Up @@ -762,6 +778,9 @@ void http_cleanup(void)
#endif
curl_global_cleanup();

curl_slist_free_all(extra_http_headers);
extra_http_headers = NULL;

curl_slist_free_all(pragma_header);
pragma_header = NULL;

Expand Down Expand Up @@ -1160,6 +1179,16 @@ int run_one_slot(struct active_request_slot *slot,
return handle_curl_result(results);
}

struct curl_slist *http_copy_default_headers(void)
{
struct curl_slist *headers = NULL, *h;

for (h = extra_http_headers; h; h = h->next)
headers = curl_slist_append(headers, h->data);

return headers;
}

static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf)
{
char *ptr;
Expand Down Expand Up @@ -1377,7 +1406,7 @@ static int http_request(const char *url,
{
struct active_request_slot *slot;
struct slot_results results;
struct curl_slist *headers = NULL;
struct curl_slist *headers = http_copy_default_headers();
struct strbuf buf = STRBUF_INIT;
const char *accept_language;
int ret;
Expand Down
1 change: 1 addition & 0 deletions http.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ extern void step_active_slots(void);
extern void http_init(struct remote *remote, const char *url,
int proactive_auth);
extern void http_cleanup(void);
extern struct curl_slist *http_copy_default_headers(void);

extern long int git_curl_ipresolve;
extern int active_requests;
Expand Down
Loading

0 comments on commit abd3b0f

Please # to comment.