]> git.proxmox.com Git - cargo.git/blob - tests/testsuite/git.rs
Auto merge of #8823 - ehuss:minimal-download, r=alexcrichton
[cargo.git] / tests / testsuite / git.rs
1 //! Tests for git support.
2
3 use std::env;
4 use std::fs;
5 use std::io::prelude::*;
6 use std::net::{TcpListener, TcpStream};
7 use std::path::Path;
8 use std::str;
9 use std::sync::atomic::{AtomicBool, Ordering};
10 use std::sync::Arc;
11 use std::thread;
12
13 use cargo_test_support::paths::{self, CargoPathExt};
14 use cargo_test_support::{basic_lib_manifest, basic_manifest, git, main_file, path2url, project};
15 use cargo_test_support::{sleep_ms, t, Project};
16
17 fn disable_git_cli() -> bool {
18 // mingw git on Windows does not support Windows-style file URIs.
19 // Appveyor in the rust repo has that git up front in the PATH instead
20 // of Git-for-Windows, which causes this to fail.
21 env::var("CARGO_TEST_DISABLE_GIT_CLI") == Ok("1".to_string())
22 }
23
24 #[cargo_test]
25 fn cargo_compile_simple_git_dep() {
26 let project = project();
27 let git_project = git::new("dep1", |project| {
28 project
29 .file("Cargo.toml", &basic_lib_manifest("dep1"))
30 .file(
31 "src/dep1.rs",
32 r#"
33 pub fn hello() -> &'static str {
34 "hello world"
35 }
36 "#,
37 )
38 });
39
40 let project = project
41 .file(
42 "Cargo.toml",
43 &format!(
44 r#"
45 [project]
46
47 name = "foo"
48 version = "0.5.0"
49 authors = ["wycats@example.com"]
50
51 [dependencies.dep1]
52
53 git = '{}'
54 "#,
55 git_project.url()
56 ),
57 )
58 .file(
59 "src/main.rs",
60 &main_file(r#""{}", dep1::hello()"#, &["dep1"]),
61 )
62 .build();
63
64 let git_root = git_project.root();
65
66 project
67 .cargo("build")
68 .with_stderr(&format!(
69 "[UPDATING] git repository `{}`\n\
70 [COMPILING] dep1 v0.5.0 ({}#[..])\n\
71 [COMPILING] foo v0.5.0 ([CWD])\n\
72 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
73 path2url(&git_root),
74 path2url(&git_root),
75 ))
76 .run();
77
78 assert!(project.bin("foo").is_file());
79
80 project
81 .process(&project.bin("foo"))
82 .with_stdout("hello world\n")
83 .run();
84 }
85
86 #[cargo_test]
87 fn cargo_compile_git_dep_branch() {
88 let project = project();
89 let git_project = git::new("dep1", |project| {
90 project
91 .file("Cargo.toml", &basic_lib_manifest("dep1"))
92 .file(
93 "src/dep1.rs",
94 r#"
95 pub fn hello() -> &'static str {
96 "hello world"
97 }
98 "#,
99 )
100 });
101
102 // Make a new branch based on the current HEAD commit
103 let repo = git2::Repository::open(&git_project.root()).unwrap();
104 let head = repo.head().unwrap().target().unwrap();
105 let head = repo.find_commit(head).unwrap();
106 repo.branch("branchy", &head, true).unwrap();
107
108 let project = project
109 .file(
110 "Cargo.toml",
111 &format!(
112 r#"
113 [project]
114
115 name = "foo"
116 version = "0.5.0"
117 authors = ["wycats@example.com"]
118
119 [dependencies.dep1]
120
121 git = '{}'
122 branch = "branchy"
123
124 "#,
125 git_project.url()
126 ),
127 )
128 .file(
129 "src/main.rs",
130 &main_file(r#""{}", dep1::hello()"#, &["dep1"]),
131 )
132 .build();
133
134 let git_root = git_project.root();
135
136 project
137 .cargo("build")
138 .with_stderr(&format!(
139 "[UPDATING] git repository `{}`\n\
140 [COMPILING] dep1 v0.5.0 ({}?branch=branchy#[..])\n\
141 [COMPILING] foo v0.5.0 ([CWD])\n\
142 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
143 path2url(&git_root),
144 path2url(&git_root),
145 ))
146 .run();
147
148 assert!(project.bin("foo").is_file());
149
150 project
151 .process(&project.bin("foo"))
152 .with_stdout("hello world\n")
153 .run();
154 }
155
156 #[cargo_test]
157 fn cargo_compile_git_dep_tag() {
158 let project = project();
159 let git_project = git::new("dep1", |project| {
160 project
161 .file("Cargo.toml", &basic_lib_manifest("dep1"))
162 .file(
163 "src/dep1.rs",
164 r#"
165 pub fn hello() -> &'static str {
166 "hello world"
167 }
168 "#,
169 )
170 });
171
172 // Make a tag corresponding to the current HEAD
173 let repo = git2::Repository::open(&git_project.root()).unwrap();
174 let head = repo.head().unwrap().target().unwrap();
175 repo.tag(
176 "v0.1.0",
177 &repo.find_object(head, None).unwrap(),
178 &repo.signature().unwrap(),
179 "make a new tag",
180 false,
181 )
182 .unwrap();
183
184 let project = project
185 .file(
186 "Cargo.toml",
187 &format!(
188 r#"
189 [project]
190
191 name = "foo"
192 version = "0.5.0"
193 authors = ["wycats@example.com"]
194
195 [dependencies.dep1]
196
197 git = '{}'
198 tag = "v0.1.0"
199 "#,
200 git_project.url()
201 ),
202 )
203 .file(
204 "src/main.rs",
205 &main_file(r#""{}", dep1::hello()"#, &["dep1"]),
206 )
207 .build();
208
209 let git_root = git_project.root();
210
211 project
212 .cargo("build")
213 .with_stderr(&format!(
214 "[UPDATING] git repository `{}`\n\
215 [COMPILING] dep1 v0.5.0 ({}?tag=v0.1.0#[..])\n\
216 [COMPILING] foo v0.5.0 ([CWD])\n\
217 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
218 path2url(&git_root),
219 path2url(&git_root),
220 ))
221 .run();
222
223 assert!(project.bin("foo").is_file());
224
225 project
226 .process(&project.bin("foo"))
227 .with_stdout("hello world\n")
228 .run();
229
230 project.cargo("build").run();
231 }
232
233 #[cargo_test]
234 fn cargo_compile_with_nested_paths() {
235 let git_project = git::new("dep1", |project| {
236 project
237 .file(
238 "Cargo.toml",
239 r#"
240 [project]
241
242 name = "dep1"
243 version = "0.5.0"
244 authors = ["carlhuda@example.com"]
245
246 [dependencies.dep2]
247
248 version = "0.5.0"
249 path = "vendor/dep2"
250
251 [lib]
252
253 name = "dep1"
254 "#,
255 )
256 .file(
257 "src/dep1.rs",
258 r#"
259 extern crate dep2;
260
261 pub fn hello() -> &'static str {
262 dep2::hello()
263 }
264 "#,
265 )
266 .file("vendor/dep2/Cargo.toml", &basic_lib_manifest("dep2"))
267 .file(
268 "vendor/dep2/src/dep2.rs",
269 r#"
270 pub fn hello() -> &'static str {
271 "hello world"
272 }
273 "#,
274 )
275 });
276
277 let p = project()
278 .file(
279 "Cargo.toml",
280 &format!(
281 r#"
282 [project]
283
284 name = "foo"
285 version = "0.5.0"
286 authors = ["wycats@example.com"]
287
288 [dependencies.dep1]
289
290 version = "0.5.0"
291 git = '{}'
292
293 [[bin]]
294
295 name = "foo"
296 "#,
297 git_project.url()
298 ),
299 )
300 .file(
301 "src/foo.rs",
302 &main_file(r#""{}", dep1::hello()"#, &["dep1"]),
303 )
304 .build();
305
306 p.cargo("build").run();
307
308 assert!(p.bin("foo").is_file());
309
310 p.process(&p.bin("foo")).with_stdout("hello world\n").run();
311 }
312
313 #[cargo_test]
314 fn cargo_compile_with_malformed_nested_paths() {
315 let git_project = git::new("dep1", |project| {
316 project
317 .file("Cargo.toml", &basic_lib_manifest("dep1"))
318 .file(
319 "src/dep1.rs",
320 r#"
321 pub fn hello() -> &'static str {
322 "hello world"
323 }
324 "#,
325 )
326 .file("vendor/dep2/Cargo.toml", "!INVALID!")
327 .file(
328 "vendor/dep3/Cargo.toml",
329 r#"
330 [project]
331 name = "dep3"
332 version = "0.5.0"
333 [dependencies]
334 subdep1 = { path = "../require-extra-build-step" }
335 "#,
336 )
337 .file("vendor/dep3/src/lib.rs", "")
338 });
339
340 let p = project()
341 .file(
342 "Cargo.toml",
343 &format!(
344 r#"
345 [project]
346
347 name = "foo"
348 version = "0.5.0"
349 authors = ["wycats@example.com"]
350
351 [dependencies.dep1]
352
353 version = "0.5.0"
354 git = '{}'
355
356 [[bin]]
357
358 name = "foo"
359 "#,
360 git_project.url()
361 ),
362 )
363 .file(
364 "src/foo.rs",
365 &main_file(r#""{}", dep1::hello()"#, &["dep1"]),
366 )
367 .build();
368
369 p.cargo("build").run();
370
371 assert!(p.bin("foo").is_file());
372
373 p.process(&p.bin("foo")).with_stdout("hello world\n").run();
374 }
375
376 #[cargo_test]
377 fn cargo_compile_with_meta_package() {
378 let git_project = git::new("meta-dep", |project| {
379 project
380 .file("dep1/Cargo.toml", &basic_lib_manifest("dep1"))
381 .file(
382 "dep1/src/dep1.rs",
383 r#"
384 pub fn hello() -> &'static str {
385 "this is dep1"
386 }
387 "#,
388 )
389 .file("dep2/Cargo.toml", &basic_lib_manifest("dep2"))
390 .file(
391 "dep2/src/dep2.rs",
392 r#"
393 pub fn hello() -> &'static str {
394 "this is dep2"
395 }
396 "#,
397 )
398 });
399
400 let p = project()
401 .file(
402 "Cargo.toml",
403 &format!(
404 r#"
405 [project]
406
407 name = "foo"
408 version = "0.5.0"
409 authors = ["wycats@example.com"]
410
411 [dependencies.dep1]
412
413 version = "0.5.0"
414 git = '{}'
415
416 [dependencies.dep2]
417
418 version = "0.5.0"
419 git = '{}'
420
421 [[bin]]
422
423 name = "foo"
424 "#,
425 git_project.url(),
426 git_project.url()
427 ),
428 )
429 .file(
430 "src/foo.rs",
431 &main_file(
432 r#""{} {}", dep1::hello(), dep2::hello()"#,
433 &["dep1", "dep2"],
434 ),
435 )
436 .build();
437
438 p.cargo("build").run();
439
440 assert!(p.bin("foo").is_file());
441
442 p.process(&p.bin("foo"))
443 .with_stdout("this is dep1 this is dep2\n")
444 .run();
445 }
446
447 #[cargo_test]
448 fn cargo_compile_with_short_ssh_git() {
449 let url = "git@github.com:a/dep";
450
451 let p = project()
452 .file(
453 "Cargo.toml",
454 &format!(
455 r#"
456 [project]
457
458 name = "foo"
459 version = "0.5.0"
460 authors = ["wycats@example.com"]
461
462 [dependencies.dep]
463
464 git = "{}"
465
466 [[bin]]
467
468 name = "foo"
469 "#,
470 url
471 ),
472 )
473 .file(
474 "src/foo.rs",
475 &main_file(r#""{}", dep1::hello()"#, &["dep1"]),
476 )
477 .build();
478
479 p.cargo("build")
480 .with_status(101)
481 .with_stdout("")
482 .with_stderr(&format!(
483 "\
484 [ERROR] failed to parse manifest at `[..]`
485
486 Caused by:
487 invalid url `{}`: relative URL without a base
488 ",
489 url
490 ))
491 .run();
492 }
493
494 #[cargo_test]
495 fn two_revs_same_deps() {
496 let bar = git::new("meta-dep", |project| {
497 project
498 .file("Cargo.toml", &basic_manifest("bar", "0.0.0"))
499 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
500 });
501
502 let repo = git2::Repository::open(&bar.root()).unwrap();
503 let rev1 = repo.revparse_single("HEAD").unwrap().id();
504
505 // Commit the changes and make sure we trigger a recompile
506 bar.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
507 git::add(&repo);
508 let rev2 = git::commit(&repo);
509
510 let foo = project()
511 .file(
512 "Cargo.toml",
513 &format!(
514 r#"
515 [project]
516 name = "foo"
517 version = "0.0.0"
518 authors = []
519
520 [dependencies.bar]
521 git = '{}'
522 rev = "{}"
523
524 [dependencies.baz]
525 path = "../baz"
526 "#,
527 bar.url(),
528 rev1
529 ),
530 )
531 .file(
532 "src/main.rs",
533 r#"
534 extern crate bar;
535 extern crate baz;
536
537 fn main() {
538 assert_eq!(bar::bar(), 1);
539 assert_eq!(baz::baz(), 2);
540 }
541 "#,
542 )
543 .build();
544
545 let _baz = project()
546 .at("baz")
547 .file(
548 "Cargo.toml",
549 &format!(
550 r#"
551 [package]
552 name = "baz"
553 version = "0.0.0"
554 authors = []
555
556 [dependencies.bar]
557 git = '{}'
558 rev = "{}"
559 "#,
560 bar.url(),
561 rev2
562 ),
563 )
564 .file(
565 "src/lib.rs",
566 r#"
567 extern crate bar;
568 pub fn baz() -> i32 { bar::bar() }
569 "#,
570 )
571 .build();
572
573 foo.cargo("build -v").run();
574 assert!(foo.bin("foo").is_file());
575 foo.process(&foo.bin("foo")).run();
576 }
577
578 #[cargo_test]
579 fn recompilation() {
580 let git_project = git::new("bar", |project| {
581 project
582 .file("Cargo.toml", &basic_lib_manifest("bar"))
583 .file("src/bar.rs", "pub fn bar() {}")
584 });
585
586 let p = project()
587 .file(
588 "Cargo.toml",
589 &format!(
590 r#"
591 [project]
592
593 name = "foo"
594 version = "0.5.0"
595 authors = ["wycats@example.com"]
596
597 [dependencies.bar]
598
599 version = "0.5.0"
600 git = '{}'
601 "#,
602 git_project.url()
603 ),
604 )
605 .file("src/main.rs", &main_file(r#""{:?}", bar::bar()"#, &["bar"]))
606 .build();
607
608 // First time around we should compile both foo and bar
609 p.cargo("build")
610 .with_stderr(&format!(
611 "[UPDATING] git repository `{}`\n\
612 [COMPILING] bar v0.5.0 ({}#[..])\n\
613 [COMPILING] foo v0.5.0 ([CWD])\n\
614 [FINISHED] dev [unoptimized + debuginfo] target(s) \
615 in [..]\n",
616 git_project.url(),
617 git_project.url(),
618 ))
619 .run();
620
621 // Don't recompile the second time
622 p.cargo("build").with_stdout("").run();
623
624 // Modify a file manually, shouldn't trigger a recompile
625 git_project.change_file("src/bar.rs", r#"pub fn bar() { println!("hello!"); }"#);
626
627 p.cargo("build").with_stdout("").run();
628
629 p.cargo("update")
630 .with_stderr(&format!(
631 "[UPDATING] git repository `{}`",
632 git_project.url()
633 ))
634 .run();
635
636 p.cargo("build").with_stdout("").run();
637
638 // Commit the changes and make sure we don't trigger a recompile because the
639 // lock file says not to change
640 let repo = git2::Repository::open(&git_project.root()).unwrap();
641 git::add(&repo);
642 git::commit(&repo);
643
644 println!("compile after commit");
645 p.cargo("build").with_stdout("").run();
646 p.root().move_into_the_past();
647
648 // Update the dependency and carry on!
649 p.cargo("update")
650 .with_stderr(&format!(
651 "[UPDATING] git repository `{}`\n\
652 [UPDATING] bar v0.5.0 ([..]) -> #[..]\n\
653 ",
654 git_project.url()
655 ))
656 .run();
657 println!("going for the last compile");
658 p.cargo("build")
659 .with_stderr(&format!(
660 "[COMPILING] bar v0.5.0 ({}#[..])\n\
661 [COMPILING] foo v0.5.0 ([CWD])\n\
662 [FINISHED] dev [unoptimized + debuginfo] target(s) \
663 in [..]\n",
664 git_project.url(),
665 ))
666 .run();
667
668 // Make sure clean only cleans one dep
669 p.cargo("clean -p foo").with_stdout("").run();
670 p.cargo("build")
671 .with_stderr(
672 "[COMPILING] foo v0.5.0 ([CWD])\n\
673 [FINISHED] dev [unoptimized + debuginfo] target(s) \
674 in [..]",
675 )
676 .run();
677 }
678
679 #[cargo_test]
680 fn update_with_shared_deps() {
681 let git_project = git::new("bar", |project| {
682 project
683 .file("Cargo.toml", &basic_lib_manifest("bar"))
684 .file("src/bar.rs", "pub fn bar() {}")
685 });
686
687 let p = project()
688 .file(
689 "Cargo.toml",
690 r#"
691 [package]
692 name = "foo"
693 version = "0.5.0"
694 authors = ["wycats@example.com"]
695
696 [dependencies.dep1]
697 path = "dep1"
698 [dependencies.dep2]
699 path = "dep2"
700 "#,
701 )
702 .file(
703 "src/main.rs",
704 r#"
705 #[allow(unused_extern_crates)]
706 extern crate dep1;
707 #[allow(unused_extern_crates)]
708 extern crate dep2;
709 fn main() {}
710 "#,
711 )
712 .file(
713 "dep1/Cargo.toml",
714 &format!(
715 r#"
716 [package]
717 name = "dep1"
718 version = "0.5.0"
719 authors = ["wycats@example.com"]
720
721 [dependencies.bar]
722 version = "0.5.0"
723 git = '{}'
724 "#,
725 git_project.url()
726 ),
727 )
728 .file("dep1/src/lib.rs", "")
729 .file(
730 "dep2/Cargo.toml",
731 &format!(
732 r#"
733 [package]
734 name = "dep2"
735 version = "0.5.0"
736 authors = ["wycats@example.com"]
737
738 [dependencies.bar]
739 version = "0.5.0"
740 git = '{}'
741 "#,
742 git_project.url()
743 ),
744 )
745 .file("dep2/src/lib.rs", "")
746 .build();
747
748 // First time around we should compile both foo and bar
749 p.cargo("build")
750 .with_stderr(&format!(
751 "\
752 [UPDATING] git repository `{git}`
753 [COMPILING] bar v0.5.0 ({git}#[..])
754 [COMPILING] [..] v0.5.0 ([..])
755 [COMPILING] [..] v0.5.0 ([..])
756 [COMPILING] foo v0.5.0 ([CWD])
757 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
758 git = git_project.url(),
759 ))
760 .run();
761
762 // Modify a file manually, and commit it
763 git_project.change_file("src/bar.rs", r#"pub fn bar() { println!("hello!"); }"#);
764 let repo = git2::Repository::open(&git_project.root()).unwrap();
765 let old_head = repo.head().unwrap().target().unwrap();
766 git::add(&repo);
767 git::commit(&repo);
768
769 sleep_ms(1000);
770
771 // By default, not transitive updates
772 println!("dep1 update");
773 p.cargo("update -p dep1").with_stdout("").run();
774
775 // Don't do anything bad on a weird --precise argument
776 println!("bar bad precise update");
777 p.cargo("update -p bar --precise 0.1.2")
778 .with_status(101)
779 .with_stderr(
780 "\
781 [ERROR] Unable to update [..]
782
783 Caused by:
784 precise value for git is not a git revision: 0.1.2
785
786 Caused by:
787 unable to parse OID - contains invalid characters; class=Invalid (3)
788 ",
789 )
790 .run();
791
792 // Specifying a precise rev to the old rev shouldn't actually update
793 // anything because we already have the rev in the db.
794 println!("bar precise update");
795 p.cargo("update -p bar --precise")
796 .arg(&old_head.to_string())
797 .with_stdout("")
798 .run();
799
800 // Updating aggressively should, however, update the repo.
801 println!("dep1 aggressive update");
802 p.cargo("update -p dep1 --aggressive")
803 .with_stderr(&format!(
804 "[UPDATING] git repository `{}`\n\
805 [UPDATING] bar v0.5.0 ([..]) -> #[..]\n\
806 ",
807 git_project.url()
808 ))
809 .run();
810
811 // Make sure we still only compile one version of the git repo
812 println!("build");
813 p.cargo("build")
814 .with_stderr(&format!(
815 "\
816 [COMPILING] bar v0.5.0 ({git}#[..])
817 [COMPILING] [..] v0.5.0 ([CWD][..]dep[..])
818 [COMPILING] [..] v0.5.0 ([CWD][..]dep[..])
819 [COMPILING] foo v0.5.0 ([CWD])
820 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
821 git = git_project.url(),
822 ))
823 .run();
824
825 // We should be able to update transitive deps
826 p.cargo("update -p bar")
827 .with_stderr(&format!(
828 "[UPDATING] git repository `{}`",
829 git_project.url()
830 ))
831 .run();
832 }
833
834 #[cargo_test]
835 fn dep_with_submodule() {
836 let project = project();
837 let git_project = git::new("dep1", |project| {
838 project.file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
839 });
840 let git_project2 = git::new("dep2", |project| project.file("lib.rs", "pub fn dep() {}"));
841
842 let repo = git2::Repository::open(&git_project.root()).unwrap();
843 let url = path2url(git_project2.root()).to_string();
844 git::add_submodule(&repo, &url, Path::new("src"));
845 git::commit(&repo);
846
847 let project = project
848 .file(
849 "Cargo.toml",
850 &format!(
851 r#"
852 [project]
853
854 name = "foo"
855 version = "0.5.0"
856 authors = ["wycats@example.com"]
857
858 [dependencies.dep1]
859
860 git = '{}'
861 "#,
862 git_project.url()
863 ),
864 )
865 .file(
866 "src/lib.rs",
867 "extern crate dep1; pub fn foo() { dep1::dep() }",
868 )
869 .build();
870
871 project
872 .cargo("build")
873 .with_stderr(
874 "\
875 [UPDATING] git repository [..]
876 [UPDATING] git submodule `file://[..]/dep2`
877 [COMPILING] dep1 [..]
878 [COMPILING] foo [..]
879 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
880 )
881 .run();
882 }
883
884 #[cargo_test]
885 fn dep_with_bad_submodule() {
886 let project = project();
887 let git_project = git::new("dep1", |project| {
888 project.file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
889 });
890 let git_project2 = git::new("dep2", |project| project.file("lib.rs", "pub fn dep() {}"));
891
892 let repo = git2::Repository::open(&git_project.root()).unwrap();
893 let url = path2url(git_project2.root()).to_string();
894 git::add_submodule(&repo, &url, Path::new("src"));
895 git::commit(&repo);
896
897 // now amend the first commit on git_project2 to make submodule ref point to not-found
898 // commit
899 let repo = git2::Repository::open(&git_project2.root()).unwrap();
900 let original_submodule_ref = repo.refname_to_id("refs/heads/master").unwrap();
901 let commit = repo.find_commit(original_submodule_ref).unwrap();
902 commit
903 .amend(
904 Some("refs/heads/master"),
905 None,
906 None,
907 None,
908 Some("something something"),
909 None,
910 )
911 .unwrap();
912
913 let p = project
914 .file(
915 "Cargo.toml",
916 &format!(
917 r#"
918 [project]
919
920 name = "foo"
921 version = "0.5.0"
922 authors = ["wycats@example.com"]
923
924 [dependencies.dep1]
925
926 git = '{}'
927 "#,
928 git_project.url()
929 ),
930 )
931 .file(
932 "src/lib.rs",
933 "extern crate dep1; pub fn foo() { dep1::dep() }",
934 )
935 .build();
936
937 let expected = format!(
938 "\
939 [UPDATING] git repository [..]
940 [UPDATING] git submodule `file://[..]/dep2`
941 [ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 [..]`
942
943 Caused by:
944 failed to load source for dependency `dep1`
945
946 Caused by:
947 Unable to update {}
948
949 Caused by:
950 failed to update submodule `src`
951
952 Caused by:
953 object not found - no match for id [..]
954 ",
955 path2url(git_project.root())
956 );
957
958 p.cargo("build")
959 .with_stderr(expected)
960 .with_status(101)
961 .run();
962 }
963
964 #[cargo_test]
965 fn two_deps_only_update_one() {
966 let project = project();
967 let git1 = git::new("dep1", |project| {
968 project
969 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
970 .file("src/lib.rs", "")
971 });
972 let git2 = git::new("dep2", |project| {
973 project
974 .file("Cargo.toml", &basic_manifest("dep2", "0.5.0"))
975 .file("src/lib.rs", "")
976 });
977
978 let p = project
979 .file(
980 "Cargo.toml",
981 &format!(
982 r#"
983 [project]
984
985 name = "foo"
986 version = "0.5.0"
987 authors = ["wycats@example.com"]
988
989 [dependencies.dep1]
990 git = '{}'
991 [dependencies.dep2]
992 git = '{}'
993 "#,
994 git1.url(),
995 git2.url()
996 ),
997 )
998 .file("src/main.rs", "fn main() {}")
999 .build();
1000
1001 fn oid_to_short_sha(oid: git2::Oid) -> String {
1002 oid.to_string()[..8].to_string()
1003 }
1004 fn git_repo_head_sha(p: &Project) -> String {
1005 let repo = git2::Repository::open(p.root()).unwrap();
1006 let head = repo.head().unwrap().target().unwrap();
1007 oid_to_short_sha(head)
1008 }
1009
1010 println!("dep1 head sha: {}", git_repo_head_sha(&git1));
1011 println!("dep2 head sha: {}", git_repo_head_sha(&git2));
1012
1013 p.cargo("build")
1014 .with_stderr(
1015 "[UPDATING] git repository `[..]`\n\
1016 [UPDATING] git repository `[..]`\n\
1017 [COMPILING] [..] v0.5.0 ([..])\n\
1018 [COMPILING] [..] v0.5.0 ([..])\n\
1019 [COMPILING] foo v0.5.0 ([CWD])\n\
1020 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
1021 )
1022 .run();
1023
1024 git1.change_file("src/lib.rs", "pub fn foo() {}");
1025 let repo = git2::Repository::open(&git1.root()).unwrap();
1026 git::add(&repo);
1027 let oid = git::commit(&repo);
1028 println!("dep1 head sha: {}", oid_to_short_sha(oid));
1029
1030 p.cargo("update -p dep1")
1031 .with_stderr(&format!(
1032 "[UPDATING] git repository `{}`\n\
1033 [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
1034 ",
1035 git1.url()
1036 ))
1037 .run();
1038 }
1039
1040 #[cargo_test]
1041 fn stale_cached_version() {
1042 let bar = git::new("meta-dep", |project| {
1043 project
1044 .file("Cargo.toml", &basic_manifest("bar", "0.0.0"))
1045 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1046 });
1047
1048 // Update the git database in the cache with the current state of the git
1049 // repo
1050 let foo = project()
1051 .file(
1052 "Cargo.toml",
1053 &format!(
1054 r#"
1055 [project]
1056 name = "foo"
1057 version = "0.0.0"
1058 authors = []
1059
1060 [dependencies.bar]
1061 git = '{}'
1062 "#,
1063 bar.url()
1064 ),
1065 )
1066 .file(
1067 "src/main.rs",
1068 r#"
1069 extern crate bar;
1070
1071 fn main() { assert_eq!(bar::bar(), 1) }
1072 "#,
1073 )
1074 .build();
1075
1076 foo.cargo("build").run();
1077 foo.process(&foo.bin("foo")).run();
1078
1079 // Update the repo, and simulate someone else updating the lock file and then
1080 // us pulling it down.
1081 bar.change_file("src/lib.rs", "pub fn bar() -> i32 { 1 + 0 }");
1082 let repo = git2::Repository::open(&bar.root()).unwrap();
1083 git::add(&repo);
1084 git::commit(&repo);
1085
1086 sleep_ms(1000);
1087
1088 let rev = repo.revparse_single("HEAD").unwrap().id();
1089
1090 foo.change_file(
1091 "Cargo.lock",
1092 &format!(
1093 r#"
1094 [[package]]
1095 name = "foo"
1096 version = "0.0.0"
1097 dependencies = [
1098 'bar 0.0.0 (git+{url}#{hash})'
1099 ]
1100
1101 [[package]]
1102 name = "bar"
1103 version = "0.0.0"
1104 source = 'git+{url}#{hash}'
1105 "#,
1106 url = bar.url(),
1107 hash = rev
1108 ),
1109 );
1110
1111 // Now build!
1112 foo.cargo("build")
1113 .with_stderr(&format!(
1114 "\
1115 [UPDATING] git repository `{bar}`
1116 [COMPILING] bar v0.0.0 ({bar}#[..])
1117 [COMPILING] foo v0.0.0 ([CWD])
1118 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1119 ",
1120 bar = bar.url(),
1121 ))
1122 .run();
1123 foo.process(&foo.bin("foo")).run();
1124 }
1125
1126 #[cargo_test]
1127 fn dep_with_changed_submodule() {
1128 let project = project();
1129 let git_project = git::new("dep1", |project| {
1130 project.file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
1131 });
1132
1133 let git_project2 = git::new("dep2", |project| {
1134 project.file("lib.rs", "pub fn dep() -> &'static str { \"project2\" }")
1135 });
1136
1137 let git_project3 = git::new("dep3", |project| {
1138 project.file("lib.rs", "pub fn dep() -> &'static str { \"project3\" }")
1139 });
1140
1141 let repo = git2::Repository::open(&git_project.root()).unwrap();
1142 let mut sub = git::add_submodule(&repo, &git_project2.url().to_string(), Path::new("src"));
1143 git::commit(&repo);
1144
1145 let p = project
1146 .file(
1147 "Cargo.toml",
1148 &format!(
1149 r#"
1150 [project]
1151 name = "foo"
1152 version = "0.5.0"
1153 authors = ["wycats@example.com"]
1154 [dependencies.dep1]
1155 git = '{}'
1156 "#,
1157 git_project.url()
1158 ),
1159 )
1160 .file(
1161 "src/main.rs",
1162 "
1163 extern crate dep1;
1164 pub fn main() { println!(\"{}\", dep1::dep()) }
1165 ",
1166 )
1167 .build();
1168
1169 println!("first run");
1170 p.cargo("run")
1171 .with_stderr(
1172 "[UPDATING] git repository `[..]`\n\
1173 [UPDATING] git submodule `file://[..]/dep2`\n\
1174 [COMPILING] dep1 v0.5.0 ([..])\n\
1175 [COMPILING] foo v0.5.0 ([..])\n\
1176 [FINISHED] dev [unoptimized + debuginfo] target(s) in \
1177 [..]\n\
1178 [RUNNING] `target/debug/foo[EXE]`\n",
1179 )
1180 .with_stdout("project2\n")
1181 .run();
1182
1183 git_project.change_file(
1184 ".gitmodules",
1185 &format!(
1186 "[submodule \"src\"]\n\tpath = src\n\turl={}",
1187 git_project3.url()
1188 ),
1189 );
1190
1191 // Sync the submodule and reset it to the new remote.
1192 sub.sync().unwrap();
1193 {
1194 let subrepo = sub.open().unwrap();
1195 subrepo
1196 .remote_add_fetch("origin", "refs/heads/*:refs/heads/*")
1197 .unwrap();
1198 subrepo
1199 .remote_set_url("origin", &git_project3.url().to_string())
1200 .unwrap();
1201 let mut origin = subrepo.find_remote("origin").unwrap();
1202 origin.fetch(&Vec::<String>::new(), None, None).unwrap();
1203 let id = subrepo.refname_to_id("refs/remotes/origin/master").unwrap();
1204 let obj = subrepo.find_object(id, None).unwrap();
1205 subrepo.reset(&obj, git2::ResetType::Hard, None).unwrap();
1206 }
1207 sub.add_to_index(true).unwrap();
1208 git::add(&repo);
1209 git::commit(&repo);
1210
1211 sleep_ms(1000);
1212 // Update the dependency and carry on!
1213 println!("update");
1214 p.cargo("update -v")
1215 .with_stderr("")
1216 .with_stderr(&format!(
1217 "[UPDATING] git repository `{}`\n\
1218 [UPDATING] git submodule `file://[..]/dep3`\n\
1219 [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
1220 ",
1221 git_project.url()
1222 ))
1223 .run();
1224
1225 println!("last run");
1226 p.cargo("run")
1227 .with_stderr(
1228 "[COMPILING] dep1 v0.5.0 ([..])\n\
1229 [COMPILING] foo v0.5.0 ([..])\n\
1230 [FINISHED] dev [unoptimized + debuginfo] target(s) in \
1231 [..]\n\
1232 [RUNNING] `target/debug/foo[EXE]`\n",
1233 )
1234 .with_stdout("project3\n")
1235 .run();
1236 }
1237
1238 #[cargo_test]
1239 fn dev_deps_with_testing() {
1240 let p2 = git::new("bar", |project| {
1241 project
1242 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1243 .file(
1244 "src/lib.rs",
1245 r#"
1246 pub fn gimme() -> &'static str { "zoidberg" }
1247 "#,
1248 )
1249 });
1250
1251 let p = project()
1252 .file(
1253 "Cargo.toml",
1254 &format!(
1255 r#"
1256 [project]
1257
1258 name = "foo"
1259 version = "0.5.0"
1260 authors = ["wycats@example.com"]
1261
1262 [dev-dependencies.bar]
1263 version = "0.5.0"
1264 git = '{}'
1265 "#,
1266 p2.url()
1267 ),
1268 )
1269 .file(
1270 "src/main.rs",
1271 r#"
1272 fn main() {}
1273
1274 #[cfg(test)]
1275 mod tests {
1276 extern crate bar;
1277 #[test] fn foo() { bar::gimme(); }
1278 }
1279 "#,
1280 )
1281 .build();
1282
1283 // Generate a lock file which did not use `bar` to compile, but had to update
1284 // `bar` to generate the lock file
1285 p.cargo("build")
1286 .with_stderr(&format!(
1287 "\
1288 [UPDATING] git repository `{bar}`
1289 [COMPILING] foo v0.5.0 ([CWD])
1290 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1291 ",
1292 bar = p2.url()
1293 ))
1294 .run();
1295
1296 // Make sure we use the previous resolution of `bar` instead of updating it
1297 // a second time.
1298 p.cargo("test")
1299 .with_stderr(
1300 "\
1301 [COMPILING] [..] v0.5.0 ([..])
1302 [COMPILING] [..] v0.5.0 ([..]
1303 [FINISHED] test [unoptimized + debuginfo] target(s) in [..]
1304 [RUNNING] target/debug/deps/foo-[..][EXE]",
1305 )
1306 .with_stdout_contains("test tests::foo ... ok")
1307 .run();
1308 }
1309
1310 #[cargo_test]
1311 fn git_build_cmd_freshness() {
1312 let foo = git::new("foo", |project| {
1313 project
1314 .file(
1315 "Cargo.toml",
1316 r#"
1317 [package]
1318 name = "foo"
1319 version = "0.0.0"
1320 authors = []
1321 build = "build.rs"
1322 "#,
1323 )
1324 .file("build.rs", "fn main() {}")
1325 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1326 .file(".gitignore", "src/bar.rs")
1327 });
1328 foo.root().move_into_the_past();
1329
1330 sleep_ms(1000);
1331
1332 foo.cargo("build")
1333 .with_stderr(
1334 "\
1335 [COMPILING] foo v0.0.0 ([CWD])
1336 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1337 ",
1338 )
1339 .run();
1340
1341 // Smoke test to make sure it doesn't compile again
1342 println!("first pass");
1343 foo.cargo("build").with_stdout("").run();
1344
1345 // Modify an ignored file and make sure we don't rebuild
1346 println!("second pass");
1347 foo.change_file("src/bar.rs", "");
1348 foo.cargo("build").with_stdout("").run();
1349 }
1350
1351 #[cargo_test]
1352 fn git_name_not_always_needed() {
1353 let p2 = git::new("bar", |project| {
1354 project
1355 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1356 .file(
1357 "src/lib.rs",
1358 r#"
1359 pub fn gimme() -> &'static str { "zoidberg" }
1360 "#,
1361 )
1362 });
1363
1364 let repo = git2::Repository::open(&p2.root()).unwrap();
1365 let mut cfg = repo.config().unwrap();
1366 let _ = cfg.remove("user.name");
1367 let _ = cfg.remove("user.email");
1368
1369 let p = project()
1370 .file(
1371 "Cargo.toml",
1372 &format!(
1373 r#"
1374 [project]
1375 name = "foo"
1376 version = "0.5.0"
1377 authors = []
1378
1379 [dev-dependencies.bar]
1380 git = '{}'
1381 "#,
1382 p2.url()
1383 ),
1384 )
1385 .file("src/main.rs", "fn main() {}")
1386 .build();
1387
1388 // Generate a lock file which did not use `bar` to compile, but had to update
1389 // `bar` to generate the lock file
1390 p.cargo("build")
1391 .with_stderr(&format!(
1392 "\
1393 [UPDATING] git repository `{bar}`
1394 [COMPILING] foo v0.5.0 ([CWD])
1395 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1396 ",
1397 bar = p2.url()
1398 ))
1399 .run();
1400 }
1401
1402 #[cargo_test]
1403 fn git_repo_changing_no_rebuild() {
1404 let bar = git::new("bar", |project| {
1405 project
1406 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1407 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1408 });
1409
1410 // Lock p1 to the first rev in the git repo
1411 let p1 = project()
1412 .at("p1")
1413 .file(
1414 "Cargo.toml",
1415 &format!(
1416 r#"
1417 [project]
1418 name = "p1"
1419 version = "0.5.0"
1420 authors = []
1421 build = 'build.rs'
1422 [dependencies.bar]
1423 git = '{}'
1424 "#,
1425 bar.url()
1426 ),
1427 )
1428 .file("src/main.rs", "fn main() {}")
1429 .file("build.rs", "fn main() {}")
1430 .build();
1431 p1.root().move_into_the_past();
1432 p1.cargo("build")
1433 .with_stderr(&format!(
1434 "\
1435 [UPDATING] git repository `{bar}`
1436 [COMPILING] [..]
1437 [COMPILING] [..]
1438 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1439 ",
1440 bar = bar.url()
1441 ))
1442 .run();
1443
1444 // Make a commit to lock p2 to a different rev
1445 bar.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
1446 let repo = git2::Repository::open(&bar.root()).unwrap();
1447 git::add(&repo);
1448 git::commit(&repo);
1449
1450 // Lock p2 to the second rev
1451 let p2 = project()
1452 .at("p2")
1453 .file(
1454 "Cargo.toml",
1455 &format!(
1456 r#"
1457 [project]
1458 name = "p2"
1459 version = "0.5.0"
1460 authors = []
1461 [dependencies.bar]
1462 git = '{}'
1463 "#,
1464 bar.url()
1465 ),
1466 )
1467 .file("src/main.rs", "fn main() {}")
1468 .build();
1469 p2.cargo("build")
1470 .with_stderr(&format!(
1471 "\
1472 [UPDATING] git repository `{bar}`
1473 [COMPILING] [..]
1474 [COMPILING] [..]
1475 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1476 ",
1477 bar = bar.url()
1478 ))
1479 .run();
1480
1481 // And now for the real test! Make sure that p1 doesn't get rebuilt
1482 // even though the git repo has changed.
1483 p1.cargo("build").with_stdout("").run();
1484 }
1485
1486 #[cargo_test]
1487 fn git_dep_build_cmd() {
1488 let p = git::new("foo", |project| {
1489 project
1490 .file(
1491 "Cargo.toml",
1492 r#"
1493 [project]
1494
1495 name = "foo"
1496 version = "0.5.0"
1497 authors = ["wycats@example.com"]
1498
1499 [dependencies.bar]
1500
1501 version = "0.5.0"
1502 path = "bar"
1503
1504 [[bin]]
1505
1506 name = "foo"
1507 "#,
1508 )
1509 .file("src/foo.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"]))
1510 .file(
1511 "bar/Cargo.toml",
1512 r#"
1513 [project]
1514
1515 name = "bar"
1516 version = "0.5.0"
1517 authors = ["wycats@example.com"]
1518 build = "build.rs"
1519
1520 [lib]
1521 name = "bar"
1522 path = "src/bar.rs"
1523 "#,
1524 )
1525 .file(
1526 "bar/src/bar.rs.in",
1527 r#"
1528 pub fn gimme() -> i32 { 0 }
1529 "#,
1530 )
1531 .file(
1532 "bar/build.rs",
1533 r#"
1534 use std::fs;
1535 fn main() {
1536 fs::copy("src/bar.rs.in", "src/bar.rs").unwrap();
1537 }
1538 "#,
1539 )
1540 });
1541
1542 p.root().join("bar").move_into_the_past();
1543
1544 p.cargo("build").run();
1545
1546 p.process(&p.bin("foo")).with_stdout("0\n").run();
1547
1548 // Touching bar.rs.in should cause the `build` command to run again.
1549 p.change_file("bar/src/bar.rs.in", "pub fn gimme() -> i32 { 1 }");
1550
1551 p.cargo("build").run();
1552
1553 p.process(&p.bin("foo")).with_stdout("1\n").run();
1554 }
1555
1556 #[cargo_test]
1557 fn fetch_downloads() {
1558 let bar = git::new("bar", |project| {
1559 project
1560 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1561 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1562 });
1563
1564 let p = project()
1565 .file(
1566 "Cargo.toml",
1567 &format!(
1568 r#"
1569 [project]
1570 name = "foo"
1571 version = "0.5.0"
1572 authors = []
1573 [dependencies.bar]
1574 git = '{}'
1575 "#,
1576 bar.url()
1577 ),
1578 )
1579 .file("src/main.rs", "fn main() {}")
1580 .build();
1581 p.cargo("fetch")
1582 .with_stderr(&format!(
1583 "[UPDATING] git repository `{url}`",
1584 url = bar.url()
1585 ))
1586 .run();
1587
1588 p.cargo("fetch").with_stdout("").run();
1589 }
1590
1591 #[cargo_test]
1592 fn warnings_in_git_dep() {
1593 let bar = git::new("bar", |project| {
1594 project
1595 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1596 .file("src/lib.rs", "fn unused() {}")
1597 });
1598
1599 let p = project()
1600 .file(
1601 "Cargo.toml",
1602 &format!(
1603 r#"
1604 [project]
1605 name = "foo"
1606 version = "0.5.0"
1607 authors = []
1608 [dependencies.bar]
1609 git = '{}'
1610 "#,
1611 bar.url()
1612 ),
1613 )
1614 .file("src/main.rs", "fn main() {}")
1615 .build();
1616
1617 p.cargo("build")
1618 .with_stderr(&format!(
1619 "[UPDATING] git repository `{}`\n\
1620 [COMPILING] bar v0.5.0 ({}#[..])\n\
1621 [COMPILING] foo v0.5.0 ([CWD])\n\
1622 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
1623 bar.url(),
1624 bar.url(),
1625 ))
1626 .run();
1627 }
1628
1629 #[cargo_test]
1630 fn update_ambiguous() {
1631 let bar1 = git::new("bar1", |project| {
1632 project
1633 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1634 .file("src/lib.rs", "")
1635 });
1636 let bar2 = git::new("bar2", |project| {
1637 project
1638 .file("Cargo.toml", &basic_manifest("bar", "0.6.0"))
1639 .file("src/lib.rs", "")
1640 });
1641 let baz = git::new("baz", |project| {
1642 project
1643 .file(
1644 "Cargo.toml",
1645 &format!(
1646 r#"
1647 [package]
1648 name = "baz"
1649 version = "0.5.0"
1650 authors = ["wycats@example.com"]
1651
1652 [dependencies.bar]
1653 git = '{}'
1654 "#,
1655 bar2.url()
1656 ),
1657 )
1658 .file("src/lib.rs", "")
1659 });
1660
1661 let p = project()
1662 .file(
1663 "Cargo.toml",
1664 &format!(
1665 r#"
1666 [project]
1667 name = "foo"
1668 version = "0.5.0"
1669 authors = []
1670 [dependencies.bar]
1671 git = '{}'
1672 [dependencies.baz]
1673 git = '{}'
1674 "#,
1675 bar1.url(),
1676 baz.url()
1677 ),
1678 )
1679 .file("src/main.rs", "fn main() {}")
1680 .build();
1681
1682 p.cargo("generate-lockfile").run();
1683 p.cargo("update -p bar")
1684 .with_status(101)
1685 .with_stderr(
1686 "\
1687 [ERROR] There are multiple `bar` packages in your project, and the specification `bar` \
1688 is ambiguous.
1689 Please re-run this command with `-p <spec>` where `<spec>` is one of the \
1690 following:
1691 bar:0.[..].0
1692 bar:0.[..].0
1693 ",
1694 )
1695 .run();
1696 }
1697
1698 #[cargo_test]
1699 fn update_one_dep_in_repo_with_many_deps() {
1700 let bar = git::new("bar", |project| {
1701 project
1702 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1703 .file("src/lib.rs", "")
1704 .file("a/Cargo.toml", &basic_manifest("a", "0.5.0"))
1705 .file("a/src/lib.rs", "")
1706 });
1707
1708 let p = project()
1709 .file(
1710 "Cargo.toml",
1711 &format!(
1712 r#"
1713 [project]
1714 name = "foo"
1715 version = "0.5.0"
1716 authors = []
1717 [dependencies.bar]
1718 git = '{}'
1719 [dependencies.a]
1720 git = '{}'
1721 "#,
1722 bar.url(),
1723 bar.url()
1724 ),
1725 )
1726 .file("src/main.rs", "fn main() {}")
1727 .build();
1728
1729 p.cargo("generate-lockfile").run();
1730 p.cargo("update -p bar")
1731 .with_stderr(&format!("[UPDATING] git repository `{}`", bar.url()))
1732 .run();
1733 }
1734
1735 #[cargo_test]
1736 fn switch_deps_does_not_update_transitive() {
1737 let transitive = git::new("transitive", |project| {
1738 project
1739 .file("Cargo.toml", &basic_manifest("transitive", "0.5.0"))
1740 .file("src/lib.rs", "")
1741 });
1742 let dep1 = git::new("dep1", |project| {
1743 project
1744 .file(
1745 "Cargo.toml",
1746 &format!(
1747 r#"
1748 [package]
1749 name = "dep"
1750 version = "0.5.0"
1751 authors = ["wycats@example.com"]
1752
1753 [dependencies.transitive]
1754 git = '{}'
1755 "#,
1756 transitive.url()
1757 ),
1758 )
1759 .file("src/lib.rs", "")
1760 });
1761 let dep2 = git::new("dep2", |project| {
1762 project
1763 .file(
1764 "Cargo.toml",
1765 &format!(
1766 r#"
1767 [package]
1768 name = "dep"
1769 version = "0.5.0"
1770 authors = ["wycats@example.com"]
1771
1772 [dependencies.transitive]
1773 git = '{}'
1774 "#,
1775 transitive.url()
1776 ),
1777 )
1778 .file("src/lib.rs", "")
1779 });
1780
1781 let p = project()
1782 .file(
1783 "Cargo.toml",
1784 &format!(
1785 r#"
1786 [project]
1787 name = "foo"
1788 version = "0.5.0"
1789 authors = []
1790 [dependencies.dep]
1791 git = '{}'
1792 "#,
1793 dep1.url()
1794 ),
1795 )
1796 .file("src/main.rs", "fn main() {}")
1797 .build();
1798
1799 p.cargo("build")
1800 .with_stderr(&format!(
1801 "\
1802 [UPDATING] git repository `{}`
1803 [UPDATING] git repository `{}`
1804 [COMPILING] transitive [..]
1805 [COMPILING] dep [..]
1806 [COMPILING] foo [..]
1807 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1808 ",
1809 dep1.url(),
1810 transitive.url()
1811 ))
1812 .run();
1813
1814 // Update the dependency to point to the second repository, but this
1815 // shouldn't update the transitive dependency which is the same.
1816 p.change_file(
1817 "Cargo.toml",
1818 &format!(
1819 r#"
1820 [project]
1821 name = "foo"
1822 version = "0.5.0"
1823 authors = []
1824 [dependencies.dep]
1825 git = '{}'
1826 "#,
1827 dep2.url()
1828 ),
1829 );
1830
1831 p.cargo("build")
1832 .with_stderr(&format!(
1833 "\
1834 [UPDATING] git repository `{}`
1835 [COMPILING] dep [..]
1836 [COMPILING] foo [..]
1837 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1838 ",
1839 dep2.url()
1840 ))
1841 .run();
1842 }
1843
1844 #[cargo_test]
1845 fn update_one_source_updates_all_packages_in_that_git_source() {
1846 let dep = git::new("dep", |project| {
1847 project
1848 .file(
1849 "Cargo.toml",
1850 r#"
1851 [package]
1852 name = "dep"
1853 version = "0.5.0"
1854 authors = []
1855
1856 [dependencies.a]
1857 path = "a"
1858 "#,
1859 )
1860 .file("src/lib.rs", "")
1861 .file("a/Cargo.toml", &basic_manifest("a", "0.5.0"))
1862 .file("a/src/lib.rs", "")
1863 });
1864
1865 let p = project()
1866 .file(
1867 "Cargo.toml",
1868 &format!(
1869 r#"
1870 [project]
1871 name = "foo"
1872 version = "0.5.0"
1873 authors = []
1874 [dependencies.dep]
1875 git = '{}'
1876 "#,
1877 dep.url()
1878 ),
1879 )
1880 .file("src/main.rs", "fn main() {}")
1881 .build();
1882
1883 p.cargo("build").run();
1884
1885 let repo = git2::Repository::open(&dep.root()).unwrap();
1886 let rev1 = repo.revparse_single("HEAD").unwrap().id();
1887
1888 // Just be sure to change a file
1889 dep.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
1890 git::add(&repo);
1891 git::commit(&repo);
1892
1893 p.cargo("update -p dep").run();
1894 let lockfile = p.read_lockfile();
1895 assert!(
1896 !lockfile.contains(&rev1.to_string()),
1897 "{} in {}",
1898 rev1,
1899 lockfile
1900 );
1901 }
1902
1903 #[cargo_test]
1904 fn switch_sources() {
1905 let a1 = git::new("a1", |project| {
1906 project
1907 .file("Cargo.toml", &basic_manifest("a", "0.5.0"))
1908 .file("src/lib.rs", "")
1909 });
1910 let a2 = git::new("a2", |project| {
1911 project
1912 .file("Cargo.toml", &basic_manifest("a", "0.5.1"))
1913 .file("src/lib.rs", "")
1914 });
1915
1916 let p = project()
1917 .file(
1918 "Cargo.toml",
1919 r#"
1920 [project]
1921 name = "foo"
1922 version = "0.5.0"
1923 authors = []
1924 [dependencies.b]
1925 path = "b"
1926 "#,
1927 )
1928 .file("src/main.rs", "fn main() {}")
1929 .file(
1930 "b/Cargo.toml",
1931 &format!(
1932 r#"
1933 [project]
1934 name = "b"
1935 version = "0.5.0"
1936 authors = []
1937 [dependencies.a]
1938 git = '{}'
1939 "#,
1940 a1.url()
1941 ),
1942 )
1943 .file("b/src/lib.rs", "pub fn main() {}")
1944 .build();
1945
1946 p.cargo("build")
1947 .with_stderr(
1948 "\
1949 [UPDATING] git repository `file://[..]a1`
1950 [COMPILING] a v0.5.0 ([..]a1#[..]
1951 [COMPILING] b v0.5.0 ([..])
1952 [COMPILING] foo v0.5.0 ([..])
1953 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1954 ",
1955 )
1956 .run();
1957
1958 p.change_file(
1959 "b/Cargo.toml",
1960 &format!(
1961 r#"
1962 [project]
1963 name = "b"
1964 version = "0.5.0"
1965 authors = []
1966 [dependencies.a]
1967 git = '{}'
1968 "#,
1969 a2.url()
1970 ),
1971 );
1972
1973 p.cargo("build")
1974 .with_stderr(
1975 "\
1976 [UPDATING] git repository `file://[..]a2`
1977 [COMPILING] a v0.5.1 ([..]a2#[..]
1978 [COMPILING] b v0.5.0 ([..])
1979 [COMPILING] foo v0.5.0 ([..])
1980 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1981 ",
1982 )
1983 .run();
1984 }
1985
1986 #[cargo_test]
1987 fn dont_require_submodules_are_checked_out() {
1988 let p = project().build();
1989 let git1 = git::new("dep1", |p| {
1990 p.file(
1991 "Cargo.toml",
1992 r#"
1993 [project]
1994 name = "foo"
1995 version = "0.5.0"
1996 authors = []
1997 build = "build.rs"
1998 "#,
1999 )
2000 .file("build.rs", "fn main() {}")
2001 .file("src/lib.rs", "")
2002 .file("a/foo", "")
2003 });
2004 let git2 = git::new("dep2", |p| p);
2005
2006 let repo = git2::Repository::open(&git1.root()).unwrap();
2007 let url = path2url(git2.root()).to_string();
2008 git::add_submodule(&repo, &url, Path::new("a/submodule"));
2009 git::commit(&repo);
2010
2011 git2::Repository::init(&p.root()).unwrap();
2012 let url = path2url(git1.root()).to_string();
2013 let dst = paths::home().join("foo");
2014 git2::Repository::clone(&url, &dst).unwrap();
2015
2016 git1.cargo("build -v").cwd(&dst).run();
2017 }
2018
2019 #[cargo_test]
2020 fn doctest_same_name() {
2021 let a2 = git::new("a2", |p| {
2022 p.file("Cargo.toml", &basic_manifest("a", "0.5.0"))
2023 .file("src/lib.rs", "pub fn a2() {}")
2024 });
2025
2026 let a1 = git::new("a1", |p| {
2027 p.file(
2028 "Cargo.toml",
2029 &format!(
2030 r#"
2031 [project]
2032 name = "a"
2033 version = "0.5.0"
2034 authors = []
2035 [dependencies]
2036 a = {{ git = '{}' }}
2037 "#,
2038 a2.url()
2039 ),
2040 )
2041 .file("src/lib.rs", "extern crate a; pub fn a1() {}")
2042 });
2043
2044 let p = project()
2045 .file(
2046 "Cargo.toml",
2047 &format!(
2048 r#"
2049 [package]
2050 name = "foo"
2051 version = "0.0.1"
2052 authors = []
2053
2054 [dependencies]
2055 a = {{ git = '{}' }}
2056 "#,
2057 a1.url()
2058 ),
2059 )
2060 .file(
2061 "src/lib.rs",
2062 r#"
2063 #[macro_use]
2064 extern crate a;
2065 "#,
2066 )
2067 .build();
2068
2069 p.cargo("test -v").run();
2070 }
2071
2072 #[cargo_test]
2073 fn lints_are_suppressed() {
2074 let a = git::new("a", |p| {
2075 p.file("Cargo.toml", &basic_manifest("a", "0.5.0")).file(
2076 "src/lib.rs",
2077 "
2078 use std::option;
2079 ",
2080 )
2081 });
2082
2083 let p = project()
2084 .file(
2085 "Cargo.toml",
2086 &format!(
2087 r#"
2088 [package]
2089 name = "foo"
2090 version = "0.0.1"
2091 authors = []
2092
2093 [dependencies]
2094 a = {{ git = '{}' }}
2095 "#,
2096 a.url()
2097 ),
2098 )
2099 .file("src/lib.rs", "")
2100 .build();
2101
2102 p.cargo("build")
2103 .with_stderr(
2104 "\
2105 [UPDATING] git repository `[..]`
2106 [COMPILING] a v0.5.0 ([..])
2107 [COMPILING] foo v0.0.1 ([..])
2108 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2109 ",
2110 )
2111 .run();
2112 }
2113
2114 #[cargo_test]
2115 fn denied_lints_are_allowed() {
2116 let a = git::new("a", |p| {
2117 p.file("Cargo.toml", &basic_manifest("a", "0.5.0")).file(
2118 "src/lib.rs",
2119 "
2120 #![deny(warnings)]
2121 use std::option;
2122 ",
2123 )
2124 });
2125
2126 let p = project()
2127 .file(
2128 "Cargo.toml",
2129 &format!(
2130 r#"
2131 [package]
2132 name = "foo"
2133 version = "0.0.1"
2134 authors = []
2135
2136 [dependencies]
2137 a = {{ git = '{}' }}
2138 "#,
2139 a.url()
2140 ),
2141 )
2142 .file("src/lib.rs", "")
2143 .build();
2144
2145 p.cargo("build")
2146 .with_stderr(
2147 "\
2148 [UPDATING] git repository `[..]`
2149 [COMPILING] a v0.5.0 ([..])
2150 [COMPILING] foo v0.0.1 ([..])
2151 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2152 ",
2153 )
2154 .run();
2155 }
2156
2157 #[cargo_test]
2158 fn add_a_git_dep() {
2159 let git = git::new("git", |p| {
2160 p.file("Cargo.toml", &basic_manifest("git", "0.5.0"))
2161 .file("src/lib.rs", "")
2162 });
2163
2164 let p = project()
2165 .file(
2166 "Cargo.toml",
2167 &format!(
2168 r#"
2169 [package]
2170 name = "foo"
2171 version = "0.0.1"
2172 authors = []
2173
2174 [dependencies]
2175 a = {{ path = 'a' }}
2176 git = {{ git = '{}' }}
2177 "#,
2178 git.url()
2179 ),
2180 )
2181 .file("src/lib.rs", "")
2182 .file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
2183 .file("a/src/lib.rs", "")
2184 .build();
2185
2186 p.cargo("build").run();
2187
2188 p.change_file(
2189 "a/Cargo.toml",
2190 &format!(
2191 r#"
2192 [package]
2193 name = "a"
2194 version = "0.0.1"
2195 authors = []
2196
2197 [dependencies]
2198 git = {{ git = '{}' }}
2199 "#,
2200 git.url()
2201 ),
2202 );
2203
2204 p.cargo("build").run();
2205 }
2206
2207 #[cargo_test]
2208 fn two_at_rev_instead_of_tag() {
2209 let git = git::new("git", |p| {
2210 p.file("Cargo.toml", &basic_manifest("git1", "0.5.0"))
2211 .file("src/lib.rs", "")
2212 .file("a/Cargo.toml", &basic_manifest("git2", "0.5.0"))
2213 .file("a/src/lib.rs", "")
2214 });
2215
2216 // Make a tag corresponding to the current HEAD
2217 let repo = git2::Repository::open(&git.root()).unwrap();
2218 let head = repo.head().unwrap().target().unwrap();
2219 repo.tag(
2220 "v0.1.0",
2221 &repo.find_object(head, None).unwrap(),
2222 &repo.signature().unwrap(),
2223 "make a new tag",
2224 false,
2225 )
2226 .unwrap();
2227
2228 let p = project()
2229 .file(
2230 "Cargo.toml",
2231 &format!(
2232 r#"
2233 [package]
2234 name = "foo"
2235 version = "0.0.1"
2236 authors = []
2237
2238 [dependencies]
2239 git1 = {{ git = '{0}', rev = 'v0.1.0' }}
2240 git2 = {{ git = '{0}', rev = 'v0.1.0' }}
2241 "#,
2242 git.url()
2243 ),
2244 )
2245 .file("src/lib.rs", "")
2246 .build();
2247
2248 p.cargo("generate-lockfile").run();
2249 p.cargo("build -v").run();
2250 }
2251
2252 #[cargo_test]
2253 fn include_overrides_gitignore() {
2254 // Make sure that `package.include` takes precedence over .gitignore.
2255 let p = git::new("foo", |repo| {
2256 repo.file(
2257 "Cargo.toml",
2258 r#"
2259 [package]
2260 name = "foo"
2261 version = "0.5.0"
2262 include = ["src/lib.rs", "ignored.txt", "Cargo.toml"]
2263 "#,
2264 )
2265 .file(
2266 ".gitignore",
2267 r#"
2268 /target
2269 Cargo.lock
2270 ignored.txt
2271 "#,
2272 )
2273 .file("src/lib.rs", "")
2274 .file("ignored.txt", "")
2275 .file("build.rs", "fn main() {}")
2276 });
2277
2278 p.cargo("build").run();
2279 p.change_file("ignored.txt", "Trigger rebuild.");
2280 p.cargo("build -v")
2281 .with_stderr(
2282 "\
2283 [COMPILING] foo v0.5.0 ([..])
2284 [RUNNING] `[..]build-script-build[..]`
2285 [RUNNING] `rustc --crate-name foo src/lib.rs [..]`
2286 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2287 ",
2288 )
2289 .run();
2290 p.cargo("package --list --allow-dirty")
2291 .with_stdout(
2292 "\
2293 Cargo.toml
2294 Cargo.toml.orig
2295 ignored.txt
2296 src/lib.rs
2297 ",
2298 )
2299 .run();
2300 }
2301
2302 #[cargo_test]
2303 fn invalid_git_dependency_manifest() {
2304 let project = project();
2305 let git_project = git::new("dep1", |project| {
2306 project
2307 .file(
2308 "Cargo.toml",
2309 r#"
2310 [project]
2311
2312 name = "dep1"
2313 version = "0.5.0"
2314 authors = ["carlhuda@example.com"]
2315 categories = ["algorithms"]
2316 categories = ["algorithms"]
2317
2318 [lib]
2319
2320 name = "dep1"
2321 "#,
2322 )
2323 .file(
2324 "src/dep1.rs",
2325 r#"
2326 pub fn hello() -> &'static str {
2327 "hello world"
2328 }
2329 "#,
2330 )
2331 });
2332
2333 let project = project
2334 .file(
2335 "Cargo.toml",
2336 &format!(
2337 r#"
2338 [project]
2339
2340 name = "foo"
2341 version = "0.5.0"
2342 authors = ["wycats@example.com"]
2343
2344 [dependencies.dep1]
2345
2346 git = '{}'
2347 "#,
2348 git_project.url()
2349 ),
2350 )
2351 .file(
2352 "src/main.rs",
2353 &main_file(r#""{}", dep1::hello()"#, &["dep1"]),
2354 )
2355 .build();
2356
2357 let git_root = git_project.root();
2358
2359 project
2360 .cargo("build")
2361 .with_status(101)
2362 .with_stderr(&format!(
2363 "\
2364 [UPDATING] git repository `{}`
2365 [ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([..])`
2366
2367 Caused by:
2368 failed to load source for dependency `dep1`
2369
2370 Caused by:
2371 Unable to update {}
2372
2373 Caused by:
2374 failed to parse manifest at `[..]`
2375
2376 Caused by:
2377 could not parse input as TOML
2378
2379 Caused by:
2380 duplicate key: `categories` for key `project` at line 10 column 21",
2381 path2url(&git_root),
2382 path2url(&git_root),
2383 ))
2384 .run();
2385 }
2386
2387 #[cargo_test]
2388 fn failed_submodule_checkout() {
2389 let project = project();
2390 let git_project = git::new("dep1", |project| {
2391 project.file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
2392 });
2393
2394 let git_project2 = git::new("dep2", |project| project.file("lib.rs", ""));
2395
2396 let listener = TcpListener::bind("127.0.0.1:0").unwrap();
2397 let addr = listener.local_addr().unwrap();
2398 let done = Arc::new(AtomicBool::new(false));
2399 let done2 = done.clone();
2400
2401 let t = thread::spawn(move || {
2402 while !done2.load(Ordering::SeqCst) {
2403 if let Ok((mut socket, _)) = listener.accept() {
2404 drop(socket.write_all(b"foo\r\n"));
2405 }
2406 }
2407 });
2408
2409 let repo = git2::Repository::open(&git_project2.root()).unwrap();
2410 let url = format!("https://{}:{}/", addr.ip(), addr.port());
2411 {
2412 let mut s = repo.submodule(&url, Path::new("bar"), false).unwrap();
2413 let subrepo = s.open().unwrap();
2414 let mut cfg = subrepo.config().unwrap();
2415 cfg.set_str("user.email", "foo@bar.com").unwrap();
2416 cfg.set_str("user.name", "Foo Bar").unwrap();
2417 git::commit(&subrepo);
2418 s.add_finalize().unwrap();
2419 }
2420 git::commit(&repo);
2421 drop((repo, url));
2422
2423 let repo = git2::Repository::open(&git_project.root()).unwrap();
2424 let url = path2url(git_project2.root()).to_string();
2425 git::add_submodule(&repo, &url, Path::new("src"));
2426 git::commit(&repo);
2427 drop(repo);
2428
2429 let project = project
2430 .file(
2431 "Cargo.toml",
2432 &format!(
2433 r#"
2434 [project]
2435 name = "foo"
2436 version = "0.5.0"
2437 authors = []
2438
2439 [dependencies]
2440 dep1 = {{ git = '{}' }}
2441 "#,
2442 git_project.url()
2443 ),
2444 )
2445 .file("src/lib.rs", "")
2446 .build();
2447
2448 project
2449 .cargo("build")
2450 .with_status(101)
2451 .with_stderr_contains(" failed to update submodule `src`")
2452 .with_stderr_contains(" failed to update submodule `bar`")
2453 .run();
2454 project
2455 .cargo("build")
2456 .with_status(101)
2457 .with_stderr_contains(" failed to update submodule `src`")
2458 .with_stderr_contains(" failed to update submodule `bar`")
2459 .run();
2460
2461 done.store(true, Ordering::SeqCst);
2462 drop(TcpStream::connect(&addr));
2463 t.join().unwrap();
2464 }
2465
2466 #[cargo_test]
2467 fn use_the_cli() {
2468 if disable_git_cli() {
2469 return;
2470 }
2471 let project = project();
2472 let git_project = git::new("dep1", |project| {
2473 project
2474 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
2475 .file("src/lib.rs", "")
2476 });
2477
2478 let project = project
2479 .file(
2480 "Cargo.toml",
2481 &format!(
2482 r#"
2483 [project]
2484 name = "foo"
2485 version = "0.5.0"
2486 authors = []
2487
2488 [dependencies]
2489 dep1 = {{ git = '{}' }}
2490 "#,
2491 git_project.url()
2492 ),
2493 )
2494 .file("src/lib.rs", "")
2495 .file(
2496 ".cargo/config",
2497 "
2498 [net]
2499 git-fetch-with-cli = true
2500 ",
2501 )
2502 .build();
2503
2504 let stderr = "\
2505 [UPDATING] git repository `[..]`
2506 [RUNNING] `git fetch [..]`
2507 [COMPILING] dep1 [..]
2508 [RUNNING] `rustc [..]`
2509 [COMPILING] foo [..]
2510 [RUNNING] `rustc [..]`
2511 [FINISHED] [..]
2512 ";
2513
2514 project.cargo("build -v").with_stderr(stderr).run();
2515 }
2516
2517 #[cargo_test]
2518 fn templatedir_doesnt_cause_problems() {
2519 let git_project2 = git::new("dep2", |project| {
2520 project
2521 .file("Cargo.toml", &basic_manifest("dep2", "0.5.0"))
2522 .file("src/lib.rs", "")
2523 });
2524 let git_project = git::new("dep1", |project| {
2525 project
2526 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
2527 .file("src/lib.rs", "")
2528 });
2529 let p = project()
2530 .file(
2531 "Cargo.toml",
2532 &format!(
2533 r#"
2534 [project]
2535 name = "fo"
2536 version = "0.5.0"
2537 authors = []
2538
2539 [dependencies]
2540 dep1 = {{ git = '{}' }}
2541 "#,
2542 git_project.url()
2543 ),
2544 )
2545 .file("src/main.rs", "fn main() {}")
2546 .build();
2547
2548 fs::write(
2549 paths::home().join(".gitconfig"),
2550 format!(
2551 r#"
2552 [init]
2553 templatedir = {}
2554 "#,
2555 git_project2
2556 .url()
2557 .to_file_path()
2558 .unwrap()
2559 .to_str()
2560 .unwrap()
2561 .replace("\\", "/")
2562 ),
2563 )
2564 .unwrap();
2565
2566 p.cargo("build").run();
2567 }
2568
2569 #[cargo_test]
2570 fn git_with_cli_force() {
2571 if disable_git_cli() {
2572 return;
2573 }
2574 // Supports a force-pushed repo.
2575 let git_project = git::new("dep1", |project| {
2576 project
2577 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2578 .file("src/lib.rs", r#"pub fn f() { println!("one"); }"#)
2579 });
2580 let p = project()
2581 .file(
2582 "Cargo.toml",
2583 &format!(
2584 r#"
2585 [project]
2586 name = "foo"
2587 version = "0.0.1"
2588 edition = "2018"
2589
2590 [dependencies]
2591 dep1 = {{ git = "{}" }}
2592 "#,
2593 git_project.url()
2594 ),
2595 )
2596 .file("src/main.rs", "fn main() { dep1::f(); }")
2597 .file(
2598 ".cargo/config",
2599 "
2600 [net]
2601 git-fetch-with-cli = true
2602 ",
2603 )
2604 .build();
2605 p.cargo("build").run();
2606 p.rename_run("foo", "foo1").with_stdout("one").run();
2607
2608 // commit --amend a change that will require a force fetch.
2609 let repo = git2::Repository::open(&git_project.root()).unwrap();
2610 git_project.change_file("src/lib.rs", r#"pub fn f() { println!("two"); }"#);
2611 git::add(&repo);
2612 let id = repo.refname_to_id("HEAD").unwrap();
2613 let commit = repo.find_commit(id).unwrap();
2614 let tree_id = t!(t!(repo.index()).write_tree());
2615 t!(commit.amend(
2616 Some("HEAD"),
2617 None,
2618 None,
2619 None,
2620 None,
2621 Some(&t!(repo.find_tree(tree_id)))
2622 ));
2623 // Perform the fetch.
2624 p.cargo("update").run();
2625 p.cargo("build").run();
2626 p.rename_run("foo", "foo2").with_stdout("two").run();
2627 }
2628
2629 #[cargo_test]
2630 fn git_fetch_cli_env_clean() {
2631 if disable_git_cli() {
2632 return;
2633 }
2634 // This tests that git-fetch-with-cli works when GIT_DIR environment
2635 // variable is set (for whatever reason).
2636 let git_dep = git::new("dep1", |project| {
2637 project
2638 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
2639 .file("src/lib.rs", "")
2640 });
2641
2642 let git_proj = git::new("foo", |project| {
2643 project
2644 .file(
2645 "Cargo.toml",
2646 &format!(
2647 r#"
2648 [package]
2649 name = "foo"
2650 version = "0.1.0"
2651 [dependencies]
2652 dep1 = {{ git = '{}' }}
2653 "#,
2654 git_dep.url()
2655 ),
2656 )
2657 .file("src/lib.rs", "pub extern crate dep1;")
2658 .file(
2659 ".cargo/config",
2660 "
2661 [net]
2662 git-fetch-with-cli = true
2663 ",
2664 )
2665 });
2666
2667 // The directory set here isn't too important. Pointing to our own git
2668 // directory causes git to be confused and fail. Can also point to an
2669 // empty directory, or a nonexistent one.
2670 git_proj
2671 .cargo("fetch")
2672 .env("GIT_DIR", git_proj.root().join(".git"))
2673 .run();
2674 }
2675
2676 #[cargo_test]
2677 fn dirty_submodule() {
2678 // `cargo package` warns for dirty file in submodule.
2679 let (git_project, repo) = git::new_repo("foo", |project| {
2680 project
2681 .file("Cargo.toml", &basic_manifest("foo", "0.5.0"))
2682 // This is necessary because `git::add` is too eager.
2683 .file(".gitignore", "/target")
2684 });
2685 let git_project2 = git::new("src", |project| {
2686 project.no_manifest().file("lib.rs", "pub fn f() {}")
2687 });
2688
2689 let url = path2url(git_project2.root()).to_string();
2690 git::add_submodule(&repo, &url, Path::new("src"));
2691
2692 // Submodule added, but not committed.
2693 git_project
2694 .cargo("package --no-verify")
2695 .with_status(101)
2696 .with_stderr(
2697 "\
2698 [WARNING] manifest has no [..]
2699 See [..]
2700 [ERROR] 1 files in the working directory contain changes that were not yet committed into git:
2701
2702 .gitmodules
2703
2704 to proceed despite [..]
2705 ",
2706 )
2707 .run();
2708
2709 git::commit(&repo);
2710 git_project.cargo("package --no-verify").run();
2711
2712 // Modify file, check for warning.
2713 git_project.change_file("src/lib.rs", "");
2714 git_project
2715 .cargo("package --no-verify")
2716 .with_status(101)
2717 .with_stderr(
2718 "\
2719 [WARNING] manifest has no [..]
2720 See [..]
2721 [ERROR] 1 files in the working directory contain changes that were not yet committed into git:
2722
2723 src/lib.rs
2724
2725 to proceed despite [..]
2726 ",
2727 )
2728 .run();
2729 // Commit the change.
2730 let sub_repo = git2::Repository::open(git_project.root().join("src")).unwrap();
2731 git::add(&sub_repo);
2732 git::commit(&sub_repo);
2733 git::add(&repo);
2734 git::commit(&repo);
2735 git_project.cargo("package --no-verify").run();
2736
2737 // Try with a nested submodule.
2738 let git_project3 = git::new("bar", |project| project.no_manifest().file("mod.rs", ""));
2739 let url = path2url(git_project3.root()).to_string();
2740 git::add_submodule(&sub_repo, &url, Path::new("bar"));
2741 git_project
2742 .cargo("package --no-verify")
2743 .with_status(101)
2744 .with_stderr(
2745 "\
2746 [WARNING] manifest has no [..]
2747 See [..]
2748 [ERROR] 1 files in the working directory contain changes that were not yet committed into git:
2749
2750 src/.gitmodules
2751
2752 to proceed despite [..]
2753 ",
2754 )
2755 .run();
2756
2757 // Commit the submodule addition.
2758 git::commit(&sub_repo);
2759 git::add(&repo);
2760 git::commit(&repo);
2761 git_project.cargo("package --no-verify").run();
2762 // Modify within nested submodule.
2763 git_project.change_file("src/bar/mod.rs", "//test");
2764 git_project
2765 .cargo("package --no-verify")
2766 .with_status(101)
2767 .with_stderr(
2768 "\
2769 [WARNING] manifest has no [..]
2770 See [..]
2771 [ERROR] 1 files in the working directory contain changes that were not yet committed into git:
2772
2773 src/bar/mod.rs
2774
2775 to proceed despite [..]
2776 ",
2777 )
2778 .run();
2779 // And commit the change.
2780 let sub_sub_repo = git2::Repository::open(git_project.root().join("src/bar")).unwrap();
2781 git::add(&sub_sub_repo);
2782 git::commit(&sub_sub_repo);
2783 git::add(&sub_repo);
2784 git::commit(&sub_repo);
2785 git::add(&repo);
2786 git::commit(&repo);
2787 git_project.cargo("package --no-verify").run();
2788 }
2789
2790 #[cargo_test]
2791 fn default_not_master() {
2792 let project = project();
2793
2794 // Create a repository with a `master` branch, but switch the head to a
2795 // branch called `main` at the same time.
2796 let (git_project, repo) = git::new_repo("dep1", |project| {
2797 project
2798 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2799 .file("src/lib.rs", "pub fn foo() {}")
2800 });
2801 let head_id = repo.head().unwrap().target().unwrap();
2802 let head = repo.find_commit(head_id).unwrap();
2803 repo.branch("main", &head, false).unwrap();
2804 repo.set_head("refs/heads/main").unwrap();
2805
2806 // Then create a commit on the new `main` branch so `master` and `main`
2807 // differ.
2808 git_project.change_file("src/lib.rs", "");
2809 git::add(&repo);
2810 git::commit(&repo);
2811
2812 let project = project
2813 .file(
2814 "Cargo.toml",
2815 &format!(
2816 r#"
2817 [project]
2818 name = "foo"
2819 version = "0.5.0"
2820
2821 [dependencies]
2822 dep1 = {{ git = '{}' }}
2823 "#,
2824 git_project.url()
2825 ),
2826 )
2827 .file("src/lib.rs", "pub fn foo() { dep1::foo() }")
2828 .build();
2829
2830 project
2831 .cargo("build")
2832 .with_stderr(
2833 "\
2834 [UPDATING] git repository `[..]`
2835 warning: fetching `master` branch from `[..]` but the `HEAD` \
2836 reference for this repository is not the \
2837 `master` branch. This behavior will change \
2838 in Cargo in the future and your build may \
2839 break, so it's recommended to place \
2840 `branch = \"master\"` in Cargo.toml when \
2841 depending on this git repository to ensure \
2842 that your build will continue to work.
2843 [COMPILING] dep1 v0.5.0 ([..])
2844 [COMPILING] foo v0.5.0 ([..])
2845 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
2846 )
2847 .run();
2848 }
2849
2850 #[cargo_test]
2851 fn historical_lockfile_works() {
2852 let project = project();
2853
2854 let (git_project, repo) = git::new_repo("dep1", |project| {
2855 project
2856 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2857 .file("src/lib.rs", "")
2858 });
2859 let head_id = repo.head().unwrap().target().unwrap();
2860
2861 let project = project
2862 .file(
2863 "Cargo.toml",
2864 &format!(
2865 r#"
2866 [project]
2867 name = "foo"
2868 version = "0.5.0"
2869
2870 [dependencies]
2871 dep1 = {{ git = '{}', branch = 'master' }}
2872 "#,
2873 git_project.url()
2874 ),
2875 )
2876 .file("src/lib.rs", "")
2877 .build();
2878
2879 project.cargo("build").run();
2880 project.change_file(
2881 "Cargo.lock",
2882 &format!(
2883 r#"# This file is automatically @generated by Cargo.
2884 # It is not intended for manual editing.
2885 [[package]]
2886 name = "dep1"
2887 version = "0.5.0"
2888 source = "git+{}#{}"
2889
2890 [[package]]
2891 name = "foo"
2892 version = "0.5.0"
2893 dependencies = [
2894 "dep1",
2895 ]
2896 "#,
2897 git_project.url(),
2898 head_id
2899 ),
2900 );
2901 project
2902 .cargo("build")
2903 .with_stderr("[FINISHED] [..]\n")
2904 .run();
2905 }
2906
2907 #[cargo_test]
2908 fn historical_lockfile_works_with_vendor() {
2909 let project = project();
2910
2911 let (git_project, repo) = git::new_repo("dep1", |project| {
2912 project
2913 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2914 .file("src/lib.rs", "")
2915 });
2916 let head_id = repo.head().unwrap().target().unwrap();
2917
2918 let project = project
2919 .file(
2920 "Cargo.toml",
2921 &format!(
2922 r#"
2923 [project]
2924 name = "foo"
2925 version = "0.5.0"
2926
2927 [dependencies]
2928 dep1 = {{ git = '{}', branch = 'master' }}
2929 "#,
2930 git_project.url()
2931 ),
2932 )
2933 .file("src/lib.rs", "")
2934 .build();
2935
2936 let output = project.cargo("vendor").exec_with_output().unwrap();
2937 project.change_file(".cargo/config", str::from_utf8(&output.stdout).unwrap());
2938 project.change_file(
2939 "Cargo.lock",
2940 &format!(
2941 r#"# This file is automatically @generated by Cargo.
2942 # It is not intended for manual editing.
2943 [[package]]
2944 name = "dep1"
2945 version = "0.5.0"
2946 source = "git+{}#{}"
2947
2948 [[package]]
2949 name = "foo"
2950 version = "0.5.0"
2951 dependencies = [
2952 "dep1",
2953 ]
2954 "#,
2955 git_project.url(),
2956 head_id
2957 ),
2958 );
2959 project.cargo("build").run();
2960 }
2961
2962 #[cargo_test]
2963 fn two_dep_forms() {
2964 let project = project();
2965
2966 let (git_project, _repo) = git::new_repo("dep1", |project| {
2967 project
2968 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2969 .file("src/lib.rs", "")
2970 });
2971
2972 let project = project
2973 .file(
2974 "Cargo.toml",
2975 &format!(
2976 r#"
2977 [project]
2978 name = "foo"
2979 version = "0.5.0"
2980
2981 [dependencies]
2982 dep1 = {{ git = '{}', branch = 'master' }}
2983 a = {{ path = 'a' }}
2984 "#,
2985 git_project.url()
2986 ),
2987 )
2988 .file("src/lib.rs", "")
2989 .file(
2990 "a/Cargo.toml",
2991 &format!(
2992 r#"
2993 [project]
2994 name = "a"
2995 version = "0.5.0"
2996
2997 [dependencies]
2998 dep1 = {{ git = '{}' }}
2999 "#,
3000 git_project.url()
3001 ),
3002 )
3003 .file("a/src/lib.rs", "")
3004 .build();
3005
3006 project
3007 .cargo("build")
3008 .with_stderr(
3009 "\
3010 [UPDATING] [..]
3011 warning: two git dependencies found for `[..]` where one uses `branch = \"master\"` \
3012 and the other doesn't; this will break in a future version of Cargo, so please \
3013 ensure the dependency forms are consistent
3014 warning: [..]
3015 [COMPILING] [..]
3016 [COMPILING] [..]
3017 [COMPILING] [..]
3018 [FINISHED] [..]
3019 ",
3020 )
3021 .run();
3022 }
3023
3024 #[cargo_test]
3025 fn metadata_master_consistency() {
3026 // SourceId consistency in the `cargo metadata` output when `master` is
3027 // explicit or implicit, using new or old Cargo.lock.
3028 let (git_project, git_repo) = git::new_repo("bar", |project| {
3029 project
3030 .file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
3031 .file("src/lib.rs", "")
3032 });
3033 let bar_hash = git_repo.head().unwrap().target().unwrap().to_string();
3034
3035 // Explicit branch="master" with a lock file created before 1.47 (does not contain ?branch=master).
3036 let p = project()
3037 .file(
3038 "Cargo.toml",
3039 &format!(
3040 r#"
3041 [package]
3042 name = "foo"
3043 version = "0.1.0"
3044
3045 [dependencies]
3046 bar = {{ git = "{}", branch = "master" }}
3047 "#,
3048 git_project.url()
3049 ),
3050 )
3051 .file(
3052 "Cargo.lock",
3053 &format!(
3054 r#"
3055 [[package]]
3056 name = "bar"
3057 version = "1.0.0"
3058 source = "git+{}#{}"
3059
3060 [[package]]
3061 name = "foo"
3062 version = "0.1.0"
3063 dependencies = [
3064 "bar",
3065 ]
3066 "#,
3067 git_project.url(),
3068 bar_hash,
3069 ),
3070 )
3071 .file("src/lib.rs", "")
3072 .build();
3073
3074 let metadata = |bar_source| -> String {
3075 r#"
3076 {
3077 "packages": [
3078 {
3079 "name": "bar",
3080 "version": "1.0.0",
3081 "id": "bar 1.0.0 (__BAR_SOURCE__#__BAR_HASH__)",
3082 "license": null,
3083 "license_file": null,
3084 "description": null,
3085 "source": "__BAR_SOURCE__#__BAR_HASH__",
3086 "dependencies": [],
3087 "targets": "{...}",
3088 "features": {},
3089 "manifest_path": "[..]",
3090 "metadata": null,
3091 "publish": null,
3092 "authors": [],
3093 "categories": [],
3094 "keywords": [],
3095 "readme": null,
3096 "repository": null,
3097 "homepage": null,
3098 "documentation": null,
3099 "edition": "2015",
3100 "links": null
3101 },
3102 {
3103 "name": "foo",
3104 "version": "0.1.0",
3105 "id": "foo 0.1.0 [..]",
3106 "license": null,
3107 "license_file": null,
3108 "description": null,
3109 "source": null,
3110 "dependencies": [
3111 {
3112 "name": "bar",
3113 "source": "__BAR_SOURCE__",
3114 "req": "*",
3115 "kind": null,
3116 "rename": null,
3117 "optional": false,
3118 "uses_default_features": true,
3119 "features": [],
3120 "target": null,
3121 "registry": null
3122 }
3123 ],
3124 "targets": "{...}",
3125 "features": {},
3126 "manifest_path": "[..]",
3127 "metadata": null,
3128 "publish": null,
3129 "authors": [],
3130 "categories": [],
3131 "keywords": [],
3132 "readme": null,
3133 "repository": null,
3134 "homepage": null,
3135 "documentation": null,
3136 "edition": "2015",
3137 "links": null
3138 }
3139 ],
3140 "workspace_members": [
3141 "foo 0.1.0 [..]"
3142 ],
3143 "resolve": {
3144 "nodes": [
3145 {
3146 "id": "bar 1.0.0 (__BAR_SOURCE__#__BAR_HASH__)",
3147 "dependencies": [],
3148 "deps": [],
3149 "features": []
3150 },
3151 {
3152 "id": "foo 0.1.0 [..]",
3153 "dependencies": [
3154 "bar 1.0.0 (__BAR_SOURCE__#__BAR_HASH__)"
3155 ],
3156 "deps": [
3157 {
3158 "name": "bar",
3159 "pkg": "bar 1.0.0 (__BAR_SOURCE__#__BAR_HASH__)",
3160 "dep_kinds": [
3161 {
3162 "kind": null,
3163 "target": null
3164 }
3165 ]
3166 }
3167 ],
3168 "features": []
3169 }
3170 ],
3171 "root": "foo 0.1.0 [..]"
3172 },
3173 "target_directory": "[..]",
3174 "version": 1,
3175 "workspace_root": "[..]",
3176 "metadata": null
3177 }
3178 "#
3179 .replace("__BAR_SOURCE__", bar_source)
3180 .replace("__BAR_HASH__", &bar_hash)
3181 };
3182
3183 let bar_source = format!("git+{}?branch=master", git_project.url());
3184 p.cargo("metadata").with_json(&metadata(&bar_source)).run();
3185
3186 // Conversely, remove branch="master" from Cargo.toml, but use a new Cargo.lock that has ?branch=master.
3187 let p = project()
3188 .file(
3189 "Cargo.toml",
3190 &format!(
3191 r#"
3192 [package]
3193 name = "foo"
3194 version = "0.1.0"
3195
3196 [dependencies]
3197 bar = {{ git = "{}" }}
3198 "#,
3199 git_project.url()
3200 ),
3201 )
3202 .file(
3203 "Cargo.lock",
3204 &format!(
3205 r#"
3206 [[package]]
3207 name = "bar"
3208 version = "1.0.0"
3209 source = "git+{}?branch=master#{}"
3210
3211 [[package]]
3212 name = "foo"
3213 version = "0.1.0"
3214 dependencies = [
3215 "bar",
3216 ]
3217 "#,
3218 git_project.url(),
3219 bar_hash
3220 ),
3221 )
3222 .file("src/lib.rs", "")
3223 .build();
3224
3225 // No ?branch=master!
3226 let bar_source = format!("git+{}", git_project.url());
3227 p.cargo("metadata").with_json(&metadata(&bar_source)).run();
3228 }