Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 172 additions & 2 deletions crates/empack-lib/src/application/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3601,9 +3601,28 @@ async fn continue_pending_restricted_build_inner(
let results = run_build_pipeline(session, &build_targets, archive_format, true).await?;
let restricted_entries = collect_restricted_entries(&results);
if !restricted_entries.is_empty() {
let cache_dir = pending.restricted_cache_path();
display_restricted_mod_infos(session, &cache_dir, &restricted_entries)?;
let rerun_comparison = compare_rerun_restricted_entries(&pending, &restricted_entries);
let (diagnostic, cache_label) = restricted_rerun_diagnostic(rerun_comparison);
session.display().status().warning(diagnostic);
if let Some(cache_label) = cache_label {
session
.display()
.status()
.info(&format!("{cache_label}: {}", cache_dir.display()));
}
let restricted_count = count_unique_restricted_mod_urls(&restricted_entries);
if let Some(detail) = restricted_rerun_error_detail(&restricted_entries) {
return Err(anyhow::anyhow!(
"{} restricted download(s) are still required after continue: {}",
restricted_count,
detail
));
}
return Err(anyhow::anyhow!(
"{} restricted download(s) are still required after continue",
count_unique_restricted_mod_urls(&restricted_entries)
restricted_count
));
}

Expand Down Expand Up @@ -3748,10 +3767,17 @@ fn count_unique_restricted_mod_urls(
let mut seen = std::collections::HashSet::new();
entries
.iter()
.filter(|entry| seen.insert(entry.url.clone()))
.filter(|entry| seen.insert(restricted_entry_url_key(&entry.url)))
.count()
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum RestrictedRerunComparison {
Same,
Subset,
Different,
}

fn restricted_download_dirs(
downloads_dir: Option<&str>,
pending: &crate::empack::restricted_build::PendingRestrictedBuild,
Expand Down Expand Up @@ -3790,6 +3816,150 @@ fn dedup_restricted_entry_urls(
.collect()
}

fn dedup_restricted_mod_infos(
entries: &[crate::empack::packwiz::RestrictedModInfo],
) -> Vec<&crate::empack::packwiz::RestrictedModInfo> {
let mut seen = std::collections::HashSet::new();
entries
.iter()
.filter(|entry| {
seen.insert((
restricted_entry_url_key(&entry.url),
entry.dest_path.clone(),
))
})
.collect()
}

fn dedup_restricted_mod_urls(
entries: &[crate::empack::packwiz::RestrictedModInfo],
) -> Vec<&crate::empack::packwiz::RestrictedModInfo> {
let mut seen = std::collections::HashSet::new();
entries
.iter()
.filter(|entry| seen.insert(restricted_entry_url_key(&entry.url)))
.collect()
}

fn restricted_entry_url_key(url: &str) -> String {
crate::empack::packwiz::restricted_curseforge_file_id(url)
.map(|file_id| format!("curseforge:{file_id}"))
.unwrap_or_else(|| url.to_string())
}

fn compare_rerun_restricted_entries(
pending: &crate::empack::restricted_build::PendingRestrictedBuild,
rerun_entries: &[crate::empack::packwiz::RestrictedModInfo],
) -> RestrictedRerunComparison {
let pending_signatures: HashSet<(String, String, String)> = pending
.entries
.iter()
.map(|entry| {
(
restricted_entry_url_key(&entry.url),
entry.dest_path.clone(),
entry.filename.clone(),
)
})
.collect();
let rerun_signatures: HashSet<(String, String, String)> = rerun_entries
.iter()
.map(|entry| {
(
restricted_entry_url_key(&entry.url),
entry.dest_path.clone(),
crate::empack::packwiz::restricted_destination_filename(&entry.dest_path)
.unwrap_or_default(),
)
})
.collect();

if rerun_signatures == pending_signatures {
RestrictedRerunComparison::Same
} else if rerun_signatures.is_subset(&pending_signatures) {
RestrictedRerunComparison::Subset
} else {
RestrictedRerunComparison::Different
}
}

fn restricted_rerun_diagnostic(
comparison: RestrictedRerunComparison,
) -> (&'static str, Option<&'static str>) {
match comparison {
RestrictedRerunComparison::Same => (
"The same restricted download(s) were reported again after restore. The managed cache entry may be stale, invalid, or the wrong file.",
Some("Managed cache"),
),
RestrictedRerunComparison::Subset => (
"A subset of the original restricted download(s) were reported again after restore. The remaining managed cache entries may be stale, invalid, or the wrong file.",
Some("Managed cache"),
),
RestrictedRerunComparison::Different => (
"The rerun reported a different restricted download set than the original pending state.",
None,
),
}
}

fn restricted_mod_info_summary(entry: &crate::empack::packwiz::RestrictedModInfo) -> String {
format!("{} [{} -> {}]", entry.name, entry.url, entry.dest_path)
}

fn restricted_rerun_error_detail(
rerun_entries: &[crate::empack::packwiz::RestrictedModInfo],
) -> Option<String> {
let summaries = dedup_restricted_mod_infos(rerun_entries)
.into_iter()
.map(restricted_mod_info_summary)
.collect::<Vec<_>>()
.join("; ");

if summaries.is_empty() {
None
} else {
Some(summaries)
}
}

fn display_restricted_mod_infos(
session: &dyn Session,
cache_dir: &Path,
restricted_entries: &[crate::empack::packwiz::RestrictedModInfo],
) -> Result<()> {
let unique_entries = dedup_restricted_mod_urls(restricted_entries);

session.display().status().section(&format!(
"Build incomplete: {} restricted download(s) are still required after continue",
unique_entries.len()
));

for entry in unique_entries {
session
.display()
.status()
.warning(&format!(" {}", entry.name));
session
.display()
.status()
.info(&format!(" Download: {}", entry.url));
if let Some(filename) =
crate::empack::packwiz::restricted_destination_filename(&entry.dest_path)
{
session.display().status().info(&format!(
" Cache as: {}",
cache_dir.join(filename).display()
));
}
session
.display()
.status()
.subtle(&format!(" Will restore to: {}", entry.dest_path));
}

Ok(())
}

fn display_pending_restricted_build(
session: &dyn Session,
pending: &crate::empack::restricted_build::PendingRestrictedBuild,
Expand Down
Loading
Loading