Improve deployment after game update #92
3 changed files with 71 additions and 38 deletions
|
@ -525,6 +525,7 @@ where
|
|||
))]
|
||||
pub(crate) async fn deploy_mods(state: ActionState) -> Result<()> {
|
||||
let state = Arc::new(state);
|
||||
let bundle_dir = state.game_dir.join("bundle");
|
||||
|
||||
let (_, game_info, deployment_info) = tokio::try_join!(
|
||||
async {
|
||||
|
@ -565,16 +566,46 @@ pub(crate) async fn deploy_mods(state: ActionState) -> Result<()> {
|
|||
.map(|i| game_info.last_updated > i.timestamp)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
eyre::bail!("Game was updated since last mod deployment. Please reset first.");
|
||||
tracing::warn!(
|
||||
"Game was updated since last mod deployment. \
|
||||
Attempting to reconcile game files."
|
||||
);
|
||||
|
||||
tokio::try_join!(
|
||||
async {
|
||||
let path = bundle_dir.join(BUNDLE_DATABASE_NAME);
|
||||
let backup_path = path.with_extension("data.bak");
|
||||
|
||||
fs::copy(&path, &backup_path)
|
||||
.await
|
||||
.wrap_err("Failed to re-create backup for bundle database.")
|
||||
},
|
||||
async {
|
||||
let path = bundle_dir.join(BOOT_BUNDLE_NAME);
|
||||
let backup_path = path.with_extension("bak");
|
||||
|
||||
fs::copy(&path, &backup_path)
|
||||
.await
|
||||
.wrap_err("Failed to re-create backup for boot bundle")
|
||||
}
|
||||
)
|
||||
.with_suggestion(|| {
|
||||
"Reset the game using 'Reset Game', then verify game files.".to_string()
|
||||
})?;
|
||||
|
||||
tracing::info!(
|
||||
"Successfully re-created game file backups. \
|
||||
Continuing mod deployment."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
check_mod_order(&state)?;
|
||||
|
||||
tracing::info!(
|
||||
"Deploying {} mods to {}",
|
||||
"Deploying {} mods to '{}'.",
|
||||
state.mods.iter().filter(|i| i.enabled).count(),
|
||||
state.game_dir.join("bundle").display()
|
||||
bundle_dir.display()
|
||||
);
|
||||
|
||||
tracing::info!("Build mod bundles");
|
||||
|
@ -589,36 +620,32 @@ pub(crate) async fn deploy_mods(state: ActionState) -> Result<()> {
|
|||
bundles.append(&mut more_bundles);
|
||||
|
||||
if let Some(info) = &deployment_info {
|
||||
let bundle_dir = Arc::new(state.game_dir.join("bundle"));
|
||||
let tasks = info
|
||||
.bundles
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|v| (v, bundle_dir.clone()))
|
||||
.filter_map(|(file_name, bundle_dir)| {
|
||||
let contains = bundles.iter().any(|b2| {
|
||||
let name = b2.name().to_murmur64().to_string();
|
||||
file_name == name
|
||||
});
|
||||
|
||||
if !contains {
|
||||
let task = async move {
|
||||
let path = bundle_dir.join(&file_name);
|
||||
|
||||
tracing::debug!("Removing unused bundle '{}'", file_name);
|
||||
|
||||
if let Err(err) = fs::remove_file(&path).await.wrap_err_with(|| {
|
||||
format!("Failed to remove unused bundle '{}'", path.display())
|
||||
}) {
|
||||
tracing::error!("{:?}", err);
|
||||
}
|
||||
};
|
||||
Some(task)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let bundle_dir = Arc::new(bundle_dir);
|
||||
let tasks = info.bundles.iter().cloned().filter_map(|file_name| {
|
||||
let contains = bundles.iter().any(|b2| {
|
||||
let name = b2.name().to_murmur64().to_string();
|
||||
file_name == name
|
||||
});
|
||||
|
||||
if !contains {
|
||||
let bundle_dir = bundle_dir.clone();
|
||||
let task = async move {
|
||||
let path = bundle_dir.join(&file_name);
|
||||
|
||||
tracing::debug!("Removing unused bundle '{}'", file_name);
|
||||
|
||||
if let Err(err) = fs::remove_file(&path).await.wrap_err_with(|| {
|
||||
format!("Failed to remove unused bundle '{}'", path.display())
|
||||
}) {
|
||||
tracing::error!("{:?}", err);
|
||||
}
|
||||
};
|
||||
Some(task)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
futures::future::join_all(tasks).await;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use tokio::fs;
|
|||
use tokio_stream::wrappers::ReadDirStream;
|
||||
|
||||
#[tracing::instrument]
|
||||
pub async fn foo<P>(path: P) -> Vec<PathBuf>
|
||||
pub async fn process_path<P>(path: P) -> Vec<PathBuf>
|
||||
where
|
||||
P: AsRef<Path> + std::fmt::Debug,
|
||||
{
|
||||
|
@ -98,7 +98,10 @@ where
|
|||
I: Iterator<Item = PathBuf> + std::fmt::Debug,
|
||||
{
|
||||
let tasks = paths.map(|p| async move {
|
||||
match tokio::spawn(async move { foo(&p).await }).await {
|
||||
// Clippy doesn't understand that the block here is required to `move` in the reference.
|
||||
// The task is spawned to make sure tokio can distribute these over threads.
|
||||
#[allow(clippy::redundant_async_block)]
|
||||
match tokio::spawn(async move { process_path(&p).await }).await {
|
||||
Ok(paths) => paths,
|
||||
Err(err) => {
|
||||
tracing::error!(%err, "failed to spawn task to resolve bundle paths");
|
||||
|
@ -111,6 +114,9 @@ where
|
|||
results.into_iter().flatten().collect()
|
||||
}
|
||||
|
||||
// `tracing::instrument` generates code that triggers this warning.
|
||||
// Not much we can do to prevent that.
|
||||
#[allow(clippy::let_with_type_underscore)]
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub fn resolve_bundle_paths<I>(paths: I) -> impl Stream<Item = PathBuf>
|
||||
where
|
||||
|
@ -129,12 +135,12 @@ mod tests {
|
|||
use tempfile::tempdir;
|
||||
use tokio::process::Command;
|
||||
|
||||
use super::foo;
|
||||
use super::process_path;
|
||||
|
||||
#[tokio::test]
|
||||
async fn resolve_single_file() {
|
||||
let path = PathBuf::from("foo");
|
||||
let paths = foo(&path).await;
|
||||
let paths = process_path(&path).await;
|
||||
assert_eq!(paths.len(), 1);
|
||||
assert_eq!(paths[0], path);
|
||||
}
|
||||
|
@ -142,7 +148,7 @@ mod tests {
|
|||
#[tokio::test]
|
||||
async fn resolve_empty_directory() {
|
||||
let dir = tempdir().expect("failed to create temporary directory");
|
||||
let paths = foo(dir).await;
|
||||
let paths = process_path(dir).await;
|
||||
assert!(paths.is_empty());
|
||||
}
|
||||
|
||||
|
@ -170,7 +176,7 @@ mod tests {
|
|||
.await
|
||||
.expect("failed to create temporary files");
|
||||
|
||||
let paths = foo(dir).await;
|
||||
let paths = process_path(dir).await;
|
||||
|
||||
assert_eq!(bundle_names.len(), paths.len());
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 18797c4d2a53834210fd096dd39195ce7f2bce21
|
||||
Subproject commit 11c4eddaa4667ea7fffad40b034cf3fcb19fbdd3
|
Loading…
Add table
Reference in a new issue