]> git.proxmox.com Git - cargo.git/blame - tests/testsuite/package.rs
Improve testing framework for http registries
[cargo.git] / tests / testsuite / package.rs
CommitLineData
83571aee
EH
1//! Tests for the `cargo package` command.
2
9115b2c3 3use cargo_test_support::paths::CargoPathExt;
156c6512
EH
4use cargo_test_support::publish::validate_crate_contents;
5use cargo_test_support::registry::{self, Package};
9115b2c3 6use cargo_test_support::{
156c6512 7 basic_manifest, cargo_process, git, path2url, paths, project, symlink_supported, t,
3d84d0ad 8};
e46ca84b 9use flate2::read::GzDecoder;
1232ad3c 10use std::fs::{self, read_to_string, File};
4ae79d2f 11use std::path::Path;
e46ca84b 12use tar::Archive;
69c16fc6 13
0e0d9688 14#[cargo_test]
6950bbb0 15fn simple() {
7fe2fbc8 16 let p = project()
fecb7246
AC
17 .file(
18 "Cargo.toml",
19 r#"
6f8c7d5a
EH
20 [project]
21 name = "foo"
22 version = "0.0.1"
23 authors = []
24 exclude = ["*.txt"]
25 license = "MIT"
26 description = "foo"
27 "#,
fecb7246 28 )
ca7d9ee2 29 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
d43ee1dd
NK
30 .file("src/bar.txt", "") // should be ignored when packaging
31 .build();
69c16fc6 32
85984a87 33 p.cargo("package")
2cd9cce6 34 .with_stderr(
1e682848 35 "\
eeebadff 36[WARNING] manifest has no documentation[..]
32275465 37See [..]
89f43938
ZL
38[PACKAGING] foo v0.0.1 ([CWD])
39[VERIFYING] foo v0.0.1 ([CWD])
40[COMPILING] foo v0.0.1 ([CWD][..])
34628b65 41[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
69c16fc6 42",
fecb7246
AC
43 )
44 .run();
570fe892 45 assert!(p.root().join("target/package/foo-0.0.1.crate").is_file());
85984a87
DW
46 p.cargo("package -l")
47 .with_stdout(
1e682848 48 "\
34307c61 49Cargo.lock
229e1e43 50Cargo.toml
90887707 51Cargo.toml.orig
05400b80 52src/main.rs
1e682848 53",
fecb7246
AC
54 )
55 .run();
85984a87 56 p.cargo("package").with_stdout("").run();
97f073ef 57
9ed3a6ea 58 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
3d84d0ad
EH
59 validate_crate_contents(
60 f,
61 "foo-0.0.1.crate",
34307c61 62 &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
3d84d0ad
EH
63 &[],
64 );
6950bbb0 65}
5db1316a 66
0e0d9688 67#[cargo_test]
6950bbb0 68fn metadata_warning() {
85984a87
DW
69 let p = project().file("src/main.rs", "fn main() {}").build();
70 p.cargo("package")
2cd9cce6 71 .with_stderr(
1e682848 72 "\
eeebadff 73warning: manifest has no description, license, license-file, documentation, \
32275465 74homepage or repository.
0c3851c0 75See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
89f43938
ZL
76[PACKAGING] foo v0.0.1 ([CWD])
77[VERIFYING] foo v0.0.1 ([CWD])
78[COMPILING] foo v0.0.1 ([CWD][..])
34628b65 79[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
5db1316a 80",
fecb7246
AC
81 )
82 .run();
5db1316a 83
f8c9928c 84 let p = project()
1e682848
AC
85 .file(
86 "Cargo.toml",
87 r#"
6f8c7d5a
EH
88 [project]
89 name = "foo"
90 version = "0.0.1"
91 authors = []
92 license = "MIT"
93 "#,
fecb7246
AC
94 )
95 .file("src/main.rs", "fn main() {}")
d43ee1dd 96 .build();
85984a87 97 p.cargo("package")
2cd9cce6 98 .with_stderr(
1e682848 99 "\
32275465 100warning: manifest has no description, documentation, homepage or repository.
0c3851c0 101See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
89f43938
ZL
102[PACKAGING] foo v0.0.1 ([CWD])
103[VERIFYING] foo v0.0.1 ([CWD])
104[COMPILING] foo v0.0.1 ([CWD][..])
34628b65 105[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
5db1316a 106",
fecb7246
AC
107 )
108 .run();
5db1316a 109
f8c9928c 110 let p = project()
1e682848
AC
111 .file(
112 "Cargo.toml",
113 r#"
6f8c7d5a
EH
114 [project]
115 name = "foo"
116 version = "0.0.1"
117 authors = []
118 license = "MIT"
119 description = "foo"
120 repository = "bar"
121 "#,
fecb7246
AC
122 )
123 .file("src/main.rs", "fn main() {}")
d43ee1dd 124 .build();
85984a87 125 p.cargo("package")
2cd9cce6 126 .with_stderr(
1e682848 127 "\
89f43938
ZL
128[PACKAGING] foo v0.0.1 ([CWD])
129[VERIFYING] foo v0.0.1 ([CWD])
130[COMPILING] foo v0.0.1 ([CWD][..])
34628b65 131[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
5db1316a 132",
fecb7246
AC
133 )
134 .run();
6950bbb0 135}
5db1316a 136
0e0d9688 137#[cargo_test]
6950bbb0 138fn package_verbose() {
c84bc16b 139 let root = paths::root().join("all");
6b9961a3 140 let repo = git::repo(&root)
ab19c483 141 .file("Cargo.toml", &basic_manifest("foo", "0.0.1"))
ca7d9ee2 142 .file("src/main.rs", "fn main() {}")
b8b127a8
NK
143 .file("a/a/Cargo.toml", &basic_manifest("a", "0.0.1"))
144 .file("a/a/src/lib.rs", "")
d43ee1dd 145 .build();
85984a87 146 cargo_process("build").cwd(repo.root()).run();
09847df8
AC
147
148 println!("package main repo");
85984a87
DW
149 cargo_process("package -v --no-verify")
150 .cwd(repo.root())
151 .with_stderr(
1e682848 152 "\
eeebadff 153[WARNING] manifest has no description[..]
0c3851c0 154See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
fee4308b 155[PACKAGING] foo v0.0.1 ([..])
6b9961a3 156[ARCHIVING] .cargo_vcs_info.json
34307c61 157[ARCHIVING] Cargo.lock
90887707
EH
158[ARCHIVING] Cargo.toml
159[ARCHIVING] Cargo.toml.orig
160[ARCHIVING] src/main.rs
1e682848 161",
fecb7246
AC
162 )
163 .run();
09847df8 164
6b9961a3 165 let f = File::open(&repo.root().join("target/package/foo-0.0.1.crate")).unwrap();
3d84d0ad
EH
166 let vcs_contents = format!(
167 r#"{{
6b9961a3
DK
168 "git": {{
169 "sha1": "{}"
b8b127a8
NK
170 }},
171 "path_in_vcs": ""
6b9961a3
DK
172}}
173"#,
3d84d0ad
EH
174 repo.revparse_head()
175 );
176 validate_crate_contents(
177 f,
178 "foo-0.0.1.crate",
179 &[
34307c61 180 "Cargo.lock",
3d84d0ad
EH
181 "Cargo.toml",
182 "Cargo.toml.orig",
183 "src/main.rs",
184 ".cargo_vcs_info.json",
185 ],
186 &[(".cargo_vcs_info.json", &vcs_contents)],
6b9961a3
DK
187 );
188
09847df8 189 println!("package sub-repo");
85984a87 190 cargo_process("package -v --no-verify")
b8b127a8 191 .cwd(repo.root().join("a/a"))
85984a87 192 .with_stderr(
1e682848 193 "\
eeebadff 194[WARNING] manifest has no description[..]
0c3851c0 195See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
fee4308b 196[PACKAGING] a v0.0.1 ([..])
90887707 197[ARCHIVING] .cargo_vcs_info.json
6b9961a3 198[ARCHIVING] Cargo.toml
90887707 199[ARCHIVING] Cargo.toml.orig
6b9961a3 200[ARCHIVING] src/lib.rs
1e682848 201",
fecb7246
AC
202 )
203 .run();
b8b127a8
NK
204
205 let f = File::open(&repo.root().join("a/a/target/package/a-0.0.1.crate")).unwrap();
206 let vcs_contents = format!(
207 r#"{{
208 "git": {{
209 "sha1": "{}"
210 }},
211 "path_in_vcs": "a/a"
212}}
213"#,
214 repo.revparse_head()
215 );
216 validate_crate_contents(
217 f,
218 "a-0.0.1.crate",
219 &[
220 "Cargo.toml",
221 "Cargo.toml.orig",
222 "src/lib.rs",
223 ".cargo_vcs_info.json",
224 ],
225 &[(".cargo_vcs_info.json", &vcs_contents)],
226 );
6950bbb0 227}
6e81812e 228
0e0d9688 229#[cargo_test]
6950bbb0 230fn package_verification() {
85984a87
DW
231 let p = project().file("src/main.rs", "fn main() {}").build();
232 p.cargo("build").run();
233 p.cargo("package")
2cd9cce6 234 .with_stderr(
1e682848 235 "\
eeebadff 236[WARNING] manifest has no description[..]
0c3851c0 237See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
89f43938
ZL
238[PACKAGING] foo v0.0.1 ([CWD])
239[VERIFYING] foo v0.0.1 ([CWD])
240[COMPILING] foo v0.0.1 ([CWD][..])
34628b65 241[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
6e81812e 242",
fecb7246
AC
243 )
244 .run();
6950bbb0 245}
5935ec1d 246
0e0d9688 247#[cargo_test]
ab787720
DK
248fn vcs_file_collision() {
249 let p = project().build();
250 let _ = git::repo(&paths::root().join("foo"))
251 .file(
252 "Cargo.toml",
253 r#"
6f8c7d5a
EH
254 [project]
255 name = "foo"
256 description = "foo"
257 version = "0.0.1"
258 authors = []
259 license = "MIT"
260 documentation = "foo"
261 homepage = "foo"
262 repository = "foo"
263 exclude = ["*.no-existe"]
264 "#,
fecb7246
AC
265 )
266 .file(
ab787720
DK
267 "src/main.rs",
268 r#"
6f8c7d5a
EH
269 fn main() {}
270 "#,
fecb7246
AC
271 )
272 .file(".cargo_vcs_info.json", "foo")
ab787720 273 .build();
85984a87
DW
274 p.cargo("package")
275 .arg("--no-verify")
276 .with_status(101)
2cd9cce6 277 .with_stderr(
ab787720 278 "\
90887707 279[ERROR] invalid inclusion of reserved file name .cargo_vcs_info.json \
ab787720
DK
280in package source
281",
fecb7246
AC
282 )
283 .run();
ab787720
DK
284}
285
42424065
JB
286#[cargo_test]
287fn orig_file_collision() {
288 let p = project().build();
289 let _ = git::repo(&paths::root().join("foo"))
290 .file(
291 "Cargo.toml",
292 r#"
293 [project]
294 name = "foo"
295 description = "foo"
296 version = "0.0.1"
297 authors = []
298 license = "MIT"
299 documentation = "foo"
300 homepage = "foo"
301 repository = "foo"
302 exclude = ["*.no-existe"]
303 "#,
304 )
305 .file(
306 "src/main.rs",
307 r#"
308 fn main() {}
309 "#,
310 )
311 .file("Cargo.toml.orig", "oops")
312 .build();
313 p.cargo("package")
314 .arg("--no-verify")
315 .with_status(101)
316 .with_stderr(
317 "\
318[ERROR] invalid inclusion of reserved file name Cargo.toml.orig \
319in package source
320",
321 )
322 .run();
323}
324
0e0d9688 325#[cargo_test]
4f01c02a 326fn path_dependency_no_version() {
7fe2fbc8 327 let p = project()
1e682848
AC
328 .file(
329 "Cargo.toml",
330 r#"
6f8c7d5a
EH
331 [project]
332 name = "foo"
333 version = "0.0.1"
334 authors = []
335 license = "MIT"
336 description = "foo"
4f01c02a 337
6f8c7d5a
EH
338 [dependencies.bar]
339 path = "bar"
340 "#,
fecb7246
AC
341 )
342 .file("src/main.rs", "fn main() {}")
ab19c483 343 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
d43ee1dd
NK
344 .file("bar/src/lib.rs", "")
345 .build();
4f01c02a 346
85984a87
DW
347 p.cargo("package")
348 .with_status(101)
349 .with_stderr(
1e682848 350 "\
32275465 351[WARNING] manifest has no documentation, homepage or repository.
0c3851c0 352See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
4e1910d9
B
353[ERROR] all dependencies must have a version specified when packaging.
354dependency `bar` does not specify a version\n\
355Note: The packaged dependency will use the version from crates.io,
356the `path` specification will be removed from the dependency declaration.
357",
358 )
359 .run();
360}
361
362#[cargo_test]
363fn git_dependency_no_version() {
364 registry::init();
365
366 let p = project()
367 .file(
368 "Cargo.toml",
369 r#"
370 [project]
371 name = "foo"
372 version = "0.0.1"
373 authors = []
374 license = "MIT"
375 description = "foo"
376
377 [dependencies.foo]
378 git = "git://path/to/nowhere"
379 "#,
380 )
381 .file("src/main.rs", "fn main() {}")
382 .build();
383
384 p.cargo("package")
385 .with_status(101)
386 .with_stderr(
387 "\
388[WARNING] manifest has no documentation, homepage or repository.
389See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
390[ERROR] all dependencies must have a version specified when packaging.
391dependency `foo` does not specify a version
392Note: The packaged dependency will use the version from crates.io,
393the `git` specification will be removed from the dependency declaration.
1e682848 394",
fecb7246
AC
395 )
396 .run();
4f01c02a
RG
397}
398
0e0d9688 399#[cargo_test]
6950bbb0 400fn exclude() {
dd998a09
XL
401 let root = paths::root().join("exclude");
402 let repo = git::repo(&root)
fecb7246
AC
403 .file(
404 "Cargo.toml",
405 r#"
6f8c7d5a
EH
406 [project]
407 name = "foo"
408 version = "0.0.1"
409 authors = []
410 exclude = [
411 "*.txt",
412 # file in root
413 "file_root_1", # NO_CHANGE (ignored)
414 "/file_root_2", # CHANGING (packaged -> ignored)
415 "file_root_3/", # NO_CHANGE (packaged)
416 "file_root_4/*", # NO_CHANGE (packaged)
417 "file_root_5/**", # NO_CHANGE (packaged)
418 # file in sub-dir
419 "file_deep_1", # CHANGING (packaged -> ignored)
420 "/file_deep_2", # NO_CHANGE (packaged)
421 "file_deep_3/", # NO_CHANGE (packaged)
422 "file_deep_4/*", # NO_CHANGE (packaged)
423 "file_deep_5/**", # NO_CHANGE (packaged)
424 # dir in root
425 "dir_root_1", # CHANGING (packaged -> ignored)
426 "/dir_root_2", # CHANGING (packaged -> ignored)
427 "dir_root_3/", # CHANGING (packaged -> ignored)
428 "dir_root_4/*", # NO_CHANGE (ignored)
429 "dir_root_5/**", # NO_CHANGE (ignored)
430 # dir in sub-dir
431 "dir_deep_1", # CHANGING (packaged -> ignored)
432 "/dir_deep_2", # NO_CHANGE
433 "dir_deep_3/", # CHANGING (packaged -> ignored)
434 "dir_deep_4/*", # CHANGING (packaged -> ignored)
435 "dir_deep_5/**", # CHANGING (packaged -> ignored)
436 ]
437 "#,
fecb7246 438 )
ca7d9ee2 439 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
5935ec1d 440 .file("bar.txt", "")
c072ba42 441 .file("src/bar.txt", "")
f7c91ba6 442 // File in root.
c072ba42
BE
443 .file("file_root_1", "")
444 .file("file_root_2", "")
445 .file("file_root_3", "")
446 .file("file_root_4", "")
447 .file("file_root_5", "")
f7c91ba6 448 // File in sub-dir.
c072ba42
BE
449 .file("some_dir/file_deep_1", "")
450 .file("some_dir/file_deep_2", "")
451 .file("some_dir/file_deep_3", "")
452 .file("some_dir/file_deep_4", "")
453 .file("some_dir/file_deep_5", "")
f7c91ba6 454 // Dir in root.
c072ba42
BE
455 .file("dir_root_1/some_dir/file", "")
456 .file("dir_root_2/some_dir/file", "")
457 .file("dir_root_3/some_dir/file", "")
458 .file("dir_root_4/some_dir/file", "")
459 .file("dir_root_5/some_dir/file", "")
f7c91ba6 460 // Dir in sub-dir.
c072ba42
BE
461 .file("some_dir/dir_deep_1/some_dir/file", "")
462 .file("some_dir/dir_deep_2/some_dir/file", "")
463 .file("some_dir/dir_deep_3/some_dir/file", "")
464 .file("some_dir/dir_deep_4/some_dir/file", "")
465 .file("some_dir/dir_deep_5/some_dir/file", "")
d43ee1dd 466 .build();
5935ec1d 467
dd998a09
XL
468 cargo_process("package --no-verify -v")
469 .cwd(repo.root())
85984a87
DW
470 .with_stdout("")
471 .with_stderr(
1e682848 472 "\
eeebadff 473[WARNING] manifest has no description[..]
0c3851c0 474See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
6b9961a3 475[PACKAGING] foo v0.0.1 ([..])
90887707
EH
476[ARCHIVING] .cargo_vcs_info.json
477[ARCHIVING] Cargo.lock
34307c61 478[ARCHIVING] Cargo.toml
90887707 479[ARCHIVING] Cargo.toml.orig
34307c61
EH
480[ARCHIVING] file_root_3
481[ARCHIVING] file_root_4
482[ARCHIVING] file_root_5
483[ARCHIVING] some_dir/dir_deep_2/some_dir/file
484[ARCHIVING] some_dir/dir_deep_4/some_dir/file
485[ARCHIVING] some_dir/dir_deep_5/some_dir/file
486[ARCHIVING] some_dir/file_deep_2
487[ARCHIVING] some_dir/file_deep_3
488[ARCHIVING] some_dir/file_deep_4
489[ARCHIVING] some_dir/file_deep_5
490[ARCHIVING] src/main.rs
1e682848 491",
fecb7246
AC
492 )
493 .run();
c072ba42 494
dd998a09 495 assert!(repo.root().join("target/package/foo-0.0.1.crate").is_file());
c072ba42 496
dd998a09
XL
497 cargo_process("package -l")
498 .cwd(repo.root())
85984a87 499 .with_stdout(
1e682848 500 "\
dd998a09 501.cargo_vcs_info.json
34307c61 502Cargo.lock
c072ba42 503Cargo.toml
90887707 504Cargo.toml.orig
c072ba42
BE
505file_root_3
506file_root_4
507file_root_5
05400b80 508some_dir/dir_deep_2/some_dir/file
05400b80
DW
509some_dir/dir_deep_4/some_dir/file
510some_dir/dir_deep_5/some_dir/file
05400b80
DW
511some_dir/file_deep_2
512some_dir/file_deep_3
513some_dir/file_deep_4
514some_dir/file_deep_5
515src/main.rs
1e682848 516",
fecb7246
AC
517 )
518 .run();
6950bbb0 519}
5935ec1d 520
0e0d9688 521#[cargo_test]
6950bbb0 522fn include() {
dd998a09
XL
523 let root = paths::root().join("include");
524 let repo = git::repo(&root)
fecb7246
AC
525 .file(
526 "Cargo.toml",
527 r#"
6f8c7d5a
EH
528 [project]
529 name = "foo"
530 version = "0.0.1"
531 authors = []
532 exclude = ["*.txt"]
533 include = ["foo.txt", "**/*.rs", "Cargo.toml", ".dotfile"]
534 "#,
fecb7246 535 )
5935ec1d 536 .file("foo.txt", "")
ca7d9ee2 537 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
7662c2d8 538 .file(".dotfile", "")
f7c91ba6
AR
539 // Should be ignored when packaging.
540 .file("src/bar.txt", "")
d43ee1dd 541 .build();
5935ec1d 542
dd998a09
XL
543 cargo_process("package --no-verify -v")
544 .cwd(repo.root())
85984a87 545 .with_stderr(
1e682848 546 "\
eeebadff 547[WARNING] manifest has no description[..]
0c3851c0 548See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
db3328ec 549[WARNING] both package.include and package.exclude are specified; the exclude list will be ignored
fee4308b 550[PACKAGING] foo v0.0.1 ([..])
90887707 551[ARCHIVING] .cargo_vcs_info.json
7662c2d8 552[ARCHIVING] .dotfile
90887707 553[ARCHIVING] Cargo.lock
34307c61 554[ARCHIVING] Cargo.toml
90887707 555[ARCHIVING] Cargo.toml.orig
34307c61
EH
556[ARCHIVING] foo.txt
557[ARCHIVING] src/main.rs
1e682848 558",
fecb7246
AC
559 )
560 .run();
6950bbb0 561}
350bd8d2 562
0e0d9688 563#[cargo_test]
6950bbb0 564fn package_lib_with_bin() {
7fe2fbc8 565 let p = project()
ca7d9ee2 566 .file("src/main.rs", "extern crate foo; fn main() {}")
d43ee1dd
NK
567 .file("src/lib.rs", "")
568 .build();
350bd8d2 569
85984a87 570 p.cargo("package -v").run();
6950bbb0 571}
a8e9ce22 572
0e0d9688 573#[cargo_test]
6950bbb0 574fn package_git_submodule() {
036d6f6d 575 let project = git::new("foo", |project| {
1e682848
AC
576 project
577 .file(
578 "Cargo.toml",
579 r#"
036d6f6d
IU
580 [project]
581 name = "foo"
582 version = "0.0.1"
583 authors = ["foo@example.com"]
584 license = "MIT"
585 description = "foo"
586 repository = "foo"
1e682848 587 "#,
fecb7246
AC
588 )
589 .file("src/lib.rs", "pub fn foo() {}")
3c20a243 590 });
85984a87
DW
591 let library = git::new("bar", |library| {
592 library.no_manifest().file("Makefile", "all:")
3c20a243 593 });
036d6f6d
IU
594
595 let repository = git2::Repository::open(&project.root()).unwrap();
596 let url = path2url(library.root()).to_string();
597 git::add_submodule(&repository, &url, Path::new("bar"));
598 git::commit(&repository);
599
600 let repository = git2::Repository::open(&project.root().join("bar")).unwrap();
1e682848
AC
601 repository
602 .reset(
603 &repository.revparse_single("HEAD").unwrap(),
604 git2::ResetType::Hard,
605 None,
fecb7246
AC
606 )
607 .unwrap();
1e682848 608
fecb7246
AC
609 project
610 .cargo("package --no-verify -v")
85984a87
DW
611 .with_stderr_contains("[ARCHIVING] bar/Makefile")
612 .run();
6950bbb0 613}
d33da549 614
77cfceea 615#[cargo_test]
673bb69c
TW
616/// Tests if a symlink to a git submodule is properly handled.
617///
55e56233
TW
618/// This test requires you to be able to make symlinks.
619/// For windows, this may require you to enable developer mode.
77cfceea 620fn package_symlink_to_submodule() {
50a24ff2 621 #[cfg(unix)]
673bb69c 622 use std::os::unix::fs::symlink;
50a24ff2 623 #[cfg(windows)]
32130f8e 624 use std::os::windows::fs::symlink_dir as symlink;
50a24ff2 625
55e56233
TW
626 if !symlink_supported() {
627 return;
628 }
629
77cfceea 630 let project = git::new("foo", |project| {
673bb69c 631 project.file("src/lib.rs", "pub fn foo() {}")
3c20a243 632 });
77cfceea
TW
633
634 let library = git::new("submodule", |library| {
635 library.no_manifest().file("Makefile", "all:")
3c20a243 636 });
77cfceea
TW
637
638 let repository = git2::Repository::open(&project.root()).unwrap();
639 let url = path2url(library.root()).to_string();
640 git::add_submodule(&repository, &url, Path::new("submodule"));
673bb69c
TW
641 t!(symlink(
642 &project.root().join("submodule"),
643 &project.root().join("submodule-link")
644 ));
50a24ff2 645 git::add(&repository);
77cfceea
TW
646 git::commit(&repository);
647
648 let repository = git2::Repository::open(&project.root().join("submodule")).unwrap();
649 repository
650 .reset(
651 &repository.revparse_single("HEAD").unwrap(),
652 git2::ResetType::Hard,
673bb69c
TW
653 None,
654 )
655 .unwrap();
77cfceea
TW
656
657 project
658 .cargo("package --no-verify -v")
659 .with_stderr_contains("[ARCHIVING] submodule/Makefile")
660 .run();
661}
662
0e0d9688 663#[cargo_test]
6950bbb0 664fn no_duplicates_from_modified_tracked_files() {
4ae79d2f
EH
665 let p = git::new("all", |p| p.file("src/main.rs", "fn main() {}"));
666 p.change_file("src/main.rs", r#"fn main() { println!("A change!"); }"#);
667 p.cargo("build").run();
668 p.cargo("package --list --allow-dirty")
85984a87 669 .with_stdout(
1e682848 670 "\
34307c61 671Cargo.lock
e2cd4cdb 672Cargo.toml
90887707 673Cargo.toml.orig
e2cd4cdb 674src/main.rs
1e682848 675",
fecb7246
AC
676 )
677 .run();
6950bbb0 678}
e2cd4cdb 679
0e0d9688 680#[cargo_test]
6950bbb0 681fn ignore_nested() {
d33da549
SF
682 let cargo_toml = r#"
683 [project]
f8c9928c 684 name = "foo"
d33da549
SF
685 version = "0.0.1"
686 authors = []
687 license = "MIT"
f8c9928c 688 description = "foo"
d33da549
SF
689 "#;
690 let main_rs = r#"
691 fn main() { println!("hello"); }
692 "#;
f8c9928c 693 let p = project()
d33da549
SF
694 .file("Cargo.toml", cargo_toml)
695 .file("src/main.rs", main_rs)
696 // If a project happens to contain a copy of itself, we should
697 // ignore it.
f8c9928c
DW
698 .file("a_dir/foo/Cargo.toml", cargo_toml)
699 .file("a_dir/foo/src/main.rs", main_rs)
d43ee1dd 700 .build();
d33da549 701
85984a87 702 p.cargo("package")
2cd9cce6 703 .with_stderr(
1e682848 704 "\
eeebadff 705[WARNING] manifest has no documentation[..]
0c3851c0 706See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
89f43938
ZL
707[PACKAGING] foo v0.0.1 ([CWD])
708[VERIFYING] foo v0.0.1 ([CWD])
709[COMPILING] foo v0.0.1 ([CWD][..])
34628b65 710[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
d33da549 711",
fecb7246
AC
712 )
713 .run();
570fe892 714 assert!(p.root().join("target/package/foo-0.0.1.crate").is_file());
85984a87
DW
715 p.cargo("package -l")
716 .with_stdout(
1e682848 717 "\
34307c61 718Cargo.lock
d33da549 719Cargo.toml
90887707
EH
720Cargo.toml.orig
721src/main.rs
1e682848 722",
fecb7246
AC
723 )
724 .run();
85984a87 725 p.cargo("package").with_stdout("").run();
d33da549 726
f8c9928c 727 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
3d84d0ad
EH
728 validate_crate_contents(
729 f,
730 "foo-0.0.1.crate",
34307c61 731 &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
3d84d0ad
EH
732 &[],
733 );
6950bbb0 734}
afe837d7 735
f7c91ba6
AR
736// Windows doesn't allow these characters in filenames.
737#[cfg(unix)]
0e0d9688 738#[cargo_test]
6950bbb0 739fn package_weird_characters() {
7fe2fbc8 740 let p = project()
ca7d9ee2 741 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
d43ee1dd
NK
742 .file("src/:foo", "")
743 .build();
afe837d7 744
85984a87
DW
745 p.cargo("package")
746 .with_status(101)
747 .with_stderr(
1e682848 748 "\
afe837d7 749warning: [..]
32275465 750See [..]
90887707 751[ERROR] cannot package a filename with a special character `:`: src/:foo
1e682848 752",
fecb7246
AC
753 )
754 .run();
6950bbb0 755}
18bf06d3 756
0e0d9688 757#[cargo_test]
18bf06d3 758fn repackage_on_source_change() {
7fe2fbc8 759 let p = project()
ca7d9ee2 760 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
d43ee1dd 761 .build();
18bf06d3 762
85984a87 763 p.cargo("package").run();
18bf06d3
BF
764
765 // Add another source file
4ae79d2f 766 p.change_file("src/foo.rs", r#"fn main() { println!("foo"); }"#);
18bf06d3 767
18bf06d3 768 // Check that cargo rebuilds the tarball
4415c728 769 p.cargo("package")
2cd9cce6 770 .with_stderr(
1e682848 771 "\
18bf06d3 772[WARNING] [..]
32275465 773See [..]
89f43938
ZL
774[PACKAGING] foo v0.0.1 ([CWD])
775[VERIFYING] foo v0.0.1 ([CWD])
776[COMPILING] foo v0.0.1 ([CWD][..])
34628b65 777[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
18bf06d3 778",
fecb7246
AC
779 )
780 .run();
18bf06d3
BF
781
782 // Check that the tarball contains the added file
783 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
3d84d0ad
EH
784 validate_crate_contents(
785 f,
786 "foo-0.0.1.crate",
34307c61
EH
787 &[
788 "Cargo.lock",
789 "Cargo.toml",
790 "Cargo.toml.orig",
791 "src/main.rs",
792 "src/foo.rs",
793 ],
3d84d0ad
EH
794 &[],
795 );
18bf06d3 796}
77812987 797
0e0d9688 798#[cargo_test]
673bb69c
TW
799/// Tests if a broken symlink is properly handled when packaging.
800///
55e56233
TW
801/// This test requires you to be able to make symlinks.
802/// For windows, this may require you to enable developer mode.
77812987 803fn broken_symlink() {
32130f8e 804 #[cfg(unix)]
673bb69c 805 use std::os::unix::fs::symlink;
32130f8e
TW
806 #[cfg(windows)]
807 use std::os::windows::fs::symlink_dir as symlink;
77812987 808
55e56233
TW
809 if !symlink_supported() {
810 return;
811 }
812
7fe2fbc8 813 let p = project()
1e682848
AC
814 .file(
815 "Cargo.toml",
816 r#"
6f8c7d5a
EH
817 [project]
818 name = "foo"
819 version = "0.0.1"
820 authors = []
821 license = "MIT"
822 description = 'foo'
823 documentation = 'foo'
824 homepage = 'foo'
825 repository = 'foo'
826 "#,
fecb7246
AC
827 )
828 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
d43ee1dd 829 .build();
32130f8e 830 t!(symlink("nowhere", &p.root().join("src/foo.rs")));
77812987 831
85984a87
DW
832 p.cargo("package -v")
833 .with_status(101)
834 .with_stderr_contains(
1e682848 835 "\
d92dceae 836[ERROR] failed to prepare local package for uploading
77812987
AC
837
838Caused by:
d92dceae 839 failed to open for archiving: `[..]foo.rs`
77812987
AC
840
841Caused by:
842 [..]
1e682848 843",
fecb7246
AC
844 )
845 .run();
77812987 846}
ee32e105 847
79cc65fa
JG
848#[cargo_test]
849#[cfg(not(windows))] // https://github.com/libgit2/libgit2/issues/6250
850/// Test that /dir and /dir/ matches symlinks to directories.
851fn gitignore_symlink_dir() {
852 if !symlink_supported() {
853 return;
854 }
855
856 let (p, _repo) = git::new_repo("foo", |p| {
857 p.file("src/main.rs", r#"fn main() { println!("hello"); }"#)
858 .symlink_dir("src", "src1")
859 .symlink_dir("src", "src2")
860 .symlink_dir("src", "src3")
861 .symlink_dir("src", "src4")
862 .file(".gitignore", "/src1\n/src2/\nsrc3\nsrc4/")
863 });
864
865 p.cargo("package -l --no-metadata")
866 .with_stderr("")
867 .with_stdout(
868 "\
869.cargo_vcs_info.json
870.gitignore
871Cargo.lock
872Cargo.toml
873Cargo.toml.orig
874src/main.rs
875",
876 )
877 .run();
878}
879
880#[cargo_test]
881#[cfg(not(windows))] // https://github.com/libgit2/libgit2/issues/6250
882/// Test that /dir and /dir/ matches symlinks to directories in dirty working directory.
883fn gitignore_symlink_dir_dirty() {
884 if !symlink_supported() {
885 return;
886 }
887
888 let (p, _repo) = git::new_repo("foo", |p| {
889 p.file("src/main.rs", r#"fn main() { println!("hello"); }"#)
890 .file(".gitignore", "/src1\n/src2/\nsrc3\nsrc4/")
891 });
892
893 p.symlink("src", "src1");
894 p.symlink("src", "src2");
895 p.symlink("src", "src3");
896 p.symlink("src", "src4");
897
898 p.cargo("package -l --no-metadata")
899 .with_stderr("")
900 .with_stdout(
901 "\
902.cargo_vcs_info.json
903.gitignore
904Cargo.lock
905Cargo.toml
906Cargo.toml.orig
907src/main.rs
908",
909 )
910 .run();
911
912 p.cargo("package -l --no-metadata --allow-dirty")
913 .with_stderr("")
914 .with_stdout(
915 "\
916.gitignore
917Cargo.lock
918Cargo.toml
919Cargo.toml.orig
920src/main.rs
921",
922 )
923 .run();
924}
925
77cfceea 926#[cargo_test]
34f2d471 927/// Tests if a symlink to a directory is properly included.
673bb69c 928///
55e56233
TW
929/// This test requires you to be able to make symlinks.
930/// For windows, this may require you to enable developer mode.
77cfceea 931fn package_symlink_to_dir() {
55e56233
TW
932 if !symlink_supported() {
933 return;
934 }
935
77cfceea
TW
936 project()
937 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
938 .file("bla/Makefile", "all:")
939 .symlink_dir("bla", "foo")
940 .build()
941 .cargo("package -v")
942 .with_stderr_contains("[ARCHIVING] foo/Makefile")
943 .run();
944}
945
6fa0f01d
WL
946#[cargo_test]
947/// Tests if a symlink to ancestor causes filesystem loop error.
948///
949/// This test requires you to be able to make symlinks.
950/// For windows, this may require you to enable developer mode.
951fn filesystem_loop() {
952 if !symlink_supported() {
953 return;
954 }
955
956 project()
957 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
958 .symlink_dir("a/b", "a/b/c/d/foo")
959 .build()
960 .cargo("package -v")
6fa0f01d 961 .with_stderr_contains(
d92dceae 962 "[WARNING] File system loop found: [..]/a/b/c/d/foo points to an ancestor [..]/a/b",
6fa0f01d
WL
963 )
964 .run();
965}
966
0e0d9688 967#[cargo_test]
ee32e105 968fn do_not_package_if_repository_is_dirty() {
7fe2fbc8 969 let p = project().build();
5e8eef97 970
ee32e105 971 // Create a Git repository containing a minimal Rust project.
d43ee1dd 972 let _ = git::repo(&paths::root().join("foo"))
1e682848
AC
973 .file(
974 "Cargo.toml",
975 r#"
6f8c7d5a
EH
976 [project]
977 name = "foo"
978 version = "0.0.1"
979 license = "MIT"
980 description = "foo"
981 documentation = "foo"
982 homepage = "foo"
983 repository = "foo"
984 "#,
fecb7246
AC
985 )
986 .file("src/main.rs", "fn main() {}")
ee32e105
BBT
987 .build();
988
989 // Modify Cargo.toml without committing the change.
1e682848
AC
990 p.change_file(
991 "Cargo.toml",
992 r#"
5e8eef97
AK
993 [project]
994 name = "foo"
995 version = "0.0.1"
996 license = "MIT"
997 description = "foo"
998 documentation = "foo"
999 homepage = "foo"
1000 repository = "foo"
1001 # change
6514c289 1002 "#,
1e682848 1003 );
ee32e105 1004
85984a87
DW
1005 p.cargo("package")
1006 .with_status(101)
1007 .with_stderr(
1e682848 1008 "\
ca1acc57
JL
1009error: 1 files in the working directory contain changes that were not yet \
1010committed into git:
ee32e105
BBT
1011
1012Cargo.toml
1013
34f2d471 1014to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag
1e682848 1015",
fecb7246
AC
1016 )
1017 .run();
ee32e105 1018}
57db8bde 1019
a200640d
EH
1020#[cargo_test]
1021fn dirty_ignored() {
1022 // Cargo warns about an ignored file that will be published.
1023 let (p, repo) = git::new_repo("foo", |p| {
1024 p.file(
1025 "Cargo.toml",
1026 r#"
1027 [package]
1028 name = "foo"
1029 version = "0.1.0"
1030 description = "foo"
1031 license = "foo"
1032 documentation = "foo"
1033 include = ["src", "build"]
1034 "#,
1035 )
1036 .file("src/lib.rs", "")
1037 .file(".gitignore", "build")
1038 });
1039 // Example of adding a file that is confusingly ignored by an overzealous
1040 // gitignore rule.
1041 p.change_file("src/build/mod.rs", "");
1042 p.cargo("package --list")
1043 .with_status(101)
1044 .with_stderr(
1045 "\
1046error: 1 files in the working directory contain changes that were not yet committed into git:
1047
1048src/build/mod.rs
1049
1050to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag
1051",
1052 )
1053 .run();
1054 // Add the ignored file and make sure it is included.
1055 let mut index = t!(repo.index());
1056 t!(index.add_path(Path::new("src/build/mod.rs")));
1057 t!(index.write());
1058 git::commit(&repo);
1059 p.cargo("package --list")
1060 .with_stderr("")
1061 .with_stdout(
1062 "\
1063.cargo_vcs_info.json
1064Cargo.toml
1065Cargo.toml.orig
1066src/build/mod.rs
1067src/lib.rs
1068",
1069 )
1070 .run();
1071}
1072
0e0d9688 1073#[cargo_test]
57db8bde 1074fn generated_manifest() {
24dac452 1075 let registry = registry::alt_init();
f38c53f5 1076 Package::new("abc", "1.0.0").publish();
a4a3302d 1077 Package::new("def", "1.0.0").alternative(true).publish();
f38c53f5 1078 Package::new("ghi", "1.0.0").publish();
34307c61 1079 Package::new("bar", "0.1.0").publish();
a4a3302d 1080
7fe2fbc8 1081 let p = project()
1e682848
AC
1082 .file(
1083 "Cargo.toml",
1084 r#"
6f8c7d5a
EH
1085 [project]
1086 name = "foo"
1087 version = "0.0.1"
1088 authors = []
1089 exclude = ["*.txt"]
1090 license = "MIT"
1091 description = "foo"
57db8bde 1092
6f8c7d5a
EH
1093 [project.metadata]
1094 foo = 'bar'
0c704f8d 1095
6f8c7d5a 1096 [workspace]
57db8bde 1097
6f8c7d5a
EH
1098 [dependencies]
1099 bar = { path = "bar", version = "0.1" }
1100 def = { version = "1.0", registry = "alternative" }
1101 ghi = "1.0"
1102 abc = "1.0"
1103 "#,
fecb7246
AC
1104 )
1105 .file("src/main.rs", "")
ab19c483 1106 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
d43ee1dd
NK
1107 .file("bar/src/lib.rs", "")
1108 .build();
57db8bde 1109
87449f45 1110 p.cargo("package --no-verify").run();
57db8bde
AC
1111
1112 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
3d84d0ad 1113 let rewritten_toml = format!(
787e75b7 1114 r#"{}
57db8bde
AC
1115[package]
1116name = "foo"
1117version = "0.0.1"
1118authors = []
1119exclude = ["*.txt"]
1120description = "foo"
1121license = "MIT"
0c704f8d
AC
1122
1123[package.metadata]
1124foo = "bar"
320c279f 1125
f38c53f5
SS
1126[dependencies.abc]
1127version = "1.0"
1128
57db8bde
AC
1129[dependencies.bar]
1130version = "0.1"
f38c53f5
SS
1131
1132[dependencies.def]
1133version = "1.0"
c40d1836 1134registry-index = "{}"
f38c53f5
SS
1135
1136[dependencies.ghi]
1137version = "1.0"
f6dcdb5c 1138"#,
787e75b7 1139 cargo::core::package::MANIFEST_PREAMBLE,
24dac452 1140 registry.index_url()
3d84d0ad
EH
1141 );
1142
1143 validate_crate_contents(
1144 f,
1145 "foo-0.0.1.crate",
34307c61 1146 &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
3d84d0ad 1147 &[("Cargo.toml", &rewritten_toml)],
1e682848 1148 );
57db8bde
AC
1149}
1150
0e0d9688 1151#[cargo_test]
57db8bde 1152fn ignore_workspace_specifier() {
7fe2fbc8 1153 let p = project()
1e682848
AC
1154 .file(
1155 "Cargo.toml",
1156 r#"
6f8c7d5a
EH
1157 [project]
1158 name = "foo"
1159 version = "0.0.1"
d1e70e49 1160
6f8c7d5a 1161 authors = []
57db8bde 1162
6f8c7d5a 1163 [workspace]
57db8bde 1164
6f8c7d5a
EH
1165 [dependencies]
1166 bar = { path = "bar", version = "0.1" }
1167 "#,
fecb7246
AC
1168 )
1169 .file("src/main.rs", "")
1e682848
AC
1170 .file(
1171 "bar/Cargo.toml",
1172 r#"
6f8c7d5a
EH
1173 [package]
1174 name = "bar"
1175 version = "0.1.0"
1176 authors = []
1177 workspace = ".."
1178 "#,
fecb7246
AC
1179 )
1180 .file("bar/src/lib.rs", "")
d43ee1dd 1181 .build();
57db8bde 1182
f16efff1 1183 p.cargo("package --no-verify").cwd("bar").run();
57db8bde
AC
1184
1185 let f = File::open(&p.root().join("target/package/bar-0.1.0.crate")).unwrap();
787e75b7
EH
1186 let rewritten_toml = format!(
1187 r#"{}
57db8bde
AC
1188[package]
1189name = "bar"
1190version = "0.1.0"
1191authors = []
787e75b7
EH
1192"#,
1193 cargo::core::package::MANIFEST_PREAMBLE
1194 );
3d84d0ad
EH
1195 validate_crate_contents(
1196 f,
1197 "bar-0.1.0.crate",
1198 &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs"],
787e75b7 1199 &[("Cargo.toml", &rewritten_toml)],
1e682848 1200 );
57db8bde 1201}
d1e70e49 1202
0e0d9688 1203#[cargo_test]
d1e70e49
AC
1204fn package_two_kinds_of_deps() {
1205 Package::new("other", "1.0.0").publish();
1206 Package::new("other1", "1.0.0").publish();
7fe2fbc8 1207 let p = project()
1e682848
AC
1208 .file(
1209 "Cargo.toml",
1210 r#"
6f8c7d5a
EH
1211 [project]
1212 name = "foo"
1213 version = "0.0.1"
1214 authors = []
d1e70e49 1215
6f8c7d5a
EH
1216 [dependencies]
1217 other = "1.0"
1218 other1 = { version = "1.0" }
1219 "#,
fecb7246
AC
1220 )
1221 .file("src/main.rs", "")
d43ee1dd 1222 .build();
d1e70e49 1223
85984a87 1224 p.cargo("package --no-verify").run();
d1e70e49 1225}
5d615a69 1226
0e0d9688 1227#[cargo_test]
3bbe93ce 1228fn test_edition() {
7fe2fbc8 1229 let p = project()
1e682848
AC
1230 .file(
1231 "Cargo.toml",
1232 r#"
6f8c7d5a
EH
1233 cargo-features = ["edition"]
1234 [package]
1235 name = "foo"
1236 version = "0.0.1"
1237 authors = []
1238 edition = "2018"
1239 "#,
fecb7246
AC
1240 )
1241 .file("src/lib.rs", r#" "#)
5d615a69
MG
1242 .build();
1243
fecb7246 1244 p.cargo("build -v")
fecb7246
AC
1245 .with_stderr_contains(
1246 "\
3dbae343
EH
1247[COMPILING] foo v0.0.1 ([..])
1248[RUNNING] `rustc [..]--edition=2018 [..]
fecb7246
AC
1249",
1250 )
1251 .run();
5d615a69
MG
1252}
1253
0e0d9688 1254#[cargo_test]
8590a5fb 1255fn edition_with_metadata() {
8590a5fb 1256 let p = project()
85984a87
DW
1257 .file(
1258 "Cargo.toml",
1259 r#"
3d029039
AC
1260 [package]
1261 name = "foo"
1262 version = "0.0.1"
1263 authors = []
1264 edition = "2018"
1265
1266 [package.metadata.docs.rs]
1267 features = ["foobar"]
1268 "#,
fecb7246
AC
1269 )
1270 .file("src/lib.rs", "")
8590a5fb
DS
1271 .build();
1272
3d029039 1273 p.cargo("package").run();
5d615a69
MG
1274}
1275
0e0d9688 1276#[cargo_test]
3bbe93ce 1277fn test_edition_malformed() {
7fe2fbc8 1278 let p = project()
1e682848
AC
1279 .file(
1280 "Cargo.toml",
1281 r#"
3d029039
AC
1282 [package]
1283 name = "foo"
1284 version = "0.0.1"
1285 authors = []
1286 edition = "chicken"
1287 "#,
fecb7246
AC
1288 )
1289 .file("src/lib.rs", r#" "#)
5d615a69
MG
1290 .build();
1291
85984a87 1292 p.cargo("build -v")
85984a87
DW
1293 .with_status(101)
1294 .with_stderr(
1e682848 1295 "\
5d615a69
MG
1296error: failed to parse manifest at `[..]`
1297
1298Caused by:
84130089
AC
1299 failed to parse the `edition` key
1300
1301Caused by:
de839dab 1302 supported edition values are `2015`, `2018`, or `2021`, but `chicken` is unknown
fecb7246
AC
1303"
1304 .to_string(),
1305 )
1306 .run();
5d615a69
MG
1307}
1308
f57c4c9b
K
1309#[cargo_test]
1310fn test_edition_from_the_future() {
1311 let p = project()
1312 .file(
1313 "Cargo.toml",
1314 r#"[package]
1315 edition = "2038"
1316 name = "foo"
1317 version = "99.99.99"
1318 authors = []
1319 "#,
1320 )
1321 .file("src/main.rs", r#""#)
1322 .build();
1323
1324 p.cargo("build")
1325 .with_status(101)
1326 .with_stderr(
1327 "\
1328error: failed to parse manifest at `[..]`
1329
1330Caused by:
1331 failed to parse the `edition` key
1332
1333Caused by:
de839dab 1334 this version of Cargo is older than the `2038` edition, and only supports `2015`, `2018`, and `2021` editions.
f57c4c9b
K
1335"
1336 .to_string(),
1337 )
1338 .run();
1339}
1340
0e0d9688 1341#[cargo_test]
ba48ff42 1342fn do_not_package_if_src_was_modified() {
7fe2fbc8 1343 let p = project()
ca7d9ee2 1344 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
aef2a9cb 1345 .file("dir/foo.txt", "")
78a60bc7 1346 .file("bar.txt", "")
85984a87
DW
1347 .file(
1348 "build.rs",
1349 r#"
6f8c7d5a
EH
1350 use std::fs;
1351
1352 fn main() {
1353 fs::write("src/generated.txt",
1354 "Hello, world of generated files."
1355 ).expect("failed to create file");
1356 fs::remove_file("dir/foo.txt").expect("failed to remove file");
1357 fs::remove_dir("dir").expect("failed to remove dir");
1358 fs::write("bar.txt", "updated content").expect("failed to update");
1359 fs::create_dir("new-dir").expect("failed to create dir");
1360 }
1361 "#,
fecb7246
AC
1362 )
1363 .build();
ba48ff42 1364
85984a87
DW
1365 p.cargo("package")
1366 .with_status(101)
1367 .with_stderr_contains(
1368 "\
53480ac7
GF
1369error: failed to verify package tarball
1370
1371Caused by:
1372 Source directory was modified by build.rs during cargo publish. \
6514c289
AC
1373 Build scripts should not modify anything outside of OUT_DIR.
1374 Changed: [CWD]/target/package/foo-0.0.1/bar.txt
1375 Added: [CWD]/target/package/foo-0.0.1/new-dir
1376 <tab>[CWD]/target/package/foo-0.0.1/src/generated.txt
1377 Removed: [CWD]/target/package/foo-0.0.1/dir
1378 <tab>[CWD]/target/package/foo-0.0.1/dir/foo.txt
1379
1380 To proceed despite this, pass the `--no-verify` flag.",
fecb7246
AC
1381 )
1382 .run();
ba48ff42 1383
85984a87 1384 p.cargo("package --no-verify").run();
ba48ff42 1385}
142bafb7 1386
0e0d9688 1387#[cargo_test]
142bafb7
KF
1388fn package_with_select_features() {
1389 let p = project()
1390 .file(
1391 "Cargo.toml",
1392 r#"
6f8c7d5a
EH
1393 [project]
1394 name = "foo"
1395 version = "0.0.1"
1396 authors = []
1397 license = "MIT"
1398 description = "foo"
142bafb7 1399
6f8c7d5a
EH
1400 [features]
1401 required = []
1402 optional = []
1403 "#,
db09895f 1404 )
1405 .file(
142bafb7
KF
1406 "src/main.rs",
1407 "#[cfg(not(feature = \"required\"))]
1408 compile_error!(\"This crate requires `required` feature!\");
1409 fn main() {}",
db09895f 1410 )
1411 .build();
142bafb7 1412
87449f45 1413 p.cargo("package --features required").run();
142bafb7
KF
1414}
1415
0e0d9688 1416#[cargo_test]
142bafb7
KF
1417fn package_with_all_features() {
1418 let p = project()
1419 .file(
1420 "Cargo.toml",
1421 r#"
6f8c7d5a
EH
1422 [project]
1423 name = "foo"
1424 version = "0.0.1"
1425 authors = []
1426 license = "MIT"
1427 description = "foo"
142bafb7 1428
6f8c7d5a
EH
1429 [features]
1430 required = []
1431 optional = []
1432 "#,
db09895f 1433 )
1434 .file(
142bafb7
KF
1435 "src/main.rs",
1436 "#[cfg(not(feature = \"required\"))]
1437 compile_error!(\"This crate requires `required` feature!\");
1438 fn main() {}",
db09895f 1439 )
1440 .build();
142bafb7 1441
87449f45 1442 p.cargo("package --all-features").run();
142bafb7 1443}
b29e3796 1444
0e0d9688 1445#[cargo_test]
b29e3796
KF
1446fn package_no_default_features() {
1447 let p = project()
1448 .file(
1449 "Cargo.toml",
1450 r#"
6f8c7d5a
EH
1451 [project]
1452 name = "foo"
1453 version = "0.0.1"
1454 authors = []
1455 license = "MIT"
1456 description = "foo"
b29e3796 1457
6f8c7d5a
EH
1458 [features]
1459 default = ["required"]
1460 required = []
1461 "#,
db09895f 1462 )
1463 .file(
b29e3796
KF
1464 "src/main.rs",
1465 "#[cfg(not(feature = \"required\"))]
1466 compile_error!(\"This crate requires `required` feature!\");
1467 fn main() {}",
db09895f 1468 )
1469 .build();
b29e3796
KF
1470
1471 p.cargo("package --no-default-features")
b29e3796
KF
1472 .with_stderr_contains("error: This crate requires `required` feature!")
1473 .with_status(101)
1474 .run();
1475}
49e37f80 1476
0e0d9688 1477#[cargo_test]
49e37f80
EH
1478fn include_cargo_toml_implicit() {
1479 let p = project()
1480 .file(
1481 "Cargo.toml",
1482 r#"
1483 [package]
1484 name = "foo"
1485 version = "0.1.0"
1486 include = ["src/lib.rs"]
1487 "#,
1488 )
1489 .file("src/lib.rs", "")
1490 .build();
1491
1492 p.cargo("package --list")
90887707 1493 .with_stdout("Cargo.toml\nCargo.toml.orig\nsrc/lib.rs\n")
49e37f80
EH
1494 .run();
1495}
d4b6e90f 1496
24d28502 1497fn include_exclude_test(include: &str, exclude: &str, files: &[&str], expected: &str) {
d4b6e90f
EH
1498 let mut pb = project().file(
1499 "Cargo.toml",
1500 &format!(
1501 r#"
1502 [package]
1503 name = "foo"
1504 version = "0.1.0"
1505 authors = []
1506 license = "MIT"
1507 description = "foo"
1508 documentation = "foo"
1509 homepage = "foo"
1510 repository = "foo"
1511 include = {}
1512 exclude = {}
1513 "#,
1514 include, exclude
1515 ),
1516 );
1517 for file in files {
1518 pb = pb.file(file, "");
1519 }
1520 let p = pb.build();
1521
24d28502
EH
1522 p.cargo("package --list")
1523 .with_stderr("")
1524 .with_stdout(expected)
1525 .run();
d4b6e90f
EH
1526 p.root().rm_rf();
1527}
1528
0e0d9688 1529#[cargo_test]
d4b6e90f
EH
1530fn package_include_ignore_only() {
1531 // Test with a gitignore pattern that fails to parse with glob.
1532 // This is a somewhat nonsense pattern, but is an example of something git
1533 // allows and glob does not.
1534 assert!(glob::Pattern::new("src/abc**").is_err());
1535
1536 include_exclude_test(
1537 r#"["Cargo.toml", "src/abc**", "src/lib.rs"]"#,
1538 "[]",
1539 &["src/lib.rs", "src/abc1.rs", "src/abc2.rs", "src/abc/mod.rs"],
1540 "Cargo.toml\n\
90887707 1541 Cargo.toml.orig\n\
d4b6e90f
EH
1542 src/abc/mod.rs\n\
1543 src/abc1.rs\n\
1544 src/abc2.rs\n\
1545 src/lib.rs\n\
1546 ",
1547 )
1548}
1549
0e0d9688 1550#[cargo_test]
d4b6e90f
EH
1551fn gitignore_patterns() {
1552 include_exclude_test(
1553 r#"["Cargo.toml", "foo"]"#, // include
1554 "[]",
1555 &["src/lib.rs", "foo", "a/foo", "a/b/foo", "x/foo/y", "bar"],
1556 "Cargo.toml\n\
90887707 1557 Cargo.toml.orig\n\
d4b6e90f
EH
1558 a/b/foo\n\
1559 a/foo\n\
1560 foo\n\
1561 x/foo/y\n\
1562 ",
1563 );
1564
1565 include_exclude_test(
1566 r#"["Cargo.toml", "/foo"]"#, // include
1567 "[]",
1568 &["src/lib.rs", "foo", "a/foo", "a/b/foo", "x/foo/y", "bar"],
1569 "Cargo.toml\n\
90887707 1570 Cargo.toml.orig\n\
d4b6e90f
EH
1571 foo\n\
1572 ",
1573 );
1574
1575 include_exclude_test(
1576 "[]",
1577 r#"["foo/"]"#, // exclude
1578 &["src/lib.rs", "foo", "a/foo", "x/foo/y", "bar"],
1579 "Cargo.toml\n\
90887707 1580 Cargo.toml.orig\n\
d4b6e90f
EH
1581 a/foo\n\
1582 bar\n\
1583 foo\n\
1584 src/lib.rs\n\
1585 ",
1586 );
1587
1588 include_exclude_test(
1589 "[]",
1590 r#"["*.txt", "[ab]", "[x-z]"]"#, // exclude
1591 &[
1592 "src/lib.rs",
1593 "foo.txt",
1594 "bar/foo.txt",
1595 "other",
1596 "a",
1597 "b",
1598 "c",
1599 "x",
1600 "y",
1601 "z",
1602 ],
1603 "Cargo.toml\n\
90887707 1604 Cargo.toml.orig\n\
d4b6e90f
EH
1605 c\n\
1606 other\n\
1607 src/lib.rs\n\
1608 ",
1609 );
1610
1611 include_exclude_test(
1612 r#"["Cargo.toml", "**/foo/bar"]"#, // include
1613 "[]",
1614 &["src/lib.rs", "a/foo/bar", "foo", "bar"],
1615 "Cargo.toml\n\
90887707 1616 Cargo.toml.orig\n\
d4b6e90f
EH
1617 a/foo/bar\n\
1618 ",
1619 );
1620
1621 include_exclude_test(
1622 r#"["Cargo.toml", "foo/**"]"#, // include
1623 "[]",
1624 &["src/lib.rs", "a/foo/bar", "foo/x/y/z"],
1625 "Cargo.toml\n\
90887707 1626 Cargo.toml.orig\n\
d4b6e90f
EH
1627 foo/x/y/z\n\
1628 ",
1629 );
1630
1631 include_exclude_test(
1632 r#"["Cargo.toml", "a/**/b"]"#, // include
1633 "[]",
1634 &["src/lib.rs", "a/b", "a/x/b", "a/x/y/b"],
1635 "Cargo.toml\n\
90887707 1636 Cargo.toml.orig\n\
d4b6e90f
EH
1637 a/b\n\
1638 a/x/b\n\
1639 a/x/y/b\n\
1640 ",
3ca96e90
EH
1641 );
1642}
1643
0e0d9688 1644#[cargo_test]
3ca96e90
EH
1645fn gitignore_negate() {
1646 include_exclude_test(
1647 r#"["Cargo.toml", "*.rs", "!foo.rs", "\\!important"]"#, // include
1648 "[]",
1649 &["src/lib.rs", "foo.rs", "!important"],
1650 "!important\n\
1651 Cargo.toml\n\
90887707 1652 Cargo.toml.orig\n\
3ca96e90
EH
1653 src/lib.rs\n\
1654 ",
3ca96e90
EH
1655 );
1656
1657 // NOTE: This is unusual compared to git. Git treats `src/` as a
1658 // short-circuit which means rules like `!src/foo.rs` would never run.
1659 // However, because Cargo only works by iterating over *files*, it doesn't
1660 // short-circuit.
1661 include_exclude_test(
1662 r#"["Cargo.toml", "src/", "!src/foo.rs"]"#, // include
1663 "[]",
1664 &["src/lib.rs", "src/foo.rs"],
1665 "Cargo.toml\n\
90887707 1666 Cargo.toml.orig\n\
3ca96e90
EH
1667 src/lib.rs\n\
1668 ",
3ca96e90
EH
1669 );
1670
1671 include_exclude_test(
337fbaaa 1672 r#"["Cargo.toml", "src/*.rs", "!foo.rs"]"#, // include
3ca96e90
EH
1673 "[]",
1674 &["src/lib.rs", "foo.rs", "src/foo.rs", "src/bar/foo.rs"],
1675 "Cargo.toml\n\
90887707 1676 Cargo.toml.orig\n\
3ca96e90
EH
1677 src/lib.rs\n\
1678 ",
3ca96e90
EH
1679 );
1680
1681 include_exclude_test(
1682 "[]",
1683 r#"["*.rs", "!foo.rs", "\\!important"]"#, // exclude
1684 &["src/lib.rs", "foo.rs", "!important"],
1685 "Cargo.toml\n\
90887707 1686 Cargo.toml.orig\n\
3ca96e90
EH
1687 foo.rs\n\
1688 ",
d4b6e90f
EH
1689 );
1690}
5c5d1718
SH
1691
1692#[cargo_test]
1693fn exclude_dot_files_and_directories_by_default() {
1694 include_exclude_test(
1695 "[]",
1696 "[]",
1697 &["src/lib.rs", ".dotfile", ".dotdir/file"],
1698 "Cargo.toml\n\
90887707 1699 Cargo.toml.orig\n\
5c5d1718
SH
1700 src/lib.rs\n\
1701 ",
1702 );
1703
1704 include_exclude_test(
1705 r#"["Cargo.toml", "src/lib.rs", ".dotfile", ".dotdir/file"]"#,
1706 "[]",
1707 &["src/lib.rs", ".dotfile", ".dotdir/file"],
1708 ".dotdir/file\n\
1709 .dotfile\n\
1710 Cargo.toml\n\
90887707 1711 Cargo.toml.orig\n\
5c5d1718
SH
1712 src/lib.rs\n\
1713 ",
1714 );
1715}
ab33bc0c
EH
1716
1717#[cargo_test]
1718fn invalid_license_file_path() {
1719 // Test warning when license-file points to a non-existent file.
1720 let p = project()
1721 .file(
1722 "Cargo.toml",
1723 r#"
1724 [package]
1725 name = "foo"
1726 version = "1.0.0"
1727 license-file = "does-not-exist"
1728 description = "foo"
1729 homepage = "foo"
1730 "#,
1731 )
1732 .file("src/lib.rs", "")
1733 .build();
1734
1735 p.cargo("package --no-verify")
1736 .with_stderr(
1737 "\
1738[WARNING] license-file `does-not-exist` does not appear to exist (relative to `[..]/foo`).
1739Please update the license-file setting in the manifest at `[..]/foo/Cargo.toml`
1740This may become a hard error in the future.
1741[PACKAGING] foo v1.0.0 ([..]/foo)
1742",
1743 )
1744 .run();
1745}
90887707
EH
1746
1747#[cargo_test]
1748fn license_file_implicit_include() {
1749 // license-file should be automatically included even if not listed.
1750 let p = git::new("foo", |p| {
1751 p.file(
1752 "Cargo.toml",
1753 r#"
1754 [package]
1755 name = "foo"
1756 version = "1.0.0"
1757 license-file = "subdir/LICENSE"
1758 description = "foo"
1759 homepage = "foo"
1760 include = ["src"]
1761 "#,
1762 )
1763 .file("src/lib.rs", "")
1764 .file("subdir/LICENSE", "license text")
1765 });
1766
1767 p.cargo("package --list")
1768 .with_stdout(
1769 "\
1770.cargo_vcs_info.json
1771Cargo.toml
1772Cargo.toml.orig
1773src/lib.rs
1774subdir/LICENSE
1775",
1776 )
1777 .with_stderr("")
1778 .run();
1779
1780 p.cargo("package --no-verify -v")
1781 .with_stderr(
1782 "\
1783[PACKAGING] foo v1.0.0 [..]
1784[ARCHIVING] .cargo_vcs_info.json
1785[ARCHIVING] Cargo.toml
1786[ARCHIVING] Cargo.toml.orig
1787[ARCHIVING] src/lib.rs
1788[ARCHIVING] subdir/LICENSE
1789",
1790 )
1791 .run();
1792 let f = File::open(&p.root().join("target/package/foo-1.0.0.crate")).unwrap();
1793 validate_crate_contents(
1794 f,
1795 "foo-1.0.0.crate",
1796 &[
1797 ".cargo_vcs_info.json",
1798 "Cargo.toml",
1799 "Cargo.toml.orig",
1800 "subdir/LICENSE",
1801 "src/lib.rs",
1802 ],
1803 &[("subdir/LICENSE", "license text")],
1804 );
1805}
1806
1807#[cargo_test]
1808fn relative_license_included() {
1809 // license-file path outside of package will copy into root.
1810 let p = project()
1811 .file(
1812 "Cargo.toml",
1813 r#"
1814 [package]
1815 name = "foo"
1816 version = "1.0.0"
1817 license-file = "../LICENSE"
1818 description = "foo"
1819 homepage = "foo"
1820 "#,
1821 )
1822 .file("src/lib.rs", "")
1823 .file("../LICENSE", "license text")
1824 .build();
1825
1826 p.cargo("package --list")
1827 .with_stdout(
1828 "\
1829Cargo.toml
1830Cargo.toml.orig
1831LICENSE
1832src/lib.rs
1833",
1834 )
1835 .with_stderr("")
1836 .run();
1837
1838 p.cargo("package")
1839 .with_stderr(
1840 "\
1841[PACKAGING] foo v1.0.0 [..]
1842[VERIFYING] foo v1.0.0 [..]
1843[COMPILING] foo v1.0.0 [..]
1844[FINISHED] [..]
1845",
1846 )
1847 .run();
1848 let f = File::open(&p.root().join("target/package/foo-1.0.0.crate")).unwrap();
1849 validate_crate_contents(
1850 f,
1851 "foo-1.0.0.crate",
1852 &["Cargo.toml", "Cargo.toml.orig", "LICENSE", "src/lib.rs"],
1853 &[("LICENSE", "license text")],
1854 );
1855 let manifest =
1856 std::fs::read_to_string(p.root().join("target/package/foo-1.0.0/Cargo.toml")).unwrap();
1857 assert!(manifest.contains("license-file = \"LICENSE\""));
1858 let orig =
1859 std::fs::read_to_string(p.root().join("target/package/foo-1.0.0/Cargo.toml.orig")).unwrap();
1860 assert!(orig.contains("license-file = \"../LICENSE\""));
1861}
1862
1863#[cargo_test]
1864fn relative_license_include_collision() {
1865 // Can't copy a relative license-file if there is a file with that name already.
1866 let p = project()
1867 .file(
1868 "Cargo.toml",
1869 r#"
1870 [package]
1871 name = "foo"
1872 version = "1.0.0"
1873 license-file = "../LICENSE"
1874 description = "foo"
1875 homepage = "foo"
1876 "#,
1877 )
1878 .file("src/lib.rs", "")
1879 .file("../LICENSE", "outer license")
1880 .file("LICENSE", "inner license")
1881 .build();
1882
1883 p.cargo("package --list")
1884 .with_stdout(
1885 "\
1886Cargo.toml
1887Cargo.toml.orig
1888LICENSE
1889src/lib.rs
1890",
1891 )
1892 .with_stderr("[WARNING] license-file `../LICENSE` appears to be [..]")
1893 .run();
1894
1895 p.cargo("package")
1896 .with_stderr(
1897 "\
1898[WARNING] license-file `../LICENSE` appears to be [..]
1899[PACKAGING] foo v1.0.0 [..]
1900[VERIFYING] foo v1.0.0 [..]
1901[COMPILING] foo v1.0.0 [..]
1902[FINISHED] [..]
1903",
1904 )
1905 .run();
1906 let f = File::open(&p.root().join("target/package/foo-1.0.0.crate")).unwrap();
1907 validate_crate_contents(
1908 f,
1909 "foo-1.0.0.crate",
1910 &["Cargo.toml", "Cargo.toml.orig", "LICENSE", "src/lib.rs"],
1911 &[("LICENSE", "inner license")],
1912 );
1913 let manifest = read_to_string(p.root().join("target/package/foo-1.0.0/Cargo.toml")).unwrap();
1914 assert!(manifest.contains("license-file = \"LICENSE\""));
1915 let orig = read_to_string(p.root().join("target/package/foo-1.0.0/Cargo.toml.orig")).unwrap();
1916 assert!(orig.contains("license-file = \"../LICENSE\""));
1917}
2a874aa5
EH
1918
1919#[cargo_test]
1920#[cfg(not(windows))] // Don't want to create invalid files on Windows.
1921fn package_restricted_windows() {
1922 let p = project()
1923 .file(
1924 "Cargo.toml",
1925 r#"
1926 [package]
1927 name = "foo"
1928 version = "0.1.0"
1929 license = "MIT"
1930 description = "foo"
1931 homepage = "foo"
1932 "#,
1933 )
1934 .file("src/lib.rs", "pub mod con;\npub mod aux;")
1935 .file("src/con.rs", "pub fn f() {}")
1936 .file("src/aux/mod.rs", "pub fn f() {}")
1937 .build();
1938
1939 p.cargo("package")
6fa0f01d
WL
1940 // use unordered here because the order of the warning is different on each platform.
1941 .with_stderr_unordered(
2a874aa5
EH
1942 "\
1943[WARNING] file src/aux/mod.rs is a reserved Windows filename, it will not work on Windows platforms
1944[WARNING] file src/con.rs is a reserved Windows filename, it will not work on Windows platforms
1945[PACKAGING] foo [..]
1946[VERIFYING] foo [..]
1947[COMPILING] foo [..]
1948[FINISHED] [..]
1949",
1950 )
1951 .run();
1952}
1232ad3c
EH
1953
1954#[cargo_test]
1955fn finds_git_in_parent() {
1956 // Test where `Cargo.toml` is not in the root of the git repo.
1957 let repo_path = paths::root().join("repo");
1958 fs::create_dir(&repo_path).unwrap();
1959 let p = project()
1960 .at("repo/foo")
1961 .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
1962 .file("src/lib.rs", "")
1963 .build();
1964 let repo = git::init(&repo_path);
1965 git::add(&repo);
1966 git::commit(&repo);
1967 p.change_file("ignoreme", "");
1968 p.change_file("ignoreme2", "");
1969 p.cargo("package --list --allow-dirty")
1970 .with_stdout(
1971 "\
1972Cargo.toml
1973Cargo.toml.orig
1974ignoreme
1975ignoreme2
1976src/lib.rs
1977",
1978 )
1979 .run();
1980
1981 p.change_file(".gitignore", "ignoreme");
1982 p.cargo("package --list --allow-dirty")
1983 .with_stdout(
1984 "\
1985.gitignore
1986Cargo.toml
1987Cargo.toml.orig
1988ignoreme2
1989src/lib.rs
1990",
1991 )
1992 .run();
1993
1994 fs::write(repo_path.join(".gitignore"), "ignoreme2").unwrap();
1995 p.cargo("package --list --allow-dirty")
1996 .with_stdout(
1997 "\
1998.gitignore
1999Cargo.toml
2000Cargo.toml.orig
2001src/lib.rs
2002",
2003 )
2004 .run();
2005}
2c671115
HBA
2006
2007#[cargo_test]
2008#[cfg(windows)]
2009fn reserved_windows_name() {
2010 Package::new("bar", "1.0.0")
2011 .file("src/lib.rs", "pub mod aux;")
2012 .file("src/aux.rs", "")
2013 .publish();
2014
2015 let p = project()
2016 .file(
2017 "Cargo.toml",
2018 r#"
6f8c7d5a
EH
2019 [project]
2020 name = "foo"
2021 version = "0.0.1"
2022 authors = []
2023 license = "MIT"
2024 description = "foo"
2c671115 2025
6f8c7d5a
EH
2026 [dependencies]
2027 bar = "1.0.0"
2028 "#,
2c671115
HBA
2029 )
2030 .file("src/main.rs", "extern crate bar;\nfn main() { }")
2031 .build();
2032 p.cargo("package")
2033 .with_status(101)
2034 .with_stderr_contains(
2035 "\
2036error: failed to verify package tarball
2037
2038Caused by:
2039 failed to download replaced source registry `[..]`
2040
2041Caused by:
2042 failed to unpack package `[..] `[..]`)`
2043
2044Caused by:
2045 failed to unpack entry at `[..]aux.rs`
2046
2047Caused by:
2048 `[..]aux.rs` appears to contain a reserved Windows path, it cannot be extracted on Windows
2049
2050Caused by:
2051 failed to unpack `[..]aux.rs`
2052
2053Caused by:
2054 failed to unpack `[..]aux.rs` into `[..]aux.rs`",
2055 )
2056 .run();
2057}
156c6512
EH
2058
2059#[cargo_test]
2060fn list_with_path_and_lock() {
2061 // Allow --list even for something that isn't packageable.
2062
2063 // Init an empty registry because a versionless path dep will search for
2064 // the package on crates.io.
2065 registry::init();
2066 let p = project()
2067 .file(
2068 "Cargo.toml",
2069 r#"
2070 [package]
2071 name = "foo"
2072 version = "0.1.0"
2073 license = "MIT"
2074 description = "foo"
2075 homepage = "foo"
2076
2077 [dependencies]
2078 bar = {path="bar"}
2079 "#,
2080 )
2081 .file("src/main.rs", "fn main() {}")
2082 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
2083 .file("bar/src/lib.rs", "")
2084 .build();
2085
2086 p.cargo("package --list")
2087 .with_stdout(
2088 "\
2089Cargo.lock
2090Cargo.toml
2091Cargo.toml.orig
2092src/main.rs
2093",
2094 )
2095 .run();
2096
2097 p.cargo("package")
2098 .with_status(101)
2099 .with_stderr(
2100 "\
4e1910d9
B
2101[ERROR] all dependencies must have a version specified when packaging.
2102dependency `bar` does not specify a version
2103Note: The packaged dependency will use the version from crates.io,
2104the `path` specification will be removed from the dependency declaration.
156c6512
EH
2105",
2106 )
2107 .run();
2108}
0dfd4a88
MP
2109
2110#[cargo_test]
2111fn long_file_names() {
2112 // Filenames over 100 characters require a GNU extension tarfile.
2113 // See #8453.
2114
2115 registry::init();
2116 let long_name = concat!(
2117 "012345678901234567890123456789012345678901234567890123456789",
2118 "012345678901234567890123456789012345678901234567890123456789",
2119 "012345678901234567890123456789012345678901234567890123456789"
2120 );
35758d2c
EH
2121 if cfg!(windows) {
2122 // Long paths on Windows require a special registry entry that is
2123 // disabled by default (even on Windows 10).
2124 // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
2125 // If the directory where Cargo runs happens to be more than 80 characters
2126 // long, then it will bump into this limit.
2127 //
2128 // First create a directory to account for various paths Cargo will
2129 // be using in the target directory (such as "target/package/foo-0.1.0").
2130 let test_path = paths::root().join("test-dir-probe-long-path-support");
2131 test_path.mkdir_p();
2132 let test_path = test_path.join(long_name);
2133 if let Err(e) = File::create(&test_path) {
f23b9119
MK
2134 // write to stderr directly to avoid output from being captured
2135 // and always display text, even without --nocapture
35758d2c
EH
2136 use std::io::Write;
2137 writeln!(
2138 std::io::stderr(),
2139 "\nSkipping long_file_names test, this OS or filesystem does not \
2140 appear to support long file paths: {:?}\n{:?}",
2141 e,
2142 test_path
2143 )
2144 .unwrap();
2145 return;
2146 }
2147 }
2148
0dfd4a88
MP
2149 let p = project()
2150 .file(
2151 "Cargo.toml",
2152 r#"
2153 [package]
2154 name = "foo"
2155 version = "0.1.0"
2156 license = "MIT"
2157 description = "foo"
2158 homepage = "foo"
2159
2160 [dependencies]
2161 "#,
2162 )
2163 .file(long_name, "something")
2164 .file("src/main.rs", "fn main() {}")
2165 .build();
2166
2167 p.cargo("package").run();
2168 p.cargo("package --list")
2169 .with_stdout(&format!(
2170 "\
2171{}
2172Cargo.lock
2173Cargo.toml
2174Cargo.toml.orig
2175src/main.rs
2176",
2177 long_name
2178 ))
2179 .run();
2180}
e46ca84b 2181
2182#[cargo_test]
2183fn reproducible_output() {
2184 let p = project()
2185 .file(
2186 "Cargo.toml",
2187 r#"
2188 [project]
2189 name = "foo"
2190 version = "0.0.1"
2191 authors = []
2192 exclude = ["*.txt"]
2193 license = "MIT"
2194 description = "foo"
2195 "#,
2196 )
2197 .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
2198 .build();
2199
449ead05 2200 p.cargo("package").run();
e46ca84b 2201 assert!(p.root().join("target/package/foo-0.0.1.crate").is_file());
2202
2203 let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
2204 let decoder = GzDecoder::new(f);
2205 let mut archive = Archive::new(decoder);
2206 for ent in archive.entries().unwrap() {
2207 let ent = ent.unwrap();
a02b6e5b 2208 println!("checking {:?}", ent.path());
e46ca84b 2209 let header = ent.header();
2210 assert_eq!(header.mode().unwrap(), 0o644);
a02b6e5b 2211 assert!(header.mtime().unwrap() != 0);
449ead05 2212 assert_eq!(header.username().unwrap().unwrap(), "");
2213 assert_eq!(header.groupname().unwrap().unwrap(), "");
e46ca84b 2214 }
2215}
6bc74556
AC
2216
2217#[cargo_test]
2218fn package_with_resolver_and_metadata() {
2219 let p = project()
2220 .file(
2221 "Cargo.toml",
2222 r#"
2223 [package]
2224 name = "foo"
2225 version = "0.0.1"
2226 authors = []
2227 resolver = '2'
2228
2229 [package.metadata.docs.rs]
2230 all-features = true
2231 "#,
2232 )
2233 .file("src/lib.rs", "")
2234 .build();
2235
2236 p.cargo("package").run();
2237}
97a13504
EH
2238
2239#[cargo_test]
2240fn deleted_git_working_tree() {
2241 // When deleting a file, but not staged, cargo should ignore the file.
2242 let (p, repo) = git::new_repo("foo", |p| {
2243 p.file("src/lib.rs", "").file("src/main.rs", "fn main() {}")
2244 });
2245 p.root().join("src/lib.rs").rm_rf();
2246 p.cargo("package --allow-dirty --list")
2247 .with_stdout(
2248 "\
2249Cargo.lock
2250Cargo.toml
2251Cargo.toml.orig
2252src/main.rs
2253",
2254 )
2255 .run();
2256 p.cargo("package --allow-dirty").run();
2257 let mut index = t!(repo.index());
2258 t!(index.remove(Path::new("src/lib.rs"), 0));
2259 t!(index.write());
2260 p.cargo("package --allow-dirty --list")
2261 .with_stdout(
2262 "\
2263Cargo.lock
2264Cargo.toml
2265Cargo.toml.orig
2266src/main.rs
2267",
2268 )
2269 .run();
2270 p.cargo("package --allow-dirty").run();
2271}
8f1f0e40 2272
2273#[cargo_test]
2274fn in_workspace() {
2275 let p = project()
2276 .file(
2277 "Cargo.toml",
2278 r#"
2279 [project]
2280 name = "foo"
2281 version = "0.0.1"
2282 authors = []
2283 license = "MIT"
2284 description = "foo"
2285
2286 [workspace]
2287 members = ["bar"]
2288 "#,
2289 )
2290 .file("src/main.rs", "fn main() {}")
2291 .file(
2292 "bar/Cargo.toml",
2293 r#"
2294 [project]
2295 name = "bar"
2296 version = "0.0.1"
2297 authors = []
2298 license = "MIT"
2299 description = "bar"
2300 workspace = ".."
2301 "#,
2302 )
2303 .file("bar/src/main.rs", "fn main() {}")
2304 .build();
2305
2306 p.cargo("package --workspace")
2307 .with_stderr(
2308 "\
2309[WARNING] manifest has no documentation, [..]
2310See [..]
2311[PACKAGING] bar v0.0.1 ([CWD]/bar)
2312[VERIFYING] bar v0.0.1 ([CWD]/bar)
2313[COMPILING] bar v0.0.1 ([CWD][..])
2314[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2315[WARNING] manifest has no documentation, [..]
2316See [..]
2317[PACKAGING] foo v0.0.1 ([CWD])
2318[VERIFYING] foo v0.0.1 ([CWD])
2319[COMPILING] foo v0.0.1 ([CWD][..])
2320[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2321",
2322 )
2323 .run();
2324
2325 assert!(p.root().join("target/package/foo-0.0.1.crate").is_file());
2326 assert!(p.root().join("target/package/bar-0.0.1.crate").is_file());
2327}