git.delta.rocks / jrsonnet / refs/commits / 80f6128c09ce

difftreelog

feat(jrb) use native-tls on apple/windows-mingw

pkwxmtqpYaroslav Bolyukin2026-05-07parent: #de9f0cb.patch.diff
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

modifiedCargo.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"
modifiedCargo.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]
modifiedcrates/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"] }
modifiedcrates/jrsonnet-pkg/src/install/github.rsdiffbeforeafterboth
after · crates/jrsonnet-pkg/src/install/github.rs
1#![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}
modifiedcrates/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))?;
 			}
 		}
 	}