diff --git a/src/cargo/ops/cargo_generate_lockfile.rs b/src/cargo/ops/cargo_generate_lockfile.rs index 88600ec11e8..5ad95a846af 100644 --- a/src/cargo/ops/cargo_generate_lockfile.rs +++ b/src/cargo/ops/cargo_generate_lockfile.rs @@ -46,7 +46,19 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes let previous_resolve = match ops::load_pkg_lockfile(ws)? { Some(resolve) => resolve, - None => return generate_lockfile(ws), + None => { + match opts.precise { + None => return generate_lockfile(ws), + + // Precise option specified, so calculate a previous_resolve required + // by precise package update later. + Some(_) => { + let mut registry = PackageRegistry::new(opts.config)?; + ops::resolve_with_previous(&mut registry, ws, Method::Everything, + None, None, &[], true)? + } + } + } }; let mut registry = PackageRegistry::new(opts.config)?; let mut to_avoid = HashSet::new(); diff --git a/tests/testsuite/update.rs b/tests/testsuite/update.rs index 7a95c72cc0a..10fd2a66e27 100644 --- a/tests/testsuite/update.rs +++ b/tests/testsuite/update.rs @@ -395,6 +395,168 @@ fn update_precise() { .run(); } +// cargo update should respect its arguments even without a lockfile. +// See issue "Running cargo update without a Cargo.lock ignores arguments" +// at . +#[test] +fn update_precise_first_run() { + Package::new("serde", "0.1.0").publish(); + Package::new("serde", "0.2.0").publish(); + Package::new("serde", "0.2.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + + [dependencies] + serde = "0.2" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("update -p serde --precise 0.2.0") + .with_stderr( + "\ +[UPDATING] `[..]` index +[UPDATING] serde v0.2.1 -> v0.2.0 +", + ) + .run(); + + // Assert `cargo metadata` shows serde 0.2.0 + p.cargo("metadata") + .with_json( + r#"{ + "packages": [ + { + "authors": [], + "categories": [], + "dependencies": [], + "description": null, + "edition": "2015", + "features": {}, + "id": "serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[..]/home/.cargo/registry/src/-[..]/serde-0.2.0/Cargo.toml", + "metadata": null, + "name": "serde", + "readme": null, + "repository": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "targets": [ + { + "crate_types": [ + "lib" + ], + "edition": "2015", + "kind": [ + "lib" + ], + "name": "serde", + "src_path": "[..]/home/.cargo/registry/src/-[..]/serde-0.2.0/src/lib.rs" + } + ], + "version": "0.2.0" + }, + { + "authors": [], + "categories": [], + "dependencies": [ + { + "features": [], + "kind": null, + "name": "serde", + "optional": false, + "registry": null, + "rename": null, + "req": "^0.2", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "edition": "2015", + "features": {}, + "id": "bar 0.0.1 (path+file://[..]/foo)", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[..]/foo/Cargo.toml", + "metadata": null, + "name": "bar", + "readme": null, + "repository": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[..]/foo/src/lib.rs" + } + ], + "version": "0.0.1" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [ + "serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" + ], + "deps": [ + { + "name": "serde", + "pkg": "serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" + } + ], + "features": [], + "id": "bar 0.0.1 (path+file://[..]/foo)" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" + } + ], + "root": "bar 0.0.1 (path+file://[..]/foo)" + }, + "target_directory": "[..]/foo/target", + "version": 1, + "workspace_members": [ + "bar 0.0.1 (path+file://[..]/foo)" + ], + "workspace_root": "[..]/foo" +}"#, + ) + .run(); + + p.cargo("update -p serde --precise 0.2.0") + .with_stderr( + "\ +[UPDATING] `[..]` index +", + ) + .run(); + +} + #[test] fn preserve_top_comment() { let p = project().file("src/lib.rs", "").build();