Skip to content

Commit e3835f7

Browse files
committed
Remove the RefCell from PackageRegistry
Some choice refactoring makes it no longer necessary!
1 parent 857c19c commit e3835f7

File tree

1 file changed

+105
-112
lines changed

1 file changed

+105
-112
lines changed

src/cargo/core/registry.rs

Lines changed: 105 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use std::cell::RefCell;
21
use std::collections::HashMap;
32

43
use core::{Source, SourceId, SourceMap, Summary, Dependency, PackageId};
@@ -53,10 +52,7 @@ impl<'a, T: ?Sized + Registry + 'a> Registry for Box<T> {
5352
/// a `Source`. Each `Source` in the map has been updated (using network
5453
/// operations if necessary) and is ready to be queried for packages.
5554
pub struct PackageRegistry<'cfg> {
56-
// Note that in general we don't have interior mutability but the
57-
// implementation of `query` below necessitates the need for this `RefCell`,
58-
// see comments there for more.
59-
sources: RefCell<SourceMap<'cfg>>,
55+
sources: SourceMap<'cfg>,
6056

6157
// A list of sources which are considered "overrides" which take precedent
6258
// when querying for packages.
@@ -79,10 +75,12 @@ pub struct PackageRegistry<'cfg> {
7975
// what exactly the key is.
8076
source_ids: HashMap<SourceId, (SourceId, Kind)>,
8177

82-
locked: HashMap<SourceId, HashMap<String, Vec<(PackageId, Vec<PackageId>)>>>,
78+
locked: LockedMap,
8379
source_config: SourceConfigMap<'cfg>,
8480
}
8581

