Skip to content

Commit 4111520

Browse files
committed
dist: decentralize download status
1 parent d8cc07a commit 4111520

File tree

6 files changed

+61
-121
lines changed

6 files changed

+61
-121
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/dist/download.rs

Lines changed: 20 additions & 68 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,13 +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 progress bars.
196-
/// The `Option<Instant>` represents the instant where the download is being retried,
197-
/// allowing us delay the reappearance of the progress bar so that the user can see
198-
/// the message "retrying download" for at least a second.
199-
/// Without it, the progress bar would reappear immediately, not allowing the user to
200-
/// correctly see the message, before the progress bar starts again.
201-
file_progress_bars: Mutex<HashMap<String, DownloadStatus>>,
202196
}
203197

204198
impl DownloadTracker {
@@ -212,64 +206,24 @@ impl DownloadTracker {
212206

213207
Self {
214208
multi_progress_bars,
215-
file_progress_bars: Mutex::new(HashMap::new()),
216209
}
217210
}
218211

219212
/// Creates a new ProgressBar for the given component.
220-
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 {
221214
let status = DownloadStatus::new(component);
222215
self.multi_progress_bars.add(status.progress.clone());
223-
self.file_progress_bars.lock().unwrap().insert(url, status);
224-
}
225-
226-
/// Sets the length for a new ProgressBar and gives it a style.
227-
pub(crate) fn content_length_received(&self, content_len: u64, url: &str) {
228-
if let Some(status) = self.file_progress_bars.lock().unwrap().get(url) {
229-
status.received_length(content_len);
230-
}
231-
}
232-
233-
/// Notifies self that data of size `len` has been received.
234-
pub(crate) fn data_received(&self, len: usize, url: &str) {
235-
let mut map = self.file_progress_bars.lock().unwrap();
236-
if let Some(status) = map.get_mut(url) {
237-
status.received_data(len);
238-
};
239-
}
240-
241-
/// Notifies self that the download has finished.
242-
pub(crate) fn download_finished(&self, url: &str) {
243-
let map = self.file_progress_bars.lock().unwrap();
244-
if let Some(status) = map.get(url) {
245-
status.finished()
246-
};
247-
}
248-
249-
/// Notifies self that the download has failed.
250-
pub(crate) fn download_failed(&self, url: &str) {
251-
let map = self.file_progress_bars.lock().unwrap();
252-
if let Some(status) = map.get(url) {
253-
status.failed();
254-
};
255-
}
256-
257-
/// Notifies self that the download is being retried.
258-
pub(crate) fn retrying_download(&self, url: &str) {
259-
let mut map = self.file_progress_bars.lock().unwrap();
260-
if let Some(status) = map.get_mut(url) {
261-
status.retrying();
262-
};
216+
status
263217
}
264218
}
265219

266-
struct DownloadStatus {
220+
pub(crate) struct DownloadStatus {
267221
progress: ProgressBar,
268-
retry_time: Option<Instant>,
222+
retry_time: Mutex<Option<Instant>>,
269223
}
270224

271225
impl DownloadStatus {
272-
fn new(component: String) -> Self {
226+
fn new(component: impl Into<Cow<'static, str>>) -> Self {
273227
let progress = ProgressBar::hidden();
274228
progress.set_style(
275229
ProgressStyle::with_template(
@@ -282,25 +236,23 @@ impl DownloadStatus {
282236

283237
Self {
284238
progress,
285-
retry_time: None,
239+
retry_time: Mutex::new(None),
286240
}
287241
}
288242

289-
fn received_length(&self, len: u64) {
243+
pub(crate) fn received_length(&self, len: u64) {
290244
self.progress.reset();
291245
self.progress.set_length(len);
292246
}
293247

294-
fn received_data(&mut self, len: usize) {
248+
pub(crate) fn received_data(&self, len: usize) {
295249
self.progress.inc(len as u64);
296-
if !self
297-
.retry_time
298-
.is_some_and(|instant| instant.elapsed() > Duration::from_secs(1))
299-
{
250+
let mut retry_time = self.retry_time.lock().unwrap();
251+
if !retry_time.is_some_and(|instant| instant.elapsed() > Duration::from_secs(1)) {
300252
return;
301253
}
302254

303-
self.retry_time = None;
255+
*retry_time = None;
304256
self.progress.set_style(
305257
ProgressStyle::with_template(
306258
"{msg:>12.bold} [{bar:40}] {bytes}/{total_bytes} ({bytes_per_sec}, ETA: {eta})",
@@ -310,24 +262,24 @@ impl DownloadStatus {
310262
);
311263
}
312264

313-
fn finished(&self) {
265+
pub(crate) fn finished(&self) {
314266
self.progress.set_style(
315267
ProgressStyle::with_template("{msg:>12.bold} downloaded {total_bytes} in {elapsed}")
316268
.unwrap(),
317269
);
318270
self.progress.finish();
319271
}
320272

321-
fn failed(&self) {
273+
pub(crate) fn failed(&self) {
322274
self.progress.set_style(
323275
ProgressStyle::with_template("{msg:>12.bold} download failed after {elapsed}")
324276
.unwrap(),
325277
);
326278
self.progress.finish();
327279
}
328280

329-
fn retrying(&mut self) {
330-
self.retry_time = Some(Instant::now());
281+
pub(crate) fn retrying(&self) {
282+
*self.retry_time.lock().unwrap() = Some(Instant::now());
331283
self.progress
332284
.set_style(ProgressStyle::with_template("{msg:>12.bold} retrying download").unwrap());
333285
}

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)