/// 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
- }
+ fn supports_checksums(&self) -> bool;
+
+ /// Returns whether or not this registry will return summaries with
+ /// the `precise` field in the source id listed.
+ fn requires_precise(&self) -> bool;
}
impl<'a, T: ?Sized + Registry + 'a> Registry for Box<T> {
f: &mut FnMut(Summary)) -> CargoResult<()> {
(**self).query(dep, f)
}
+
+ fn supports_checksums(&self) -> bool {
+ (**self).supports_checksums()
+ }
+
+ fn requires_precise(&self) -> bool {
+ (**self).requires_precise()
+ }
}
/// This structure represents a registry of known packages. It internally
f(self.lock(override_summary));
Ok(())
}
+
+ fn supports_checksums(&self) -> bool {
+ false
+ }
+
+ fn requires_precise(&self) -> bool {
+ false
+ }
}
fn lock(locked: &LockedMap,
Ok(())
}
}
+
+ fn supports_checksums(&self) -> bool {
+ false
+ }
+
+ fn requires_precise(&self) -> bool {
+ false
+ }
}
}
use url::Url;
-use core::{Source, SourceId};
+use core::{Source, SourceId, GitReference};
use sources::ReplacedSource;
use util::{Config, ToUrl};
use util::config::ConfigValue;
}
let new_src = new_id.load(self.config)?;
let old_src = id.load(self.config)?;
- if new_src.supports_checksums() != old_src.supports_checksums() {
- let (supports, no_support) = if new_src.supports_checksums() {
- (name, orig_name)
- } else {
- (orig_name, name)
- };
+ if !new_src.supports_checksums() && old_src.supports_checksums() {
bail!("\
-cannot replace `{orig}` with `{name}`, the source `{supports}` supports \
-checksums, but `{no_support}` does not
+cannot replace `{orig}` with `{name}`, the source `{orig}` supports \
+checksums, but `{name}` does not
a lock file compatible with `{orig}` cannot be generated in this situation
-", orig = orig_name, name = name, supports = supports, no_support = no_support);
+", orig = orig_name, name = name);
+ }
+
+ if old_src.requires_precise() && id.precise().is_none() {
+ bail!("\
+the source {orig} requires a lock file to be present first before it can be
+used against vendored source code
+
+remove the source replacement configuration, generate a lock file, and then
+restore the source replacement configuration to continue the build
+", orig = orig_name);
}
+
Ok(Box::new(ReplacedSource::new(id, &new_id, new_src)))
}
path.push(s);
srcs.push(SourceId::for_directory(&path)?);
}
+ if let Some(val) = table.get("git") {
+ let url = url(val, &format!("source.{}.git", name))?;
+ let try = |s: &str| {
+ let val = match table.get(s) {
+ Some(s) => s,
+ None => return Ok(None),
+ };
+ let key = format!("source.{}.{}", name, s);
+ val.string(&key).map(Some)
+ };
+ let reference = match try("branch")? {
+ Some(b) => GitReference::Branch(b.0.to_string()),
+ None => {
+ match try("tag")? {
+ Some(b) => GitReference::Tag(b.0.to_string()),
+ None => {
+ match try("rev")? {
+ Some(b) => GitReference::Rev(b.0.to_string()),
+ None => GitReference::Branch("master".to_string()),
+ }
+ }
+ }
+ }
+ };
+ srcs.push(SourceId::for_git(&url, reference)?);
+ }
if name == "crates-io" && srcs.is_empty() {
srcs.push(SourceId::crates_io(self.config)?);
}
#[derive(Deserialize)]
struct Checksum {
- package: String,
+ package: Option<String>,
files: HashMap<String, String>,
}
fn supports_checksums(&self) -> bool {
true
}
+
+ fn requires_precise(&self) -> bool {
+ true
+ }
}
impl<'cfg> Source for DirectorySource<'cfg> {
})?;
let mut manifest = pkg.manifest().clone();
- let summary = manifest.summary().clone();
- manifest.set_summary(summary.set_checksum(cksum.package.clone()));
+ let mut summary = manifest.summary().clone();
+ if let Some(ref package) = cksum.package {
+ summary = summary.set_checksum(package.clone());
+ }
+ manifest.set_summary(summary);
let pkg = Package::new(manifest, pkg.manifest_path());
self.packages.insert(pkg.package_id().clone(), (pkg, cksum));
}
.expect("BUG: update() must be called before query()");
src.query(dep, f)
}
+
+ fn supports_checksums(&self) -> bool {
+ false
+ }
+
+ fn requires_precise(&self) -> bool {
+ true
+ }
}
impl<'cfg> Source for GitSource<'cfg> {
}
Ok(())
}
+
+ fn supports_checksums(&self) -> bool {
+ false
+ }
+
+ fn requires_precise(&self) -> bool {
+ false
+ }
}
impl<'cfg> Source for PathSource<'cfg> {
fn supports_checksums(&self) -> bool {
true
}
+
+ fn requires_precise(&self) -> bool {
+ false
+ }
}
impl<'cfg> Source for RegistrySource<'cfg> {
self.to_replace)
})
}
+
+ fn supports_checksums(&self) -> bool {
+ self.inner.supports_checksums()
+ }
+
+ fn requires_precise(&self) -> bool {
+ self.inner.requires_precise()
+ }
}
impl<'cfg> Source for ReplacedSource<'cfg> {
registry = "https://example.com/path/to/index"
local-registry = "path/to/registry"
directory = "path/to/vendor"
+
+# Git sources can optionally specify a branch/tag/rev as well
+git = "https://example.com/path/to/repo"
+# branch = "master"
+# tag = "v1.0.1"
+# rev = "313f44e8"
```
The `crates-io` represents the crates.io online registry (default source of
use std::str;
use cargotest::cargo_process;
-use cargotest::support::{project, execs, ProjectBuilder};
+use cargotest::support::git;
use cargotest::support::paths;
use cargotest::support::registry::{Package, cksum};
+use cargotest::support::{project, execs, ProjectBuilder};
use hamcrest::assert_that;
fn setup() {
#[derive(Serialize)]
struct Checksum {
- package: String,
+ package: Option<String>,
files: HashMap<String, String>,
}
VendorPackage {
p: Some(project(&format!("index/{}", name))),
cksum: Checksum {
- package: String::new(),
+ package: Some(String::new()),
files: HashMap::new(),
},
}
self
}
+ fn disable_checksum(&mut self) -> &mut VendorPackage {
+ self.cksum.package = None;
+ self
+ }
+
fn build(&mut self) {
let p = self.p.take().unwrap();
let json = serde_json::to_string(&self.cksum).unwrap();
authors = []
"#);
v.file("src/lib.rs", "pub fn foo() -> u32 { 1 }");
- v.cksum.package = cksum;
+ v.cksum.package = Some(cksum);
v.build();
assert_that(p.cargo("build"),
assert_that(p.cargo("build"), execs().with_status(0));
}
+
+#[test]
+fn git_lock_file_doesnt_change() {
+
+ let git = git::new("git", |p| {
+ p.file("Cargo.toml", r#"
+ [project]
+ name = "git"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+
+ VendorPackage::new("git")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "git"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .disable_checksum()
+ .build();
+
+ let p = project("bar")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ git = {{ git = '{0}' }}
+ "#, git.url()))
+ .file("src/lib.rs", "");
+ p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ let mut lock1 = String::new();
+ t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lock1));
+
+ let root = paths::root();
+ t!(fs::create_dir(&root.join(".cargo")));
+ t!(t!(File::create(root.join(".cargo/config"))).write_all(&format!(r#"
+ [source.my-git-repo]
+ git = '{}'
+ replace-with = 'my-awesome-local-registry'
+
+ [source.my-awesome-local-registry]
+ directory = 'index'
+ "#, git.url()).as_bytes()));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] [..]
+[COMPILING] [..]
+[FINISHED] [..]
+"));
+
+ let mut lock2 = String::new();
+ t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lock2));
+ assert!(lock1 == lock2, "lock files changed");
+}
+
+#[test]
+fn git_override_requires_lockfile() {
+ VendorPackage::new("git")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "git"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .disable_checksum()
+ .build();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ git = { git = 'https://example.com/' }
+ "#)
+ .file("src/lib.rs", "");
+ p.build();
+
+ let root = paths::root();
+ t!(fs::create_dir(&root.join(".cargo")));
+ t!(t!(File::create(root.join(".cargo/config"))).write_all(br#"
+ [source.my-git-repo]
+ git = 'https://example.com/'
+ replace-with = 'my-awesome-local-registry'
+
+ [source.my-awesome-local-registry]
+ directory = 'index'
+ "#));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to load source for a dependency on `git`
+
+Caused by:
+ Unable to update [..]
+
+Caused by:
+ the source my-git-repo requires a lock file to be present first before it can be
+used against vendored source code
+
+remove the source replacement configuration, generate a lock file, and then
+restore the source replacement configuration to continue the build
+
+"));
+}
}
Ok(())
}
+ fn supports_checksums(&self) -> bool { false }
+ fn requires_precise(&self) -> bool { false }
}
let mut registry = MyRegistry(registry);
let summary = Summary::new(pkg.clone(), deps, HashMap::new()).unwrap();