]> git.proxmox.com Git - rustc.git/blame - src/tools/cargo/tests/testsuite/tree.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / src / tools / cargo / tests / testsuite / tree.rs
CommitLineData
0a29b90c
FG
1//! Tests for the `cargo tree` command.
2
3use super::features2::switch_to_resolver_2;
4use cargo_test_support::cross_compile::{self, alternate};
5use cargo_test_support::registry::{Dependency, Package};
6use cargo_test_support::{basic_manifest, git, project, rustc_host, Project};
7
8fn make_simple_proj() -> Project {
9 Package::new("c", "1.0.0").publish();
10 Package::new("b", "1.0.0").dep("c", "1.0").publish();
11 Package::new("a", "1.0.0").dep("b", "1.0").publish();
12 Package::new("bdep", "1.0.0").dep("b", "1.0").publish();
13 Package::new("devdep", "1.0.0").dep("b", "1.0.0").publish();
14
15 project()
16 .file(
17 "Cargo.toml",
18 r#"
19 [package]
20 name = "foo"
21 version = "0.1.0"
22
23 [dependencies]
24 a = "1.0"
25 c = "1.0"
26
27 [build-dependencies]
28 bdep = "1.0"
29
30 [dev-dependencies]
31 devdep = "1.0"
32 "#,
33 )
34 .file("src/lib.rs", "")
35 .file("build.rs", "fn main() {}")
36 .build()
37}
38
39#[cargo_test]
40fn simple() {
41 // A simple test with a few different dependencies.
42 let p = make_simple_proj();
43
44 p.cargo("tree")
45 .with_stdout(
46 "\
47foo v0.1.0 ([..]/foo)
48├── a v1.0.0
49│ └── b v1.0.0
50│ └── c v1.0.0
51└── c v1.0.0
52[build-dependencies]
53└── bdep v1.0.0
54 └── b v1.0.0 (*)
55[dev-dependencies]
56└── devdep v1.0.0
57 └── b v1.0.0 (*)
58",
59 )
60 .run();
61
62 p.cargo("tree -p bdep")
63 .with_stdout(
64 "\
65bdep v1.0.0
66└── b v1.0.0
67 └── c v1.0.0
68",
69 )
70 .run();
71}
72
73#[cargo_test]
74fn virtual_workspace() {
75 // Multiple packages in a virtual workspace.
76 Package::new("somedep", "1.0.0").publish();
77 let p = project()
78 .file(
79 "Cargo.toml",
80 r#"
81 [workspace]
82 members = ["a", "baz", "c"]
83 "#,
84 )
85 .file("a/Cargo.toml", &basic_manifest("a", "1.0.0"))
86 .file("a/src/lib.rs", "")
87 .file(
88 "baz/Cargo.toml",
89 r#"
90 [package]
91 name = "baz"
92 version = "0.1.0"
93
94 [dependencies]
95 c = { path = "../c" }
96 somedep = "1.0"
97 "#,
98 )
99 .file("baz/src/lib.rs", "")
100 .file("c/Cargo.toml", &basic_manifest("c", "1.0.0"))
101 .file("c/src/lib.rs", "")
102 .build();
103
104 p.cargo("tree")
105 .with_stdout(
106 "\
107a v1.0.0 ([..]/foo/a)
108
109baz v0.1.0 ([..]/foo/baz)
110├── c v1.0.0 ([..]/foo/c)
111└── somedep v1.0.0
112
113c v1.0.0 ([..]/foo/c)
114",
115 )
116 .run();
117
118 p.cargo("tree -p a").with_stdout("a v1.0.0 [..]").run();
119
120 p.cargo("tree")
121 .cwd("baz")
122 .with_stdout(
123 "\
124baz v0.1.0 ([..]/foo/baz)
125├── c v1.0.0 ([..]/foo/c)
126└── somedep v1.0.0
127",
128 )
129 .run();
130
131 // exclude baz
132 p.cargo("tree --workspace --exclude baz")
133 .with_stdout(
134 "\
135a v1.0.0 ([..]/foo/a)
136
137c v1.0.0 ([..]/foo/c)
138",
139 )
140 .run();
141
142 // exclude glob '*z'
143 p.cargo("tree --workspace --exclude '*z'")
144 .with_stdout(
145 "\
146a v1.0.0 ([..]/foo/a)
147
148c v1.0.0 ([..]/foo/c)
149",
150 )
151 .run();
152
153 // include glob '*z'
154 p.cargo("tree -p '*z'")
155 .with_stdout(
156 "\
157baz v0.1.0 ([..]/foo/baz)
158├── c v1.0.0 ([..]/foo/c)
159└── somedep v1.0.0
160",
161 )
162 .run();
163}
164
165#[cargo_test]
166fn dedupe_edges() {
167 // Works around https://github.com/rust-lang/cargo/issues/7985
168 Package::new("bitflags", "1.0.0").publish();
169 Package::new("manyfeat", "1.0.0")
170 .feature("f1", &[])
171 .feature("f2", &[])
172 .feature("f3", &[])
173 .dep("bitflags", "1.0")
174 .publish();
175 Package::new("a", "1.0.0")
176 .feature_dep("manyfeat", "1.0", &["f1"])
177 .publish();
178 Package::new("b", "1.0.0")
179 .feature_dep("manyfeat", "1.0", &["f2"])
180 .publish();
181 Package::new("c", "1.0.0")
182 .feature_dep("manyfeat", "1.0", &["f3"])
183 .publish();
184
185 let p = project()
186 .file(
187 "Cargo.toml",
188 r#"
189 [package]
190 name = "foo"
191 version = "0.1.0"
192
193 [dependencies]
194 a = "1.0"
195 b = "1.0"
196 c = "1.0"
197 "#,
198 )
199 .file("src/lib.rs", "")
200 .build();
201
202 p.cargo("tree")
203 .with_stdout(
204 "\
205foo v0.1.0 ([..]/foo)
206├── a v1.0.0
207│ └── manyfeat v1.0.0
208│ └── bitflags v1.0.0
209├── b v1.0.0
210│ └── manyfeat v1.0.0 (*)
211└── c v1.0.0
212 └── manyfeat v1.0.0 (*)
213",
214 )
215 .run();
216}
217
218#[cargo_test]
219fn renamed_deps() {
220 // Handles renamed dependencies.
221 Package::new("one", "1.0.0").publish();
222 Package::new("two", "1.0.0").publish();
223 Package::new("bar", "1.0.0").dep("one", "1.0").publish();
224 Package::new("bar", "2.0.0").dep("two", "1.0").publish();
225 let p = project()
226 .file(
227 "Cargo.toml",
228 r#"
229 [package]
230 name = "foo"
231 version = "1.0.0"
232
233 [dependencies]
234 bar1 = {version = "1.0", package="bar"}
235 bar2 = {version = "2.0", package="bar"}
236 "#,
237 )
238 .file("src/lib.rs", "")
239 .build();
240
241 p.cargo("tree")
242 .with_stdout(
243 "\
244foo v1.0.0 ([..]/foo)
245├── bar v1.0.0
246│ └── one v1.0.0
247└── bar v2.0.0
248 └── two v1.0.0
249",
250 )
251 .run();
252}
253
254#[cargo_test]
255fn source_kinds() {
256 // Handles git and path sources.
257 Package::new("regdep", "1.0.0").publish();
258 let git_project = git::new("gitdep", |p| {
259 p.file("Cargo.toml", &basic_manifest("gitdep", "1.0.0"))
260 .file("src/lib.rs", "")
261 });
262 let p = project()
263 .file(
264 "Cargo.toml",
265 &format!(
266 r#"
267 [package]
268 name = "foo"
269 version = "0.1.0"
270
271 [dependencies]
272 regdep = "1.0"
273 pathdep = {{ path = "pathdep" }}
274 gitdep = {{ git = "{}" }}
275 "#,
276 git_project.url()
277 ),
278 )
279 .file("src/lib.rs", "")
280 .file("pathdep/Cargo.toml", &basic_manifest("pathdep", "1.0.0"))
281 .file("pathdep/src/lib.rs", "")
282 .build();
283
284 p.cargo("tree")
285 .with_stdout(
286 "\
287foo v0.1.0 ([..]/foo)
288├── gitdep v1.0.0 (file://[..]/gitdep#[..])
289├── pathdep v1.0.0 ([..]/foo/pathdep)
290└── regdep v1.0.0
291",
292 )
293 .run();
294}
295
296#[cargo_test]
297fn features() {
298 // Exercises a variety of feature behaviors.
299 Package::new("optdep_default", "1.0.0").publish();
300 Package::new("optdep", "1.0.0").publish();
301 let p = project()
302 .file(
303 "Cargo.toml",
304 r#"
305 [package]
306 name = "a"
307 version = "0.1.0"
308
309 [dependencies]
310 optdep_default = { version = "1.0", optional = true }
311 optdep = { version = "1.0", optional = true }
312
313 [features]
314 default = ["optdep_default"]
315 "#,
316 )
317 .file("src/lib.rs", "")
318 .build();
319
320 p.cargo("tree")
321 .with_stdout(
322 "\
323a v0.1.0 ([..]/foo)
324└── optdep_default v1.0.0
325",
326 )
327 .run();
328
329 p.cargo("tree --no-default-features")
330 .with_stdout(
331 "\
332a v0.1.0 ([..]/foo)
333",
334 )
335 .run();
336
337 p.cargo("tree --all-features")
338 .with_stdout(
339 "\
340a v0.1.0 ([..]/foo)
341├── optdep v1.0.0
342└── optdep_default v1.0.0
343",
344 )
345 .run();
346
347 p.cargo("tree --features optdep")
348 .with_stdout(
349 "\
350a v0.1.0 ([..]/foo)
351├── optdep v1.0.0
352└── optdep_default v1.0.0
353",
354 )
355 .run();
356}
357
358#[cargo_test]
359fn filters_target() {
360 // --target flag
361 if cross_compile::disabled() {
362 return;
363 }
364 Package::new("targetdep", "1.0.0").publish();
365 Package::new("hostdep", "1.0.0").publish();
366 Package::new("devdep", "1.0.0").publish();
367 Package::new("build_target_dep", "1.0.0").publish();
368 Package::new("build_host_dep", "1.0.0")
369 .target_dep("targetdep", "1.0", alternate())
370 .target_dep("hostdep", "1.0", rustc_host())
371 .publish();
372 Package::new("pm_target", "1.0.0")
373 .proc_macro(true)
374 .publish();
375 Package::new("pm_host", "1.0.0").proc_macro(true).publish();
376
377 let p = project()
378 .file(
379 "Cargo.toml",
380 &format!(
381 r#"
382 [package]
383 name = "foo"
384 version = "0.1.0"
385
386 [target.'{alt}'.dependencies]
387 targetdep = "1.0"
388 pm_target = "1.0"
389
390 [target.'{host}'.dependencies]
391 hostdep = "1.0"
392 pm_host = "1.0"
393
394 [target.'{alt}'.dev-dependencies]
395 devdep = "1.0"
396
397 [target.'{alt}'.build-dependencies]
398 build_target_dep = "1.0"
399
400 [target.'{host}'.build-dependencies]
401 build_host_dep = "1.0"
402 "#,
403 alt = alternate(),
404 host = rustc_host()
405 ),
406 )
407 .file("src/lib.rs", "")
408 .file("build.rs", "fn main() {}")
409 .build();
410
411 p.cargo("tree")
412 .with_stdout(
413 "\
414foo v0.1.0 ([..]/foo)
415├── hostdep v1.0.0
416└── pm_host v1.0.0 (proc-macro)
417[build-dependencies]
418└── build_host_dep v1.0.0
419 └── hostdep v1.0.0
420",
421 )
422 .run();
423
424 p.cargo("tree --target")
425 .arg(alternate())
426 .with_stdout(
427 "\
428foo v0.1.0 ([..]/foo)
429├── pm_target v1.0.0 (proc-macro)
430└── targetdep v1.0.0
431[build-dependencies]
432└── build_host_dep v1.0.0
433 └── hostdep v1.0.0
434[dev-dependencies]
435└── devdep v1.0.0
436",
437 )
438 .run();
439
440 p.cargo("tree --target")
441 .arg(rustc_host())
442 .with_stdout(
443 "\
444foo v0.1.0 ([..]/foo)
445├── hostdep v1.0.0
446└── pm_host v1.0.0 (proc-macro)
447[build-dependencies]
448└── build_host_dep v1.0.0
449 └── hostdep v1.0.0
450",
451 )
452 .run();
453
454 p.cargo("tree --target=all")
455 .with_stdout(
456 "\
457foo v0.1.0 ([..]/foo)
458├── hostdep v1.0.0
459├── pm_host v1.0.0 (proc-macro)
460├── pm_target v1.0.0 (proc-macro)
461└── targetdep v1.0.0
462[build-dependencies]
463├── build_host_dep v1.0.0
464│ ├── hostdep v1.0.0
465│ └── targetdep v1.0.0
466└── build_target_dep v1.0.0
467[dev-dependencies]
468└── devdep v1.0.0
469",
470 )
471 .run();
472
473 // no-proc-macro
474 p.cargo("tree --target=all -e no-proc-macro")
475 .with_stdout(
476 "\
477foo v0.1.0 ([..]/foo)
478├── hostdep v1.0.0
479└── targetdep v1.0.0
480[build-dependencies]
481├── build_host_dep v1.0.0
482│ ├── hostdep v1.0.0
483│ └── targetdep v1.0.0
484└── build_target_dep v1.0.0
485[dev-dependencies]
486└── devdep v1.0.0
487",
488 )
489 .run();
490}
491
492#[cargo_test]
493fn no_selected_target_dependency() {
494 // --target flag
495 if cross_compile::disabled() {
496 return;
497 }
498 Package::new("targetdep", "1.0.0").publish();
499
500 let p = project()
501 .file(
502 "Cargo.toml",
503 &format!(
504 r#"
505 [package]
506 name = "foo"
507 version = "0.1.0"
508
509 [target.'{alt}'.dependencies]
510 targetdep = "1.0"
511
512 "#,
513 alt = alternate(),
514 ),
515 )
516 .file("src/lib.rs", "")
517 .file("build.rs", "fn main() {}")
518 .build();
519
520 p.cargo("tree")
521 .with_stdout(
522 "\
523foo v0.1.0 ([..]/foo)
524",
525 )
526 .run();
527
528 p.cargo("tree -i targetdep")
529 .with_stderr(
530 "\
531[WARNING] nothing to print.
532
533To find dependencies that require specific target platforms, \
534try to use option `--target all` first, and then narrow your search scope accordingly.
535",
536 )
537 .run();
538 p.cargo("tree -i targetdep --target all")
539 .with_stdout(
540 "\
541targetdep v1.0.0
542└── foo v0.1.0 ([..]/foo)
543",
544 )
545 .run();
546}
547
548#[cargo_test]
549fn dep_kinds() {
550 Package::new("inner-devdep", "1.0.0").publish();
551 Package::new("inner-builddep", "1.0.0").publish();
552 Package::new("inner-normal", "1.0.0").publish();
553 Package::new("inner-pm", "1.0.0").proc_macro(true).publish();
554 Package::new("inner-buildpm", "1.0.0")
555 .proc_macro(true)
556 .publish();
557 Package::new("normaldep", "1.0.0")
558 .dep("inner-normal", "1.0")
559 .dev_dep("inner-devdep", "1.0")
560 .build_dep("inner-builddep", "1.0")
561 .publish();
562 Package::new("devdep", "1.0.0")
563 .dep("inner-normal", "1.0")
564 .dep("inner-pm", "1.0")
565 .dev_dep("inner-devdep", "1.0")
566 .build_dep("inner-builddep", "1.0")
567 .build_dep("inner-buildpm", "1.0")
568 .publish();
569 Package::new("builddep", "1.0.0")
570 .dep("inner-normal", "1.0")
571 .dev_dep("inner-devdep", "1.0")
572 .build_dep("inner-builddep", "1.0")
573 .publish();
574 let p = project()
575 .file(
576 "Cargo.toml",
577 r#"
578 [package]
579 name = "foo"
580 version = "0.1.0"
581
582 [dependencies]
583 normaldep = "1.0"
584
585 [dev-dependencies]
586 devdep = "1.0"
587
588 [build-dependencies]
589 builddep = "1.0"
590 "#,
591 )
592 .file("src/lib.rs", "")
593 .build();
594
595 p.cargo("tree")
596 .with_stdout(
597 "\
598foo v0.1.0 ([..]/foo)
599└── normaldep v1.0.0
600 └── inner-normal v1.0.0
601 [build-dependencies]
602 └── inner-builddep v1.0.0
603[build-dependencies]
604└── builddep v1.0.0
605 └── inner-normal v1.0.0
606 [build-dependencies]
607 └── inner-builddep v1.0.0
608[dev-dependencies]
609└── devdep v1.0.0
610 ├── inner-normal v1.0.0
611 └── inner-pm v1.0.0 (proc-macro)
612 [build-dependencies]
613 ├── inner-builddep v1.0.0
614 └── inner-buildpm v1.0.0 (proc-macro)
615",
616 )
617 .run();
618
619 p.cargo("tree -e no-dev")
620 .with_stdout(
621 "\
622foo v0.1.0 ([..]/foo)
623└── normaldep v1.0.0
624 └── inner-normal v1.0.0
625 [build-dependencies]
626 └── inner-builddep v1.0.0
627[build-dependencies]
628└── builddep v1.0.0
629 └── inner-normal v1.0.0
630 [build-dependencies]
631 └── inner-builddep v1.0.0
632",
633 )
634 .run();
635
636 p.cargo("tree -e normal")
637 .with_stdout(
638 "\
639foo v0.1.0 ([..]/foo)
640└── normaldep v1.0.0
641 └── inner-normal v1.0.0
642",
643 )
644 .run();
645
646 p.cargo("tree -e dev,build")
647 .with_stdout(
648 "\
649foo v0.1.0 ([..]/foo)
650[build-dependencies]
651└── builddep v1.0.0
652 [build-dependencies]
653 └── inner-builddep v1.0.0
654[dev-dependencies]
655└── devdep v1.0.0
656 [build-dependencies]
657 ├── inner-builddep v1.0.0
658 └── inner-buildpm v1.0.0 (proc-macro)
659",
660 )
661 .run();
662
663 p.cargo("tree -e dev,build,no-proc-macro")
664 .with_stdout(
665 "\
666foo v0.1.0 ([..]/foo)
667[build-dependencies]
668└── builddep v1.0.0
669 [build-dependencies]
670 └── inner-builddep v1.0.0
671[dev-dependencies]
672└── devdep v1.0.0
673 [build-dependencies]
674 └── inner-builddep v1.0.0
675",
676 )
677 .run();
678}
679
680#[cargo_test]
681fn cyclic_dev_dep() {
682 // Cyclical dev-dependency and inverse flag.
683 let p = project()
684 .file(
685 "Cargo.toml",
686 r#"
687 [package]
688 name = "foo"
689 version = "0.1.0"
690
691 [dev-dependencies]
692 dev-dep = { path = "dev-dep" }
693 "#,
694 )
695 .file("src/lib.rs", "")
696 .file(
697 "dev-dep/Cargo.toml",
698 r#"
699 [package]
700 name = "dev-dep"
701 version = "0.1.0"
702
703 [dependencies]
704 foo = { path=".." }
705 "#,
706 )
707 .file("dev-dep/src/lib.rs", "")
708 .build();
709
710 p.cargo("tree")
711 .with_stdout(
712 "\
713foo v0.1.0 ([..]/foo)
714[dev-dependencies]
715└── dev-dep v0.1.0 ([..]/foo/dev-dep)
716 └── foo v0.1.0 ([..]/foo) (*)
717",
718 )
719 .run();
720
721 p.cargo("tree --invert foo")
722 .with_stdout(
723 "\
724foo v0.1.0 ([..]/foo)
725└── dev-dep v0.1.0 ([..]/foo/dev-dep)
726 [dev-dependencies]
727 └── foo v0.1.0 ([..]/foo) (*)
728",
729 )
730 .run();
731}
732
733#[cargo_test]
734fn invert() {
735 Package::new("b1", "1.0.0").dep("c", "1.0").publish();
736 Package::new("b2", "1.0.0").dep("d", "1.0").publish();
737 Package::new("c", "1.0.0").publish();
738 Package::new("d", "1.0.0").publish();
739 let p = project()
740 .file(
741 "Cargo.toml",
742 r#"
743 [package]
744 name = "foo"
745 version = "0.1.0"
746
747 [dependencies]
748 b1 = "1.0"
749 b2 = "1.0"
750 c = "1.0"
751 "#,
752 )
753 .file("src/lib.rs", "")
754 .build();
755
756 p.cargo("tree")
757 .with_stdout(
758 "\
759foo v0.1.0 ([..]/foo)
760├── b1 v1.0.0
761│ └── c v1.0.0
762├── b2 v1.0.0
763│ └── d v1.0.0
764└── c v1.0.0
765",
766 )
767 .run();
768
769 p.cargo("tree --invert c")
770 .with_stdout(
771 "\
772c v1.0.0
773├── b1 v1.0.0
774│ └── foo v0.1.0 ([..]/foo)
775└── foo v0.1.0 ([..]/foo)
776",
777 )
778 .run();
779}
780
781#[cargo_test]
782fn invert_with_build_dep() {
783 // -i for a common dependency between normal and build deps.
784 Package::new("common", "1.0.0").publish();
785 Package::new("bdep", "1.0.0").dep("common", "1.0").publish();
786 let p = project()
787 .file(
788 "Cargo.toml",
789 r#"
790 [package]
791 name = "foo"
792 version = "0.1.0"
793
794 [dependencies]
795 common = "1.0"
796
797 [build-dependencies]
798 bdep = "1.0"
799 "#,
800 )
801 .file("src/lib.rs", "")
802 .build();
803
804 p.cargo("tree")
805 .with_stdout(
806 "\
807foo v0.1.0 ([..]/foo)
808└── common v1.0.0
809[build-dependencies]
810└── bdep v1.0.0
811 └── common v1.0.0
812",
813 )
814 .run();
815
816 p.cargo("tree -i common")
817 .with_stdout(
818 "\
819common v1.0.0
820├── bdep v1.0.0
821│ [build-dependencies]
822│ └── foo v0.1.0 ([..]/foo)
823└── foo v0.1.0 ([..]/foo)
824",
825 )
826 .run();
827}
828
829#[cargo_test]
830fn no_indent() {
831 let p = make_simple_proj();
832
833 p.cargo("tree --prefix=none")
834 .with_stdout(
835 "\
836foo v0.1.0 ([..]/foo)
837a v1.0.0
838b v1.0.0
839c v1.0.0
840c v1.0.0
841bdep v1.0.0
842b v1.0.0 (*)
843devdep v1.0.0
844b v1.0.0 (*)
845",
846 )
847 .run();
848}
849
850#[cargo_test]
851fn prefix_depth() {
852 let p = make_simple_proj();
853
854 p.cargo("tree --prefix=depth")
855 .with_stdout(
856 "\
8570foo v0.1.0 ([..]/foo)
8581a v1.0.0
8592b v1.0.0
8603c v1.0.0
8611c v1.0.0
8621bdep v1.0.0
8632b v1.0.0 (*)
8641devdep v1.0.0
8652b v1.0.0 (*)
866",
867 )
868 .run();
869}
870
871#[cargo_test]
872fn no_dedupe() {
873 let p = make_simple_proj();
874
875 p.cargo("tree --no-dedupe")
876 .with_stdout(
877 "\
878foo v0.1.0 ([..]/foo)
879├── a v1.0.0
880│ └── b v1.0.0
881│ └── c v1.0.0
882└── c v1.0.0
883[build-dependencies]
884└── bdep v1.0.0
885 └── b v1.0.0
886 └── c v1.0.0
887[dev-dependencies]
888└── devdep v1.0.0
889 └── b v1.0.0
890 └── c v1.0.0
891",
892 )
893 .run();
894}
895
896#[cargo_test]
897fn no_dedupe_cycle() {
898 // --no-dedupe with a dependency cycle
899 let p = project()
900 .file(
901 "Cargo.toml",
902 r#"
903 [package]
904 name = "foo"
905 version = "0.1.0"
906
907 [dev-dependencies]
908 bar = {path = "bar"}
909 "#,
910 )
911 .file("src/lib.rs", "")
912 .file(
913 "bar/Cargo.toml",
914 r#"
915 [package]
916 name = "bar"
917 version = "0.1.0"
918
919 [dependencies]
920 foo = {path=".."}
921 "#,
922 )
923 .file("bar/src/lib.rs", "")
924 .build();
925
926 p.cargo("tree")
927 .with_stdout(
928 "\
929foo v0.1.0 ([..]/foo)
930[dev-dependencies]
931└── bar v0.1.0 ([..]/foo/bar)
932 └── foo v0.1.0 ([..]/foo) (*)
933",
934 )
935 .run();
936
937 p.cargo("tree --no-dedupe")
938 .with_stdout(
939 "\
940foo v0.1.0 ([..]/foo)
941[dev-dependencies]
942└── bar v0.1.0 ([..]/foo/bar)
943 └── foo v0.1.0 ([..]/foo) (*)
944",
945 )
946 .run();
947}
948
949#[cargo_test]
950fn duplicates() {
951 Package::new("dog", "1.0.0").publish();
952 Package::new("dog", "2.0.0").publish();
953 Package::new("cat", "1.0.0").publish();
954 Package::new("cat", "2.0.0").publish();
955 Package::new("dep", "1.0.0")
956 .dep("dog", "1.0")
957 .dep("cat", "1.0")
958 .publish();
959 let p = project()
960 .file(
961 "Cargo.toml",
962 r#"
963 [workspace]
964 members = ["a", "b"]
965 "#,
966 )
967 .file(
968 "a/Cargo.toml",
969 r#"
970 [package]
971 name = "a"
972 version = "0.1.0"
973
974 [dependencies]
975 dog1 = { version = "1.0", package = "dog" }
976 dog2 = { version = "2.0", package = "dog" }
977 "#,
978 )
979 .file("a/src/lib.rs", "")
980 .file(
981 "b/Cargo.toml",
982 r#"
983 [package]
984 name = "b"
985 version = "0.1.0"
986
987 [dependencies]
988 dep = "1.0"
989 cat = "2.0"
990 "#,
991 )
992 .file("b/src/lib.rs", "")
993 .build();
994
995 p.cargo("tree -p a")
996 .with_stdout(
997 "\
998a v0.1.0 ([..]/foo/a)
999├── dog v1.0.0
1000└── dog v2.0.0
1001",
1002 )
1003 .run();
1004
1005 p.cargo("tree -p b")
1006 .with_stdout(
1007 "\
1008b v0.1.0 ([..]/foo/b)
1009├── cat v2.0.0
1010└── dep v1.0.0
1011 ├── cat v1.0.0
1012 └── dog v1.0.0
1013",
1014 )
1015 .run();
1016
1017 p.cargo("tree -p a -d")
1018 .with_stdout(
1019 "\
1020dog v1.0.0
1021└── a v0.1.0 ([..]/foo/a)
1022
1023dog v2.0.0
1024└── a v0.1.0 ([..]/foo/a)
1025",
1026 )
1027 .run();
1028
1029 p.cargo("tree -p b -d")
1030 .with_stdout(
1031 "\
1032cat v1.0.0
1033└── dep v1.0.0
1034 └── b v0.1.0 ([..]/foo/b)
1035
1036cat v2.0.0
1037└── b v0.1.0 ([..]/foo/b)
1038",
1039 )
1040 .run();
1041}
1042
1043#[cargo_test]
1044fn duplicates_with_target() {
1045 // --target flag
1046 if cross_compile::disabled() {
1047 return;
1048 }
1049 Package::new("a", "1.0.0").publish();
1050 Package::new("dog", "1.0.0").publish();
1051
1052 let p = project()
1053 .file(
1054 "Cargo.toml",
1055 r#"
1056 [package]
1057 name = "foo"
1058 version = "0.1.0"
1059
1060 [dependencies]
1061 a = "1.0"
1062 dog = "1.0"
1063
1064 [build-dependencies]
1065 a = "1.0"
1066 dog = "1.0"
1067
1068 "#,
1069 )
1070 .file("src/lib.rs", "")
1071 .file("build.rs", "fn main() {}")
1072 .build();
1073 p.cargo("tree -d").with_stdout("").run();
1074
1075 p.cargo("tree -d --target")
1076 .arg(alternate())
1077 .with_stdout("")
1078 .run();
1079
1080 p.cargo("tree -d --target")
1081 .arg(rustc_host())
1082 .with_stdout("")
1083 .run();
1084
1085 p.cargo("tree -d --target=all").with_stdout("").run();
1086}
1087
49aad941
FG
1088#[cargo_test]
1089fn duplicates_with_proc_macro() {
1090 Package::new("dupe-dep", "1.0.0").publish();
1091 Package::new("dupe-dep", "2.0.0").publish();
1092 Package::new("proc", "1.0.0")
1093 .proc_macro(true)
1094 .dep("dupe-dep", "1.0")
1095 .publish();
1096 let p = project()
1097 .file(
1098 "Cargo.toml",
1099 r#"
1100 [package]
1101 name = "foo"
1102 version = "0.1.0"
1103
1104 [dependencies]
1105 proc = "1.0"
1106 dupe-dep = "2.0"
1107 "#,
1108 )
1109 .file("src/lib.rs", "")
1110 .build();
1111
1112 p.cargo("tree")
1113 .with_stdout(
1114 "\
1115foo v0.1.0 ([..]/foo)
1116├── dupe-dep v2.0.0
1117└── proc v1.0.0 (proc-macro)
1118 └── dupe-dep v1.0.0
1119",
1120 )
1121 .run();
1122
1123 p.cargo("tree --duplicates")
1124 .with_stdout(
1125 "\
1126dupe-dep v1.0.0
1127└── proc v1.0.0 (proc-macro)
1128 └── foo v0.1.0 ([..]/foo)
1129
1130dupe-dep v2.0.0
1131└── foo v0.1.0 ([..]/foo)
1132",
1133 )
1134 .run();
1135
1136 p.cargo("tree --duplicates --edges no-proc-macro")
1137 .with_stdout("")
1138 .run();
1139}
1140
0a29b90c
FG
1141#[cargo_test]
1142fn charset() {
1143 let p = make_simple_proj();
1144 p.cargo("tree --charset ascii")
1145 .with_stdout(
1146 "\
1147foo v0.1.0 ([..]/foo)
1148|-- a v1.0.0
1149| `-- b v1.0.0
1150| `-- c v1.0.0
1151`-- c v1.0.0
1152[build-dependencies]
1153`-- bdep v1.0.0
1154 `-- b v1.0.0 (*)
1155[dev-dependencies]
1156`-- devdep v1.0.0
1157 `-- b v1.0.0 (*)
1158",
1159 )
1160 .run();
1161}
1162
1163#[cargo_test]
1164fn format() {
1165 Package::new("dep", "1.0.0").publish();
1166 Package::new("other-dep", "1.0.0").publish();
1167
1168 Package::new("dep_that_is_awesome", "1.0.0")
1169 .file(
1170 "Cargo.toml",
1171 r#"
1172 [package]
1173 name = "dep_that_is_awesome"
1174 version = "1.0.0"
1175
1176 [lib]
1177 name = "awesome_dep"
1178 "#,
1179 )
1180 .file("src/lib.rs", "pub struct Straw;")
1181 .publish();
1182
1183 let p = project()
1184 .file(
1185 "Cargo.toml",
1186 r#"
1187 [package]
1188 name = "foo"
1189 version = "0.1.0"
1190 license = "MIT"
1191 repository = "https://github.com/rust-lang/cargo"
1192
1193 [dependencies]
1194 dep = {version="1.0", optional=true}
1195 other-dep = {version="1.0", optional=true}
1196 dep_that_is_awesome = {version="1.0", optional=true}
1197
1198
1199 [features]
1200 default = ["foo"]
1201 foo = ["bar"]
1202 bar = []
1203 "#,
1204 )
1205 .file("src/main.rs", "")
1206 .build();
1207
1208 p.cargo("tree --format <<<{p}>>>")
1209 .with_stdout("<<<foo v0.1.0 ([..]/foo)>>>")
1210 .run();
1211
1212 p.cargo("tree --format {}")
1213 .with_stderr(
1214 "\
1215[ERROR] tree format `{}` not valid
1216
1217Caused by:
1218 unsupported pattern ``
1219",
1220 )
1221 .with_status(101)
1222 .run();
1223
1224 p.cargo("tree --format {p}-{{hello}}")
1225 .with_stdout("foo v0.1.0 ([..]/foo)-{hello}")
1226 .run();
1227
1228 p.cargo("tree --format")
1229 .arg("{p} {l} {r}")
1230 .with_stdout("foo v0.1.0 ([..]/foo) MIT https://github.com/rust-lang/cargo")
1231 .run();
1232
1233 p.cargo("tree --format")
1234 .arg("{p} {f}")
1235 .with_stdout("foo v0.1.0 ([..]/foo) bar,default,foo")
1236 .run();
1237
1238 p.cargo("tree --all-features --format")
1239 .arg("{p} [{f}]")
1240 .with_stdout(
1241 "\
1242foo v0.1.0 ([..]/foo) [bar,default,dep,dep_that_is_awesome,foo,other-dep]
1243├── dep v1.0.0 []
1244├── dep_that_is_awesome v1.0.0 []
1245└── other-dep v1.0.0 []
1246",
1247 )
1248 .run();
1249
1250 p.cargo("tree")
1251 .arg("--features=other-dep,dep_that_is_awesome")
1252 .arg("--format={lib}")
1253 .with_stdout(
1254 "
1255├── awesome_dep
1256└── other_dep
1257",
1258 )
1259 .run();
1260}
1261
1262#[cargo_test]
1263fn dev_dep_feature() {
1264 // New feature resolver with optional dep
1265 Package::new("optdep", "1.0.0").publish();
1266 Package::new("bar", "1.0.0")
1267 .add_dep(Dependency::new("optdep", "1.0").optional(true))
1268 .publish();
1269 let p = project()
1270 .file(
1271 "Cargo.toml",
1272 r#"
1273 [package]
1274 name = "foo"
1275 version = "0.1.0"
1276
1277 [dev-dependencies]
1278 bar = { version = "1.0", features = ["optdep"] }
1279
1280 [dependencies]
1281 bar = "1.0"
1282 "#,
1283 )
1284 .file("src/lib.rs", "")
1285 .build();
1286
1287 // Old behavior.
1288 p.cargo("tree")
1289 .with_stdout(
1290 "\
1291foo v0.1.0 ([..]/foo)
1292└── bar v1.0.0
1293 └── optdep v1.0.0
1294[dev-dependencies]
1295└── bar v1.0.0 (*)
1296",
1297 )
1298 .run();
1299
1300 p.cargo("tree -e normal")
1301 .with_stdout(
1302 "\
1303foo v0.1.0 ([..]/foo)
1304└── bar v1.0.0
1305 └── optdep v1.0.0
1306",
1307 )
1308 .run();
1309
1310 // New behavior.
1311 switch_to_resolver_2(&p);
1312
1313 p.cargo("tree")
1314 .with_stdout(
1315 "\
1316foo v0.1.0 ([..]/foo)
1317└── bar v1.0.0
1318 └── optdep v1.0.0
1319[dev-dependencies]
1320└── bar v1.0.0 (*)
1321",
1322 )
1323 .run();
1324
1325 p.cargo("tree -e normal")
1326 .with_stdout(
1327 "\
1328foo v0.1.0 ([..]/foo)
1329└── bar v1.0.0
1330",
1331 )
1332 .run();
1333}
1334
1335#[cargo_test]
1336fn host_dep_feature() {
1337 // New feature resolver with optional build dep
1338 Package::new("optdep", "1.0.0").publish();
1339 Package::new("bar", "1.0.0")
1340 .add_dep(Dependency::new("optdep", "1.0").optional(true))
1341 .publish();
1342 let p = project()
1343 .file(
1344 "Cargo.toml",
1345 r#"
1346 [package]
1347 name = "foo"
1348 version = "0.1.0"
1349
1350 [build-dependencies]
1351 bar = { version = "1.0", features = ["optdep"] }
1352
1353 [dependencies]
1354 bar = "1.0"
1355 "#,
1356 )
1357 .file("src/lib.rs", "")
1358 .file("build.rs", "fn main() {}")
1359 .build();
1360
1361 // Old behavior
1362 p.cargo("tree")
1363 .with_stdout(
1364 "\
1365foo v0.1.0 ([..]/foo)
1366└── bar v1.0.0
1367 └── optdep v1.0.0
1368[build-dependencies]
1369└── bar v1.0.0 (*)
1370",
1371 )
1372 .run();
1373
1374 // -p
1375 p.cargo("tree -p bar")
1376 .with_stdout(
1377 "\
1378bar v1.0.0
1379└── optdep v1.0.0
1380",
1381 )
1382 .run();
1383
1384 // invert
1385 p.cargo("tree -i optdep")
1386 .with_stdout(
1387 "\
1388optdep v1.0.0
1389└── bar v1.0.0
1390 └── foo v0.1.0 ([..]/foo)
1391 [build-dependencies]
1392 └── foo v0.1.0 ([..]/foo)
1393",
1394 )
1395 .run();
1396
1397 // New behavior.
1398 switch_to_resolver_2(&p);
1399
1400 p.cargo("tree")
1401 .with_stdout(
1402 "\
1403foo v0.1.0 ([..]/foo)
1404└── bar v1.0.0
1405[build-dependencies]
1406└── bar v1.0.0
1407 └── optdep v1.0.0
1408",
1409 )
1410 .run();
1411
1412 p.cargo("tree -p bar")
1413 .with_stdout(
1414 "\
1415bar v1.0.0
1416
1417bar v1.0.0
1418└── optdep v1.0.0
1419",
1420 )
1421 .run();
1422
1423 p.cargo("tree -i optdep")
1424 .with_stdout(
1425 "\
1426optdep v1.0.0
1427└── bar v1.0.0
1428 [build-dependencies]
1429 └── foo v0.1.0 ([..]/foo)
1430",
1431 )
1432 .run();
1433
1434 // Check that -d handles duplicates with features.
1435 p.cargo("tree -d")
1436 .with_stdout(
1437 "\
1438bar v1.0.0
1439└── foo v0.1.0 ([..]/foo)
1440
1441bar v1.0.0
1442[build-dependencies]
1443└── foo v0.1.0 ([..]/foo)
1444",
1445 )
1446 .run();
1447}
1448
1449#[cargo_test]
1450fn proc_macro_features() {
1451 // New feature resolver with a proc-macro
1452 Package::new("optdep", "1.0.0").publish();
1453 Package::new("somedep", "1.0.0")
1454 .add_dep(Dependency::new("optdep", "1.0").optional(true))
1455 .publish();
1456 Package::new("pm", "1.0.0")
1457 .proc_macro(true)
1458 .feature_dep("somedep", "1.0", &["optdep"])
1459 .publish();
1460 let p = project()
1461 .file(
1462 "Cargo.toml",
1463 r#"
1464 [package]
1465 name = "foo"
1466 version = "0.1.0"
1467
1468 [dependencies]
1469 pm = "1.0"
1470 somedep = "1.0"
1471 "#,
1472 )
1473 .file("src/lib.rs", "")
1474 .build();
1475
1476 // Old behavior
1477 p.cargo("tree")
1478 .with_stdout(
1479 "\
1480foo v0.1.0 ([..]/foo)
1481├── pm v1.0.0 (proc-macro)
1482│ └── somedep v1.0.0
1483│ └── optdep v1.0.0
1484└── somedep v1.0.0 (*)
1485",
1486 )
1487 .run();
1488
1489 // Old behavior + no-proc-macro
1490 p.cargo("tree -e no-proc-macro")
1491 .with_stdout(
1492 "\
1493foo v0.1.0 ([..]/foo)
1494└── somedep v1.0.0
1495 └── optdep v1.0.0
1496",
1497 )
1498 .run();
1499
1500 // -p
1501 p.cargo("tree -p somedep")
1502 .with_stdout(
1503 "\
1504somedep v1.0.0
1505└── optdep v1.0.0
1506",
1507 )
1508 .run();
1509
1510 // -p -e no-proc-macro
1511 p.cargo("tree -p somedep -e no-proc-macro")
1512 .with_stdout(
1513 "\
1514somedep v1.0.0
1515└── optdep v1.0.0
1516",
1517 )
1518 .run();
1519
1520 // invert
1521 p.cargo("tree -i somedep")
1522 .with_stdout(
1523 "\
1524somedep v1.0.0
1525├── foo v0.1.0 ([..]/foo)
1526└── pm v1.0.0 (proc-macro)
1527 └── foo v0.1.0 ([..]/foo)
1528",
1529 )
1530 .run();
1531
1532 // invert + no-proc-macro
1533 p.cargo("tree -i somedep -e no-proc-macro")
1534 .with_stdout(
1535 "\
1536somedep v1.0.0
1537└── foo v0.1.0 ([..]/foo)
1538",
1539 )
1540 .run();
1541
1542 // New behavior.
1543 switch_to_resolver_2(&p);
1544
1545 // Note the missing (*)
1546 p.cargo("tree")
1547 .with_stdout(
1548 "\
1549foo v0.1.0 ([..]/foo)
1550├── pm v1.0.0 (proc-macro)
1551│ └── somedep v1.0.0
1552│ └── optdep v1.0.0
1553└── somedep v1.0.0
1554",
1555 )
1556 .run();
1557
1558 p.cargo("tree -e no-proc-macro")
1559 .with_stdout(
1560 "\
1561foo v0.1.0 ([..]/foo)
1562└── somedep v1.0.0
1563",
1564 )
1565 .run();
1566
1567 p.cargo("tree -p somedep")
1568 .with_stdout(
1569 "\
1570somedep v1.0.0
1571
1572somedep v1.0.0
1573└── optdep v1.0.0
1574",
1575 )
1576 .run();
1577
1578 p.cargo("tree -i somedep")
1579 .with_stdout(
1580 "\
1581somedep v1.0.0
1582└── foo v0.1.0 ([..]/foo)
1583
1584somedep v1.0.0
1585└── pm v1.0.0 (proc-macro)
1586 └── foo v0.1.0 ([..]/foo)
1587",
1588 )
1589 .run();
1590
1591 p.cargo("tree -i somedep -e no-proc-macro")
1592 .with_stdout(
1593 "\
1594somedep v1.0.0
1595└── foo v0.1.0 ([..]/foo)
0a29b90c
FG
1596",
1597 )
1598 .run();
1599}
1600
1601#[cargo_test]
1602fn itarget_opt_dep() {
1603 // New feature resolver with optional target dep
1604 Package::new("optdep", "1.0.0").publish();
1605 Package::new("common", "1.0.0")
1606 .add_dep(Dependency::new("optdep", "1.0").optional(true))
1607 .publish();
1608
1609 let p = project()
1610 .file(
1611 "Cargo.toml",
1612 r#"
1613 [package]
1614 name = "foo"
1615 version = "1.0.0"
1616
1617 [dependencies]
1618 common = "1.0"
1619
1620 [target.'cfg(whatever)'.dependencies]
1621 common = { version = "1.0", features = ["optdep"] }
1622
1623 "#,
1624 )
1625 .file("src/lib.rs", "")
1626 .build();
1627
1628 // Old behavior
1629 p.cargo("tree")
1630 .with_stdout(
1631 "\
1632foo v1.0.0 ([..]/foo)
1633└── common v1.0.0
1634 └── optdep v1.0.0
1635",
1636 )
1637 .run();
1638
1639 // New behavior.
1640 switch_to_resolver_2(&p);
1641
1642 p.cargo("tree")
1643 .with_stdout(
1644 "\
1645foo v1.0.0 ([..]/foo)
1646└── common v1.0.0
1647",
1648 )
1649 .run();
1650}
1651
1652#[cargo_test]
1653fn ambiguous_name() {
1654 // -p that is ambiguous.
1655 Package::new("dep", "1.0.0").publish();
1656 Package::new("dep", "2.0.0").publish();
1657 Package::new("bar", "1.0.0").dep("dep", "2.0").publish();
1658 let p = project()
1659 .file(
1660 "Cargo.toml",
1661 r#"
1662 [package]
1663 name = "foo"
1664 version = "0.1.0"
1665
1666 [dependencies]
1667 dep = "1.0"
1668 bar = "1.0"
1669 "#,
1670 )
1671 .file("src/lib.rs", "")
1672 .build();
1673
1674 p.cargo("tree -p dep")
1675 .with_stderr_contains(
1676 "\
1677error: There are multiple `dep` packages in your project, and the specification `dep` is ambiguous.
781aab86 1678Please re-run this command with one of the following specifications:
0a29b90c
FG
1679 dep@1.0.0
1680 dep@2.0.0
1681",
1682 )
1683 .with_status(101)
1684 .run();
1685}
1686
1687#[cargo_test]
1688fn workspace_features_are_local() {
1689 // The features for workspace packages should be the same as `cargo build`
1690 // (i.e., the features selected depend on the "current" package).
1691 Package::new("optdep", "1.0.0").publish();
1692 Package::new("somedep", "1.0.0")
1693 .add_dep(Dependency::new("optdep", "1.0").optional(true))
1694 .publish();
1695 let p = project()
1696 .file(
1697 "Cargo.toml",
1698 r#"
1699 [workspace]
1700 members = ["a", "b"]
1701 "#,
1702 )
1703 .file(
1704 "a/Cargo.toml",
1705 r#"
1706 [package]
1707 name = "a"
1708 version = "0.1.0"
1709
1710 [dependencies]
1711 somedep = {version="1.0", features=["optdep"]}
1712 "#,
1713 )
1714 .file("a/src/lib.rs", "")
1715 .file(
1716 "b/Cargo.toml",
1717 r#"
1718 [package]
1719 name = "b"
1720 version = "0.1.0"
1721
1722 [dependencies]
1723 somedep = "1.0"
1724 "#,
1725 )
1726 .file("b/src/lib.rs", "")
1727 .build();
1728
1729 p.cargo("tree")
1730 .with_stdout(
1731 "\
1732a v0.1.0 ([..]/foo/a)
1733└── somedep v1.0.0
1734 └── optdep v1.0.0
1735
1736b v0.1.0 ([..]/foo/b)
1737└── somedep v1.0.0 (*)
1738",
1739 )
1740 .run();
1741
1742 p.cargo("tree -p a")
1743 .with_stdout(
1744 "\
1745a v0.1.0 ([..]/foo/a)
1746└── somedep v1.0.0
1747 └── optdep v1.0.0
1748",
1749 )
1750 .run();
1751
1752 p.cargo("tree -p b")
1753 .with_stdout(
1754 "\
1755b v0.1.0 ([..]/foo/b)
1756└── somedep v1.0.0
1757",
1758 )
1759 .run();
1760}
1761
1762#[cargo_test]
1763fn unknown_edge_kind() {
1764 let p = project()
1765 .file("Cargo.toml", "")
1766 .file("src/lib.rs", "")
1767 .build();
1768
1769 p.cargo("tree -e unknown")
1770 .with_stderr(
1771 "\
1772[ERROR] unknown edge kind `unknown`, valid values are \
1773\"normal\", \"build\", \"dev\", \
1774\"no-normal\", \"no-build\", \"no-dev\", \"no-proc-macro\", \
1775\"features\", or \"all\"
1776",
1777 )
1778 .with_status(101)
1779 .run();
1780}
1781
1782#[cargo_test]
1783fn mixed_no_edge_kinds() {
1784 let p = project()
1785 .file(
1786 "Cargo.toml",
1787 r#"
1788 [package]
1789 name = "foo"
1790 version = "0.1.0"
1791 "#,
1792 )
1793 .file("src/lib.rs", "")
1794 .build();
1795
1796 p.cargo("tree -e no-build,normal")
1797 .with_stderr(
1798 "\
1799[ERROR] `normal` dependency kind cannot be mixed with \
1800\"no-normal\", \"no-build\", or \"no-dev\" dependency kinds
1801",
1802 )
1803 .with_status(101)
1804 .run();
1805
1806 // `no-proc-macro` can be mixed with others
1807 p.cargo("tree -e no-proc-macro,normal")
1808 .with_stdout(
1809 "\
1810foo v0.1.0 ([..]/foo)
1811",
1812 )
1813 .run();
1814}
1815
1816#[cargo_test]
1817fn depth_limit() {
1818 let p = make_simple_proj();
1819
1820 p.cargo("tree --depth 0")
1821 .with_stdout(
1822 "\
1823foo v0.1.0 ([..]/foo)
1824[build-dependencies]
1825[dev-dependencies]
1826",
1827 )
1828 .run();
1829
1830 p.cargo("tree --depth 1")
1831 .with_stdout(
1832 "\
1833foo v0.1.0 ([..]/foo)
1834├── a v1.0.0
1835└── c v1.0.0
1836[build-dependencies]
1837└── bdep v1.0.0
1838[dev-dependencies]
1839└── devdep v1.0.0
1840",
1841 )
1842 .run();
1843
1844 p.cargo("tree --depth 2")
1845 .with_stdout(
1846 "\
1847foo v0.1.0 ([..]/foo)
1848├── a v1.0.0
1849│ └── b v1.0.0
1850└── c v1.0.0
1851[build-dependencies]
1852└── bdep v1.0.0
1853 └── b v1.0.0 (*)
1854[dev-dependencies]
1855└── devdep v1.0.0
1856 └── b v1.0.0 (*)
1857",
1858 )
1859 .run();
1860
1861 // specify a package
1862 p.cargo("tree -p bdep --depth 1")
1863 .with_stdout(
1864 "\
1865bdep v1.0.0
1866└── b v1.0.0
1867",
1868 )
1869 .run();
1870
1871 // different prefix
1872 p.cargo("tree --depth 1 --prefix depth")
1873 .with_stdout(
1874 "\
18750foo v0.1.0 ([..]/foo)
18761a v1.0.0
18771c v1.0.0
18781bdep v1.0.0
18791devdep v1.0.0
1880",
1881 )
1882 .run();
1883
1884 // with edge-kinds
1885 p.cargo("tree --depth 1 -e no-dev")
1886 .with_stdout(
1887 "\
1888foo v0.1.0 ([..]/foo)
1889├── a v1.0.0
1890└── c v1.0.0
1891[build-dependencies]
1892└── bdep v1.0.0
1893",
1894 )
1895 .run();
1896
1897 // invert
1898 p.cargo("tree --depth 1 --invert c")
1899 .with_stdout(
1900 "\
1901c v1.0.0
1902├── b v1.0.0
1903└── foo v0.1.0 ([..]/foo)
1904",
1905 )
1906 .run();
1907}
1908
1909#[cargo_test]
1910fn prune() {
1911 let p = make_simple_proj();
1912
1913 p.cargo("tree --prune c")
1914 .with_stdout(
1915 "\
1916foo v0.1.0 ([..]/foo)
1917└── a v1.0.0
1918 └── b v1.0.0
1919[build-dependencies]
1920└── bdep v1.0.0
1921 └── b v1.0.0 (*)
1922[dev-dependencies]
1923└── devdep v1.0.0
1924 └── b v1.0.0 (*)
1925",
1926 )
1927 .run();
1928
1929 // multiple prune
1930 p.cargo("tree --prune c --prune bdep")
1931 .with_stdout(
1932 "\
1933foo v0.1.0 ([..]/foo)
1934└── a v1.0.0
1935 └── b v1.0.0
1936[build-dependencies]
1937[dev-dependencies]
1938└── devdep v1.0.0
1939 └── b v1.0.0 (*)
1940",
1941 )
1942 .run();
1943
1944 // with edge-kinds
1945 p.cargo("tree --prune c -e normal")
1946 .with_stdout(
1947 "\
1948foo v0.1.0 ([..]/foo)
1949└── a v1.0.0
1950 └── b v1.0.0
1951",
1952 )
1953 .run();
1954
1955 // pruning self does not works
1956 p.cargo("tree --prune foo")
1957 .with_stdout(
1958 "\
1959foo v0.1.0 ([..]/foo)
1960├── a v1.0.0
1961│ └── b v1.0.0
1962│ └── c v1.0.0
1963└── c v1.0.0
1964[build-dependencies]
1965└── bdep v1.0.0
1966 └── b v1.0.0 (*)
1967[dev-dependencies]
1968└── devdep v1.0.0
1969 └── b v1.0.0 (*)
1970",
1971 )
1972 .run();
1973
1974 // dep not exist
1975 p.cargo("tree --prune no-dep")
1976 .with_stderr(
1977 "\
1978[ERROR] package ID specification `no-dep` did not match any packages
1979
1980<tab>Did you mean `bdep`?
1981",
1982 )
1983 .with_status(101)
1984 .run();
1985}
1986
1987#[cargo_test]
1988fn cyclic_features() {
1989 // Check for stack overflow with cyclic features (oops!).
1990 let p = project()
1991 .file(
1992 "Cargo.toml",
1993 r#"
1994 [package]
1995 name = "foo"
1996 version = "1.0.0"
1997
1998 [features]
1999 a = ["b"]
2000 b = ["a"]
2001 default = ["a"]
2002 "#,
2003 )
2004 .file("src/lib.rs", "")
2005 .build();
2006
2007 p.cargo("tree -e features")
2008 .with_stdout("foo v1.0.0 ([ROOT]/foo)")
2009 .run();
2010
2011 p.cargo("tree -e features -i foo")
2012 .with_stdout(
2013 "\
2014foo v1.0.0 ([ROOT]/foo)
2015├── foo feature \"a\"
2016│ ├── foo feature \"b\"
2017│ │ └── foo feature \"a\" (*)
2018│ └── foo feature \"default\" (command-line)
2019├── foo feature \"b\" (*)
2020└── foo feature \"default\" (command-line)
2021",
2022 )
2023 .run();
2024}
2025
2026#[cargo_test]
2027fn dev_dep_cycle_with_feature() {
2028 // Cycle with features and a dev-dependency.
2029 let p = project()
2030 .file(
2031 "Cargo.toml",
2032 r#"
2033 [package]
2034 name = "foo"
2035 version = "1.0.0"
2036
2037 [dev-dependencies]
2038 bar = { path = "bar" }
2039
2040 [features]
2041 a = ["bar/feat1"]
2042 "#,
2043 )
2044 .file("src/lib.rs", "")
2045 .file(
2046 "bar/Cargo.toml",
2047 r#"
2048 [package]
2049 name = "bar"
2050 version = "1.0.0"
2051
2052 [dependencies]
2053 foo = { path = ".." }
2054
2055 [features]
2056 feat1 = ["foo/a"]
2057 "#,
2058 )
2059 .file("bar/src/lib.rs", "")
2060 .build();
2061
2062 p.cargo("tree -e features --features a")
2063 .with_stdout(
2064 "\
2065foo v1.0.0 ([ROOT]/foo)
2066[dev-dependencies]
2067└── bar feature \"default\"
2068 └── bar v1.0.0 ([ROOT]/foo/bar)
2069 └── foo feature \"default\" (command-line)
2070 └── foo v1.0.0 ([ROOT]/foo) (*)
2071",
2072 )
2073 .run();
2074
2075 p.cargo("tree -e features --features a -i foo")
2076 .with_stdout(
2077 "\
2078foo v1.0.0 ([ROOT]/foo)
2079├── foo feature \"a\" (command-line)
2080│ └── bar feature \"feat1\"
2081│ └── foo feature \"a\" (command-line) (*)
2082└── foo feature \"default\" (command-line)
2083 └── bar v1.0.0 ([ROOT]/foo/bar)
2084 ├── bar feature \"default\"
2085 │ [dev-dependencies]
2086 │ └── foo v1.0.0 ([ROOT]/foo) (*)
2087 └── bar feature \"feat1\" (*)
2088",
2089 )
2090 .run();
2091}
2092
2093#[cargo_test]
2094fn dev_dep_cycle_with_feature_nested() {
2095 // Checks for an issue where a cyclic dev dependency tries to activate a
2096 // feature on its parent that tries to activate the feature back on the
2097 // dev-dependency.
2098 let p = project()
2099 .file(
2100 "Cargo.toml",
2101 r#"
2102 [package]
2103 name = "foo"
2104 version = "1.0.0"
2105
2106 [dev-dependencies]
2107 bar = { path = "bar" }
2108
2109 [features]
2110 a = ["bar/feat1"]
2111 b = ["a"]
2112 "#,
2113 )
2114 .file("src/lib.rs", "")
2115 .file(
2116 "bar/Cargo.toml",
2117 r#"
2118 [package]
2119 name = "bar"
2120 version = "1.0.0"
2121
2122 [dependencies]
2123 foo = { path = ".." }
2124
2125 [features]
2126 feat1 = ["foo/b"]
2127 "#,
2128 )
2129 .file("bar/src/lib.rs", "")
2130 .build();
2131
2132 p.cargo("tree -e features")
2133 .with_stdout(
2134 "\
2135foo v1.0.0 ([ROOT]/foo)
2136[dev-dependencies]
2137└── bar feature \"default\"
2138 └── bar v1.0.0 ([ROOT]/foo/bar)
2139 └── foo feature \"default\" (command-line)
2140 └── foo v1.0.0 ([ROOT]/foo) (*)
2141",
2142 )
2143 .run();
2144
2145 p.cargo("tree -e features --features a -i foo")
2146 .with_stdout(
2147 "\
2148foo v1.0.0 ([ROOT]/foo)
2149├── foo feature \"a\" (command-line)
2150│ └── foo feature \"b\"
2151│ └── bar feature \"feat1\"
2152│ └── foo feature \"a\" (command-line) (*)
2153├── foo feature \"b\" (*)
2154└── foo feature \"default\" (command-line)
2155 └── bar v1.0.0 ([ROOT]/foo/bar)
2156 ├── bar feature \"default\"
2157 │ [dev-dependencies]
2158 │ └── foo v1.0.0 ([ROOT]/foo) (*)
2159 └── bar feature \"feat1\" (*)
2160",
2161 )
2162 .run();
2163
2164 p.cargo("tree -e features --features b -i foo")
2165 .with_stdout(
2166 "\
2167foo v1.0.0 ([ROOT]/foo)
2168├── foo feature \"a\"
2169│ └── foo feature \"b\" (command-line)
2170│ └── bar feature \"feat1\"
2171│ └── foo feature \"a\" (*)
2172├── foo feature \"b\" (command-line) (*)
2173└── foo feature \"default\" (command-line)
2174 └── bar v1.0.0 ([ROOT]/foo/bar)
2175 ├── bar feature \"default\"
2176 │ [dev-dependencies]
2177 │ └── foo v1.0.0 ([ROOT]/foo) (*)
2178 └── bar feature \"feat1\" (*)
2179",
2180 )
2181 .run();
2182
2183 p.cargo("tree -e features --features bar/feat1 -i foo")
2184 .with_stdout(
2185 "\
2186foo v1.0.0 ([ROOT]/foo)
2187├── foo feature \"a\"
2188│ └── foo feature \"b\"
2189│ └── bar feature \"feat1\" (command-line)
2190│ └── foo feature \"a\" (*)
2191├── foo feature \"b\" (*)
2192└── foo feature \"default\" (command-line)
2193 └── bar v1.0.0 ([ROOT]/foo/bar)
2194 ├── bar feature \"default\"
2195 │ [dev-dependencies]
2196 │ └── foo v1.0.0 ([ROOT]/foo) (*)
2197 └── bar feature \"feat1\" (command-line) (*)
2198",
2199 )
2200 .run();
2201}