// Renaming a package in the manifest via the `package` key
[unstable] rename_dependency: bool,
+
+ // Whether a lock file is published with this crate
+ [unstable] publish_lockfile: bool,
}
}
metadata: ManifestMetadata,
profiles: Profiles,
publish: Option<Vec<String>>,
+ publish_lockfile: bool,
replace: Vec<(PackageIdSpec, Dependency)>,
patch: HashMap<Url, Vec<Dependency>>,
workspace: WorkspaceConfig,
metadata: ManifestMetadata,
profiles: Profiles,
publish: Option<Vec<String>>,
+ publish_lockfile: bool,
replace: Vec<(PackageIdSpec, Dependency)>,
patch: HashMap<Url, Vec<Dependency>>,
workspace: WorkspaceConfig,
epoch,
original,
im_a_teapot,
+ publish_lockfile,
}
}
pub fn warnings(&self) -> &[DelayedWarning] { &self.warnings }
pub fn profiles(&self) -> &Profiles { &self.profiles }
pub fn publish(&self) -> &Option<Vec<String>> { &self.publish }
+ pub fn publish_lockfile(&self) -> bool { self.publish_lockfile }
pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] { &self.replace }
pub fn original(&self) -> &TomlManifest { &self.original }
pub fn patch(&self) -> &HashMap<Url, Vec<Dependency>> { &self.patch }
use core::{Package, Workspace, Source, SourceId};
use sources::PathSource;
use util::{self, internal, Config, FileLock};
+use util::paths;
use util::errors::{CargoResult, CargoResultExt};
use ops::{self, DefaultExecutor};
pub fn package(ws: &Workspace,
opts: &PackageOpts) -> CargoResult<Option<FileLock>> {
+ ops::resolve_ws(ws)?;
let pkg = ws.current()?;
let config = ws.config();
let mut list: Vec<_> = src.list_files(pkg)?.iter().map(|file| {
util::without_prefix(file, root).unwrap().to_path_buf()
}).collect();
+ if include_lockfile(&pkg) {
+ list.push("Cargo.lock".into());
+ }
list.sort();
for file in list.iter() {
println!("{}", file.display());
Ok(Some(dst))
}
+fn include_lockfile(pkg: &Package) -> bool {
+ pkg.manifest().publish_lockfile() &&
+ pkg.targets().iter().any(|t| t.is_example() || t.is_bin())
+}
+
// check that the package has some piece of metadata that a human can
// use to tell what the package is about.
fn check_metadata(pkg: &Package, config: &Config) -> CargoResult<()> {
})?;
}
}
+
+ if include_lockfile(pkg) {
+ let toml = paths::read(&ws.root().join("Cargo.lock"))?;
+ let path = format!("{}-{}{}Cargo.lock", pkg.name(), pkg.version(),
+ path::MAIN_SEPARATOR);
+ let mut header = Header::new_ustar();
+ header.set_path(&path)?;
+ header.set_entry_type(EntryType::file());
+ header.set_mode(0o644);
+ header.set_size(toml.len() as u64);
+ header.set_cksum();
+ ar.append(&header, toml.as_bytes()).chain_err(|| {
+ internal("could not archive source file `Cargo.lock`")
+ })?;
+ }
+
let encoder = ar.into_inner()?;
encoder.finish()?;
Ok(())
exclude: Option<Vec<String>>,
include: Option<Vec<String>>,
publish: Option<VecStringOrBool>,
+ #[serde(rename = "publish-lockfile")]
+ publish_lockfile: Option<bool>,
workspace: Option<String>,
#[serde(rename = "im-a-teapot")]
im_a_teapot: Option<bool>,
None | Some(VecStringOrBool::Bool(true)) => None,
};
+ let publish_lockfile = match project.publish_lockfile {
+ Some(b) => {
+ features.require(Feature::publish_lockfile())?;
+ b
+ }
+ None => false,
+ };
+
let epoch = if let Some(ref epoch) = project.rust {
features.require(Feature::epoch()).chain_err(|| {
"epoches are unstable"
metadata,
profiles,
publish,
+ publish_lockfile,
replace,
patch,
workspace_config,
assert_that(cargo_process("install").arg("foo"),
execs().with_status(0));
}
+
+#[test]
+fn lock_file_path_deps_ok() {
+ Package::new("bar", "0.1.0").publish();
+
+ Package::new("foo", "0.1.0")
+ .dep("bar", "0.1")
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "
+ extern crate foo;
+ extern crate bar;
+ fn main() {}
+ ")
+ .file("Cargo.lock", r#"
+[[package]]
+name = "bar"
+version = "0.1.0"
+
+[[package]]
+name = "foo"
+version = "0.1.0"
+dependencies = [
+ "bar 0.1.0",
+]
+"#)
+ .publish();
+
+ assert_that(cargo_process("install").arg("foo"),
+ execs().with_status(0));
+}
#[test]
fn generated_manifest() {
Package::new("abc", "1.0.0").publish();
- Package::new("def", "1.0.0").publish();
+ Package::new("def", "1.0.0").alternative(true).publish();
Package::new("ghi", "1.0.0").publish();
+
let p = project("foo")
.file("Cargo.toml", r#"
cargo-features = ["alternative-registries"]
consider adding `cargo-features = [\"epoch\"]` to the manifest
")));
}
+
+#[test]
+fn package_lockfile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["publish-lockfile"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ publish-lockfile = true
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("package").masquerade_as_nightly_cargo(),
+ execs().with_status(0).with_stderr(&format!("\
+[WARNING] manifest has no documentation[..]
+See [..]
+[PACKAGING] foo v0.0.1 ({dir})
+[VERIFYING] foo v0.0.1 ({dir})
+[COMPILING] foo v0.0.1 ({dir}[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.url())));
+ assert_that(&p.root().join("target/package/foo-0.0.1.crate"), existing_file());
+ assert_that(p.cargo("package").arg("-l").masquerade_as_nightly_cargo(),
+ execs().with_status(0).with_stdout("\
+Cargo.lock
+Cargo.toml
+src[/]main.rs
+"));
+ assert_that(p.cargo("package").masquerade_as_nightly_cargo(),
+ execs().with_status(0).with_stdout(""));
+
+ let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
+ let mut rdr = GzDecoder::new(f);
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ for f in ar.entries().unwrap() {
+ let f = f.unwrap();
+ let fname = f.header().path_bytes();
+ let fname = &*fname;
+ assert!(fname == b"foo-0.0.1/Cargo.toml" ||
+ fname == b"foo-0.0.1/Cargo.toml.orig" ||
+ fname == b"foo-0.0.1/Cargo.lock" ||
+ fname == b"foo-0.0.1/src/main.rs",
+ "unexpected filename: {:?}", f.header().path())
+ }
+}
+
+#[test]
+fn package_lockfile_git_repo() {
+ let p = project("foo").build();
+
+ // Create a Git repository containing a minimal Rust project.
+ let _ = git::repo(&paths::root().join("foo"))
+ .file("Cargo.toml", r#"
+ cargo-features = ["publish-lockfile"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ license = "MIT"
+ description = "foo"
+ documentation = "foo"
+ homepage = "foo"
+ repository = "foo"
+ publish-lockfile = true
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+ assert_that(p.cargo("package").arg("-l").masquerade_as_nightly_cargo(),
+ execs().with_status(0).with_stdout("\
+Cargo.lock
+Cargo.toml
+src/main.rs
+"));
+}
+
+#[test]
+fn no_lock_file_with_library() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["publish-lockfile"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ publish-lockfile = true
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("package").masquerade_as_nightly_cargo(),
+ execs().with_status(0));
+
+ let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
+ let mut rdr = GzDecoder::new(f);
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ for f in ar.entries().unwrap() {
+ let f = f.unwrap();
+ let fname = f.header().path().unwrap();
+ assert!(!fname.ends_with("Cargo.lock"));
+ }
+}
+
+#[test]
+fn lock_file_and_workspace() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ cargo-features = ["publish-lockfile"]
+
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ publish-lockfile = true
+ "#)
+ .file("foo/src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("package")
+ .cwd(p.root().join("foo"))
+ .masquerade_as_nightly_cargo(),
+ execs().with_status(0));
+
+ let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
+ let mut rdr = GzDecoder::new(f);
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ assert!(
+ ar.entries().unwrap()
+ .into_iter()
+ .any(|f|{
+ let f = f.unwrap();
+ let fname = f.header().path().unwrap();
+ fname.ends_with("Cargo.lock")
+ })
+ );
+}