3 use std
::io
::prelude
::*;
6 use crate::support
::registry
::Package
;
8 basic_manifest
, git
, is_nightly
, path2url
, paths
, project
, publish
::validate_crate_contents
,
11 use crate::support
::{cargo_process, sleep_ms}
;
29 .file("src/main.rs", r
#"fn main() { println!("hello"); }"#)
30 .file("src/bar.txt", "") // should be ignored when packaging
36 [WARNING] manifest has no documentation[..]
38 [PACKAGING] foo v0.0.1 ([CWD])
39 [VERIFYING] foo v0.0.1 ([CWD])
40 [COMPILING] foo v0.0.1 ([CWD][..])
41 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
45 assert
!(p
.root().join("target/package/foo-0.0.1.crate").is_file());
54 p
.cargo("package").with_stdout("").run();
56 let f
= File
::open(&p
.root().join("target/package/foo-0.0.1.crate")).unwrap();
57 validate_crate_contents(
60 &["Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
66 fn metadata_warning() {
67 let p
= project().file("src/main.rs", "fn main() {}").build();
71 warning: manifest has no description, license, license-file, documentation, \
72 homepage or repository.
73 See http://doc.crates.io/manifest.html#package-metadata for more info.
74 [PACKAGING] foo v0.0.1 ([CWD])
75 [VERIFYING] foo v0.0.1 ([CWD])
76 [COMPILING] foo v0.0.1 ([CWD][..])
77 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
93 .file("src/main.rs", "fn main() {}")
98 warning: manifest has no description, documentation, homepage or repository.
99 See http://doc.crates.io/manifest.html#package-metadata for more info.
100 [PACKAGING] foo v0.0.1 ([CWD])
101 [VERIFYING] foo v0.0.1 ([CWD])
102 [COMPILING] foo v0.0.1 ([CWD][..])
103 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
121 .file("src/main.rs", "fn main() {}")
126 [PACKAGING] foo v0.0.1 ([CWD])
127 [VERIFYING] foo v0.0.1 ([CWD])
128 [COMPILING] foo v0.0.1 ([CWD][..])
129 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
136 fn package_verbose() {
137 let root
= paths
::root().join("all");
138 let repo
= git
::repo(&root
)
139 .file("Cargo.toml", &basic_manifest("foo", "0.0.1"))
140 .file("src/main.rs", "fn main() {}")
141 .file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
142 .file("a/src/lib.rs", "")
144 cargo_process("build").cwd(repo
.root()).run();
146 println
!("package main repo");
147 cargo_process("package -v --no-verify")
151 [WARNING] manifest has no description[..]
152 See http://doc.crates.io/manifest.html#package-metadata for more info.
153 [PACKAGING] foo v0.0.1 ([..])
156 [ARCHIVING] .cargo_vcs_info.json
161 let f
= File
::open(&repo
.root().join("target/package/foo-0.0.1.crate")).unwrap();
162 let vcs_contents
= format
!(
171 validate_crate_contents(
178 ".cargo_vcs_info.json",
180 &[(".cargo_vcs_info.json", &vcs_contents
)],
183 println
!("package sub-repo");
184 cargo_process("package -v --no-verify")
185 .cwd(repo
.root().join("a"))
188 [WARNING] manifest has no description[..]
189 See http://doc.crates.io/manifest.html#package-metadata for more info.
190 [PACKAGING] a v0.0.1 ([..])
191 [ARCHIVING] Cargo.toml
192 [ARCHIVING] src/lib.rs
193 [ARCHIVING] .cargo_vcs_info.json
200 fn package_verification() {
201 let p
= project().file("src/main.rs", "fn main() {}").build();
202 p
.cargo("build").run();
206 [WARNING] manifest has no description[..]
207 See http://doc.crates.io/manifest.html#package-metadata for more info.
208 [PACKAGING] foo v0.0.1 ([CWD])
209 [VERIFYING] foo v0.0.1 ([CWD])
210 [COMPILING] foo v0.0.1 ([CWD][..])
211 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
218 fn vcs_file_collision() {
219 let p
= project().build();
220 let _
= git
::repo(&paths
::root().join("foo"))
230 documentation = "foo"
233 exclude = ["*.no-existe"]
242 .file(".cargo_vcs_info.json", "foo")
249 [ERROR] Invalid inclusion of reserved file name .cargo_vcs_info.json \
257 fn path_dependency_no_version() {
273 .file("src/main.rs", "fn main() {}")
274 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
275 .file("bar/src/lib.rs", "")
282 [WARNING] manifest has no documentation, homepage or repository.
283 See http://doc.crates.io/manifest.html#package-metadata for more info.
284 [ERROR] all path dependencies must have a version specified when packaging.
285 dependency `bar` does not specify a version.
293 let root
= paths
::root().join("exclude");
294 let repo
= git
::repo(&root
)
305 "file_root_1", # NO_CHANGE (ignored)
306 "/file_root_2", # CHANGING (packaged -> ignored)
307 "file_root_3/", # NO_CHANGE (packaged)
308 "file_root_4/*", # NO_CHANGE (packaged)
309 "file_root_5/**", # NO_CHANGE (packaged)
311 "file_deep_1", # CHANGING (packaged -> ignored)
312 "/file_deep_2", # NO_CHANGE (packaged)
313 "file_deep_3/", # NO_CHANGE (packaged)
314 "file_deep_4/*", # NO_CHANGE (packaged)
315 "file_deep_5/**", # NO_CHANGE (packaged)
317 "dir_root_1", # CHANGING (packaged -> ignored)
318 "/dir_root_2", # CHANGING (packaged -> ignored)
319 "dir_root_3/", # CHANGING (packaged -> ignored)
320 "dir_root_4/*", # NO_CHANGE (ignored)
321 "dir_root_5/**", # NO_CHANGE (ignored)
323 "dir_deep_1", # CHANGING (packaged -> ignored)
324 "/dir_deep_2", # NO_CHANGE
325 "dir_deep_3/", # CHANGING (packaged -> ignored)
326 "dir_deep_4/*", # CHANGING (packaged -> ignored)
327 "dir_deep_5/**", # CHANGING (packaged -> ignored)
331 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
333 .file("src/bar.txt", "")
335 .file("file_root_1", "")
336 .file("file_root_2", "")
337 .file("file_root_3", "")
338 .file("file_root_4", "")
339 .file("file_root_5", "")
341 .file("some_dir/file_deep_1", "")
342 .file("some_dir/file_deep_2", "")
343 .file("some_dir/file_deep_3", "")
344 .file("some_dir/file_deep_4", "")
345 .file("some_dir/file_deep_5", "")
347 .file("dir_root_1/some_dir/file", "")
348 .file("dir_root_2/some_dir/file", "")
349 .file("dir_root_3/some_dir/file", "")
350 .file("dir_root_4/some_dir/file", "")
351 .file("dir_root_5/some_dir/file", "")
353 .file("some_dir/dir_deep_1/some_dir/file", "")
354 .file("some_dir/dir_deep_2/some_dir/file", "")
355 .file("some_dir/dir_deep_3/some_dir/file", "")
356 .file("some_dir/dir_deep_4/some_dir/file", "")
357 .file("some_dir/dir_deep_5/some_dir/file", "")
360 cargo_process("package --no-verify -v")
365 [WARNING] manifest has no description[..]
366 See http://doc.crates.io/manifest.html#package-metadata for more info.
367 [WARNING] [..] file `dir_root_1/some_dir/file` WILL be excluded [..]
369 [WARNING] [..] file `dir_root_2/some_dir/file` WILL be excluded [..]
371 [WARNING] [..] file `dir_root_3/some_dir/file` WILL be excluded [..]
373 [WARNING] [..] file `some_dir/dir_deep_1/some_dir/file` WILL be excluded [..]
375 [WARNING] [..] file `some_dir/dir_deep_3/some_dir/file` WILL be excluded [..]
377 [WARNING] [..] file `some_dir/file_deep_1` WILL be excluded [..]
379 [PACKAGING] foo v0.0.1 ([..])
398 [ARCHIVING] .cargo_vcs_info.json
403 assert!(repo.root().join("target/package/foo-0.0.1.crate").is_file());
405 cargo_process("package -l")
411 dir_root_1/some_dir/file
412 dir_root_2/some_dir/file
413 dir_root_3/some_dir/file
417 some_dir/dir_deep_1/some_dir/file
418 some_dir/dir_deep_2/some_dir/file
419 some_dir/dir_deep_3/some_dir/file
420 some_dir/dir_deep_4/some_dir/file
421 some_dir/dir_deep_5/some_dir/file
435 let root = paths::root().join("include");
436 let repo = git::repo(&root)
445 include = ["foo.txt", "**/*.rs", "Cargo.toml"]
449 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
450 .file("src/bar.txt", "") // should be ignored when packaging
453 cargo_process("package --no-verify -v")
457 [WARNING] manifest has no description[..]
458 See http://doc.crates.io/manifest.html#package-metadata for more info.
459 [PACKAGING] foo v0.0.1 ([..])
463 [ARCHIVING] .cargo_vcs_info.json
470 fn package_lib_with_bin() {
472 .file("src/main.rs", "extern crate foo; fn main() {}")
473 .file("src/lib.rs", "")
476 p.cargo("package -v").run();
480 fn package_git_submodule() {
481 let project = git::new("foo", |project| {
489 authors = ["foo@example.com"]
495 .file("src/lib.rs", "pub fn foo() {}")
498 let library = git::new("bar", |library| {
499 library.no_manifest().file("Makefile", "all:")
503 let repository = git2::Repository::open(&project.root()).unwrap();
504 let url = path2url(library.root()).to_string();
505 git::add_submodule(&repository, &url, Path::new("bar"));
506 git::commit(&repository);
508 let repository = git2::Repository::open(&project.root().join("bar")).unwrap();
511 &repository.revparse_single("HEAD").unwrap(),
512 git2::ResetType::Hard,
518 .cargo("package --no-verify -v")
519 .with_stderr_contains("[ARCHIVING] bar/Makefile")
524 fn no_duplicates_from_modified_tracked_files() {
525 let root = paths::root().join("all");
526 let p = git::repo(&root)
527 .file("Cargo.toml", &basic_manifest("foo", "0.0.1"))
528 .file("src/main.rs", "fn main() {}")
530 File::create(p.root().join("src/main.rs"))
532 .write_all(br#"fn main() { println!("A change!"); }"#)
534 cargo_process("build").cwd(p.root()).run();
535 cargo_process("package --list --allow-dirty")
557 fn main() { println!("hello"); }
560 .file("Cargo.toml", cargo_toml)
561 .file("src/main.rs", main_rs)
562 // If a project happens to contain a copy of itself, we should
564 .file("a_dir/foo/Cargo.toml", cargo_toml)
565 .file("a_dir/foo/src/main.rs", main_rs)
571 [WARNING] manifest has no documentation[..]
572 See http://doc.crates.io/manifest.html#package-metadata for more info.
573 [PACKAGING] foo v0.0.1 ([CWD])
574 [VERIFYING] foo v0.0.1 ([CWD])
575 [COMPILING] foo v0.0.1 ([CWD][..])
576 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
580 assert!(p.root().join("target/package/foo-0.0.1.crate").is_file());
581 p.cargo("package -l")
589 p.cargo("package").with_stdout("").run();
591 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
592 validate_crate_contents(
595 &["Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
600 #[cfg(unix)] // windows doesn't allow these characters in filenames
602 fn package_weird_characters() {
604 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
605 .file("src/:foo", "")
615 [ERROR] failed to prepare local package for uploading
618 cannot package a filename with a special character `:`: src/:foo
625 fn repackage_on_source_change() {
627 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
630 p.cargo("package").run();
632 // Add another source file
633 let mut file = File::create(p.root().join("src").join("foo.rs")).unwrap_or_else(|e| {
635 "could not create file {}: {}",
636 p.root().join("src/foo.rs").display(),
641 file.write_all(br#"fn main() { println!("foo"); }"#)
643 std::mem::drop(file);
645 // Check that cargo rebuilds the tarball
651 [PACKAGING] foo v0.0.1 ([CWD])
652 [VERIFYING] foo v0.0.1 ([CWD])
653 [COMPILING] foo v0.0.1 ([CWD][..])
654 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
659 // Check that the tarball contains the added file
660 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
661 validate_crate_contents(
664 &["Cargo.toml", "Cargo.toml.orig", "src/main.rs", "src/foo.rs"],
671 fn broken_symlink() {
672 use std::os::unix::fs;
684 documentation = 'foo'
689 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
691 t!(fs::symlink("nowhere", &p.root().join("src/foo.rs")));
693 p.cargo("package -v")
695 .with_stderr_contains(
697 error: failed to prepare local package for uploading
700 failed to open for archiving: `[..]foo.rs`
710 fn do_not_package_if_repository_is_dirty() {
711 let p = project().build();
713 // Create a Git repository containing a minimal Rust project.
714 let _ = git::repo(&paths::root().join("foo"))
723 documentation = "foo"
728 .file("src/main.rs", "fn main() {}")
731 // Modify Cargo.toml without committing the change.
740 documentation = "foo"
751 error: 1 files in the working directory contain changes that were not yet \
756 to proceed despite this, pass the `--allow-dirty` flag
763 fn generated_manifest() {
764 Package::new("abc", "1.0.0").publish();
765 Package::new("def", "1.0.0").alternative(true).publish();
766 Package::new("ghi", "1.0.0").publish();
772 cargo-features = ["alternative-registries"]
788 bar = { path = "bar", version = "0.1" }
789 def = { version = "1.0", registry = "alternative" }
794 .file("src/main.rs", "")
795 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
796 .file("bar/src/lib.rs", "")
799 p.cargo("package --no-verify")
800 .masquerade_as_nightly_cargo()
803 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
804 let rewritten_toml = format!(
805 r#"# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
807 # When uploading crates to the registry Cargo will automatically
808 # "normalize" Cargo.toml files for maximal compatibility
809 # with all versions of Cargo and also rewrite `path` dependencies
810 # to registry (e.g. crates.io) dependencies
812 # If you believe there's an error in this file please file an
813 # issue against the rust-lang/cargo repository. If you're
814 # editing this file be aware that the upstream Cargo.toml
815 # will likely look very different (and much more reasonable)
817 cargo-features = ["alternative-registries"]
837 registry-index = "{}"
842 registry::alt_registry_url()
845 validate_crate_contents(
848 &["Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
849 &[("Cargo.toml", &rewritten_toml)],
854 fn ignore_workspace_specifier() {
868 bar = { path = "bar", version = "0.1" }
871 .file("src/main.rs", "")
882 .file("bar/src/lib.rs", "")
885 p.cargo("package --no-verify")
886 .cwd(p.root().join("bar"))
889 let f = File::open(&p.root().join("target/package/bar-0.1.0.crate")).unwrap();
890 let rewritten_toml = r#"# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
892 # When uploading crates to the registry Cargo will automatically
893 # "normalize" Cargo.toml files for maximal compatibility
894 # with all versions of Cargo and also rewrite `path` dependencies
895 # to registry (e.g. crates.io) dependencies
897 # If you believe there's an error in this file please file an
898 # issue against the rust-lang/cargo repository. If you're
899 # editing this file be aware that the upstream Cargo.toml
900 # will likely look very different (and much more reasonable)
907 validate_crate_contents(
910 &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs"],
911 &[("Cargo.toml", &rewritten_toml)],
916 fn package_two_kinds_of_deps() {
917 Package::new("other", "1.0.0").publish();
918 Package::new("other1", "1.0.0").publish();
930 other1 = { version = "1.0" }
933 .file("src/main.rs", "")
936 p.cargo("package --no-verify").run();
945 cargo-features = ["edition"]
953 .file("src/lib.rs", r#" "#)
957 .masquerade_as_nightly_cargo()
958 .without_status() // passes on nightly, fails on stable, b/c --edition is nightly-only
959 // --edition is still in flux and we're not passing -Zunstable-options
960 // from Cargo so it will probably error. Only partially match the output
961 // until stuff stabilizes
962 .with_stderr_contains(
964 [COMPILING] foo v0.0.1 ([..])
965 [RUNNING] `rustc [..]--edition=2018 [..]
972 fn edition_with_metadata() {
974 // --edition is nightly-only
988 [package.metadata.docs.rs]
989 features = ["foobar"]
992 .file("src/lib.rs", "")
995 p.cargo("package").run();
999 fn test_edition_malformed() {
1011 .file("src/lib.rs", r#" "#)
1018 error: failed to parse manifest at `[..]`
1021 failed to parse the `edition` key
1024 supported edition values are `2015` or `2018`, but `chicken` is unknown
1032 fn package_lockfile() {
1037 cargo-features = ["publish-lockfile"]
1045 publish-lockfile = true
1048 .file("src/main.rs", "fn main() {}")
1052 .masquerade_as_nightly_cargo()
1055 [WARNING] manifest has no documentation[..]
1057 [PACKAGING] foo v0.0.1 ([CWD])
1058 [VERIFYING] foo v0.0.1 ([CWD])
1059 [COMPILING] foo v0.0.1 ([CWD][..])
1060 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1064 assert!(p.root().join("target/package/foo-0.0.1.crate").is_file());
1065 p.cargo("package -l")
1066 .masquerade_as_nightly_cargo()
1076 .masquerade_as_nightly_cargo()
1080 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
1081 validate_crate_contents(
1084 &["Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "src/main.rs"],
1090 fn package_lockfile_git_repo() {
1091 let p = project().build();
1093 // Create a Git repository containing a minimal Rust project.
1094 let _ = git::repo(&paths::root().join("foo"))
1098 cargo-features = ["publish-lockfile"]
1105 documentation = "foo"
1108 publish-lockfile = true
1111 .file("src/main.rs", "fn main() {}")
1113 p.cargo("package -l")
1114 .masquerade_as_nightly_cargo()
1117 .cargo_vcs_info.json
1127 fn no_lock_file_with_library() {
1132 cargo-features = ["publish-lockfile"]
1140 publish-lockfile = true
1143 .file("src/lib.rs", "")
1146 p.cargo("package").masquerade_as_nightly_cargo().run();
1148 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
1149 validate_crate_contents(
1152 &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs"],
1158 fn lock_file_and_workspace() {
1170 cargo-features = ["publish-lockfile"]
1178 publish-lockfile = true
1181 .file("foo/src/main.rs", "fn main() {}")
1185 .cwd(p.root().join("foo"))
1186 .masquerade_as_nightly_cargo()
1189 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
1190 validate_crate_contents(
1193 &["Cargo.toml", "Cargo.toml.orig", "src/main.rs", "Cargo.lock"],
1199 fn do_not_package_if_src_was_modified() {
1201 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
1209 let mut file = File::create("src/generated.txt").expect("failed to create file");
1210 file.write_all(b"Hello, world of generated files.").expect("failed to write");
1216 if cfg!(target_os = "macos") {
1217 // MacOS has 1s resolution filesystem.
1218 // If src/main.rs is created within 1s of src/generated.txt, then it
1219 // won't trigger the modification check.
1225 .with_stderr_contains(
1227 error: failed to verify package tarball
1230 Source directory was modified by build.rs during cargo publish. \
1231 Build scripts should not modify anything outside of OUT_DIR. Modified file: [..]src/generated.txt
1233 To proceed despite this, pass the `--no-verify` flag.",
1237 p.cargo("package --no-verify").run();
1241 fn package_with_select_features() {
1260 "#[cfg(not(feature = \"required\"))]
1261 compile_error!(\"This crate requires `required` feature!\");
1266 p.cargo("package --features required")
1267 .masquerade_as_nightly_cargo()
1273 fn package_with_all_features() {
1292 "#[cfg(not(feature = \"required\"))]
1293 compile_error!(\"This crate requires `required` feature!\");
1298 p.cargo("package --all-features")
1299 .masquerade_as_nightly_cargo()
1305 fn package_no_default_features() {
1318 default = ["required"]
1324 "#[cfg(not(feature = \"required\"))]
1325 compile_error!(\"This crate requires `required` feature!\");
1330 p.cargo("package --no-default-features")
1331 .masquerade_as_nightly_cargo()
1332 .with_stderr_contains("error: This crate requires `required` feature!")