cargo/tests/testsuite/package.rs

1419 lines
36 KiB
Rust
Raw Normal View History

use std;
use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
2014-09-09 02:38:16 +00:00
use git2;
use cargotest::{cargo_process, process, ChannelChanger};
2018-03-14 15:17:44 +00:00
use cargotest::support::{cargo_exe, execs, git, paths, project, registry, path2url};
use cargotest::support::registry::Package;
use flate2::read::GzDecoder;
2018-03-14 15:17:44 +00:00
use hamcrest::{assert_that, contains, existing_file};
use tar::Archive;
#[test]
fn simple() {
let p = project("foo")
.file("Cargo.toml", r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
2014-09-09 02:38:16 +00:00
exclude = ["*.txt"]
license = "MIT"
description = "foo"
"#)
.file("src/main.rs", r#"
fn main() { println!("hello"); }
2014-09-09 02:38:16 +00:00
"#)
.file("src/bar.txt", "") // should be ignored when packaging
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package"),
execs().with_status(0).with_stderr(&format!(
"\
2016-05-20 00:52:13 +00:00
[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 [..]
",
2018-03-14 15:17:44 +00:00
dir = p.url()
)),
);
assert_that(
&p.root().join("target/package/foo-0.0.1.crate"),
existing_file(),
);
assert_that(
p.cargo("package").arg("-l"),
execs().with_status(0).with_stdout(
"\
Cargo.toml
src[/]main.rs
2018-03-14 15:17:44 +00:00
",
),
);
assert_that(p.cargo("package"), execs().with_status(0).with_stdout(""));
2014-09-09 02:38:16 +00:00
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;
2018-03-14 15:17:44 +00:00
assert!(
fname == b"foo-0.0.1/Cargo.toml" || fname == b"foo-0.0.1/Cargo.toml.orig"
|| fname == b"foo-0.0.1/src/main.rs",
"unexpected filename: {:?}",
f.header().path()
)
2014-09-09 02:38:16 +00:00
}
}
#[test]
fn metadata_warning() {
let p = project("all")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"src/main.rs",
r#"
fn main() {}
2018-03-14 15:17:44 +00:00
"#,
)
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package"),
execs().with_status(0).with_stderr(&format!(
"\
2016-05-20 00:52:13 +00:00
warning: manifest has no description, license, license-file, documentation, \
homepage or repository.
See http://doc.crates.io/manifest.html#package-metadata for more info.
[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 [..]
",
2018-03-14 15:17:44 +00:00
dir = p.url()
)),
);
let p = project("one")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
license = "MIT"
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"src/main.rs",
r#"
fn main() {}
2018-03-14 15:17:44 +00:00
"#,
)
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package"),
execs().with_status(0).with_stderr(&format!(
"\
warning: manifest has no description, documentation, homepage or repository.
See http://doc.crates.io/manifest.html#package-metadata for more info.
[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 [..]
",
2018-03-14 15:17:44 +00:00
dir = p.url()
)),
);
let p = project("all")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
license = "MIT"
description = "foo"
repository = "bar"
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"src/main.rs",
r#"
fn main() {}
2018-03-14 15:17:44 +00:00
"#,
)
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package"),
execs().with_status(0).with_stderr(&format!(
"\
[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 [..]
",
2018-03-14 15:17:44 +00:00
dir = p.url()
)),
);
}
#[test]
fn package_verbose() {
let root = paths::root().join("all");
let p = git::repo(&root)
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"src/main.rs",
r#"
fn main() {}
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"a/Cargo.toml",
r#"
[project]
name = "a"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
)
.file("a/src/lib.rs", "")
.build();
let mut cargo = cargo_process();
cargo.cwd(p.root());
assert_that(cargo.clone().arg("build"), execs().with_status(0));
println!("package main repo");
2018-03-14 15:17:44 +00:00
assert_that(
cargo.clone().arg("package").arg("-v").arg("--no-verify"),
execs().with_status(0).with_stderr(
"\
2016-05-20 00:52:13 +00:00
[WARNING] manifest has no description[..]
See http://doc.crates.io/manifest.html#package-metadata for more info.
[PACKAGING] foo v0.0.1 ([..])
[ARCHIVING] [..]
[ARCHIVING] [..]
2018-03-14 15:17:44 +00:00
",
),
);
println!("package sub-repo");
2018-03-14 15:17:44 +00:00
assert_that(
cargo
.arg("package")
.arg("-v")
.arg("--no-verify")
.cwd(p.root().join("a")),
execs().with_status(0).with_stderr(
"\
2016-05-20 00:52:13 +00:00
[WARNING] manifest has no description[..]
See http://doc.crates.io/manifest.html#package-metadata for more info.
[PACKAGING] a v0.0.1 ([..])
[ARCHIVING] [..]
[ARCHIVING] [..]
2018-03-14 15:17:44 +00:00
",
),
);
}
#[test]
fn package_verification() {
let p = project("all")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"src/main.rs",
r#"
fn main() {}
2018-03-14 15:17:44 +00:00
"#,
)
.build();
2018-03-14 15:17:44 +00:00
assert_that(p.cargo("build"), execs().with_status(0));
assert_that(
p.cargo("package"),
execs().with_status(0).with_stderr(&format!(
"\
2016-05-20 00:52:13 +00:00
[WARNING] manifest has no description[..]
See http://doc.crates.io/manifest.html#package-metadata for more info.
[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 [..]
",
2018-03-14 15:17:44 +00:00
dir = p.url()
)),
);
}
#[test]
fn path_dependency_no_version() {
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
license = "MIT"
description = "foo"
[dependencies.bar]
path = "bar"
2018-03-14 15:17:44 +00:00
"#,
)
.file("src/main.rs", "fn main() {}")
2018-03-14 15:17:44 +00:00
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
)
.file("bar/src/lib.rs", "")
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package"),
execs().with_status(101).with_stderr(
"\
[WARNING] manifest has no documentation, homepage or repository.
See http://doc.crates.io/manifest.html#package-metadata for more info.
[ERROR] all path dependencies must have a version specified when packaging.
dependency `bar` does not specify a version.
2018-03-14 15:17:44 +00:00
",
),
);
}
#[test]
fn exclude() {
let p = project("foo")
.file("Cargo.toml", r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
exclude = [
"*.txt",
# file in root
"file_root_1", # NO_CHANGE (ignored)
"/file_root_2", # CHANGING (packaged -> ignored)
"file_root_3/", # NO_CHANGE (packaged)
"file_root_4/*", # NO_CHANGE (packaged)
"file_root_5/**", # NO_CHANGE (packaged)
# file in sub-dir
"file_deep_1", # CHANGING (packaged -> ignored)
"/file_deep_2", # NO_CHANGE (packaged)
"file_deep_3/", # NO_CHANGE (packaged)
"file_deep_4/*", # NO_CHANGE (packaged)
"file_deep_5/**", # NO_CHANGE (packaged)
# dir in root
"dir_root_1", # CHANGING (packaged -> ignored)
"/dir_root_2", # CHANGING (packaged -> ignored)
"dir_root_3/", # CHANGING (packaged -> ignored)
"dir_root_4/*", # NO_CHANGE (ignored)
"dir_root_5/**", # NO_CHANGE (ignored)
# dir in sub-dir
"dir_deep_1", # CHANGING (packaged -> ignored)
"/dir_deep_2", # NO_CHANGE
"dir_deep_3/", # CHANGING (packaged -> ignored)
"dir_deep_4/*", # CHANGING (packaged -> ignored)
"dir_deep_5/**", # CHANGING (packaged -> ignored)
]
"#)
.file("src/main.rs", r#"
fn main() { println!("hello"); }
"#)
.file("bar.txt", "")
.file("src/bar.txt", "")
// file in root
.file("file_root_1", "")
.file("file_root_2", "")
.file("file_root_3", "")
.file("file_root_4", "")
.file("file_root_5", "")
// file in sub-dir
.file("some_dir/file_deep_1", "")
.file("some_dir/file_deep_2", "")
.file("some_dir/file_deep_3", "")
.file("some_dir/file_deep_4", "")
.file("some_dir/file_deep_5", "")
// dir in root
.file("dir_root_1/some_dir/file", "")
.file("dir_root_2/some_dir/file", "")
.file("dir_root_3/some_dir/file", "")
.file("dir_root_4/some_dir/file", "")
.file("dir_root_5/some_dir/file", "")
// dir in sub-dir
.file("some_dir/dir_deep_1/some_dir/file", "")
.file("some_dir/dir_deep_2/some_dir/file", "")
.file("some_dir/dir_deep_3/some_dir/file", "")
.file("some_dir/dir_deep_4/some_dir/file", "")
.file("some_dir/dir_deep_5/some_dir/file", "")
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package").arg("--no-verify").arg("-v"),
execs().with_status(0).with_stdout("").with_stderr(
"\
2016-05-20 00:52:13 +00:00
[WARNING] manifest has no description[..]
See http://doc.crates.io/manifest.html#package-metadata for more info.
[PACKAGING] foo v0.0.1 ([..])
[WARNING] [..] file `dir_root_1[/]some_dir[/]file` WILL be excluded [..]
See [..]
[WARNING] [..] file `dir_root_2[/]some_dir[/]file` WILL be excluded [..]
See [..]
[WARNING] [..] file `dir_root_3[/]some_dir[/]file` WILL be excluded [..]
See [..]
[WARNING] [..] file `some_dir[/]dir_deep_1[/]some_dir[/]file` WILL be excluded [..]
See [..]
[WARNING] [..] file `some_dir[/]dir_deep_3[/]some_dir[/]file` WILL be excluded [..]
See [..]
[WARNING] [..] file `some_dir[/]file_deep_1` WILL be excluded [..]
See [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
2018-03-14 15:17:44 +00:00
",
),
);
2018-03-14 15:17:44 +00:00
assert_that(
&p.root().join("target/package/foo-0.0.1.crate"),
existing_file(),
);
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package").arg("-l"),
execs().with_status(0).with_stdout(
"\
Cargo.toml
dir_root_1[/]some_dir[/]file
dir_root_2[/]some_dir[/]file
dir_root_3[/]some_dir[/]file
file_root_3
file_root_4
file_root_5
some_dir[/]dir_deep_1[/]some_dir[/]file
some_dir[/]dir_deep_2[/]some_dir[/]file
some_dir[/]dir_deep_3[/]some_dir[/]file
some_dir[/]dir_deep_4[/]some_dir[/]file
some_dir[/]dir_deep_5[/]some_dir[/]file
some_dir[/]file_deep_1
some_dir[/]file_deep_2
some_dir[/]file_deep_3
some_dir[/]file_deep_4
some_dir[/]file_deep_5
src[/]main.rs
2018-03-14 15:17:44 +00:00
",
),
);
}
#[test]
fn include() {
let p = project("foo")
.file("Cargo.toml", r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
exclude = ["*.txt"]
include = ["foo.txt", "**/*.rs", "Cargo.toml"]
"#)
.file("foo.txt", "")
.file("src/main.rs", r#"
fn main() { println!("hello"); }
"#)
.file("src/bar.txt", "") // should be ignored when packaging
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package").arg("--no-verify").arg("-v"),
execs().with_status(0).with_stderr(
"\
2016-05-20 00:52:13 +00:00
[WARNING] manifest has no description[..]
See http://doc.crates.io/manifest.html#package-metadata for more info.
[PACKAGING] foo v0.0.1 ([..])
[ARCHIVING] [..]
[ARCHIVING] [..]
[ARCHIVING] [..]
2018-03-14 15:17:44 +00:00
",
),
);
}
#[test]
fn package_lib_with_bin() {
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"src/main.rs",
r#"
extern crate foo;
fn main() {}
2018-03-14 15:17:44 +00:00
"#,
)
.file("src/lib.rs", "")
.build();
2018-03-14 15:17:44 +00:00
assert_that(p.cargo("package").arg("-v"), execs().with_status(0));
}
#[test]
fn package_git_submodule() {
let project = git::new("foo", |project| {
2018-03-14 15:17:44 +00:00
project
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = ["foo@example.com"]
license = "MIT"
description = "foo"
repository = "foo"
2018-03-14 15:17:44 +00:00
"#,
)
.file("src/lib.rs", "pub fn foo() {}")
}).unwrap();
2018-03-14 15:17:44 +00:00
let library = git::new("bar", |library| library.file("Makefile", "all:")).unwrap();
let repository = git2::Repository::open(&project.root()).unwrap();
let url = path2url(library.root()).to_string();
git::add_submodule(&repository, &url, Path::new("bar"));
git::commit(&repository);
let repository = git2::Repository::open(&project.root().join("bar")).unwrap();
2018-03-14 15:17:44 +00:00
repository
.reset(
&repository.revparse_single("HEAD").unwrap(),
git2::ResetType::Hard,
None,
)
.unwrap();
assert_that(
cargo_process()
.arg("package")
.cwd(project.root())
.arg("--no-verify")
.arg("-v"),
execs()
.with_status(0)
.with_stderr_contains("[ARCHIVING] bar/Makefile"),
);
}
#[test]
fn no_duplicates_from_modified_tracked_files() {
let root = paths::root().join("all");
let p = git::repo(&root)
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"src/main.rs",
r#"
fn main() {}
2018-03-14 15:17:44 +00:00
"#,
)
.build();
2018-03-14 15:17:44 +00:00
File::create(p.root().join("src/main.rs"))
.unwrap()
.write_all(
br#"
fn main() { println!("A change!"); }
2018-03-14 15:17:44 +00:00
"#,
)
.unwrap();
let mut cargo = cargo_process();
cargo.cwd(p.root());
assert_that(cargo.clone().arg("build"), execs().with_status(0));
2018-03-14 15:17:44 +00:00
assert_that(
cargo.arg("package").arg("--list"),
execs().with_status(0).with_stdout(
"\
Cargo.toml
src/main.rs
2018-03-14 15:17:44 +00:00
",
),
);
}
#[test]
fn ignore_nested() {
let cargo_toml = r#"
[project]
name = "nested"
version = "0.0.1"
authors = []
license = "MIT"
description = "nested"
"#;
let main_rs = r#"
fn main() { println!("hello"); }
"#;
let p = project("nested")
.file("Cargo.toml", cargo_toml)
.file("src/main.rs", main_rs)
// If a project happens to contain a copy of itself, we should
// ignore it.
.file("a_dir/nested/Cargo.toml", cargo_toml)
.file("a_dir/nested/src/main.rs", main_rs)
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package"),
execs().with_status(0).with_stderr(&format!(
"\
2016-05-20 00:52:13 +00:00
[WARNING] manifest has no documentation[..]
See http://doc.crates.io/manifest.html#package-metadata for more info.
[PACKAGING] nested v0.0.1 ({dir})
[VERIFYING] nested v0.0.1 ({dir})
[COMPILING] nested v0.0.1 ({dir}[..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
2018-03-14 15:17:44 +00:00
dir = p.url()
)),
);
assert_that(
&p.root().join("target/package/nested-0.0.1.crate"),
existing_file(),
);
assert_that(
p.cargo("package").arg("-l"),
execs().with_status(0).with_stdout(
"\
Cargo.toml
src[..]main.rs
2018-03-14 15:17:44 +00:00
",
),
);
assert_that(p.cargo("package"), execs().with_status(0).with_stdout(""));
let f = File::open(&p.root().join("target/package/nested-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;
2018-03-14 15:17:44 +00:00
assert!(
fname == b"nested-0.0.1/Cargo.toml" || fname == b"nested-0.0.1/Cargo.toml.orig"
|| fname == b"nested-0.0.1/src/main.rs",
"unexpected filename: {:?}",
f.header().path()
)
}
}
#[cfg(unix)] // windows doesn't allow these characters in filenames
#[test]
fn package_weird_characters() {
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"src/main.rs",
r#"
fn main() { println!("hello"); }
2018-03-14 15:17:44 +00:00
"#,
)
.file("src/:foo", "")
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package"),
execs().with_status(101).with_stderr(
"\
warning: [..]
See [..]
2016-05-20 00:52:13 +00:00
[PACKAGING] foo [..]
[ERROR] failed to prepare local package for uploading
Caused by:
cannot package a filename with a special character `:`: src/:foo
2018-03-14 15:17:44 +00:00
",
),
);
}
#[test]
fn repackage_on_source_change() {
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"src/main.rs",
r#"
fn main() { println!("hello"); }
2018-03-14 15:17:44 +00:00
"#,
)
.build();
2018-03-14 15:17:44 +00:00
assert_that(p.cargo("package"), execs().with_status(0));
// Add another source file
let mut file = File::create(p.root().join("src").join("foo.rs")).unwrap_or_else(|e| {
2018-03-14 15:17:44 +00:00
panic!(
"could not create file {}: {}",
p.root().join("src/foo.rs").display(),
e
)
});
2018-03-14 15:17:44 +00:00
file.write_all(
br#"
fn main() { println!("foo"); }
2018-03-14 15:17:44 +00:00
"#,
).unwrap();
std::mem::drop(file);
let mut pro = process(&cargo_exe());
pro.arg("package").cwd(p.root());
// Check that cargo rebuilds the tarball
2018-03-14 15:17:44 +00:00
assert_that(
pro,
execs().with_status(0).with_stderr(&format!(
"\
[WARNING] [..]
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 [..]
",
2018-03-14 15:17:44 +00:00
dir = p.url()
)),
);
// Check that the tarball contains the added file
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[..]);
let entries = ar.entries().unwrap();
2018-03-14 15:17:44 +00:00
let entry_paths = entries
.map(|entry| entry.unwrap().path().unwrap().into_owned())
.collect::<Vec<PathBuf>>();
assert_that(
&entry_paths,
contains(vec![PathBuf::from("foo-0.0.1/src/foo.rs")]),
);
}
#[test]
#[cfg(unix)]
fn broken_symlink() {
use std::os::unix::fs;
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
license = "MIT"
description = 'foo'
documentation = 'foo'
homepage = 'foo'
repository = 'foo'
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"src/main.rs",
r#"
fn main() { println!("hello"); }
2018-03-14 15:17:44 +00:00
"#,
)
.build();
t!(fs::symlink("nowhere", &p.root().join("src/foo.rs")));
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package").arg("-v"),
execs().with_status(101).with_stderr_contains(
"\
error: failed to prepare local package for uploading
Caused by:
failed to open for archiving: `[..]foo.rs`
Caused by:
[..]
2018-03-14 15:17:44 +00:00
",
),
);
}
#[test]
fn do_not_package_if_repository_is_dirty() {
let p = project("foo").build();
// Create a Git repository containing a minimal Rust project.
let _ = git::repo(&paths::root().join("foo"))
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
license = "MIT"
description = "foo"
documentation = "foo"
homepage = "foo"
repository = "foo"
2018-03-14 15:17:44 +00:00
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
// Modify Cargo.toml without committing the change.
2018-03-14 15:17:44 +00:00
p.change_file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
license = "MIT"
description = "foo"
documentation = "foo"
homepage = "foo"
repository = "foo"
# change
2018-03-14 15:17:44 +00:00
"#,
);
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package"),
execs().with_status(101).with_stderr(
"\
error: 1 files in the working directory contain changes that were not yet \
committed into git:
Cargo.toml
to proceed despite this, pass the `--allow-dirty` flag
2018-03-14 15:17:44 +00:00
",
),
);
}
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
#[test]
fn generated_manifest() {
Package::new("abc", "1.0.0").publish();
Package::new("def", "1.0.0").alternative(true).publish();
Package::new("ghi", "1.0.0").publish();
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
cargo-features = ["alternative-registries"]
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
[project]
name = "foo"
version = "0.0.1"
authors = []
exclude = ["*.txt"]
license = "MIT"
description = "foo"
[project.metadata]
foo = 'bar'
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
[workspace]
[dependencies]
bar = { path = "bar", version = "0.1" }
def = { version = "1.0", registry = "alternative" }
ghi = "1.0"
abc = "1.0"
2018-03-14 15:17:44 +00:00
"#,
)
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
.file("src/main.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"bar/Cargo.toml",
r#"
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
[package]
name = "bar"
version = "0.1.0"
authors = []
2018-03-14 15:17:44 +00:00
"#,
)
.file("bar/src/lib.rs", "")
.build();
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package")
.masquerade_as_nightly_cargo()
.arg("--no-verify"),
execs().with_status(0),
);
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
let mut rdr = GzDecoder::new(f);
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
let mut contents = Vec::new();
rdr.read_to_end(&mut contents).unwrap();
let mut ar = Archive::new(&contents[..]);
2018-03-14 15:17:44 +00:00
let mut entry = ar.entries()
.unwrap()
.map(|f| f.unwrap())
.find(|e| e.path().unwrap().ends_with("Cargo.toml"))
.unwrap();
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
let mut contents = String::new();
entry.read_to_string(&mut contents).unwrap();
// BTreeMap makes the order of dependencies in the generated file deterministic
// by sorting alphabetically
2018-03-14 15:17:44 +00:00
assert_eq!(
&contents[..],
&*format!(
r#"# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g. crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
cargo-features = ["alternative-registries"]
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
exclude = ["*.txt"]
description = "foo"
license = "MIT"
[package.metadata]
foo = "bar"
[dependencies.abc]
version = "1.0"
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
[dependencies.bar]
version = "0.1"
[dependencies.def]
version = "1.0"
2018-01-18 19:53:12 +00:00
registry-index = "{}"
[dependencies.ghi]
version = "1.0"
"#,
2018-03-14 15:17:44 +00:00
registry::alt_registry()
)
);
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
}
#[test]
fn ignore_workspace_specifier() {
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
[project]
name = "foo"
version = "0.0.1"
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
authors = []
[workspace]
[dependencies]
bar = { path = "bar", version = "0.1" }
2018-03-14 15:17:44 +00:00
"#,
)
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
.file("src/main.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"bar/Cargo.toml",
r#"
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
[package]
name = "bar"
version = "0.1.0"
authors = []
workspace = ".."
2018-03-14 15:17:44 +00:00
"#,
)
.file("bar/src/lib.rs", "")
.build();
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package")
.arg("--no-verify")
.cwd(p.root().join("bar")),
execs().with_status(0),
);
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
let f = File::open(&p.root().join("target/package/bar-0.1.0.crate")).unwrap();
let mut rdr = GzDecoder::new(f);
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
let mut contents = Vec::new();
rdr.read_to_end(&mut contents).unwrap();
let mut ar = Archive::new(&contents[..]);
2018-03-14 15:17:44 +00:00
let mut entry = ar.entries()
.unwrap()
.map(|f| f.unwrap())
.find(|e| e.path().unwrap().ends_with("Cargo.toml"))
.unwrap();
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
let mut contents = String::new();
entry.read_to_string(&mut contents).unwrap();
2018-03-14 15:17:44 +00:00
assert_eq!(
&contents[..],
r#"# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g. crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
[package]
name = "bar"
version = "0.1.0"
authors = []
2018-03-14 15:17:44 +00:00
"#
);
Rewrite Cargo.toml when packaging crates This commit is an implementation of rewriting TOML manifests when we publish them to the registry. The rationale for doing this is to provide a guarantee that downloaded tarballs from crates.io can be built with `cargo build` (literally). This in turn eases a number of other possible consumers of crates from crates.io * Vendored sources can now be more easily modified/checked as cargo build should work and they're standalone crates that suffice for `path` dependencies * Tools like cargobomb/crater no longer need to edit the manifest and can instead perform regression testing on the literal tarballs they download * Other systems such as packaging Rust code may be able to take advantage of this, but this is a less clear benefit. Overall I'm hesitatnt about this, unfortunately. This is a silent translation happening on *publish*, a rare operation, that's difficult to inspect before it flies up to crates.io. I wrote a script to run this transformation over all crates.io crates and found a surprisingly large number of discrepancies. The transformation basically just downloaded all crates at all versions, regenerated the manifest, and then tested if the two manifests were (in memory) the same. Unfortunately historical Cargo had a critical bug which I think made this exercise not too useful. Cargo used to *not* recreate tarballs if one already existed, which I believe led to situations such as: 1. `cargo publish` 2. Cargo generates an error about a dependency. This could be that there's a `version` not present in a `path` dependency, there could be a `git` dependency, etc. 3. Errors are fixed. 4. `cargo publish` 5. Publish is successful In step 4 above historical Cargo *would not recreate the tarball*. This means that the contents of the index (what was published) aren't guaranteed to match with the tarball's `Cargo.toml`. When building from crates.io this is ok as the index is the source of truth for dependency information, but it means that *any* transformation to rewrite Cargo.toml is impossible to verify against all crates on crates.io (due to historical bugs like these). I strove to read as many errors as possible regardless, attempting to suss out bugs in the implementation here. To further guard against surprises I've updated the verification step of packaging to work "normally" in these sense that it's not rewriting dependencies itself or changing summaries. I'm hoping that this serves as a good last-ditch effort that what we're about to publish will indeed build as expected when uploaded to crates.io Overall I'm probably 70% confident in this change. I think it's necessary to make progress, but I think there are going to be very painful bugs that arise from this feature. I'm open to ideas to help weed out these bugs ahead of time! I've done what I can but I fear it may not be entirely enough. Closes #4027
2017-05-11 05:09:44 +00:00
}
#[test]
fn package_two_kinds_of_deps() {
Package::new("other", "1.0.0").publish();
Package::new("other1", "1.0.0").publish();
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
other = "1.0"
other1 = { version = "1.0" }
2018-03-14 15:17:44 +00:00
"#,
)
.file("src/main.rs", "")
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package").arg("--no-verify"),
execs().with_status(0),
);
}
2018-02-05 21:42:42 +00:00
#[test]
2018-03-21 16:41:22 +00:00
fn test_edition() {
2018-02-05 21:42:42 +00:00
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2018-03-21 16:41:22 +00:00
cargo-features = ["edition"]
2018-02-05 21:42:42 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
edition = "2018"
2018-03-14 15:17:44 +00:00
"#,
)
2018-02-05 21:42:42 +00:00
.file("src/lib.rs", r#" "#)
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("build").arg("-v").masquerade_as_nightly_cargo(),
execs()
2018-04-22 19:14:21 +00:00
// --edition is still in flux and we're not passing -Zunstable-options
2018-02-05 21:42:42 +00:00
// from Cargo so it will probably error. Only partially match the output
// until stuff stabilizes
.with_stderr_contains("\
[COMPILING] foo v0.0.1 ([..])
[RUNNING] `rustc [..]--edition=2018 [..]
"),
2018-03-14 15:17:44 +00:00
);
2018-02-05 21:42:42 +00:00
}
#[test]
2018-03-21 16:41:22 +00:00
fn test_edition_missing() {
// no edition = 2015
2018-02-05 21:42:42 +00:00
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2018-03-21 16:41:22 +00:00
cargo-features = ["edition"]
2018-02-05 21:42:42 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2018-03-14 15:17:44 +00:00
"#,
)
2018-02-05 21:42:42 +00:00
.file("src/lib.rs", r#" "#)
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("build").arg("-v").masquerade_as_nightly_cargo(),
execs()
2018-04-22 19:14:21 +00:00
// --edition is still in flux and we're not passing -Zunstable-options
2018-02-05 21:42:42 +00:00
// from Cargo so it will probably error. Only partially match the output
// until stuff stabilizes
.with_stderr_contains("\
[COMPILING] foo v0.0.1 ([..])
[RUNNING] `rustc [..]--edition=2015 [..]
"),
2018-03-14 15:17:44 +00:00
);
2018-02-05 21:42:42 +00:00
}
#[test]
2018-03-21 16:41:22 +00:00
fn test_edition_malformed() {
2018-02-05 21:42:42 +00:00
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2018-03-21 16:41:22 +00:00
cargo-features = ["edition"]
2018-02-05 21:42:42 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
edition = "chicken"
2018-03-14 15:17:44 +00:00
"#,
)
2018-02-05 21:42:42 +00:00
.file("src/lib.rs", r#" "#)
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("build").arg("-v").masquerade_as_nightly_cargo(),
execs().with_status(101).with_stderr(format!(
"\
2018-02-05 21:42:42 +00:00
error: failed to parse manifest at `[..]`
Caused by:
failed to parse the `edition` key
Caused by:
supported edition values are `2015` or `2018`, but `chicken` is unknown
2018-03-14 15:17:44 +00:00
"
)),
);
2018-02-05 21:42:42 +00:00
}
#[test]
2018-03-21 16:41:22 +00:00
fn test_edition_nightly() {
2018-02-05 21:42:42 +00:00
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2018-02-05 21:42:42 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
edition = "2015"
2018-03-14 15:17:44 +00:00
"#,
)
2018-02-05 21:42:42 +00:00
.file("src/lib.rs", r#" "#)
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("build").arg("-v").masquerade_as_nightly_cargo(),
execs().with_status(101).with_stderr(format!(
"\
2018-02-05 21:42:42 +00:00
error: failed to parse manifest at `[..]`
Caused by:
editions are unstable
2018-02-05 21:42:42 +00:00
Caused by:
2018-03-21 16:41:22 +00:00
feature `edition` is required
2018-02-05 21:42:42 +00:00
2018-03-21 16:41:22 +00:00
consider adding `cargo-features = [\"edition\"]` to the manifest
2018-03-14 15:17:44 +00:00
"
)),
);
}
#[test]
fn package_lockfile() {
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
cargo-features = ["publish-lockfile"]
[project]
name = "foo"
version = "0.0.1"
authors = []
license = "MIT"
description = "foo"
publish-lockfile = true
2018-03-14 15:17:44 +00:00
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
2018-03-14 15:17:44 +00:00
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 [..]
",
2018-03-14 15:17:44 +00:00
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
2018-03-14 15:17:44 +00:00
",
),
);
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;
2018-03-14 15:17:44 +00:00
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"))
2018-03-14 15:17:44 +00:00
.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
2018-03-14 15:17:44 +00:00
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
2018-03-14 15:17:44 +00:00
assert_that(
p.cargo("package").arg("-l").masquerade_as_nightly_cargo(),
execs().with_status(0).with_stdout(
"\
Cargo.lock
Cargo.toml
src/main.rs
2018-03-14 15:17:44 +00:00
",
),
);
}
#[test]
fn no_lock_file_with_library() {
let p = project("foo")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
cargo-features = ["publish-lockfile"]
[project]
name = "foo"
version = "0.0.1"
authors = []
license = "MIT"
description = "foo"
publish-lockfile = true
2018-03-14 15:17:44 +00:00
"#,
)
.file("src/lib.rs", "")
.build();
2018-03-14 15:17:44 +00:00
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")
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
[workspace]
members = ["foo"]
2018-03-14 15:17:44 +00:00
"#,
)
.file(
"foo/Cargo.toml",
r#"
cargo-features = ["publish-lockfile"]
[package]
name = "foo"
version = "0.0.1"
authors = []
license = "MIT"
description = "foo"
publish-lockfile = true
2018-03-14 15:17:44 +00:00
"#,
)
.file("foo/src/main.rs", "fn main() {}")
.build();
2018-03-14 15:17:44 +00:00
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[..]);
2018-03-14 15:17:44 +00:00
assert!(ar.entries().unwrap().into_iter().any(|f| {
let f = f.unwrap();
let fname = f.header().path().unwrap();
fname.ends_with("Cargo.lock")
}));
}