Skip to content

Commit 4400514

Browse files
committed
keep track of crates that are whitelisted to be used even if yanked
1 parent 9f1f786 commit 4400514

File tree

9 files changed

+86
-37
lines changed

9 files changed

+86
-37
lines changed

src/cargo/core/registry.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use std::collections::{HashMap, HashSet};
22

33
use log::{debug, trace};
44
use semver::VersionReq;
@@ -71,6 +71,7 @@ pub struct PackageRegistry<'cfg> {
7171
source_ids: HashMap<SourceId, (SourceId, Kind)>,
7272

7373
locked: LockedMap,
74+
yanked_whitelist: HashSet<PackageId>,
7475
source_config: SourceConfigMap<'cfg>,
7576

7677
patches: HashMap<Url, Vec<Summary>>,
@@ -97,6 +98,7 @@ impl<'cfg> PackageRegistry<'cfg> {
9798
overrides: Vec::new(),
9899
source_config,
99100
locked: HashMap::new(),
101+
yanked_whitelist: HashSet::new(),
100102
patches: HashMap::new(),
101103
patches_locked: false,
102104
patches_available: HashMap::new(),
@@ -166,6 +168,10 @@ impl<'cfg> PackageRegistry<'cfg> {
166168
self.add_source(source, Kind::Override);
167169
}
168170

171+
pub fn add_to_yanked_whitelist(&mut self, iter: impl Iterator<Item = PackageId>) {
172+
self.yanked_whitelist.extend(iter)
173+
}
174+
169175
pub fn register_lock(&mut self, id: PackageId, deps: Vec<PackageId>) {
170176
trace!("register_lock: {}", id);
171177
for dep in deps.iter() {
@@ -301,7 +307,9 @@ impl<'cfg> PackageRegistry<'cfg> {
301307
fn load(&mut self, source_id: SourceId, kind: Kind) -> CargoResult<()> {
302308
(|| {
303309
debug!("loading source {}", source_id);
304-
let source = self.source_config.load(source_id)?;
310+
let source = self
311+
.source_config
312+
.load(source_id, self.yanked_whitelist.clone())?;
305313
assert_eq!(source.source_id(), source_id);
306314

307315
if kind == Kind::Override {

src/cargo/core/source/source_id.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use serde::de;
1313
use serde::ser;
1414
use url::Url;
1515

16+
use crate::core::PackageId;
1617
use crate::ops;
1718
use crate::sources::git;
1819
use crate::sources::DirectorySource;
@@ -257,7 +258,11 @@ impl SourceId {
257258
}
258259

259260
/// Creates an implementation of `Source` corresponding to this ID.
260-
pub fn load<'a>(self, config: &'a Config) -> CargoResult<Box<dyn super::Source + 'a>> {
261+
pub fn load<'a>(
262+
self,
263+
config: &'a Config,
264+
yanked_whitelist: HashSet<PackageId>,
265+
) -> CargoResult<Box<dyn super::Source + 'a>> {
261266
trace!("loading SourceId; {}", self);
262267
match self.inner.kind {
263268
Kind::Git(..) => Ok(Box::new(GitSource::new(self, config)?)),
@@ -268,7 +273,11 @@ impl SourceId {
268273
};
269274
Ok(Box::new(PathSource::new(&path, self, config)))
270275
}
271-
Kind::Registry => Ok(Box::new(RegistrySource::remote(self, config))),
276+
Kind::Registry => Ok(Box::new(RegistrySource::remote(
277+
self,
278+
yanked_whitelist,
279+
config,
280+
))),
272281
Kind::LocalRegistry => {
273282
let path = match self.inner.url.to_file_path() {
274283
Ok(p) => p,

src/cargo/ops/cargo_install.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::{BTreeMap, BTreeSet};
1+
use std::collections::{BTreeMap, BTreeSet, HashSet};
22
use std::path::{Path, PathBuf};
33
use std::sync::Arc;
44
use std::{env, fs};
@@ -181,7 +181,7 @@ fn install_one(
181181
})?
182182
} else {
183183
select_pkg(
184-
map.load(source_id)?,
184+
map.load(source_id, HashSet::new())?,
185185
krate,
186186
vers,
187187
config,

src/cargo/ops/registry.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::BTreeMap;
1+
use std::collections::{BTreeMap, HashSet};
22
use std::fs::{self, File};
33
use std::io::{self, BufRead};
44
use std::iter::repeat;
@@ -350,7 +350,7 @@ pub fn registry(
350350
let token = token.or(token_config);
351351
let sid = get_source_id(config, index_config.or(index), registry)?;
352352
let api_host = {
353-
let mut src = RegistrySource::remote(sid, config);
353+
let mut src = RegistrySource::remote(sid, HashSet::new(), config);
354354
// Only update the index if the config is not available or `force` is set.
355355
let cfg = src.config();
356356
let cfg = if force_update || cfg.is_err() {
@@ -696,7 +696,7 @@ fn get_source_id(
696696
(_, Some(i)) => SourceId::for_registry(&i.to_url()?),
697697
_ => {
698698
let map = SourceConfigMap::new(config)?;
699-
let src = map.load(SourceId::crates_io(config)?)?;
699+
let src = map.load(SourceId::crates_io(config)?, HashSet::new())?;
700700
Ok(src.replaced_source_id())
701701
}
702702
}

src/cargo/ops/resolve.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ fn register_previous_locks(
471471
// package's dependencies here as that'll be covered below to poison those
472472
// if they changed.
473473
let mut avoid_locking = HashSet::new();
474+
registry.add_to_yanked_whitelist(resolve.iter());
474475
for node in resolve.iter() {
475476
if !keep(&node) {
476477
add_deps(resolve, node, &mut avoid_locking);

src/cargo/sources/config.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
//! structure usable by Cargo itself. Currently this is primarily used to map
55
//! sources to one another via the `replace-with` key in `.cargo/config`.
66
7-
use std::collections::HashMap;
7+
use std::collections::{HashMap, HashSet};
88
use std::path::{Path, PathBuf};
99

1010
use log::debug;
1111
use url::Url;
1212

13-
use crate::core::{GitReference, Source, SourceId};
13+
use crate::core::{GitReference, PackageId, Source, SourceId};
1414
use crate::sources::{ReplacedSource, CRATES_IO_REGISTRY};
1515
use crate::util::config::ConfigValue;
1616
use crate::util::errors::{CargoResult, CargoResultExt};
@@ -73,11 +73,15 @@ impl<'cfg> SourceConfigMap<'cfg> {
7373
self.config
7474
}
7575

76-
pub fn load(&self, id: SourceId) -> CargoResult<Box<dyn Source + 'cfg>> {
76+
pub fn load(
77+
&self,
78+
id: SourceId,
79+
yanked_whitelist: HashSet<PackageId>,
80+
) -> CargoResult<Box<dyn Source + 'cfg>> {
7781
debug!("loading: {}", id);
7882
let mut name = match self.id2name.get(&id) {
7983
Some(name) => name,
80-
None => return Ok(id.load(self.config)?),
84+
None => return Ok(id.load(self.config, yanked_whitelist)?),
8185
};
8286
let mut path = Path::new("/");
8387
let orig_name = name;
@@ -99,7 +103,7 @@ impl<'cfg> SourceConfigMap<'cfg> {
99103
name = s;
100104
path = p;
101105
}
102-
None if id == cfg.id => return Ok(id.load(self.config)?),
106+
None if id == cfg.id => return Ok(id.load(self.config, yanked_whitelist)?),
103107
None => {
104108
new_id = cfg.id.with_precise(id.precise().map(|s| s.to_string()));
105109
break;
@@ -116,8 +120,8 @@ impl<'cfg> SourceConfigMap<'cfg> {
116120
)
117121
}
118122
}
119-
let new_src = new_id.load(self.config)?;
120-
let old_src = id.load(self.config)?;
123+
let new_src = new_id.load(self.config, yanked_whitelist.clone())?;
124+
let old_src = id.load(self.config, yanked_whitelist.clone())?;
121125
if !new_src.supports_checksums() && old_src.supports_checksums() {
122126
failure::bail!(
123127
"\

src/cargo/sources/registry/index.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use std::collections::{HashMap, HashSet};
22
use std::path::Path;
33
use std::str;
44

@@ -273,14 +273,17 @@ impl<'cfg> RegistryIndex<'cfg> {
273273
&mut self,
274274
dep: &Dependency,
275275
load: &mut dyn RegistryData,
276+
yanked_whitelist: &HashSet<PackageId>,
276277
f: &mut dyn FnMut(Summary),
277278
) -> CargoResult<()> {
278279
let source_id = self.source_id;
279280
let name = dep.package_name().as_str();
280281
let summaries = self.summaries(name, load)?;
281282
let summaries = summaries
282283
.iter()
283-
.filter(|&&(_, yanked)| dep.source_id().precise().is_some() || !yanked)
284+
.filter(|&(summary, yanked)| {
285+
!yanked || yanked_whitelist.contains(&summary.package_id())
286+
})
284287
.map(|s| s.0.clone());
285288

286289
// Handle `cargo update --precise` here. If specified, our own source

src/cargo/sources/registry/mod.rs

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
161161
use std::borrow::Cow;
162162
use std::collections::BTreeMap;
163+
use std::collections::HashSet;
163164
use std::io::Write;
164165
use std::path::{Path, PathBuf};
165166

@@ -192,6 +193,7 @@ pub struct RegistrySource<'cfg> {
192193
updated: bool,
193194
ops: Box<dyn RegistryData + 'cfg>,
194195
index: index::RegistryIndex<'cfg>,
196+
yanked_whitelist: HashSet<PackageId>,
195197
index_locked: bool,
196198
}
197199

@@ -385,23 +387,42 @@ fn short_name(id: SourceId) -> String {
385387
}
386388

387389
impl<'cfg> RegistrySource<'cfg> {
388-
pub fn remote(source_id: SourceId, config: &'cfg Config) -> RegistrySource<'cfg> {
390+
pub fn remote(
391+
source_id: SourceId,
392+
yanked_whitelist: HashSet<PackageId>,
393+
config: &'cfg Config,
394+
) -> RegistrySource<'cfg> {
389395
let name = short_name(source_id);
390396
let ops = remote::RemoteRegistry::new(source_id, config, &name);
391-
RegistrySource::new(source_id, config, &name, Box::new(ops), true)
397+
RegistrySource::new(
398+
source_id,
399+
config,
400+
&name,
401+
Box::new(ops),
402+
yanked_whitelist,
403+
true,
404+
)
392405
}
393406

394407
pub fn local(source_id: SourceId, path: &Path, config: &'cfg Config) -> RegistrySource<'cfg> {
395408
let name = short_name(source_id);
396409
let ops = local::LocalRegistry::new(path, config, &name);
397-
RegistrySource::new(source_id, config, &name, Box::new(ops), false)
410+
RegistrySource::new(
411+
source_id,
412+
config,
413+
&name,
414+
Box::new(ops),
415+
HashSet::new(),
416+
false,
417+
)
398418
}
399419

400420
fn new(
401421
source_id: SourceId,
402422
config: &'cfg Config,
403423
name: &str,
404424
ops: Box<dyn RegistryData + 'cfg>,
425+
yanked_whitelist: HashSet<PackageId>,
405426
index_locked: bool,
406427
) -> RegistrySource<'cfg> {
407428
RegistrySource {
@@ -410,6 +431,7 @@ impl<'cfg> RegistrySource<'cfg> {
410431
source_id,
411432
updated: false,
412433
index: index::RegistryIndex::new(source_id, ops.index_path(), config, index_locked),
434+
yanked_whitelist,
413435
index_locked,
414436
ops,
415437
}
@@ -431,9 +453,7 @@ impl<'cfg> RegistrySource<'cfg> {
431453
// unpacked and to lock the directory for unpacking.
432454
let mut ok = {
433455
let package_dir = format!("{}-{}", pkg.name(), pkg.version());
434-
let dst = self
435-
.src_path
436-
.join(&package_dir);
456+
let dst = self.src_path.join(&package_dir);
437457
dst.create_dir()?;
438458

439459
// Attempt to open a read-only copy first to avoid an exclusive write
@@ -526,12 +546,13 @@ impl<'cfg> Source for RegistrySource<'cfg> {
526546
if dep.source_id().precise().is_some() && !self.updated {
527547
debug!("attempting query without update");
528548
let mut called = false;
529-
self.index.query_inner(dep, &mut *self.ops, &mut |s| {
530-
if dep.matches(&s) {
531-
called = true;
532-
f(s);
533-
}
534-
})?;
549+
self.index
550+
.query_inner(dep, &mut *self.ops, &self.yanked_whitelist, &mut |s| {
551+
if dep.matches(&s) {
552+
called = true;
553+
f(s);
554+
}
555+
})?;
535556
if called {
536557
return Ok(());
537558
} else {
@@ -540,15 +561,17 @@ impl<'cfg> Source for RegistrySource<'cfg> {
540561
}
541562
}
542563

543-
self.index.query_inner(dep, &mut *self.ops, &mut |s| {
544-
if dep.matches(&s) {
545-
f(s);
546-
}
547-
})
564+
self.index
565+
.query_inner(dep, &mut *self.ops, &self.yanked_whitelist, &mut |s| {
566+
if dep.matches(&s) {
567+
f(s);
568+
}
569+
})
548570
}
549571

550572
fn fuzzy_query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()> {
551-
self.index.query_inner(dep, &mut *self.ops, f)
573+
self.index
574+
.query_inner(dep, &mut *self.ops, &self.yanked_whitelist, f)
552575
}
553576

554577
fn supports_checksums(&self) -> bool {

tests/testsuite/search.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::collections::HashSet;
12
use std::fs::{self, File};
23
use std::io::prelude::*;
34
use std::path::Path;
@@ -107,7 +108,7 @@ fn not_update() {
107108

108109
let sid = SourceId::for_registry(&registry_url()).unwrap();
109110
let cfg = Config::new(Shell::new(), paths::root(), paths::home().join(".cargo"));
110-
let mut regsrc = RegistrySource::remote(sid, &cfg);
111+
let mut regsrc = RegistrySource::remote(sid, HashSet::new(), &cfg);
111112
regsrc.update().unwrap();
112113

113114
cargo_process("search postgres")

0 commit comments

Comments
 (0)