Skip to content

Commit 2b901be

Browse files
committed
Auto merge of #11713 - ehuss:publish-waiting-extra-info, r=epage
Add more information to wait-for-publish This reworks the console output when waiting for a publish to be available: * Shows a "Published" status to try to make it clear that the publish is complete, and that Cargo is moving to a separate phase. * Removes the repeated status bars and updating messages, and uses a single progress bar to track the publish. * Provides more of a description of why Cargo is waiting to try to make it clearer what is happening. * Provides more information when a timeout happens to try to explain what might be happening. * Shows a "Completed" message at the end to let the user know that everything is complete. Comparing the output: Before (with git): ``` Updating crates.io index Packaging delay v0.0.2 (/Users/eric/Proj/rust/cargo/target/tmp/cit/t0/foo) Packaged 3 files, 761.0B (569.0B compressed) Uploading delay v0.4.27 (/Users/eric/Proj/rust/cargo/target/tmp/cit/t0/foo) Updating crates.io index Waiting on `delay` to propagate to crates.io index (ctrl-c to wait asynchronously) Updating crates.io index Updating crates.io index Updating crates.io index Updating crates.io index Updating crates.io index Updating crates.io index Updating crates.io index Updating crates.io index Updating crates.io index Updating crates.io index ``` Before (with sparse): ``` Updating crates.io index Packaging delay v0.0.2 (/Users/eric/Proj/rust/cargo/target/tmp/cit/t0/foo) Packaged 3 files, 761.0B (569.0B compressed) Uploading delay v0.0.2 (/Users/eric/Proj/rust/cargo/target/tmp/cit/t0/foo) Updating crates.io index Waiting on `delay` to propagate to crates.io index (ctrl-c to wait asynchronously) Fetch [=============================> ] 36 complete; 1 pending ``` New (git or sparse): ``` Updating crates.io index Packaging delay v0.0.2 (/Users/eric/Proj/rust/cargo/target/tmp/cit/t0/foo) Packaged 3 files, 761.0B (569.0B compressed) Uploading delay v0.0.2 (/Users/eric/Proj/rust/cargo/target/tmp/cit/t0/foo) Uploaded delay v0.0.2 (/Users/eric/Proj/rust/cargo/target/tmp/cit/t0/foo) note: Waiting for `[email protected]` to be available at registry `crates-io`. You may press ctrl-c to skip waiting; the crate should be available shortly. Waiting [===> ] 11/60 Published delay v0.0.2 (/Users/eric/Proj/rust/cargo/target/tmp/cit/t0/foo) has been successfully published to registry `crates-io` ``` (Note: In the last two cases the progress bar disappears when it is done, I have just included it here to illustrate.) Fixes #11304
2 parents 97487fb + 3c295cf commit 2b901be

24 files changed

+563
-121
lines changed

crates/cargo-test-support/src/compare.rs

