Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support local mirrors of registries, take 2 #2857

Merged
merged 12 commits into from
Aug 2, 2016
2 changes: 1 addition & 1 deletion Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ clean:
# === Documentation

DOCS := index faq config guide manifest build-script pkgid-spec crates-io \
environment-variables specifying-dependencies
environment-variables specifying-dependencies source-replacement
DOC_DIR := target/doc
DOC_OPTS := --markdown-no-toc \
--markdown-css stylesheets/normalize.css \
Expand Down
12 changes: 3 additions & 9 deletions src/bin/git_checkout.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use cargo::core::source::{Source, SourceId, GitReference};
use cargo::sources::git::{GitSource};
use cargo::util::{Config, CliResult, CliError, human, ToUrl};
use cargo::util::{Config, CliResult, ToUrl};

#[derive(RustcDecodable)]
pub struct Options {
Expand Down Expand Up @@ -37,20 +37,14 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
options.flag_locked));
let Options { flag_url: url, flag_reference: reference, .. } = options;

let url = try!(url.to_url().map_err(|e| {
human(format!("The URL `{}` you passed was \
not a valid URL: {}", url, e))
})
.map_err(|e| CliError::new(e, 1)));
let url = try!(url.to_url());

let reference = GitReference::Branch(reference.clone());
let source_id = SourceId::for_git(&url, reference);

let mut source = GitSource::new(&source_id, config);

try!(source.update().map_err(|e| {
CliError::new(human(format!("Couldn't update {:?}: {:?}", source, e)), 1)
}));
try!(source.update());

Ok(None)
}
6 changes: 3 additions & 3 deletions src/bin/install.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use cargo::ops;
use cargo::core::{SourceId, GitReference};
use cargo::util::{CliResult, Config, ToUrl, human};
use cargo::util::{CliResult, Config, ToUrl};

#[derive(RustcDecodable)]
pub struct Options {
Expand Down Expand Up @@ -116,7 +116,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
};

