diff --git a/crates/cargo-test-support/src/compare.rs b/crates/cargo-test-support/src/compare.rs index 3a60ac5d789..96ce52afcd7 100644 --- a/crates/cargo-test-support/src/compare.rs +++ b/crates/cargo-test-support/src/compare.rs @@ -211,6 +211,7 @@ fn substitute_macros(input: &str) -> String { ("[DOWNLOADING]", " Downloading"), ("[DOWNLOADED]", " Downloaded"), ("[UPLOADING]", " Uploading"), + ("[UPLOADED]", " Uploaded"), ("[VERIFYING]", " Verifying"), ("[ARCHIVING]", " Archiving"), ("[INSTALLING]", " Installing"), @@ -232,6 +233,7 @@ fn substitute_macros(input: &str) -> String { ("[EXECUTABLE]", " Executable"), ("[SKIPPING]", " Skipping"), ("[WAITING]", " Waiting"), + ("[PUBLISHED]", " Published"), ]; let mut result = input.to_owned(); for &(pat, subst) in ¯os { diff --git a/crates/cargo-test-support/src/publish.rs b/crates/cargo-test-support/src/publish.rs index 85bc93cbdf7..64774bc43c8 100644 --- a/crates/cargo-test-support/src/publish.rs +++ b/crates/cargo-test-support/src/publish.rs @@ -189,7 +189,7 @@ pub(crate) fn create_index_line( json.to_string() } -pub(crate) fn write_to_index(registry_path: &PathBuf, name: &str, line: String, local: bool) { +pub(crate) fn write_to_index(registry_path: &Path, name: &str, line: String, local: bool) { let file = cargo_util::registry::make_dep_path(name, false); // Write file/line in the index. diff --git a/crates/cargo-test-support/src/registry.rs b/crates/cargo-test-support/src/registry.rs index 7b1dc541a42..cb63b29ca9f 100644 --- a/crates/cargo-test-support/src/registry.rs +++ b/crates/cargo-test-support/src/registry.rs @@ -13,7 +13,7 @@ use std::fmt; use std::fs::{self, File}; use std::io::{BufRead, BufReader, Read, Write}; use std::net::{SocketAddr, TcpListener, TcpStream}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::thread::{self, JoinHandle}; use tar::{Builder, Header}; use time::format_description::well_known::Rfc3339; @@ -98,6 +98,8 @@ pub struct RegistryBuilder { configure_registry: bool, /// API responders. custom_responders: HashMap<&'static str, Box Response>>, + /// If nonzero, the git index update to be delayed by the given number of seconds. + delayed_index_update: usize, } pub struct TestRegistry { @@ -157,6 +159,7 @@ impl RegistryBuilder { configure_registry: true, configure_token: true, custom_responders: HashMap::new(), + delayed_index_update: 0, } } @@ -171,6 +174,13 @@ impl RegistryBuilder { self } + /// Configures the git index update to be delayed by the given number of seconds. + #[must_use] + pub fn delayed_index_update(mut self, delay: usize) -> Self { + self.delayed_index_update = delay; + self + } + /// Sets whether or not to initialize as an alternative registry. #[must_use] pub fn alternative_named(mut self, alt: &str) -> Self { @@ -265,6 +275,7 @@ impl RegistryBuilder { token.clone(), self.auth_required, self.custom_responders, + self.delayed_index_update, ); let index_url = if self.http_index { server.index_url() @@ -591,6 +602,7 @@ pub struct HttpServer { token: Token, auth_required: bool, custom_responders: HashMap<&'static str, Box Response>>, + delayed_index_update: usize, } /// A helper struct that collects the arguments for [HttpServer::check_authorized]. @@ -613,6 +625,7 @@ impl HttpServer { &'static str, Box Response>, >, + delayed_index_update: usize, ) -> HttpServerHandle { let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); @@ -625,6 +638,7 @@ impl HttpServer { token, auth_required, custom_responders: api_responders, + delayed_index_update, }; let handle = Some(thread::spawn(move || server.start())); HttpServerHandle { addr, handle } @@ -1040,49 +1054,23 @@ impl HttpServer { return self.unauthorized(req); } - // Write the `.crate` let dst = self .dl_path .join(&new_crate.name) .join(&new_crate.vers) .join("download"); - t!(fs::create_dir_all(dst.parent().unwrap())); - t!(fs::write(&dst, file)); - - let deps = new_crate - .deps - .iter() - .map(|dep| { - let (name, package) = match &dep.explicit_name_in_toml { - Some(explicit) => (explicit.to_string(), Some(dep.name.to_string())), - None => (dep.name.to_string(), None), - }; - serde_json::json!({ - "name": name, - "req": dep.version_req, - "features": dep.features, - "default_features": true, - "target": dep.target, - "optional": dep.optional, - "kind": dep.kind, - "registry": dep.registry, - "package": package, - }) - }) - .collect::>(); - - let line = create_index_line( - serde_json::json!(new_crate.name), - &new_crate.vers, - deps, - &file_cksum, - new_crate.features, - false, - new_crate.links, - None, - ); - write_to_index(&self.registry_path, &new_crate.name, line, false); + if self.delayed_index_update == 0 { + save_new_crate(dst, new_crate, file, file_cksum, &self.registry_path); + } else { + let delayed_index_update = self.delayed_index_update; + let registry_path = self.registry_path.clone(); + let file = Vec::from(file); + thread::spawn(move || { + thread::sleep(std::time::Duration::new(delayed_index_update as u64, 0)); + save_new_crate(dst, new_crate, &file, file_cksum, ®istry_path); + }); + } self.ok(&req) } else { @@ -1095,6 +1083,53 @@ impl HttpServer { } } +fn save_new_crate( + dst: PathBuf, + new_crate: crates_io::NewCrate, + file: &[u8], + file_cksum: String, + registry_path: &Path, +) { + // Write the `.crate` + t!(fs::create_dir_all(dst.parent().unwrap())); + t!(fs::write(&dst, file)); + + let deps = new_crate + .deps + .iter() + .map(|dep| { + let (name, package) = match &dep.explicit_name_in_toml { + Some(explicit) => (explicit.to_string(), Some(dep.name.to_string())), + None => (dep.name.to_string(), None), + }; + serde_json::json!({ + "name": name, + "req": dep.version_req, + "features": dep.features, + "default_features": true, + "target": dep.target, + "optional": dep.optional, + "kind": dep.kind, + "registry": dep.registry, + "package": package, + }) + }) + .collect::>(); + + let line = create_index_line( + serde_json::json!(new_crate.name), + &new_crate.vers, + deps, + &file_cksum, + new_crate.features, + false, + new_crate.links, + None, + ); + + write_to_index(registry_path, &new_crate.name, line, false); +} + impl Package { /// Creates a new package builder. /// Call `publish()` to finalize and build the package. diff --git a/src/cargo/core/source/mod.rs b/src/cargo/core/source/mod.rs index 13c32d2dd5c..dca71b64e9d 100644 --- a/src/cargo/core/source/mod.rs +++ b/src/cargo/core/source/mod.rs @@ -44,6 +44,9 @@ pub trait Source { /// Ensure that the source is fully up-to-date for the current session on the next query. fn invalidate_cache(&mut self); + /// If quiet, the source should not display any progress or status messages. + fn set_quiet(&mut self, quiet: bool); + /// Fetches the full package for each name and version specified. fn download(&mut self, package: PackageId) -> CargoResult; @@ -163,6 +166,10 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box { (**self).invalidate_cache() } + fn set_quiet(&mut self, quiet: bool) { + (**self).set_quiet(quiet) + } + /// Forwards to `Source::download`. fn download(&mut self, id: PackageId) -> CargoResult { (**self).download(id) @@ -233,6 +240,10 @@ impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T { (**self).invalidate_cache() } + fn set_quiet(&mut self, quiet: bool) { + (**self).set_quiet(quiet) + } + fn download(&mut self, id: PackageId) -> CargoResult { (**self).download(id) } diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index c7ef023f1a2..07ae318ddfe 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -36,6 +36,7 @@ use crate::util::config::{Config, SslVersionConfig, SslVersionConfigRange}; use crate::util::errors::CargoResult; use crate::util::important_paths::find_root_manifest_for_wd; use crate::util::{truncate_with_ellipsis, IntoUrl}; +use crate::util::{Progress, ProgressStyle}; use crate::{drop_print, drop_println, version}; /// Registry settings loaded from config files. @@ -442,13 +443,29 @@ fn wait_for_publish( ) -> CargoResult<()> { let version_req = format!("={}", pkg.version()); let mut source = SourceConfigMap::empty(config)?.load(registry_src, &HashSet::new())?; - let source_description = source.describe(); + // Disable the source's built-in progress bars. Repeatedly showing a bunch + // of independent progress bars can be a little confusing. There is an + // overall progress bar managed here. + source.set_quiet(true); + let source_description = source.source_id().to_string(); let query = Dependency::parse(pkg.name(), Some(&version_req), registry_src)?; let now = std::time::Instant::now(); let sleep_time = std::time::Duration::from_secs(1); - let mut logged = false; - loop { + let max = timeout.as_secs() as usize; + // Short does not include the registry name. + let short_pkg_description = format!("{} v{}", pkg.name(), pkg.version()); + config.shell().status( + "Uploaded", + format!("{short_pkg_description} to {source_description}"), + )?; + config.shell().note(format!( + "Waiting for `{short_pkg_description}` to be available at {source_description}.\n\ + You may press ctrl-c to skip waiting; the crate should be available shortly." + ))?; + let mut progress = Progress::with_style("Waiting", ProgressStyle::Ratio, config); + progress.tick_now(0, max, "")?; + let is_available = loop { { let _lock = config.acquire_package_cache_lock()?; // Force re-fetching the source @@ -470,31 +487,30 @@ fn wait_for_publish( } }; if !summaries.is_empty() { - break; + break true; } } - if timeout < now.elapsed() { + let elapsed = now.elapsed(); + if timeout < elapsed { config.shell().warn(format!( - "timed out waiting for `{}` to be in {}", - pkg.name(), - source_description + "timed out waiting for `{short_pkg_description}` to be available in {source_description}", ))?; - break; - } - - if !logged { - config.shell().status( - "Waiting", - format!( - "on `{}` to propagate to {} (ctrl-c to wait asynchronously)", - pkg.name(), - source_description - ), + config.shell().note( + "The registry may have a backlog that is delaying making the \ + crate available. The crate should be available soon.", )?; - logged = true; + break false; } + + progress.tick_now(elapsed.as_secs() as usize, max, "")?; std::thread::sleep(sleep_time); + }; + if is_available { + config.shell().status( + "Published", + format!("{short_pkg_description} at {source_description}"), + )?; } Ok(()) diff --git a/src/cargo/sources/directory.rs b/src/cargo/sources/directory.rs index e30755643a7..46acb9f8630 100644 --- a/src/cargo/sources/directory.rs +++ b/src/cargo/sources/directory.rs @@ -217,6 +217,10 @@ impl<'cfg> Source for DirectorySource<'cfg> { } fn invalidate_cache(&mut self) { - // Path source has no local cache. + // Directory source has no local cache. + } + + fn set_quiet(&mut self, _quiet: bool) { + // Directory source does not display status } } diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index d09d5271627..90c47093dce 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -21,6 +21,7 @@ pub struct GitSource<'cfg> { path_source: Option>, ident: String, config: &'cfg Config, + quiet: bool, } impl<'cfg> GitSource<'cfg> { @@ -43,6 +44,7 @@ impl<'cfg> GitSource<'cfg> { path_source: None, ident, config, + quiet: false, }; Ok(source) @@ -162,10 +164,12 @@ impl<'cfg> Source for GitSource<'cfg> { self.remote.url() ); } - self.config.shell().status( - "Updating", - format!("git repository `{}`", self.remote.url()), - )?; + if !self.quiet { + self.config.shell().status( + "Updating", + format!("git repository `{}`", self.remote.url()), + )?; + } trace!("updating git source `{:?}`", self.remote); @@ -233,6 +237,10 @@ impl<'cfg> Source for GitSource<'cfg> { } fn invalidate_cache(&mut self) {} + + fn set_quiet(&mut self, quiet: bool) { + self.quiet = quiet; + } } #[cfg(test)] diff --git a/src/cargo/sources/path.rs b/src/cargo/sources/path.rs index c4cff058ba9..37e1e1f0f9d 100644 --- a/src/cargo/sources/path.rs +++ b/src/cargo/sources/path.rs @@ -574,4 +574,8 @@ impl<'cfg> Source for PathSource<'cfg> { fn invalidate_cache(&mut self) { // Path source has no local cache. } + + fn set_quiet(&mut self, _quiet: bool) { + // Path source does not display status + } } diff --git a/src/cargo/sources/registry/http_remote.rs b/src/cargo/sources/registry/http_remote.rs index 79620f0ca94..e41c385a60b 100644 --- a/src/cargo/sources/registry/http_remote.rs +++ b/src/cargo/sources/registry/http_remote.rs @@ -89,10 +89,13 @@ pub struct HttpRegistry<'cfg> { /// Url to get a token for the registry. login_url: Option, + + /// Disables status messages. + quiet: bool, } /// Helper for downloading crates. -pub struct Downloads<'cfg> { +struct Downloads<'cfg> { /// When a download is started, it is added to this map. The key is a /// "token" (see `Download::token`). It is removed once the download is /// finished. @@ -196,6 +199,7 @@ impl<'cfg> HttpRegistry<'cfg> { registry_config: None, auth_required: false, login_url: None, + quiet: false, }) } @@ -231,9 +235,11 @@ impl<'cfg> HttpRegistry<'cfg> { // let's not flood the server with connections self.multi.set_max_host_connections(2)?; - self.config - .shell() - .status("Updating", self.source_id.display_index())?; + if !self.quiet { + self.config + .shell() + .status("Updating", self.source_id.display_index())?; + } Ok(()) } @@ -681,6 +687,11 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> { self.requested_update = true; } + fn set_quiet(&mut self, quiet: bool) { + self.quiet = quiet; + self.downloads.progress.replace(None); + } + fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult { let registry_config = loop { match self.config()? { @@ -747,7 +758,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> { impl<'cfg> Downloads<'cfg> { fn tick(&self) -> CargoResult<()> { let mut progress = self.progress.borrow_mut(); - let progress = progress.as_mut().unwrap(); + let Some(progress) = progress.as_mut() else { return Ok(()); }; // Since the sparse protocol discovers dependencies as it goes, // it's not possible to get an accurate progress indication. @@ -780,7 +791,7 @@ mod tls { thread_local!(static PTR: Cell = Cell::new(0)); - pub(crate) fn with(f: impl FnOnce(Option<&Downloads<'_>>) -> R) -> R { + pub(super) fn with(f: impl FnOnce(Option<&Downloads<'_>>) -> R) -> R { let ptr = PTR.with(|p| p.get()); if ptr == 0 { f(None) @@ -791,7 +802,7 @@ mod tls { } } - pub(crate) fn set(dl: &Downloads<'_>, f: impl FnOnce() -> R) -> R { + pub(super) fn set(dl: &Downloads<'_>, f: impl FnOnce() -> R) -> R { struct Reset<'a, T: Copy>(&'a Cell, T); impl<'a, T: Copy> Drop for Reset<'a, T> { diff --git a/src/cargo/sources/registry/local.rs b/src/cargo/sources/registry/local.rs index a4b57a91e7a..89419191f97 100644 --- a/src/cargo/sources/registry/local.rs +++ b/src/cargo/sources/registry/local.rs @@ -18,6 +18,7 @@ pub struct LocalRegistry<'cfg> { src_path: Filesystem, config: &'cfg Config, updated: bool, + quiet: bool, } impl<'cfg> LocalRegistry<'cfg> { @@ -28,6 +29,7 @@ impl<'cfg> LocalRegistry<'cfg> { root: Filesystem::new(root.to_path_buf()), config, updated: false, + quiet: false, } } } @@ -104,6 +106,10 @@ impl<'cfg> RegistryData for LocalRegistry<'cfg> { // Local registry has no cache - just reads from disk. } + fn set_quiet(&mut self, _quiet: bool) { + self.quiet = true; + } + fn is_updated(&self) -> bool { self.updated } @@ -124,7 +130,9 @@ impl<'cfg> RegistryData for LocalRegistry<'cfg> { return Ok(MaybeLock::Ready(crate_file)); } - self.config.shell().status("Unpacking", pkg)?; + if !self.quiet { + self.config.shell().status("Unpacking", pkg)?; + } // We don't actually need to download anything per-se, we just need to // verify the checksum matches the .crate file itself. diff --git a/src/cargo/sources/registry/mod.rs b/src/cargo/sources/registry/mod.rs index 930a42f3678..38fc1f94559 100644 --- a/src/cargo/sources/registry/mod.rs +++ b/src/cargo/sources/registry/mod.rs @@ -474,6 +474,9 @@ pub trait RegistryData { /// Invalidates locally cached data. fn invalidate_cache(&mut self); + /// If quiet, the source should not display any progress or status messages. + fn set_quiet(&mut self, quiet: bool); + /// Is the local cached data up-to-date? fn is_updated(&self) -> bool; @@ -832,6 +835,10 @@ impl<'cfg> Source for RegistrySource<'cfg> { self.ops.invalidate_cache(); } + fn set_quiet(&mut self, quiet: bool) { + self.ops.set_quiet(quiet); + } + fn download(&mut self, package: PackageId) -> CargoResult { let hash = loop { match self.index.hash(package, &mut *self.ops)? { diff --git a/src/cargo/sources/registry/remote.rs b/src/cargo/sources/registry/remote.rs index aa0ec90233e..3e502914472 100644 --- a/src/cargo/sources/registry/remote.rs +++ b/src/cargo/sources/registry/remote.rs @@ -32,6 +32,7 @@ pub struct RemoteRegistry<'cfg> { head: Cell>, current_sha: Cell>, needs_update: bool, // Does this registry need to be updated? + quiet: bool, } impl<'cfg> RemoteRegistry<'cfg> { @@ -48,6 +49,7 @@ impl<'cfg> RemoteRegistry<'cfg> { head: Cell::new(None), current_sha: Cell::new(None), needs_update: false, + quiet: false, } } @@ -292,9 +294,11 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> { *self.tree.borrow_mut() = None; self.current_sha.set(None); let path = self.config.assert_package_cache_locked(&self.index_path); - self.config - .shell() - .status("Updating", self.source_id.display_index())?; + if !self.quiet { + self.config + .shell() + .status("Updating", self.source_id.display_index())?; + } // Fetch the latest version of our `index_git_ref` into the index // checkout. @@ -315,6 +319,10 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> { self.needs_update = true; } + fn set_quiet(&mut self, quiet: bool) { + self.quiet = quiet; + } + fn is_updated(&self) -> bool { self.is_updated() } diff --git a/src/cargo/sources/replaced.rs b/src/cargo/sources/replaced.rs index a2147703388..13191d2234f 100644 --- a/src/cargo/sources/replaced.rs +++ b/src/cargo/sources/replaced.rs @@ -67,6 +67,10 @@ impl<'cfg> Source for ReplacedSource<'cfg> { self.inner.invalidate_cache() } + fn set_quiet(&mut self, quiet: bool) { + self.inner.set_quiet(quiet); + } + fn download(&mut self, id: PackageId) -> CargoResult { let id = id.with_source_id(self.replace_with); let pkg = self diff --git a/src/cargo/util/progress.rs b/src/cargo/util/progress.rs index f2758485011..bcbc1bc0edc 100644 --- a/src/cargo/util/progress.rs +++ b/src/cargo/util/progress.rs @@ -1,3 +1,5 @@ +//! Support for CLI progress bars. + use std::cmp; use std::time::{Duration, Instant}; @@ -7,13 +9,49 @@ use crate::util::{CargoResult, Config}; use cargo_util::is_ci; use unicode_width::UnicodeWidthChar; +/// CLI progress bar. +/// +/// The `Progress` object can be in an enabled or disabled state. When +/// disabled, calling any of the methods to update it will not display +/// anything. Disabling is typically done by the user with options such as +/// `--quiet` or the `term.progress` config option. +/// +/// There are several methods to update the progress bar and to cause it to +/// update its display. +/// +/// The bar will be removed from the display when the `Progress` object is +/// dropped or [`Progress::clear`] is called. +/// +/// The progress bar has built-in rate limiting to avoid updating the display +/// too fast. It should usually be fine to call [`Progress::tick`] as often as +/// needed, though be cautious if the tick rate is very high or it is +/// expensive to compute the progress value. pub struct Progress<'cfg> { state: Option>, } +/// Indicates the style of information for displaying the amount of progress. +/// +/// See also [`Progress::print_now`] for displaying progress without a bar. pub enum ProgressStyle { + /// Displays progress as a percentage. + /// + /// Example: `Fetch [=====================> ] 88.15%` + /// + /// This is good for large values like number of bytes downloaded. Percentage, + /// Displays progress as a ratio. + /// + /// Example: `Building [===> ] 35/222` + /// + /// This is good for smaller values where the exact number is useful to see. Ratio, + /// Does not display an exact value of how far along it is. + /// + /// Example: `Fetch [===========> ]` + /// + /// This is good for situations where the exact value is an approximation, + /// and thus there isn't anything accurate to display to the user. Indeterminate, } @@ -39,6 +77,16 @@ struct Format { } impl<'cfg> Progress<'cfg> { + /// Creates a new progress bar. + /// + /// The first parameter is the text displayed to the left of the bar, such + /// as "Fetching". + /// + /// The progress bar is not displayed until explicitly updated with one if + /// its methods. + /// + /// The progress bar may be created in a disabled state if the user has + /// disabled progress display (such as with the `--quiet` option). pub fn with_style(name: &str, style: ProgressStyle, cfg: &'cfg Config) -> Progress<'cfg> { // report no progress when -q (for quiet) or TERM=dumb are set // or if running on Continuous Integration service like Travis where the @@ -84,18 +132,33 @@ impl<'cfg> Progress<'cfg> { } } + /// Disables the progress bar, ensuring it won't be displayed. pub fn disable(&mut self) { self.state = None; } + /// Returns whether or not the progress bar is allowed to be displayed. pub fn is_enabled(&self) -> bool { self.state.is_some() } + /// Creates a new `Progress` with the [`ProgressStyle::Percentage`] style. + /// + /// See [`Progress::with_style`] for more information. pub fn new(name: &str, cfg: &'cfg Config) -> Progress<'cfg> { Self::with_style(name, ProgressStyle::Percentage, cfg) } + /// Updates the state of the progress bar. + /// + /// * `cur` should be how far along the progress is. + /// * `max` is the maximum value for the progress bar. + /// * `msg` is a small piece of text to display at the end of the progress + /// bar. It will be truncated with `...` if it does not fit on the + /// terminal. + /// + /// This may not actually update the display if `tick` is being called too + /// quickly. pub fn tick(&mut self, cur: usize, max: usize, msg: &str) -> CargoResult<()> { let s = match &mut self.state { Some(s) => s, @@ -121,6 +184,14 @@ impl<'cfg> Progress<'cfg> { s.tick(cur, max, msg) } + /// Updates the state of the progress bar. + /// + /// This is the same as [`Progress::tick`], but ignores rate throttling + /// and forces the display to be updated immediately. + /// + /// This may be useful for situations where you know you aren't calling + /// `tick` too fast, and accurate information is more important than + /// limiting the console update rate. pub fn tick_now(&mut self, cur: usize, max: usize, msg: &str) -> CargoResult<()> { match self.state { Some(ref mut s) => s.tick(cur, max, msg), @@ -128,6 +199,10 @@ impl<'cfg> Progress<'cfg> { } } + /// Returns whether or not updates are currently being throttled. + /// + /// This can be useful if computing the values for calling the + /// [`Progress::tick`] function may require some expensive work. pub fn update_allowed(&mut self) -> bool { match &mut self.state { Some(s) => s.throttle.allowed(), @@ -135,6 +210,14 @@ impl<'cfg> Progress<'cfg> { } } + /// Displays progress without a bar. + /// + /// The given `msg` is the text to display after the status message. + /// + /// Example: `Downloading 61 crates, remaining bytes: 28.0 MB` + /// + /// This does not have any rate limit throttling, so be careful about + /// calling it too often. pub fn print_now(&mut self, msg: &str) -> CargoResult<()> { match &mut self.state { Some(s) => s.print("", msg), @@ -142,6 +225,7 @@ impl<'cfg> Progress<'cfg> { } } + /// Clears the progress bar from the console. pub fn clear(&mut self) { if let Some(ref mut s) = self.state { s.clear(); diff --git a/tests/testsuite/alt_registry.rs b/tests/testsuite/alt_registry.rs index f5195a7b8b6..26bd864b008 100644 --- a/tests/testsuite/alt_registry.rs +++ b/tests/testsuite/alt_registry.rs @@ -328,7 +328,10 @@ fn publish_with_registry_dependency() { [FINISHED] [..] [PACKAGED] [..] [UPLOADING] foo v0.0.1 [..] -[UPDATING] `alternative` index +[UPLOADED] foo v0.0.1 to registry `alternative` +note: Waiting for `foo v0.0.1` to be available at registry `alternative`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `alternative` ", ) .run(); @@ -457,7 +460,10 @@ fn publish_to_alt_registry() { [FINISHED] [..] [PACKAGED] [..] [UPLOADING] foo v0.0.1 [..] -[UPDATING] `alternative` index +[UPLOADED] foo v0.0.1 to registry `alternative` +note: Waiting for `foo v0.0.1` to be available at registry `alternative`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `alternative` ", ) .run(); @@ -535,7 +541,10 @@ fn publish_with_crates_io_dep() { [FINISHED] [..] [PACKAGED] [..] [UPLOADING] foo v0.0.1 [..] -[UPDATING] `alternative` index +[UPLOADED] foo v0.0.1 to registry `alternative` +note: Waiting for `foo v0.0.1` to be available at registry `alternative`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `alternative` ", ) .run(); diff --git a/tests/testsuite/artifact_dep.rs b/tests/testsuite/artifact_dep.rs index 358ca898fc0..ec6bb7103a2 100644 --- a/tests/testsuite/artifact_dep.rs +++ b/tests/testsuite/artifact_dep.rs @@ -1911,7 +1911,10 @@ fn publish_artifact_dep() { [PACKAGING] foo v0.1.0 [..] [PACKAGED] [..] [UPLOADING] foo v0.1.0 [..] -[UPDATING] [..] +[UPLOADED] foo v0.1.0 [..] +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.1.0 [..] ", ) .run(); diff --git a/tests/testsuite/cargo_features.rs b/tests/testsuite/cargo_features.rs index 720d221fe1f..6e553143174 100644 --- a/tests/testsuite/cargo_features.rs +++ b/tests/testsuite/cargo_features.rs @@ -644,7 +644,10 @@ fn publish_allowed() { [FINISHED] [..] [PACKAGED] [..] [UPLOADING] a v0.0.1 [..] -[UPDATING] [..] +[UPLOADED] a v0.0.1 to registry `crates-io` +note: Waiting for `a v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] a v0.0.1 at registry `crates-io` ", ) .run(); diff --git a/tests/testsuite/credential_process.rs b/tests/testsuite/credential_process.rs index 0d174b6e379..ced8c34a09f 100644 --- a/tests/testsuite/credential_process.rs +++ b/tests/testsuite/credential_process.rs @@ -130,7 +130,10 @@ Only one of these values may be set, remove one or the other to proceed. [PACKAGING] foo v0.1.0 [..] [PACKAGED] [..] [UPLOADING] foo v0.1.0 [..] -[UPDATING] [..] +[UPLOADED] foo v0.1.0 [..] +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.1.0 [..] ", ) .run(); @@ -222,7 +225,10 @@ fn publish() { [PACKAGING] foo v0.1.0 [..] [PACKAGED] [..] [UPLOADING] foo v0.1.0 [..] -[UPDATING] [..] +[UPLOADED] foo v0.1.0 [..] +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.1.0 [..] ", ) .run(); diff --git a/tests/testsuite/cross_publish.rs b/tests/testsuite/cross_publish.rs index 5b1416ef072..83e0ecab709 100644 --- a/tests/testsuite/cross_publish.rs +++ b/tests/testsuite/cross_publish.rs @@ -112,7 +112,10 @@ fn publish_with_target() { [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] [PACKAGED] [..] [UPLOADING] foo v0.0.0 ([CWD]) -[UPDATING] crates.io index +[UPLOADED] foo v0.0.0 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.0 at registry `crates-io` ", ) .run(); diff --git a/tests/testsuite/features_namespaced.rs b/tests/testsuite/features_namespaced.rs index 26c4d0ac53e..8ec2fc2e35d 100644 --- a/tests/testsuite/features_namespaced.rs +++ b/tests/testsuite/features_namespaced.rs @@ -894,7 +894,10 @@ fn publish_no_implicit() { [PACKAGING] foo v0.1.0 [..] [PACKAGED] [..] [UPLOADING] foo v0.1.0 [..] -[UPDATING] [..] +[UPLOADED] foo v0.1.0 [..] +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.1.0 [..] ", ) .run(); @@ -1013,7 +1016,10 @@ fn publish() { [FINISHED] [..] [PACKAGED] [..] [UPLOADING] foo v0.1.0 [..] -[UPDATING] [..] +[UPLOADED] foo v0.1.0 [..] +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.1.0 [..] ", ) .run(); diff --git a/tests/testsuite/inheritable_workspace_fields.rs b/tests/testsuite/inheritable_workspace_fields.rs index 1fc4873df6b..92c96b985a5 100644 --- a/tests/testsuite/inheritable_workspace_fields.rs +++ b/tests/testsuite/inheritable_workspace_fields.rs @@ -172,7 +172,10 @@ fn inherit_own_workspace_fields() { [FINISHED] [..] [PACKAGED] [..] [UPLOADING] foo v1.2.3 [..] -[UPDATING] [..] +[UPLOADED] foo v1.2.3 to registry `crates-io` +note: Waiting for `foo v1.2.3` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v1.2.3 at registry `crates-io` ", ) .run(); @@ -318,7 +321,10 @@ fn inherit_own_dependencies() { [FINISHED] [..] [PACKAGED] [..] [UPLOADING] bar v0.2.0 [..] -[UPDATING] [..] +[UPLOADED] bar v0.2.0 to registry `crates-io` +note: Waiting for `bar v0.2.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] bar v0.2.0 at registry `crates-io` ", ) .run(); @@ -460,7 +466,10 @@ fn inherit_own_detailed_dependencies() { [FINISHED] [..] [PACKAGED] [..] [UPLOADING] bar v0.2.0 [..] -[UPDATING] [..] +[UPLOADED] bar v0.2.0 to registry `crates-io` +note: Waiting for `bar v0.2.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] bar v0.2.0 at registry `crates-io` ", ) .run(); @@ -696,7 +705,10 @@ fn inherit_workspace_fields() { [FINISHED] [..] [PACKAGED] [..] [UPLOADING] bar v1.2.3 [..] -[UPDATING] [..] +[UPLOADED] bar v1.2.3 to registry `crates-io` +note: Waiting for `bar v1.2.3` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] bar v1.2.3 at registry `crates-io` ", ) .run(); @@ -850,7 +862,10 @@ fn inherit_dependencies() { [FINISHED] [..] [PACKAGED] [..] [UPLOADING] bar v0.2.0 [..] -[UPDATING] [..] +[UPLOADED] bar v0.2.0 to registry `crates-io` +note: Waiting for `bar v0.2.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] bar v0.2.0 at registry `crates-io` ", ) .run(); diff --git a/tests/testsuite/publish.rs b/tests/testsuite/publish.rs index e3f86905d4c..806177615cc 100644 --- a/tests/testsuite/publish.rs +++ b/tests/testsuite/publish.rs @@ -114,7 +114,10 @@ See [..] [PACKAGING] foo v0.0.1 ([CWD]) [PACKAGED] [..] files, [..] ([..] compressed) [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] [..] +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` ", ) .run(); @@ -155,7 +158,10 @@ See [..] [PACKAGING] foo v0.0.1 ([CWD]) [PACKAGED] [..] files, [..] ([..] compressed) [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] `dummy-registry` index +[UPLOADED] foo v0.0.1 to registry `dummy-registry` +note: Waiting for `foo v0.0.1` to be available at registry `dummy-registry`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `dummy-registry` ", ) .run(); @@ -195,7 +201,10 @@ See [..] [PACKAGING] foo v0.0.1 ([CWD]) [PACKAGED] [..] files, [..] ([..] compressed) [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] `dummy-registry` index +[UPLOADED] foo v0.0.1 to registry `dummy-registry` +note: Waiting for `foo v0.0.1` to be available at registry `dummy-registry`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `dummy-registry` ", ) .run(); @@ -246,7 +255,10 @@ See [..] [PACKAGING] foo v0.0.1 ([CWD]) [PACKAGED] [..] files, [..] ([..] compressed) [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] [..] +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -288,7 +300,10 @@ fn simple_with_index() { [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] [..] +[UPLOADED] foo v0.0.1 to registry `[ROOT]/registry` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -486,7 +501,10 @@ fn publish_clean() { [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] [..] +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -532,7 +550,10 @@ fn publish_in_sub_repo() { [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] [..] +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -578,7 +599,10 @@ fn publish_when_ignored() { [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] [..] +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -623,7 +647,10 @@ fn ignore_when_crate_ignored() { [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] [..] +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -809,7 +836,10 @@ fn publish_allowed_registry() { [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] `alternative` index +[UPLOADED] foo v0.0.1 to registry `alternative` +note: Waiting for `foo v0.0.1` to be available at registry `alternative`. +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 at registry `alternative` ", ) .run(); @@ -867,7 +897,10 @@ fn publish_implicitly_to_only_allowed_registry() { [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] `alternative` index +[UPLOADED] foo v0.0.1 to registry `alternative` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -993,7 +1026,10 @@ The registry `alternative` is not listed in the `package.publish` value in Cargo [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] crates.io index +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -1041,7 +1077,10 @@ fn publish_with_select_features() { [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] crates.io index +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -1089,7 +1128,10 @@ fn publish_with_all_features() { [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] crates.io index +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -1191,7 +1233,10 @@ fn publish_with_patch() { [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] crates.io index +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -1387,7 +1432,10 @@ fn publish_git_with_version() { [..] [..] [UPLOADING] foo v0.1.0 ([CWD]) -[UPDATING] crates.io index +[UPLOADED] foo v0.1.0 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.1.0 [..] ", ) .run(); @@ -1506,7 +1554,10 @@ fn publish_dev_dep_no_version() { [PACKAGING] foo v0.1.0 [..] [PACKAGED] [..] files, [..] ([..] compressed) [UPLOADING] foo v0.1.0 [..] -[UPDATING] crates.io index +[UPLOADED] foo v0.1.0 [..] +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.1.0 [..] ", ) .run(); @@ -1602,7 +1653,10 @@ fn credentials_ambiguous_filename() { [..] [..] [UPLOADING] foo v0.0.1 [..] -[UPDATING] crates.io index +[UPLOADED] foo v0.0.1 [..] +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -2009,7 +2063,10 @@ See [..] [PACKAGING] li v0.0.1 ([CWD]/li) [PACKAGED] [..] files, [..] ([..] compressed) [UPLOADING] li v0.0.1 ([CWD]/li) -[UPDATING] crates.io index +[UPLOADED] li v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] li v0.0.1 [..] ", ) .run(); @@ -2108,7 +2165,10 @@ See [..] [PACKAGING] li v0.0.1 ([CWD]/li) [PACKAGED] [..] files, [..] ([..] compressed) [UPLOADING] li v0.0.1 ([CWD]/li) -[UPDATING] crates.io index +[UPLOADED] li v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] li v0.0.1 [..] ", ) .run(); @@ -2200,7 +2260,10 @@ See [..] [PACKAGING] li v0.0.1 ([CWD]/li) [PACKAGED] [..] files, [..] ([..] compressed) [UPLOADING] li v0.0.1 ([CWD]/li) -[UPDATING] crates.io index +[UPLOADED] li v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] li v0.0.1 [..] ", ) .run(); @@ -2387,7 +2450,10 @@ fn http_api_not_noop() { [..] [..] [UPLOADING] foo v0.0.1 ([CWD]) -[UPDATING] [..] +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.0.1 [..] ", ) .run(); @@ -2461,8 +2527,10 @@ See [..] [PACKAGING] delay v0.0.1 ([CWD]) [PACKAGED] [..] files, [..] ([..] compressed) [UPLOADING] delay v0.0.1 ([CWD]) -[UPDATING] crates.io index -[WAITING] on `delay` to propagate to crates.io index (ctrl-c to wait asynchronously) +[UPLOADED] delay v0.0.1 to registry `crates-io` +note: Waiting for `delay v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] delay v0.0.1 at registry `crates-io` ", ) .run(); @@ -2541,8 +2609,10 @@ See [..] [PACKAGING] delay_with_underscore v0.0.1 ([CWD]) [PACKAGED] [..] files, [..] ([..] compressed) [UPLOADING] delay_with_underscore v0.0.1 ([CWD]) -[UPDATING] crates.io index -[WAITING] on `delay_with_underscore` to propagate to crates.io index (ctrl-c to wait asynchronously) +[UPLOADED] delay_with_underscore v0.0.1 to registry `crates-io` +note: Waiting for `delay_with_underscore v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] delay_with_underscore v0.0.1 at registry `crates-io` ", ) .run(); @@ -2631,8 +2701,10 @@ See [..] [PACKAGING] delay v0.0.2 ([CWD]) [PACKAGED] [..] files, [..] ([..] compressed) [UPLOADING] delay v0.0.2 ([CWD]) -[UPDATING] crates.io index -[WAITING] on `delay` to propagate to crates.io index (ctrl-c to wait asynchronously) +[UPLOADED] delay v0.0.2 to registry `crates-io` +note: Waiting for `delay v0.0.2` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] delay v0.0.2 at registry `crates-io` ", ) .run(); @@ -2657,7 +2729,7 @@ See [..] .file("src/main.rs", "fn main() {}") .build(); - p.cargo("build").with_status(0).run(); + p.cargo("check").with_status(0).run(); } #[cargo_test] @@ -2702,3 +2774,120 @@ See [..] ) .run(); } + +#[cargo_test] +fn timeout_waiting_for_publish() { + // Publish doesn't happen within the timeout window. + let registry = registry::RegistryBuilder::new() + .http_api() + .delayed_index_update(20) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "delay" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [publish] + timeout = 2 + "#, + ) + .build(); + + p.cargo("publish --no-verify -Zpublish-timeout") + .replace_crates_io(registry.index_url()) + .masquerade_as_nightly_cargo(&["publish-timeout"]) + .with_status(0) + .with_stderr( + "\ +[UPDATING] crates.io index +[WARNING] manifest has no documentation, [..] +See [..] +[PACKAGING] delay v0.0.1 ([CWD]) +[PACKAGED] [..] files, [..] ([..] compressed) +[UPLOADING] delay v0.0.1 ([CWD]) +[UPLOADED] delay v0.0.1 to registry `crates-io` +note: Waiting for `delay v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +warning: timed out waiting for `delay v0.0.1` to be available in registry `crates-io` +note: The registry may have a backlog that is delaying making the crate available. The crate should be available soon. +", + ) + .run(); +} + +#[cargo_test] +fn wait_for_git_publish() { + // Slow publish to an index with a git index. + let registry = registry::RegistryBuilder::new() + .http_api() + .delayed_index_update(5) + .build(); + + // Publish an earlier version + Package::new("delay", "0.0.1") + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "delay" + version = "0.0.2" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(0) + .with_stderr( + "\ +[UPDATING] crates.io index +[WARNING] manifest has no documentation, [..] +See [..] +[PACKAGING] delay v0.0.2 ([CWD]) +[PACKAGED] [..] files, [..] ([..] compressed) +[UPLOADING] delay v0.0.2 ([CWD]) +[UPLOADED] delay v0.0.2 to registry `crates-io` +note: Waiting for `delay v0.0.2` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] delay v0.0.2 at registry `crates-io` +", + ) + .run(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + [dependencies] + delay = "0.0.2" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").with_status(0).run(); +} diff --git a/tests/testsuite/source_replacement.rs b/tests/testsuite/source_replacement.rs index ef7cc555c04..24f2ca3e3e3 100644 --- a/tests/testsuite/source_replacement.rs +++ b/tests/testsuite/source_replacement.rs @@ -220,7 +220,10 @@ See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for [FINISHED] dev [..] [PACKAGED] [..] [UPLOADING] foo v0.0.1 ([..]) -[UPDATING] crates.io index +[UPLOADED] foo v0.0.1 to registry `crates-io` +note: Waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` ", ) .run(); diff --git a/tests/testsuite/weak_dep_features.rs b/tests/testsuite/weak_dep_features.rs index dfc1e6b794e..ee91114df5f 100644 --- a/tests/testsuite/weak_dep_features.rs +++ b/tests/testsuite/weak_dep_features.rs @@ -561,7 +561,10 @@ fn publish() { [FINISHED] [..] [PACKAGED] [..] [UPLOADING] foo v0.1.0 [..] -[UPDATING] [..] +[UPLOADED] foo v0.1.0 to registry `crates-io` +note: Waiting for `foo v0.1.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.1.0 at registry `crates-io` ", ) .run();