diff --git a/src/bin/publish.rs b/src/bin/publish.rs index 97aa2e13764..f5a9d827767 100644 --- a/src/bin/publish.rs +++ b/src/bin/publish.rs @@ -14,6 +14,7 @@ pub struct Options { flag_no_verify: bool, flag_allow_dirty: bool, flag_jobs: Option, + flag_dry_run: bool, } pub const USAGE: &'static str = " @@ -30,6 +31,7 @@ Options: --allow-dirty Allow publishing with a dirty source directory --manifest-path PATH Path to the manifest of the package to publish -j N, --jobs N Number of parallel jobs, defaults to # of CPUs + --dry-run Perform all checks without uploading -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never @@ -47,6 +49,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult> { flag_no_verify: no_verify, flag_allow_dirty: allow_dirty, flag_jobs: jobs, + flag_dry_run: dry_run, .. } = options; @@ -59,6 +62,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult> { verify: !no_verify, allow_dirty: allow_dirty, jobs: jobs, + dry_run: dry_run, })); Ok(None) } diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index cda3d9abec9..ac831b3576a 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -36,6 +36,7 @@ pub struct PublishOpts<'cfg> { pub verify: bool, pub allow_dirty: bool, pub jobs: Option, + pub dry_run: bool, } pub fn publish(ws: &Workspace, opts: &PublishOpts) -> CargoResult<()> { @@ -64,7 +65,7 @@ pub fn publish(ws: &Workspace, opts: &PublishOpts) -> CargoResult<()> { // Upload said tarball to the specified destination try!(opts.config.shell().status("Uploading", pkg.package_id().to_string())); - try!(transmit(&pkg, tarball.file(), &mut registry)); + try!(transmit(opts.config, &pkg, tarball.file(), &mut registry, opts.dry_run)); Ok(()) } @@ -87,8 +88,11 @@ fn verify_dependencies(pkg: &Package, registry_src: &SourceId) Ok(()) } -fn transmit(pkg: &Package, tarball: &File, registry: &mut Registry) - -> CargoResult<()> { +fn transmit(config: &Config, + pkg: &Package, + tarball: &File, + registry: &mut Registry, + dry_run: bool) -> CargoResult<()> { let deps = pkg.dependencies().iter().map(|dep| { NewCrateDependency { optional: dep.is_optional(), @@ -121,6 +125,13 @@ fn transmit(pkg: &Package, tarball: &File, registry: &mut Registry) } None => {} } + + // Do not upload if performing a dry run + if dry_run { + try!(config.shell().warn("aborting upload due to dry run")); + return Ok(()); + } + registry.publish(&NewCrate { name: pkg.name().to_string(), vers: pkg.version().to_string(), diff --git a/tests/publish.rs b/tests/publish.rs index b823672f933..63642a7bd48 100644 --- a/tests/publish.rs +++ b/tests/publish.rs @@ -327,3 +327,35 @@ fn new_crate_rejected() { assert_that(p.cargo("publish"), execs().with_status(101)); } + +#[test] +fn dry_run() { + setup(); + + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#) + .file("src/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("publish").arg("--dry-run"), + execs().with_status(0).with_stderr(&format!("\ +[UPDATING] registry `{reg}` +[WARNING] manifest has no documentation, [..] +[PACKAGING] foo v0.0.1 ({dir}) +[VERIFYING] foo v0.0.1 ({dir}) +[COMPILING] foo v0.0.1 [..] +[UPLOADING] foo v0.0.1 ({dir}) +[WARNING] aborting upload due to dry run +", + dir = p.url(), + reg = registry()))); + + // Ensure the API request wasn't actually made + assert!(!upload_path().join("api/v1/crates/new").exists()); +}