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