Skip to content

Commit b903e2d

Browse files
committed
Translate all cargo http options into the ones used by gitoxide
1 parent 4fc0796 commit b903e2d

File tree

3 files changed

+96
-26
lines changed

3 files changed

+96
-26
lines changed

src/cargo/ops/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ mod cargo_uninstall;
5252
mod common_for_install_and_uninstall;
5353
mod fix;
5454
mod lockfile;
55-
mod registry;
55+
pub(crate) mod registry;
5656
mod resolve;
5757
pub mod tree;
5858
mod vendor;

src/cargo/ops/registry.rs

+17-17
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,23 @@ pub fn needs_custom_http_transport(config: &Config) -> CargoResult<bool> {
554554
|| env::var_os("HTTP_TIMEOUT").is_some())
555555
}
556556

557+
pub(crate) fn to_ssl_version(s: &str) -> CargoResult<SslVersion> {
558+
let version = match s {
559+
"default" => SslVersion::Default,
560+
"tlsv1" => SslVersion::Tlsv1,
561+
"tlsv1.0" => SslVersion::Tlsv10,
562+
"tlsv1.1" => SslVersion::Tlsv11,
563+
"tlsv1.2" => SslVersion::Tlsv12,
564+
"tlsv1.3" => SslVersion::Tlsv13,
565+
_ => bail!(
566+
"Invalid ssl version `{}`,\
567+
choose from 'default', 'tlsv1', 'tlsv1.0', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3'.",
568+
s
569+
),
570+
};
571+
Ok(version)
572+
}
573+
557574
/// Configure a libcurl http handle with the defaults options for Cargo
558575
pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<HttpTimeout> {
559576
let http = config.http_config()?;
@@ -576,23 +593,6 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<
576593

577594
// Empty string accept encoding expands to the encodings supported by the current libcurl.
578595
handle.accept_encoding("")?;
579-
580-
fn to_ssl_version(s: &str) -> CargoResult<SslVersion> {
581-
let version = match s {
582-
"default" => SslVersion::Default,
583-
"tlsv1" => SslVersion::Tlsv1,
584-
"tlsv1.0" => SslVersion::Tlsv10,
585-
"tlsv1.1" => SslVersion::Tlsv11,
586-
"tlsv1.2" => SslVersion::Tlsv12,
587-
"tlsv1.3" => SslVersion::Tlsv13,
588-
_ => bail!(
589-
"Invalid ssl version `{}`,\
590-
choose from 'default', 'tlsv1', 'tlsv1.0', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3'.",
591-
s
592-
),
593-
};
594-
Ok(version)
595-
}
596596
if let Some(ssl_version) = &http.ssl_version {
597597
match ssl_version {
598598
SslVersionConfig::Single(s) => {

src/cargo/sources/git/oxide.rs

+78-8
Original file line numberDiff line numberDiff line change
@@ -190,22 +190,92 @@ fn amend_authentication_hints(
190190
pub fn open_repo(repo_path: &std::path::Path, config: &Config) -> CargoResult<git::Repository> {
191191
git::open_opts(repo_path, {
192192
let mut opts = git::open::Options::default();
193-
let timeout = HttpTimeout::new(config)?;
194-
195193
// We need `git_binary` configuration as well for being able to see credential helpers
196194
// that are configured with the `git` installation itself.
197195
// However, this is slow on windows (~150ms) and most people won't need it as they use the
198196
// standard index which won't ever need authentication.
199197
// TODO: This is certainly something to make configurable, at the very least on windows.
200198
// Maybe it's also something that could be cached, all we need is the path to the configuration file
201199
// which usually doesn't change unless the installation changes. Maybe something keyed by the location of the
202-
// binary along with its fingerprint.
200+
// binary along with its fingerprint, without doing much work unless the modification
201+
// time of the binary changes to signal an update.
202+
// TODO(QUESTION): all HTTP options set here might not actually be used if the user has per-URL options set which override these.
203+
// To me this seems like an advantage. If it's not, there should be a way to tell `gitoxide` not to look for URL
204+
// specific overrides.
203205
opts.permissions.config = git::permissions::Config::all();
204-
opts.config_overrides([
205-
format!("gitoxide.http.connectTimeout={}", timeout.dur.as_millis()),
206-
format!("http.lowSpeedLimit={}", timeout.low_speed_limit),
207-
format!("http.lowSpeedTime={}", timeout.dur.as_secs()),
208-
])
206+
opts.permissions.config.git_binary = !cfg!(windows); // TODO: make this configurable maybe? It's just slow on windows to run a program once per `cargo` invocation.
207+
opts.with(git::sec::Trust::Full)
208+
.config_overrides(cargo_config_to_gitoxide_overrides(config)?)
209209
})
210210
.map_err(Into::into)
211211
}
212+
213+
fn cargo_config_to_gitoxide_overrides(config: &Config) -> CargoResult<Vec<String>> {
214+
let timeout = HttpTimeout::new(config)?;
215+
let http = config.http_config()?;
216+
217+
let mut values = vec![
218+
format!("gitoxide.http.connectTimeout={}", timeout.dur.as_millis()),
219+
format!("http.lowSpeedLimit={}", timeout.low_speed_limit),
220+
format!("http.lowSpeedTime={}", timeout.dur.as_secs()),
221+
];
222+
if let Some(proxy) = &http.proxy {
223+
values.push(format!("http.proxy={}", proxy));
224+
}
225+
if let Some(check_revoke) = http.check_revoke {
226+
values.push(format!("http.schannelCheckRevoke={}", check_revoke));
227+
}
228+
if let Some(cainfo) = &http.cainfo {
229+
values.push(format!(
230+
"http.sslCAInfo={}",
231+
cainfo.resolve_path(config).display()
232+
));
233+
}
234+
if let Some(user_agent) = &http.user_agent {
235+
values.push(format!("http.userAgent={}", user_agent));
236+
}
237+
if let Some(ssl_version) = &http.ssl_version {
238+
use crate::util::config::SslVersionConfig;
239+
fn checked_version_config_value(
240+
version: Option<&str>,
241+
key: &str,
242+
out: &mut Vec<String>,
243+
) -> CargoResult<()> {
244+
version.map_or(Ok(curl::easy::SslVersion::Default), |version| {
245+
crate::ops::registry::to_ssl_version(version)
246+
})?;
247+
out.push(format!("{key}={}", version.unwrap_or("default")));
248+
Ok(())
249+
}
250+
match ssl_version {
251+
SslVersionConfig::Single(version) => {
252+
checked_version_config_value(Some(&version), "http.sslVersion", &mut values)?;
253+
}
254+
SslVersionConfig::Range(range) => {
255+
checked_version_config_value(
256+
range.min.as_deref(),
257+
"gitoxide.http.sslVersionMin",
258+
&mut values,
259+
)?;
260+
checked_version_config_value(
261+
range.max.as_deref(),
262+
"gitoxide.http.sslVersionMax",
263+
&mut values,
264+
)?;
265+
}
266+
}
267+
}
268+
if let Some(debug) = http.debug {
269+
values.push(format!("gitoxide.http.verbose={debug}"));
270+
}
271+
if let Some(multiplexing) = http.multiplexing {
272+
let http_version = multiplexing.then(|| "HTTP/2").unwrap_or("HTTP/1.1");
273+
// Note: the HTTP version itself should automatically make multiplexing available.
274+
// It's unclear at this time if it does affect performance of fetches measurably.
275+
// In `curl`, it appears special support via a `Multi` handle is needed which also doesn't
276+
// exist in `gitoxide` - each fetch is probably its own connection that way.
277+
values.push(format!("http.version={http_version}"));
278+
}
279+
280+
Ok(values)
281+
}

0 commit comments

Comments
 (0)