refactor(core): 拆分越 400 行红线的 install.rs 与 install/libraries.rs
合并 termux-glibc 后两个文件顶破了「单文件 ≤400 行」(guards.yml 的 file-size): `game/java/install.rs` 379 → 456、`game/install/libraries.rs` 258 → 409。 按步骤拆,纯搬运、零行为变化: - `install/termux_install.rs`(新):Termux 系统包那条路。它与归档链不共用任何一步 (不查版本元数据、不下载、不解压、不校验 sha256),原来只能是一段嵌在 install() 中间的 if。返回 `Outcome::Done`/`Skipped` 并用 Box 装 `InstalledJdk`(否则 large_enum_variant: 392 vs 24 字节)。 - `install/one.rs`(新):回退链里「一家」的机械步骤——下载 → 解压 → 探测 + 幂等复用, 连同 `Prepared` 与 `note()`。 - `install/libraries/arm64_natives.rs`(新):Linux arm64 的 natives 改写与 Maven 兜底 (两个常量 + 改写/拼址两个函数)。用例仍留在 libraries.rs 的 tests 里,它们从 `plan()` 的出口断言,不碰私有步骤。 拆分后:install.rs 319、one.rs 100、termux_install.rs 104、libraries.rs 348、 arm64_natives.rs 72;全仓受检文件(*.rs/*.md/*.toml/*.yml/*.json/*.py/*.sh)复算 最大 400 行,红线内。
This commit is contained in:
1 parent
c82e39d0eb
commit
4dbeb07220
5 files changed
+302
-202
No files matched your search
@@ -18,6 +18,10 @@ use super::super::library::Library;
|
||||
use super::plan::{FileRole, PlanFile};
|
||||
use crate::download::ResourceKind;
|
||||
|
||||
use arm64_natives::{arm64_native_url, linux_arm64_native_entry, LINUX_ARM64_CLASSIFIER};
|
||||
|
||||
mod arm64_natives;
|
||||
|
||||
/// 没写 `url` 的库兜底用的 Maven 基址(Mojang 官方库仓)。
|
||||
pub const DEFAULT_MAVEN_BASE: &str = "https://libraries.minecraft.net/";
|
||||
|
||||
@@ -150,39 +154,6 @@ fn library_dest(
|
||||
}
|
||||
}
|
||||
|
||||
/// 现代清单里 LWJGL3 natives 条目的改写结果。
|
||||
struct Arm64Native {
|
||||
name: String,
|
||||
relative: PathBuf,
|
||||
url: String,
|
||||
}
|
||||
|
||||
/// Linux arm64:把 `org.lwjgl:<module>:<version>:natives-linux` 改写成 arm64。
|
||||
fn linux_arm64_native_entry(library: &Library, env: &Environment) -> Option<Arm64Native> {
|
||||
let name = library.linux_arm64_native_name(env)?;
|
||||
let base = name.strip_suffix(":natives-linux-arm64")?;
|
||||
let mut parts = base.split(':');
|
||||
let group = parts.next()?;
|
||||
let artifact = parts.next()?;
|
||||
let version = parts.next()?;
|
||||
if parts.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
let relative = PathBuf::from(format!(
|
||||
"{}/{artifact}/{version}/{artifact}-{version}-natives-linux-arm64.jar",
|
||||
group.replace('.', "/")
|
||||
));
|
||||
let url = format!(
|
||||
"{LINUX_ARM64_NATIVES_BASE}{}",
|
||||
relative.to_string_lossy().replace('\\', "/")
|
||||
);
|
||||
Some(Arm64Native {
|
||||
name,
|
||||
relative,
|
||||
url,
|
||||
})
|
||||
}
|
||||
|
||||
/// 按库声明(或默认)的 Maven 基址拼下载地址。
|
||||
fn maven_url(library: &Library, relative: &Path) -> String {
|
||||
let base = library
|
||||
@@ -199,22 +170,6 @@ fn maven_url(library: &Library, relative: &Path) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Linux arm64 的 natives 兜底仓库:Mojang 的 `libraries.minecraft.net` 对
|
||||
/// `natives-linux-arm64` 一律 404(实测 3.3.2 的 lwjgl/glfw/opengl/stb/tinyfd/openal),
|
||||
/// 同一坐标在 Maven Central / 阿里云镜像有。
|
||||
pub const LINUX_ARM64_NATIVES_BASE: &str = "https://maven.aliyun.com/repository/public/";
|
||||
|
||||
/// Linux arm64 的 natives 分类器(见 `Library::native_classifier`)。
|
||||
pub const LINUX_ARM64_CLASSIFIER: &str = "natives-linux-arm64";
|
||||
|
||||
/// arm64 natives 的兜底 URL(按相对路径拼镜像基址)。
|
||||
fn arm64_native_url(relative: &Path) -> String {
|
||||
format!(
|
||||
"{LINUX_ARM64_NATIVES_BASE}{}",
|
||||
relative.to_string_lossy().replace('\\', "/")
|
||||
)
|
||||
}
|
||||
|
||||
/// 供上层判错用:库展开不产生硬失败,缺地址一律降级成告警。
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
//! Linux arm64 的 natives 改写与下载兜底。
|
||||
//!
|
||||
//! 两件事实拼出来的特例:
|
||||
//! 1. Mojang 清单里 LWJGL3 的 natives 只写 `natives-linux`(x86_64 的 `.so`);
|
||||
//! 直接用它,在 aarch64 JVM 里加载必失败。
|
||||
//! 2. 同一个 Maven 坐标确实有 `natives-linux-arm64` 分类器,但 `libraries.minecraft.net`
|
||||
//! 对它一律 404(实测 3.3.2 的 lwjgl/glfw/opengl/stb/tinyfd/openal),Maven Central 与
|
||||
//! 阿里云镜像有。
|
||||
//!
|
||||
//! 所以 Linux arm64 上:分类器改写(`Library::native_classifier` /
|
||||
//! `Library::linux_arm64_native_name`)+ 地址兜底到镜像。**只在 linux + arm64 生效**,
|
||||
//! x86_64 / Windows / macOS 的地址一个字节不变。用例仍在 `libraries.rs` 的 tests 里
|
||||
//! (它们从 `plan()` 的出口断言,不直接调这里的私有步骤)。
|
||||
//!
|
||||
//! 从 `libraries.rs` 拆出来是为了守住 400 行红线(`guards.yml` 的 `file-size`)。
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::game::arguments::Environment;
|
||||
use crate::game::library::Library;
|
||||
|
||||
/// Linux arm64 的 natives 兜底仓库:Mojang 的 `libraries.minecraft.net` 对
|
||||
/// `natives-linux-arm64` 一律 404(实测 3.3.2 的 lwjgl/glfw/opengl/stb/tinyfd/openal),
|
||||
/// 同一坐标在 Maven Central / 阿里云镜像有。
|
||||
pub const LINUX_ARM64_NATIVES_BASE: &str = "https://maven.aliyun.com/repository/public/";
|
||||
|
||||
/// Linux arm64 的 natives 分类器(见 `Library::native_classifier`)。
|
||||
pub const LINUX_ARM64_CLASSIFIER: &str = "natives-linux-arm64";
|
||||
|
||||
/// 现代清单里 LWJGL3 natives 条目的改写结果。
|
||||
pub(super) struct Arm64Native {
|
||||
pub(super) name: String,
|
||||
pub(super) relative: PathBuf,
|
||||
pub(super) url: String,
|
||||
}
|
||||
|
||||
/// Linux arm64:把 `org.lwjgl:<module>:<version>:natives-linux` 改写成 arm64。
|
||||
pub(super) fn linux_arm64_native_entry(
|
||||
library: &Library,
|
||||
env: &Environment,
|
||||
) -> Option<Arm64Native> {
|
||||
let name = library.linux_arm64_native_name(env)?;
|
||||
let base = name.strip_suffix(":natives-linux-arm64")?;
|
||||
let mut parts = base.split(':');
|
||||
let group = parts.next()?;
|
||||
let artifact = parts.next()?;
|
||||
let version = parts.next()?;
|
||||
if parts.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
let relative = PathBuf::from(format!(
|
||||
"{}/{artifact}/{version}/{artifact}-{version}-natives-linux-arm64.jar",
|
||||
group.replace('.', "/")
|
||||
));
|
||||
let url = format!(
|
||||
"{LINUX_ARM64_NATIVES_BASE}{}",
|
||||
relative.to_string_lossy().replace('\\', "/")
|
||||
);
|
||||
Some(Arm64Native {
|
||||
name,
|
||||
relative,
|
||||
url,
|
||||
})
|
||||
}
|
||||
|
||||
/// arm64 natives 的兜底 URL(按相对路径拼镜像基址)。
|
||||
pub(super) fn arm64_native_url(relative: &Path) -> String {
|
||||
format!(
|
||||
"{LINUX_ARM64_NATIVES_BASE}{}",
|
||||
relative.to_string_lossy().replace('\\', "/")
|
||||
)
|
||||
}
|
||||
@@ -19,16 +19,21 @@
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use super::error::{io_error, JavaError, JavaErrorKind};
|
||||
use super::error::{JavaError, JavaErrorKind};
|
||||
use super::extract;
|
||||
use super::location::{JavaInstallRoot, LocationMode};
|
||||
use super::probe::{self, JavaOrigin, JavaRuntime};
|
||||
use super::release::{JdkArchive, JdkRelease};
|
||||
use super::probe::{self, JavaRuntime};
|
||||
use super::release::JdkRelease;
|
||||
use super::source::{self, ChainLog};
|
||||
use super::target::AdoptiumTarget;
|
||||
use super::vendor::{self, JdkVendor};
|
||||
use crate::download::{DownloadEngine, DownloadRequest, ResourceKind};
|
||||
|
||||
use one::install_one;
|
||||
|
||||
mod one;
|
||||
mod termux_install;
|
||||
|
||||
/// 归档缓存目录名(在安装根下;托管目录扫描跳过它)。
|
||||
pub use super::location::CACHE_DIR;
|
||||
|
||||
@@ -186,75 +191,24 @@ pub async fn install(
|
||||
) -> Result<InstalledJdk, JavaError> {
|
||||
let domestic = engine.region().is_domestic();
|
||||
let priority = request.order(domestic);
|
||||
let mut chain = ChainLog::new();
|
||||
let mut reasons: Vec<String> = Vec::new();
|
||||
// 清掉上次中断留下的 .staging-* 与空壳(只碰我们自己的形状,见 location 模块)。
|
||||
let _ = super::location::cleanup_orphans(&location.root);
|
||||
|
||||
// Termux:JDK 由系统包管理器装进 `$PREFIX`,不是可下载的归档。
|
||||
// 默认(没钉发行版)时优先走它;`--vendor termux` 时只走它。
|
||||
let want_termux = match request.vendor {
|
||||
Some(JdkVendor::Termux) => true,
|
||||
Some(_) => false,
|
||||
None => super::termux::available(),
|
||||
// Termux 那一条路(系统包)单独成模块:它与归档链不共用任何一步,见 `termux_install`。
|
||||
// 它把 chain 还回来(没走成时),归档链接着往上记。
|
||||
let mut chain = match termux_install::attempt(
|
||||
request.vendor,
|
||||
request.major,
|
||||
location,
|
||||
ChainLog::new(),
|
||||
&mut reasons,
|
||||
)
|
||||
.await?
|
||||
{
|
||||
termux_install::Outcome::Done(installed) => return Ok(*installed),
|
||||
termux_install::Outcome::Skipped(chain) => chain,
|
||||
};
|
||||
if want_termux {
|
||||
if !super::termux::available() {
|
||||
return Err(
|
||||
JavaError::new(JavaErrorKind::Unsupported, "termux 源只在 Termux 里可用")
|
||||
.with_hint("普通 Linux/Windows 用 --vendor temurin|oracle|microsoft|zulu"),
|
||||
);
|
||||
}
|
||||
match super::termux::install(request.major).await {
|
||||
Ok((home, reused)) => {
|
||||
let mut runtime = probe::probe(&extract::java_binary(&home), JavaOrigin::Managed);
|
||||
runtime.vendor = Some(JdkVendor::Termux.id().to_string());
|
||||
let version = runtime
|
||||
.version
|
||||
.clone()
|
||||
.unwrap_or_else(|| request.major.to_string());
|
||||
let release = JdkRelease {
|
||||
vendor: JdkVendor::Termux,
|
||||
major: request.major,
|
||||
version,
|
||||
semver: None,
|
||||
release_name: format!("Termux openjdk-{}", request.major),
|
||||
archive: JdkArchive {
|
||||
name: format!("openjdk-{}.deb", request.major),
|
||||
url: String::new(),
|
||||
sha256: String::new(),
|
||||
size: 0,
|
||||
},
|
||||
};
|
||||
chain.hit(JdkVendor::Termux, format!("命中 {}", release.summary()));
|
||||
return Ok(InstalledJdk {
|
||||
major: release.major,
|
||||
vendor: JdkVendor::Termux,
|
||||
release,
|
||||
root: home,
|
||||
mode: location.mode,
|
||||
archive: PathBuf::new(),
|
||||
runtime,
|
||||
downloaded: if reused {
|
||||
None
|
||||
} else {
|
||||
Some("termux".to_string())
|
||||
},
|
||||
bytes: 0,
|
||||
files: 0,
|
||||
extracted: false,
|
||||
chain,
|
||||
});
|
||||
}
|
||||
Err(error) => {
|
||||
if request.vendor == Some(JdkVendor::Termux) {
|
||||
return Err(error);
|
||||
}
|
||||
chain.failed(JdkVendor::Termux, error.message().to_string());
|
||||
reasons.push(format!("termux:{}", error.message()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 归档发行版需要 Adoptium 的平台参数;Termux/Android 上这里会 Unsupported,
|
||||
// 不提前 `?` 退出——让每一家都记一条降级原因,错误里能看见全貌。
|
||||
@@ -327,84 +281,6 @@ pub async fn install(
|
||||
.with_hint("`ull java vendors` 看各发行版的可用性;或手动装 JDK 后设 JAVA_HOME"))
|
||||
}
|
||||
|
||||
/// 某一家的中间结果(把七元组元组换成具名结构,读起来才不费劲)。
|
||||
struct Prepared {
|
||||
root: PathBuf,
|
||||
archive: PathBuf,
|
||||
runtime: JavaRuntime,
|
||||
downloaded: Option<String>,
|
||||
bytes: u64,
|
||||
files: usize,
|
||||
extracted: bool,
|
||||
}
|
||||
|
||||
/// 装某一家的那一份(下载 → 解压 → 探测)。
|
||||
async fn install_one(
|
||||
engine: &DownloadEngine,
|
||||
location: &JavaInstallRoot,
|
||||
release: &JdkRelease,
|
||||
) -> Result<Prepared, JavaError> {
|
||||
let root = location.jdk_dir(release.major, release.vendor, &release.version);
|
||||
let binary = extract::java_binary(&root);
|
||||
let archive = archive_path(&location.root, release);
|
||||
|
||||
// 幂等第一层:戳记里的 sha256 与本次一致,且 bin/java 在 → 一个字节都不动。
|
||||
if extract::is_ready(&root, release.sha256()) {
|
||||
let runtime = probe::probe(&binary, JavaOrigin::Managed);
|
||||
if runtime.major == Some(release.major) {
|
||||
let mut runtime = runtime;
|
||||
runtime.vendor = Some(release.vendor.id().to_string());
|
||||
return Ok(Prepared {
|
||||
root,
|
||||
archive,
|
||||
runtime,
|
||||
downloaded: None,
|
||||
bytes: 0,
|
||||
files: 0,
|
||||
extracted: false,
|
||||
});
|
||||
}
|
||||
note(&format!(
|
||||
"托管目录 {} 里的 java 跑不起来,重装一份",
|
||||
root.display()
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(parent) = archive.parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.map_err(|error| io_error("创建归档缓存目录", parent.display(), &error))?;
|
||||
}
|
||||
let outcome = engine
|
||||
.download(archive_request(release, archive.clone()))
|
||||
.await?;
|
||||
let report = extract::extract_archive(&archive, release.sha256(), release.major, &root)?;
|
||||
let mut runtime = probe::probe(&binary, JavaOrigin::Managed);
|
||||
runtime.vendor = Some(release.vendor.id().to_string());
|
||||
if runtime.major != Some(release.major) {
|
||||
return Err(JavaError::new(
|
||||
JavaErrorKind::Probe,
|
||||
format!(
|
||||
"装好的 JDK 探测结果是 Java {},与请求的 {} 不符({})",
|
||||
runtime
|
||||
.major
|
||||
.map_or_else(|| "未知".to_string(), |major| major.to_string()),
|
||||
release.major,
|
||||
binary.display()
|
||||
),
|
||||
)
|
||||
.with_hint("删掉该托管目录后重跑 `ull java install`;或手动设 JAVA_HOME"));
|
||||
}
|
||||
Ok(Prepared {
|
||||
root,
|
||||
archive,
|
||||
runtime,
|
||||
downloaded: Some(outcome.source),
|
||||
bytes: outcome.bytes,
|
||||
files: report.files,
|
||||
extracted: report.wrote(),
|
||||
})
|
||||
}
|
||||
|
||||
/// 只做规划不落盘:返回将要安装的版本、目标目录与「是否已经装好」。
|
||||
///
|
||||
/// # Errors
|
||||
@@ -446,11 +322,3 @@ fn majors_text(vendor: JdkVendor) -> String {
|
||||
.collect::<Vec<_>>()
|
||||
.join("/")
|
||||
}
|
||||
|
||||
fn note(message: &str) {
|
||||
if cfg!(debug_assertions) {
|
||||
eprintln!("[ull::game::java] {message}");
|
||||
} else {
|
||||
let _ = message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
//! 回退链里的「一家」怎么装:下载 → 解压 → 探测,外加幂等复用。
|
||||
//!
|
||||
//! 从 `install.rs` 拆出来是为了守住 400 行红线(`guards.yml` 的 `file-size`):
|
||||
//! `install.rs` 只保留「按优先级链挑一家 / 记降级原因」的编排,这里放单家的机械步骤。
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::super::error::{io_error, JavaError, JavaErrorKind};
|
||||
use super::super::extract;
|
||||
use super::super::location::JavaInstallRoot;
|
||||
use super::super::probe::{self, JavaOrigin, JavaRuntime};
|
||||
use super::super::release::JdkRelease;
|
||||
use super::{archive_path, archive_request};
|
||||
use crate::download::DownloadEngine;
|
||||
|
||||
/// 某一家的中间结果(把七元组元组换成具名结构,读起来才不费劲)。
|
||||
pub(super) struct Prepared {
|
||||
pub(super) root: PathBuf,
|
||||
pub(super) archive: PathBuf,
|
||||
pub(super) runtime: JavaRuntime,
|
||||
pub(super) downloaded: Option<String>,
|
||||
pub(super) bytes: u64,
|
||||
pub(super) files: usize,
|
||||
pub(super) extracted: bool,
|
||||
}
|
||||
|
||||
/// 装某一家的那一份(下载 → 解压 → 探测)。
|
||||
pub(super) async fn install_one(
|
||||
engine: &DownloadEngine,
|
||||
location: &JavaInstallRoot,
|
||||
release: &JdkRelease,
|
||||
) -> Result<Prepared, JavaError> {
|
||||
let root = location.jdk_dir(release.major, release.vendor, &release.version);
|
||||
let binary = extract::java_binary(&root);
|
||||
let archive = archive_path(&location.root, release);
|
||||
|
||||
// 幂等第一层:戳记里的 sha256 与本次一致,且 bin/java 在 → 一个字节都不动。
|
||||
if extract::is_ready(&root, release.sha256()) {
|
||||
let runtime = probe::probe(&binary, JavaOrigin::Managed);
|
||||
if runtime.major == Some(release.major) {
|
||||
let mut runtime = runtime;
|
||||
runtime.vendor = Some(release.vendor.id().to_string());
|
||||
return Ok(Prepared {
|
||||
root,
|
||||
archive,
|
||||
runtime,
|
||||
downloaded: None,
|
||||
bytes: 0,
|
||||
files: 0,
|
||||
extracted: false,
|
||||
});
|
||||
}
|
||||
note(&format!(
|
||||
"托管目录 {} 里的 java 跑不起来,重装一份",
|
||||
root.display()
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(parent) = archive.parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.map_err(|error| io_error("创建归档缓存目录", parent.display(), &error))?;
|
||||
}
|
||||
let outcome = engine
|
||||
.download(archive_request(release, archive.clone()))
|
||||
.await?;
|
||||
let report = extract::extract_archive(&archive, release.sha256(), release.major, &root)?;
|
||||
let mut runtime = probe::probe(&binary, JavaOrigin::Managed);
|
||||
runtime.vendor = Some(release.vendor.id().to_string());
|
||||
if runtime.major != Some(release.major) {
|
||||
return Err(JavaError::new(
|
||||
JavaErrorKind::Probe,
|
||||
format!(
|
||||
"装好的 JDK 探测结果是 Java {},与请求的 {} 不符({})",
|
||||
runtime
|
||||
.major
|
||||
.map_or_else(|| "未知".to_string(), |major| major.to_string()),
|
||||
release.major,
|
||||
binary.display()
|
||||
),
|
||||
)
|
||||
.with_hint("删掉该托管目录后重跑 `ull java install`;或手动设 JAVA_HOME"));
|
||||
}
|
||||
Ok(Prepared {
|
||||
root,
|
||||
archive,
|
||||
runtime,
|
||||
downloaded: Some(outcome.source),
|
||||
bytes: outcome.bytes,
|
||||
files: report.files,
|
||||
extracted: report.wrote(),
|
||||
})
|
||||
}
|
||||
|
||||
fn note(message: &str) {
|
||||
if cfg!(debug_assertions) {
|
||||
eprintln!("[ull::game::java] {message}");
|
||||
} else {
|
||||
let _ = message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
//! `install` 的 Termux 分支:JDK 由系统包管理器装进 `$PREFIX`,不是可下载的归档。
|
||||
//!
|
||||
//! 单独成模块有两个理由:`.deb` 这条路与归档链**没有共用步骤**(不查版本元数据、不下载、
|
||||
//! 不解压、不校验 sha256),留在 `install()` 里只能是一段嵌在中间的 if;而 `install.rs`
|
||||
//! 贴着 400 行红线(拆分前 456 行,见 `guards.yml` 的 `file-size`)。
|
||||
|
||||
use super::super::error::{JavaError, JavaErrorKind};
|
||||
use super::super::extract;
|
||||
use super::super::location::JavaInstallRoot;
|
||||
use super::super::probe::{self, JavaOrigin};
|
||||
use super::super::release::{JdkArchive, JdkRelease};
|
||||
use super::super::source::ChainLog;
|
||||
use super::super::vendor::JdkVendor;
|
||||
use super::InstalledJdk;
|
||||
|
||||
/// Termux 分支的结果。
|
||||
pub(super) enum Outcome {
|
||||
/// 系统包装成了,`install` 直接返回它(装箱只为让枚举别撑到 392 字节,
|
||||
/// 这条路一次安装才走一次)。
|
||||
Done(Box<InstalledJdk>),
|
||||
/// 不该走这条分支,或者走了但失败(原因已进 `chain` 与 `reasons`)——把 chain 还给调用方,
|
||||
/// 由它继续跑归档回退链。
|
||||
Skipped(ChainLog),
|
||||
}
|
||||
|
||||
/// 尝试走 Termux 系统包。
|
||||
///
|
||||
/// 语义(D23「`--vendor` 钉死一家、不自动降级」):
|
||||
/// - `pinned = Some(Termux)`:只走这条,失败直接冒泡;
|
||||
/// - `pinned = None`:Termux 上先试系统包,失败记一条降级原因后继续归档链;
|
||||
/// - 其它平台:`Ok(Skipped(chain))`,一个字节都不动。
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// 只有「钉死 termux」且失败时才返回错误;其余失败一律降级成 `reasons` 里的一行。
|
||||
pub(super) async fn attempt(
|
||||
pinned: Option<JdkVendor>,
|
||||
major: u32,
|
||||
location: &JavaInstallRoot,
|
||||
chain: ChainLog,
|
||||
reasons: &mut Vec<String>,
|
||||
) -> Result<Outcome, JavaError> {
|
||||
let wanted = match pinned {
|
||||
Some(JdkVendor::Termux) => true,
|
||||
Some(_) => false,
|
||||
None => super::super::termux::available(),
|
||||
};
|
||||
if !wanted {
|
||||
return Ok(Outcome::Skipped(chain));
|
||||
}
|
||||
if !super::super::termux::available() {
|
||||
return Err(
|
||||
JavaError::new(JavaErrorKind::Unsupported, "termux 源只在 Termux 里可用")
|
||||
.with_hint("普通 Linux/Windows 用 --vendor temurin|oracle|microsoft|zulu"),
|
||||
);
|
||||
}
|
||||
let mut chain = chain;
|
||||
match super::super::termux::install(major).await {
|
||||
Ok((home, reused)) => {
|
||||
let mut runtime = probe::probe(&extract::java_binary(&home), JavaOrigin::Managed);
|
||||
runtime.vendor = Some(JdkVendor::Termux.id().to_string());
|
||||
let version = runtime.version.clone().unwrap_or_else(|| major.to_string());
|
||||
let release = JdkRelease {
|
||||
vendor: JdkVendor::Termux,
|
||||
major,
|
||||
version,
|
||||
semver: None,
|
||||
release_name: format!("Termux openjdk-{major}"),
|
||||
archive: JdkArchive {
|
||||
name: format!("openjdk-{major}.deb"),
|
||||
url: String::new(),
|
||||
sha256: String::new(),
|
||||
size: 0,
|
||||
},
|
||||
};
|
||||
chain.hit(JdkVendor::Termux, format!("命中 {}", release.summary()));
|
||||
Ok(Outcome::Done(Box::new(InstalledJdk {
|
||||
major: release.major,
|
||||
vendor: JdkVendor::Termux,
|
||||
release,
|
||||
root: home,
|
||||
mode: location.mode,
|
||||
archive: std::path::PathBuf::new(),
|
||||
runtime,
|
||||
downloaded: if reused {
|
||||
None
|
||||
} else {
|
||||
Some("termux".to_string())
|
||||
},
|
||||
bytes: 0,
|
||||
files: 0,
|
||||
extracted: false,
|
||||
chain,
|
||||
})))
|
||||
}
|
||||
Err(error) => {
|
||||
if pinned == Some(JdkVendor::Termux) {
|
||||
return Err(error);
|
||||
}
|
||||
chain.failed(JdkVendor::Termux, error.message().to_string());
|
||||
reasons.push(format!("termux:{}", error.message()));
|
||||
Ok(Outcome::Skipped(chain))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user