Skip to content

Commit 96e9496

Browse files
committed
Auto merge of #6840 - ehuss:publish-lockfile-updates, r=alexcrichton
publish-lockfile: Various updates This is a collection of changes to the `publish-lockfile` feature. They are separated by commit (see each for more detailed commit messages), and I can separate them into separate PRs if necessary. - Move publish-lockfile tests to a dedicated file. - Regenerate `Cargo.lock` when creating a package. - Ignore `Cargo.lock` in `cargo install` by default (requires `--locked` to use). - Add warnings for yanked dependencies. - Change default of publish-lockfile to true.
2 parents f2ea95a + 7d20230 commit 96e9496

28 files changed

+895
-272
lines changed

src/cargo/core/package.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::cell::{Cell, Ref, RefCell};
1+
use std::cell::{Cell, Ref, RefCell, RefMut};
22
use std::cmp::Ordering;
33
use std::collections::{HashMap, HashSet};
44
use std::fmt;
@@ -236,6 +236,12 @@ impl Package {
236236
toml
237237
))
238238
}
239+
240+
/// Returns if package should include `Cargo.lock`.
241+
pub fn include_lockfile(&self) -> bool {
242+
self.manifest().publish_lockfile()
243+
&& self.targets().iter().any(|t| t.is_example() || t.is_bin())
244+
}
239245
}
240246

241247
impl fmt::Display for Package {
@@ -454,6 +460,10 @@ impl<'cfg> PackageSet<'cfg> {
454460
pub fn sources(&self) -> Ref<'_, SourceMap<'cfg>> {
455461
self.sources.borrow()
456462
}
463+
464+
pub fn sources_mut(&self) -> RefMut<'_, SourceMap<'cfg>> {
465+
self.sources.borrow_mut()
466+
}
457467
}
458468

459469
// When dynamically linked against libcurl, we want to ignore some failures

src/cargo/core/source/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ pub trait Source {
9696
/// queries, even if they are yanked. Currently only applies to registry
9797
/// sources.
9898
fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]);
99+
100+
/// Query if a package is yanked. Only registry sources can mark packages
101+
/// as yanked. This ignores the yanked whitelist.
102+
fn is_yanked(&mut self, _pkg: PackageId) -> CargoResult<bool>;
99103
}
100104

101105
pub enum MaybePackage {
@@ -169,6 +173,10 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
169173
fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]) {
170174
(**self).add_to_yanked_whitelist(pkgs);
171175
}
176+
177+
fn is_yanked(&mut self, pkg: PackageId) -> CargoResult<bool> {
178+
(**self).is_yanked(pkg)
179+
}
172180
}
173181

174182
impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
@@ -227,6 +235,10 @@ impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
227235
fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]) {
228236
(**self).add_to_yanked_whitelist(pkgs);
229237
}
238+
239+
fn is_yanked(&mut self, pkg: PackageId) -> CargoResult<bool> {
240+
(**self).is_yanked(pkg)
241+
}
230242
}
231243

232244
/// A `HashMap` of `SourceId` -> `Box<Source>`.

src/cargo/core/source/source_id.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,24 @@ impl SourceId {
228228
&self.inner.url
229229
}
230230

