From 2cf5221f68d3d57cff978144a904dde28123a338 Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 19 Aug 2024 23:45:13 +0900 Subject: [PATCH] Add support the `[http]` table (#20) --- .github/.cspell/project-dictionary.txt | 2 + src/de.rs | 69 +++++++++++++++- src/easy.rs | 87 ++++++++++++++++++++- src/gen/assert_impl.rs | 10 +++ src/gen/de.rs | 27 +++++++ src/gen/is_none.rs | 16 ++++ tests/fixtures/reference/.cargo/config.toml | 20 ++--- tests/test.rs | 9 ++- 8 files changed, 227 insertions(+), 13 deletions(-) diff --git a/.github/.cspell/project-dictionary.txt b/.github/.cspell/project-dictionary.txt index 8e3ce8b..dbb4a46 100644 --- a/.github/.cspell/project-dictionary.txt +++ b/.github/.cspell/project-dictionary.txt @@ -1,3 +1,5 @@ fxsr unparse USERPROFILE +cainfo +libcurl diff --git a/src/de.rs b/src/de.rs index f643143..62913dc 100644 --- a/src/de.rs +++ b/src/de.rs @@ -67,7 +67,12 @@ pub struct Config { #[serde(skip_serializing_if = "FutureIncompatReportConfig::is_none")] pub future_incompat_report: FutureIncompatReportConfig, // TODO: cargo-new - // TODO: http + /// The `[http]` table. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#http) + #[serde(default)] + #[serde(skip_serializing_if = "HttpConfig::is_none")] + pub http: HttpConfig, // TODO: install /// The `[net]` table. /// @@ -438,6 +443,68 @@ pub struct FutureIncompatReportConfig { pub frequency: Option>, } +/// The `[http]` table. +/// +/// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#http) +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +#[non_exhaustive] +pub struct HttpConfig { + /// If true, enables debugging of HTTP requests. + /// The debug information can be seen by setting the `CARGO_LOG=network=debug` environment variable + /// (or use `network=trace` for even more information). + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpdebug) + #[serde(skip_serializing_if = "Option::is_none")] + pub debug: Option>, + /// Sets an HTTP and HTTPS proxy to use. The format is in libcurl format as in `[protocol://]host[:port]`. + /// If not set, Cargo will also check the http.proxy setting in your global git configuration. + /// If none of those are set, the HTTPS_PROXY or https_proxy environment variables set the proxy for HTTPS requests, + /// and http_proxy sets it for HTTP requests. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpproxy) + #[serde(skip_serializing_if = "Option::is_none")] + pub proxy: Option>, + /// Sets the timeout for each HTTP request, in seconds. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httptimeout) + #[serde(skip_serializing_if = "Option::is_none")] + pub timeout: Option>, + /// Path to a Certificate Authority (CA) bundle file, used to verify TLS certificates. + /// If not specified, Cargo attempts to use the system certificates. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpcainfo) + #[serde(skip_serializing_if = "Option::is_none")] + pub cainfo: Option>, + /// This determines whether or not TLS certificate revocation checks should be performed. + /// This only works on Windows. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpcheck-revoke) + #[serde(skip_serializing_if = "Option::is_none")] + pub check_revoke: Option>, + // TODO: handle ssl-version + /// This setting controls timeout behavior for slow connections. + /// If the average transfer speed in bytes per second is below the given value + /// for `http.timeout` seconds (default 30 seconds), then the connection is considered too slow and Cargo will abort and retry. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httplow-speed-limit) + #[serde(skip_serializing_if = "Option::is_none")] + pub low_speed_limit: Option>, + /// When true, Cargo will attempt to use the HTTP2 protocol with multiplexing. + /// This allows multiple requests to use the same connection, usually improving performance when fetching multiple files. + /// If false, Cargo will use HTTP 1.1 without pipelining. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpmultiplexing) + #[serde(skip_serializing_if = "Option::is_none")] + pub multiplexing: Option>, + /// Specifies a custom user-agent header to use. + /// The default if not specified is a string that includes Cargo’s version. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpuser-agent) + #[serde(skip_serializing_if = "Option::is_none")] + pub user_agent: Option>, +} + /// The `[net]` table. /// /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#net) diff --git a/src/easy.rs b/src/easy.rs index 7e01ede..378256c 100644 --- a/src/easy.rs +++ b/src/easy.rs @@ -60,7 +60,13 @@ pub struct Config { #[serde(skip_serializing_if = "FutureIncompatReportConfig::is_none")] pub future_incompat_report: FutureIncompatReportConfig, // TODO: cargo-new - // TODO: http + /// The `[http]` table. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#http) + #[serde(default)] + #[serde(skip_serializing_if = "HttpConfig::is_none")] + pub http: HttpConfig, + // TODO: install /// The `[net]` table. /// @@ -145,6 +151,7 @@ impl Config { } let future_incompat_report = FutureIncompatReportConfig::from_unresolved(de.future_incompat_report); + let http = HttpConfig::from_unresolved(de.http); let net = NetConfig::from_unresolved(de.net); let mut registries = BTreeMap::new(); for (k, v) in de.registries { @@ -159,6 +166,7 @@ impl Config { doc, env, future_incompat_report, + http, net, registries, registry, @@ -694,6 +702,83 @@ impl FutureIncompatReportConfig { } } +/// The `[http]` table. +/// +/// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#http) +#[derive(Debug, Clone, Default, Serialize)] +#[serde(rename_all = "kebab-case")] +#[non_exhaustive] +pub struct HttpConfig { + /// If true, enables debugging of HTTP requests. + /// The debug information can be seen by setting the `CARGO_LOG=network=debug` environment variable + /// (or use `network=trace` for even more information). + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpdebug) + #[serde(skip_serializing_if = "Option::is_none")] + pub debug: Option, + /// Sets an HTTP and HTTPS proxy to use. The format is in libcurl format as in `[protocol://]host[:port]`. + /// If not set, Cargo will also check the http.proxy setting in your global git configuration. + /// If none of those are set, the HTTPS_PROXY or https_proxy environment variables set the proxy for HTTPS requests, + /// and http_proxy sets it for HTTP requests. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpproxy) + #[serde(skip_serializing_if = "Option::is_none")] + pub proxy: Option, + /// Sets the timeout for each HTTP request, in seconds. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httptimeout) + #[serde(skip_serializing_if = "Option::is_none")] + pub timeout: Option, + /// Path to a Certificate Authority (CA) bundle file, used to verify TLS certificates. + /// If not specified, Cargo attempts to use the system certificates. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpcainfo) + #[serde(skip_serializing_if = "Option::is_none")] + pub cainfo: Option, + /// This determines whether or not TLS certificate revocation checks should be performed. + /// This only works on Windows. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpcheck-revoke) + #[serde(skip_serializing_if = "Option::is_none")] + pub check_revoke: Option, + // TODO: Add ssl-version + /// This setting controls timeout behavior for slow connections. + /// If the average transfer speed in bytes per second is below the given value + /// for `http.timeout` seconds (default 30 seconds), then the connection is considered too slow and Cargo will abort and retry. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httplow-speed-limit) + #[serde(skip_serializing_if = "Option::is_none")] + pub low_speed_limit: Option, + /// When true, Cargo will attempt to use the HTTP2 protocol with multiplexing. + /// This allows multiple requests to use the same connection, usually improving performance when fetching multiple files. + /// If false, Cargo will use HTTP 1.1 without pipelining. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpmultiplexing) + #[serde(skip_serializing_if = "Option::is_none")] + pub multiplexing: Option, + /// Specifies a custom user-agent header to use. + /// The default if not specified is a string that includes Cargo’s version. + /// + /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpuser-agent) + #[serde(skip_serializing_if = "Option::is_none")] + pub user_agent: Option, +} + +impl HttpConfig { + fn from_unresolved(de: de::HttpConfig) -> Self { + Self { + debug: de.debug.map(|v| v.val), + proxy: de.proxy.map(|v| v.val), + timeout: de.timeout.map(|v| v.val), + cainfo: de.cainfo.map(|v| v.val), + check_revoke: de.check_revoke.map(|v| v.val), + low_speed_limit: de.low_speed_limit.map(|v| v.val), + multiplexing: de.multiplexing.map(|v| v.val), + user_agent: de.user_agent.map(|v| v.val), + } + } +} + /// The `[net]` table. /// /// [reference](https://doc.rust-lang.org/nightly/cargo/reference/config.html#net) diff --git a/src/gen/assert_impl.rs b/src/gen/assert_impl.rs index b7d3663..104cfbf 100644 --- a/src/gen/assert_impl.rs +++ b/src/gen/assert_impl.rs @@ -83,6 +83,11 @@ const _: fn() = || { assert_unpin::(); assert_unwind_safe::(); assert_ref_unwind_safe::(); + assert_send::(); + assert_sync::(); + assert_unpin::(); + assert_unwind_safe::(); + assert_ref_unwind_safe::(); assert_send::(); assert_sync::(); assert_unpin::(); @@ -183,6 +188,11 @@ const _: fn() = || { assert_unpin::(); assert_unwind_safe::(); assert_ref_unwind_safe::(); + assert_send::(); + assert_sync::(); + assert_unpin::(); + assert_unwind_safe::(); + assert_ref_unwind_safe::(); assert_send::(); assert_sync::(); assert_unpin::(); diff --git a/src/gen/de.rs b/src/gen/de.rs index 21a5032..e9177d2 100644 --- a/src/gen/de.rs +++ b/src/gen/de.rs @@ -13,6 +13,7 @@ impl Merge for crate::de::Config { self.doc.merge(low.doc, force)?; self.env.merge(low.env, force)?; self.future_incompat_report.merge(low.future_incompat_report, force)?; + self.http.merge(low.http, force)?; self.net.merge(low.net, force)?; self.registries.merge(low.registries, force)?; self.registry.merge(low.registry, force)?; @@ -28,6 +29,7 @@ impl SetPath for crate::de::Config { self.doc.set_path(path); self.env.set_path(path); self.future_incompat_report.set_path(path); + self.http.set_path(path); self.net.set_path(path); self.registries.set_path(path); self.registry.set_path(path); @@ -117,6 +119,31 @@ impl SetPath for crate::de::FutureIncompatReportConfig { self.frequency.set_path(path); } } +impl Merge for crate::de::HttpConfig { + fn merge(&mut self, low: Self, force: bool) -> Result<()> { + self.debug.merge(low.debug, force)?; + self.proxy.merge(low.proxy, force)?; + self.timeout.merge(low.timeout, force)?; + self.cainfo.merge(low.cainfo, force)?; + self.check_revoke.merge(low.check_revoke, force)?; + self.low_speed_limit.merge(low.low_speed_limit, force)?; + self.multiplexing.merge(low.multiplexing, force)?; + self.user_agent.merge(low.user_agent, force)?; + Ok(()) + } +} +impl SetPath for crate::de::HttpConfig { + fn set_path(&mut self, path: &Path) { + self.debug.set_path(path); + self.proxy.set_path(path); + self.timeout.set_path(path); + self.cainfo.set_path(path); + self.check_revoke.set_path(path); + self.low_speed_limit.set_path(path); + self.multiplexing.set_path(path); + self.user_agent.set_path(path); + } +} impl Merge for crate::de::NetConfig { fn merge(&mut self, low: Self, force: bool) -> Result<()> { self.retry.merge(low.retry, force)?; diff --git a/src/gen/is_none.rs b/src/gen/is_none.rs index 84501fe..a2fd500 100644 --- a/src/gen/is_none.rs +++ b/src/gen/is_none.rs @@ -23,6 +23,14 @@ impl crate::easy::FutureIncompatReportConfig { self.frequency.is_none() } } +impl crate::easy::HttpConfig { + pub(crate) fn is_none(&self) -> bool { + self.debug.is_none() && self.proxy.is_none() && self.timeout.is_none() + && self.cainfo.is_none() && self.check_revoke.is_none() + && self.low_speed_limit.is_none() && self.multiplexing.is_none() + && self.user_agent.is_none() + } +} impl crate::easy::NetConfig { pub(crate) fn is_none(&self) -> bool { self.retry.is_none() && self.git_fetch_with_cli.is_none() @@ -64,6 +72,14 @@ impl crate::de::FutureIncompatReportConfig { self.frequency.is_none() } } +impl crate::de::HttpConfig { + pub(crate) fn is_none(&self) -> bool { + self.debug.is_none() && self.proxy.is_none() && self.timeout.is_none() + && self.cainfo.is_none() && self.check_revoke.is_none() + && self.low_speed_limit.is_none() && self.multiplexing.is_none() + && self.user_agent.is_none() + } +} impl crate::de::NetConfig { pub(crate) fn is_none(&self) -> bool { self.retry.is_none() && self.git_fetch_with_cli.is_none() diff --git a/tests/fixtures/reference/.cargo/config.toml b/tests/fixtures/reference/.cargo/config.toml index 71afc2b..5aa5ff3 100644 --- a/tests/fixtures/reference/.cargo/config.toml +++ b/tests/fixtures/reference/.cargo/config.toml @@ -41,18 +41,18 @@ frequency = 'always' # when to display a notification about a future incompat re # [cargo-new] # vcs = "none" # VCS to use ('git', 'hg', 'pijul', 'fossil', 'none') -# [http] -# debug = false # HTTP debugging -# proxy = "host:port" # HTTP proxy in libcurl format -# # ssl-version = "tlsv1.3" # TLS version to use +[http] +debug = false # HTTP debugging +proxy = "host:port" # HTTP proxy in libcurl format +# ssl-version = "tlsv1.3" # TLS version to use # ssl-version.max = "tlsv1.3" # maximum TLS version # ssl-version.min = "tlsv1.1" # minimum TLS version -# timeout = 30 # timeout for each HTTP request, in seconds -# low-speed-limit = 10 # network timeout threshold (bytes/sec) -# cainfo = "cert.pem" # path to Certificate Authority (CA) bundle -# check-revoke = true # check for SSL certificate revocation -# multiplexing = true # HTTP/2 multiplexing -# user-agent = "…" # the user-agent header +timeout = 30 # timeout for each HTTP request, in seconds +low-speed-limit = 10 # network timeout threshold (bytes/sec) +cainfo = "cert.pem" # path to Certificate Authority (CA) bundle +check-revoke = true # check for SSL certificate revocation +multiplexing = true # HTTP/2 multiplexing +user-agent = "foo-usr-agt" # the user-agent header # [install] # root = "/some/path" # `cargo install` destination directory diff --git a/tests/test.rs b/tests/test.rs index ad419bd..052b675 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -74,8 +74,15 @@ fn assert_reference_example(de: fn(&Path, ResolveOptions) -> Result) -> // TODO // [cargo-new] - // TODO // [http] + assert_eq!(config.http.debug, Some(false)); + assert_eq!(config.http.proxy.as_deref(), Some("host:port")); + assert_eq!(config.http.timeout, Some(30)); + assert_eq!(config.http.low_speed_limit, Some(10)); + assert_eq!(config.http.cainfo.as_deref(), Some("cert.pem")); + assert_eq!(config.http.check_revoke, Some(true)); + assert_eq!(config.http.multiplexing, Some(true)); + assert_eq!(config.http.user_agent.as_deref(), Some("foo-usr-agt")); // TODO // [install]