1 //! Tests for git support.
5 use std
::io
::prelude
::*;
6 use std
::net
::{TcpListener, TcpStream}
;
9 use std
::sync
::atomic
::{AtomicBool, Ordering}
;
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}
;
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())
25 fn cargo_compile_simple_git_dep() {
26 let project
= project();
27 let git_project
= git
::new("dep1", |project
| {
29 .file("Cargo.toml", &basic_lib_manifest("dep1"))
33 pub fn hello() -> &'static str {
49 authors = ["wycats@example.com"]
60 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
64 let git_root
= git_project
.root();
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",
78 assert
!(project
.bin("foo").is_file());
81 .process(&project
.bin("foo"))
82 .with_stdout("hello world\n")
87 fn cargo_compile_git_dep_branch() {
88 let project
= project();
89 let git_project
= git
::new("dep1", |project
| {
91 .file("Cargo.toml", &basic_lib_manifest("dep1"))
95 pub fn hello() -> &'static str {
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();
108 let project
= project
117 authors = ["wycats@example.com"]
130 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
134 let git_root
= git_project
.root();
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",
148 assert
!(project
.bin("foo").is_file());
151 .process(&project
.bin("foo"))
152 .with_stdout("hello world\n")
157 fn cargo_compile_git_dep_tag() {
158 let project
= project();
159 let git_project
= git
::new("dep1", |project
| {
161 .file("Cargo.toml", &basic_lib_manifest("dep1"))
165 pub fn hello() -> &'static str {
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();
177 &repo
.find_object(head
, None
).unwrap(),
178 &repo
.signature().unwrap(),
184 let project
= project
193 authors = ["wycats@example.com"]
205 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
209 let git_root
= git_project
.root();
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",
223 assert
!(project
.bin("foo").is_file());
226 .process(&project
.bin("foo"))
227 .with_stdout("hello world\n")
230 project
.cargo("build").run();
234 fn cargo_compile_with_nested_paths() {
235 let git_project
= git
::new("dep1", |project
| {
244 authors = ["carlhuda@example.com"]
261 pub fn hello() -> &'static str {
266 .file("vendor/dep2/Cargo.toml", &basic_lib_manifest("dep2"))
268 "vendor/dep2/src/dep2.rs",
270 pub fn hello() -> &'static str {
286 authors = ["wycats@example.com"]
302 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
306 p
.cargo("build").run();
308 assert
!(p
.bin("foo").is_file());
310 p
.process(&p
.bin("foo")).with_stdout("hello world\n").run();
314 fn cargo_compile_with_malformed_nested_paths() {
315 let git_project
= git
::new("dep1", |project
| {
317 .file("Cargo.toml", &basic_lib_manifest("dep1"))
321 pub fn hello() -> &'static str {
326 .file("vendor/dep2/Cargo.toml", "!INVALID!")
328 "vendor/dep3/Cargo.toml",
334 subdep1 = { path = "../require-extra-build-step" }
337 .file("vendor/dep3/src/lib.rs", "")
349 authors = ["wycats@example.com"]
365 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
369 p
.cargo("build").run();
371 assert
!(p
.bin("foo").is_file());
373 p
.process(&p
.bin("foo")).with_stdout("hello world\n").run();
377 fn cargo_compile_with_meta_package() {
378 let git_project
= git
::new("meta-dep", |project
| {
380 .file("dep1/Cargo.toml", &basic_lib_manifest("dep1"))
384 pub fn hello() -> &'static str {
389 .file("dep2/Cargo.toml", &basic_lib_manifest("dep2"))
393 pub fn hello() -> &'static str {
409 authors = ["wycats@example.com"]
432 r
#""{} {}", dep1::hello(), dep2::hello()"#,
438 p
.cargo("build").run();
440 assert
!(p
.bin("foo").is_file());
442 p
.process(&p
.bin("foo"))
443 .with_stdout("this is dep1 this is dep2\n")
448 fn cargo_compile_with_short_ssh_git() {
449 let url
= "git@github.com:a/dep";
460 authors = ["wycats@example.com"]
475 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
482 .with_stderr(&format
!(
484 [ERROR] failed to parse manifest at `[..]`
487 invalid url `{}`: relative URL without a base
495 fn two_revs_same_deps() {
496 let bar
= git
::new("meta-dep", |project
| {
498 .file("Cargo.toml", &basic_manifest("bar", "0.0.0"))
499 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
502 let repo
= git2
::Repository
::open(&bar
.root()).unwrap();
503 let rev1
= repo
.revparse_single("HEAD").unwrap().id();
505 // Commit the changes and make sure we trigger a recompile
506 bar
.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
508 let rev2
= git
::commit(&repo
);
538 assert_eq!(bar::bar(), 1);
539 assert_eq!(baz::baz(), 2);
568 pub fn baz() -> i32 { bar::bar() }
573 foo
.cargo("build -v").run();
574 assert
!(foo
.bin("foo").is_file());
575 foo
.process(&foo
.bin("foo")).run();
580 let git_project
= git
::new("bar", |project
| {
582 .file("Cargo.toml", &basic_lib_manifest("bar"))
583 .file("src/bar.rs", "pub fn bar() {}")
595 authors = ["wycats@example.com"]
605 .file("src/main.rs", &main_file(r
#""{:?}", bar::bar()"#, &["bar"]))
608 // First time around we should compile both foo and bar
610 .with_stderr(&format
!(
611 "[UPDATING] git repository `{}`\n\
612 [COMPILING] bar v0.5.0 ({}#[..])\n\
613 [COMPILING] foo v0.5.0 ([CWD])\n\
614 [FINISHED] dev [unoptimized + debuginfo] target(s) \
621 // Don't recompile the second time
622 p
.cargo("build").with_stdout("").run();
624 // Modify a file manually, shouldn't trigger a recompile
625 git_project
.change_file("src/bar.rs", r
#"pub fn bar() { println!("hello!"); }"#);
627 p
.cargo("build").with_stdout("").run();
630 .with_stderr(&format
!(
631 "[UPDATING] git repository `{}`",
636 p
.cargo("build").with_stdout("").run();
638 // Commit the changes and make sure we don't trigger a recompile because the
639 // lock file says not to change
640 let repo
= git2
::Repository
::open(&git_project
.root()).unwrap();
644 println
!("compile after commit");
645 p
.cargo("build").with_stdout("").run();
646 p
.root().move_into_the_past();
648 // Update the dependency and carry on!
650 .with_stderr(&format
!(
651 "[UPDATING] git repository `{}`\n\
652 [UPDATING] bar v0.5.0 ([..]) -> #[..]\n\
657 println
!("going for the last compile");
659 .with_stderr(&format
!(
660 "[COMPILING] bar v0.5.0 ({}#[..])\n\
661 [COMPILING] foo v0.5.0 ([CWD])\n\
662 [FINISHED] dev [unoptimized + debuginfo] target(s) \
668 // Make sure clean only cleans one dep
669 p
.cargo("clean -p foo").with_stdout("").run();
672 "[COMPILING] foo v0.5.0 ([CWD])\n\
673 [FINISHED] dev [unoptimized + debuginfo] target(s) \
680 fn update_with_shared_deps() {
681 let git_project
= git
::new("bar", |project
| {
683 .file("Cargo.toml", &basic_lib_manifest("bar"))
684 .file("src/bar.rs", "pub fn bar() {}")
694 authors = ["wycats@example.com"]
705 #[allow(unused_extern_crates)]
707 #[allow(unused_extern_crates)]
719 authors = ["wycats@example.com"]
728 .file("dep1/src/lib.rs", "")
736 authors = ["wycats@example.com"]
745 .file("dep2/src/lib.rs", "")
748 // First time around we should compile both foo and bar
750 .with_stderr(&format
!(
752 [UPDATING] git repository `{git}`
753 [COMPILING] bar v0.5.0 ({git}#[..])
754 [COMPILING] [..] v0.5.0 ([..])
755 [COMPILING] [..] v0.5.0 ([..])
756 [COMPILING] foo v0.5.0 ([CWD])
757 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
758 git
= git_project
.url(),
762 // Modify a file manually, and commit it
763 git_project
.change_file("src/bar.rs", r
#"pub fn bar() { println!("hello!"); }"#);
764 let repo
= git2
::Repository
::open(&git_project
.root()).unwrap();
765 let old_head
= repo
.head().unwrap().target().unwrap();
771 // By default, not transitive updates
772 println
!("dep1 update");
773 p
.cargo("update -p dep1").with_stdout("").run();
775 // Don't do anything bad on a weird --precise argument
776 println
!("bar bad precise update");
777 p
.cargo("update -p bar --precise 0.1.2")
781 [ERROR] Unable to update [..]
784 precise value for git is not a git revision: 0.1.2
787 unable to parse OID - contains invalid characters; class=Invalid (3)
792 // Specifying a precise rev to the old rev shouldn't actually update
793 // anything because we already have the rev in the db.
794 println
!("bar precise update");
795 p
.cargo("update -p bar --precise")
796 .arg(&old_head
.to_string())
800 // Updating aggressively should, however, update the repo.
801 println
!("dep1 aggressive update");
802 p
.cargo("update -p dep1 --aggressive")
803 .with_stderr(&format
!(
804 "[UPDATING] git repository `{}`\n\
805 [UPDATING] bar v0.5.0 ([..]) -> #[..]\n\
811 // Make sure we still only compile one version of the git repo
814 .with_stderr(&format
!(
816 [COMPILING] bar v0.5.0 ({git}#[..])
817 [COMPILING] [..] v0.5.0 ([CWD][..]dep[..])
818 [COMPILING] [..] v0.5.0 ([CWD][..]dep[..])
819 [COMPILING] foo v0.5.0 ([CWD])
820 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
821 git
= git_project
.url(),
825 // We should be able to update transitive deps
826 p
.cargo("update -p bar")
827 .with_stderr(&format
!(
828 "[UPDATING] git repository `{}`",
835 fn dep_with_submodule() {
836 let project
= project();
837 let git_project
= git
::new("dep1", |project
| {
838 project
.file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
840 let git_project2
= git
::new("dep2", |project
| project
.file("lib.rs", "pub fn dep() {}"));
842 let repo
= git2
::Repository
::open(&git_project
.root()).unwrap();
843 let url
= path2url(git_project2
.root()).to_string();
844 git
::add_submodule(&repo
, &url
, Path
::new("src"));
847 let project
= project
856 authors = ["wycats@example.com"]
867 "extern crate dep1; pub fn foo() { dep1::dep() }",
875 [UPDATING] git repository [..]
876 [UPDATING] git submodule `file://[..]/dep2`
877 [COMPILING] dep1 [..]
879 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
885 fn dep_with_bad_submodule() {
886 let project
= project();
887 let git_project
= git
::new("dep1", |project
| {
888 project
.file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
890 let git_project2
= git
::new("dep2", |project
| project
.file("lib.rs", "pub fn dep() {}"));
892 let repo
= git2
::Repository
::open(&git_project
.root()).unwrap();
893 let url
= path2url(git_project2
.root()).to_string();
894 git
::add_submodule(&repo
, &url
, Path
::new("src"));
897 // now amend the first commit on git_project2 to make submodule ref point to not-found
899 let repo
= git2
::Repository
::open(&git_project2
.root()).unwrap();
900 let original_submodule_ref
= repo
.refname_to_id("refs/heads/master").unwrap();
901 let commit
= repo
.find_commit(original_submodule_ref
).unwrap();
904 Some("refs/heads/master"),
908 Some("something something"),
922 authors = ["wycats@example.com"]
933 "extern crate dep1; pub fn foo() { dep1::dep() }",
937 let expected
= format
!(
939 [UPDATING] git repository [..]
940 [UPDATING] git submodule `file://[..]/dep2`
941 [ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 [..]`
944 failed to load source for dependency `dep1`
950 failed to update submodule `src`
953 object not found - no match for id [..]
955 path2url(git_project
.root())
959 .with_stderr(expected
)
965 fn two_deps_only_update_one() {
966 let project
= project();
967 let git1
= git
::new("dep1", |project
| {
969 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
970 .file("src/lib.rs", "")
972 let git2
= git
::new("dep2", |project
| {
974 .file("Cargo.toml", &basic_manifest("dep2", "0.5.0"))
975 .file("src/lib.rs", "")
987 authors = ["wycats@example.com"]
998 .file("src/main.rs", "fn main() {}")
1001 fn oid_to_short_sha(oid
: git2
::Oid
) -> String
{
1002 oid
.to_string()[..8].to_string()
1004 fn git_repo_head_sha(p
: &Project
) -> String
{
1005 let repo
= git2
::Repository
::open(p
.root()).unwrap();
1006 let head
= repo
.head().unwrap().target().unwrap();
1007 oid_to_short_sha(head
)
1010 println
!("dep1 head sha: {}", git_repo_head_sha(&git1
));
1011 println
!("dep2 head sha: {}", git_repo_head_sha(&git2
));
1015 "[UPDATING] git repository `[..]`\n\
1016 [UPDATING] git repository `[..]`\n\
1017 [COMPILING] [..] v0.5.0 ([..])\n\
1018 [COMPILING] [..] v0.5.0 ([..])\n\
1019 [COMPILING] foo v0.5.0 ([CWD])\n\
1020 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
1024 git1
.change_file("src/lib.rs", "pub fn foo() {}");
1025 let repo
= git2
::Repository
::open(&git1
.root()).unwrap();
1027 let oid
= git
::commit(&repo
);
1028 println
!("dep1 head sha: {}", oid_to_short_sha(oid
));
1030 p
.cargo("update -p dep1")
1031 .with_stderr(&format
!(
1032 "[UPDATING] git repository `{}`\n\
1033 [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
1041 fn stale_cached_version() {
1042 let bar
= git
::new("meta-dep", |project
| {
1044 .file("Cargo.toml", &basic_manifest("bar", "0.0.0"))
1045 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1048 // Update the git database in the cache with the current state of the git
1071 fn main() { assert_eq!(bar::bar(), 1) }
1076 foo
.cargo("build").run();
1077 foo
.process(&foo
.bin("foo")).run();
1079 // Update the repo, and simulate someone else updating the lock file and then
1080 // us pulling it down.
1081 bar
.change_file("src/lib.rs", "pub fn bar() -> i32 { 1 + 0 }");
1082 let repo
= git2
::Repository
::open(&bar
.root()).unwrap();
1088 let rev
= repo
.revparse_single("HEAD").unwrap().id();
1098 'bar 0.0.0 (git+{url}#{hash})'
1104 source = 'git+{url}#{hash}'
1113 .with_stderr(&format
!(
1115 [UPDATING] git repository `{bar}`
1116 [COMPILING] bar v0.0.0 ({bar}#[..])
1117 [COMPILING] foo v0.0.0 ([CWD])
1118 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1123 foo
.process(&foo
.bin("foo")).run();
1127 fn dep_with_changed_submodule() {
1128 let project
= project();
1129 let git_project
= git
::new("dep1", |project
| {
1130 project
.file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
1133 let git_project2
= git
::new("dep2", |project
| {
1134 project
.file("lib.rs", "pub fn dep() -> &'static str { \"project2\" }")
1137 let git_project3
= git
::new("dep3", |project
| {
1138 project
.file("lib.rs", "pub fn dep() -> &'static str { \"project3\" }")
1141 let repo
= git2
::Repository
::open(&git_project
.root()).unwrap();
1142 let mut sub
= git
::add_submodule(&repo
, &git_project2
.url().to_string(), Path
::new("src"));
1153 authors = ["wycats@example.com"]
1164 pub fn main() { println!(\"{}\", dep1::dep()) }
1169 println
!("first run");
1172 "[UPDATING] git repository `[..]`\n\
1173 [UPDATING] git submodule `file://[..]/dep2`\n\
1174 [COMPILING] dep1 v0.5.0 ([..])\n\
1175 [COMPILING] foo v0.5.0 ([..])\n\
1176 [FINISHED] dev [unoptimized + debuginfo] target(s) in \
1178 [RUNNING] `target/debug/foo[EXE]`\n",
1180 .with_stdout("project2\n")
1183 git_project
.change_file(
1186 "[submodule \"src\"]\n\tpath = src\n\turl={}",
1191 // Sync the submodule and reset it to the new remote.
1192 sub
.sync().unwrap();
1194 let subrepo
= sub
.open().unwrap();
1196 .remote_add_fetch("origin", "refs/heads/*:refs/heads/*")
1199 .remote_set_url("origin", &git_project3
.url().to_string())
1201 let mut origin
= subrepo
.find_remote("origin").unwrap();
1202 origin
.fetch(&Vec
::<String
>::new(), None
, None
).unwrap();
1203 let id
= subrepo
.refname_to_id("refs/remotes/origin/master").unwrap();
1204 let obj
= subrepo
.find_object(id
, None
).unwrap();
1205 subrepo
.reset(&obj
, git2
::ResetType
::Hard
, None
).unwrap();
1207 sub
.add_to_index(true).unwrap();
1212 // Update the dependency and carry on!
1214 p
.cargo("update -v")
1216 .with_stderr(&format
!(
1217 "[UPDATING] git repository `{}`\n\
1218 [UPDATING] git submodule `file://[..]/dep3`\n\
1219 [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
1225 println
!("last run");
1228 "[COMPILING] dep1 v0.5.0 ([..])\n\
1229 [COMPILING] foo v0.5.0 ([..])\n\
1230 [FINISHED] dev [unoptimized + debuginfo] target(s) in \
1232 [RUNNING] `target/debug/foo[EXE]`\n",
1234 .with_stdout("project3\n")
1239 fn dev_deps_with_testing() {
1240 let p2
= git
::new("bar", |project
| {
1242 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1246 pub fn gimme() -> &'static str { "zoidberg" }
1260 authors = ["wycats@example.com"]
1262 [dev-dependencies.bar]
1277 #[test] fn foo() { bar::gimme(); }
1283 // Generate a lock file which did not use `bar` to compile, but had to update
1284 // `bar` to generate the lock file
1286 .with_stderr(&format
!(
1288 [UPDATING] git repository `{bar}`
1289 [COMPILING] foo v0.5.0 ([CWD])
1290 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1296 // Make sure we use the previous resolution of `bar` instead of updating it
1301 [COMPILING] [..] v0.5.0 ([..])
1302 [COMPILING] [..] v0.5.0 ([..]
1303 [FINISHED] test [unoptimized + debuginfo] target(s) in [..]
1304 [RUNNING] target/debug/deps/foo-[..][EXE]",
1306 .with_stdout_contains("test tests::foo ... ok")
1311 fn git_build_cmd_freshness() {
1312 let foo
= git
::new("foo", |project
| {
1324 .file("build.rs", "fn main() {}")
1325 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1326 .file(".gitignore", "src/bar.rs")
1328 foo
.root().move_into_the_past();
1335 [COMPILING] foo v0.0.0 ([CWD])
1336 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1341 // Smoke test to make sure it doesn't compile again
1342 println
!("first pass");
1343 foo
.cargo("build").with_stdout("").run();
1345 // Modify an ignored file and make sure we don't rebuild
1346 println
!("second pass");
1347 foo
.change_file("src/bar.rs", "");
1348 foo
.cargo("build").with_stdout("").run();
1352 fn git_name_not_always_needed() {
1353 let p2
= git
::new("bar", |project
| {
1355 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1359 pub fn gimme() -> &'static str { "zoidberg" }
1364 let repo
= git2
::Repository
::open(&p2
.root()).unwrap();
1365 let mut cfg
= repo
.config().unwrap();
1366 let _
= cfg
.remove("user.name");
1367 let _
= cfg
.remove("user.email");
1379 [dev-dependencies.bar]
1385 .file("src/main.rs", "fn main() {}")
1388 // Generate a lock file which did not use `bar` to compile, but had to update
1389 // `bar` to generate the lock file
1391 .with_stderr(&format
!(
1393 [UPDATING] git repository `{bar}`
1394 [COMPILING] foo v0.5.0 ([CWD])
1395 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1403 fn git_repo_changing_no_rebuild() {
1404 let bar
= git
::new("bar", |project
| {
1406 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1407 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1410 // Lock p1 to the first rev in the git repo
1428 .file("src/main.rs", "fn main() {}")
1429 .file("build.rs", "fn main() {}")
1431 p1
.root().move_into_the_past();
1433 .with_stderr(&format
!(
1435 [UPDATING] git repository `{bar}`
1438 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1444 // Make a commit to lock p2 to a different rev
1445 bar
.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
1446 let repo
= git2
::Repository
::open(&bar
.root()).unwrap();
1450 // Lock p2 to the second rev
1467 .file("src/main.rs", "fn main() {}")
1470 .with_stderr(&format
!(
1472 [UPDATING] git repository `{bar}`
1475 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1481 // And now for the real test! Make sure that p1 doesn't get rebuilt
1482 // even though the git repo has changed.
1483 p1
.cargo("build").with_stdout("").run();
1487 fn git_dep_build_cmd() {
1488 let p
= git
::new("foo", |project
| {
1497 authors = ["wycats@example.com"]
1509 .file("src/foo.rs", &main_file(r
#""{}", bar::gimme()"#, &["bar"]))
1517 authors = ["wycats@example.com"]
1526 "bar/src/bar.rs.in",
1528 pub fn gimme() -> i32 { 0 }
1536 fs::copy("src/bar.rs.in", "src/bar.rs").unwrap();
1542 p
.root().join("bar").move_into_the_past();
1544 p
.cargo("build").run();
1546 p
.process(&p
.bin("foo")).with_stdout("0\n").run();
1548 // Touching bar.rs.in should cause the `build` command to run again.
1549 p
.change_file("bar/src/bar.rs.in", "pub fn gimme() -> i32 { 1 }");
1551 p
.cargo("build").run();
1553 p
.process(&p
.bin("foo")).with_stdout("1\n").run();
1557 fn fetch_downloads() {
1558 let bar
= git
::new("bar", |project
| {
1560 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1561 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1579 .file("src/main.rs", "fn main() {}")
1582 .with_stderr(&format
!(
1583 "[UPDATING] git repository `{url}`",
1588 p
.cargo("fetch").with_stdout("").run();
1592 fn warnings_in_git_dep() {
1593 let bar
= git
::new("bar", |project
| {
1595 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1596 .file("src/lib.rs", "fn unused() {}")
1614 .file("src/main.rs", "fn main() {}")
1618 .with_stderr(&format
!(
1619 "[UPDATING] git repository `{}`\n\
1620 [COMPILING] bar v0.5.0 ({}#[..])\n\
1621 [COMPILING] foo v0.5.0 ([CWD])\n\
1622 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
1630 fn update_ambiguous() {
1631 let bar1
= git
::new("bar1", |project
| {
1633 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1634 .file("src/lib.rs", "")
1636 let bar2
= git
::new("bar2", |project
| {
1638 .file("Cargo.toml", &basic_manifest("bar", "0.6.0"))
1639 .file("src/lib.rs", "")
1641 let baz
= git
::new("baz", |project
| {
1650 authors = ["wycats@example.com"]
1658 .file("src/lib.rs", "")
1679 .file("src/main.rs", "fn main() {}")
1682 p
.cargo("generate-lockfile").run();
1683 p
.cargo("update -p bar")
1687 [ERROR] There are multiple `bar` packages in your project, and the specification `bar` \
1689 Please re-run this command with `-p <spec>` where `<spec>` is one of the \
1699 fn update_one_dep_in_repo_with_many_deps() {
1700 let bar
= git
::new("bar", |project
| {
1702 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1703 .file("src/lib.rs", "")
1704 .file("a/Cargo.toml", &basic_manifest("a", "0.5.0"))
1705 .file("a/src/lib.rs", "")
1726 .file("src/main.rs", "fn main() {}")
1729 p
.cargo("generate-lockfile").run();
1730 p
.cargo("update -p bar")
1731 .with_stderr(&format
!("[UPDATING] git repository `{}`", bar
.url()))
1736 fn switch_deps_does_not_update_transitive() {
1737 let transitive
= git
::new("transitive", |project
| {
1739 .file("Cargo.toml", &basic_manifest("transitive", "0.5.0"))
1740 .file("src/lib.rs", "")
1742 let dep1
= git
::new("dep1", |project
| {
1751 authors = ["wycats@example.com"]
1753 [dependencies.transitive]
1759 .file("src/lib.rs", "")
1761 let dep2
= git
::new("dep2", |project
| {
1770 authors = ["wycats@example.com"]
1772 [dependencies.transitive]
1778 .file("src/lib.rs", "")
1796 .file("src/main.rs", "fn main() {}")
1800 .with_stderr(&format
!(
1802 [UPDATING] git repository `{}`
1803 [UPDATING] git repository `{}`
1804 [COMPILING] transitive [..]
1805 [COMPILING] dep [..]
1806 [COMPILING] foo [..]
1807 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1814 // Update the dependency to point to the second repository, but this
1815 // shouldn't update the transitive dependency which is the same.
1832 .with_stderr(&format
!(
1834 [UPDATING] git repository `{}`
1835 [COMPILING] dep [..]
1836 [COMPILING] foo [..]
1837 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1845 fn update_one_source_updates_all_packages_in_that_git_source() {
1846 let dep
= git
::new("dep", |project
| {
1860 .file("src/lib.rs", "")
1861 .file("a/Cargo.toml", &basic_manifest("a", "0.5.0"))
1862 .file("a/src/lib.rs", "")
1880 .file("src/main.rs", "fn main() {}")
1883 p
.cargo("build").run();
1885 let repo
= git2
::Repository
::open(&dep
.root()).unwrap();
1886 let rev1
= repo
.revparse_single("HEAD").unwrap().id();
1888 // Just be sure to change a file
1889 dep
.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
1893 p
.cargo("update -p dep").run();
1894 let lockfile
= p
.read_lockfile();
1896 !lockfile
.contains(&rev1
.to_string()),
1904 fn switch_sources() {
1905 let a1
= git
::new("a1", |project
| {
1907 .file("Cargo.toml", &basic_manifest("a", "0.5.0"))
1908 .file("src/lib.rs", "")
1910 let a2
= git
::new("a2", |project
| {
1912 .file("Cargo.toml", &basic_manifest("a", "0.5.1"))
1913 .file("src/lib.rs", "")
1928 .file("src/main.rs", "fn main() {}")
1943 .file("b/src/lib.rs", "pub fn main() {}")
1949 [UPDATING] git repository `file://[..]a1`
1950 [COMPILING] a v0.5.0 ([..]a1#[..]
1951 [COMPILING] b v0.5.0 ([..])
1952 [COMPILING] foo v0.5.0 ([..])
1953 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1976 [UPDATING] git repository `file://[..]a2`
1977 [COMPILING] a v0.5.1 ([..]a2#[..]
1978 [COMPILING] b v0.5.0 ([..])
1979 [COMPILING] foo v0.5.0 ([..])
1980 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1987 fn dont_require_submodules_are_checked_out() {
1988 let p
= project().build();
1989 let git1
= git
::new("dep1", |p
| {
2000 .file("build.rs", "fn main() {}")
2001 .file("src/lib.rs", "")
2004 let git2
= git
::new("dep2", |p
| p
);
2006 let repo
= git2
::Repository
::open(&git1
.root()).unwrap();
2007 let url
= path2url(git2
.root()).to_string();
2008 git
::add_submodule(&repo
, &url
, Path
::new("a/submodule"));
2011 git2
::Repository
::init(&p
.root()).unwrap();
2012 let url
= path2url(git1
.root()).to_string();
2013 let dst
= paths
::home().join("foo");
2014 git2
::Repository
::clone(&url
, &dst
).unwrap();
2016 git1
.cargo("build -v").cwd(&dst
).run();
2020 fn doctest_same_name() {
2021 let a2
= git
::new("a2", |p
| {
2022 p
.file("Cargo.toml", &basic_manifest("a", "0.5.0"))
2023 .file("src/lib.rs", "pub fn a2() {}")
2026 let a1
= git
::new("a1", |p
| {
2036 a = {{ git = '{}' }}
2041 .file("src/lib.rs", "extern crate a; pub fn a1() {}")
2055 a = {{ git = '{}' }}
2069 p
.cargo("test -v").run();
2073 fn lints_are_suppressed() {
2074 let a
= git
::new("a", |p
| {
2075 p
.file("Cargo.toml", &basic_manifest("a", "0.5.0")).file(
2094 a = {{ git = '{}' }}
2099 .file("src/lib.rs", "")
2105 [UPDATING] git repository `[..]`
2106 [COMPILING] a v0.5.0 ([..])
2107 [COMPILING] foo v0.0.1 ([..])
2108 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2115 fn denied_lints_are_allowed() {
2116 let a
= git
::new("a", |p
| {
2117 p
.file("Cargo.toml", &basic_manifest("a", "0.5.0")).file(
2137 a = {{ git = '{}' }}
2142 .file("src/lib.rs", "")
2148 [UPDATING] git repository `[..]`
2149 [COMPILING] a v0.5.0 ([..])
2150 [COMPILING] foo v0.0.1 ([..])
2151 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2158 fn add_a_git_dep() {
2159 let git
= git
::new("git", |p
| {
2160 p
.file("Cargo.toml", &basic_manifest("git", "0.5.0"))
2161 .file("src/lib.rs", "")
2175 a = {{ path = 'a' }}
2176 git = {{ git = '{}' }}
2181 .file("src/lib.rs", "")
2182 .file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
2183 .file("a/src/lib.rs", "")
2186 p
.cargo("build").run();
2198 git = {{ git = '{}' }}
2204 p
.cargo("build").run();
2208 fn two_at_rev_instead_of_tag() {
2209 let git
= git
::new("git", |p
| {
2210 p
.file("Cargo.toml", &basic_manifest("git1", "0.5.0"))
2211 .file("src/lib.rs", "")
2212 .file("a/Cargo.toml", &basic_manifest("git2", "0.5.0"))
2213 .file("a/src/lib.rs", "")
2216 // Make a tag corresponding to the current HEAD
2217 let repo
= git2
::Repository
::open(&git
.root()).unwrap();
2218 let head
= repo
.head().unwrap().target().unwrap();
2221 &repo
.find_object(head
, None
).unwrap(),
2222 &repo
.signature().unwrap(),
2239 git1 = {{ git = '{0}', rev = 'v0.1.0' }}
2240 git2 = {{ git = '{0}', rev = 'v0.1.0' }}
2245 .file("src/lib.rs", "")
2248 p
.cargo("generate-lockfile").run();
2249 p
.cargo("build -v").run();
2253 fn include_overrides_gitignore() {
2254 // Make sure that `package.include` takes precedence over .gitignore.
2255 let p
= git
::new("foo", |repo
| {
2262 include = ["src/lib.rs", "ignored.txt", "Cargo.toml"]
2273 .file("src/lib.rs", "")
2274 .file("ignored.txt", "")
2275 .file("build.rs", "fn main() {}")
2278 p
.cargo("build").run();
2279 p
.change_file("ignored.txt", "Trigger rebuild.");
2283 [COMPILING] foo v0.5.0 ([..])
2284 [RUNNING] `[..]build-script-build[..]`
2285 [RUNNING] `rustc --crate-name foo src/lib.rs [..]`
2286 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2290 p
.cargo("package --list --allow-dirty")
2303 fn invalid_git_dependency_manifest() {
2304 let project
= project();
2305 let git_project
= git
::new("dep1", |project
| {
2314 authors = ["carlhuda@example.com"]
2315 categories = ["algorithms"]
2316 categories = ["algorithms"]
2326 pub fn hello() -> &'static str {
2333 let project
= project
2342 authors = ["wycats@example.com"]
2353 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
2357 let git_root
= git_project
.root();
2362 .with_stderr(&format
!(
2364 [UPDATING] git repository `{}`
2365 [ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([..])`
2368 failed to load source for dependency `dep1`
2374 failed to parse manifest at `[..]`
2377 could not parse input as TOML
2380 duplicate key: `categories` for key `project` at line 10 column 21",
2381 path2url(&git_root
),
2382 path2url(&git_root
),
2388 fn failed_submodule_checkout() {
2389 let project
= project();
2390 let git_project
= git
::new("dep1", |project
| {
2391 project
.file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
2394 let git_project2
= git
::new("dep2", |project
| project
.file("lib.rs", ""));
2396 let listener
= TcpListener
::bind("127.0.0.1:0").unwrap();
2397 let addr
= listener
.local_addr().unwrap();
2398 let done
= Arc
::new(AtomicBool
::new(false));
2399 let done2
= done
.clone();
2401 let t
= thread
::spawn(move || {
2402 while !done2
.load(Ordering
::SeqCst
) {
2403 if let Ok((mut socket
, _
)) = listener
.accept() {
2404 drop(socket
.write_all(b
"foo\r\n"));
2409 let repo
= git2
::Repository
::open(&git_project2
.root()).unwrap();
2410 let url
= format
!("https://{}:{}/", addr
.ip(), addr
.port());
2412 let mut s
= repo
.submodule(&url
, Path
::new("bar"), false).unwrap();
2413 let subrepo
= s
.open().unwrap();
2414 let mut cfg
= subrepo
.config().unwrap();
2415 cfg
.set_str("user.email", "foo@bar.com").unwrap();
2416 cfg
.set_str("user.name", "Foo Bar").unwrap();
2417 git
::commit(&subrepo
);
2418 s
.add_finalize().unwrap();
2423 let repo
= git2
::Repository
::open(&git_project
.root()).unwrap();
2424 let url
= path2url(git_project2
.root()).to_string();
2425 git
::add_submodule(&repo
, &url
, Path
::new("src"));
2429 let project
= project
2440 dep1 = {{ git = '{}' }}
2445 .file("src/lib.rs", "")
2451 .with_stderr_contains(" failed to update submodule `src`")
2452 .with_stderr_contains(" failed to update submodule `bar`")
2457 .with_stderr_contains(" failed to update submodule `src`")
2458 .with_stderr_contains(" failed to update submodule `bar`")
2461 done
.store(true, Ordering
::SeqCst
);
2462 drop(TcpStream
::connect(&addr
));
2468 if disable_git_cli() {
2471 let project
= project();
2472 let git_project
= git
::new("dep1", |project
| {
2474 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
2475 .file("src/lib.rs", "")
2478 let project
= project
2489 dep1 = {{ git = '{}' }}
2494 .file("src/lib.rs", "")
2499 git-fetch-with-cli = true
2505 [UPDATING] git repository `[..]`
2506 [RUNNING] `git fetch [..]`
2507 [COMPILING] dep1 [..]
2508 [RUNNING] `rustc [..]`
2509 [COMPILING] foo [..]
2510 [RUNNING] `rustc [..]`
2514 project
.cargo("build -v").with_stderr(stderr
).run();
2518 fn templatedir_doesnt_cause_problems() {
2519 let git_project2
= git
::new("dep2", |project
| {
2521 .file("Cargo.toml", &basic_manifest("dep2", "0.5.0"))
2522 .file("src/lib.rs", "")
2524 let git_project
= git
::new("dep1", |project
| {
2526 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
2527 .file("src/lib.rs", "")
2540 dep1 = {{ git = '{}' }}
2545 .file("src/main.rs", "fn main() {}")
2549 paths
::home().join(".gitconfig"),
2566 p
.cargo("build").run();
2570 fn git_with_cli_force() {
2571 if disable_git_cli() {
2574 // Supports a force-pushed repo.
2575 let git_project
= git
::new("dep1", |project
| {
2577 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2578 .file("src/lib.rs", r
#"pub fn f() { println!("one"); }"#)
2591 dep1 = {{ git = "{}" }}
2596 .file("src
/main
.rs
", "fn main() { dep1::f(); }
")
2601 git
-fetch
-with
-cli
= true
2605 p.cargo("build
").run();
2606 p.rename_run("foo
", "foo1
").with_stdout("one
").run();
2608 // commit --amend a change that will require a force fetch.
2609 let repo = git2::Repository::open(&git_project.root()).unwrap();
2610 git_project.change_file("src
/lib
.rs
", r#"pub fn f() { println!("two"); }
"#);
2612 let id = repo.refname_to_id("HEAD
").unwrap();
2613 let commit = repo.find_commit(id).unwrap();
2614 let tree_id = t!(t!(repo.index()).write_tree());
2621 Some(&t!(repo.find_tree(tree_id)))
2623 // Perform the fetch.
2624 p.cargo("update
").run();
2625 p.cargo("build
").run();
2626 p.rename_run("foo
", "foo2
").with_stdout("two
").run();
2630 fn git_fetch_cli_env_clean() {
2631 if disable_git_cli() {
2634 // This tests that git-fetch-with-cli works when GIT_DIR environment
2635 // variable is set (for whatever reason).
2636 let git_dep = git::new("dep1
", |project| {
2638 .file("Cargo
.toml
", &basic_manifest("dep1
", "0.5.0"))
2639 .file("src
/lib
.rs
", "")
2642 let git_proj = git::new("foo
", |project| {
2652 dep1
= {{ git = '{}'
}}
2657 .file("src
/lib
.rs
", "pub extern crate dep1
;")
2662 git
-fetch
-with
-cli
= true
2667 // The directory set here isn't too important. Pointing to our own git
2668 // directory causes git to be confused and fail. Can also point to an
2669 // empty directory, or a nonexistent one.
2672 .env("GIT_DIR
", git_proj.root().join(".git
"))
2677 fn dirty_submodule() {
2678 // `cargo package` warns for dirty file in submodule.
2679 let (git_project, repo) = git::new_repo("foo
", |project| {
2681 .file("Cargo
.toml
", &basic_manifest("foo
", "0.5.0"))
2682 // This is necessary because `git::add` is too eager.
2683 .file(".gitignore
", "/target
")
2685 let git_project2 = git::new("src
", |project| {
2686 project.no_manifest().file("lib
.rs
", "pub fn f() {}
")
2689 let url = path2url(git_project2.root()).to_string();
2690 git::add_submodule(&repo, &url, Path::new("src
"));
2692 // Submodule added, but not committed.
2694 .cargo("package
--no
-verify
")
2698 [WARNING
] manifest has no
[..]
2700 [ERROR
] 1 files
in the working directory contain changes that were not yet committed into git
:
2704 to proceed despite
[..]
2710 git_project.cargo("package
--no
-verify
").run();
2712 // Modify file, check for warning.
2713 git_project.change_file("src
/lib
.rs
", "");
2715 .cargo("package
--no
-verify
")
2719 [WARNING
] manifest has no
[..]
2721 [ERROR
] 1 files
in the working directory contain changes that were not yet committed into git
:
2725 to proceed despite
[..]
2729 // Commit the change.
2730 let sub_repo = git2::Repository::open(git_project.root().join("src
")).unwrap();
2731 git::add(&sub_repo);
2732 git::commit(&sub_repo);
2735 git_project.cargo("package
--no
-verify
").run();
2737 // Try with a nested submodule.
2738 let git_project3 = git::new("bar
", |project| project.no_manifest().file("mod.rs
", ""));
2739 let url = path2url(git_project3.root()).to_string();
2740 git::add_submodule(&sub_repo, &url, Path::new("bar
"));
2742 .cargo("package
--no
-verify
")
2746 [WARNING
] manifest has no
[..]
2748 [ERROR
] 1 files
in the working directory contain changes that were not yet committed into git
:
2752 to proceed despite
[..]
2757 // Commit the submodule addition.
2758 git::commit(&sub_repo);
2761 git_project.cargo("package
--no
-verify
").run();
2762 // Modify within nested submodule.
2763 git_project.change_file("src
/bar
/mod.rs
", "//test");
2765 .cargo("package --no-verify")
2769 [WARNING] manifest has no [..]
2771 [ERROR] 1 files in the working directory contain changes that were not yet committed into git:
2775 to proceed despite [..]
2779 // And commit the change.
2780 let sub_sub_repo
= git2
::Repository
::open(git_project
.root().join("src/bar")).unwrap();
2781 git
::add(&sub_sub_repo
);
2782 git
::commit(&sub_sub_repo
);
2783 git
::add(&sub_repo
);
2784 git
::commit(&sub_repo
);
2787 git_project
.cargo("package --no-verify").run();
2791 fn default_not_master() {
2792 let project
= project();
2794 // Create a repository with a `master` branch, but switch the head to a
2795 // branch called `main` at the same time.
2796 let (git_project
, repo
) = git
::new_repo("dep1", |project
| {
2798 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2799 .file("src/lib.rs", "pub fn foo() {}")
2801 let head_id
= repo
.head().unwrap().target().unwrap();
2802 let head
= repo
.find_commit(head_id
).unwrap();
2803 repo
.branch("main", &head
, false).unwrap();
2804 repo
.set_head("refs/heads/main").unwrap();
2806 // Then create a commit on the new `main` branch so `master` and `main`
2808 git_project
.change_file("src/lib.rs", "");
2812 let project
= project
2822 dep1 = {{ git = '{}' }}
2827 .file("src/lib.rs", "pub fn foo() { dep1::foo() }")
2834 [UPDATING] git repository `[..]`
2835 warning: fetching `master` branch from `[..]` but the `HEAD` \
2836 reference for this repository is not the \
2837 `master` branch. This behavior will change \
2838 in Cargo in the future and your build may \
2839 break, so it's recommended to place \
2840 `branch = \"master\"` in Cargo.toml when \
2841 depending on this git repository to ensure \
2842 that your build will continue to work.
2843 [COMPILING] dep1 v0.5.0 ([..])
2844 [COMPILING] foo v0.5.0 ([..])
2845 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
2851 fn historical_lockfile_works() {
2852 let project
= project();
2854 let (git_project
, repo
) = git
::new_repo("dep1", |project
| {
2856 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2857 .file("src/lib.rs", "")
2859 let head_id
= repo
.head().unwrap().target().unwrap();
2861 let project
= project
2871 dep1 = {{ git = '{}', branch = 'master' }}
2876 .file("src/lib.rs", "")
2879 project
.cargo("build").run();
2880 project
.change_file(
2883 r
#"# This file is automatically @generated by Cargo.
2884 # It is not intended for manual editing.
2888 source = "git+{}#{}"
2903 .with_stderr("[FINISHED] [..]\n")
2908 fn historical_lockfile_works_with_vendor() {
2909 let project
= project();
2911 let (git_project
, repo
) = git
::new_repo("dep1", |project
| {
2913 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2914 .file("src/lib.rs", "")
2916 let head_id
= repo
.head().unwrap().target().unwrap();
2918 let project
= project
2928 dep1 = {{ git = '{}', branch = 'master' }}
2933 .file("src/lib.rs", "")
2936 let output
= project
.cargo("vendor").exec_with_output().unwrap();
2937 project
.change_file(".cargo/config", str::from_utf8(&output
.stdout
).unwrap());
2938 project
.change_file(
2941 r
#"# This file is automatically @generated by Cargo.
2942 # It is not intended for manual editing.
2946 source = "git+{}#{}"
2959 project
.cargo("build").run();
2963 fn two_dep_forms() {
2964 let project
= project();
2966 let (git_project
, _repo
) = git
::new_repo("dep1", |project
| {
2968 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2969 .file("src/lib.rs", "")
2972 let project
= project
2982 dep1 = {{ git = '{}', branch = 'master' }}
2983 a = {{ path = 'a' }}
2988 .file("src/lib.rs", "")
2998 dep1 = {{ git = '{}' }}
3003 .file("a/src/lib.rs", "")
3011 warning: two git dependencies found for `[..]` where one uses `branch = \"master\"` \
3012 and the other doesn't; this will break in a future version of Cargo, so please \
3013 ensure the dependency forms are consistent