mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-07-22 05:55:15 +08:00
@@ -1459,8 +1459,9 @@ impl OfficialUpdateLock {
|
||||
continue;
|
||||
}
|
||||
return Err(anyhow::anyhow!(
|
||||
"官方资源目录已被锁定 (locked):{}",
|
||||
path.display()
|
||||
"官方资源目录已被锁定 (locked):{};{}",
|
||||
path.display(),
|
||||
describe_lock_owner(&path)
|
||||
));
|
||||
}
|
||||
Err(error) => {
|
||||
@@ -1481,14 +1482,21 @@ impl OfficialUpdateLock {
|
||||
|
||||
impl Drop for OfficialUpdateLock {
|
||||
fn drop(&mut self) {
|
||||
let _ = fs::remove_file(&self.path);
|
||||
let expected = std::process::id().to_string();
|
||||
if fs::read_to_string(&self.path)
|
||||
.map(|contents| contents.trim() == expected)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let _ = fs::remove_file(&self.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_stale_lock(path: &Path) -> anyhow::Result<bool> {
|
||||
let contents = fs::read_to_string(path).unwrap_or_default();
|
||||
let Some(pid) = parse_lock_pid(&contents) else {
|
||||
return Ok(false);
|
||||
fs::remove_file(path)?;
|
||||
return Ok(true);
|
||||
};
|
||||
if process_exists(pid) {
|
||||
return Ok(false);
|
||||
@@ -1498,6 +1506,15 @@ fn remove_stale_lock(path: &Path) -> anyhow::Result<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn describe_lock_owner(path: &Path) -> String {
|
||||
let contents = fs::read_to_string(path).unwrap_or_default();
|
||||
match parse_lock_pid(&contents) {
|
||||
Some(pid) if process_exists(pid) => format!("owner_pid={pid} 仍在运行"),
|
||||
Some(pid) => format!("owner_pid={pid} 已失效,可重新执行或 clean-stable 清理"),
|
||||
None => "锁文件内容不是有效 PID,可执行 clean-stable 清理".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_lock_pid(contents: &str) -> Option<u32> {
|
||||
contents.trim().parse::<u32>().ok().filter(|pid| *pid > 0)
|
||||
}
|
||||
@@ -1716,6 +1733,25 @@ mod tests {
|
||||
assert!(!config.lock_path().exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_dry_run_lock_removes_corrupt_pid_file() {
|
||||
let temp = tempfile::TempDir::new().unwrap();
|
||||
let config = OfficialUpdateConfig {
|
||||
output_root: temp.path().to_path_buf(),
|
||||
..OfficialUpdateConfig::default()
|
||||
};
|
||||
fs::create_dir_all(&config.output_root).unwrap();
|
||||
fs::write(config.lock_path(), "not-a-pid").unwrap();
|
||||
|
||||
let lock = OfficialUpdateLock::acquire(&config).unwrap();
|
||||
assert_eq!(
|
||||
fs::read_to_string(config.lock_path()).unwrap(),
|
||||
std::process::id().to_string()
|
||||
);
|
||||
drop(lock);
|
||||
assert!(!config.lock_path().exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_run_can_be_cancelled_before_network_work() {
|
||||
let temp = tempfile::TempDir::new().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user