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