231-
pub fn display_registry(self) -> String {
231+
pub fn display_index(self) -> String {
232232
if self.is_default_registry() {
233233
"crates.io index".to_string()
234234
} else {
235235
format!("`{}` index", url_display(self.url()))
236236
}
237237
}
238238

239+
pub fn display_registry_name(self) -> String {
240+
if self.is_default_registry() {
241+
"crates.io".to_string()
242+
} else if let Some(name) = &self.inner.name {
243+
name.clone()
244+
} else {
245+
url_display(self.url())
246+
}
247+
}
248+
239249
/// Returns `true` if this source is from a filesystem path.
240250
pub fn is_path(self) -> bool {
241251
self.inner.kind == Kind::Path

src/cargo/core/workspace.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ pub struct Workspace<'cfg> {
7777
// A cache of loaded packages for particular paths which is disjoint from
7878
// `packages` up above, used in the `load` method down below.
7979
loaded_packages: RefCell<HashMap<PathBuf, Package>>,
80+
81+
// If `true`, then the resolver will ignore any existing `Cargo.lock`
82+
// file. This is set for `cargo install` without `--locked`.
83+
ignore_lock: bool,
8084
}
8185

8286
// Separate structure for tracking loaded packages (to avoid loading anything
@@ -148,6 +152,7 @@ impl<'cfg> Workspace<'cfg> {
148152
is_ephemeral: false,
149153
require_optional_deps: true,
150154
loaded_packages: RefCell::new(HashMap::new()),
155+
ignore_lock: false,
151156
};
152157
ws.root_manifest = ws.find_root(manifest_path)?;
153158
ws.find_members()?;
@@ -184,6 +189,7 @@ impl<'cfg> Workspace<'cfg> {
184189
is_ephemeral: true,
185190
require_optional_deps,
186191
loaded_packages: RefCell::new(HashMap::new()),
192+
ignore_lock: false,
187193
};
188194
{
189195
let key = ws.current_manifest.parent().unwrap();
@@ -320,14 +326,23 @@ impl<'cfg> Workspace<'cfg> {
320326
self.require_optional_deps
321327
}
322328

323-
pub fn set_require_optional_deps<'a>(
324-
&'a mut self,
329+
pub fn set_require_optional_deps(
330+
&mut self,
325331
require_optional_deps: bool,
326332
) -> &mut Workspace<'cfg> {
327333
self.require_optional_deps = require_optional_deps;
328334
self
329335
}
330336

337+
pub fn ignore_lock(&self) -> bool {
338+
self.ignore_lock
339+
}
340+
341+
pub fn set_ignore_lock(&mut self, ignore_lock: bool) -> &mut Workspace<'cfg> {
342+
self.ignore_lock = ignore_lock;
343+
self
344+
}
345+
331346
/// Finds the root of a workspace for the crate whose manifest is located
332347
/// at `manifest_path`.
333348
///

src/cargo/ops/cargo_compile.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::core::compiler::{
3131
use crate::core::compiler::{CompileMode, Kind, Unit};
3232
use crate::core::profiles::{Profiles, UnitFor};
3333
use crate::core::resolver::{Method, Resolve};
34-
use crate::core::{Package, Source, Target};
34+
use crate::core::{Package, Target};
3535
use crate::core::{PackageId, PackageIdSpec, TargetKind, Workspace};
3636
use crate::ops;
3737
use crate::util::config::Config;
@@ -247,12 +247,11 @@ pub fn compile_with_exec<'a>(
247247
exec: &Arc<dyn Executor>,
248248
) -> CargoResult<Compilation<'a>> {
249249
ws.emit_warnings()?;
250-
compile_ws(ws, None, options, exec)
250+
compile_ws(ws, options, exec)
251251
}
252252

253253
pub fn compile_ws<'a>(
254254
ws: &Workspace<'a>,
255-
source: Option<Box<dyn Source + 'a>>,
256255
options: &CompileOptions<'a>,
257256
exec: &Arc<dyn Executor>,
258257
) -> CargoResult<Compilation<'a>> {
@@ -305,7 +304,7 @@ pub fn compile_ws<'a>(
305304
all_features,
306305
uses_default_features: !no_default_features,
307306
};
308-
let resolve = ops::resolve_ws_with_method(ws, source, method, &specs)?;
307+
let resolve = ops::resolve_ws_with_method(ws, method, &specs)?;
309308
let (packages, resolve_with_overrides) = resolve;
310309

311310
let to_build_ids = specs

