]> git.proxmox.com Git - cargo.git/blame - tests/testsuite/publish.rs
Add RegistryBuilder to help initializing test registries.
[cargo.git] / tests / testsuite / publish.rs
CommitLineData
83571aee
EH
1//! Tests for the `cargo publish` command.
2
9115b2c3
AC
3use cargo_test_support::git::{self, repo};
4use cargo_test_support::paths;
5use cargo_test_support::registry::{self, registry_path, registry_url, Package};
7a5f0369 6use cargo_test_support::{basic_manifest, no_such_file_err_msg, project, publish};
4ae79d2f 7use std::fs;
3d84d0ad
EH
8
9const CLEAN_FOO_JSON: &str = r#"
10 {
11 "authors": [],
12 "badges": {},
13 "categories": [],
14 "deps": [],
15 "description": "foo",
16 "documentation": "foo",
17 "features": {},
18 "homepage": "foo",
19 "keywords": [],
20 "license": "MIT",
21 "license_file": null,
22 "links": null,
23 "name": "foo",
24 "readme": null,
25 "readme_file": null,
26 "repository": "foo",
27 "vers": "0.0.1"
28 }
29"#;
30
31fn validate_upload_foo() {
32 publish::validate_upload(
33 r#"
34 {
35 "authors": [],
36 "badges": {},
37 "categories": [],
38 "deps": [],
39 "description": "foo",
40 "documentation": null,
41 "features": {},
42 "homepage": null,
43 "keywords": [],
44 "license": "MIT",
45 "license_file": null,
46 "links": null,
47 "name": "foo",
48 "readme": null,
49 "readme_file": null,
50 "repository": null,
51 "vers": "0.0.1"
52 }
53 "#,
54 "foo-0.0.1.crate",
34307c61 55 &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
3d84d0ad
EH
56 );
57}
58
59fn validate_upload_foo_clean() {
60 publish::validate_upload(
61 CLEAN_FOO_JSON,
62 "foo-0.0.1.crate",
63 &[
34307c61 64 "Cargo.lock",
3d84d0ad
EH
65 "Cargo.toml",
66 "Cargo.toml.orig",
67 "src/main.rs",
68 ".cargo_vcs_info.json",
69 ],
70 );
71}
eccdcae0 72
0e0d9688 73#[cargo_test]
6950bbb0 74fn simple() {
b5144c7f 75 registry::init();
6950bbb0 76
7fe2fbc8 77 let p = project()
1e682848
AC
78 .file(
79 "Cargo.toml",
80 r#"
6f8c7d5a
EH
81 [project]
82 name = "foo"
83 version = "0.0.1"
84 authors = []
85 license = "MIT"
86 description = "foo"
87 "#,
fecb7246
AC
88 )
89 .file("src/main.rs", "fn main() {}")
d43ee1dd 90 .build();
ce9e47ac 91
b4c37403 92 p.cargo("publish --no-verify --token sekrit")
85984a87 93 .with_stderr(&format!(
1e682848 94 "\
41aa6fba 95[UPDATING] `{reg}` index
ce9e47ac
NB
96[WARNING] manifest has no documentation, [..]
97See [..]
89f43938
ZL
98[PACKAGING] foo v0.0.1 ([CWD])
99[UPLOADING] foo v0.0.1 ([CWD])
5cb5e7d8 100",
b5144c7f 101 reg = registry::registry_path().to_str().unwrap()
fecb7246
AC
102 ))
103 .run();
5cb5e7d8 104
3d84d0ad 105 validate_upload_foo();
5cb5e7d8
SF
106}
107
0e0d9688 108#[cargo_test]
5cb5e7d8 109fn old_token_location() {
b5144c7f
EH
110 // Check that the `token` key works at the root instead of under a
111 // `[registry]` table.
112 registry::init();
5cb5e7d8 113
7fe2fbc8 114 let p = project()
1e682848
AC
115 .file(
116 "Cargo.toml",
117 r#"
6f8c7d5a
EH
118 [project]
119 name = "foo"
120 version = "0.0.1"
121 authors = []
122 license = "MIT"
123 description = "foo"
124 "#,
fecb7246
AC
125 )
126 .file("src/main.rs", "fn main() {}")
5cb5e7d8
SF
127 .build();
128
b5144c7f
EH
129 let credentials = paths::home().join(".cargo/credentials");
130 fs::remove_file(&credentials).unwrap();
131
132 // Verify can't publish without a token.
b4c37403 133 p.cargo("publish --no-verify")
b5144c7f 134 .with_status(101)
b4c37403
EH
135 .with_stderr_contains(
136 "[ERROR] no upload token found, \
137 please run `cargo login` or pass `--token`",
138 )
b5144c7f
EH
139 .run();
140
4ae79d2f 141 fs::write(&credentials, r#"token = "api-token""#).unwrap();
b5144c7f 142
b4c37403 143 p.cargo("publish --no-verify")
85984a87 144 .with_stderr(&format!(
1e682848 145 "\
41aa6fba 146[UPDATING] `{reg}` index
65274ea7
EH
147[WARNING] using `registry.token` config value with source replacement is deprecated
148This may become a hard error in the future[..]
149Use the --token command-line flag to remove this warning.
5cb5e7d8
SF
150[WARNING] manifest has no documentation, [..]
151See [..]
89f43938
ZL
152[PACKAGING] foo v0.0.1 ([CWD])
153[UPLOADING] foo v0.0.1 ([CWD])
ce9e47ac 154",
b5144c7f 155 reg = registry_path().to_str().unwrap()
fecb7246
AC
156 ))
157 .run();
ce9e47ac 158
3d84d0ad 159 validate_upload_foo();
ce9e47ac
NB
160}
161
78e64de9
NB
162// TODO: Deprecated
163// remove once it has been decided --host can be removed
0e0d9688 164#[cargo_test]
ce9e47ac 165fn simple_with_host() {
b5144c7f 166 registry::init();
ce9e47ac 167
7fe2fbc8 168 let p = project()
1e682848
AC
169 .file(
170 "Cargo.toml",
171 r#"
6f8c7d5a
EH
172 [project]
173 name = "foo"
174 version = "0.0.1"
175 authors = []
176 license = "MIT"
177 description = "foo"
178 "#,
fecb7246
AC
179 )
180 .file("src/main.rs", "fn main() {}")
d43ee1dd 181 .build();
eccdcae0 182
b4c37403 183 p.cargo("publish --no-verify --token sekrit --host")
b5144c7f 184 .arg(registry_url().to_string())
85984a87 185 .with_stderr(&format!(
1e682848 186 "\
ce9e47ac
NB
187[WARNING] The flag '--host' is no longer valid.
188
189Previous versions of Cargo accepted this flag, but it is being
190deprecated. The flag is being renamed to 'index', as the flag
444101a6 191wants the location of the index. Please use '--index' instead.
fba459d2
NB
192
193This will soon become a hard error, so it's either recommended
194to update to a fixed version or contact the upstream maintainer
195about this warning.
41aa6fba 196[UPDATING] `{reg}` index
fba459d2
NB
197[WARNING] manifest has no documentation, [..]
198See [..]
89f43938
ZL
199[PACKAGING] foo v0.0.1 ([CWD])
200[UPLOADING] foo v0.0.1 ([CWD])
fba459d2 201",
b5144c7f 202 reg = registry_path().to_str().unwrap()
fecb7246
AC
203 ))
204 .run();
fba459d2 205
3d84d0ad 206 validate_upload_foo();
fba459d2
NB
207}
208
78e64de9
NB
209// TODO: Deprecated
210// remove once it has been decided --host can be removed
0e0d9688 211#[cargo_test]
fba459d2 212fn simple_with_index_and_host() {
b5144c7f 213 registry::init();
fba459d2 214
7fe2fbc8 215 let p = project()
1e682848
AC
216 .file(
217 "Cargo.toml",
218 r#"
6f8c7d5a
EH
219 [project]
220 name = "foo"
221 version = "0.0.1"
222 authors = []
223 license = "MIT"
224 description = "foo"
225 "#,
fecb7246
AC
226 )
227 .file("src/main.rs", "fn main() {}")
d43ee1dd 228 .build();
fba459d2 229
b4c37403 230 p.cargo("publish --no-verify --token sekrit --index")
b5144c7f 231 .arg(registry_url().to_string())
85984a87 232 .arg("--host")
b5144c7f 233 .arg(registry_url().to_string())
85984a87 234 .with_stderr(&format!(
1e682848 235 "\
fba459d2
NB
236[WARNING] The flag '--host' is no longer valid.
237
238Previous versions of Cargo accepted this flag, but it is being
239deprecated. The flag is being renamed to 'index', as the flag
444101a6 240wants the location of the index. Please use '--index' instead.
ce9e47ac
NB
241
242This will soon become a hard error, so it's either recommended
243to update to a fixed version or contact the upstream maintainer
244about this warning.
41aa6fba 245[UPDATING] `{reg}` index
1c991f83 246[WARNING] manifest has no documentation, [..]
32275465 247See [..]
89f43938
ZL
248[PACKAGING] foo v0.0.1 ([CWD])
249[UPLOADING] foo v0.0.1 ([CWD])
eccdcae0 250",
b5144c7f 251 reg = registry_path().to_str().unwrap()
fecb7246
AC
252 ))
253 .run();
eccdcae0 254
3d84d0ad 255 validate_upload_foo();
6950bbb0
AC
256}
257
0e0d9688 258#[cargo_test]
6950bbb0 259fn git_deps() {
b5144c7f 260 registry::init();
eccdcae0 261
7fe2fbc8 262 let p = project()
1e682848
AC
263 .file(
264 "Cargo.toml",
265 r#"
6f8c7d5a
EH
266 [project]
267 name = "foo"
268 version = "0.0.1"
269 authors = []
270 license = "MIT"
271 description = "foo"
eccdcae0 272
6f8c7d5a
EH
273 [dependencies.foo]
274 git = "git://path/to/nowhere"
275 "#,
fecb7246
AC
276 )
277 .file("src/main.rs", "fn main() {}")
d43ee1dd 278 .build();
eccdcae0 279
b4c37403 280 p.cargo("publish -v --no-verify --token sekrit")
85984a87
DW
281 .with_status(101)
282 .with_stderr(
1e682848 283 "\
41aa6fba 284[UPDATING] [..] index
d682439b
EH
285[ERROR] all dependencies must have a version specified when publishing.
286dependency `foo` does not specify a version
287Note: The published dependency will use the version from crates.io,
288the `git` specification will be removed from the dependency declaration.
1e682848 289",
fecb7246
AC
290 )
291 .run();
6950bbb0
AC
292}
293
0e0d9688 294#[cargo_test]
6950bbb0 295fn path_dependency_no_version() {
b5144c7f 296 registry::init();
9fba127e 297
7fe2fbc8 298 let p = project()
1e682848
AC
299 .file(
300 "Cargo.toml",
301 r#"
6f8c7d5a
EH
302 [project]
303 name = "foo"
304 version = "0.0.1"
305 authors = []
306 license = "MIT"
307 description = "foo"
9fba127e 308
6f8c7d5a
EH
309 [dependencies.bar]
310 path = "bar"
311 "#,
fecb7246
AC
312 )
313 .file("src/main.rs", "fn main() {}")
ab19c483 314 .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
d43ee1dd
NK
315 .file("bar/src/lib.rs", "")
316 .build();
eccdcae0 317
b4c37403 318 p.cargo("publish --token sekrit")
85984a87
DW
319 .with_status(101)
320 .with_stderr(
1e682848 321 "\
41aa6fba 322[UPDATING] [..] index
d682439b 323[ERROR] all dependencies must have a version specified when publishing.
9fba127e 324dependency `bar` does not specify a version
d682439b
EH
325Note: The published dependency will use the version from crates.io,
326the `path` specification will be removed from the dependency declaration.
1e682848 327",
fecb7246
AC
328 )
329 .run();
6950bbb0
AC
330}
331
0e0d9688 332#[cargo_test]
6950bbb0 333fn unpublishable_crate() {
b5144c7f 334 registry::init();
d28f8bb0 335
7fe2fbc8 336 let p = project()
1e682848
AC
337 .file(
338 "Cargo.toml",
339 r#"
6f8c7d5a
EH
340 [project]
341 name = "foo"
342 version = "0.0.1"
343 authors = []
344 license = "MIT"
345 description = "foo"
346 publish = false
347 "#,
fecb7246
AC
348 )
349 .file("src/main.rs", "fn main() {}")
d43ee1dd 350 .build();
d28f8bb0 351
85984a87 352 p.cargo("publish --index")
b5144c7f 353 .arg(registry_url().to_string())
85984a87
DW
354 .with_status(101)
355 .with_stderr(
1e682848 356 "\
bf23a7e4
EH
357[ERROR] `foo` cannot be published.
358The registry `crates-io` is not listed in the `publish` value in Cargo.toml.
1e682848 359",
fecb7246
AC
360 )
361 .run();
6950bbb0 362}
088d14ad 363
0e0d9688 364#[cargo_test]
088d14ad 365fn dont_publish_dirty() {
b5144c7f 366 registry::init();
7fe2fbc8 367 let p = project().file("bar", "").build();
088d14ad 368
d682439b 369 let _ = git::repo(&paths::root().join("foo"))
1e682848
AC
370 .file(
371 "Cargo.toml",
372 r#"
6f8c7d5a
EH
373 [project]
374 name = "foo"
375 version = "0.0.1"
376 authors = []
377 license = "MIT"
378 description = "foo"
379 documentation = "foo"
380 homepage = "foo"
381 repository = "foo"
382 "#,
fecb7246
AC
383 )
384 .file("src/main.rs", "fn main() {}")
088d14ad
AC
385 .build();
386
b4c37403 387 p.cargo("publish --token sekrit")
85984a87
DW
388 .with_status(101)
389 .with_stderr(
1e682848 390 "\
41aa6fba 391[UPDATING] `[..]` index
ca1acc57
JL
392error: 1 files in the working directory contain changes that were not yet \
393committed into git:
088d14ad
AC
394
395bar
396
34f2d471 397to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag
1e682848 398",
fecb7246
AC
399 )
400 .run();
088d14ad
AC
401}
402
0e0d9688 403#[cargo_test]
088d14ad 404fn publish_clean() {
b5144c7f 405 registry::init();
088d14ad 406
7fe2fbc8 407 let p = project().build();
5e8eef97 408
d43ee1dd 409 let _ = repo(&paths::root().join("foo"))
1e682848
AC
410 .file(
411 "Cargo.toml",
412 r#"
6f8c7d5a
EH
413 [project]
414 name = "foo"
415 version = "0.0.1"
416 authors = []
417 license = "MIT"
418 description = "foo"
419 documentation = "foo"
420 homepage = "foo"
421 repository = "foo"
422 "#,
fecb7246
AC
423 )
424 .file("src/main.rs", "fn main() {}")
088d14ad
AC
425 .build();
426
b4c37403 427 p.cargo("publish --token sekrit").run();
3d84d0ad
EH
428
429 validate_upload_foo_clean();
088d14ad
AC
430}
431
0e0d9688 432#[cargo_test]
088d14ad 433fn publish_in_sub_repo() {
b5144c7f 434 registry::init();
088d14ad 435
252f6e8e 436 let p = project().no_manifest().file("baz", "").build();
5e8eef97 437
d43ee1dd 438 let _ = repo(&paths::root().join("foo"))
1e682848
AC
439 .file(
440 "bar/Cargo.toml",
441 r#"
6f8c7d5a
EH
442 [project]
443 name = "foo"
444 version = "0.0.1"
445 authors = []
446 license = "MIT"
447 description = "foo"
448 documentation = "foo"
449 homepage = "foo"
450 repository = "foo"
451 "#,
fecb7246
AC
452 )
453 .file("bar/src/main.rs", "fn main() {}")
088d14ad
AC
454 .build();
455
b4c37403 456 p.cargo("publish --token sekrit").cwd("bar").run();
3d84d0ad
EH
457
458 validate_upload_foo_clean();
088d14ad
AC
459}
460
0e0d9688 461#[cargo_test]
088d14ad 462fn publish_when_ignored() {
b5144c7f 463 registry::init();
088d14ad 464
7fe2fbc8 465 let p = project().file("baz", "").build();
5e8eef97 466
d43ee1dd 467 let _ = repo(&paths::root().join("foo"))
1e682848
AC
468 .file(
469 "Cargo.toml",
470 r#"
6f8c7d5a
EH
471 [project]
472 name = "foo"
473 version = "0.0.1"
474 authors = []
475 license = "MIT"
476 description = "foo"
477 documentation = "foo"
478 homepage = "foo"
479 repository = "foo"
480 "#,
fecb7246
AC
481 )
482 .file("src/main.rs", "fn main() {}")
088d14ad
AC
483 .file(".gitignore", "baz")
484 .build();
485
b4c37403 486 p.cargo("publish --token sekrit").run();
3d84d0ad
EH
487
488 publish::validate_upload(
489 CLEAN_FOO_JSON,
490 "foo-0.0.1.crate",
491 &[
34307c61 492 "Cargo.lock",
3d84d0ad
EH
493 "Cargo.toml",
494 "Cargo.toml.orig",
495 "src/main.rs",
496 ".gitignore",
497 ".cargo_vcs_info.json",
498 ],
499 );
088d14ad
AC
500}
501
0e0d9688 502#[cargo_test]
088d14ad 503fn ignore_when_crate_ignored() {
b5144c7f 504 registry::init();
088d14ad 505
252f6e8e 506 let p = project().no_manifest().file("bar/baz", "").build();
5e8eef97 507
d43ee1dd 508 let _ = repo(&paths::root().join("foo"))
088d14ad 509 .file(".gitignore", "bar")
1e682848
AC
510 .nocommit_file(
511 "bar/Cargo.toml",
512 r#"
6f8c7d5a
EH
513 [project]
514 name = "foo"
515 version = "0.0.1"
516 authors = []
517 license = "MIT"
518 description = "foo"
519 documentation = "foo"
520 homepage = "foo"
521 repository = "foo"
522 "#,
fecb7246
AC
523 )
524 .nocommit_file("bar/src/main.rs", "fn main() {}");
b4c37403 525 p.cargo("publish --token sekrit").cwd("bar").run();
3d84d0ad
EH
526
527 publish::validate_upload(
528 CLEAN_FOO_JSON,
529 "foo-0.0.1.crate",
34307c61
EH
530 &[
531 "Cargo.lock",
532 "Cargo.toml",
533 "Cargo.toml.orig",
534 "src/main.rs",
535 "baz",
536 ],
3d84d0ad 537 );
088d14ad
AC
538}
539
0e0d9688 540#[cargo_test]
088d14ad 541fn new_crate_rejected() {
b5144c7f 542 registry::init();
088d14ad 543
7fe2fbc8 544 let p = project().file("baz", "").build();
5e8eef97 545
d43ee1dd 546 let _ = repo(&paths::root().join("foo"))
1e682848
AC
547 .nocommit_file(
548 "Cargo.toml",
549 r#"
6f8c7d5a
EH
550 [project]
551 name = "foo"
552 version = "0.0.1"
553 authors = []
554 license = "MIT"
555 description = "foo"
556 documentation = "foo"
557 homepage = "foo"
558 repository = "foo"
559 "#,
fecb7246
AC
560 )
561 .nocommit_file("src/main.rs", "fn main() {}");
b4c37403 562 p.cargo("publish --token sekrit")
85984a87 563 .with_status(101)
f58d107e
EH
564 .with_stderr_contains(
565 "[ERROR] 3 files in the working directory contain \
566 changes that were not yet committed into git:",
567 )
85984a87 568 .run();
088d14ad 569}
c05a5b4a 570
0e0d9688 571#[cargo_test]
c05a5b4a 572fn dry_run() {
b5144c7f 573 registry::init();
c05a5b4a 574
7fe2fbc8 575 let p = project()
1e682848
AC
576 .file(
577 "Cargo.toml",
578 r#"
6f8c7d5a
EH
579 [project]
580 name = "foo"
581 version = "0.0.1"
582 authors = []
583 license = "MIT"
584 description = "foo"
585 "#,
fecb7246
AC
586 )
587 .file("src/main.rs", "fn main() {}")
d43ee1dd 588 .build();
c05a5b4a 589
85984a87 590 p.cargo("publish --dry-run --index")
b5144c7f 591 .arg(registry_url().to_string())
2cd9cce6 592 .with_stderr(
1e682848 593 "\
41aa6fba 594[UPDATING] `[..]` index
c05a5b4a 595[WARNING] manifest has no documentation, [..]
32275465 596See [..]
89f43938
ZL
597[PACKAGING] foo v0.0.1 ([CWD])
598[VERIFYING] foo v0.0.1 ([CWD])
c05a5b4a 599[COMPILING] foo v0.0.1 [..]
34628b65 600[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
89f43938 601[UPLOADING] foo v0.0.1 ([CWD])
c05a5b4a
WM
602[WARNING] aborting upload due to dry run
603",
fecb7246
AC
604 )
605 .run();
c05a5b4a
WM
606
607 // Ensure the API request wasn't actually made
b5144c7f
EH
608 assert!(registry::api_path().join("api/v1/crates").exists());
609 assert!(!registry::api_path().join("api/v1/crates/new").exists());
c05a5b4a 610}
345c03d4 611
0e0d9688 612#[cargo_test]
caf7681f 613fn registry_not_in_publish_list() {
b5144c7f 614 registry::init();
345c03d4 615
7fe2fbc8 616 let p = project()
1e682848
AC
617 .file(
618 "Cargo.toml",
619 r#"
6f8c7d5a
EH
620 [project]
621 name = "foo"
622 version = "0.0.1"
623 authors = []
624 license = "MIT"
625 description = "foo"
626 publish = [
627 "test"
628 ]
629 "#,
fecb7246
AC
630 )
631 .file("src/main.rs", "fn main() {}")
caf7681f 632 .build();
345c03d4 633
85984a87 634 p.cargo("publish")
85984a87
DW
635 .arg("--registry")
636 .arg("alternative")
85984a87
DW
637 .with_status(101)
638 .with_stderr(
1e682848 639 "\
bf23a7e4
EH
640[ERROR] `foo` cannot be published.
641The registry `alternative` is not listed in the `publish` value in Cargo.toml.
1e682848 642",
fecb7246
AC
643 )
644 .run();
345c03d4
CS
645}
646
0e0d9688 647#[cargo_test]
345c03d4 648fn publish_empty_list() {
b5144c7f 649 registry::init();
345c03d4 650
7fe2fbc8 651 let p = project()
1e682848
AC
652 .file(
653 "Cargo.toml",
654 r#"
6f8c7d5a
EH
655 [project]
656 name = "foo"
657 version = "0.0.1"
658 authors = []
659 license = "MIT"
660 description = "foo"
661 publish = []
662 "#,
fecb7246
AC
663 )
664 .file("src/main.rs", "fn main() {}")
caf7681f 665 .build();
345c03d4 666
737382d7 667 p.cargo("publish --registry alternative")
85984a87
DW
668 .with_status(101)
669 .with_stderr(
1e682848 670 "\
bf23a7e4
EH
671[ERROR] `foo` cannot be published.
672The registry `alternative` is not listed in the `publish` value in Cargo.toml.
1e682848 673",
fecb7246
AC
674 )
675 .run();
345c03d4
CS
676}
677
0e0d9688 678#[cargo_test]
caf7681f 679fn publish_allowed_registry() {
340656e2 680 registry::alt_init();
345c03d4 681
7fe2fbc8 682 let p = project().build();
345c03d4 683
caf7681f 684 let _ = repo(&paths::root().join("foo"))
1e682848
AC
685 .file(
686 "Cargo.toml",
687 r#"
6f8c7d5a
EH
688 [project]
689 name = "foo"
690 version = "0.0.1"
691 authors = []
692 license = "MIT"
693 description = "foo"
694 documentation = "foo"
695 homepage = "foo"
696 repository = "foo"
697 publish = ["alternative"]
698 "#,
fecb7246
AC
699 )
700 .file("src/main.rs", "fn main() {}")
345c03d4
CS
701 .build();
702
737382d7 703 p.cargo("publish --registry alternative").run();
3d84d0ad 704
b5144c7f
EH
705 publish::validate_alt_upload(
706 CLEAN_FOO_JSON,
707 "foo-0.0.1.crate",
708 &[
34307c61 709 "Cargo.lock",
b5144c7f
EH
710 "Cargo.toml",
711 "Cargo.toml.orig",
712 "src/main.rs",
713 ".cargo_vcs_info.json",
714 ],
715 );
345c03d4 716}
caf7681f 717
32449a70
NCA
718#[cargo_test]
719fn publish_implicitly_to_only_allowed_registry() {
340656e2 720 registry::alt_init();
32449a70
NCA
721
722 let p = project().build();
723
724 let _ = repo(&paths::root().join("foo"))
725 .file(
726 "Cargo.toml",
727 r#"
6f8c7d5a
EH
728 [project]
729 name = "foo"
730 version = "0.0.1"
731 authors = []
732 license = "MIT"
733 description = "foo"
734 documentation = "foo"
735 homepage = "foo"
736 repository = "foo"
737 publish = ["alternative"]
738 "#,
32449a70
NCA
739 )
740 .file("src/main.rs", "fn main() {}")
741 .build();
742
743 p.cargo("publish").run();
744
745 publish::validate_alt_upload(
746 CLEAN_FOO_JSON,
747 "foo-0.0.1.crate",
748 &[
749 "Cargo.lock",
750 "Cargo.toml",
751 "Cargo.toml.orig",
752 "src/main.rs",
753 ".cargo_vcs_info.json",
754 ],
755 );
756}
757
758#[cargo_test]
759fn publish_fail_with_no_registry_specified() {
760 registry::init();
761
762 let p = project().build();
763
764 let _ = repo(&paths::root().join("foo"))
765 .file(
766 "Cargo.toml",
767 r#"
6f8c7d5a
EH
768 [project]
769 name = "foo"
770 version = "0.0.1"
771 authors = []
772 license = "MIT"
773 description = "foo"
774 documentation = "foo"
775 homepage = "foo"
776 repository = "foo"
777 publish = ["alternative", "test"]
778 "#,
32449a70
NCA
779 )
780 .file("src/main.rs", "fn main() {}")
781 .build();
782
783 p.cargo("publish")
784 .with_status(101)
785 .with_stderr(
786 "\
787[ERROR] `foo` cannot be published.
788The registry `crates-io` is not listed in the `publish` value in Cargo.toml.
789",
790 )
791 .run();
792}
793
0e0d9688 794#[cargo_test]
caf7681f 795fn block_publish_no_registry() {
b5144c7f 796 registry::init();
caf7681f 797
7fe2fbc8 798 let p = project()
1e682848
AC
799 .file(
800 "Cargo.toml",
801 r#"
6f8c7d5a
EH
802 [project]
803 name = "foo"
804 version = "0.0.1"
805 authors = []
806 license = "MIT"
807 description = "foo"
808 publish = []
809 "#,
fecb7246
AC
810 )
811 .file("src/main.rs", "fn main() {}")
caf7681f
CS
812 .build();
813
737382d7 814 p.cargo("publish --registry alternative")
85984a87
DW
815 .with_status(101)
816 .with_stderr(
1e682848 817 "\
bf23a7e4
EH
818[ERROR] `foo` cannot be published.
819The registry `alternative` is not listed in the `publish` value in Cargo.toml.
1e682848 820",
fecb7246
AC
821 )
822 .run();
caf7681f 823}
142bafb7 824
0e0d9688 825#[cargo_test]
bf23a7e4
EH
826fn publish_with_crates_io_explicit() {
827 // Explicitly setting `crates-io` in the publish list.
828 registry::init();
829
830 let p = project()
831 .file(
832 "Cargo.toml",
833 r#"
6f8c7d5a
EH
834 [project]
835 name = "foo"
836 version = "0.0.1"
837 authors = []
838 license = "MIT"
839 description = "foo"
840 publish = ["crates-io"]
841 "#,
bf23a7e4
EH
842 )
843 .file("src/main.rs", "fn main() {}")
844 .build();
845
846 p.cargo("publish --registry alternative")
847 .with_status(101)
848 .with_stderr(
849 "\
850[ERROR] `foo` cannot be published.
851The registry `alternative` is not listed in the `publish` value in Cargo.toml.
852",
853 )
854 .run();
855
856 p.cargo("publish").run();
857}
858
0e0d9688 859#[cargo_test]
142bafb7 860fn publish_with_select_features() {
b5144c7f 861 registry::init();
142bafb7
KF
862
863 let p = project()
864 .file(
865 "Cargo.toml",
866 r#"
6f8c7d5a
EH
867 [project]
868 name = "foo"
869 version = "0.0.1"
870 authors = []
871 license = "MIT"
872 description = "foo"
142bafb7 873
6f8c7d5a
EH
874 [features]
875 required = []
876 optional = []
877 "#,
40cca805
KF
878 )
879 .file(
142bafb7 880 "src/main.rs",
8c3bf82f 881 "#[cfg(not(feature = \"required\"))]
142bafb7
KF
882 compile_error!(\"This crate requires `required` feature!\");
883 fn main() {}",
8c3bf82f
KF
884 )
885 .build();
142bafb7 886
b4c37403 887 p.cargo("publish --features required --token sekrit")
8c3bf82f
KF
888 .with_stderr_contains("[UPLOADING] foo v0.0.1 ([CWD])")
889 .run();
142bafb7
KF
890}
891
0e0d9688 892#[cargo_test]
142bafb7 893fn publish_with_all_features() {
b5144c7f 894 registry::init();
142bafb7
KF
895
896 let p = project()
897 .file(
898 "Cargo.toml",
899 r#"
6f8c7d5a
EH
900 [project]
901 name = "foo"
902 version = "0.0.1"
903 authors = []
904 license = "MIT"
905 description = "foo"
142bafb7 906
6f8c7d5a
EH
907 [features]
908 required = []
909 optional = []
910 "#,
40cca805
KF
911 )
912 .file(
142bafb7 913 "src/main.rs",
8c3bf82f 914 "#[cfg(not(feature = \"required\"))]
142bafb7
KF
915 compile_error!(\"This crate requires `required` feature!\");
916 fn main() {}",
8c3bf82f
KF
917 )
918 .build();
142bafb7 919
b4c37403 920 p.cargo("publish --all-features --token sekrit")
8c3bf82f
KF
921 .with_stderr_contains("[UPLOADING] foo v0.0.1 ([CWD])")
922 .run();
caf7681f 923}
b29e3796 924
0e0d9688 925#[cargo_test]
b29e3796 926fn publish_with_no_default_features() {
b5144c7f 927 registry::init();
b29e3796
KF
928
929 let p = project()
930 .file(
931 "Cargo.toml",
932 r#"
6f8c7d5a
EH
933 [project]
934 name = "foo"
935 version = "0.0.1"
936 authors = []
937 license = "MIT"
938 description = "foo"
b29e3796 939
6f8c7d5a
EH
940 [features]
941 default = ["required"]
942 required = []
943 "#,
b29e3796
KF
944 )
945 .file(
946 "src/main.rs",
947 "#[cfg(not(feature = \"required\"))]
948 compile_error!(\"This crate requires `required` feature!\");
949 fn main() {}",
950 )
951 .build();
952
b4c37403 953 p.cargo("publish --no-default-features --token sekrit")
b29e3796
KF
954 .with_stderr_contains("error: This crate requires `required` feature!")
955 .with_status(101)
956 .run();
957}
b5144c7f 958
0e0d9688 959#[cargo_test]
b5144c7f
EH
960fn publish_with_patch() {
961 Package::new("bar", "1.0.0").publish();
962
963 let p = project()
964 .file(
965 "Cargo.toml",
966 r#"
6f8c7d5a
EH
967 [project]
968 name = "foo"
969 version = "0.0.1"
970 authors = []
971 license = "MIT"
972 description = "foo"
973 [dependencies]
974 bar = "1.0"
975 [patch.crates-io]
976 bar = { path = "bar" }
977 "#,
b5144c7f 978 )
d3f7bb0a
JB
979 .file(
980 "src/main.rs",
981 "extern crate bar;
982 fn main() {
983 bar::newfunc();
984 }",
985 )
b5144c7f 986 .file("bar/Cargo.toml", &basic_manifest("bar", "1.0.0"))
d3f7bb0a 987 .file("bar/src/lib.rs", "pub fn newfunc() {}")
b5144c7f
EH
988 .build();
989
990 // Check that it works with the patched crate.
991 p.cargo("build").run();
992
d3f7bb0a 993 // Check that verify fails with patched crate which has new functionality.
b4c37403 994 p.cargo("publish --token sekrit")
d3f7bb0a 995 .with_stderr_contains("[..]newfunc[..]")
b5144c7f 996 .with_status(101)
b5144c7f 997 .run();
d3f7bb0a
JB
998
999 // Remove the usage of new functionality and try again.
1000 p.change_file("src/main.rs", "extern crate bar; pub fn main() {}");
1001
b4c37403 1002 p.cargo("publish --token sekrit").run();
d3f7bb0a
JB
1003
1004 // Note, use of `registry` in the deps here is an artifact that this
1005 // publishes to a fake, local registry that is pretending to be crates.io.
1006 // Normal publishes would set it to null.
1007 publish::validate_upload(
1008 r#"
1009 {
1010 "authors": [],
1011 "badges": {},
1012 "categories": [],
1013 "deps": [
1014 {
1015 "default_features": true,
1016 "features": [],
1017 "kind": "normal",
1018 "name": "bar",
1019 "optional": false,
1020 "registry": "https://github.com/rust-lang/crates.io-index",
1021 "target": null,
1022 "version_req": "^1.0"
1023 }
1024 ],
1025 "description": "foo",
1026 "documentation": null,
1027 "features": {},
1028 "homepage": null,
1029 "keywords": [],
1030 "license": "MIT",
1031 "license_file": null,
1032 "links": null,
1033 "name": "foo",
1034 "readme": null,
1035 "readme_file": null,
1036 "repository": null,
1037 "vers": "0.0.1"
1038 }
1039 "#,
1040 "foo-0.0.1.crate",
34307c61 1041 &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
d3f7bb0a 1042 );
b5144c7f 1043}
f7c424f3 1044
0e0d9688 1045#[cargo_test]
f7c424f3
AH
1046fn publish_checks_for_token_before_verify() {
1047 registry::init();
1048
1049 let p = project()
1050 .file(
1051 "Cargo.toml",
1052 r#"
6f8c7d5a
EH
1053 [project]
1054 name = "foo"
1055 version = "0.0.1"
1056 authors = []
1057 license = "MIT"
1058 description = "foo"
1059 "#,
f7c424f3
AH
1060 )
1061 .file("src/main.rs", "fn main() {}")
1062 .build();
1063
1064 let credentials = paths::home().join(".cargo/credentials");
1065 fs::remove_file(&credentials).unwrap();
1066
1067 // Assert upload token error before the package is verified
1068 p.cargo("publish")
1069 .with_status(101)
b4c37403
EH
1070 .with_stderr_contains(
1071 "[ERROR] no upload token found, \
1072 please run `cargo login` or pass `--token`",
1073 )
f7c424f3
AH
1074 .with_stderr_does_not_contain("[VERIFYING] foo v0.0.1 ([CWD])")
1075 .run();
1076
1077 // Assert package verified successfully on dry run
1078 p.cargo("publish --dry-run")
1079 .with_status(0)
1080 .with_stderr_contains("[VERIFYING] foo v0.0.1 ([CWD])")
1081 .run();
1082}
cce87428
EH
1083
1084#[cargo_test]
1085fn publish_with_bad_source() {
1086 let p = project()
1087 .file(
1088 ".cargo/config",
1089 r#"
1090 [source.crates-io]
1091 replace-with = 'local-registry'
1092
1093 [source.local-registry]
1094 local-registry = 'registry'
1095 "#,
1096 )
1097 .file("src/lib.rs", "")
1098 .build();
1099
b4c37403 1100 p.cargo("publish --token sekrit")
cce87428
EH
1101 .with_status(101)
1102 .with_stderr(
1103 "\
1104[ERROR] registry `[..]/foo/registry` does not support API commands.
1105Check for a source-replacement in .cargo/config.
1106",
1107 )
1108 .run();
1109
1110 p.change_file(
1111 ".cargo/config",
1112 r#"
1113 [source.crates-io]
1114 replace-with = "vendored-sources"
1115
1116 [source.vendored-sources]
1117 directory = "vendor"
1118 "#,
1119 );
1120
b4c37403 1121 p.cargo("publish --token sekrit")
cce87428
EH
1122 .with_status(101)
1123 .with_stderr(
1124 "\
1125[ERROR] dir [..]/foo/vendor does not support API commands.
1126Check for a source-replacement in .cargo/config.
1127",
1128 )
1129 .run();
1130}
d682439b
EH
1131
1132#[cargo_test]
1133fn publish_git_with_version() {
1134 // A dependency with both `git` and `version`.
1135 Package::new("dep1", "1.0.1")
1136 .file("src/lib.rs", "pub fn f() -> i32 {1}")
1137 .publish();
1138
1139 let git_project = git::new("dep1", |project| {
1140 project
1141 .file("Cargo.toml", &basic_manifest("dep1", "1.0.0"))
1142 .file("src/lib.rs", "pub fn f() -> i32 {2}")
1143 });
1144
1145 let p = project()
1146 .file(
1147 "Cargo.toml",
1148 &format!(
1149 r#"
1150 [package]
1151 name = "foo"
1152 version = "0.1.0"
1153 authors = []
1154 edition = "2018"
1155 license = "MIT"
1156 description = "foo"
1157
1158 [dependencies]
1159 dep1 = {{version = "1.0", git="{}"}}
1160 "#,
1161 git_project.url()
1162 ),
1163 )
1164 .file(
1165 "src/main.rs",
1166 r#"
1167 pub fn main() {
1168 println!("{}", dep1::f());
1169 }
1170 "#,
1171 )
1172 .build();
1173
1174 p.cargo("run").with_stdout("2").run();
b4c37403 1175 p.cargo("publish --no-verify --token sekrit").run();
d682439b
EH
1176
1177 publish::validate_upload_with_contents(
1178 r#"
1179 {
1180 "authors": [],
1181 "badges": {},
1182 "categories": [],
1183 "deps": [
1184 {
1185 "default_features": true,
1186 "features": [],
1187 "kind": "normal",
1188 "name": "dep1",
1189 "optional": false,
1190 "registry": "https://github.com/rust-lang/crates.io-index",
1191 "target": null,
1192 "version_req": "^1.0"
1193 }
1194 ],
1195 "description": "foo",
1196 "documentation": null,
1197 "features": {},
1198 "homepage": null,
1199 "keywords": [],
1200 "license": "MIT",
1201 "license_file": null,
1202 "links": null,
1203 "name": "foo",
1204 "readme": null,
1205 "readme_file": null,
1206 "repository": null,
1207 "vers": "0.1.0"
1208 }
1209 "#,
1210 "foo-0.1.0.crate",
1211 &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
1212 &[
1213 (
1214 "Cargo.toml",
1215 // Check that only `version` is included in Cargo.toml.
1216 "[..]\n\
1217 [dependencies.dep1]\n\
1218 version = \"1.0\"\n\
1219 ",
1220 ),
1221 (
1222 "Cargo.lock",
1223 // The important check here is that it is 1.0.1 in the registry.
1224 "[..]\n\
1225 [[package]]\n\
1226 name = \"foo\"\n\
1227 version = \"0.1.0\"\n\
1228 dependencies = [\n\
366ae3f7 1229 \x20\"dep1\",\n\
d682439b
EH
1230 ]\n\
1231 [..]",
1232 ),
1233 ],
1234 );
1235}
d709c10d
EH
1236
1237#[cargo_test]
1238fn publish_dev_dep_no_version() {
1239 registry::init();
1240
1241 let p = project()
1242 .file(
1243 "Cargo.toml",
1244 r#"
1245 [package]
1246 name = "foo"
1247 version = "0.1.0"
1248 authors = []
1249 license = "MIT"
1250 description = "foo"
1251 documentation = "foo"
1252 homepage = "foo"
1253 repository = "foo"
1254
1255 [dev-dependencies]
1256 bar = { path = "bar" }
1257 "#,
1258 )
1259 .file("src/lib.rs", "")
1260 .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
1261 .file("bar/src/lib.rs", "")
1262 .build();
1263
b4c37403 1264 p.cargo("publish --no-verify --token sekrit")
d709c10d
EH
1265 .with_stderr(
1266 "\
1267[UPDATING] [..]
1268[PACKAGING] foo v0.1.0 [..]
1269[UPLOADING] foo v0.1.0 [..]
1270",
1271 )
1272 .run();
1273
e4345b2e 1274 publish::validate_upload_with_contents(
d709c10d
EH
1275 r#"
1276 {
1277 "authors": [],
1278 "badges": {},
1279 "categories": [],
1280 "deps": [],
1281 "description": "foo",
1282 "documentation": "foo",
1283 "features": {},
1284 "homepage": "foo",
1285 "keywords": [],
1286 "license": "MIT",
1287 "license_file": null,
1288 "links": null,
1289 "name": "foo",
1290 "readme": null,
1291 "readme_file": null,
1292 "repository": "foo",
1293 "vers": "0.1.0"
1294 }
1295 "#,
1296 "foo-0.1.0.crate",
1297 &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs"],
e4345b2e
EH
1298 &[(
1299 "Cargo.toml",
1300 r#"[..]
1301[package]
1302name = "foo"
1303version = "0.1.0"
1304authors = []
1305description = "foo"
1306homepage = "foo"
1307documentation = "foo"
1308license = "MIT"
1309repository = "foo"
1310
1311[dev-dependencies]
1312"#,
1313 )],
d709c10d
EH
1314 );
1315}
4b70f149
TN
1316
1317#[cargo_test]
1318fn credentials_ambiguous_filename() {
1319 registry::init();
1320
1321 let credentials_toml = paths::home().join(".cargo/credentials.toml");
8076f578 1322 fs::write(credentials_toml, r#"token = "api-token""#).unwrap();
4b70f149
TN
1323
1324 let p = project()
1325 .file(
1326 "Cargo.toml",
1327 r#"
6f8c7d5a
EH
1328 [project]
1329 name = "foo"
1330 version = "0.0.1"
1331 authors = []
1332 license = "MIT"
1333 description = "foo"
1334 "#,
4b70f149
TN
1335 )
1336 .file("src/main.rs", "fn main() {}")
1337 .build();
1338
b4c37403 1339 p.cargo("publish --no-verify --token sekrit")
4b70f149
TN
1340 .with_stderr_contains(
1341 "\
1342[WARNING] Both `[..]/credentials` and `[..]/credentials.toml` exist. Using `[..]/credentials`
1343",
1344 )
1345 .run();
1346
1347 validate_upload_foo();
1348}
b4c37403
EH
1349
1350#[cargo_test]
1351fn index_requires_token() {
1352 // --index will not load registry.token to avoid possibly leaking
1353 // crates.io token to another server.
1354 registry::init();
65274ea7
EH
1355 let credentials = paths::home().join(".cargo/credentials");
1356 fs::remove_file(&credentials).unwrap();
b4c37403
EH
1357
1358 let p = project()
1359 .file(
1360 "Cargo.toml",
1361 r#"
1362 [package]
1363 name = "foo"
1364 version = "0.0.1"
1365 authors = []
1366 license = "MIT"
1367 description = "foo"
1368 "#,
1369 )
1370 .file("src/lib.rs", "")
1371 .build();
1372
1373 p.cargo("publish --no-verify --index")
1374 .arg(registry_url().to_string())
1375 .with_status(101)
65274ea7
EH
1376 .with_stderr(
1377 "\
1378[UPDATING] [..]
1379[ERROR] command-line argument --index requires --token to be specified
1380",
1381 )
1382 .run();
1383}
1384
1385#[cargo_test]
1386fn registry_token_with_source_replacement() {
1387 // publish with source replacement without --token
1388 registry::init();
1389
1390 let p = project()
1391 .file(
1392 "Cargo.toml",
1393 r#"
6f8c7d5a
EH
1394 [project]
1395 name = "foo"
1396 version = "0.0.1"
1397 authors = []
1398 license = "MIT"
1399 description = "foo"
1400 "#,
65274ea7
EH
1401 )
1402 .file("src/lib.rs", "")
1403 .build();
1404
1405 p.cargo("publish --no-verify")
1406 .with_stderr(
1407 "\
1408[UPDATING] [..]
1409[WARNING] using `registry.token` config value with source replacement is deprecated
1410This may become a hard error in the future[..]
1411Use the --token command-line flag to remove this warning.
1412[WARNING] manifest has no documentation, [..]
1413See [..]
1414[PACKAGING] foo v0.0.1 ([CWD])
1415[UPLOADING] foo v0.0.1 ([CWD])
1416",
1417 )
b4c37403
EH
1418 .run();
1419}
7a5f0369
EH
1420
1421#[cargo_test]
1422fn publish_with_missing_readme() {
1423 registry::init();
1424 let p = project()
1425 .file(
1426 "Cargo.toml",
1427 r#"
1428 [package]
1429 name = "foo"
1430 version = "0.1.0"
1431 authors = []
1432 license = "MIT"
1433 description = "foo"
1434 homepage = "https://example.com/"
1435 readme = "foo.md"
1436 "#,
1437 )
1438 .file("src/lib.rs", "")
1439 .build();
1440
1441 p.cargo("publish --no-verify --token sekrit")
1442 .with_status(101)
1443 .with_stderr(&format!(
1444 "\
1445[UPDATING] [..]
1446[PACKAGING] foo v0.1.0 [..]
1447[UPLOADING] foo v0.1.0 [..]
1448[ERROR] failed to read `readme` file for package `foo v0.1.0 ([ROOT]/foo)`
1449
1450Caused by:
1451 failed to read `[ROOT]/foo/foo.md`
1452
1453Caused by:
1454 {}
1455",
1456 no_such_file_err_msg()
1457 ))
1458 .run();
1459}