1 //! Tests for git support.
5 use std
::io
::prelude
::*;
6 use std
::net
::{TcpListener, TcpStream}
;
8 use std
::sync
::atomic
::{AtomicBool, Ordering}
;
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}
;
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())
24 fn cargo_compile_simple_git_dep() {
25 let project
= project();
26 let git_project
= git
::new("dep1", |project
| {
28 .file("Cargo.toml", &basic_lib_manifest("dep1"))
32 pub fn hello() -> &'static str {
48 authors = ["wycats@example.com"]
59 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
63 let git_root
= git_project
.root();
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",
77 assert
!(project
.bin("foo").is_file());
80 .process(&project
.bin("foo"))
81 .with_stdout("hello world\n")
86 fn cargo_compile_git_dep_branch() {
87 let project
= project();
88 let git_project
= git
::new("dep1", |project
| {
90 .file("Cargo.toml", &basic_lib_manifest("dep1"))
94 pub fn hello() -> &'static str {
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();
107 let project
= project
116 authors = ["wycats@example.com"]
129 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
133 let git_root
= git_project
.root();
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",
147 assert
!(project
.bin("foo").is_file());
150 .process(&project
.bin("foo"))
151 .with_stdout("hello world\n")
156 fn cargo_compile_git_dep_tag() {
157 let project
= project();
158 let git_project
= git
::new("dep1", |project
| {
160 .file("Cargo.toml", &basic_lib_manifest("dep1"))
164 pub fn hello() -> &'static str {
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();
176 &repo
.find_object(head
, None
).unwrap(),
177 &repo
.signature().unwrap(),
183 let project
= project
192 authors = ["wycats@example.com"]
204 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
208 let git_root
= git_project
.root();
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",
222 assert
!(project
.bin("foo").is_file());
225 .process(&project
.bin("foo"))
226 .with_stdout("hello world\n")
229 project
.cargo("build").run();
233 fn cargo_compile_with_nested_paths() {
234 let git_project
= git
::new("dep1", |project
| {
243 authors = ["carlhuda@example.com"]
260 pub fn hello() -> &'static str {
265 .file("vendor/dep2/Cargo.toml", &basic_lib_manifest("dep2"))
267 "vendor/dep2/src/dep2.rs",
269 pub fn hello() -> &'static str {
285 authors = ["wycats@example.com"]
301 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
305 p
.cargo("build").run();
307 assert
!(p
.bin("foo").is_file());
309 p
.process(&p
.bin("foo")).with_stdout("hello world\n").run();
313 fn cargo_compile_with_malformed_nested_paths() {
314 let git_project
= git
::new("dep1", |project
| {
316 .file("Cargo.toml", &basic_lib_manifest("dep1"))
320 pub fn hello() -> &'static str {
325 .file("vendor/dep2/Cargo.toml", "!INVALID!")
327 "vendor/dep3/Cargo.toml",
333 subdep1 = { path = "../require-extra-build-step" }"#,
335 .file("vendor/dep3/src/lib.rs", "")
347 authors = ["wycats@example.com"]
363 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
367 p
.cargo("build").run();
369 assert
!(p
.bin("foo").is_file());
371 p
.process(&p
.bin("foo")).with_stdout("hello world\n").run();
375 fn cargo_compile_with_meta_package() {
376 let git_project
= git
::new("meta-dep", |project
| {
378 .file("dep1/Cargo.toml", &basic_lib_manifest("dep1"))
382 pub fn hello() -> &'static str {
387 .file("dep2/Cargo.toml", &basic_lib_manifest("dep2"))
391 pub fn hello() -> &'static str {
407 authors = ["wycats@example.com"]
430 r
#""{} {}", dep1::hello(), dep2::hello()"#,
436 p
.cargo("build").run();
438 assert
!(p
.bin("foo").is_file());
440 p
.process(&p
.bin("foo"))
441 .with_stdout("this is dep1 this is dep2\n")
446 fn cargo_compile_with_short_ssh_git() {
447 let url
= "git@github.com:a/dep";
458 authors = ["wycats@example.com"]
473 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
480 .with_stderr(&format
!(
482 [ERROR] failed to parse manifest at `[..]`
485 invalid url `{}`: relative URL without a base
493 fn two_revs_same_deps() {
494 let bar
= git
::new("meta-dep", |project
| {
496 .file("Cargo.toml", &basic_manifest("bar", "0.0.0"))
497 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
500 let repo
= git2
::Repository
::open(&bar
.root()).unwrap();
501 let rev1
= repo
.revparse_single("HEAD").unwrap().id();
503 // Commit the changes and make sure we trigger a recompile
504 bar
.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
506 let rev2
= git
::commit(&repo
);
536 assert_eq!(bar::bar(), 1);
537 assert_eq!(baz::baz(), 2);
566 pub fn baz() -> i32 { bar::bar() }
571 foo
.cargo("build -v").run();
572 assert
!(foo
.bin("foo").is_file());
573 foo
.process(&foo
.bin("foo")).run();
578 let git_project
= git
::new("bar", |project
| {
580 .file("Cargo.toml", &basic_lib_manifest("bar"))
581 .file("src/bar.rs", "pub fn bar() {}")
593 authors = ["wycats@example.com"]
603 .file("src/main.rs", &main_file(r
#""{:?}", bar::bar()"#, &["bar"]))
606 // First time around we should compile both foo and bar
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) \
619 // Don't recompile the second time
620 p
.cargo("build").with_stdout("").run();
622 // Modify a file manually, shouldn't trigger a recompile
623 git_project
.change_file("src/bar.rs", r
#"pub fn bar() { println!("hello!"); }"#);
625 p
.cargo("build").with_stdout("").run();
628 .with_stderr(&format
!(
629 "[UPDATING] git repository `{}`",
634 p
.cargo("build").with_stdout("").run();
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();
642 println
!("compile after commit");
643 p
.cargo("build").with_stdout("").run();
644 p
.root().move_into_the_past();
646 // Update the dependency and carry on!
648 .with_stderr(&format
!(
649 "[UPDATING] git repository `{}`\n\
650 [UPDATING] bar v0.5.0 ([..]) -> #[..]\n\
655 println
!("going for the last compile");
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) \
666 // Make sure clean only cleans one dep
667 p
.cargo("clean -p foo").with_stdout("").run();
670 "[COMPILING] foo v0.5.0 ([CWD])\n\
671 [FINISHED] dev [unoptimized + debuginfo] target(s) \
678 fn update_with_shared_deps() {
679 let git_project
= git
::new("bar", |project
| {
681 .file("Cargo.toml", &basic_lib_manifest("bar"))
682 .file("src/bar.rs", "pub fn bar() {}")
692 authors = ["wycats@example.com"]
703 #[allow(unused_extern_crates)]
705 #[allow(unused_extern_crates)]
717 authors = ["wycats@example.com"]
726 .file("dep1/src/lib.rs", "")
734 authors = ["wycats@example.com"]
743 .file("dep2/src/lib.rs", "")
746 // First time around we should compile both foo and bar
748 .with_stderr(&format
!(
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(),
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();
769 // By default, not transitive updates
770 println
!("dep1 update");
771 p
.cargo("update -p dep1").with_stdout("").run();
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")
779 [ERROR] Unable to update [..]
782 precise value for git is not a git revision: 0.1.2
785 unable to parse OID - contains invalid characters; class=Invalid (3)
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())
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\
809 // Make sure we still only compile one version of the git repo
812 .with_stderr(&format
!(
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(),
823 // We should be able to update transitive deps
824 p
.cargo("update -p bar")
825 .with_stderr(&format
!(
826 "[UPDATING] git repository `{}`",
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"))
838 let git_project2
= git
::new("dep2", |project
| project
.file("lib.rs", "pub fn dep() {}"));
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"));
845 let project
= project
854 authors = ["wycats@example.com"]
865 "extern crate dep1; pub fn foo() { dep1::dep() }",
873 [UPDATING] git repository [..]
874 [UPDATING] git submodule `file://[..]/dep2`
875 [COMPILING] dep1 [..]
877 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
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"))
888 let git_project2
= git
::new("dep2", |project
| project
.file("lib.rs", "pub fn dep() {}"));
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"));
895 // now amend the first commit on git_project2 to make submodule ref point to not-found
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();
902 Some("refs/heads/master"),
906 Some("something something"),
920 authors = ["wycats@example.com"]
931 "extern crate dep1; pub fn foo() { dep1::dep() }",
935 let expected
= format
!(
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 [..]`
942 failed to load source for dependency `dep1`
948 failed to update submodule `src`
951 object not found - no match for id [..]
953 path2url(git_project
.root())
957 .with_stderr(expected
)
963 fn two_deps_only_update_one() {
964 let project
= project();
965 let git1
= git
::new("dep1", |project
| {
967 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
968 .file("src/lib.rs", "")
970 let git2
= git
::new("dep2", |project
| {
972 .file("Cargo.toml", &basic_manifest("dep2", "0.5.0"))
973 .file("src/lib.rs", "")
985 authors = ["wycats@example.com"]
996 .file("src/main.rs", "fn main() {}")
999 fn oid_to_short_sha(oid
: git2
::Oid
) -> String
{
1000 oid
.to_string()[..8].to_string()
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
)
1008 println
!("dep1 head sha: {}", git_repo_head_sha(&git1
));
1009 println
!("dep2 head sha: {}", git_repo_head_sha(&git2
));
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",
1022 git1
.change_file("src/lib.rs", "pub fn foo() {}");
1023 let repo
= git2
::Repository
::open(&git1
.root()).unwrap();
1025 let oid
= git
::commit(&repo
);
1026 println
!("dep1 head sha: {}", oid_to_short_sha(oid
));
1028 p
.cargo("update -p dep1")
1029 .with_stderr(&format
!(
1030 "[UPDATING] git repository `{}`\n\
1031 [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
1039 fn stale_cached_version() {
1040 let bar
= git
::new("meta-dep", |project
| {
1042 .file("Cargo.toml", &basic_manifest("bar", "0.0.0"))
1043 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1046 // Update the git database in the cache with the current state of the git
1069 fn main() { assert_eq!(bar::bar(), 1) }
1074 foo
.cargo("build").run();
1075 foo
.process(&foo
.bin("foo")).run();
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();
1086 let rev
= repo
.revparse_single("HEAD").unwrap().id();
1096 'bar 0.0.0 (git+{url}#{hash})'
1102 source = 'git+{url}#{hash}'
1111 .with_stderr(&format
!(
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 [..]
1121 foo
.process(&foo
.bin("foo")).run();
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"))
1131 let git_project2
= git
::new("dep2", |project
| {
1132 project
.file("lib.rs", "pub fn dep() -> &'static str { \"project2\" }")
1135 let git_project3
= git
::new("dep3", |project
| {
1136 project
.file("lib.rs", "pub fn dep() -> &'static str { \"project3\" }")
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"));
1151 authors = ["wycats@example.com"]
1162 pub fn main() { println!(\"{}\", dep1::dep()) }
1167 println
!("first run");
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 \
1176 [RUNNING] `target/debug/foo[EXE]`\n",
1178 .with_stdout("project2\n")
1181 git_project
.change_file(
1184 "[submodule \"src\"]\n\tpath = src\n\turl={}",
1189 // Sync the submodule and reset it to the new remote.
1190 sub
.sync().unwrap();
1192 let subrepo
= sub
.open().unwrap();
1194 .remote_add_fetch("origin", "refs/heads/*:refs/heads/*")
1197 .remote_set_url("origin", &git_project3
.url().to_string())
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();
1205 sub
.add_to_index(true).unwrap();
1210 // Update the dependency and carry on!
1212 p
.cargo("update -v")
1214 .with_stderr(&format
!(
1215 "[UPDATING] git repository `{}`\n\
1216 [UPDATING] git submodule `file://[..]/dep3`\n\
1217 [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
1223 println
!("last run");
1226 "[COMPILING] dep1 v0.5.0 ([..])\n\
1227 [COMPILING] foo v0.5.0 ([..])\n\
1228 [FINISHED] dev [unoptimized + debuginfo] target(s) in \
1230 [RUNNING] `target/debug/foo[EXE]`\n",
1232 .with_stdout("project3\n")
1237 fn dev_deps_with_testing() {
1238 let p2
= git
::new("bar", |project
| {
1240 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1244 pub fn gimme() -> &'static str { "zoidberg" }
1258 authors = ["wycats@example.com"]
1260 [dev-dependencies.bar]
1275 #[test] fn foo() { bar::gimme(); }
1281 // Generate a lock file which did not use `bar` to compile, but had to update
1282 // `bar` to generate the lock file
1284 .with_stderr(&format
!(
1286 [UPDATING] git repository `{bar}`
1287 [COMPILING] foo v0.5.0 ([CWD])
1288 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1294 // Make sure we use the previous resolution of `bar` instead of updating it
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]",
1304 .with_stdout_contains("test tests::foo ... ok")
1309 fn git_build_cmd_freshness() {
1310 let foo
= git
::new("foo", |project
| {
1322 .file("build.rs", "fn main() {}")
1323 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1324 .file(".gitignore", "src/bar.rs")
1326 foo
.root().move_into_the_past();
1333 [COMPILING] foo v0.0.0 ([CWD])
1334 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1339 // Smoke test to make sure it doesn't compile again
1340 println
!("first pass");
1341 foo
.cargo("build").with_stdout("").run();
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();
1350 fn git_name_not_always_needed() {
1351 let p2
= git
::new("bar", |project
| {
1353 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1357 pub fn gimme() -> &'static str { "zoidberg" }
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");
1377 [dev-dependencies.bar]
1383 .file("src/main.rs", "fn main() {}")
1386 // Generate a lock file which did not use `bar` to compile, but had to update
1387 // `bar` to generate the lock file
1389 .with_stderr(&format
!(
1391 [UPDATING] git repository `{bar}`
1392 [COMPILING] foo v0.5.0 ([CWD])
1393 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1401 fn git_repo_changing_no_rebuild() {
1402 let bar
= git
::new("bar", |project
| {
1404 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1405 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1408 // Lock p1 to the first rev in the git repo
1426 .file("src/main.rs", "fn main() {}")
1427 .file("build.rs", "fn main() {}")
1429 p1
.root().move_into_the_past();
1431 .with_stderr(&format
!(
1433 [UPDATING] git repository `{bar}`
1436 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
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();
1448 // Lock p2 to the second rev
1465 .file("src/main.rs", "fn main() {}")
1468 .with_stderr(&format
!(
1470 [UPDATING] git repository `{bar}`
1473 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
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();
1485 fn git_dep_build_cmd() {
1486 let p
= git
::new("foo", |project
| {
1495 authors = ["wycats@example.com"]
1507 .file("src/foo.rs", &main_file(r
#""{}", bar::gimme()"#, &["bar"]))
1515 authors = ["wycats@example.com"]
1524 "bar/src/bar.rs.in",
1526 pub fn gimme() -> i32 { 0 }
1534 fs::copy("src/bar.rs.in", "src/bar.rs").unwrap();
1540 p
.root().join("bar").move_into_the_past();
1542 p
.cargo("build").run();
1544 p
.process(&p
.bin("foo")).with_stdout("0\n").run();
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 }");
1549 p
.cargo("build").run();
1551 p
.process(&p
.bin("foo")).with_stdout("1\n").run();
1555 fn fetch_downloads() {
1556 let bar
= git
::new("bar", |project
| {
1558 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1559 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1577 .file("src/main.rs", "fn main() {}")
1580 .with_stderr(&format
!(
1581 "[UPDATING] git repository `{url}`",
1586 p
.cargo("fetch").with_stdout("").run();
1590 fn warnings_in_git_dep() {
1591 let bar
= git
::new("bar", |project
| {
1593 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1594 .file("src/lib.rs", "fn unused() {}")
1612 .file("src/main.rs", "fn main() {}")
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",
1628 fn update_ambiguous() {
1629 let bar1
= git
::new("bar1", |project
| {
1631 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1632 .file("src/lib.rs", "")
1634 let bar2
= git
::new("bar2", |project
| {
1636 .file("Cargo.toml", &basic_manifest("bar", "0.6.0"))
1637 .file("src/lib.rs", "")
1639 let baz
= git
::new("baz", |project
| {
1648 authors = ["wycats@example.com"]
1656 .file("src/lib.rs", "")
1677 .file("src/main.rs", "fn main() {}")
1680 p
.cargo("generate-lockfile").run();
1681 p
.cargo("update -p bar")
1685 [ERROR] There are multiple `bar` packages in your project, and the specification `bar` \
1687 Please re-run this command with `-p <spec>` where `<spec>` is one of the \
1697 fn update_one_dep_in_repo_with_many_deps() {
1698 let bar
= git
::new("bar", |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", "")
1724 .file("src/main.rs", "fn main() {}")
1727 p
.cargo("generate-lockfile").run();
1728 p
.cargo("update -p bar")
1729 .with_stderr(&format
!("[UPDATING] git repository `{}`", bar
.url()))
1734 fn switch_deps_does_not_update_transitive() {
1735 let transitive
= git
::new("transitive", |project
| {
1737 .file("Cargo.toml", &basic_manifest("transitive", "0.5.0"))
1738 .file("src/lib.rs", "")
1740 let dep1
= git
::new("dep1", |project
| {
1749 authors = ["wycats@example.com"]
1751 [dependencies.transitive]
1757 .file("src/lib.rs", "")
1759 let dep2
= git
::new("dep2", |project
| {
1768 authors = ["wycats@example.com"]
1770 [dependencies.transitive]
1776 .file("src/lib.rs", "")
1794 .file("src/main.rs", "fn main() {}")
1798 .with_stderr(&format
!(
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 [..]
1812 // Update the dependency to point to the second repository, but this
1813 // shouldn't update the transitive dependency which is the same.
1830 .with_stderr(&format
!(
1832 [UPDATING] git repository `{}`
1833 [COMPILING] dep [..]
1834 [COMPILING] foo [..]
1835 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1843 fn update_one_source_updates_all_packages_in_that_git_source() {
1844 let dep
= git
::new("dep", |project
| {
1858 .file("src/lib.rs", "")
1859 .file("a/Cargo.toml", &basic_manifest("a", "0.5.0"))
1860 .file("a/src/lib.rs", "")
1878 .file("src/main.rs", "fn main() {}")
1881 p
.cargo("build").run();
1883 let repo
= git2
::Repository
::open(&dep
.root()).unwrap();
1884 let rev1
= repo
.revparse_single("HEAD").unwrap().id();
1886 // Just be sure to change a file
1887 dep
.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
1891 p
.cargo("update -p dep").run();
1892 let lockfile
= p
.read_lockfile();
1894 !lockfile
.contains(&rev1
.to_string()),
1902 fn switch_sources() {
1903 let a1
= git
::new("a1", |project
| {
1905 .file("Cargo.toml", &basic_manifest("a", "0.5.0"))
1906 .file("src/lib.rs", "")
1908 let a2
= git
::new("a2", |project
| {
1910 .file("Cargo.toml", &basic_manifest("a", "0.5.1"))
1911 .file("src/lib.rs", "")
1926 .file("src/main.rs", "fn main() {}")
1941 .file("b/src/lib.rs", "pub fn main() {}")
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 [..]
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 [..]
1985 fn dont_require_submodules_are_checked_out() {
1986 let p
= project().build();
1987 let git1
= git
::new("dep1", |p
| {
1998 .file("build.rs", "fn main() {}")
1999 .file("src/lib.rs", "")
2002 let git2
= git
::new("dep2", |p
| p
);
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"));
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();
2014 git1
.cargo("build -v").cwd(&dst
).run();
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() {}")
2024 let a1
= git
::new("a1", |p
| {
2034 a = {{ git = '{}' }}
2039 .file("src/lib.rs", "extern crate a; pub fn a1() {}")
2053 a = {{ git = '{}' }}
2067 p
.cargo("test -v").run();
2071 fn lints_are_suppressed() {
2072 let a
= git
::new("a", |p
| {
2073 p
.file("Cargo.toml", &basic_manifest("a", "0.5.0")).file(
2092 a = {{ git = '{}' }}
2097 .file("src/lib.rs", "")
2103 [UPDATING] git repository `[..]`
2104 [COMPILING] a v0.5.0 ([..])
2105 [COMPILING] foo v0.0.1 ([..])
2106 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
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(
2135 a = {{ git = '{}' }}
2140 .file("src/lib.rs", "")
2146 [UPDATING] git repository `[..]`
2147 [COMPILING] a v0.5.0 ([..])
2148 [COMPILING] foo v0.0.1 ([..])
2149 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
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", "")
2173 a = {{ path = 'a' }}
2174 git = {{ git = '{}' }}
2179 .file("src/lib.rs", "")
2180 .file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
2181 .file("a/src/lib.rs", "")
2184 p
.cargo("build").run();
2196 git = {{ git = '{}' }}
2202 p
.cargo("build").run();
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", "")
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();
2219 &repo
.find_object(head
, None
).unwrap(),
2220 &repo
.signature().unwrap(),
2237 git1 = {{ git = '{0}', rev = 'v0.1.0' }}
2238 git2 = {{ git = '{0}', rev = 'v0.1.0' }}
2243 .file("src/lib.rs", "")
2246 p
.cargo("generate-lockfile").run();
2247 p
.cargo("build -v").run();
2251 fn include_overrides_gitignore() {
2252 // Make sure that `package.include` takes precedence over .gitignore.
2253 let p
= git
::new("foo", |repo
| {
2260 include = ["src/lib.rs", "ignored.txt", "Cargo.toml"]
2271 .file("src/lib.rs", "")
2272 .file("ignored.txt", "")
2273 .file("build.rs", "fn main() {}")
2276 p
.cargo("build").run();
2277 p
.change_file("ignored.txt", "Trigger rebuild.");
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 [..]
2288 p
.cargo("package --list --allow-dirty")
2301 fn invalid_git_dependency_manifest() {
2302 let project
= project();
2303 let git_project
= git
::new("dep1", |project
| {
2312 authors = ["carlhuda@example.com"]
2313 categories = ["algorithms"]
2314 categories = ["algorithms"]
2324 pub fn hello() -> &'static str {
2331 let project
= project
2340 authors = ["wycats@example.com"]
2351 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
2355 let git_root
= git_project
.root();
2360 .with_stderr(&format
!(
2362 [UPDATING] git repository `{}`
2363 [ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([..])`
2366 failed to load source for dependency `dep1`
2372 failed to parse manifest at `[..]`
2375 could not parse input as TOML
2378 duplicate key: `categories` for key `project` at line 10 column 17",
2379 path2url(&git_root
),
2380 path2url(&git_root
),
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"))
2392 let git_project2
= git
::new("dep2", |project
| project
.file("lib.rs", ""));
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();
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"));
2407 let repo
= git2
::Repository
::open(&git_project2
.root()).unwrap();
2408 let url
= format
!("https://{}:{}/", addr
.ip(), addr
.port());
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();
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"));
2427 let project
= project
2438 dep1 = {{ git = '{}' }}
2443 .file("src/lib.rs", "")
2449 .with_stderr_contains(" failed to update submodule `src`")
2450 .with_stderr_contains(" failed to update submodule `bar`")
2455 .with_stderr_contains(" failed to update submodule `src`")
2456 .with_stderr_contains(" failed to update submodule `bar`")
2459 done
.store(true, Ordering
::SeqCst
);
2460 drop(TcpStream
::connect(&addr
));
2466 if disable_git_cli() {
2469 let project
= project();
2470 let git_project
= git
::new("dep1", |project
| {
2472 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
2473 .file("src/lib.rs", "")
2476 let project
= project
2487 dep1 = {{ git = '{}' }}
2492 .file("src/lib.rs", "")
2497 git-fetch-with-cli = true
2503 [UPDATING] git repository `[..]`
2504 [RUNNING] `git fetch [..]`
2505 [COMPILING] dep1 [..]
2506 [RUNNING] `rustc [..]`
2507 [COMPILING] foo [..]
2508 [RUNNING] `rustc [..]`
2512 project
.cargo("build -v").with_stderr(stderr
).run();
2516 fn templatedir_doesnt_cause_problems() {
2517 let git_project2
= git
::new("dep2", |project
| {
2519 .file("Cargo.toml", &basic_manifest("dep2", "0.5.0"))
2520 .file("src/lib.rs", "")
2522 let git_project
= git
::new("dep1", |project
| {
2524 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
2525 .file("src/lib.rs", "")
2538 dep1 = {{ git = '{}' }}
2543 .file("src/main.rs", "fn main() {}")
2547 paths
::home().join(".gitconfig"),
2564 p
.cargo("build").run();
2568 fn git_with_cli_force() {
2569 if disable_git_cli() {
2572 // Supports a force-pushed repo.
2573 let git_project
= git
::new("dep1", |project
| {
2575 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2576 .file("src/lib.rs", r
#"pub fn f() { println!("one"); }"#)
2589 dep1 = {{ git = "{}" }}
2594 .file("src
/main
.rs
", "fn main() { dep1::f(); }
")
2599 git
-fetch
-with
-cli
= true
2603 p.cargo("build
").run();
2604 p.rename_run("foo
", "foo1
").with_stdout("one
").run();
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"); }
"#);
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());
2619 Some(&t!(repo.find_tree(tree_id)))
2621 // Perform the fetch.
2622 p.cargo("update
").run();
2623 p.cargo("build
").run();
2624 p.rename_run("foo
", "foo2
").with_stdout("two
").run();
2628 fn git_fetch_cli_env_clean() {
2629 if disable_git_cli() {
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| {
2636 .file("Cargo
.toml
", &basic_manifest("dep1
", "0.5.0"))
2637 .file("src
/lib
.rs
", "")
2640 let git_proj = git::new("foo
", |project| {
2650 dep1
= {{ git = '{}'
}}
2655 .file("src
/lib
.rs
", "pub extern crate dep1
;")
2660 git
-fetch
-with
-cli
= true
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.
2670 .env("GIT_DIR
", git_proj.root().join(".git
"))
2675 fn dirty_submodule() {
2676 // `cargo package` warns for dirty file in submodule.
2677 let (git_project, repo) = git::new_repo("foo
", |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
")
2683 let git_project2 = git::new("src
", |project| {
2684 project.no_manifest().file("lib
.rs
", "pub fn f() {}
")
2687 let url = path2url(git_project2.root()).to_string();
2688 git::add_submodule(&repo, &url, Path::new("src
"));
2690 // Submodule added, but not committed.
2692 .cargo("package
--no
-verify
")
2696 [WARNING
] manifest has no
[..]
2698 [ERROR
] 1 files
in the working directory contain changes that were not yet committed into git
:
2702 to proceed despite
[..]
2708 git_project.cargo("package
--no
-verify
").run();
2710 // Modify file, check for warning.
2711 git_project.change_file("src
/lib
.rs
", "");
2713 .cargo("package
--no
-verify
")
2717 [WARNING
] manifest has no
[..]
2719 [ERROR
] 1 files
in the working directory contain changes that were not yet committed into git
:
2723 to proceed despite
[..]
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);
2733 git_project.cargo("package
--no
-verify
").run();
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
"));
2740 .cargo("package
--no
-verify
")
2744 [WARNING
] manifest has no
[..]
2746 [ERROR
] 1 files
in the working directory contain changes that were not yet committed into git
:
2750 to proceed despite
[..]
2755 // Commit the submodule addition.
2756 git::commit(&sub_repo);
2759 git_project.cargo("package
--no
-verify
").run();
2760 // Modify within nested submodule.
2761 git_project.change_file("src
/bar
/mod.rs
", "//test");
2763 .cargo("package --no-verify")
2767 [WARNING] manifest has no [..]
2769 [ERROR] 1 files in the working directory contain changes that were not yet committed into git:
2773 to proceed despite [..]
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
);
2785 git_project
.cargo("package --no-verify").run();
2789 fn default_not_master() {
2790 let project
= project();
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"))
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() {}");
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();
2806 let project
= project
2816 dep1 = {{ git = '{}' }}
2821 .file("src/lib.rs", "pub fn foo() { dep1::foo() }")
2828 [UPDATING] git repository `[..]`
2829 [COMPILING] dep1 v0.5.0 ([..])
2830 [COMPILING] foo v0.5.0 ([..])
2831 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",