mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-07-23 07:55:15 +08:00
feat: add official sync progress logging
This commit is contained in:
@@ -8,8 +8,9 @@
|
||||
use crate::{
|
||||
build_official_pull_plan_for_platform_inventory, build_official_sync_plan,
|
||||
changed_endpoint_urls, default_official_platforms, OfficialGameMainConfigBootstrapService,
|
||||
OfficialLauncherBootstrapService, OfficialResourcePullPlan, OfficialResourcePullService,
|
||||
YostarJpLauncherGameConfig, YostarJpLauncherManifestUrl, YostarJpLauncherRemoteManifest,
|
||||
OfficialLauncherBootstrapService, OfficialResourcePullPlan, OfficialResourcePullProgress,
|
||||
OfficialResourcePullProgressKind, OfficialResourcePullService, YostarJpLauncherGameConfig,
|
||||
YostarJpLauncherManifestUrl, YostarJpLauncherRemoteManifest,
|
||||
};
|
||||
use bat_adapters::official::game_main_config::YostarJpGameMainConfig;
|
||||
use bat_adapters::official::inventory::{
|
||||
@@ -385,6 +386,25 @@ pub struct OfficialUpdateReport {
|
||||
pub snapshot_written: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// Human-readable progress emitted while one official update run is executing.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct OfficialUpdateProgress {
|
||||
/// Stable progress stage label.
|
||||
pub stage: &'static str,
|
||||
/// Human-readable status line.
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl OfficialUpdateProgress {
|
||||
/// Creates a progress event.
|
||||
pub fn new(stage: &'static str, message: impl Into<String>) -> Self {
|
||||
Self {
|
||||
stage,
|
||||
message: message.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Official update runner.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct OfficialUpdateService;
|
||||
@@ -397,10 +417,40 @@ impl OfficialUpdateService {
|
||||
|
||||
/// Executes one official update run.
|
||||
pub fn run(&self, config: &OfficialUpdateConfig) -> anyhow::Result<OfficialUpdateReport> {
|
||||
self.run_with_progress(config, |_| {})
|
||||
}
|
||||
|
||||
/// Executes one official update run and emits human-readable progress
|
||||
/// events. Structured reports are still returned separately.
|
||||
pub fn run_with_progress(
|
||||
&self,
|
||||
config: &OfficialUpdateConfig,
|
||||
mut progress: impl FnMut(OfficialUpdateProgress),
|
||||
) -> anyhow::Result<OfficialUpdateReport> {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"start",
|
||||
format!(
|
||||
"starting official resource sync: output={} dry_run={} auto_discover={}",
|
||||
config.output_root.display(),
|
||||
config.dry_run,
|
||||
config.auto_discover
|
||||
),
|
||||
));
|
||||
|
||||
let _lock = if config.dry_run {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"lock",
|
||||
"dry-run: skipping state lock",
|
||||
));
|
||||
None
|
||||
} else {
|
||||
Some(OfficialUpdateLock::acquire(config)?)
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"lock",
|
||||
format!("acquiring state lock {}", config.lock_path().display()),
|
||||
));
|
||||
let lock = OfficialUpdateLock::acquire(config)?;
|
||||
progress(OfficialUpdateProgress::new("lock", "state lock acquired"));
|
||||
Some(lock)
|
||||
};
|
||||
|
||||
let default_platforms = default_official_platforms();
|
||||
@@ -416,14 +466,27 @@ impl OfficialUpdateService {
|
||||
let bootstrap_cache_path = config.bootstrap_cache_path();
|
||||
|
||||
let bootstrap = if config.auto_discover {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"bootstrap",
|
||||
format!(
|
||||
"auto-discover enabled; launcher_version={} cache={}",
|
||||
config.launcher_version,
|
||||
bootstrap_cache_path.display()
|
||||
),
|
||||
));
|
||||
Some(resolve_bootstrap(
|
||||
&config.launcher_version,
|
||||
&config.curl_command,
|
||||
&config.unzip_command,
|
||||
&bootstrap_cache_path,
|
||||
!config.dry_run,
|
||||
&mut progress,
|
||||
)?)
|
||||
} else {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"bootstrap",
|
||||
"auto-discover disabled; using explicit metadata inputs",
|
||||
));
|
||||
None
|
||||
};
|
||||
|
||||
@@ -451,8 +514,24 @@ impl OfficialUpdateService {
|
||||
"missing connection group; pass it explicitly or enable auto-discover"
|
||||
)
|
||||
})?;
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"metadata",
|
||||
format!(
|
||||
"using app_version={} connection_group={} platforms={}",
|
||||
app_version,
|
||||
connection_group,
|
||||
platforms_label(platforms)
|
||||
),
|
||||
));
|
||||
|
||||
let server_info_bytes = if let Some(source) = config.server_info_source.as_ref() {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"server-info",
|
||||
format!(
|
||||
"loading server-info from {}",
|
||||
server_info_source_label(source)
|
||||
),
|
||||
));
|
||||
load_server_info(source, &fetcher)?
|
||||
} else {
|
||||
let bootstrap = bootstrap.as_ref().ok_or_else(|| {
|
||||
@@ -467,19 +546,47 @@ impl OfficialUpdateService {
|
||||
.ok_or_else(|| {
|
||||
anyhow::anyhow!("official GameMainConfig has no ServerInfoDataUrl")
|
||||
})?;
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"server-info",
|
||||
format!("fetching discovered server-info {url}"),
|
||||
));
|
||||
fetcher.fetch_bytes(url).map_err(anyhow::Error::msg)?
|
||||
};
|
||||
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"server-info",
|
||||
format!("parsing server-info bytes={}", server_info_bytes.len()),
|
||||
));
|
||||
let server_info = YostarJpServerInfo::from_slice(&server_info_bytes)?;
|
||||
let current_snapshot = server_info
|
||||
.sync_snapshot(&connection_group, &app_version, platforms)
|
||||
.map_err(anyhow::Error::msg)?;
|
||||
let endpoint_markers = collect_endpoint_markers(&fetcher, ¤t_snapshot)?;
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"discovery",
|
||||
format!(
|
||||
"resolved addressables_root={} endpoints={}",
|
||||
current_snapshot.addressables_root,
|
||||
current_snapshot.endpoints.len()
|
||||
),
|
||||
));
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"markers",
|
||||
format!(
|
||||
"checking {} remote marker endpoints",
|
||||
marker_endpoint_count(¤t_snapshot)
|
||||
),
|
||||
));
|
||||
let endpoint_markers =
|
||||
collect_endpoint_markers(&fetcher, ¤t_snapshot, &mut progress)?;
|
||||
let current_update_snapshot = OfficialUpdateSnapshot::new(
|
||||
current_snapshot.clone(),
|
||||
endpoint_markers,
|
||||
bootstrap.as_ref(),
|
||||
);
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"snapshot",
|
||||
format!("reading previous snapshot {}", snapshot_path.display()),
|
||||
));
|
||||
let previous_snapshot = read_snapshot(&snapshot_path)?;
|
||||
let previous_base_snapshot = previous_snapshot
|
||||
.as_ref()
|
||||
@@ -491,18 +598,48 @@ impl OfficialUpdateService {
|
||||
let changed_urls = changed_endpoint_urls(&sync_plan.delta);
|
||||
let remote_should_download =
|
||||
config.force || sync_plan.should_download() || extended_delta.has_changes();
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"decision",
|
||||
format!(
|
||||
"remote decision={:?} force={} remote_should_download={}",
|
||||
sync_plan.decision, config.force, remote_should_download
|
||||
),
|
||||
));
|
||||
let pull_plan = if config.audit_local || remote_should_download || config.plan {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"plan",
|
||||
"building official pull plan from seed catalogs",
|
||||
));
|
||||
Some(build_pull_plan(
|
||||
&server_info,
|
||||
&connection_group,
|
||||
&app_version,
|
||||
platforms,
|
||||
&fetcher,
|
||||
&mut progress,
|
||||
)?)
|
||||
} else {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"plan",
|
||||
"pull plan not needed for clean remote state and disabled plan output",
|
||||
));
|
||||
None
|
||||
};
|
||||
if let Some(pull_plan) = pull_plan.as_ref() {
|
||||
let url_count = pull_plan.all_urls().map_err(anyhow::Error::msg)?.len();
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"plan",
|
||||
format!("pull plan contains {url_count} official URLs"),
|
||||
));
|
||||
}
|
||||
let local_audit = if config.audit_local {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"audit",
|
||||
format!(
|
||||
"auditing local download manifest {}",
|
||||
fetcher.download_manifest_path().display()
|
||||
),
|
||||
));
|
||||
Some(
|
||||
fetcher
|
||||
.audit_local_manifest(
|
||||
@@ -513,6 +650,10 @@ impl OfficialUpdateService {
|
||||
.map_err(anyhow::Error::msg)?,
|
||||
)
|
||||
} else {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"audit",
|
||||
"local manifest audit disabled",
|
||||
));
|
||||
None
|
||||
};
|
||||
let local_manifest_verified_count = local_audit
|
||||
@@ -529,6 +670,20 @@ impl OfficialUpdateService {
|
||||
.map(|audit| !audit.is_clean())
|
||||
.unwrap_or(false);
|
||||
let should_download = remote_should_download || repair_needed;
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"audit",
|
||||
format!(
|
||||
"local manifest verified={} repair_needed={}",
|
||||
local_manifest_verified_count, local_manifest_repair_needed_count
|
||||
),
|
||||
));
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"decision",
|
||||
format!(
|
||||
"final should_download={} repair_needed={}",
|
||||
should_download, repair_needed
|
||||
),
|
||||
));
|
||||
let mut report = OfficialUpdateReport {
|
||||
update_status: if should_download {
|
||||
OfficialUpdateStatus::WouldDownload
|
||||
@@ -572,6 +727,10 @@ impl OfficialUpdateService {
|
||||
};
|
||||
|
||||
if !should_download {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"finish",
|
||||
"up to date; no download needed",
|
||||
));
|
||||
return Ok(report);
|
||||
}
|
||||
|
||||
@@ -586,18 +745,61 @@ impl OfficialUpdateService {
|
||||
.map_err(anyhow::Error::msg)?;
|
||||
report.download_url_count = Some(urls.len());
|
||||
report.download_urls = urls;
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"dry-run",
|
||||
format!(
|
||||
"dry-run plan generated {} URLs",
|
||||
report.download_url_count.unwrap_or(0)
|
||||
),
|
||||
));
|
||||
} else {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"dry-run",
|
||||
"dry-run detected pending download; full URL plan disabled",
|
||||
));
|
||||
}
|
||||
report.update_status = OfficialUpdateStatus::WouldDownload;
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"finish",
|
||||
"dry-run finished without writing state",
|
||||
));
|
||||
return Ok(report);
|
||||
}
|
||||
|
||||
let pull_plan = pull_plan
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow::anyhow!("download requested but no pull plan exists"))?;
|
||||
let pull_report = fetcher.pull(pull_plan).map_err(anyhow::Error::msg)?;
|
||||
let download_url_count = pull_plan.all_urls().map_err(anyhow::Error::msg)?.len();
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"download",
|
||||
format!("downloading or reusing {download_url_count} official URLs"),
|
||||
));
|
||||
let pull_report = fetcher
|
||||
.pull_with_progress(pull_plan, |event| {
|
||||
progress(progress_from_pull_event(event));
|
||||
})
|
||||
.map_err(anyhow::Error::msg)?;
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"download",
|
||||
format!(
|
||||
"download phase finished: downloaded={} resumed={} skipped={} transferred_bytes={}",
|
||||
pull_report.downloaded_count(),
|
||||
pull_report.resumed_count(),
|
||||
pull_report.skipped_count(),
|
||||
pull_report.transferred_bytes()
|
||||
),
|
||||
));
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"audit",
|
||||
"running final local manifest audit",
|
||||
));
|
||||
let final_audit = fetcher
|
||||
.audit_local_manifest(pull_plan)
|
||||
.map_err(anyhow::Error::msg)?;
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"snapshot",
|
||||
format!("writing snapshot {}", snapshot_path.display()),
|
||||
));
|
||||
write_snapshot(&snapshot_path, ¤t_update_snapshot)?;
|
||||
|
||||
report.update_status = OfficialUpdateStatus::Downloaded;
|
||||
@@ -612,6 +814,14 @@ impl OfficialUpdateService {
|
||||
report.local_manifest_repair_needed_count = final_audit.repair_needed_count();
|
||||
report.snapshot_written = Some(snapshot_path);
|
||||
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"finish",
|
||||
format!(
|
||||
"sync finished: resources={} official_hashes_verified={}",
|
||||
report.resource_count.unwrap_or(0),
|
||||
report.official_seed_hash_verified_count
|
||||
),
|
||||
));
|
||||
Ok(report)
|
||||
}
|
||||
}
|
||||
@@ -622,11 +832,25 @@ fn build_pull_plan(
|
||||
app_version: &str,
|
||||
platforms: &[PatchPlatform],
|
||||
fetcher: &OfficialResourcePullService,
|
||||
progress: &mut dyn FnMut(OfficialUpdateProgress),
|
||||
) -> anyhow::Result<OfficialResourcePullPlan> {
|
||||
let discovery = server_info
|
||||
.discovery_plan(connection_group, app_version, platforms)
|
||||
.map_err(anyhow::Error::msg)?;
|
||||
let seed_catalogs = fetch_seed_catalogs(fetcher, &discovery)?;
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"plan",
|
||||
format!(
|
||||
"discovery plan resolved: connection_group={} app_version={} endpoints={}",
|
||||
discovery.connection_group_name,
|
||||
discovery.app_version,
|
||||
discovery.endpoints.len()
|
||||
),
|
||||
));
|
||||
let seed_catalogs = fetch_seed_catalogs(fetcher, &discovery, progress)?;
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"inventory",
|
||||
"parsing seed catalogs into download inventory",
|
||||
));
|
||||
let inventory = build_inventory_from_seed_catalogs(&seed_catalogs, platforms)?;
|
||||
Ok(build_official_pull_plan_for_platform_inventory(
|
||||
discovery, inventory, platforms,
|
||||
@@ -652,6 +876,7 @@ fn load_server_info(
|
||||
fn collect_endpoint_markers(
|
||||
fetcher: &OfficialResourcePullService,
|
||||
snapshot: &YostarJpSyncSnapshot,
|
||||
progress: &mut dyn FnMut(OfficialUpdateProgress),
|
||||
) -> anyhow::Result<Vec<OfficialEndpointMarkerSnapshot>> {
|
||||
let mut markers = Vec::new();
|
||||
|
||||
@@ -659,6 +884,15 @@ fn collect_endpoint_markers(
|
||||
let Some(role) = marker_role(endpoint.kind) else {
|
||||
continue;
|
||||
};
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"marker",
|
||||
format!(
|
||||
"fetching {} marker{} {}",
|
||||
endpoint_kind_label(endpoint.kind),
|
||||
platform_suffix(endpoint.platform),
|
||||
endpoint.url
|
||||
),
|
||||
));
|
||||
let bytes = fetcher
|
||||
.fetch_bytes(&endpoint.url)
|
||||
.map_err(anyhow::Error::msg)?;
|
||||
@@ -689,6 +923,78 @@ fn marker_role(kind: YostarJpResourceEndpointKind) -> Option<OfficialEndpointMar
|
||||
}
|
||||
}
|
||||
|
||||
fn marker_endpoint_count(snapshot: &YostarJpSyncSnapshot) -> usize {
|
||||
snapshot
|
||||
.endpoints
|
||||
.iter()
|
||||
.filter(|endpoint| marker_role(endpoint.kind).is_some())
|
||||
.count()
|
||||
}
|
||||
|
||||
fn server_info_source_label(source: &OfficialServerInfoSource) -> String {
|
||||
match source {
|
||||
OfficialServerInfoSource::LocalPath(path) => format!("local path {}", path.display()),
|
||||
OfficialServerInfoSource::OfficialFile(file_name) => {
|
||||
format!("official file {file_name}")
|
||||
}
|
||||
OfficialServerInfoSource::OfficialUrl(url) => format!("official URL {url}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn platforms_label(platforms: &[PatchPlatform]) -> String {
|
||||
platforms
|
||||
.iter()
|
||||
.map(|platform| platform.as_str())
|
||||
.collect::<Vec<_>>()
|
||||
.join(",")
|
||||
}
|
||||
|
||||
fn endpoint_kind_label(kind: YostarJpResourceEndpointKind) -> &'static str {
|
||||
match kind {
|
||||
YostarJpResourceEndpointKind::TableCatalog => "table_catalog",
|
||||
YostarJpResourceEndpointKind::TableCatalogHash => "table_catalog_hash",
|
||||
YostarJpResourceEndpointKind::AddressablesCatalog => "addressables_catalog",
|
||||
YostarJpResourceEndpointKind::AddressablesCatalogHash => "addressables_catalog_hash",
|
||||
YostarJpResourceEndpointKind::BundlePackingInfo => "bundle_packing_info",
|
||||
YostarJpResourceEndpointKind::BundlePackingInfoHash => "bundle_packing_info_hash",
|
||||
YostarJpResourceEndpointKind::MediaCatalog => "media_catalog",
|
||||
YostarJpResourceEndpointKind::MediaCatalogHash => "media_catalog_hash",
|
||||
}
|
||||
}
|
||||
|
||||
fn platform_suffix(platform: Option<PatchPlatform>) -> String {
|
||||
platform
|
||||
.map(|platform| format!(" ({})", platform.as_str()))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn progress_from_pull_event(event: OfficialResourcePullProgress) -> OfficialUpdateProgress {
|
||||
match event.kind {
|
||||
OfficialResourcePullProgressKind::Started => OfficialUpdateProgress::new(
|
||||
"download",
|
||||
format!("({}/{}) started {}", event.index, event.total, event.url),
|
||||
),
|
||||
OfficialResourcePullProgressKind::Finished => {
|
||||
let status = event
|
||||
.status
|
||||
.map(|status| status.as_str())
|
||||
.unwrap_or("unknown");
|
||||
OfficialUpdateProgress::new(
|
||||
"download",
|
||||
format!(
|
||||
"({}/{}) finished status={} bytes={} transferred_bytes={} {}",
|
||||
event.index,
|
||||
event.total,
|
||||
status,
|
||||
event.bytes.unwrap_or(0),
|
||||
event.transferred_bytes.unwrap_or(0),
|
||||
event.url
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the extended snapshot delta.
|
||||
pub fn diff_extended_snapshot(
|
||||
current: &OfficialUpdateSnapshot,
|
||||
@@ -817,21 +1123,41 @@ fn resolve_bootstrap(
|
||||
unzip_command: &Path,
|
||||
cache_path: &Path,
|
||||
write_cache: bool,
|
||||
progress: &mut dyn FnMut(OfficialUpdateProgress),
|
||||
) -> anyhow::Result<ResolvedBootstrap> {
|
||||
let launcher = OfficialLauncherBootstrapService::with_curl_command(
|
||||
launcher_version,
|
||||
curl_command.to_string_lossy().to_string(),
|
||||
);
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"launcher",
|
||||
"fetching official launcher game config and remote manifest",
|
||||
));
|
||||
let (game_config, manifest_url, manifest) = launcher
|
||||
.fetch_latest_remote_manifest()
|
||||
.map_err(anyhow::Error::msg)?;
|
||||
let launcher_metadata =
|
||||
launcher_metadata_from_parts(launcher_version, &game_config, &manifest_url, &manifest);
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"launcher",
|
||||
format!(
|
||||
"launcher metadata resolved: latest_version={} manifest_files={}",
|
||||
launcher_metadata.game_latest_version, launcher_metadata.manifest_file_count
|
||||
),
|
||||
));
|
||||
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"bootstrap-cache",
|
||||
format!("checking bootstrap cache {}", cache_path.display()),
|
||||
));
|
||||
if let Some(cache) = read_bootstrap_cache(cache_path)? {
|
||||
if let Some(game_main_config) =
|
||||
cached_game_main_config_for_metadata(&cache, &launcher_metadata)
|
||||
{
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"bootstrap-cache",
|
||||
"cache hit; reusing parsed GameMainConfig",
|
||||
));
|
||||
return Ok(ResolvedBootstrap {
|
||||
launcher_metadata,
|
||||
game_main_config,
|
||||
@@ -840,6 +1166,10 @@ fn resolve_bootstrap(
|
||||
}
|
||||
}
|
||||
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"game-main-config",
|
||||
"cache miss; fetching resources.assets and parsing GameMainConfig",
|
||||
));
|
||||
let bootstrapper = OfficialGameMainConfigBootstrapService::with_commands(
|
||||
launcher_version,
|
||||
curl_command.to_path_buf(),
|
||||
@@ -867,6 +1197,15 @@ fn resolve_bootstrap(
|
||||
game_main_config: game_main_config.clone(),
|
||||
},
|
||||
)?;
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"bootstrap-cache",
|
||||
format!("bootstrap cache written {}", cache_path.display()),
|
||||
));
|
||||
} else {
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"bootstrap-cache",
|
||||
"dry-run: bootstrap cache not written",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ResolvedBootstrap {
|
||||
@@ -879,6 +1218,7 @@ fn resolve_bootstrap(
|
||||
fn fetch_seed_catalogs(
|
||||
fetcher: &OfficialResourcePullService,
|
||||
discovery: &YostarJpResourceDiscoveryPlan,
|
||||
progress: &mut dyn FnMut(OfficialUpdateProgress),
|
||||
) -> anyhow::Result<SeedCatalogs> {
|
||||
let mut catalogs = SeedCatalogs::default();
|
||||
|
||||
@@ -892,6 +1232,15 @@ fn fetch_seed_catalogs(
|
||||
continue;
|
||||
}
|
||||
|
||||
progress(OfficialUpdateProgress::new(
|
||||
"catalog",
|
||||
format!(
|
||||
"fetching seed catalog {}{} {}",
|
||||
endpoint_kind_label(endpoint.kind),
|
||||
platform_suffix(endpoint.platform),
|
||||
endpoint.url
|
||||
),
|
||||
));
|
||||
let bytes = fetcher
|
||||
.fetch_bytes(&endpoint.url)
|
||||
.map_err(anyhow::Error::msg)?;
|
||||
|
||||
Reference in New Issue
Block a user