difftreelog
feat(jrb) use native-tls on apple/windows-mingw
in: master
Otherwise it is has some quirks. Also allows downstreams to have different features for rustls if not building with jrb.
5 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -831,6 +831,21 @@
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
+[[package]]
name = "form_urlencoded"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1356,7 +1371,7 @@
checksum = "39eb0623e15e4cb83c02ce6a959e48fadd1ae3b715b36b5acc01816e01388c82"
dependencies = [
"bstr",
- "hashbrown 0.16.1",
+ "hashbrown 0.15.5",
]
[[package]]
@@ -2125,6 +2140,22 @@
]
[[package]]
+name = "hyper-tls"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
+dependencies = [
+ "bytes",
+ "http-body-util",
+ "hyper",
+ "hyper-util",
+ "native-tls",
+ "tokio",
+ "tokio-native-tls",
+ "tower-service",
+]
+
+[[package]]
name = "hyper-util"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2934,6 +2965,23 @@
]
[[package]]
+name = "native-tls"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2"
+dependencies = [
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
+[[package]]
name = "nix"
version = "0.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3017,12 +3065,50 @@
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
[[package]]
+name = "openssl"
+version = "0.10.78"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "openssl-probe"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
[[package]]
+name = "openssl-sys"
+version = "0.9.114"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3131,6 +3217,12 @@
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
+name = "pkg-config"
+version = "0.3.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
+
+[[package]]
name = "plain"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3470,10 +3562,12 @@
"http-body-util",
"hyper",
"hyper-rustls",
+ "hyper-tls",
"hyper-util",
"js-sys",
"log",
"mime",
+ "native-tls",
"percent-encoding",
"pin-project-lite",
"quinn",
@@ -3482,6 +3576,7 @@
"rustls-platform-verifier",
"sync_wrapper",
"tokio",
+ "tokio-native-tls",
"tokio-rustls",
"tower",
"tower-http",
@@ -4096,6 +4191,16 @@
]
[[package]]
+name = "tokio-native-tls"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
+dependencies = [
+ "native-tls",
+ "tokio",
+]
+
+[[package]]
name = "tokio-rustls"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4333,6 +4438,12 @@
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
Cargo.tomldiffbeforeafterboth--- a/Cargo.toml
+++ b/Cargo.toml
@@ -125,16 +125,12 @@
# Bundler
tracing = "0.1.44"
tracing-subscriber = { version = "0.3.23", features = ["env-filter"] }
-reqwest = { version = "0.13", features = [
+reqwest = { version = "0.13", default-features = false, features = [
"blocking",
- "rustls",
-], default-features = false }
+] }
zip = { version = "8", default-features = false, features = ["deflate"] }
directories = "6.0.0"
-gix = { version = "0.83.0", features = [
- "blocking-network-client",
- "blocking-http-transport-reqwest-rust-tls",
-] }
+gix = { version = "0.83.0", features = ["blocking-network-client"] }
camino = { version = "1.2.2", features = ["serde1"] }
[workspace.lints.rust]
crates/jrsonnet-pkg/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-pkg/Cargo.toml
+++ b/crates/jrsonnet-pkg/Cargo.toml
@@ -20,11 +20,21 @@
peg.workspace = true
# Gix for git repos, reqwest + zip for github
-gix.workspace = true
-reqwest.workspace = true
zip.workspace = true
url.workspace = true
camino.workspace = true
# Global cache dir
directories.workspace = true
+
+[target.'cfg(not(any(all(target_os = "windows", target_env = "gnu"), target_vendor = "apple")))'.dependencies]
+gix = { workspace = true, features = [
+ "blocking-http-transport-reqwest-rust-tls",
+] }
+reqwest = { workspace = true, features = ["rustls"] }
+
+[target.'cfg(any(all(target_os = "windows", target_env = "gnu"), target_vendor = "apple"))'.dependencies]
+gix = { workspace = true, features = [
+ "blocking-http-transport-reqwest-native-tls",
+] }
+reqwest = { workspace = true, features = ["native-tls"] }
crates/jrsonnet-pkg/src/install/github.rsdiffbeforeafterboth1#![allow(clippy::result_large_err)]23use std::{4 collections::HashSet,5 fs::{self, File},6 io::Write as _,7 path::{Path, PathBuf},8};910use camino::Utf8PathBuf;11use reqwest::{blocking::Response, header};12use tracing::{debug, info, warn};1314use super::{15 Error, LocalExtraction, ResolveResult, Result, VendorSource,16 accessor::{AccessorEntry, ZipFileAccessor},17 make_symlink,18};19use crate::{20 install::{PKG_USER_AGENT, cache_dir},21 jsonnet_bundler::{Dependency, GitSource, JsonnetFile, Source, SubDir},22};2324fn is_sha(s: &str) -> bool {25 s.len() == 40 && s.bytes().all(|b| b.is_ascii_hexdigit())26}2728fn commit_cache_path(source: &GitSource, sha: &str) -> Result<PathBuf> {29 Ok(cache_dir("github")?30 .join(source.plain_repo_name())31 .join(format!("{sha}.zip")))32}3334fn resolve_sha(source: &GitSource, version: &str) -> Result<String> {35 let url = format!(36 "https://api.github.com/repos/{}/commits/{}",37 source.plain_repo_name(),38 version39 );40 let response = reqwest::blocking::Client::new()41 .get(&url)42 .header(header::ACCEPT, "application/vnd.github.sha")43 .header(header::USER_AGENT, PKG_USER_AGENT)44 .send()45 .and_then(Response::error_for_status)?;46 let sha = response.text()?;47 Ok(sha.trim().to_owned())48}4950fn fetch_zip(source: &GitSource, sha: &str) -> Result<ZipFileAccessor> {51 let cached = commit_cache_path(source, sha)?;52 if cached.exists() {53 debug!("using cached archive {}", cached.display());54 return Ok(ZipFileAccessor::new_prefixed(55 File::open(&cached).map_err(|e| Error::Io(cached.clone(), e))?,56 )?);57 }5859 let url = format!(60 "https://github.com/{}/archive/{}.zip",61 source.plain_repo_name(),62 sha63 );64 info!("downloading {url}");6566 let bytes = reqwest::blocking::Client::new()67 .get(&url)68 .header(header::USER_AGENT, PKG_USER_AGENT)69 .send()70 .and_then(Response::error_for_status)?71 .bytes()?;7273 if let Some(parent) = cached.parent() {74 fs::create_dir_all(parent).map_err(|e| Error::Io(parent.to_owned(), e))?;75 }76 let mut downloaded = File::create_new(&cached).map_err(|e| Error::Io(cached.clone(), e))?;77 downloaded78 .write_all(&bytes)79 .map_err(|e| Error::Io(cached.clone(), e))?;8081 Ok(ZipFileAccessor::new_prefixed(downloaded)?)82}8384fn open_cached_zip(zip_path: &Path) -> Result<ZipFileAccessor> {85 Ok(ZipFileAccessor::new_prefixed(86 File::open(zip_path).map_err(|e| Error::Io(zip_path.to_owned(), e))?,87 )?)88}8990fn extract_subdir(archive: &ZipFileAccessor, subdir: &SubDir, dest: &Path) -> Result<()> {91 archive.iter(subdir, &mut |name, entry| {92 let target = dest.join(&name);93 match entry {94 AccessorEntry::Dir => {95 fs::create_dir_all(&target).map_err(|e| Error::Io(target, e))?;96 }97 AccessorEntry::File(data) => {98 if let Some(parent) = target.parent() {99 fs::create_dir_all(parent).map_err(|e| Error::Io(parent.to_owned(), e))?;100 }101 fs::write(&target, &data).map_err(|e| Error::Io(target, e))?;102 }103 AccessorEntry::Symlink(link_target) => {104 let symlink_parent = name105 .as_path()106 .parent()107 .map(|p| SubDir::try_from(Utf8PathBuf::from(p)))108 .transpose()109 .expect("parent of a SubDir is a SubDir")110 .unwrap_or_else(SubDir::empty);111 if link_target.resolve_under(&symlink_parent).is_err() {112 warn!("symlink {name} -> {link_target} escapes extraction; skipping");113 return Ok(());114 }115 if let Some(parent) = target.parent() {116 fs::create_dir_all(parent).map_err(|e| Error::Io(parent.to_owned(), e))?;117 }118 make_symlink(&link_target.to_string(), &target)119 .map_err(|e| Error::Io(target, e))?;120 }121 }122 Ok(())123 })124}125126fn collect_archive_deps(127 archive: &ZipFileAccessor,128 dir: &SubDir,129 git_deps: &mut Vec<Dependency>,130 local_extractions: &mut Vec<LocalExtraction>,131 visited: &mut HashSet<SubDir>,132) -> Result<()> {133 if !visited.insert(dir.clone()) {134 return Ok(());135 }136137 let manifest_path = dir138 .join("jsonnetfile.json")139 .expect("appending a literal filename keeps it within parent");140141 let Some(data) = archive.read(&manifest_path)? else {142 return Ok(());143 };144 let Ok(manifest) = serde_json::from_slice::<JsonnetFile>(&data) else {145 return Ok(());146 };147148 for dep in manifest.dependencies {149 match &dep.source {150 Source::Git(_) => git_deps.push(dep),151 Source::Local(local) => {152 let Ok(child_dir) = local.resolve_under(dir) else {153 tracing::info!("local source {local} escapes its package; skipping");154 continue;155 };156 let name = child_dir157 .file_name()158 .map_or_else(|| local.to_string(), str::to_owned);159 local_extractions.push(LocalExtraction {160 tree_path: child_dir.clone(),161 name,162 });163 collect_archive_deps(archive, &child_dir, git_deps, local_extractions, visited)?;164 }165 }166 }167 Ok(())168}169170pub(super) fn resolve(source: &GitSource, version: Option<&str>) -> Result<ResolveResult> {171 let version_str = version.unwrap_or("HEAD");172 let sha = if is_sha(version_str) {173 version_str.to_owned()174 } else {175 let resolved = resolve_sha(source, version_str)?;176 info!("resolved {version_str} to {resolved}");177 resolved178 };179180 let archive = fetch_zip(source, &sha)?;181182 let mut transitive_git_deps = Vec::new();183 let mut local_extractions = Vec::new();184 let mut visited = HashSet::new();185 collect_archive_deps(186 &archive,187 &source.subdir,188 &mut transitive_git_deps,189 &mut local_extractions,190 &mut visited,191 )?;192193 let zip_path = commit_cache_path(source, &sha)?;194195 Ok(ResolveResult {196 version: sha.clone(),197 transitive_git_deps,198 local_extractions,199 source: VendorSource::GithubZip {200 zip_path,201 commit_sha: sha,202 subdir: source.subdir.clone(),203 },204 })205}206207pub(super) fn extract(zip_path: &Path, subdir: &SubDir, dest: &Path) -> Result<()> {208 let archive = open_cached_zip(zip_path)?;209 extract_subdir(&archive, subdir, dest)210}crates/jrsonnet-pkg/src/install/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-pkg/src/install/mod.rs
+++ b/crates/jrsonnet-pkg/src/install/mod.rs
@@ -120,6 +120,24 @@
Ok(plan)
}
+#[cfg(unix)]
+fn make_symlink(target: &str, link: &Path) -> std::io::Result<()> {
+ std::os::unix::fs::symlink(target, link)
+}
+
+#[cfg(windows)]
+fn make_symlink(target: &str, link: &Path) -> std::io::Result<()> {
+ std::os::windows::fs::symlink_dir(target, link)
+}
+
+#[cfg(not(any(unix, windows)))]
+fn make_symlink(_target: &str, _link: &Path) -> std::io::Result<()> {
+ Err(std::io::Error::new(
+ std::io::ErrorKind::Unsupported,
+ "symlinks are not supported on this platform",
+ ))
+}
+
fn is_up_to_date(dest: &Path, version: &str) -> bool {
fs::read_to_string(dest.join(VERSION_FILE)).is_ok_and(|v| v.trim() == version)
}
@@ -182,8 +200,7 @@
fs::remove_file(&dest).map_err(|e| Error::Io(dest.clone(), e))?;
}
info!("symlink {path} -> {target}");
- std::os::unix::fs::symlink(target.as_std_path(), &dest)
- .map_err(|e| Error::Io(dest.clone(), e))?;
+ make_symlink(target.as_str(), &dest).map_err(|e| Error::Io(dest.clone(), e))?;
}
}
}