]> git.proxmox.com Git - cargo.git/blob - tests/testsuite/package.rs
fe2e392e9c2b2fbcae86180f7d8f3397466e3063
[cargo.git] / tests / testsuite / package.rs
1 use std;
2 use std::fs::File;
3 use std::io::prelude::*;
4 use std::path::Path;
5
6 use crate::support::registry::Package;
7 use crate::support::{
8 basic_manifest, git, is_nightly, path2url, paths, project, publish::validate_crate_contents,
9 registry,
10 };
11 use crate::support::{cargo_process, sleep_ms};
12 use git2;
13
14 #[test]
15 fn simple() {
16 let p = project()
17 .file(
18 "Cargo.toml",
19 r#"
20 [project]
21 name = "foo"
22 version = "0.0.1"
23 authors = []
24 exclude = ["*.txt"]
25 license = "MIT"
26 description = "foo"
27 "#,
28 )
29 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
30 .file("src/bar.txt", "") // should be ignored when packaging
31 .build();
32
33 p.cargo("package")
34 .with_stderr(
35 "\
36 [WARNING] manifest has no documentation[..]
37 See [..]
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 [..]
42 ",
43 )
44 .run();
45 assert!(p.root().join("target/package/foo-0.0.1.crate").is_file());
46 p.cargo("package -l")
47 .with_stdout(
48 "\
49 Cargo.toml
50 src/main.rs
51 ",
52 )
53 .run();
54 p.cargo("package").with_stdout("").run();
55
56 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
57 validate_crate_contents(
58 f,
59 "foo-0.0.1.crate",
60 &["Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
61 &[],
62 );
63 }
64
65 #[test]
66 fn metadata_warning() {
67 let p = project().file("src/main.rs", "fn main() {}").build();
68 p.cargo("package")
69 .with_stderr(
70 "\
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 [..]
78 ",
79 )
80 .run();
81
82 let p = project()
83 .file(
84 "Cargo.toml",
85 r#"
86 [project]
87 name = "foo"
88 version = "0.0.1"
89 authors = []
90 license = "MIT"
91 "#,
92 )
93 .file("src/main.rs", "fn main() {}")
94 .build();
95 p.cargo("package")
96 .with_stderr(
97 "\
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 [..]
104 ",
105 )
106 .run();
107
108 let p = project()
109 .file(
110 "Cargo.toml",
111 r#"
112 [project]
113 name = "foo"
114 version = "0.0.1"
115 authors = []
116 license = "MIT"
117 description = "foo"
118 repository = "bar"
119 "#,
120 )
121 .file("src/main.rs", "fn main() {}")
122 .build();
123 p.cargo("package")
124 .with_stderr(
125 "\
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 [..]
130 ",
131 )
132 .run();
133 }
134
135 #[test]
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", "")
143 .build();
144 cargo_process("build").cwd(repo.root()).run();
145
146 println!("package main repo");
147 cargo_process("package -v --no-verify")
148 .cwd(repo.root())
149 .with_stderr(
150 "\
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 ([..])
154 [ARCHIVING] [..]
155 [ARCHIVING] [..]
156 [ARCHIVING] .cargo_vcs_info.json
157 ",
158 )
159 .run();
160
161 let f = File::open(&repo.root().join("target/package/foo-0.0.1.crate")).unwrap();
162 let vcs_contents = format!(
163 r#"{{
164 "git": {{
165 "sha1": "{}"
166 }}
167 }}
168 "#,
169 repo.revparse_head()
170 );
171 validate_crate_contents(
172 f,
173 "foo-0.0.1.crate",
174 &[
175 "Cargo.toml",
176 "Cargo.toml.orig",
177 "src/main.rs",
178 ".cargo_vcs_info.json",
179 ],
180 &[(".cargo_vcs_info.json", &vcs_contents)],
181 );
182
183 println!("package sub-repo");
184 cargo_process("package -v --no-verify")
185 .cwd(repo.root().join("a"))
186 .with_stderr(
187 "\
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
194 ",
195 )
196 .run();
197 }
198
199 #[test]
200 fn package_verification() {
201 let p = project().file("src/main.rs", "fn main() {}").build();
202 p.cargo("build").run();
203 p.cargo("package")
204 .with_stderr(
205 "\
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 [..]
212 ",
213 )
214 .run();
215 }
216
217 #[test]
218 fn vcs_file_collision() {
219 let p = project().build();
220 let _ = git::repo(&paths::root().join("foo"))
221 .file(
222 "Cargo.toml",
223 r#"
224 [project]
225 name = "foo"
226 description = "foo"
227 version = "0.0.1"
228 authors = []
229 license = "MIT"
230 documentation = "foo"
231 homepage = "foo"
232 repository = "foo"
233 exclude = ["*.no-existe"]
234 "#,
235 )
236 .file(
237 "src/main.rs",
238 r#"
239 fn main() {}
240 "#,
241 )
242 .file(".cargo_vcs_info.json", "foo")
243 .build();
244 p.cargo("package")
245 .arg("--no-verify")
246 .with_status(101)
247 .with_stderr(
248 "\
249 [ERROR] Invalid inclusion of reserved file name .cargo_vcs_info.json \
250 in package source
251 ",
252 )
253 .run();
254 }
255
256 #[test]
257 fn path_dependency_no_version() {
258 let p = project()
259 .file(
260 "Cargo.toml",
261 r#"
262 [project]
263 name = "foo"
264 version = "0.0.1"
265 authors = []
266 license = "MIT"
267 description = "foo"
268
269 [dependencies.bar]
270 path = "bar"
271 "#,
272 )
273 .file("src/main.rs", "fn main() {}")
274 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
275 .file("bar/src/lib.rs", "")
276 .build();
277
278 p.cargo("package")
279 .with_status(101)
280 .with_stderr(
281 "\
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.
286 ",
287 )
288 .run();
289 }
290
291 #[test]
292 fn exclude() {
293 let root = paths::root().join("exclude");
294 let repo = git::repo(&root)
295 .file(
296 "Cargo.toml",
297 r#"
298 [project]
299 name = "foo"
300 version = "0.0.1"
301 authors = []
302 exclude = [
303 "*.txt",
304 # file in 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)
310 # file in sub-dir
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)
316 # dir in root
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)
322 # dir in sub-dir
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)
328 ]
329 "#,
330 )
331 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
332 .file("bar.txt", "")
333 .file("src/bar.txt", "")
334 // file in root
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", "")
340 // file in sub-dir
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", "")
346 // dir in root
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", "")
352 // dir in sub-dir
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", "")
358 .build();
359
360 cargo_process("package --no-verify -v")
361 .cwd(repo.root())
362 .with_stdout("")
363 .with_stderr(
364 "\
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 [..]
368 See [..]
369 [WARNING] [..] file `dir_root_2/some_dir/file` WILL be excluded [..]
370 See [..]
371 [WARNING] [..] file `dir_root_3/some_dir/file` WILL be excluded [..]
372 See [..]
373 [WARNING] [..] file `some_dir/dir_deep_1/some_dir/file` WILL be excluded [..]
374 See [..]
375 [WARNING] [..] file `some_dir/dir_deep_3/some_dir/file` WILL be excluded [..]
376 See [..]
377 [WARNING] [..] file `some_dir/file_deep_1` WILL be excluded [..]
378 See [..]
379 [PACKAGING] foo v0.0.1 ([..])
380 [ARCHIVING] [..]
381 [ARCHIVING] [..]
382 [ARCHIVING] [..]
383 [ARCHIVING] [..]
384 [ARCHIVING] [..]
385 [ARCHIVING] [..]
386 [ARCHIVING] [..]
387 [ARCHIVING] [..]
388 [ARCHIVING] [..]
389 [ARCHIVING] [..]
390 [ARCHIVING] [..]
391 [ARCHIVING] [..]
392 [ARCHIVING] [..]
393 [ARCHIVING] [..]
394 [ARCHIVING] [..]
395 [ARCHIVING] [..]
396 [ARCHIVING] [..]
397 [ARCHIVING] [..]
398 [ARCHIVING] .cargo_vcs_info.json
399 ",
400 )
401 .run();
402
403 assert!(repo.root().join("target/package/foo-0.0.1.crate").is_file());
404
405 cargo_process("package -l")
406 .cwd(repo.root())
407 .with_stdout(
408 "\
409 .cargo_vcs_info.json
410 Cargo.toml
411 dir_root_1/some_dir/file
412 dir_root_2/some_dir/file
413 dir_root_3/some_dir/file
414 file_root_3
415 file_root_4
416 file_root_5
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
422 some_dir/file_deep_1
423 some_dir/file_deep_2
424 some_dir/file_deep_3
425 some_dir/file_deep_4
426 some_dir/file_deep_5
427 src/main.rs
428 ",
429 )
430 .run();
431 }
432
433 #[test]
434 fn include() {
435 let root = paths::root().join("include");
436 let repo = git::repo(&root)
437 .file(
438 "Cargo.toml",
439 r#"
440 [project]
441 name = "foo"
442 version = "0.0.1"
443 authors = []
444 exclude = ["*.txt"]
445 include = ["foo.txt", "**/*.rs", "Cargo.toml"]
446 "#,
447 )
448 .file("foo.txt", "")
449 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
450 .file("src/bar.txt", "") // should be ignored when packaging
451 .build();
452
453 cargo_process("package --no-verify -v")
454 .cwd(repo.root())
455 .with_stderr(
456 "\
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 ([..])
460 [ARCHIVING] [..]
461 [ARCHIVING] [..]
462 [ARCHIVING] [..]
463 [ARCHIVING] .cargo_vcs_info.json
464 ",
465 )
466 .run();
467 }
468
469 #[test]
470 fn package_lib_with_bin() {
471 let p = project()
472 .file("src/main.rs", "extern crate foo; fn main() {}")
473 .file("src/lib.rs", "")
474 .build();
475
476 p.cargo("package -v").run();
477 }
478
479 #[test]
480 fn package_git_submodule() {
481 let project = git::new("foo", |project| {
482 project
483 .file(
484 "Cargo.toml",
485 r#"
486 [project]
487 name = "foo"
488 version = "0.0.1"
489 authors = ["foo@example.com"]
490 license = "MIT"
491 description = "foo"
492 repository = "foo"
493 "#,
494 )
495 .file("src/lib.rs", "pub fn foo() {}")
496 })
497 .unwrap();
498 let library = git::new("bar", |library| {
499 library.no_manifest().file("Makefile", "all:")
500 })
501 .unwrap();
502
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);
507
508 let repository = git2::Repository::open(&project.root().join("bar")).unwrap();
509 repository
510 .reset(
511 &repository.revparse_single("HEAD").unwrap(),
512 git2::ResetType::Hard,
513 None,
514 )
515 .unwrap();
516
517 project
518 .cargo("package --no-verify -v")
519 .with_stderr_contains("[ARCHIVING] bar/Makefile")
520 .run();
521 }
522
523 #[test]
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() {}")
529 .build();
530 File::create(p.root().join("src/main.rs"))
531 .unwrap()
532 .write_all(br#"fn main() { println!("A change!"); }"#)
533 .unwrap();
534 cargo_process("build").cwd(p.root()).run();
535 cargo_process("package --list --allow-dirty")
536 .cwd(p.root())
537 .with_stdout(
538 "\
539 Cargo.toml
540 src/main.rs
541 ",
542 )
543 .run();
544 }
545
546 #[test]
547 fn ignore_nested() {
548 let cargo_toml = r#"
549 [project]
550 name = "foo"
551 version = "0.0.1"
552 authors = []
553 license = "MIT"
554 description = "foo"
555 "#;
556 let main_rs = r#"
557 fn main() { println!("hello"); }
558 "#;
559 let p = project()
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
563 // ignore it.
564 .file("a_dir/foo/Cargo.toml", cargo_toml)
565 .file("a_dir/foo/src/main.rs", main_rs)
566 .build();
567
568 p.cargo("package")
569 .with_stderr(
570 "\
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 [..]
577 ",
578 )
579 .run();
580 assert!(p.root().join("target/package/foo-0.0.1.crate").is_file());
581 p.cargo("package -l")
582 .with_stdout(
583 "\
584 Cargo.toml
585 src[..]main.rs
586 ",
587 )
588 .run();
589 p.cargo("package").with_stdout("").run();
590
591 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
592 validate_crate_contents(
593 f,
594 "foo-0.0.1.crate",
595 &["Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
596 &[],
597 );
598 }
599
600 #[cfg(unix)] // windows doesn't allow these characters in filenames
601 #[test]
602 fn package_weird_characters() {
603 let p = project()
604 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
605 .file("src/:foo", "")
606 .build();
607
608 p.cargo("package")
609 .with_status(101)
610 .with_stderr(
611 "\
612 warning: [..]
613 See [..]
614 [PACKAGING] foo [..]
615 [ERROR] failed to prepare local package for uploading
616
617 Caused by:
618 cannot package a filename with a special character `:`: src/:foo
619 ",
620 )
621 .run();
622 }
623
624 #[test]
625 fn repackage_on_source_change() {
626 let p = project()
627 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
628 .build();
629
630 p.cargo("package").run();
631
632 // Add another source file
633 let mut file = File::create(p.root().join("src").join("foo.rs")).unwrap_or_else(|e| {
634 panic!(
635 "could not create file {}: {}",
636 p.root().join("src/foo.rs").display(),
637 e
638 )
639 });
640
641 file.write_all(br#"fn main() { println!("foo"); }"#)
642 .unwrap();
643 std::mem::drop(file);
644
645 // Check that cargo rebuilds the tarball
646 p.cargo("package")
647 .with_stderr(
648 "\
649 [WARNING] [..]
650 See [..]
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 [..]
655 ",
656 )
657 .run();
658
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(
662 f,
663 "foo-0.0.1.crate",
664 &["Cargo.toml", "Cargo.toml.orig", "src/main.rs", "src/foo.rs"],
665 &[],
666 );
667 }
668
669 #[test]
670 #[cfg(unix)]
671 fn broken_symlink() {
672 use std::os::unix::fs;
673
674 let p = project()
675 .file(
676 "Cargo.toml",
677 r#"
678 [project]
679 name = "foo"
680 version = "0.0.1"
681 authors = []
682 license = "MIT"
683 description = 'foo'
684 documentation = 'foo'
685 homepage = 'foo'
686 repository = 'foo'
687 "#,
688 )
689 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
690 .build();
691 t!(fs::symlink("nowhere", &p.root().join("src/foo.rs")));
692
693 p.cargo("package -v")
694 .with_status(101)
695 .with_stderr_contains(
696 "\
697 error: failed to prepare local package for uploading
698
699 Caused by:
700 failed to open for archiving: `[..]foo.rs`
701
702 Caused by:
703 [..]
704 ",
705 )
706 .run();
707 }
708
709 #[test]
710 fn do_not_package_if_repository_is_dirty() {
711 let p = project().build();
712
713 // Create a Git repository containing a minimal Rust project.
714 let _ = git::repo(&paths::root().join("foo"))
715 .file(
716 "Cargo.toml",
717 r#"
718 [project]
719 name = "foo"
720 version = "0.0.1"
721 license = "MIT"
722 description = "foo"
723 documentation = "foo"
724 homepage = "foo"
725 repository = "foo"
726 "#,
727 )
728 .file("src/main.rs", "fn main() {}")
729 .build();
730
731 // Modify Cargo.toml without committing the change.
732 p.change_file(
733 "Cargo.toml",
734 r#"
735 [project]
736 name = "foo"
737 version = "0.0.1"
738 license = "MIT"
739 description = "foo"
740 documentation = "foo"
741 homepage = "foo"
742 repository = "foo"
743 # change
744 "#,
745 );
746
747 p.cargo("package")
748 .with_status(101)
749 .with_stderr(
750 "\
751 error: 1 files in the working directory contain changes that were not yet \
752 committed into git:
753
754 Cargo.toml
755
756 to proceed despite this, pass the `--allow-dirty` flag
757 ",
758 )
759 .run();
760 }
761
762 #[test]
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();
767
768 let p = project()
769 .file(
770 "Cargo.toml",
771 r#"
772 cargo-features = ["alternative-registries"]
773
774 [project]
775 name = "foo"
776 version = "0.0.1"
777 authors = []
778 exclude = ["*.txt"]
779 license = "MIT"
780 description = "foo"
781
782 [project.metadata]
783 foo = 'bar'
784
785 [workspace]
786
787 [dependencies]
788 bar = { path = "bar", version = "0.1" }
789 def = { version = "1.0", registry = "alternative" }
790 ghi = "1.0"
791 abc = "1.0"
792 "#,
793 )
794 .file("src/main.rs", "")
795 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
796 .file("bar/src/lib.rs", "")
797 .build();
798
799 p.cargo("package --no-verify")
800 .masquerade_as_nightly_cargo()
801 .run();
802
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
806 #
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
811 #
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)
816
817 cargo-features = ["alternative-registries"]
818
819 [package]
820 name = "foo"
821 version = "0.0.1"
822 authors = []
823 exclude = ["*.txt"]
824 description = "foo"
825 license = "MIT"
826
827 [package.metadata]
828 foo = "bar"
829 [dependencies.abc]
830 version = "1.0"
831
832 [dependencies.bar]
833 version = "0.1"
834
835 [dependencies.def]
836 version = "1.0"
837 registry-index = "{}"
838
839 [dependencies.ghi]
840 version = "1.0"
841 "#,
842 registry::alt_registry_url()
843 );
844
845 validate_crate_contents(
846 f,
847 "foo-0.0.1.crate",
848 &["Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
849 &[("Cargo.toml", &rewritten_toml)],
850 );
851 }
852
853 #[test]
854 fn ignore_workspace_specifier() {
855 let p = project()
856 .file(
857 "Cargo.toml",
858 r#"
859 [project]
860 name = "foo"
861 version = "0.0.1"
862
863 authors = []
864
865 [workspace]
866
867 [dependencies]
868 bar = { path = "bar", version = "0.1" }
869 "#,
870 )
871 .file("src/main.rs", "")
872 .file(
873 "bar/Cargo.toml",
874 r#"
875 [package]
876 name = "bar"
877 version = "0.1.0"
878 authors = []
879 workspace = ".."
880 "#,
881 )
882 .file("bar/src/lib.rs", "")
883 .build();
884
885 p.cargo("package --no-verify")
886 .cwd(p.root().join("bar"))
887 .run();
888
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
891 #
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
896 #
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)
901
902 [package]
903 name = "bar"
904 version = "0.1.0"
905 authors = []
906 "#;
907 validate_crate_contents(
908 f,
909 "bar-0.1.0.crate",
910 &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs"],
911 &[("Cargo.toml", &rewritten_toml)],
912 );
913 }
914
915 #[test]
916 fn package_two_kinds_of_deps() {
917 Package::new("other", "1.0.0").publish();
918 Package::new("other1", "1.0.0").publish();
919 let p = project()
920 .file(
921 "Cargo.toml",
922 r#"
923 [project]
924 name = "foo"
925 version = "0.0.1"
926 authors = []
927
928 [dependencies]
929 other = "1.0"
930 other1 = { version = "1.0" }
931 "#,
932 )
933 .file("src/main.rs", "")
934 .build();
935
936 p.cargo("package --no-verify").run();
937 }
938
939 #[test]
940 fn test_edition() {
941 let p = project()
942 .file(
943 "Cargo.toml",
944 r#"
945 cargo-features = ["edition"]
946 [package]
947 name = "foo"
948 version = "0.0.1"
949 authors = []
950 edition = "2018"
951 "#,
952 )
953 .file("src/lib.rs", r#" "#)
954 .build();
955
956 p.cargo("build -v")
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(
963 "\
964 [COMPILING] foo v0.0.1 ([..])
965 [RUNNING] `rustc [..]--edition=2018 [..]
966 ",
967 )
968 .run();
969 }
970
971 #[test]
972 fn edition_with_metadata() {
973 if !is_nightly() {
974 // --edition is nightly-only
975 return;
976 }
977
978 let p = project()
979 .file(
980 "Cargo.toml",
981 r#"
982 [package]
983 name = "foo"
984 version = "0.0.1"
985 authors = []
986 edition = "2018"
987
988 [package.metadata.docs.rs]
989 features = ["foobar"]
990 "#,
991 )
992 .file("src/lib.rs", "")
993 .build();
994
995 p.cargo("package").run();
996 }
997
998 #[test]
999 fn test_edition_malformed() {
1000 let p = project()
1001 .file(
1002 "Cargo.toml",
1003 r#"
1004 [package]
1005 name = "foo"
1006 version = "0.0.1"
1007 authors = []
1008 edition = "chicken"
1009 "#,
1010 )
1011 .file("src/lib.rs", r#" "#)
1012 .build();
1013
1014 p.cargo("build -v")
1015 .with_status(101)
1016 .with_stderr(
1017 "\
1018 error: failed to parse manifest at `[..]`
1019
1020 Caused by:
1021 failed to parse the `edition` key
1022
1023 Caused by:
1024 supported edition values are `2015` or `2018`, but `chicken` is unknown
1025 "
1026 .to_string(),
1027 )
1028 .run();
1029 }
1030
1031 #[test]
1032 fn package_lockfile() {
1033 let p = project()
1034 .file(
1035 "Cargo.toml",
1036 r#"
1037 cargo-features = ["publish-lockfile"]
1038
1039 [project]
1040 name = "foo"
1041 version = "0.0.1"
1042 authors = []
1043 license = "MIT"
1044 description = "foo"
1045 publish-lockfile = true
1046 "#,
1047 )
1048 .file("src/main.rs", "fn main() {}")
1049 .build();
1050
1051 p.cargo("package")
1052 .masquerade_as_nightly_cargo()
1053 .with_stderr(
1054 "\
1055 [WARNING] manifest has no documentation[..]
1056 See [..]
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 [..]
1061 ",
1062 )
1063 .run();
1064 assert!(p.root().join("target/package/foo-0.0.1.crate").is_file());
1065 p.cargo("package -l")
1066 .masquerade_as_nightly_cargo()
1067 .with_stdout(
1068 "\
1069 Cargo.lock
1070 Cargo.toml
1071 src/main.rs
1072 ",
1073 )
1074 .run();
1075 p.cargo("package")
1076 .masquerade_as_nightly_cargo()
1077 .with_stdout("")
1078 .run();
1079
1080 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
1081 validate_crate_contents(
1082 f,
1083 "foo-0.0.1.crate",
1084 &["Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "src/main.rs"],
1085 &[],
1086 );
1087 }
1088
1089 #[test]
1090 fn package_lockfile_git_repo() {
1091 let p = project().build();
1092
1093 // Create a Git repository containing a minimal Rust project.
1094 let _ = git::repo(&paths::root().join("foo"))
1095 .file(
1096 "Cargo.toml",
1097 r#"
1098 cargo-features = ["publish-lockfile"]
1099
1100 [project]
1101 name = "foo"
1102 version = "0.0.1"
1103 license = "MIT"
1104 description = "foo"
1105 documentation = "foo"
1106 homepage = "foo"
1107 repository = "foo"
1108 publish-lockfile = true
1109 "#,
1110 )
1111 .file("src/main.rs", "fn main() {}")
1112 .build();
1113 p.cargo("package -l")
1114 .masquerade_as_nightly_cargo()
1115 .with_stdout(
1116 "\
1117 .cargo_vcs_info.json
1118 Cargo.lock
1119 Cargo.toml
1120 src/main.rs
1121 ",
1122 )
1123 .run();
1124 }
1125
1126 #[test]
1127 fn no_lock_file_with_library() {
1128 let p = project()
1129 .file(
1130 "Cargo.toml",
1131 r#"
1132 cargo-features = ["publish-lockfile"]
1133
1134 [project]
1135 name = "foo"
1136 version = "0.0.1"
1137 authors = []
1138 license = "MIT"
1139 description = "foo"
1140 publish-lockfile = true
1141 "#,
1142 )
1143 .file("src/lib.rs", "")
1144 .build();
1145
1146 p.cargo("package").masquerade_as_nightly_cargo().run();
1147
1148 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
1149 validate_crate_contents(
1150 f,
1151 "foo-0.0.1.crate",
1152 &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs"],
1153 &[],
1154 );
1155 }
1156
1157 #[test]
1158 fn lock_file_and_workspace() {
1159 let p = project()
1160 .file(
1161 "Cargo.toml",
1162 r#"
1163 [workspace]
1164 members = ["foo"]
1165 "#,
1166 )
1167 .file(
1168 "foo/Cargo.toml",
1169 r#"
1170 cargo-features = ["publish-lockfile"]
1171
1172 [package]
1173 name = "foo"
1174 version = "0.0.1"
1175 authors = []
1176 license = "MIT"
1177 description = "foo"
1178 publish-lockfile = true
1179 "#,
1180 )
1181 .file("foo/src/main.rs", "fn main() {}")
1182 .build();
1183
1184 p.cargo("package")
1185 .cwd(p.root().join("foo"))
1186 .masquerade_as_nightly_cargo()
1187 .run();
1188
1189 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
1190 validate_crate_contents(
1191 f,
1192 "foo-0.0.1.crate",
1193 &["Cargo.toml", "Cargo.toml.orig", "src/main.rs", "Cargo.lock"],
1194 &[],
1195 );
1196 }
1197
1198 #[test]
1199 fn do_not_package_if_src_was_modified() {
1200 let p = project()
1201 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
1202 .file(
1203 "build.rs",
1204 r#"
1205 use std::fs::File;
1206 use std::io::Write;
1207
1208 fn main() {
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");
1211 }
1212 "#,
1213 )
1214 .build();
1215
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.
1220 sleep_ms(1000);
1221 }
1222
1223 p.cargo("package")
1224 .with_status(101)
1225 .with_stderr_contains(
1226 "\
1227 error: failed to verify package tarball
1228
1229 Caused by:
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
1232
1233 To proceed despite this, pass the `--no-verify` flag.",
1234 )
1235 .run();
1236
1237 p.cargo("package --no-verify").run();
1238 }
1239
1240 #[test]
1241 fn package_with_select_features() {
1242 let p = project()
1243 .file(
1244 "Cargo.toml",
1245 r#"
1246 [project]
1247 name = "foo"
1248 version = "0.0.1"
1249 authors = []
1250 license = "MIT"
1251 description = "foo"
1252
1253 [features]
1254 required = []
1255 optional = []
1256 "#,
1257 )
1258 .file(
1259 "src/main.rs",
1260 "#[cfg(not(feature = \"required\"))]
1261 compile_error!(\"This crate requires `required` feature!\");
1262 fn main() {}",
1263 )
1264 .build();
1265
1266 p.cargo("package --features required")
1267 .masquerade_as_nightly_cargo()
1268 .with_status(0)
1269 .run();
1270 }
1271
1272 #[test]
1273 fn package_with_all_features() {
1274 let p = project()
1275 .file(
1276 "Cargo.toml",
1277 r#"
1278 [project]
1279 name = "foo"
1280 version = "0.0.1"
1281 authors = []
1282 license = "MIT"
1283 description = "foo"
1284
1285 [features]
1286 required = []
1287 optional = []
1288 "#,
1289 )
1290 .file(
1291 "src/main.rs",
1292 "#[cfg(not(feature = \"required\"))]
1293 compile_error!(\"This crate requires `required` feature!\");
1294 fn main() {}",
1295 )
1296 .build();
1297
1298 p.cargo("package --all-features")
1299 .masquerade_as_nightly_cargo()
1300 .with_status(0)
1301 .run();
1302 }
1303
1304 #[test]
1305 fn package_no_default_features() {
1306 let p = project()
1307 .file(
1308 "Cargo.toml",
1309 r#"
1310 [project]
1311 name = "foo"
1312 version = "0.0.1"
1313 authors = []
1314 license = "MIT"
1315 description = "foo"
1316
1317 [features]
1318 default = ["required"]
1319 required = []
1320 "#,
1321 )
1322 .file(
1323 "src/main.rs",
1324 "#[cfg(not(feature = \"required\"))]
1325 compile_error!(\"This crate requires `required` feature!\");
1326 fn main() {}",
1327 )
1328 .build();
1329
1330 p.cargo("package --no-default-features")
1331 .masquerade_as_nightly_cargo()
1332 .with_stderr_contains("error: This crate requires `required` feature!")
1333 .with_status(101)
1334 .run();
1335 }