]> git.proxmox.com Git - rustc.git/blame - src/tools/cargo/tests/testsuite/install.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / src / tools / cargo / tests / testsuite / install.rs
CommitLineData
0a29b90c
FG
1//! Tests for the `cargo install` command.
2
3use std::fs::{self, OpenOptions};
4use std::io::prelude::*;
5use std::path::Path;
4b012472 6use std::thread;
0a29b90c
FG
7
8use cargo_test_support::compare;
9use cargo_test_support::cross_compile;
10use cargo_test_support::git;
11use cargo_test_support::registry::{self, registry_path, Package};
12use cargo_test_support::{
13 basic_manifest, cargo_process, no_such_file_err_msg, project, project_in, symlink_supported, t,
14};
4b012472 15use cargo_util::{ProcessBuilder, ProcessError};
0a29b90c
FG
16
17use cargo_test_support::install::{
4b012472 18 assert_has_installed_exe, assert_has_not_installed_exe, cargo_home, exe,
0a29b90c
FG
19};
20use cargo_test_support::paths::{self, CargoPathExt};
21use std::env;
22use std::path::PathBuf;
23
24fn pkg(name: &str, vers: &str) {
25 Package::new(name, vers)
26 .file("src/lib.rs", "")
27 .file(
28 "src/main.rs",
29 &format!("extern crate {}; fn main() {{}}", name),
30 )
31 .publish();
32}
33
34#[cargo_test]
35fn simple() {
36 pkg("foo", "0.0.1");
37
38 cargo_process("install foo")
39 .with_stderr(
40 "\
41[UPDATING] `[..]` index
42[DOWNLOADING] crates ...
43[DOWNLOADED] foo v0.0.1 (registry [..])
44[INSTALLING] foo v0.0.1
45[COMPILING] foo v0.0.1
46[FINISHED] release [optimized] target(s) in [..]
47[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
48[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)
49[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
50",
51 )
52 .run();
53 assert_has_installed_exe(cargo_home(), "foo");
54
55 cargo_process("uninstall foo")
56 .with_stderr("[REMOVING] [CWD]/home/.cargo/bin/foo[EXE]")
57 .run();
58 assert_has_not_installed_exe(cargo_home(), "foo");
59}
60
ed00b5ec
FG
61#[cargo_test]
62fn install_the_same_version_twice() {
63 pkg("foo", "0.0.1");
64
65 cargo_process("install foo foo")
66 .with_stderr(
67 "\
68[UPDATING] `[..]` index
69[DOWNLOADING] crates ...
70[DOWNLOADED] foo v0.0.1 (registry [..])
71[INSTALLING] foo v0.0.1
72[COMPILING] foo v0.0.1
73[FINISHED] release [optimized] target(s) in [..]
74[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
75[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)
76[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
77",
78 )
79 .run();
80 assert_has_installed_exe(cargo_home(), "foo");
81}
82
fe692bf9
FG
83#[cargo_test]
84fn toolchain() {
85 pkg("foo", "0.0.1");
86
87 cargo_process("install +nightly")
88 .with_status(101)
89 .with_stderr(
90 "\
91[ERROR] invalid character `+` in package name: `+nightly`
92 Use `cargo +nightly install` if you meant to use the `nightly` toolchain.",
93 )
94 .run();
95}
96
781aab86
FG
97#[cargo_test]
98fn url() {
99 pkg("foo", "0.0.1");
100 cargo_process("install https://github.com/bar/foo")
101 .with_status(101)
102 .with_stderr(
103 "\
104[ERROR] invalid package name: `https://github.com/bar/foo`
105 Use `cargo install --git https://github.com/bar/foo` if you meant to install from a git repository.")
106 .run();
107}
108
0a29b90c
FG
109#[cargo_test]
110fn simple_with_message_format() {
111 pkg("foo", "0.0.1");
112
113 cargo_process("install foo --message-format=json")
114 .with_stderr(
115 "\
116[UPDATING] `[..]` index
117[DOWNLOADING] crates ...
118[DOWNLOADED] foo v0.0.1 (registry [..])
119[INSTALLING] foo v0.0.1
120[COMPILING] foo v0.0.1
121[FINISHED] release [optimized] target(s) in [..]
122[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
123[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)
124[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
125",
126 )
127 .with_json(
128 r#"
129 {
130 "reason": "compiler-artifact",
131 "package_id": "foo 0.0.1 ([..])",
132 "manifest_path": "[..]",
133 "target": {
134 "kind": [
135 "lib"
136 ],
137 "crate_types": [
138 "lib"
139 ],
140 "name": "foo",
141 "src_path": "[..]/foo-0.0.1/src/lib.rs",
142 "edition": "2015",
143 "doc": true,
144 "doctest": true,
145 "test": true
146 },
147 "profile": "{...}",
148 "features": [],
149 "filenames": "{...}",
150 "executable": null,
151 "fresh": false
152 }
153
154 {
155 "reason": "compiler-artifact",
156 "package_id": "foo 0.0.1 ([..])",
157 "manifest_path": "[..]",
158 "target": {
159 "kind": [
160 "bin"
161 ],
162 "crate_types": [
163 "bin"
164 ],
165 "name": "foo",
166 "src_path": "[..]/foo-0.0.1/src/main.rs",
167 "edition": "2015",
168 "doc": true,
169 "doctest": false,
170 "test": true
171 },
172 "profile": "{...}",
173 "features": [],
174 "filenames": "{...}",
175 "executable": "[..]",
176 "fresh": false
177 }
178
179 {"reason":"build-finished","success":true}
180 "#,
181 )
182 .run();
183 assert_has_installed_exe(cargo_home(), "foo");
184}
185
186#[cargo_test]
187fn with_index() {
188 let registry = registry::init();
189 pkg("foo", "0.0.1");
190
191 cargo_process("install foo --index")
192 .arg(registry.index_url().as_str())
193 .with_stderr(&format!(
194 "\
195[UPDATING] `{reg}` index
196[DOWNLOADING] crates ...
197[DOWNLOADED] foo v0.0.1 (registry `{reg}`)
198[INSTALLING] foo v0.0.1 (registry `{reg}`)
199[COMPILING] foo v0.0.1 (registry `{reg}`)
200[FINISHED] release [optimized] target(s) in [..]
201[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
202[INSTALLED] package `foo v0.0.1 (registry `{reg}`)` (executable `foo[EXE]`)
203[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
204",
205 reg = registry_path().to_str().unwrap()
206 ))
207 .run();
208 assert_has_installed_exe(cargo_home(), "foo");
209
210 cargo_process("uninstall foo")
211 .with_stderr("[REMOVING] [CWD]/home/.cargo/bin/foo[EXE]")
212 .run();
213 assert_has_not_installed_exe(cargo_home(), "foo");
214}
215
216#[cargo_test]
217fn multiple_pkgs() {
218 pkg("foo", "0.0.1");
219 pkg("bar", "0.0.2");
220
221 cargo_process("install foo bar baz")
222 .with_status(101)
223 .with_stderr(
224 "\
225[UPDATING] `[..]` index
226[DOWNLOADING] crates ...
227[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)
228[DOWNLOADING] crates ...
229[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`)
230[ERROR] could not find `baz` in registry `[..]` with version `*`
231[INSTALLING] foo v0.0.1
232[COMPILING] foo v0.0.1
233[FINISHED] release [optimized] target(s) in [..]
234[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
235[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)
236[INSTALLING] bar v0.0.2
237[COMPILING] bar v0.0.2
238[FINISHED] release [optimized] target(s) in [..]
239[INSTALLING] [CWD]/home/.cargo/bin/bar[EXE]
240[INSTALLED] package `bar v0.0.2` (executable `bar[EXE]`)
241[SUMMARY] Successfully installed foo, bar! Failed to install baz (see error(s) above).
242[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
243[ERROR] some crates failed to install
244",
245 )
246 .run();
247 assert_has_installed_exe(cargo_home(), "foo");
248 assert_has_installed_exe(cargo_home(), "bar");
249
250 cargo_process("uninstall foo bar")
251 .with_stderr(
252 "\
253[REMOVING] [CWD]/home/.cargo/bin/foo[EXE]
254[REMOVING] [CWD]/home/.cargo/bin/bar[EXE]
255[SUMMARY] Successfully uninstalled foo, bar!
256",
257 )
258 .run();
259
260 assert_has_not_installed_exe(cargo_home(), "foo");
261 assert_has_not_installed_exe(cargo_home(), "bar");
262}
263
264fn path() -> Vec<PathBuf> {
265 env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect()
266}
267
268#[cargo_test]
269fn multiple_pkgs_path_set() {
270 // confirm partial failure results in 101 status code and does not have the
271 // '[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries'
272 // even if CARGO_HOME/bin is in the PATH
273 pkg("foo", "0.0.1");
274 pkg("bar", "0.0.2");
275
276 // add CARGO_HOME/bin to path
277 let mut path = path();
278 path.push(cargo_home().join("bin"));
279 let new_path = env::join_paths(path).unwrap();
280 cargo_process("install foo bar baz")
281 .env("PATH", new_path)
282 .with_status(101)
283 .with_stderr(
284 "\
285[UPDATING] `[..]` index
286[DOWNLOADING] crates ...
287[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)
288[DOWNLOADING] crates ...
289[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`)
290[ERROR] could not find `baz` in registry `[..]` with version `*`
291[INSTALLING] foo v0.0.1
292[COMPILING] foo v0.0.1
293[FINISHED] release [optimized] target(s) in [..]
294[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
295[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)
296[INSTALLING] bar v0.0.2
297[COMPILING] bar v0.0.2
298[FINISHED] release [optimized] target(s) in [..]
299[INSTALLING] [CWD]/home/.cargo/bin/bar[EXE]
300[INSTALLED] package `bar v0.0.2` (executable `bar[EXE]`)
301[SUMMARY] Successfully installed foo, bar! Failed to install baz (see error(s) above).
302[ERROR] some crates failed to install
303",
304 )
305 .run();
306 assert_has_installed_exe(cargo_home(), "foo");
307 assert_has_installed_exe(cargo_home(), "bar");
308
309 cargo_process("uninstall foo bar")
310 .with_stderr(
311 "\
312[REMOVING] [CWD]/home/.cargo/bin/foo[EXE]
313[REMOVING] [CWD]/home/.cargo/bin/bar[EXE]
314[SUMMARY] Successfully uninstalled foo, bar!
315",
316 )
317 .run();
318
319 assert_has_not_installed_exe(cargo_home(), "foo");
320 assert_has_not_installed_exe(cargo_home(), "bar");
321}
322
323#[cargo_test]
324fn pick_max_version() {
325 pkg("foo", "0.1.0");
326 pkg("foo", "0.2.0");
327 pkg("foo", "0.2.1");
328 pkg("foo", "0.2.1-pre.1");
329 pkg("foo", "0.3.0-pre.2");
330
331 cargo_process("install foo")
332 .with_stderr(
333 "\
334[UPDATING] `[..]` index
335[DOWNLOADING] crates ...
336[DOWNLOADED] foo v0.2.1 (registry [..])
337[INSTALLING] foo v0.2.1
338[COMPILING] foo v0.2.1
339[FINISHED] release [optimized] target(s) in [..]
340[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
341[INSTALLED] package `foo v0.2.1` (executable `foo[EXE]`)
342[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
343",
344 )
345 .run();
346 assert_has_installed_exe(cargo_home(), "foo");
347}
348
349#[cargo_test]
350fn installs_beta_version_by_explicit_name_from_git() {
351 let p = git::repo(&paths::root().join("foo"))
352 .file("Cargo.toml", &basic_manifest("foo", "0.3.0-beta.1"))
353 .file("src/main.rs", "fn main() {}")
354 .build();
355
356 cargo_process("install --git")
357 .arg(p.url().to_string())
358 .arg("foo")
359 .run();
360 assert_has_installed_exe(cargo_home(), "foo");
361}
362
363#[cargo_test]
364fn missing() {
365 pkg("foo", "0.0.1");
366 cargo_process("install bar")
367 .with_status(101)
368 .with_stderr(
369 "\
370[UPDATING] [..] index
371[ERROR] could not find `bar` in registry `[..]` with version `*`
372",
373 )
374 .run();
375}
376
377#[cargo_test]
378fn missing_current_working_directory() {
379 cargo_process("install .")
380 .with_status(101)
381 .with_stderr(
382 "error: To install the binaries for the package in current working \
383 directory use `cargo install --path .`. \n\
384 Use `cargo build` if you want to simply build the package.",
385 )
386 .run();
387}
388
389#[cargo_test]
390fn bad_version() {
391 pkg("foo", "0.0.1");
392 cargo_process("install foo --version=0.2.0")
393 .with_status(101)
394 .with_stderr(
395 "\
396[UPDATING] [..] index
397[ERROR] could not find `foo` in registry `[..]` with version `=0.2.0`
398",
399 )
400 .run();
401}
402
403#[cargo_test]
404fn bad_paths() {
405 cargo_process("install")
406 .with_status(101)
407 .with_stderr("[ERROR] `[CWD]` is not a crate root; specify a crate to install [..]")
408 .run();
409
410 cargo_process("install --path .")
411 .with_status(101)
412 .with_stderr("[ERROR] `[CWD]` does not contain a Cargo.toml file[..]")
413 .run();
414
415 let toml = paths::root().join("Cargo.toml");
416 fs::write(toml, "").unwrap();
417 cargo_process("install --path Cargo.toml")
418 .with_status(101)
419 .with_stderr("[ERROR] `[CWD]/Cargo.toml` is not a directory[..]")
420 .run();
421
422 cargo_process("install --path .")
423 .with_status(101)
424 .with_stderr_contains("[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`")
425 .run();
426}
427
428#[cargo_test]
429fn install_location_precedence() {
430 pkg("foo", "0.0.1");
431
432 let root = paths::root();
433 let t1 = root.join("t1");
434 let t2 = root.join("t2");
435 let t3 = root.join("t3");
436 let t4 = cargo_home();
437
438 fs::create_dir(root.join(".cargo")).unwrap();
439 fs::write(
440 root.join(".cargo/config"),
441 &format!(
442 "[install]
443 root = '{}'
444 ",
445 t3.display()
446 ),
447 )
448 .unwrap();
449
450 println!("install --root");
451
452 cargo_process("install foo --root")
453 .arg(&t1)
454 .env("CARGO_INSTALL_ROOT", &t2)
455 .run();
456 assert_has_installed_exe(&t1, "foo");
457 assert_has_not_installed_exe(&t2, "foo");
458
459 println!("install CARGO_INSTALL_ROOT");
460
461 cargo_process("install foo")
462 .env("CARGO_INSTALL_ROOT", &t2)
463 .run();
464 assert_has_installed_exe(&t2, "foo");
465 assert_has_not_installed_exe(&t3, "foo");
466
467 println!("install install.root");
468
469 cargo_process("install foo").run();
470 assert_has_installed_exe(&t3, "foo");
471 assert_has_not_installed_exe(&t4, "foo");
472
473 fs::remove_file(root.join(".cargo/config")).unwrap();
474
475 println!("install cargo home");
476
477 cargo_process("install foo").run();
478 assert_has_installed_exe(&t4, "foo");
479}
480
481#[cargo_test]
482fn install_path() {
483 let p = project().file("src/main.rs", "fn main() {}").build();
484
485 cargo_process("install --path").arg(p.root()).run();
486 assert_has_installed_exe(cargo_home(), "foo");
487 // path-style installs force a reinstall
488 p.cargo("install --path .")
489 .with_stderr(
490 "\
491[INSTALLING] foo v0.0.1 [..]
492[FINISHED] release [..]
493[REPLACING] [..]/.cargo/bin/foo[EXE]
494[REPLACED] package `foo v0.0.1 [..]` with `foo v0.0.1 [..]` (executable `foo[EXE]`)
495[WARNING] be sure to add [..]
496",
497 )
498 .run();
499}
500
501#[cargo_test]
502fn install_target_dir() {
503 let p = project().file("src/main.rs", "fn main() {}").build();
504
505 p.cargo("install --target-dir td_test")
506 .with_stderr(
507 "\
508[WARNING] Using `cargo install` [..]
509[INSTALLING] foo v0.0.1 [..]
510[COMPILING] foo v0.0.1 [..]
511[FINISHED] release [..]
512[INSTALLING] [..]foo[EXE]
513[INSTALLED] package `foo v0.0.1 [..]foo[..]` (executable `foo[EXE]`)
514[WARNING] be sure to add [..]
515",
516 )
517 .run();
518
519 let mut path = p.root();
520 path.push("td_test");
521 assert!(path.exists());
522
523 #[cfg(not(windows))]
524 path.push("release/foo");
525 #[cfg(windows)]
526 path.push("release/foo.exe");
527 assert!(path.exists());
528}
529
530#[cargo_test]
531#[cfg(target_os = "linux")]
532fn install_path_with_lowercase_cargo_toml() {
533 let toml = paths::root().join("cargo.toml");
534 fs::write(toml, "").unwrap();
535
536 cargo_process("install --path .")
537 .with_status(101)
538 .with_stderr(
539 "\
540[ERROR] `[CWD]` does not contain a Cargo.toml file, \
541but found cargo.toml please try to rename it to Cargo.toml. --path must point to a directory containing a Cargo.toml file.
542",
543 )
544 .run();
545}
546
547#[cargo_test]
548fn install_relative_path_outside_current_ws() {
549 let p = project()
550 .file(
551 "Cargo.toml",
552 r#"
553 [package]
554 name = "bar"
555 version = "0.1.0"
556 authors = []
557
558 [workspace]
559 members = ["baz"]
560 "#,
561 )
562 .file("src/main.rs", "fn main() {}")
563 .file(
564 "baz/Cargo.toml",
565 r#"
566 [package]
567 name = "baz"
568 version = "0.1.0"
569 authors = []
570 edition = "2021"
571
572 [dependencies]
573 foo = "1"
574 "#,
575 )
576 .file("baz/src/lib.rs", "")
577 .build();
578
579 let _bin_project = project_in("bar")
580 .file("src/main.rs", "fn main() {}")
581 .build();
582
583 p.cargo("install --path ../bar/foo")
584 .with_stderr(&format!(
585 "\
586[INSTALLING] foo v0.0.1 ([..]/bar/foo)
587[COMPILING] foo v0.0.1 ([..]/bar/foo)
588[FINISHED] release [..]
589[INSTALLING] {home}/bin/foo[EXE]
590[INSTALLED] package `foo v0.0.1 ([..]/bar/foo)` (executable `foo[EXE]`)
591[WARNING] be sure to add [..]
592",
593 home = cargo_home().display(),
594 ))
595 .run();
596
597 // Validate the workspace error message to display available targets.
598 p.cargo("install --path ../bar/foo --bin")
599 .with_status(101)
600 .with_stderr(
601 "\
602[ERROR] \"--bin\" takes one argument.
603Available binaries:
604 foo
605
606",
607 )
608 .run();
609}
610
611#[cargo_test]
612fn multiple_packages_containing_binaries() {
613 let p = git::repo(&paths::root().join("foo"))
614 .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
615 .file("src/main.rs", "fn main() {}")
616 .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0"))
617 .file("a/src/main.rs", "fn main() {}")
618 .build();
619
620 let git_url = p.url().to_string();
621 cargo_process("install --git")
622 .arg(p.url().to_string())
623 .with_status(101)
624 .with_stderr(format!(
625 "\
626[UPDATING] git repository [..]
627[ERROR] multiple packages with binaries found: bar, foo. \
628When installing a git repository, cargo will always search the entire repo for any Cargo.toml.
629Please specify a package, e.g. `cargo install --git {git_url} bar`.
630"
631 ))
632 .run();
633}
634
635#[cargo_test]
636fn multiple_packages_matching_example() {
637 let p = git::repo(&paths::root().join("foo"))
638 .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
639 .file("src/lib.rs", "")
640 .file("examples/ex1.rs", "fn main() {}")
641 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
642 .file("bar/src/lib.rs", "")
643 .file("bar/examples/ex1.rs", "fn main() {}")
644 .build();
645
646 let git_url = p.url().to_string();
647 cargo_process("install --example ex1 --git")
648 .arg(p.url().to_string())
649 .with_status(101)
650 .with_stderr(format!(
651 "\
652[UPDATING] git repository [..]
653[ERROR] multiple packages with examples found: bar, foo. \
654When installing a git repository, cargo will always search the entire repo for any Cargo.toml.
655Please specify a package, e.g. `cargo install --git {git_url} bar`."
656 ))
657 .run();
658}
659
660#[cargo_test]
661fn multiple_binaries_deep_select_uses_package_name() {
662 let p = git::repo(&paths::root().join("foo"))
663 .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
664 .file("src/main.rs", "fn main() {}")
665 .file("bar/baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
666 .file("bar/baz/src/main.rs", "fn main() {}")
667 .build();
668
669 cargo_process("install --git")
670 .arg(p.url().to_string())
671 .arg("baz")
672 .run();
673}
674
675#[cargo_test]
676fn multiple_binaries_in_selected_package_installs_all() {
677 let p = git::repo(&paths::root().join("foo"))
678 .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
679 .file("src/lib.rs", "")
680 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
681 .file("bar/src/bin/bin1.rs", "fn main() {}")
682 .file("bar/src/bin/bin2.rs", "fn main() {}")
683 .build();
684
685 cargo_process("install --git")
686 .arg(p.url().to_string())
687 .arg("bar")
688 .run();
689
690 let cargo_home = cargo_home();
691 assert_has_installed_exe(&cargo_home, "bin1");
692 assert_has_installed_exe(&cargo_home, "bin2");
693}
694
695#[cargo_test]
696fn multiple_binaries_in_selected_package_with_bin_option_installs_only_one() {
697 let p = git::repo(&paths::root().join("foo"))
698 .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
699 .file("src/lib.rs", "")
700 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
701 .file("bar/src/bin/bin1.rs", "fn main() {}")
702 .file("bar/src/bin/bin2.rs", "fn main() {}")
703 .build();
704
705 cargo_process("install --bin bin1 --git")
706 .arg(p.url().to_string())
707 .arg("bar")
708 .run();
709
710 let cargo_home = cargo_home();
711 assert_has_installed_exe(&cargo_home, "bin1");
712 assert_has_not_installed_exe(&cargo_home, "bin2");
713}
714
715#[cargo_test]
716fn multiple_crates_select() {
717 let p = git::repo(&paths::root().join("foo"))
718 .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
719 .file("src/main.rs", "fn main() {}")
720 .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0"))
721 .file("a/src/main.rs", "fn main() {}")
722 .build();
723
724 cargo_process("install --git")
725 .arg(p.url().to_string())
726 .arg("foo")
727 .run();
728 assert_has_installed_exe(cargo_home(), "foo");
729 assert_has_not_installed_exe(cargo_home(), "bar");
730
731 cargo_process("install --git")
732 .arg(p.url().to_string())
733 .arg("bar")
734 .run();
735 assert_has_installed_exe(cargo_home(), "bar");
736}
737
738#[cargo_test]
739fn multiple_crates_git_all() {
740 let p = git::repo(&paths::root().join("foo"))
741 .file(
742 "Cargo.toml",
743 r#"
744 [workspace]
745 members = ["bin1", "bin2"]
746 "#,
747 )
748 .file("bin1/Cargo.toml", &basic_manifest("bin1", "0.1.0"))
749 .file("bin2/Cargo.toml", &basic_manifest("bin2", "0.1.0"))
750 .file(
751 "bin1/src/main.rs",
752 r#"fn main() { println!("Hello, world!"); }"#,
753 )
754 .file(
755 "bin2/src/main.rs",
756 r#"fn main() { println!("Hello, world!"); }"#,
757 )
758 .build();
759
760 cargo_process(&format!("install --git {} bin1 bin2", p.url().to_string())).run();
761}
762
763#[cargo_test]
764fn multiple_crates_auto_binaries() {
765 let p = project()
766 .file(
767 "Cargo.toml",
768 r#"
769 [package]
770 name = "foo"
771 version = "0.1.0"
772 authors = []
773
774 [dependencies]
775 bar = { path = "a" }
776 "#,
777 )
778 .file("src/main.rs", "extern crate bar; fn main() {}")
779 .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0"))
780 .file("a/src/lib.rs", "")
781 .build();
782
783 cargo_process("install --path").arg(p.root()).run();
784 assert_has_installed_exe(cargo_home(), "foo");
785}
786
787#[cargo_test]
788fn multiple_crates_auto_examples() {
789 let p = project()
790 .file(
791 "Cargo.toml",
792 r#"
793 [package]
794 name = "foo"
795 version = "0.1.0"
796 authors = []
797
798 [dependencies]
799 bar = { path = "a" }
800 "#,
801 )
802 .file("src/lib.rs", "extern crate bar;")
803 .file(
804 "examples/foo.rs",
805 "
806 extern crate bar;
807 extern crate foo;
808 fn main() {}
809 ",
810 )
811 .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0"))
812 .file("a/src/lib.rs", "")
813 .build();
814
815 cargo_process("install --path")
816 .arg(p.root())
817 .arg("--example=foo")
818 .run();
819 assert_has_installed_exe(cargo_home(), "foo");
820}
821
822#[cargo_test]
823fn no_binaries_or_examples() {
824 let p = project()
825 .file(
826 "Cargo.toml",
827 r#"
828 [package]
829 name = "foo"
830 version = "0.1.0"
831 authors = []
832
833 [dependencies]
834 bar = { path = "a" }
835 "#,
836 )
837 .file("src/lib.rs", "")
838 .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0"))
839 .file("a/src/lib.rs", "")
840 .build();
841
842 cargo_process("install --path")
843 .arg(p.root())
844 .with_status(101)
845 .with_stderr("[ERROR] no packages found with binaries or examples")
846 .run();
847}
848
849#[cargo_test]
850fn no_binaries() {
851 let p = project()
852 .file("src/lib.rs", "")
853 .file("examples/foo.rs", "fn main() {}")
854 .build();
855
856 cargo_process("install --path")
857 .arg(p.root())
858 .arg("foo")
859 .with_status(101)
860 .with_stderr(
861 "\
862[ERROR] there is nothing to install in `foo v0.0.1 ([..])`, because it has no binaries[..]
863[..]
864To use a library crate, add it as a dependency to a Cargo project with `cargo add`.",
865 )
866 .run();
867}
868
869#[cargo_test]
870fn examples() {
871 let p = project()
872 .file("src/lib.rs", "")
873 .file("examples/foo.rs", "extern crate foo; fn main() {}")
874 .build();
875
876 cargo_process("install --path")
877 .arg(p.root())
878 .arg("--example=foo")
879 .run();
880 assert_has_installed_exe(cargo_home(), "foo");
881}
882
883#[cargo_test]
884fn install_force() {
885 let p = project().file("src/main.rs", "fn main() {}").build();
886
887 cargo_process("install --path").arg(p.root()).run();
888
889 let p = project()
890 .at("foo2")
891 .file("Cargo.toml", &basic_manifest("foo", "0.2.0"))
892 .file("src/main.rs", "fn main() {}")
893 .build();
894
895 cargo_process("install --force --path")
896 .arg(p.root())
897 .with_stderr(
898 "\
899[INSTALLING] foo v0.2.0 ([..])
900[COMPILING] foo v0.2.0 ([..])
901[FINISHED] release [optimized] target(s) in [..]
902[REPLACING] [CWD]/home/.cargo/bin/foo[EXE]
903[REPLACED] package `foo v0.0.1 ([..]/foo)` with `foo v0.2.0 ([..]/foo2)` (executable `foo[EXE]`)
904[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
905",
906 )
907 .run();
908
909 cargo_process("install --list")
910 .with_stdout(
911 "\
912foo v0.2.0 ([..]):
913 foo[..]
914",
915 )
916 .run();
917}
918
919#[cargo_test]
920fn install_force_partial_overlap() {
921 let p = project()
922 .file("src/bin/foo-bin1.rs", "fn main() {}")
923 .file("src/bin/foo-bin2.rs", "fn main() {}")
924 .build();
925
926 cargo_process("install --path").arg(p.root()).run();
927
928 let p = project()
929 .at("foo2")
930 .file("Cargo.toml", &basic_manifest("foo", "0.2.0"))
931 .file("src/bin/foo-bin2.rs", "fn main() {}")
932 .file("src/bin/foo-bin3.rs", "fn main() {}")
933 .build();
934
935 cargo_process("install --force --path")
936 .arg(p.root())
937 .with_stderr(
938 "\
939[INSTALLING] foo v0.2.0 ([..])
940[COMPILING] foo v0.2.0 ([..])
941[FINISHED] release [optimized] target(s) in [..]
942[INSTALLING] [CWD]/home/.cargo/bin/foo-bin3[EXE]
943[REPLACING] [CWD]/home/.cargo/bin/foo-bin2[EXE]
944[REMOVING] executable `[..]/bin/foo-bin1[EXE]` from previous version foo v0.0.1 [..]
945[INSTALLED] package `foo v0.2.0 ([..]/foo2)` (executable `foo-bin3[EXE]`)
946[REPLACED] package `foo v0.0.1 ([..]/foo)` with `foo v0.2.0 ([..]/foo2)` (executable `foo-bin2[EXE]`)
947[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
948",
949 )
950 .run();
951
952 cargo_process("install --list")
953 .with_stdout(
954 "\
955foo v0.2.0 ([..]):
956 foo-bin2[..]
957 foo-bin3[..]
958",
959 )
960 .run();
961}
962
963#[cargo_test]
964fn install_force_bin() {
965 let p = project()
966 .file("src/bin/foo-bin1.rs", "fn main() {}")
967 .file("src/bin/foo-bin2.rs", "fn main() {}")
968 .build();
969
970 cargo_process("install --path").arg(p.root()).run();
971
972 let p = project()
973 .at("foo2")
974 .file("Cargo.toml", &basic_manifest("foo", "0.2.0"))
975 .file("src/bin/foo-bin1.rs", "fn main() {}")
976 .file("src/bin/foo-bin2.rs", "fn main() {}")
977 .build();
978
979 cargo_process("install --force --bin foo-bin2 --path")
980 .arg(p.root())
981 .with_stderr(
982 "\
983[INSTALLING] foo v0.2.0 ([..])
984[COMPILING] foo v0.2.0 ([..])
985[FINISHED] release [optimized] target(s) in [..]
986[REPLACING] [CWD]/home/.cargo/bin/foo-bin2[EXE]
987[REPLACED] package `foo v0.0.1 ([..]/foo)` with `foo v0.2.0 ([..]/foo2)` (executable `foo-bin2[EXE]`)
988[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
989",
990 )
991 .run();
992
993 cargo_process("install --list")
994 .with_stdout(
995 "\
996foo v0.0.1 ([..]):
997 foo-bin1[..]
998foo v0.2.0 ([..]):
999 foo-bin2[..]
1000",
1001 )
1002 .run();
1003}
1004
1005#[cargo_test]
1006fn compile_failure() {
1007 let p = project().file("src/main.rs", "").build();
1008
1009 cargo_process("install --path")
1010 .arg(p.root())
1011 .with_status(101)
1012 .with_stderr_contains(
1013 "\
4b012472 1014[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error
0a29b90c 1015[ERROR] failed to compile `foo v0.0.1 ([..])`, intermediate artifacts can be \
fe692bf9
FG
1016 found at `[..]target`.\nTo reuse those artifacts with a future compilation, \
1017 set the environment variable `CARGO_TARGET_DIR` to that path.
0a29b90c
FG
1018",
1019 )
1020 .run();
1021}
1022
1023#[cargo_test]
1024fn git_repo() {
1025 let p = git::repo(&paths::root().join("foo"))
1026 .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
1027 .file("src/main.rs", "fn main() {}")
1028 .build();
1029
1030 // Use `--locked` to test that we don't even try to write a lock file.
1031 cargo_process("install --locked --git")
1032 .arg(p.url().to_string())
1033 .with_stderr(
1034 "\
1035[UPDATING] git repository `[..]`
1036[WARNING] no Cargo.lock file published in foo v0.1.0 ([..])
1037[INSTALLING] foo v0.1.0 ([..])
1038[COMPILING] foo v0.1.0 ([..])
1039[FINISHED] release [optimized] target(s) in [..]
1040[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
1041[INSTALLED] package `foo v0.1.0 ([..]/foo#[..])` (executable `foo[EXE]`)
1042[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
1043",
1044 )
1045 .run();
1046 assert_has_installed_exe(cargo_home(), "foo");
1047 assert_has_installed_exe(cargo_home(), "foo");
1048}
1049
1050#[cargo_test]
1051#[cfg(target_os = "linux")]
1052fn git_repo_with_lowercase_cargo_toml() {
1053 let p = git::repo(&paths::root().join("foo"))
1054 .file("cargo.toml", &basic_manifest("foo", "0.1.0"))
1055 .file("src/main.rs", "fn main() {}")
1056 .build();
1057
1058 cargo_process("install --git")
1059 .arg(p.url().to_string())
1060 .with_status(101)
1061 .with_stderr(
1062 "\
1063[UPDATING] git repository [..]
1064[ERROR] Could not find Cargo.toml in `[..]`, but found cargo.toml please try to rename it to Cargo.toml
1065",
1066 )
1067 .run();
1068}
1069
1070#[cargo_test]
1071fn list() {
1072 pkg("foo", "0.0.1");
1073 pkg("bar", "0.2.1");
1074 pkg("bar", "0.2.2");
1075
1076 cargo_process("install --list").with_stdout("").run();
1077
1078 cargo_process("install bar --version =0.2.1").run();
1079 cargo_process("install foo").run();
1080 cargo_process("install --list")
1081 .with_stdout(
1082 "\
1083bar v0.2.1:
1084 bar[..]
1085foo v0.0.1:
1086 foo[..]
1087",
1088 )
1089 .run();
1090}
1091
1092#[cargo_test]
1093fn list_error() {
1094 pkg("foo", "0.0.1");
1095 cargo_process("install foo").run();
1096 cargo_process("install --list")
1097 .with_stdout(
1098 "\
1099foo v0.0.1:
1100 foo[..]
1101",
1102 )
1103 .run();
1104 let mut worldfile_path = cargo_home();
1105 worldfile_path.push(".crates.toml");
1106 let mut worldfile = OpenOptions::new()
1107 .write(true)
1108 .open(worldfile_path)
1109 .expect(".crates.toml should be there");
1110 worldfile.write_all(b"\x00").unwrap();
1111 drop(worldfile);
1112 cargo_process("install --list --verbose")
1113 .with_status(101)
1114 .with_stderr(
1115 "\
1116[ERROR] failed to parse crate metadata at `[..]`
1117
1118Caused by:
1119 invalid TOML found for metadata
1120
1121Caused by:
1122 TOML parse error at line 1, column 1
1123 |
1124 1 | [..]
1125 | ^
1126 invalid key
1127",
1128 )
1129 .run();
1130}
1131
1132#[cargo_test]
1133fn uninstall_pkg_does_not_exist() {
1134 cargo_process("uninstall foo")
1135 .with_status(101)
1136 .with_stderr("[ERROR] package ID specification `foo` did not match any packages")
1137 .run();
1138}
1139
1140#[cargo_test]
1141fn uninstall_bin_does_not_exist() {
1142 pkg("foo", "0.0.1");
1143
1144 cargo_process("install foo").run();
1145 cargo_process("uninstall foo --bin=bar")
1146 .with_status(101)
1147 .with_stderr("[ERROR] binary `bar[..]` not installed as part of `foo v0.0.1`")
1148 .run();
1149}
1150
1151#[cargo_test]
1152fn uninstall_piecemeal() {
1153 let p = project()
1154 .file("src/bin/foo.rs", "fn main() {}")
1155 .file("src/bin/bar.rs", "fn main() {}")
1156 .build();
1157
1158 cargo_process("install --path").arg(p.root()).run();
1159 assert_has_installed_exe(cargo_home(), "foo");
1160 assert_has_installed_exe(cargo_home(), "bar");
1161
1162 cargo_process("uninstall foo --bin=bar")
1163 .with_stderr("[REMOVING] [..]bar[..]")
1164 .run();
1165
1166 assert_has_installed_exe(cargo_home(), "foo");
1167 assert_has_not_installed_exe(cargo_home(), "bar");
1168
1169 cargo_process("uninstall foo --bin=foo")
1170 .with_stderr("[REMOVING] [..]foo[..]")
1171 .run();
1172 assert_has_not_installed_exe(cargo_home(), "foo");
1173
1174 cargo_process("uninstall foo")
1175 .with_status(101)
1176 .with_stderr("[ERROR] package ID specification `foo` did not match any packages")
1177 .run();
1178}
1179
1180#[cargo_test]
1181fn subcommand_works_out_of_the_box() {
1182 Package::new("cargo-foo", "1.0.0")
1183 .file("src/main.rs", r#"fn main() { println!("bar"); }"#)
1184 .publish();
1185 cargo_process("install cargo-foo").run();
1186 cargo_process("foo").with_stdout("bar\n").run();
1187 cargo_process("--list")
1188 .with_stdout_contains(" foo\n")
1189 .run();
1190}
1191
1192#[cargo_test]
1193fn installs_from_cwd_by_default() {
1194 let p = project().file("src/main.rs", "fn main() {}").build();
1195
1196 p.cargo("install")
1197 .with_stderr_contains(
1198 "warning: Using `cargo install` to install the binaries for the \
1199 package in current working directory is deprecated, \
1200 use `cargo install --path .` instead. \
1201 Use `cargo build` if you want to simply build the package.",
1202 )
1203 .run();
1204 assert_has_installed_exe(cargo_home(), "foo");
1205}
1206
1207#[cargo_test]
1208fn installs_from_cwd_with_2018_warnings() {
1209 let p = project()
1210 .file(
1211 "Cargo.toml",
1212 r#"
1213 [package]
1214 name = "foo"
1215 version = "0.1.0"
1216 authors = []
1217 edition = "2018"
1218 "#,
1219 )
1220 .file("src/main.rs", "fn main() {}")
1221 .build();
1222
1223 p.cargo("install")
1224 .with_status(101)
1225 .with_stderr_contains(
1226 "error: Using `cargo install` to install the binaries for the \
1227 package in current working directory is no longer supported, \
1228 use `cargo install --path .` instead. \
1229 Use `cargo build` if you want to simply build the package.",
1230 )
1231 .run();
1232 assert_has_not_installed_exe(cargo_home(), "foo");
1233}
1234
1235#[cargo_test]
1236fn uninstall_cwd() {
1237 let p = project().file("src/main.rs", "fn main() {}").build();
1238 p.cargo("install --path .")
1239 .with_stderr(&format!(
1240 "\
1241[INSTALLING] foo v0.0.1 ([CWD])
1242[COMPILING] foo v0.0.1 ([CWD])
1243[FINISHED] release [optimized] target(s) in [..]
1244[INSTALLING] {home}/bin/foo[EXE]
1245[INSTALLED] package `foo v0.0.1 ([..]/foo)` (executable `foo[EXE]`)
1246[WARNING] be sure to add `{home}/bin` to your PATH to be able to run the installed binaries",
1247 home = cargo_home().display(),
1248 ))
1249 .run();
1250 assert_has_installed_exe(cargo_home(), "foo");
1251
1252 p.cargo("uninstall")
1253 .with_stdout("")
1254 .with_stderr(&format!(
1255 "[REMOVING] {home}/bin/foo[EXE]",
1256 home = cargo_home().display()
1257 ))
1258 .run();
1259 assert_has_not_installed_exe(cargo_home(), "foo");
1260}
1261
1262#[cargo_test]
1263fn uninstall_cwd_not_installed() {
1264 let p = project().file("src/main.rs", "fn main() {}").build();
1265 p.cargo("uninstall")
1266 .with_status(101)
1267 .with_stdout("")
1268 .with_stderr("error: package `foo v0.0.1 ([CWD])` is not installed")
1269 .run();
1270}
1271
1272#[cargo_test]
1273fn uninstall_cwd_no_project() {
1274 cargo_process("uninstall")
1275 .with_status(101)
1276 .with_stdout("")
1277 .with_stderr(format!(
1278 "\
1279[ERROR] failed to read `[CWD]/Cargo.toml`
1280
1281Caused by:
1282 {err_msg}",
1283 err_msg = no_such_file_err_msg(),
1284 ))
1285 .run();
1286}
1287
1288#[cargo_test]
1289fn do_not_rebuilds_on_local_install() {
1290 let p = project().file("src/main.rs", "fn main() {}").build();
1291
1292 p.cargo("build --release").run();
1293 cargo_process("install --path")
1294 .arg(p.root())
1295 .with_stderr(
1296 "\
1297[INSTALLING] [..]
1298[FINISHED] release [optimized] target(s) in [..]
1299[INSTALLING] [..]
1300[INSTALLED] package `foo v0.0.1 ([..]/foo)` (executable `foo[EXE]`)
1301[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
1302",
1303 )
1304 .run();
1305
1306 assert!(p.build_dir().exists());
1307 assert!(p.release_bin("foo").exists());
1308 assert_has_installed_exe(cargo_home(), "foo");
1309}
1310
1311#[cargo_test]
1312fn reports_unsuccessful_subcommand_result() {
1313 Package::new("cargo-fail", "1.0.0")
1314 .file("src/main.rs", "fn main() { panic!(); }")
1315 .publish();
1316 cargo_process("install cargo-fail").run();
1317 cargo_process("--list")
1318 .with_stdout_contains(" fail\n")
1319 .run();
1320 cargo_process("fail")
1321 .with_status(101)
fe692bf9
FG
1322 .with_stderr_contains("thread '[..]' panicked at [..]src/main.rs:1:[..]")
1323 .with_stderr_contains("[..]explicit panic[..]")
0a29b90c
FG
1324 .run();
1325}
1326
1327#[cargo_test]
1328fn git_with_lockfile() {
1329 let p = git::repo(&paths::root().join("foo"))
1330 .file(
1331 "Cargo.toml",
1332 r#"
1333 [package]
1334 name = "foo"
1335 version = "0.1.0"
1336 authors = []
1337
1338 [dependencies]
1339 bar = { path = "bar" }
1340 "#,
1341 )
1342 .file("src/main.rs", "fn main() {}")
1343 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
1344 .file("bar/src/lib.rs", "fn main() {}")
1345 .file(
1346 "Cargo.lock",
1347 r#"
1348 [[package]]
1349 name = "foo"
1350 version = "0.1.0"
1351 dependencies = [ "bar 0.1.0" ]
1352
1353 [[package]]
1354 name = "bar"
1355 version = "0.1.0"
1356 "#,
1357 )
1358 .build();
1359
1360 cargo_process("install --git")
1361 .arg(p.url().to_string())
1362 .run();
1363}
1364
1365#[cargo_test]
1366fn q_silences_warnings() {
1367 let p = project().file("src/main.rs", "fn main() {}").build();
1368
1369 cargo_process("install -q --path")
1370 .arg(p.root())
1371 .with_stderr("")
1372 .run();
1373}
1374
1375#[cargo_test]
1376fn readonly_dir() {
1377 pkg("foo", "0.0.1");
1378
1379 let root = paths::root();
1380 let dir = &root.join("readonly");
1381 fs::create_dir(root.join("readonly")).unwrap();
1382 let mut perms = fs::metadata(dir).unwrap().permissions();
1383 perms.set_readonly(true);
1384 fs::set_permissions(dir, perms).unwrap();
1385
1386 cargo_process("install foo").cwd(dir).run();
1387 assert_has_installed_exe(cargo_home(), "foo");
1388}
1389
1390#[cargo_test]
1391fn use_path_workspace() {
1392 Package::new("foo", "1.0.0").publish();
1393 let p = project()
1394 .file(
1395 "Cargo.toml",
1396 r#"
1397 [package]
1398 name = "bar"
1399 version = "0.1.0"
1400 authors = []
1401
1402 [workspace]
1403 members = ["baz"]
1404 "#,
1405 )
1406 .file("src/main.rs", "fn main() {}")
1407 .file(
1408 "baz/Cargo.toml",
1409 r#"
1410 [package]
1411 name = "baz"
1412 version = "0.1.0"
1413 authors = []
1414
1415 [dependencies]
1416 foo = "1"
1417 "#,
1418 )
1419 .file("baz/src/lib.rs", "")
1420 .build();
1421
1422 p.cargo("build").run();
1423 let lock = p.read_lockfile();
1424 p.cargo("install").run();
1425 let lock2 = p.read_lockfile();
1426 assert_eq!(lock, lock2, "different lockfiles");
1427}
1428
1429#[cargo_test]
1430fn path_install_workspace_root_despite_default_members() {
1431 let p = project()
1432 .file(
1433 "Cargo.toml",
1434 r#"
1435 [package]
1436 name = "ws-root"
1437 version = "0.1.0"
1438 authors = []
1439
1440 [workspace]
1441 members = ["ws-member"]
1442 default-members = ["ws-member"]
1443 "#,
1444 )
1445 .file("src/main.rs", "fn main() {}")
1446 .file(
1447 "ws-member/Cargo.toml",
1448 r#"
1449 [package]
1450 name = "ws-member"
1451 version = "0.1.0"
1452 authors = []
1453 "#,
1454 )
1455 .file("ws-member/src/main.rs", "fn main() {}")
1456 .build();
1457
1458 p.cargo("install --path")
1459 .arg(p.root())
1460 .arg("ws-root")
1461 .with_stderr_contains(
1462 "[INSTALLED] package `ws-root v0.1.0 ([..])` (executable `ws-root[EXE]`)",
1463 )
1464 // Particularly avoid "Installed package `ws-root v0.1.0 ([..]])` (executable `ws-member`)":
1465 .with_stderr_does_not_contain("ws-member")
1466 .run();
1467}
1468
49aad941
FG
1469#[cargo_test]
1470fn git_install_workspace_root_despite_default_members() {
1471 let p = git::repo(&paths::root().join("foo"))
1472 .file(
1473 "Cargo.toml",
1474 r#"
1475 [package]
1476 name = "ws-root"
1477 version = "0.1.0"
1478 authors = []
1479
1480 [workspace]
1481 members = ["ws-member"]
1482 default-members = ["ws-member"]
1483 "#,
1484 )
1485 .file("src/main.rs", "fn main() {}")
1486 .file(
1487 "ws-member/Cargo.toml",
1488 r#"
1489 [package]
1490 name = "ws-member"
1491 version = "0.1.0"
1492 authors = []
1493 "#,
1494 )
1495 .file("ws-member/src/main.rs", "fn main() {}")
1496 .build();
1497
1498 cargo_process("install --git")
1499 .arg(p.url().to_string())
1500 .arg("ws-root")
1501 .with_stderr_contains(
1502 "[INSTALLED] package `ws-root v0.1.0 ([..])` (executable `ws-root[EXE]`)",
1503 )
1504 // Particularly avoid "Installed package `ws-root v0.1.0 ([..]])` (executable `ws-member`)":
1505 .with_stderr_does_not_contain("ws-member")
1506 .run();
1507}
1508
0a29b90c
FG
1509#[cargo_test]
1510fn dev_dependencies_no_check() {
1511 Package::new("foo", "1.0.0").publish();
1512 let p = project()
1513 .file(
1514 "Cargo.toml",
1515 r#"
1516 [package]
1517 name = "bar"
1518 version = "0.1.0"
1519 authors = []
1520
1521 [dev-dependencies]
1522 baz = "1.0.0"
1523 "#,
1524 )
1525 .file("src/main.rs", "fn main() {}")
1526 .build();
1527
1528 p.cargo("build")
1529 .with_status(101)
1530 .with_stderr_contains("[..] no matching package named `baz` found")
1531 .run();
1532 p.cargo("install").run();
1533}
1534
1535#[cargo_test]
1536fn dev_dependencies_lock_file_untouched() {
1537 Package::new("foo", "1.0.0").publish();
1538 let p = project()
1539 .file(
1540 "Cargo.toml",
1541 r#"
1542 [package]
1543 name = "foo"
1544 version = "0.1.0"
1545 authors = []
1546
1547 [dev-dependencies]
1548 bar = { path = "a" }
1549 "#,
1550 )
1551 .file("src/main.rs", "fn main() {}")
1552 .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0"))
1553 .file("a/src/lib.rs", "")
1554 .build();
1555
1556 p.cargo("build").run();
1557 let lock = p.read_lockfile();
1558 p.cargo("install").run();
1559 let lock2 = p.read_lockfile();
1560 assert!(lock == lock2, "different lockfiles");
1561}
1562
1563#[cargo_test]
1564fn install_target_native() {
1565 pkg("foo", "0.1.0");
1566
1567 cargo_process("install foo --target")
1568 .arg(cargo_test_support::rustc_host())
1569 .run();
1570 assert_has_installed_exe(cargo_home(), "foo");
1571}
1572
1573#[cargo_test]
1574fn install_target_foreign() {
1575 if cross_compile::disabled() {
1576 return;
1577 }
1578
1579 pkg("foo", "0.1.0");
1580
1581 cargo_process("install foo --target")
1582 .arg(cross_compile::alternate())
1583 .run();
1584 assert_has_installed_exe(cargo_home(), "foo");
1585}
1586
1587#[cargo_test]
1588fn vers_precise() {
1589 pkg("foo", "0.1.1");
1590 pkg("foo", "0.1.2");
1591
1592 cargo_process("install foo --vers 0.1.1")
1593 .with_stderr_contains("[DOWNLOADED] foo v0.1.1 (registry [..])")
1594 .run();
1595}
1596
1597#[cargo_test]
1598fn version_precise() {
1599 pkg("foo", "0.1.1");
1600 pkg("foo", "0.1.2");
1601
1602 cargo_process("install foo --version 0.1.1")
1603 .with_stderr_contains("[DOWNLOADED] foo v0.1.1 (registry [..])")
1604 .run();
1605}
1606
1607#[cargo_test]
1608fn inline_version_precise() {
1609 pkg("foo", "0.1.1");
1610 pkg("foo", "0.1.2");
1611
1612 cargo_process("install foo@0.1.1")
1613 .with_stderr_contains("[DOWNLOADED] foo v0.1.1 (registry [..])")
1614 .run();
1615}
1616
1617#[cargo_test]
1618fn inline_version_multiple() {
1619 pkg("foo", "0.1.0");
1620 pkg("foo", "0.1.1");
1621 pkg("foo", "0.1.2");
1622 pkg("bar", "0.2.0");
1623 pkg("bar", "0.2.1");
1624 pkg("bar", "0.2.2");
1625
1626 cargo_process("install foo@0.1.1 bar@0.2.1")
1627 .with_stderr_contains("[DOWNLOADED] foo v0.1.1 (registry [..])")
1628 .with_stderr_contains("[DOWNLOADED] bar v0.2.1 (registry [..])")
1629 .run();
1630}
1631
1632#[cargo_test]
1633fn inline_version_without_name() {
1634 pkg("foo", "0.1.1");
1635 pkg("foo", "0.1.2");
1636
1637 cargo_process("install @0.1.1")
781aab86
FG
1638 .with_status(1)
1639 .with_stderr(
ed00b5ec 1640 "error: invalid value '@0.1.1' for '[CRATE[@<VER>]]...': missing crate name before '@'
781aab86
FG
1641
1642For more information, try '--help'.
1643",
1644 )
0a29b90c
FG
1645 .run();
1646}
1647
1648#[cargo_test]
1649fn inline_and_explicit_version() {
1650 pkg("foo", "0.1.1");
1651 pkg("foo", "0.1.2");
1652
1653 cargo_process("install foo@0.1.1 --version 0.1.1")
1654 .with_status(101)
781aab86 1655 .with_stderr("error: cannot specify both `@<VERSION>` and `--version <VERSION>`")
0a29b90c
FG
1656 .run();
1657}
1658
1659#[cargo_test]
1660fn not_both_vers_and_version() {
1661 pkg("foo", "0.1.1");
1662 pkg("foo", "0.1.2");
1663
1664 cargo_process("install foo --version 0.1.1 --vers 0.1.2")
1665 .with_status(1)
1666 .with_stderr_contains(
1667 "\
1668[ERROR] the argument '--version <VERSION>' cannot be used multiple times
1669",
1670 )
1671 .run();
1672}
1673
1674#[cargo_test]
1675fn test_install_git_cannot_be_a_base_url() {
1676 cargo_process("install --git github.com:rust-lang/rustfmt.git")
1677 .with_status(101)
1678 .with_stderr(
1679 "\
1680[ERROR] invalid url `github.com:rust-lang/rustfmt.git`: cannot-be-a-base-URLs are not supported",
1681 )
1682 .run();
1683}
1684
1685#[cargo_test]
1686fn uninstall_multiple_and_specifying_bin() {
1687 cargo_process("uninstall foo bar --bin baz")
1688 .with_status(101)
1689 .with_stderr("\
1690[ERROR] A binary can only be associated with a single installed package, specifying multiple specs with --bin is redundant.")
1691 .run();
1692}
1693
1694#[cargo_test]
1695fn uninstall_with_empty_package_option() {
1696 cargo_process("uninstall -p")
1697 .with_status(101)
1698 .with_stderr(
1699 "\
1700[ERROR] \"--package <SPEC>\" requires a SPEC format value.
1701Run `cargo help pkgid` for more information about SPEC format.
1702",
1703 )
1704 .run();
1705}
1706
1707#[cargo_test]
1708fn uninstall_multiple_and_some_pkg_does_not_exist() {
1709 pkg("foo", "0.0.1");
1710
1711 cargo_process("install foo").run();
1712
1713 cargo_process("uninstall foo bar")
1714 .with_status(101)
1715 .with_stderr(
1716 "\
1717[REMOVING] [CWD]/home/.cargo/bin/foo[EXE]
1718error: package ID specification `bar` did not match any packages
1719[SUMMARY] Successfully uninstalled foo! Failed to uninstall bar (see error(s) above).
1720error: some packages failed to uninstall
1721",
1722 )
1723 .run();
1724
1725 assert_has_not_installed_exe(cargo_home(), "foo");
1726 assert_has_not_installed_exe(cargo_home(), "bar");
1727}
1728
1729#[cargo_test]
1730fn custom_target_dir_for_git_source() {
1731 let p = git::repo(&paths::root().join("foo"))
1732 .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
1733 .file("src/main.rs", "fn main() {}")
1734 .build();
1735
1736 cargo_process("install --git")
1737 .arg(p.url().to_string())
1738 .run();
1739 assert!(!paths::root().join("target/release").is_dir());
1740
1741 cargo_process("install --force --git")
1742 .arg(p.url().to_string())
1743 .env("CARGO_TARGET_DIR", "target")
1744 .run();
1745 assert!(paths::root().join("target/release").is_dir());
1746}
1747
1748#[cargo_test]
1749fn install_respects_lock_file() {
1750 // `cargo install` now requires --locked to use a Cargo.lock.
1751 Package::new("bar", "0.1.0").publish();
1752 Package::new("bar", "0.1.1")
1753 .file("src/lib.rs", "not rust")
1754 .publish();
1755 Package::new("foo", "0.1.0")
1756 .dep("bar", "0.1")
1757 .file("src/lib.rs", "")
1758 .file(
1759 "src/main.rs",
1760 "extern crate foo; extern crate bar; fn main() {}",
1761 )
1762 .file(
1763 "Cargo.lock",
1764 r#"
1765[[package]]
1766name = "bar"
1767version = "0.1.0"
1768source = "registry+https://github.com/rust-lang/crates.io-index"
1769
1770[[package]]
1771name = "foo"
1772version = "0.1.0"
1773dependencies = [
1774 "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1775]
1776"#,
1777 )
1778 .publish();
1779
1780 cargo_process("install foo")
1781 .with_stderr_contains("[..]not rust[..]")
1782 .with_status(101)
1783 .run();
1784 cargo_process("install --locked foo").run();
1785}
1786
1787#[cargo_test]
1788fn install_path_respects_lock_file() {
1789 // --path version of install_path_respects_lock_file, --locked is required
1790 // to use Cargo.lock.
1791 Package::new("bar", "0.1.0").publish();
1792 Package::new("bar", "0.1.1")
1793 .file("src/lib.rs", "not rust")
1794 .publish();
1795 let p = project()
1796 .file(
1797 "Cargo.toml",
1798 r#"
1799 [package]
1800 name = "foo"
1801 version = "0.1.0"
1802
1803 [dependencies]
1804 bar = "0.1"
1805 "#,
1806 )
1807 .file("src/main.rs", "extern crate bar; fn main() {}")
1808 .file(
1809 "Cargo.lock",
1810 r#"
1811[[package]]
1812name = "bar"
1813version = "0.1.0"
1814source = "registry+https://github.com/rust-lang/crates.io-index"
1815
1816[[package]]
1817name = "foo"
1818version = "0.1.0"
1819dependencies = [
1820 "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1821]
1822"#,
1823 )
1824 .build();
1825
1826 p.cargo("install --path .")
1827 .with_stderr_contains("[..]not rust[..]")
1828 .with_status(101)
1829 .run();
1830 p.cargo("install --path . --locked").run();
1831}
1832
1833#[cargo_test]
1834fn lock_file_path_deps_ok() {
1835 Package::new("bar", "0.1.0").publish();
1836
1837 Package::new("foo", "0.1.0")
1838 .dep("bar", "0.1")
1839 .file("src/lib.rs", "")
1840 .file(
1841 "src/main.rs",
1842 "extern crate foo; extern crate bar; fn main() {}",
1843 )
1844 .file(
1845 "Cargo.lock",
1846 r#"
1847 [[package]]
1848 name = "bar"
1849 version = "0.1.0"
1850
1851 [[package]]
1852 name = "foo"
1853 version = "0.1.0"
1854 dependencies = [
1855 "bar 0.1.0",
1856 ]
1857 "#,
1858 )
1859 .publish();
1860
1861 cargo_process("install foo").run();
1862}
1863
1864#[cargo_test]
1865fn install_empty_argument() {
1866 // Bug 5229
1867 cargo_process("install")
1868 .arg("")
1869 .with_status(1)
ed00b5ec
FG
1870 .with_stderr_contains(
1871 "[ERROR] invalid value '' for '[CRATE[@<VER>]]...': crate name is empty",
1872 )
0a29b90c
FG
1873 .run();
1874}
1875
1876#[cargo_test]
1877fn git_repo_replace() {
1878 let p = git::repo(&paths::root().join("foo"))
1879 .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
1880 .file("src/main.rs", "fn main() {}")
1881 .build();
1882 let repo = git2::Repository::open(&p.root()).unwrap();
1883 let old_rev = repo.revparse_single("HEAD").unwrap().id();
1884 cargo_process("install --git")
1885 .arg(p.url().to_string())
1886 .run();
1887 git::commit(&repo);
1888 let new_rev = repo.revparse_single("HEAD").unwrap().id();
1889 let mut path = paths::home();
1890 path.push(".cargo/.crates.toml");
1891
1892 assert_ne!(old_rev, new_rev);
1893 assert!(fs::read_to_string(path.clone())
1894 .unwrap()
1895 .contains(&format!("{}", old_rev)));
1896 cargo_process("install --force --git")
1897 .arg(p.url().to_string())
1898 .run();
1899 assert!(fs::read_to_string(path)
1900 .unwrap()
1901 .contains(&format!("{}", new_rev)));
1902}
1903
1904#[cargo_test]
1905fn workspace_uses_workspace_target_dir() {
1906 let p = project()
1907 .file(
1908 "Cargo.toml",
1909 r#"
1910 [package]
1911 name = "foo"
1912 version = "0.1.0"
1913 authors = []
1914
1915 [workspace]
1916
1917 [dependencies]
1918 bar = { path = 'bar' }
1919 "#,
1920 )
1921 .file("src/main.rs", "fn main() {}")
1922 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
1923 .file("bar/src/main.rs", "fn main() {}")
1924 .build();
1925
1926 p.cargo("build --release").cwd("bar").run();
1927 cargo_process("install --path")
1928 .arg(p.root().join("bar"))
1929 .with_stderr(
1930 "[INSTALLING] [..]
1931[FINISHED] release [optimized] target(s) in [..]
1932[INSTALLING] [..]
1933[INSTALLED] package `bar v0.1.0 ([..]/bar)` (executable `bar[EXE]`)
1934[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
1935",
1936 )
1937 .run();
1938}
1939
1940#[cargo_test]
1941fn install_ignores_local_cargo_config() {
1942 pkg("bar", "0.0.1");
1943
1944 let p = project()
1945 .file(
1946 ".cargo/config",
1947 r#"
1948 [build]
1949 target = "non-existing-target"
1950 "#,
1951 )
1952 .file("src/main.rs", "fn main() {}")
1953 .build();
1954
1955 p.cargo("install bar").run();
1956 assert_has_installed_exe(cargo_home(), "bar");
1957}
1958
1959#[cargo_test]
1960fn install_ignores_unstable_table_in_local_cargo_config() {
1961 pkg("bar", "0.0.1");
1962
1963 let p = project()
1964 .file(
1965 ".cargo/config",
1966 r#"
1967 [unstable]
1968 build-std = ["core"]
1969 "#,
1970 )
1971 .file("src/main.rs", "fn main() {}")
1972 .build();
1973
1974 p.cargo("install bar")
1975 .masquerade_as_nightly_cargo(&["build-std"])
1976 .run();
1977 assert_has_installed_exe(cargo_home(), "bar");
1978}
1979
1980#[cargo_test]
1981fn install_global_cargo_config() {
1982 pkg("bar", "0.0.1");
1983
1984 let config = cargo_home().join("config");
1985 let mut toml = fs::read_to_string(&config).unwrap_or_default();
1986
1987 toml.push_str(
1988 r#"
1989 [build]
1990 target = 'nonexistent'
1991 "#,
1992 );
1993 fs::write(&config, toml).unwrap();
1994
1995 cargo_process("install bar")
1996 .with_status(101)
1997 .with_stderr_contains("[..]--target nonexistent[..]")
1998 .run();
1999}
2000
2001#[cargo_test]
2002fn install_path_config() {
2003 project()
2004 .file(
2005 ".cargo/config",
2006 r#"
2007 [build]
2008 target = 'nonexistent'
2009 "#,
2010 )
2011 .file("src/main.rs", "fn main() {}")
2012 .build();
2013 cargo_process("install --path foo")
2014 .with_status(101)
2015 .with_stderr_contains("[..]--target nonexistent[..]")
2016 .run();
2017}
2018
2019#[cargo_test]
2020fn install_version_req() {
2021 // Try using a few versionreq styles.
2022 pkg("foo", "0.0.3");
2023 pkg("foo", "1.0.4");
2024 pkg("foo", "1.0.5");
2025 cargo_process("install foo --version=*")
2026 .with_stderr_does_not_contain("[WARNING][..]is not a valid semver[..]")
2027 .with_stderr_contains("[INSTALLING] foo v1.0.5")
2028 .run();
2029 cargo_process("uninstall foo").run();
2030 cargo_process("install foo --version=^1.0")
2031 .with_stderr_does_not_contain("[WARNING][..]is not a valid semver[..]")
2032 .with_stderr_contains("[INSTALLING] foo v1.0.5")
2033 .run();
2034 cargo_process("uninstall foo").run();
2035 cargo_process("install foo --version=0.0.*")
2036 .with_stderr_does_not_contain("[WARNING][..]is not a valid semver[..]")
2037 .with_stderr_contains("[INSTALLING] foo v0.0.3")
2038 .run();
2039}
2040
2041#[cargo_test]
2042fn git_install_reads_workspace_manifest() {
2043 let p = git::repo(&paths::root().join("foo"))
2044 .file(
2045 "Cargo.toml",
2046 r#"
2047 [workspace]
2048 members = ["bin1"]
2049
2050 [profile.release]
2051 incremental = 3
2052 "#,
2053 )
2054 .file("bin1/Cargo.toml", &basic_manifest("bin1", "0.1.0"))
2055 .file(
2056 "bin1/src/main.rs",
2057 r#"fn main() { println!("Hello, world!"); }"#,
2058 )
2059 .build();
2060
2061 cargo_process(&format!("install --git {}", p.url().to_string()))
2062 .with_status(101)
2063 .with_stderr_contains(" invalid type: integer `3`[..]")
2064 .run();
2065}
2066
2067#[cargo_test]
2068fn install_git_with_symlink_home() {
2069 // Ensure that `cargo install` with a git repo is OK when CARGO_HOME is a
2070 // symlink, and uses an build script.
2071 if !symlink_supported() {
2072 return;
2073 }
2074 let p = git::new("foo", |p| {
2075 p.file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
2076 .file("src/main.rs", "fn main() {}")
2077 // This triggers discover_git_and_list_files for detecting changed files.
2078 .file("build.rs", "fn main() {}")
2079 });
2080 #[cfg(unix)]
2081 use std::os::unix::fs::symlink;
2082 #[cfg(windows)]
2083 use std::os::windows::fs::symlink_dir as symlink;
2084
2085 let actual = paths::root().join("actual-home");
2086 t!(std::fs::create_dir(&actual));
2087 t!(symlink(&actual, paths::home().join(".cargo")));
2088 cargo_process("install --git")
2089 .arg(p.url().to_string())
2090 .with_stderr(
2091 "\
2092[UPDATING] git repository [..]
2093[INSTALLING] foo v1.0.0 [..]
2094[COMPILING] foo v1.0.0 [..]
2095[FINISHED] [..]
2096[INSTALLING] [..]home/.cargo/bin/foo[..]
2097[INSTALLED] package `foo [..]
2098[WARNING] be sure to add [..]
2099",
2100 )
2101 .run();
2102}
2103
2104#[cargo_test]
2105fn install_yanked_cargo_package() {
2106 Package::new("baz", "0.0.1").yanked(true).publish();
2107 cargo_process("install baz --version 0.0.1")
2108 .with_status(101)
2109 .with_stderr_contains(
2110 "\
2111[ERROR] cannot install package `baz`, it has been yanked from registry `crates-io`
2112",
2113 )
2114 .run();
2115}
2116
2117#[cargo_test]
2118fn install_cargo_package_in_a_patched_workspace() {
2119 pkg("foo", "0.1.0");
2120 pkg("fizz", "1.0.0");
2121
2122 let p = project()
2123 .file(
2124 "Cargo.toml",
2125 r#"
2126 [package]
2127 name = "bar"
2128 version = "0.1.0"
2129 authors = []
2130
2131 [workspace]
2132 members = ["baz"]
2133 "#,
2134 )
2135 .file("src/main.rs", "fn main() {}")
2136 .file(
2137 "baz/Cargo.toml",
2138 r#"
2139 [package]
2140 name = "baz"
2141 version = "0.1.0"
2142 authors = []
2143
2144 [dependencies]
2145 fizz = "1"
2146
2147 [patch.crates-io]
2148 fizz = { version = "=1.0.0" }
2149 "#,
2150 )
2151 .file("baz/src/lib.rs", "")
2152 .build();
2153
2154 let stderr = "\
2155[WARNING] patch for the non root package will be ignored, specify patch at the workspace root:
2156package: [..]/foo/baz/Cargo.toml
2157workspace: [..]/foo/Cargo.toml
2158";
2159 p.cargo("check").with_stderr_contains(&stderr).run();
2160
2161 // A crate installation must not emit any message from a workspace under
2162 // current working directory.
2163 // See https://github.com/rust-lang/cargo/issues/8619
2164 p.cargo("install foo")
2165 .with_stderr(
2166 "\
2167[UPDATING] `[..]` index
2168[DOWNLOADING] crates ...
2169[DOWNLOADED] foo v0.1.0 (registry [..])
2170[INSTALLING] foo v0.1.0
2171[COMPILING] foo v0.1.0
2172[FINISHED] release [optimized] target(s) in [..]
2173[INSTALLING] [..]foo[EXE]
2174[INSTALLED] package `foo v0.1.0` (executable `foo[EXE]`)
2175[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
2176",
2177 )
2178 .run();
2179 assert_has_installed_exe(cargo_home(), "foo");
2180}
2181
2182#[cargo_test]
2183fn locked_install_without_published_lockfile() {
2184 Package::new("foo", "0.1.0")
2185 .file("src/main.rs", "//! Some docs\nfn main() {}")
2186 .publish();
2187
2188 cargo_process("install foo --locked")
2189 .with_stderr_contains("[WARNING] no Cargo.lock file published in foo v0.1.0")
2190 .run();
2191}
2192
2193#[cargo_test]
2194fn install_semver_metadata() {
2195 // Check trying to install a package that uses semver metadata.
2196 // This uses alt registry because the bug this is exercising doesn't
2197 // trigger with a replaced source.
2198 registry::alt_init();
2199 Package::new("foo", "1.0.0+abc")
2200 .alternative(true)
2201 .file("src/main.rs", "fn main() {}")
2202 .publish();
2203
2204 cargo_process("install foo --registry alternative --version 1.0.0+abc").run();
2205 cargo_process("install foo --registry alternative")
2206 .with_stderr("\
2207[UPDATING] `alternative` index
2208[IGNORED] package `foo v1.0.0+abc (registry `alternative`)` is already installed, use --force to override
2209[WARNING] be sure to add [..]
2210")
2211 .run();
2212 // "Updating" is not displayed here due to the --version fast-path.
2213 cargo_process("install foo --registry alternative --version 1.0.0+abc")
2214 .with_stderr("\
2215[IGNORED] package `foo v1.0.0+abc (registry `alternative`)` is already installed, use --force to override
2216[WARNING] be sure to add [..]
2217")
2218 .run();
2219 cargo_process("install foo --registry alternative --version 1.0.0 --force")
2220 .with_stderr(
2221 "\
2222[UPDATING] `alternative` index
2223[INSTALLING] foo v1.0.0+abc (registry `alternative`)
2224[COMPILING] foo v1.0.0+abc (registry `alternative`)
2225[FINISHED] [..]
2226[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]
2227[REPLACED] package [..]
2228[WARNING] be sure to add [..]
2229",
2230 )
2231 .run();
2232 // Check that from a fresh cache will work without metadata, too.
2233 paths::home().join(".cargo/registry").rm_rf();
2234 paths::home().join(".cargo/bin").rm_rf();
2235 cargo_process("install foo --registry alternative --version 1.0.0")
2236 .with_stderr(
2237 "\
2238[UPDATING] `alternative` index
2239[DOWNLOADING] crates ...
2240[DOWNLOADED] foo v1.0.0+abc (registry `alternative`)
2241[INSTALLING] foo v1.0.0+abc (registry `alternative`)
2242[COMPILING] foo v1.0.0+abc (registry `alternative`)
2243[FINISHED] [..]
2244[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]
2245[INSTALLED] package `foo v1.0.0+abc (registry `alternative`)` (executable `foo[EXE]`)
2246[WARNING] be sure to add [..]
2247",
2248 )
2249 .run();
2250}
2251
2252#[cargo_test]
2253fn no_auto_fix_note() {
2254 Package::new("auto_fix", "0.0.1")
2255 .file("src/lib.rs", "use std::io;")
2256 .file(
2257 "src/main.rs",
2258 &format!("extern crate {}; use std::io; fn main() {{}}", "auto_fix"),
2259 )
2260 .publish();
2261
2262 // This should not contain a suggestion to run `cargo fix`
2263 //
2264 // This is checked by matching the full output as `with_stderr_does_not_contain`
2265 // can be brittle
2266 cargo_process("install auto_fix")
2267 .with_stderr(
2268 "\
2269[UPDATING] `[..]` index
2270[DOWNLOADING] crates ...
2271[DOWNLOADED] auto_fix v0.0.1 (registry [..])
2272[INSTALLING] auto_fix v0.0.1
2273[COMPILING] auto_fix v0.0.1
2274[FINISHED] release [optimized] target(s) in [..]
2275[INSTALLING] [CWD]/home/.cargo/bin/auto_fix[EXE]
2276[INSTALLED] package `auto_fix v0.0.1` (executable `auto_fix[EXE]`)
2277[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
2278",
2279 )
2280 .run();
2281 assert_has_installed_exe(cargo_home(), "auto_fix");
2282
2283 cargo_process("uninstall auto_fix")
2284 .with_stderr("[REMOVING] [CWD]/home/.cargo/bin/auto_fix[EXE]")
2285 .run();
2286 assert_has_not_installed_exe(cargo_home(), "auto_fix");
2287}
2288
2289#[cargo_test]
2290fn failed_install_retains_temp_directory() {
2291 // Verifies that the temporary directory persists after a build failure.
2292 Package::new("foo", "0.0.1")
2293 .file("src/main.rs", "x")
2294 .publish();
2295 let err = cargo_process("install foo").exec_with_output().unwrap_err();
2296 let err = err.downcast::<ProcessError>().unwrap();
2297 let stderr = String::from_utf8(err.stderr.unwrap()).unwrap();
2298 compare::match_contains(
2299 "\
2300[UPDATING] `dummy-registry` index
2301[DOWNLOADING] crates ...
2302[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)
2303[INSTALLING] foo v0.0.1
2304[COMPILING] foo v0.0.1
2305",
2306 &stderr,
2307 None,
2308 )
2309 .unwrap();
2310 compare::match_contains(
fe692bf9
FG
2311 "error: failed to compile `foo v0.0.1`, intermediate artifacts can be found at \
2312 `[..]`.\nTo reuse those artifacts with a future compilation, set the environment \
2313 variable `CARGO_TARGET_DIR` to that path.",
0a29b90c
FG
2314 &stderr,
2315 None,
2316 )
2317 .unwrap();
2318
2319 // Find the path in the output.
781aab86
FG
2320 let stderr = stderr.split_once("found at `").unwrap().1;
2321 let end = stderr.find('.').unwrap() - 1;
2322 let path = Path::new(&stderr[..end]);
0a29b90c
FG
2323 assert!(path.exists());
2324 assert!(path.join("release/deps").exists());
2325}
2326
2327#[cargo_test]
2328fn sparse_install() {
2329 // Checks for an issue where uninstalling something corrupted
2330 // the SourceIds of sparse registries.
2331 // See https://github.com/rust-lang/cargo/issues/11751
2332 let _registry = registry::RegistryBuilder::new().http_index().build();
2333
2334 pkg("foo", "0.0.1");
2335 pkg("bar", "0.0.1");
2336
2337 cargo_process("install foo --registry dummy-registry")
2338 .with_stderr(
2339 "\
2340[UPDATING] `dummy-registry` index
2341[DOWNLOADING] crates ...
2342[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)
2343[INSTALLING] foo v0.0.1 (registry `dummy-registry`)
2344[UPDATING] `dummy-registry` index
2345[COMPILING] foo v0.0.1 (registry `dummy-registry`)
2346[FINISHED] release [optimized] target(s) in [..]
2347[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]
2348[INSTALLED] package `foo v0.0.1 (registry `dummy-registry`)` (executable `foo[EXE]`)
2349[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
2350",
2351 )
2352 .run();
2353 assert_has_installed_exe(cargo_home(), "foo");
2354 let assert_v1 = |expected| {
2355 let v1 = fs::read_to_string(paths::home().join(".cargo/.crates.toml")).unwrap();
2356 compare::assert_match_exact(expected, &v1);
2357 };
2358 assert_v1(
2359 r#"[v1]
2360"foo 0.0.1 (sparse+http://127.0.0.1:[..]/index/)" = ["foo[EXE]"]
2361"#,
2362 );
2363 cargo_process("install bar").run();
2364 assert_has_installed_exe(cargo_home(), "bar");
2365 assert_v1(
2366 r#"[v1]
2367"bar 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = ["bar[EXE]"]
2368"foo 0.0.1 (sparse+http://127.0.0.1:[..]/index/)" = ["foo[EXE]"]
2369"#,
2370 );
2371
2372 cargo_process("uninstall bar")
2373 .with_stderr("[REMOVING] [CWD]/home/.cargo/bin/bar[EXE]")
2374 .run();
2375 assert_has_not_installed_exe(cargo_home(), "bar");
2376 assert_v1(
2377 r#"[v1]
2378"foo 0.0.1 (sparse+http://127.0.0.1:[..]/index/)" = ["foo[EXE]"]
2379"#,
2380 );
2381 cargo_process("uninstall foo")
2382 .with_stderr("[REMOVING] [CWD]/home/.cargo/bin/foo[EXE]")
2383 .run();
2384 assert_has_not_installed_exe(cargo_home(), "foo");
2385 assert_v1(
2386 r#"[v1]
2387"#,
2388 );
2389}
49aad941
FG
2390
2391#[cargo_test]
2392fn self_referential() {
2393 // Some packages build-dep on prior versions of themselves.
2394 Package::new("foo", "0.0.1")
2395 .file("src/lib.rs", "fn hello() {}")
2396 .file("src/main.rs", "fn main() {}")
2397 .file("build.rs", "fn main() {}")
2398 .publish();
2399 Package::new("foo", "0.0.2")
2400 .file("src/lib.rs", "fn hello() {}")
2401 .file("src/main.rs", "fn main() {}")
2402 .file("build.rs", "fn main() {}")
2403 .build_dep("foo", "0.0.1")
2404 .publish();
2405
2406 cargo_process("install foo")
2407 .with_stderr(
2408 "\
2409[UPDATING] `[..]` index
2410[DOWNLOADING] crates ...
2411[DOWNLOADED] foo v0.0.2 (registry [..])
2412[INSTALLING] foo v0.0.2
2413[DOWNLOADING] crates ...
2414[DOWNLOADED] foo v0.0.1 (registry [..])
2415[COMPILING] foo v0.0.1
2416[COMPILING] foo v0.0.2
2417[FINISHED] release [optimized] target(s) in [..]
2418[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
2419[INSTALLED] package `foo v0.0.2` (executable `foo[EXE]`)
2420[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
2421",
2422 )
2423 .run();
2424 assert_has_installed_exe(cargo_home(), "foo");
2425}
2426
2427#[cargo_test]
2428fn ambiguous_registry_vs_local_package() {
2429 // Correctly install 'foo' from a local package, even if that package also
2430 // depends on a registry dependency named 'foo'.
2431 Package::new("foo", "0.0.1")
2432 .file("src/lib.rs", "fn hello() {}")
2433 .publish();
2434
2435 let p = project()
2436 .file("src/main.rs", "fn main() {}")
2437 .file(
2438 "Cargo.toml",
2439 r#"
2440 [package]
2441 name = "foo"
2442 version = "0.1.0"
2443 authors = []
2444 edition = "2021"
2445
2446 [dependencies]
2447 foo = "0.0.1"
2448 "#,
2449 )
2450 .build();
2451
2452 cargo_process("install --path")
2453 .arg(p.root())
2454 .with_stderr(
2455 "\
2456[INSTALLING] foo v0.1.0 ([..])
2457[UPDATING] `[..]` index
2458[DOWNLOADING] crates ...
2459[DOWNLOADED] foo v0.0.1 (registry [..])
2460[COMPILING] foo v0.0.1
2461[COMPILING] foo v0.1.0 ([..])
2462[FINISHED] release [optimized] target(s) in [..]
2463[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
2464[INSTALLED] package `foo v0.1.0 ([..])` (executable `foo[EXE]`)
2465[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
2466",
2467 )
2468 .run();
2469 assert_has_installed_exe(cargo_home(), "foo");
2470}
781aab86
FG
2471
2472#[cargo_test]
2473fn install_with_redundant_default_mode() {
2474 pkg("foo", "0.0.1");
2475
2476 cargo_process("install foo --release")
2477 .with_stderr(
2478 "\
2479error: unexpected argument '--release' found
2480
2481 tip: `--release` is the default for `cargo install`; instead `--debug` is supported
2482
ed00b5ec 2483Usage: cargo[EXE] install [OPTIONS] [CRATE[@<VER>]]...
781aab86
FG
2484
2485For more information, try '--help'.
2486",
2487 )
2488 .with_status(1)
2489 .run();
2490}
ed00b5ec
FG
2491
2492#[cargo_test]
2493fn install_incompat_msrv() {
2494 Package::new("foo", "0.1.0")
2495 .file("src/main.rs", "fn main() {}")
2496 .rust_version("1.30")
2497 .publish();
2498 Package::new("foo", "0.2.0")
2499 .file("src/main.rs", "fn main() {}")
2500 .rust_version("1.9876.0")
2501 .publish();
2502
2503 cargo_process("install foo")
2504 .with_stderr("\
2505[UPDATING] `dummy-registry` index
2506[ERROR] cannot install package `foo 0.2.0`, it requires rustc 1.9876.0 or newer, while the currently active rustc version is [..]
2507`foo 0.1.0` supports rustc 1.30
2508")
2509 .with_status(101).run();
2510}
4b012472
FG
2511
2512fn assert_tracker_noexistence(key: &str) {
2513 let v1_data: toml::Value =
2514 toml::from_str(&fs::read_to_string(cargo_home().join(".crates.toml")).unwrap()).unwrap();
2515 let v2_data: serde_json::Value =
2516 serde_json::from_str(&fs::read_to_string(cargo_home().join(".crates2.json")).unwrap())
2517 .unwrap();
2518
2519 assert!(v1_data["v1"].get(key).is_none());
2520 assert!(v2_data["installs"][key].is_null());
2521}
2522
2523#[cargo_test]
2524fn uninstall_running_binary() {
2525 use std::io::Write;
2526
2527 Package::new("foo", "0.0.1")
2528 .file(
2529 "Cargo.toml",
2530 r#"
2531 [package]
2532 name = "foo"
2533 version = "0.0.1"
2534 "#,
2535 )
2536 .file(
2537 "src/main.rs",
2538 r#"
2539 use std::net::TcpStream;
2540 use std::env::var;
2541 use std::io::Read;
2542 fn main() {
2543 for i in 0..2 {
2544 TcpStream::connect(&var("__ADDR__").unwrap()[..])
2545 .unwrap()
2546 .read_to_end(&mut Vec::new())
2547 .unwrap();
2548 }
2549 }
2550 "#,
2551 )
2552 .publish();
2553
2554 cargo_process("install foo")
2555 .with_stderr(
2556 "\
2557[UPDATING] `[..]` index
2558[DOWNLOADING] crates ...
2559[DOWNLOADED] foo v0.0.1 (registry [..])
2560[INSTALLING] foo v0.0.1
2561[COMPILING] foo v0.0.1
2562[FINISHED] release [optimized] target(s) in [..]
2563[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
2564[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)
2565[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
2566",
2567 )
2568 .run();
2569 assert_has_installed_exe(cargo_home(), "foo");
2570
2571 let foo_bin = cargo_home().join("bin").join(exe("foo"));
2572 let l = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
2573 let addr = l.local_addr().unwrap().to_string();
2574 let t = thread::spawn(move || {
2575 ProcessBuilder::new(foo_bin)
2576 .env("__ADDR__", addr)
2577 .exec()
2578 .unwrap();
2579 });
2580 let key = "foo 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)";
2581
2582 #[cfg(windows)]
2583 {
2584 // Ensure foo is running before the first `cargo uninstall` call
2585 l.accept().unwrap().0.write_all(&[1]).unwrap();
2586 cargo_process("uninstall foo")
2587 .with_status(101)
2588 .with_stderr_contains("[ERROR] failed to remove file `[CWD]/home/.cargo/bin/foo[EXE]`")
2589 .run();
2590 // Ensure foo is stopped before the second `cargo uninstall` call
2591 l.accept().unwrap().0.write_all(&[1]).unwrap();
2592 t.join().unwrap();
2593 cargo_process("uninstall foo")
2594 .with_stderr("[REMOVING] [CWD]/home/.cargo/bin/foo[EXE]")
2595 .run();
2596 };
2597
2598 #[cfg(not(windows))]
2599 {
2600 // Ensure foo is running before the first `cargo uninstall` call
2601 l.accept().unwrap().0.write_all(&[1]).unwrap();
2602 cargo_process("uninstall foo")
2603 .with_stderr("[REMOVING] [CWD]/home/.cargo/bin/foo[EXE]")
2604 .run();
2605 l.accept().unwrap().0.write_all(&[1]).unwrap();
2606 t.join().unwrap();
2607 };
2608
2609 assert_has_not_installed_exe(cargo_home(), "foo");
2610 assert_tracker_noexistence(key);
2611
2612 cargo_process("install foo")
2613 .with_stderr(
2614 "\
2615[UPDATING] `[..]` index
2616[INSTALLING] foo v0.0.1
2617[COMPILING] foo v0.0.1
2618[FINISHED] release [optimized] target(s) in [..]
2619[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
2620[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)
2621[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
2622",
2623 )
2624 .run();
2625}