82+
type LockedMap = HashMap<SourceId, HashMap<String, Vec<(PackageId, Vec<PackageId>)>>>;
83+
8684
#[derive(PartialEq, Eq, Clone, Copy)]
8785
enum Kind {
8886
Override,
@@ -94,7 +92,7 @@ impl<'cfg> PackageRegistry<'cfg> {
9492
pub fn new(config: &'cfg Config) -> CargoResult<PackageRegistry<'cfg>> {
9593
let source_config = SourceConfigMap::new(config)?;
9694
Ok(PackageRegistry {
97-
sources: RefCell::new(SourceMap::new()),
95+
sources: SourceMap::new(),
9896
source_ids: HashMap::new(),
9997
overrides: Vec::new(),
10098
source_config: source_config,
@@ -103,9 +101,8 @@ impl<'cfg> PackageRegistry<'cfg> {
103101
}
104102

105103
pub fn get(self, package_ids: &[PackageId]) -> PackageSet<'cfg> {
106-
let sources = self.sources.into_inner();
107-
trace!("getting packages; sources={}", sources.len());
108-
PackageSet::new(package_ids, sources)
104+
trace!("getting packages; sources={}", self.sources.len());
105+
PackageSet::new(package_ids, self.sources)
109106
}
110107

111108
fn ensure_loaded(&mut self, namespace: &SourceId, kind: Kind) -> CargoResult<()> {
@@ -157,7 +154,7 @@ impl<'cfg> PackageRegistry<'cfg> {
157154

158155
fn add_source(&mut self, source: Box<Source + 'cfg>, kind: Kind) {
159156
let id = source.source_id().clone();
160-
self.sources.get_mut().insert(source);
157+
self.sources.insert(source);
161158
self.source_ids.insert(id.clone(), (id, kind));
162159
}
163160

@@ -190,14 +187,14 @@ impl<'cfg> PackageRegistry<'cfg> {
190187

191188
// Ensure the source has fetched all necessary remote data.
192189
let _p = profile::start(format!("updating: {}", source_id));
193-
self.sources.get_mut().get_mut(source_id).unwrap().update()
190+
self.sources.get_mut(source_id).unwrap().update()
194191
})().chain_err(|| format!("Unable to update {}", source_id))
195192
}
196193

197194
fn query_overrides(&mut self, dep: &Dependency)
198195
-> CargoResult<Option<Summary>> {
199196
for s in self.overrides.iter() {
200-
let src = self.sources.get_mut().get_mut(s).unwrap();
197+
let src = self.sources.get_mut(s).unwrap();
201198
let dep = Dependency::new_override(dep.name(), s);
202199
let mut results = src.query_vec(&dep)?;
203200
if results.len() > 0 {
@@ -225,71 +222,7 @@ impl<'cfg> PackageRegistry<'cfg> {
225222
/// possible. If we're unable to map a dependency though, we just pass it on
226223
/// through.
227224
pub fn lock(&self, summary: Summary) -> Summary {
228-
let pair = self.locked.get(summary.source_id()).and_then(|map| {
229-
map.get(summary.name())
230-
}).and_then(|vec| {
231-
vec.iter().find(|&&(ref id, _)| id == summary.package_id())
232-
});
233-
234-
trace!("locking summary of {}", summary.package_id());
235-
236-
// Lock the summary's id if possible
237-
let summary = match pair {
238-
Some(&(ref precise, _)) => summary.override_id(precise.clone()),
239-
None => summary,
240-
};
241-
summary.map_dependencies(|mut dep| {
242-
trace!("\t{}/{}/{}", dep.name(), dep.version_req(),
243-
dep.source_id());
244-
245-
// If we've got a known set of overrides for this summary, then
246-
// one of a few cases can arise:
247-
//
248-
// 1. We have a lock entry for this dependency from the same
249-
// source as it's listed as coming from. In this case we make
250-
// sure to lock to precisely the given package id.
251-
//
252-
// 2. We have a lock entry for this dependency, but it's from a
253-
// different source than what's listed, or the version
254-
// requirement has changed. In this case we must discard the
255-
// locked version because the dependency needs to be
256-
// re-resolved.
257-
//
258-
// 3. We don't have a lock entry for this dependency, in which
259-
// case it was likely an optional dependency which wasn't
260-
// included previously so we just pass it through anyway.
261-
//
262-
// Cases 1/2 are handled by `matches_id` and case 3 is handled by
263-
// falling through to the logic below.
264-
if let Some(&(_, ref locked_deps)) = pair {
265-
let locked = locked_deps.iter().find(|id| dep.matches_id(id));
266-
if let Some(locked) = locked {
267-
trace!("\tfirst hit on {}", locked);
268-
dep.lock_to(locked);
269-
return dep
270-
}
271-
}
272-
273-
// If this dependency did not have a locked version, then we query
274-
// all known locked packages to see if they match this dependency.
275-
// If anything does then we lock it to that and move on.
276-
let v = self.locked.get(dep.source_id()).and_then(|map| {
277-
map.get(dep.name())
278-
}).and_then(|vec| {
279-
vec.iter().find(|&&(ref id, _)| dep.matches_id(id))
280-
});
281-
match v {
282-
Some(&(ref id, _)) => {
283-
trace!("\tsecond hit on {}", id);
284-
dep.lock_to(id);
285-
return dep
286-
}
287-
None => {
288-
trace!("\tremaining unlocked");
289-
dep
290-
}
291-
}
292-
})
225+
lock(&self.locked, summary)
293226
}
294227

295228
fn warn_bad_override(&self,
@@ -347,42 +280,34 @@ impl<'cfg> Registry for PackageRegistry<'cfg> {
347280
on `{}`", dep.name())
348281
})?;
349282

350-
// Look for an override and get ready to query the real source.
351-
//
352-
// Note that we're not using `&mut self` to load `self.sources` here but
353-
// rather we're going through `RefCell::borrow_mut`. This is currently
354-
// done to have access to both the `lock` function and the
355-
// `warn_bad_override` functions we call below.
356-
let override_summary = self.query_overrides(&dep)?;
357-
let mut sources = self.sources.borrow_mut();
358-
let source = match sources.get_mut(dep.source_id()) {
359-
Some(src) => src,
360-
None => {
361-
if override_summary.is_some() {
362-
bail!("override found but no real ones");
363-
}
364-
return Ok(())
365-
}
366-
};
367283

368-
let (override_summary, n, to_warn) = match override_summary {
369-
// If we have an override summary then we query the source to sanity
370-
// check its results. We don't actually use any of the summaries it
371-
// gives us though.
372-
Some(s) => {
373-
let mut n = 0;
374-
let mut to_warn = None;
375-
source.query(dep, &mut |summary| {
376-
n += 1;
377-
to_warn = Some(summary);
378-
})?;
379-
(s, n, to_warn)
380-
}
284+
let (override_summary, n, to_warn) = {
285+
// Look for an override and get ready to query the real source.
286+
let override_summary = self.query_overrides(&dep)?;
287+
let source = self.sources.get_mut(dep.source_id());
288+
match (override_summary, source) {
289+
(Some(_), None) => bail!("override found but no real ones"),
290+
(None, None) => return Ok(()),
381291

382-
// If we don't have an override then we just ship everything
383-
// upstairs after locking the summary
384-
None => {
385-
return source.query(dep, &mut |summary| f(self.lock(summary)))
292+
// If we don't have an override then we just ship everything
293+
// upstairs after locking the summary
294+
(None, Some(source)) => {
295+
let locked = &self.locked;
296+
return source.query(dep, &mut |summary| f(lock(locked, summary)))
297+
}
298+
299+
// If we have an override summary then we query the source to sanity
300+
// check its results. We don't actually use any of the summaries it
301+
// gives us though.
302+
(Some(override_summary), Some(source)) => {
303+
let mut n = 0;
304+
let mut to_warn = None;
305+
source.query(dep, &mut |summary| {
306+
n += 1;
307+
to_warn = Some(summary);
308+
})?;
309+
(override_summary, n, to_warn)
310+
}
386311
}
387312
};
388313

@@ -396,6 +321,74 @@ impl<'cfg> Registry for PackageRegistry<'cfg> {
396321
}
397322
}
398323

324+
fn lock(locked: &LockedMap, summary: Summary) -> Summary {
325+
let pair = locked.get(summary.source_id()).and_then(|map| {
326+
map.get(summary.name())
327+
}).and_then(|vec| {
328+
vec.iter().find(|&&(ref id, _)| id == summary.package_id())
329+
});
330+
331+
trace!("locking summary of {}", summary.package_id());
332+
333+
// Lock the summary's id if possible
334+
let summary = match pair {
335+
Some(&(ref precise, _)) => summary.override_id(precise.clone()),
336+
None => summary,
337+
};
338+
summary.map_dependencies(|mut dep| {
339+
trace!("\t{}/{}/{}", dep.name(), dep.version_req(),
340+
dep.source_id());
341+
342+
// If we've got a known set of overrides for this summary, then
343+
// one of a few cases can arise:
344+
//
345+
// 1. We have a lock entry for this dependency from the same
346+
// source as it's listed as coming from. In this case we make
347+
// sure to lock to precisely the given package id.
348+
//
349+
// 2. We have a lock entry for this dependency, but it's from a
350+
// different source than what's listed, or the version
351+
// requirement has changed. In this case we must discard the
352+
// locked version because the dependency needs to be
353+
// re-resolved.
354+
//
355+
// 3. We don't have a lock entry for this dependency, in which
356+
// case it was likely an optional dependency which wasn't
357+
// included previously so we just pass it through anyway.
358+
//
359+
// Cases 1/2 are handled by `matches_id` and case 3 is handled by
360+
// falling through to the logic below.
361+
if let Some(&(_, ref locked_deps)) = pair {
362+
let locked = locked_deps.iter().find(|id| dep.matches_id(id));
363+
if let Some(locked) = locked {
364+
trace!("\tfirst hit on {}", locked);
365+
dep.lock_to(locked);
366+
return dep
367+
}
368+
}
369+
370+
// If this dependency did not have a locked version, then we query
371+
// all known locked packages to see if they match this dependency.
372+
// If anything does then we lock it to that and move on.
373+
let v = locked.get(dep.source_id()).and_then(|map| {
374+
map.get(dep.name())
375+
}).and_then(|vec| {
376+
vec.iter().find(|&&(ref id, _)| dep.matches_id(id))
377+
});
378+
match v {
379+
Some(&(ref id, _)) => {
380+
trace!("\tsecond hit on {}", id);
381+
dep.lock_to(id);
382+
return dep
383+
}
384+
None => {
385+
trace!("\tremaining unlocked");
386+
dep
387+
}
388+
}
389+
})
390+
}
391+
399392
#[cfg(test)]
400393
pub mod test {
401394
use core::{Summary, Registry, Dependency};

0 commit comments

Comments
 (0)