src/cargo/ops/cargo_doc.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ pub fn doc(ws: &Workspace<'_>, options: &DocOptions<'_>) -> CargoResult<()> {
2323
let specs = options.compile_opts.spec.to_package_id_specs(ws)?;
2424
let resolve = ops::resolve_ws_precisely(
2525
ws,
26-
None,
2726
&options.compile_opts.features,
2827
options.compile_opts.all_features,
2928
options.compile_opts.no_default_features,

src/cargo/ops/cargo_install.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ use tempfile::Builder as TempFileBuilder;
88

99
use crate::core::compiler::Freshness;
1010
use crate::core::compiler::{DefaultExecutor, Executor};
11-
use crate::core::{Edition, PackageId, Source, SourceId, Workspace};
11+
use crate::core::resolver::Method;
12+
use crate::core::{Edition, PackageId, PackageIdSpec, Source, SourceId, Workspace};
1213
use crate::ops;
1314
use crate::ops::common_for_install_and_uninstall::*;
1415
use crate::sources::{GitSource, SourceConfigMap};
@@ -144,7 +145,7 @@ fn install_one(
144145
) -> CargoResult<()> {
145146
let config = opts.config;
146147

147-
let (pkg, source) = if source_id.is_git() {
148+
let pkg = if source_id.is_git() {
148149
select_pkg(
149150
GitSource::new(source_id, config)?,
150151
krate,
@@ -214,14 +215,15 @@ fn install_one(
214215
Some(Filesystem::new(config.cwd().join("target-install")))
215216
};
216217

217-
let ws = match overidden_target_dir {
218+
let mut ws = match overidden_target_dir {
218219
Some(dir) => Workspace::ephemeral(pkg, config, Some(dir), false)?,
219220
None => {
220221
let mut ws = Workspace::new(pkg.manifest_path(), config)?;
221222
ws.set_require_optional_deps(false);
222223
ws
223224
}
224225
};
226+
ws.set_ignore_lock(config.lock_update_allowed());
225227
let pkg = ws.current()?;
226228

227229
if from_cwd {
@@ -302,8 +304,10 @@ fn install_one(
302304

303305
config.shell().status("Installing", pkg)?;
304306

307+
check_yanked_install(&ws)?;
308+
305309
let exec: Arc<dyn Executor> = Arc::new(DefaultExecutor);
306-
let compile = ops::compile_ws(&ws, Some(source), opts, &exec).chain_err(|| {
310+
let compile = ops::compile_ws(&ws, opts, &exec).chain_err(|| {
307311
if let Some(td) = td_opt.take() {
308312
// preserve the temporary directory, so the user can inspect it
309313
td.into_path();
@@ -477,6 +481,32 @@ fn install_one(
477481
}
478482
}
479483

484+
fn check_yanked_install(ws: &Workspace<'_>) -> CargoResult<()> {
485+
if ws.ignore_lock() || !ws.root().join("Cargo.lock").exists() {
486+
return Ok(());
487+
}
488+
let specs = vec![PackageIdSpec::from_package_id(ws.current()?.package_id())];
489+
// It would be best if `source` could be passed in here to avoid a
490+
// duplicate "Updating", but since `source` is taken by value, then it
491+
// wouldn't be available for `compile_ws`.
492+
let (pkg_set, resolve) = ops::resolve_ws_with_method(ws, Method::Everything, &specs)?;
493+
let mut sources = pkg_set.sources_mut();
494+
for pkg_id in resolve.iter() {
495+
if let Some(source) = sources.get_mut(pkg_id.source_id()) {
496+
if source.is_yanked(pkg_id)? {
497+
ws.config().shell().warn(format!(
498+
"package `{}` in Cargo.lock is yanked in registry `{}`, \
499+
consider running without --locked",
500+
pkg_id,
501+
pkg_id.source_id().display_registry_name()
502+
))?;
503+
}
504+
}
505+
}
506+
507+
Ok(())
508+
}
509+
480510
/// Display a list of installed binaries.
481511
pub fn install_list(dst: Option<&str>, config: &Config) -> CargoResult<()> {
482512
let root = resolve_root(dst, config)?;

src/cargo/ops/cargo_output_metadata.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ fn metadata_full(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> CargoResult
5252
let specs = Packages::All.to_package_id_specs(ws)?;
5353
let (package_set, resolve) = ops::resolve_ws_precisely(
5454
ws,
55-
None,
5655
&opt.features,
5756
opt.all_features,
5857
opt.no_default_features,

0 commit comments

Comments
 (0)