diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6cc0e03e151711467b5edfac508d3ae8525b732c..f1ef0172a20f7451a2e5a8e4fb517eedaa5fd483 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ stages: - publish .rust_mindeps: - image: "rust:1.64" + image: "rust:1.71" variables: CARGO_UPDATE_POLICY: mindeps diff --git a/git-checks-core/Cargo.toml b/git-checks-core/Cargo.toml index 1bfba644bf285c765bc9bd10f88c9ec265535dcd..f0fe0b75328654b19080a8fb42f26381216c3d66 100644 --- a/git-checks-core/Cargo.toml +++ b/git-checks-core/Cargo.toml @@ -24,7 +24,7 @@ rayon = "^1.5" regex = { version = "^1.3.3", default-features = false, features = ["std"] } thiserror = "^1.0.2" -git-workarea = "^4.2.1" +git-workarea = "^4.2.2" # Minimum version fixes. # diff --git a/git-checks/CHANGELOG.md b/git-checks/CHANGELOG.md index b5b3b492c0ed60c077485106de54cc29fce5e327..6c61c989e3a2585f3554f4dc31df2d2938e987d6 100644 --- a/git-checks/CHANGELOG.md +++ b/git-checks/CHANGELOG.md @@ -2,11 +2,12 @@ ## Updated checks - * The `ValidName` check now performs DNS queries using `trust-dns` instead of - calling out to the system `host` binary. A global DNS resolver using the - system configuration is used. + * The `ValidName` check now performs DNS queries using + `hickory-resolver` instead of calling out to the system `host` binary. + A global DNS resolver using the system configuration is used. * The `InvalidPaths` check now rejects paths which have a restricted Windows pathname as a basename (e.g., `NUL.txt`). + * MSRV bumped to 1.71 to support the `hickory-resolver` crate. # v4.2.2 diff --git a/git-checks/Cargo.toml b/git-checks/Cargo.toml index aaae51d6b72b1b60e8e08ef0226dc04584a174d7..d9bda1d97f5cff5221dcf013a0829b046c1ca754 100644 --- a/git-checks/Cargo.toml +++ b/git-checks/Cargo.toml @@ -11,7 +11,7 @@ documentation = "https://docs.rs/git-checks/~4.2" keywords = ["git", "code-review"] edition = "2018" workspace = ".." -rust-version = "1.64" +rust-version = "1.71" [dev-dependencies] serde_json = "^1.0" @@ -24,8 +24,8 @@ lazy_static = "^1.1" log = "~0.4.4" rayon = "^1.5" thiserror = "^1.0.2" -trust-dns-proto = "~0.23" -trust-dns-resolver = { version = "~0.23", default-features = false, features = ["system-config", "tokio-runtime"] } +hickory-proto = "0.25.0-alpha.4" +hickory-resolver = { version = "0.25.0-alpha.4", default-features = false, features = ["system-config", "tokio-runtime"] } ttl_cache = "~0.5" wait-timeout = "~0.2" @@ -45,7 +45,12 @@ linked-hash-map = "^0.5.3" # https://rustsec.org/advisories/RUSTSEC-2024-0019 mio = "^0.8.11" # Pin to a lower version. -tokio = "~1.30.0" +tokio = { version = "~1.30.0", features = ["rt"] } +# Avoid an old dependency on `idna`. +url = "^2.5.4" +# Avoid transitive dependencies on `failure` and `atty` +web-sys = "~0.3.26" +bumpalo = "^3.11.1" [features] default = [] diff --git a/git-checks/src/changelog.rs b/git-checks/src/changelog.rs index 51f2329822e2a61b8eff2c5cf400e406be856fcb..4cdce51f4d84e1a99583a2df98de0a4242843af8 100644 --- a/git-checks/src/changelog.rs +++ b/git-checks/src/changelog.rs @@ -102,7 +102,7 @@ impl ChangelogStyle { let ext_ok = extension.as_ref().map_or(true, |ext| { diff_path .extension() - .map_or(false, |diff_ext| diff_ext == (ext.as_ref() as &Path)) + .is_some_and(|diff_ext| diff_ext == (ext.as_ref() as &Path)) }); ext_ok && diff_path.starts_with(path) diff --git a/git-checks/src/check_end_of_line.rs b/git-checks/src/check_end_of_line.rs index d0da5adad8c21a0ed54e64349a36f573108a2cc0..258877067292f25be0efd6301629b56dba11c61c 100644 --- a/git-checks/src/check_end_of_line.rs +++ b/git-checks/src/check_end_of_line.rs @@ -60,10 +60,7 @@ impl ContentCheck for CheckEndOfLine { }, }; - let has_missing_newline = patch - .lines() - .last() - .map_or(false, |line| line == "\\ No newline at end of file"); + let has_missing_newline = patch.lines().last() == Some("\\ No newline at end of file"); if has_missing_newline { result.add_error(format!( diff --git a/git-checks/src/check_executable_permissions.rs b/git-checks/src/check_executable_permissions.rs index 2960487e723f56c37d95e203359735bc39923c2d..e2fb5064dcde79fcb32c88144a446f7664996897 100644 --- a/git-checks/src/check_executable_permissions.rs +++ b/git-checks/src/check_executable_permissions.rs @@ -106,7 +106,7 @@ impl ContentCheck for CheckExecutablePermissions { true } else { binary_format::detect_binary_format(content) - .map_or(false, |fmt| fmt.is_executable()) + .is_some_and(|fmt| fmt.is_executable()) } }; diff --git a/git-checks/src/valid_name.rs b/git-checks/src/valid_name.rs index 1322baa8155d93aac2065f92f29011e32e5435c9..e70d42e2bcdbfa8d76014ff822b86eff9d581cf7 100644 --- a/git-checks/src/valid_name.rs +++ b/git-checks/src/valid_name.rs @@ -14,11 +14,13 @@ use std::time::{Duration, Instant}; use derive_builder::Builder; use git_checks_core::impl_prelude::*; +use hickory_proto::ProtoErrorKind; +use hickory_resolver::name_server::TokioConnectionProvider; +use hickory_resolver::{Name, ResolveError, ResolveErrorKind, Resolver}; use lazy_static::lazy_static; use log::{error, warn}; use thiserror::Error; -use trust_dns_resolver::error::ResolveErrorKind; -use trust_dns_resolver::{Name, Resolver}; +use tokio::runtime::Runtime; use ttl_cache::TtlCache; /// Configuration value for `ValidName` policy for use of full names in identities. @@ -60,7 +62,7 @@ const DEFAULT_TTL_CACHE_MISS_DURATION: Duration = Duration::from_secs(5 * 60); lazy_static! { // DNS resolver. - static ref DNS_RESOLVER: io::Result = Resolver::from_system_conf() + static ref DNS_RESOLVER: Result, ResolveError> = Resolver::tokio_from_system_conf() .map_err(|err| { error!( target: "git-checks/valid_name", @@ -189,19 +191,27 @@ impl HostLookup { enum ValidNameError { #[error("failed to initialize a DNS resolver: {}", reason)] NoResolver { reason: String }, + #[error("failed to start a tokio runtime: {}", source)] + TokioRuntime { source: io::Error }, #[error("failed to parse the domain name: {}", source)] ParseName { #[from] - source: trust_dns_proto::error::ProtoError, + source: hickory_proto::ProtoError, }, } impl ValidNameError { - fn no_resolver(source: &io::Error) -> Self { + fn no_resolver(source: &ResolveError) -> Self { Self::NoResolver { reason: format!("{}", source), } } + + fn tokio_runtime(source: io::Error) -> Self { + Self::TokioRuntime { + source, + } + } } impl ValidName { @@ -221,36 +231,50 @@ impl ValidName { // Search for the absolute domain. let abs_domain = format!("{}.", domain); let name = Name::from_str_relaxed(abs_domain)?; - let lookup = resolver.mx_lookup(name); + let lookup_async = resolver.mx_lookup(name); + + let rt = Runtime::new().map_err(ValidNameError::tokio_runtime)?; + let lookup = rt.block_on(lookup_async); Ok(match lookup { Ok(_) => Some(HostLookup::Hit), Err(err) => { - match err.kind() { - ResolveErrorKind::NoRecordsFound { - negative_ttl, .. - } => { - let valid_until = negative_ttl.and_then(|ttl| { - let ttl_duration = Duration::from_secs(ttl.into()); - let now = Instant::now(); - - now.checked_add(ttl_duration) - }); - Some(HostLookup::Miss { - valid_until, - }) - }, - ResolveErrorKind::Timeout => None, - _ => { - warn!( - target: "git-checks/valid_name", - "failed to look up MX record for domain {}: {:?}", - domain, - err, - ); - - None - }, + if let ResolveErrorKind::Proto(err) = err.kind() { + match err.kind() { + ProtoErrorKind::NoRecordsFound { + negative_ttl, .. + } => { + let valid_until = negative_ttl.and_then(|ttl| { + let ttl_duration = Duration::from_secs(ttl.into()); + let now = Instant::now(); + + now.checked_add(ttl_duration) + }); + Some(HostLookup::Miss { + valid_until, + }) + }, + ProtoErrorKind::Timeout => None, + _ => { + warn!( + target: "git-checks/valid_name", + "failed to look up MX record for domain {} (timeout): {:?}", + domain, + err, + ); + + None + }, + } + } else { + warn!( + target: "git-checks/valid_name", + "failed to look up MX record for domain {}: {:?}", + domain, + err, + ); + + None } }, }) @@ -271,7 +295,7 @@ impl ValidName { } if let Ok(lookup) = Self::check_host(domain) { - lookup.map_or(false, |lookup| { + lookup.is_some_and(|lookup| { let hit = lookup.is_hit(); cache.insert(domain.into(), hit, lookup.cache_duration()); hit