Skip to content

Commit 6f47dd9

Browse files
committed
dist: decentralize download status
1 parent 3e2dd7b commit 6f47dd9

File tree

7 files changed

+62
-117
lines changed

7 files changed

+62
-117
lines changed

src/cli/self_update.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,14 +1275,7 @@ pub(crate) async fn prepare_update(dl_cfg: &DownloadCfg<'_>) -> Result<Option<Pa
12751275

12761276
// Download new version
12771277
info!("downloading self-update (new version: {available_version})");
1278-
download_file(
1279-
&download_url,
1280-
&setup_path,
1281-
None,
1282-
&dl_cfg.tracker,
1283-
dl_cfg.process,
1284-
)
1285-
.await?;
1278+
download_file(&download_url, &setup_path, None, None, dl_cfg.process).await?;
12861279

12871280
// Mark as executable
12881281
utils::make_executable(&setup_path)?;
@@ -1301,14 +1294,7 @@ async fn get_available_rustup_version(dl_cfg: &DownloadCfg<'_>) -> Result<String
13011294
let release_file_url = format!("{update_root}/release-stable.toml");
13021295
let release_file_url = utils::parse_url(&release_file_url)?;
13031296
let release_file = tempdir.path().join("release-stable.toml");
1304-
download_file(
1305-
&release_file_url,
1306-
&release_file,
1307-
None,
1308-
&dl_cfg.tracker,
1309-
dl_cfg.process,
1310-
)
1311-
.await?;
1297+
download_file(&release_file_url, &release_file, None, None, dl_cfg.process).await?;
13121298
let release_toml_str = utils::read_file("rustup release", &release_file)?;
13131299
let release_toml = toml::from_str::<RustupManifest>(&release_toml_str)
13141300
.context("unable to parse rustup release file")?;

src/cli/self_update/windows.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ pub(crate) async fn try_install_msvc(
277277
&visual_studio_url,
278278
&visual_studio,
279279
None,
280-
&dl_cfg.tracker,
280+
None,
281281
dl_cfg.process,
282282
)
283283
.await?;

src/dist/download.rs

Lines changed: 20 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use std::borrow::Cow;
22
use std::fs;
33
use std::ops;
44
use std::path::{Path, PathBuf};
@@ -76,7 +76,7 @@ impl<'a> DownloadCfg<'a> {
7676
&partial_file_path,
7777
Some(&mut hasher),
7878
true,
79-
&self.tracker,
79+
None,
8080
self.process,
8181
)
8282
.await
@@ -125,7 +125,7 @@ impl<'a> DownloadCfg<'a> {
125125
let hash_url = utils::parse_url(&(url.to_owned() + ".sha256"))?;
126126
let hash_file = self.tmp_cx.new_file()?;
127127

128-
download_file(&hash_url, &hash_file, None, &self.tracker, self.process).await?;
128+
download_file(&hash_url, &hash_file, None, None, self.process).await?;
129129

130130
utils::read_file("hash", &hash_file).map(|s| s[0..64].to_owned())
131131
}
@@ -139,6 +139,7 @@ impl<'a> DownloadCfg<'a> {
139139
&self,
140140
url_str: &str,
141141
update_hash: Option<&Path>,
142+
status: Option<&DownloadStatus>,
142143
ext: &str,
143144
) -> Result<Option<(temp::File, String)>> {
144145
let hash = self.download_hash(url_str).await?;
@@ -166,7 +167,7 @@ impl<'a> DownloadCfg<'a> {
166167
let file = self.tmp_cx.new_file_with_ext("", ext)?;
167168

168169
let mut hasher = Sha256::new();
169-
download_file(&url, &file, Some(&mut hasher), &self.tracker, self.process).await?;
170+
download_file(&url, &file, Some(&mut hasher), status, self.process).await?;
170171
let actual_hash = format!("{:x}", hasher.finalize());
171172

172173
if hash != actual_hash {
@@ -192,8 +193,6 @@ impl<'a> DownloadCfg<'a> {
192193
pub(crate) struct DownloadTracker {
193194
/// MultiProgress bar for the downloads.
194195
multi_progress_bars: MultiProgress,
195-
/// Mapping of URLs being downloaded to their corresponding download status.
196-
file_progress_bars: Mutex<HashMap<String, DownloadStatus>>,
197196
}
198197

199198
impl DownloadTracker {
@@ -207,70 +206,30 @@ impl DownloadTracker {
207206

208207
Self {
209208
multi_progress_bars,
210-
file_progress_bars: Mutex::new(HashMap::new()),
211209
}
212210
}
213211

214212
/// Creates a new ProgressBar for the given component.
215-
pub(crate) fn create_progress_bar(&self, component: String, url: String) {
213+
pub(crate) fn status_for(&self, component: impl Into<Cow<'static, str>>) -> DownloadStatus {
216214
let status = DownloadStatus::new(component);
217215
self.multi_progress_bars.add(status.progress.clone());
218-
self.file_progress_bars.lock().unwrap().insert(url, status);
219-
}
220-
221-
/// Sets the length for a new ProgressBar and gives it a style.
222-
pub(crate) fn content_length_received(&self, content_len: u64, url: &str) {
223-
if let Some(status) = self.file_progress_bars.lock().unwrap().get(url) {
224-
status.received_length(content_len);
225-
}
226-
}
227-
228-
/// Notifies self that data of size `len` has been received.
229-
pub(crate) fn data_received(&self, len: usize, url: &str) {
230-
let mut map = self.file_progress_bars.lock().unwrap();
231-
if let Some(status) = map.get_mut(url) {
232-
status.received_data(len);
233-
};
234-
}
235-
236-
/// Notifies self that the download has finished.
237-
pub(crate) fn download_finished(&self, url: &str) {
238-
let map = self.file_progress_bars.lock().unwrap();
239-
if let Some(status) = map.get(url) {
240-
status.finished()
241-
};
242-
}
243-
244-
/// Notifies self that the download has failed.
245-
pub(crate) fn download_failed(&self, url: &str) {
246-
let map = self.file_progress_bars.lock().unwrap();
247-
if let Some(status) = map.get(url) {
248-
status.failed();
249-
};
250-
}
251-
252-
/// Notifies self that the download is being retried.
253-
pub(crate) fn retrying_download(&self, url: &str) {
254-
let mut map = self.file_progress_bars.lock().unwrap();
255-
if let Some(status) = map.get_mut(url) {
256-
status.retrying();
257-
};
216+
status
258217
}
259218
}
260219

261-
struct DownloadStatus {
220+
pub(crate) struct DownloadStatus {
262221
progress: ProgressBar,
263222
/// The instant where the download is being retried.
264223
///
265224
/// Allows us to delay the reappearance of the progress bar so that the user can see
266225
/// the message "retrying download" for at least a second. Without it, the progress
267226
/// bar would reappear immediately, not allowing the user to correctly see the message,
268227
/// before the progress bar starts again.
269-
retry_time: Option<Instant>,
228+
retry_time: Mutex<Option<Instant>>,
270229
}
271230

272231
impl DownloadStatus {
273-
fn new(component: String) -> Self {
232+
fn new(component: impl Into<Cow<'static, str>>) -> Self {
274233
let progress = ProgressBar::hidden();
275234
progress.set_style(
276235
ProgressStyle::with_template(
@@ -283,25 +242,23 @@ impl DownloadStatus {
283242

284243
Self {
285244
progress,
286-
retry_time: None,
245+
retry_time: Mutex::new(None),
287246
}
288247
}
289248

290-
fn received_length(&self, len: u64) {
249+
pub(crate) fn received_length(&self, len: u64) {
291250
self.progress.reset();
292251
self.progress.set_length(len);
293252
}
294253

295-
fn received_data(&mut self, len: usize) {
254+
pub(crate) fn received_data(&self, len: usize) {
296255
self.progress.inc(len as u64);
297-
if !self
298-
.retry_time
299-
.is_some_and(|instant| instant.elapsed() > Duration::from_secs(1))
300-
{
256+
let mut retry_time = self.retry_time.lock().unwrap();
257+
if !retry_time.is_some_and(|instant| instant.elapsed() > Duration::from_secs(1)) {
301258
return;
302259
}
303260

304-
self.retry_time = None;
261+
*retry_time = None;
305262
self.progress.set_style(
306263
ProgressStyle::with_template(
307264
"{msg:>12.bold} [{bar:40}] {bytes}/{total_bytes} ({bytes_per_sec}, ETA: {eta})",
@@ -311,24 +268,24 @@ impl DownloadStatus {
311268
);
312269
}
313270

314-
fn finished(&self) {
271+
pub(crate) fn finished(&self) {
315272
self.progress.set_style(
316273
ProgressStyle::with_template("{msg:>12.bold} downloaded {total_bytes} in {elapsed}")
317274
.unwrap(),
318275
);
319276
self.progress.finish();
320277
}
321278

322-
fn failed(&self) {
279+
pub(crate) fn failed(&self) {
323280
self.progress.set_style(
324281
ProgressStyle::with_template("{msg:>12.bold} download failed after {elapsed}")
325282
.unwrap(),
326283
);
327284
self.progress.finish();
328285
}
329286

330-
fn retrying(&mut self) {
331-
self.retry_time = Some(Instant::now());
287+
pub(crate) fn retrying(&self) {
288+
*self.retry_time.lock().unwrap() = Some(Instant::now());
332289
self.progress
333290
.set_style(ProgressStyle::with_template("{msg:>12.bold} retrying download").unwrap());
334291
}

src/dist/manifestation.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::dist::component::{
1717
Components, Package, TarGzPackage, TarXzPackage, TarZStdPackage, Transaction,
1818
};
1919
use crate::dist::config::Config;
20-
use crate::dist::download::{DownloadCfg, File};
20+
use crate::dist::download::{DownloadCfg, DownloadStatus, File};
2121
use crate::dist::manifest::{Component, CompressionKind, HashedBinary, Manifest, TargetedPackage};
2222
use crate::dist::prefix::InstallPrefix;
2323
#[cfg(test)]
@@ -160,7 +160,15 @@ impl Manifestation {
160160
let mut things_downloaded = Vec::new();
161161
let components = update
162162
.components_urls_and_hashes(new_manifest)
163-
.map(|res| res.map(|(component, binary)| ComponentBinary { component, binary }))
163+
.map(|res| {
164+
res.map(|(component, binary)| ComponentBinary {
165+
component,
166+
binary,
167+
status: download_cfg
168+
.tracker
169+
.status_for(component.short_name(new_manifest)),
170+
})
171+
})
164172
.collect::<Result<Vec<_>>>()?;
165173

166174
let components_len = components.len();
@@ -179,13 +187,6 @@ impl Manifestation {
179187
.unwrap_or(DEFAULT_MAX_RETRIES);
180188

181189
info!("downloading component(s)");
182-
for bin in &components {
183-
download_cfg.tracker.create_progress_bar(
184-
bin.component.short_name(new_manifest),
185-
bin.binary.url.clone(),
186-
);
187-
}
188-
189190
let semaphore = Arc::new(Semaphore::new(concurrent_downloads));
190191
let component_stream = tokio_stream::iter(components.into_iter()).map(|bin| {
191192
let sem = semaphore.clone();
@@ -443,12 +444,9 @@ impl Manifestation {
443444
.unwrap()
444445
.replace(DEFAULT_DIST_SERVER, dl_cfg.tmp_cx.dist_server.as_str());
445446

446-
dl_cfg
447-
.tracker
448-
.create_progress_bar("rust".to_owned(), url.clone());
449-
447+
let status = dl_cfg.tracker.status_for("rust");
450448
let dl = dl_cfg
451-
.download_and_check(&url, update_hash, ".tar.gz")
449+
.download_and_check(&url, update_hash, Some(&status), ".tar.gz")
452450
.await?;
453451
if dl.is_none() {
454452
return Ok(None);
@@ -730,6 +728,7 @@ impl Update {
730728
struct ComponentBinary<'a> {
731729
component: &'a Component,
732730
binary: &'a HashedBinary,
731+
status: DownloadStatus,
733732
}
734733

735734
impl<'a> ComponentBinary<'a> {
@@ -750,7 +749,7 @@ impl<'a> ComponentBinary<'a> {
750749
match e.downcast_ref::<RustupError>() {
751750
Some(RustupError::BrokenPartialFile)
752751
| Some(RustupError::DownloadingFile { .. }) => {
753-
download_cfg.tracker.retrying_download(url.as_str());
752+
self.status.retrying();
754753
true
755754
}
756755
_ => false,

src/dist/manifestation/tests.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -489,14 +489,7 @@ impl TestContext {
489489
// Download the dist manifest and place it into the installation prefix
490490
let manifest_url = make_manifest_url(&self.url, &self.toolchain)?;
491491
let manifest_file = self.tmp_cx.new_file()?;
492-
download_file(
493-
&manifest_url,
494-
&manifest_file,
495-
None,
496-
&dl_cfg.tracker,
497-
dl_cfg.process,
498-
)
499-
.await?;
492+
download_file(&manifest_url, &manifest_file, None, None, dl_cfg.process).await?;
500493
let manifest_str = utils::read_file("manifest", &manifest_file)?;
501494
let manifest = Manifest::parse(&manifest_str)?;
502495

src/dist/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,7 +1236,7 @@ pub(crate) async fn dl_v2_manifest(
12361236
) -> Result<Option<(ManifestV2, String)>> {
12371237
let manifest_url = toolchain.manifest_v2_url(dist_root, download.process);
12381238
match download
1239-
.download_and_check(&manifest_url, update_hash, ".toml")
1239+
.download_and_check(&manifest_url, update_hash, None, ".toml")
12401240
.await
12411241
{
12421242
Ok(manifest_dl) => {
@@ -1293,7 +1293,9 @@ async fn dl_v1_manifest(
12931293
}
12941294

12951295
let manifest_url = toolchain.manifest_v1_url(dist_root, download.process);
1296-
let manifest_dl = download.download_and_check(&manifest_url, None, "").await?;
1296+
let manifest_dl = download
1297+
.download_and_check(&manifest_url, None, None, "")
1298+
.await?;
12971299
let (manifest_file, _) = manifest_dl.unwrap();
12981300
let manifest_str = utils::read_file("manifest", &manifest_file)?;
12991301
let urls = manifest_str

0 commit comments

Comments
 (0)