+2
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ fn substitute_macros(input: &str) -> String {
211211
("[DOWNLOADING]", " Downloading"),
212212
("[DOWNLOADED]", " Downloaded"),
213213
("[UPLOADING]", " Uploading"),
214+
("[UPLOADED]", " Uploaded"),
214215
("[VERIFYING]", " Verifying"),
215216
("[ARCHIVING]", " Archiving"),
216217
("[INSTALLING]", " Installing"),
@@ -232,6 +233,7 @@ fn substitute_macros(input: &str) -> String {
232233
("[EXECUTABLE]", " Executable"),
233234
("[SKIPPING]", " Skipping"),
234235
("[WAITING]", " Waiting"),
236+
("[PUBLISHED]", " Published"),
235237
];
236238
let mut result = input.to_owned();
237239
for &(pat, subst) in &macros {

crates/cargo-test-support/src/publish.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ pub(crate) fn create_index_line(
189189
json.to_string()
190190
}
191191

192-
pub(crate) fn write_to_index(registry_path: &PathBuf, name: &str, line: String, local: bool) {
192+
pub(crate) fn write_to_index(registry_path: &Path, name: &str, line: String, local: bool) {
193193
let file = cargo_util::registry::make_dep_path(name, false);
194194

195195
// Write file/line in the index.

crates/cargo-test-support/src/registry.rs

+73-38
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::fmt;
1313
use std::fs::{self, File};
1414
use std::io::{BufRead, BufReader, Read, Write};
1515
use std::net::{SocketAddr, TcpListener, TcpStream};
16-
use std::path::PathBuf;
16+
use std::path::{Path, PathBuf};
1717
use std::thread::{self, JoinHandle};
1818
use tar::{Builder, Header};
1919
use time::format_description::well_known::Rfc3339;
@@ -98,6 +98,8 @@ pub struct RegistryBuilder {
9898
configure_registry: bool,
9999
/// API responders.
100100
custom_responders: HashMap<&'static str, Box<dyn Send + Fn(&Request, &HttpServer) -> Response>>,
101+
/// If nonzero, the git index update to be delayed by the given number of seconds.
102+
delayed_index_update: usize,
101103
}
102104

103105
pub struct TestRegistry {
@@ -157,6 +159,7 @@ impl RegistryBuilder {
157159
configure_registry: true,
158160
configure_token: true,
159161
custom_responders: HashMap::new(),
162+
delayed_index_update: 0,
160163
}
161164
}
162165

@@ -171,6 +174,13 @@ impl RegistryBuilder {
171174
self
172175
}
173176

177+
/// Configures the git index update to be delayed by the given number of seconds.
178+
#[must_use]
179+
pub fn delayed_index_update(mut self, delay: usize) -> Self {
180+
self.delayed_index_update = delay;
181+
self
182+
}
183+
174184
/// Sets whether or not to initialize as an alternative registry.
175185
#[must_use]
176186
pub fn alternative_named(mut self, alt: &str) -> Self {
@@ -265,6 +275,7 @@ impl RegistryBuilder {
265275
token.clone(),
266276
self.auth_required,
267277
self.custom_responders,
278+
self.delayed_index_update,
268279
);
269280
let index_url = if self.http_index {
270281
server.index_url()
@@ -591,6 +602,7 @@ pub struct HttpServer {
591602
token: Token,
592603
auth_required: bool,
593604
custom_responders: HashMap<&'static str, Box<dyn Send + Fn(&Request, &HttpServer) -> Response>>,
605+
delayed_index_update: usize,
594606
}
595607

596608
/// A helper struct that collects the arguments for [`HttpServer::check_authorized`].
@@ -613,6 +625,7 @@ impl HttpServer {
613625
&'static str,
614626
Box<dyn Send + Fn(&Request, &HttpServer) -> Response>,
615627
>,
628+
delayed_index_update: usize,
616629
) -> HttpServerHandle {
617630
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
618631
let addr = listener.local_addr().unwrap();
@@ -625,6 +638,7 @@ impl HttpServer {
625638
token,
626639
auth_required,
627640
custom_responders: api_responders,
641+
delayed_index_update,
628642
};
629643
let handle = Some(thread::spawn(move || server.start()));
630644
HttpServerHandle { addr, handle }
@@ -1040,49 +1054,23 @@ impl HttpServer {
10401054
return self.unauthorized(req);
10411055
}
10421056

1043-
// Write the `.crate`
10441057
let dst = self
10451058
.dl_path
10461059
.join(&new_crate.name)
10471060
.join(&new_crate.vers)
10481061
.join("download");
1049-
t!(fs::create_dir_all(dst.parent().unwrap()));
1050-
t!(fs::write(&dst, file));
1051-
1052-
let deps = new_crate
1053-
.deps
1054-
.iter()
1055-
.map(|dep| {
1056-
let (name, package) = match &dep.explicit_name_in_toml {
1057-
Some(explicit) => (explicit.to_string(), Some(dep.name.to_string())),
1058-
None => (dep.name.to_string(), None),
1059-
};
1060-
serde_json::json!({
1061-
"name": name,
1062-
"req": dep.version_req,
1063-
"features": dep.features,
1064-
"default_features": true,
1065-
"target": dep.target,
1066-
"optional": dep.optional,
1067-
"kind": dep.kind,
1068-
"registry": dep.registry,
1069-
"package": package,
1070-
})
1071-
})
1072-
.collect::<Vec<_>>();
1073-
1074-
let line = create_index_line(
1075-
serde_json::json!(new_crate.name),
1076-
&new_crate.vers,
1077-
deps,
1078-
&file_cksum,
1079-
new_crate.features,
1080-
false,
1081-
new_crate.links,
1082-
None,
1083-
);
10841062

1085-
write_to_index(&self.registry_path, &new_crate.name, line, false);
1063+
if self.delayed_index_update == 0 {
1064+
save_new_crate(dst, new_crate, file, file_cksum, &self.registry_path);
1065+
} else {
1066+
let delayed_index_update = self.delayed_index_update;
1067+
let registry_path = self.registry_path.clone();
1068+
let file = Vec::from(file);
1069+
thread::spawn(move || {
1070+
thread::sleep(std::time::Duration::new(delayed_index_update as u64, 0));
1071+
save_new_crate(dst, new_crate, &file, file_cksum, &registry_path);
1072+
});
1073+
}
10861074

10871075
self.ok(&req)
10881076
} else {
@@ -1095,6 +1083,53 @@ impl HttpServer {
10951083
}
10961084
}
10971085

1086+
fn save_new_crate(
1087+
dst: PathBuf,
1088+
new_crate: crates_io::NewCrate,
1089+
file: &[u8],
1090+
file_cksum: String,
1091+
registry_path: &Path,
1092+
) {
1093+
// Write the `.crate`
1094+
t!(fs::create_dir_all(dst.parent().unwrap()));
1095+
t!(fs::write(&dst, file));
1096+
1097+
let deps = new_crate
1098+
.deps
1099+
.iter()
1100+
.map(|dep| {
1101+
let (name, package) = match &dep.explicit_name_in_toml {
1102+
Some(explicit) => (explicit.to_string(), Some(dep.name.to_string())),
1103+
None => (dep.name.to_string(), None),
1104+
};
1105+
serde_json::json!({
1106+
"name": name,
1107+
"req": dep.version_req,
1108+
"features": dep.features,
1109+
"default_features": true,
1110+
"target": dep.target,
1111+
"optional": dep.optional,
1112+
"kind": dep.kind,
1113+
"registry": dep.registry,
1114+
"package": package,
1115+
})
1116+
})
1117+
.collect::<Vec<_>>();
1118+
1119+
let line = create_index_line(
1120+
serde_json::json!(new_crate.name),
1121+
&new_crate.vers,
1122+
deps,
1123+
&file_cksum,
1124+
new_crate.features,
1125+
false,
1126+
new_crate.links,
1127+
None,
1128+
);
1129+
1130+
write_to_index(registry_path, &new_crate.name, line, false);
1131+
}
1132+
10981133
impl Package {
10991134
/// Creates a new package builder.
11001135
/// Call `publish()` to finalize and build the package.

src/cargo/core/source/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ pub trait Source {
4444
/// Ensure that the source is fully up-to-date for the current session on the next query.
4545
fn invalidate_cache(&mut self);
4646

47+
/// If quiet, the source should not display any progress or status messages.
48+
fn set_quiet(&mut self, quiet: bool);
49+
4750
/// Fetches the full package for each name and version specified.
4851
fn download(&mut self, package: PackageId) -> CargoResult<MaybePackage>;
4952

@@ -163,6 +166,10 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
163166
(**self).invalidate_cache()
164167
}
165168

169+
fn set_quiet(&mut self, quiet: bool) {
170+
(**self).set_quiet(quiet)
171+
}
172+
166173
/// Forwards to `Source::download`.
167174
fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {
168175
(**self).download(id)
@@ -233,6 +240,10 @@ impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
233240
(**self).invalidate_cache()
234241
}
235242

243+
fn set_quiet(&mut self, quiet: bool) {
244+
(**self).set_quiet(quiet)
245+
}
246+
236247
fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {
237248
(**self).download(id)
238249
}

src/cargo/ops/registry.rs

+36-20
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use crate::util::config::{Config, SslVersionConfig, SslVersionConfigRange};
3636
use crate::util::errors::CargoResult;
3737
use crate::util::important_paths::find_root_manifest_for_wd;
3838
use crate::util::{truncate_with_ellipsis, IntoUrl};
39+
use crate::util::{Progress, ProgressStyle};
3940
use crate::{drop_print, drop_println, version};
4041

4142
/// Registry settings loaded from config files.
@@ -442,13 +443,29 @@ fn wait_for_publish(
442443
) -> CargoResult<()> {
443444
let version_req = format!("={}", pkg.version());
444445
let mut source = SourceConfigMap::empty(config)?.load(registry_src, &HashSet::new())?;
445-
let source_description = source.describe();
446+
// Disable the source's built-in progress bars. Repeatedly showing a bunch
447+
// of independent progress bars can be a little confusing. There is an
448+
// overall progress bar managed here.
449+
source.set_quiet(true);
450+
let source_description = source.source_id().to_string();
446451
let query = Dependency::parse(pkg.name(), Some(&version_req), registry_src)?;
447452

448453
let now = std::time::Instant::now();
449454
let sleep_time = std::time::Duration::from_secs(1);
450-
let mut logged = false;
451-
loop {
455+
let max = timeout.as_secs() as usize;
456+
// Short does not include the registry name.
457+
let short_pkg_description = format!("{} v{}", pkg.name(), pkg.version());
458+
config.shell().status(
459+
"Uploaded",
460+
format!("{short_pkg_description} to {source_description}"),
461+
)?;
462+
config.shell().note(format!(
463+
"Waiting for `{short_pkg_description}` to be available at {source_description}.\n\
464+
You may press ctrl-c to skip waiting; the crate should be available shortly."
465+
))?;
466+
let mut progress = Progress::with_style("Waiting", ProgressStyle::Ratio, config);
467+
progress.tick_now(0, max, "")?;
468+
let is_available = loop {
452469
{
453470
let _lock = config.acquire_package_cache_lock()?;
454471
// Force re-fetching the source
@@ -470,31 +487,30 @@ fn wait_for_publish(
470487
}
471488
};
472489
if !summaries.is_empty() {
473-
break;
490+
break true;
474491
}
475492
}
476493

477-
if timeout < now.elapsed() {
494+
let elapsed = now.elapsed();
495+
if timeout < elapsed {
478496
config.shell().warn(format!(
479-
"timed out waiting for `{}` to be in {}",
480-
pkg.name(),
481-
source_description
497+
"timed out waiting for `{short_pkg_description}` to be available in {source_description}",
482498
))?;
483-
break;
484-
}
485-
486-
if !logged {
487-
config.shell().status(
488-
"Waiting",
489-
format!(
490-
"on `{}` to propagate to {} (ctrl-c to wait asynchronously)",
491-
pkg.name(),
492-
source_description
493-
),
499+
config.shell().note(
500+
"The registry may have a backlog that is delaying making the \
501+
crate available. The crate should be available soon.",
494502
)?;
495-
logged = true;
503+
break false;
496504
}
505+
506+
progress.tick_now(elapsed.as_secs() as usize, max, "")?;
497507
std::thread::sleep(sleep_time);
508+
};
509+
if is_available {
510+
config.shell().status(
511+
"Published",
512+
format!("{short_pkg_description} at {source_description}"),
513+
)?;
498514
}
499515

500516
Ok(())

src/cargo/sources/directory.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ impl<'cfg> Source for DirectorySource<'cfg> {
217217
}
218218

219219
fn invalidate_cache(&mut self) {
220-
// Path source has no local cache.
220+
// Directory source has no local cache.
221+
}
222+
223+
fn set_quiet(&mut self, _quiet: bool) {
224+
// Directory source does not display status
221225
}
222226
}

src/cargo/sources/git/source.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub struct GitSource<'cfg> {
2121
path_source: Option<PathSource<'cfg>>,
2222
ident: String,
2323
config: &'cfg Config,
24+
quiet: bool,
2425
}
2526

2627
impl<'cfg> GitSource<'cfg> {
@@ -43,6 +44,7 @@ impl<'cfg> GitSource<'cfg> {
4344
path_source: None,
4445
ident,
4546
config,
47+
quiet: false,
4648
};
4749

4850
Ok(source)
@@ -162,10 +164,12 @@ impl<'cfg> Source for GitSource<'cfg> {
162164
self.remote.url()
163165
);
164166
}
165-
self.config.shell().status(
166-
"Updating",
167-
format!("git repository `{}`", self.remote.url()),
168-
)?;
167+
if !self.quiet {
168+
self.config.shell().status(
169+
"Updating",
170+
format!("git repository `{}`", self.remote.url()),
171+
)?;
172+
}
169173

170174
trace!("updating git source `{:?}`", self.remote);
171175

@@ -233,6 +237,10 @@ impl<'cfg> Source for GitSource<'cfg> {
233237
}
234238

235239
fn invalidate_cache(&mut self) {}
240+
241+
fn set_quiet(&mut self, quiet: bool) {
242+
self.quiet = quiet;
243+
}
236244
}
237245

238246
#[cfg(test)]

src/cargo/sources/path.rs

+4
Original file line numberDiff line numberDiff line change
@@ -574,4 +574,8 @@ impl<'cfg> Source for PathSource<'cfg> {
574574
fn invalidate_cache(&mut self) {
575575
// Path source has no local cache.
576576
}
577+
578+
fn set_quiet(&mut self, _quiet: bool) {
579+
// Path source does not display status
580+
}
577581
}

0 commit comments

Comments
 (0)