Skip to content

Commit

Permalink
Translate all cargo http options into the ones used by gitoxide
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Dec 24, 2022
1 parent 4fc0796 commit b903e2d
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/cargo/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ mod cargo_uninstall;
mod common_for_install_and_uninstall;
mod fix;
mod lockfile;
mod registry;
pub(crate) mod registry;
mod resolve;
pub mod tree;
mod vendor;
Expand Down
34 changes: 17 additions & 17 deletions src/cargo/ops/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,23 @@ pub fn needs_custom_http_transport(config: &Config) -> CargoResult<bool> {
|| env::var_os("HTTP_TIMEOUT").is_some())
}

pub(crate) fn to_ssl_version(s: &str) -> CargoResult<SslVersion> {
let version = match s {
"default" => SslVersion::Default,
"tlsv1" => SslVersion::Tlsv1,
"tlsv1.0" => SslVersion::Tlsv10,
"tlsv1.1" => SslVersion::Tlsv11,
"tlsv1.2" => SslVersion::Tlsv12,
"tlsv1.3" => SslVersion::Tlsv13,
_ => bail!(
"Invalid ssl version `{}`,\
choose from 'default', 'tlsv1', 'tlsv1.0', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3'.",
s
),
};
Ok(version)
}

/// Configure a libcurl http handle with the defaults options for Cargo
pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<HttpTimeout> {
let http = config.http_config()?;
Expand All @@ -576,23 +593,6 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<

// Empty string accept encoding expands to the encodings supported by the current libcurl.
handle.accept_encoding("")?;

fn to_ssl_version(s: &str) -> CargoResult<SslVersion> {
let version = match s {
"default" => SslVersion::Default,
"tlsv1" => SslVersion::Tlsv1,
"tlsv1.0" => SslVersion::Tlsv10,
"tlsv1.1" => SslVersion::Tlsv11,
"tlsv1.2" => SslVersion::Tlsv12,
"tlsv1.3" => SslVersion::Tlsv13,
_ => bail!(
"Invalid ssl version `{}`,\
choose from 'default', 'tlsv1', 'tlsv1.0', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3'.",
s
),
};
Ok(version)
}
if let Some(ssl_version) = &http.ssl_version {
match ssl_version {
SslVersionConfig::Single(s) => {
Expand Down
86 changes: 78 additions & 8 deletions src/cargo/sources/git/oxide.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,22 +190,92 @@ fn amend_authentication_hints(
pub fn open_repo(repo_path: &std::path::Path, config: &Config) -> CargoResult<git::Repository> {
git::open_opts(repo_path, {
let mut opts = git::open::Options::default();
let timeout = HttpTimeout::new(config)?;

// We need `git_binary` configuration as well for being able to see credential helpers
// that are configured with the `git` installation itself.
// However, this is slow on windows (~150ms) and most people won't need it as they use the
// standard index which won't ever need authentication.
// TODO: This is certainly something to make configurable, at the very least on windows.
// Maybe it's also something that could be cached, all we need is the path to the configuration file
// which usually doesn't change unless the installation changes. Maybe something keyed by the location of the
// binary along with its fingerprint.
// binary along with its fingerprint, without doing much work unless the modification
// time of the binary changes to signal an update.
// TODO(QUESTION): all HTTP options set here might not actually be used if the user has per-URL options set which override these.
// To me this seems like an advantage. If it's not, there should be a way to tell `gitoxide` not to look for URL
// specific overrides.
opts.permissions.config = git::permissions::Config::all();
opts.config_overrides([
format!("gitoxide.http.connectTimeout={}", timeout.dur.as_millis()),
format!("http.lowSpeedLimit={}", timeout.low_speed_limit),
format!("http.lowSpeedTime={}", timeout.dur.as_secs()),
])
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.
opts.with(git::sec::Trust::Full)
.config_overrides(cargo_config_to_gitoxide_overrides(config)?)
})
.map_err(Into::into)
}

fn cargo_config_to_gitoxide_overrides(config: &Config) -> CargoResult<Vec<String>> {
let timeout = HttpTimeout::new(config)?;
let http = config.http_config()?;

let mut values = vec![
format!("gitoxide.http.connectTimeout={}", timeout.dur.as_millis()),
format!("http.lowSpeedLimit={}", timeout.low_speed_limit),
format!("http.lowSpeedTime={}", timeout.dur.as_secs()),
];
if let Some(proxy) = &http.proxy {
values.push(format!("http.proxy={}", proxy));
}
if let Some(check_revoke) = http.check_revoke {
values.push(format!("http.schannelCheckRevoke={}", check_revoke));
}
if let Some(cainfo) = &http.cainfo {
values.push(format!(
"http.sslCAInfo={}",
cainfo.resolve_path(config).display()
));
}
if let Some(user_agent) = &http.user_agent {
values.push(format!("http.userAgent={}", user_agent));
}
if let Some(ssl_version) = &http.ssl_version {
use crate::util::config::SslVersionConfig;
fn checked_version_config_value(
version: Option<&str>,
key: &str,
out: &mut Vec<String>,
) -> CargoResult<()> {
version.map_or(Ok(curl::easy::SslVersion::Default), |version| {
crate::ops::registry::to_ssl_version(version)
})?;
out.push(format!("{key}={}", version.unwrap_or("default")));
Ok(())
}
match ssl_version {
SslVersionConfig::Single(version) => {
checked_version_config_value(Some(&version), "http.sslVersion", &mut values)?;
}
SslVersionConfig::Range(range) => {
checked_version_config_value(
range.min.as_deref(),
"gitoxide.http.sslVersionMin",
&mut values,
)?;
checked_version_config_value(
range.max.as_deref(),
"gitoxide.http.sslVersionMax",
&mut values,
)?;
}
}
}
if let Some(debug) = http.debug {
values.push(format!("gitoxide.http.verbose={debug}"));
}
if let Some(multiplexing) = http.multiplexing {
let http_version = multiplexing.then(|| "HTTP/2").unwrap_or("HTTP/1.1");
// Note: the HTTP version itself should automatically make multiplexing available.
// It's unclear at this time if it does affect performance of fetches measurably.
// In `curl`, it appears special support via a `Multi` handle is needed which also doesn't
// exist in `gitoxide` - each fetch is probably its own connection that way.
values.push(format!("http.version={http_version}"));
}

Ok(values)
}

0 comments on commit b903e2d

Please sign in to comment.