mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 12:45:17 +08:00
fix(release): 修复发布一致性与并发边界
This commit is contained in:
@@ -3224,7 +3224,15 @@ fn copy_tree_no_symlink(
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if let Err(_error) = fs::hard_link(&source_path, &destination_path) {
|
||||
if is_release_local_mutable_state(&source_path) {
|
||||
fs::copy(&source_path, &destination_path).map_err(|copy_error| {
|
||||
format!(
|
||||
"复制官方 release mutable state 失败 {} -> {}:{copy_error}",
|
||||
source_path.display(),
|
||||
destination_path.display()
|
||||
)
|
||||
})?;
|
||||
} else if let Err(_error) = fs::hard_link(&source_path, &destination_path) {
|
||||
fs::copy(&source_path, &destination_path).map_err(|copy_error| {
|
||||
format!(
|
||||
"复制官方资源到 staging 失败 {} -> {}:{copy_error}",
|
||||
@@ -3243,6 +3251,17 @@ fn copy_tree_no_symlink(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_release_local_mutable_state(path: &Path) -> bool {
|
||||
matches!(
|
||||
path.file_name().and_then(|name| name.to_str()),
|
||||
Some(
|
||||
"translation-tasks.sqlite"
|
||||
| "translation-tasks.sqlite-wal"
|
||||
| "translation-tasks.sqlite-shm"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn switch_current_symlink(
|
||||
root: &Path,
|
||||
@@ -4415,6 +4434,46 @@ fn process_exists(_pid: u32) -> bool {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn staging_copy_does_not_hard_link_mutable_translation_state() {
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
let temp = tempfile::TempDir::new().unwrap();
|
||||
let source = temp.path().join("old");
|
||||
let destination = temp.path().join("new");
|
||||
fs::create_dir_all(&source).unwrap();
|
||||
fs::write(source.join("translation-tasks.sqlite"), b"old-db").unwrap();
|
||||
fs::write(source.join("translation-tasks.sqlite-wal"), b"old-wal").unwrap();
|
||||
fs::write(source.join("immutable.bundle"), b"payload").unwrap();
|
||||
|
||||
copy_tree_no_symlink(&source, &destination, false).unwrap();
|
||||
|
||||
let old_db_inode = fs::metadata(source.join("translation-tasks.sqlite"))
|
||||
.unwrap()
|
||||
.ino();
|
||||
let new_db_inode = fs::metadata(destination.join("translation-tasks.sqlite"))
|
||||
.unwrap()
|
||||
.ino();
|
||||
assert_ne!(old_db_inode, new_db_inode);
|
||||
fs::write(destination.join("translation-tasks.sqlite"), b"new-db").unwrap();
|
||||
fs::write(destination.join("translation-tasks.sqlite-wal"), b"new-wal").unwrap();
|
||||
assert_eq!(
|
||||
fs::read(source.join("translation-tasks.sqlite")).unwrap(),
|
||||
b"old-db"
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read(source.join("translation-tasks.sqlite-wal")).unwrap(),
|
||||
b"old-wal"
|
||||
);
|
||||
assert_eq!(
|
||||
fs::metadata(source.join("immutable.bundle")).unwrap().ino(),
|
||||
fs::metadata(destination.join("immutable.bundle"))
|
||||
.unwrap()
|
||||
.ino()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_app_version_carries_input_error_code() {
|
||||
// 未启用 auto-discover 且未传 app-version:配置校验失败应携带
|
||||
|
||||
Reference in New Issue
Block a user