let source = if let Some(url) = options.flag_git {
let url = try!(url.to_url().map_err(human));
let url = try!(url.to_url());
let gitref = if let Some(branch) = options.flag_branch {
GitReference::Branch(branch)
} else if let Some(tag) = options.flag_tag {
Expand All @@ -132,7 +132,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
} else if options.arg_crate == None {
try!(SourceId::for_path(&config.cwd()))
} else {
try!(SourceId::for_central(config))
try!(SourceId::crates_io(config))
};

let krate = options.arg_crate.as_ref().map(|s| &s[..]);
Expand Down
6 changes: 3 additions & 3 deletions src/bin/login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
let token = match options.arg_token.clone() {
Some(token) => token,
None => {
let src = try!(SourceId::for_central(config));
let mut src = RegistrySource::new(&src, config);
let src = try!(SourceId::crates_io(config));
let mut src = RegistrySource::remote(&src, config);
try!(src.update());
let config = try!(src.config());
let config = try!(src.config()).unwrap();
let host = options.flag_host.clone().unwrap_or(config.api);
println!("please visit {}me and paste the API Token below", host);
let mut line = String::new();
Expand Down
12 changes: 12 additions & 0 deletions src/cargo/core/dependency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ impl Dependency {
pub fn is_transitive(&self) -> bool { self.inner.is_transitive() }
pub fn is_build(&self) -> bool { self.inner.is_build() }
pub fn is_optional(&self) -> bool { self.inner.is_optional() }

/// Returns true if the default features of the dependency are requested.
pub fn uses_default_features(&self) -> bool {
self.inner.uses_default_features()
Expand All @@ -263,6 +264,17 @@ impl Dependency {
pub fn matches_id(&self, id: &PackageId) -> bool {
self.inner.matches_id(id)
}

pub fn map_source(self, to_replace: &SourceId, replace_with: &SourceId)
-> Dependency {
if self.source_id() != to_replace {
self
} else {
Rc::try_unwrap(self.inner).unwrap_or_else(|r| (*r).clone())
.set_source_id(replace_with.clone())
.into_dependency()
}
}
}

impl Platform {
Expand Down
11 changes: 10 additions & 1 deletion src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use std::path::{PathBuf, Path};
use semver::Version;
use rustc_serialize::{Encoder, Encodable};

use core::{Dependency, PackageId, PackageIdSpec, Summary, WorkspaceConfig};
use core::{Dependency, PackageId, Summary, SourceId, PackageIdSpec};
use core::WorkspaceConfig;
use core::package_id::Metadata;

pub enum EitherManifest {
Expand Down Expand Up @@ -232,6 +233,14 @@ impl Manifest {
pub fn set_summary(&mut self, summary: Summary) {
self.summary = summary;
}

pub fn map_source(self, to_replace: &SourceId, replace_with: &SourceId)
-> Manifest {
Manifest {
summary: self.summary.map_source(to_replace, replace_with),
..self
}
}
}

impl VirtualManifest {
Expand Down
8 changes: 8 additions & 0 deletions src/cargo/core/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ impl Package {
.filter(|&(d, _)| d < 4);
matches.min_by_key(|t| t.0).map(|t| t.1)
}

pub fn map_source(self, to_replace: &SourceId, replace_with: &SourceId)
-> Package {
Package {
manifest: self.manifest.map_source(to_replace, replace_with),
manifest_path: self.manifest_path,
}
}
}

impl fmt::Display for Package {
Expand Down
40 changes: 33 additions & 7 deletions src/cargo/core/package_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ use util::{CargoResult, CargoError, short_hash, ToSemver};
use core::source::SourceId;

/// Identifier for a specific version of a package in a specific source.
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct PackageId {
inner: Arc<PackageIdInner>,
}

#[derive(PartialEq, PartialOrd, Eq, Ord, Debug)]
#[derive(PartialEq, PartialOrd, Eq, Ord)]
struct PackageIdInner {
name: String,
version: semver::Version,
Expand All @@ -38,13 +38,19 @@ impl Decodable for PackageId {
fn decode<D: Decoder>(d: &mut D) -> Result<PackageId, D::Error> {
let string: String = try!(Decodable::decode(d));
let regex = Regex::new(r"^([^ ]+) ([^ ]+) \(([^\)]+)\)$").unwrap();
let captures = regex.captures(&string).expect("invalid serialized PackageId");
let captures = try!(regex.captures(&string).ok_or_else(|| {
d.error("invalid serialized PackageId")
}));

let name = captures.at(1).unwrap();
let version = captures.at(2).unwrap();
let url = captures.at(3).unwrap();
let version = semver::Version::parse(version).ok().expect("invalid version");
let source_id = SourceId::from_url(url);
let version = try!(semver::Version::parse(version).map_err(|_| {
d.error("invalid version")
}));
let source_id = try!(SourceId::from_url(url).map_err(|e| {
d.error(&e.to_string())
}));

Ok(PackageId {
inner: Arc::new(PackageIdInner {
Expand Down Expand Up @@ -151,6 +157,16 @@ impl PackageId {
}),
}
}

pub fn with_source_id(&self, source: &SourceId) -> PackageId {
PackageId {
inner: Arc::new(PackageIdInner {
name: self.inner.name.to_string(),
version: self.inner.version.clone(),
source_id: source.clone(),
}),
}
}
}

impl Metadata {
Expand All @@ -173,16 +189,26 @@ impl fmt::Display for PackageId {
}
}

impl fmt::Debug for PackageId {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("PackageId")
.field("name", &self.inner.name)
.field("version", &self.inner.version.to_string())
.field("source", &self.inner.source_id.to_string())
.finish()
}
}

#[cfg(test)]
mod tests {
use super::PackageId;
use core::source::SourceId;
use sources::RegistrySource;
use sources::CRATES_IO;
use util::ToUrl;

#[test]
fn invalid_version_handled_nicely() {
let loc = RegistrySource::default_url().to_url().unwrap();
let loc = CRATES_IO.to_url().unwrap();
let repo = SourceId::for_registry(&loc);

assert!(PackageId::new("foo", "1.0", &repo).is_err());
Expand Down
30 changes: 23 additions & 7 deletions src/cargo/core/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,22 @@ use std::collections::{HashSet, HashMap};
use core::{Source, SourceId, SourceMap, Summary, Dependency, PackageId, Package};
use core::PackageSet;
use util::{CargoResult, ChainError, Config, human, profile};
use sources::config::SourceConfigMap;

/// Source of information about a group of packages.
///
/// See also `core::Source`.
pub trait Registry {
/// Attempt to find the packages that match a dependency request.
fn query(&mut self, name: &Dependency) -> CargoResult<Vec<Summary>>;

/// Returns whether or not this registry will return summaries with
/// checksums listed.
///
/// By default, registries do not support checksums.
fn supports_checksums(&self) -> bool {
false
}
}

impl Registry for Vec<Summary> {
Expand All @@ -26,6 +35,12 @@ impl Registry for Vec<Package> {
}
}

impl<'a, T: ?Sized + Registry + 'a> Registry for Box<T> {
fn query(&mut self, name: &Dependency) -> CargoResult<Vec<Summary>> {
(**self).query(name)
}
}

/// This structure represents a registry of known packages. It internally
/// contains a number of `Box<Source>` instances which are used to load a
/// `Package` from.
Expand All @@ -41,7 +56,6 @@ impl Registry for Vec<Package> {
/// operations if necessary) and is ready to be queried for packages.
pub struct PackageRegistry<'cfg> {
sources: SourceMap<'cfg>,
config: &'cfg Config,

// A list of sources which are considered "overrides" which take precedent
// when querying for packages.
Expand All @@ -65,6 +79,7 @@ pub struct PackageRegistry<'cfg> {
source_ids: HashMap<SourceId, (SourceId, Kind)>,

locked: HashMap<SourceId, HashMap<String, Vec<(PackageId, Vec<PackageId>)>>>,
source_config: SourceConfigMap<'cfg>,
}

#[derive(PartialEq, Eq, Clone, Copy)]
Expand All @@ -75,14 +90,15 @@ enum Kind {
}

impl<'cfg> PackageRegistry<'cfg> {
pub fn new(config: &'cfg Config) -> PackageRegistry<'cfg> {
PackageRegistry {
pub fn new(config: &'cfg Config) -> CargoResult<PackageRegistry<'cfg>> {
let source_config = try!(SourceConfigMap::new(config));
Ok(PackageRegistry {
sources: SourceMap::new(),
source_ids: HashMap::new(),
overrides: Vec::new(),
config: config,
source_config: source_config,
locked: HashMap::new(),
}
})
}

pub fn get(self, package_ids: &[PackageId]) -> PackageSet<'cfg> {
Expand Down Expand Up @@ -158,8 +174,8 @@ impl<'cfg> PackageRegistry<'cfg> {

fn load(&mut self, source_id: &SourceId, kind: Kind) -> CargoResult<()> {
(|| {
// Save off the source
let source = source_id.load(self.config);
let source = try!(self.source_config.load(source_id));

if kind == Kind::Override {
self.overrides.push(source_id.clone());
}
Expand Down
Loading