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" }"#,
336 .file("vendor/dep3/src/lib.rs", "")
348 authors = ["wycats@example.com"]
364 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
368 p
.cargo("build").run();
370 assert
!(p
.bin("foo").is_file());
372 p
.process(&p
.bin("foo")).with_stdout("hello world\n").run();
376 fn cargo_compile_with_meta_package() {
377 let git_project
= git
::new("meta-dep", |project
| {
379 .file("dep1/Cargo.toml", &basic_lib_manifest("dep1"))
383 pub fn hello() -> &'static str {
388 .file("dep2/Cargo.toml", &basic_lib_manifest("dep2"))
392 pub fn hello() -> &'static str {
408 authors = ["wycats@example.com"]
431 r
#""{} {}", dep1::hello(), dep2::hello()"#,
437 p
.cargo("build").run();
439 assert
!(p
.bin("foo").is_file());
441 p
.process(&p
.bin("foo"))
442 .with_stdout("this is dep1 this is dep2\n")
447 fn cargo_compile_with_short_ssh_git() {
448 let url
= "git@github.com:a/dep";
459 authors = ["wycats@example.com"]
474 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
481 .with_stderr(&format
!(
483 [ERROR] failed to parse manifest at `[..]`
486 invalid url `{}`: relative URL without a base
494 fn two_revs_same_deps() {
495 let bar
= git
::new("meta-dep", |project
| {
497 .file("Cargo.toml", &basic_manifest("bar", "0.0.0"))
498 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
501 let repo
= git2
::Repository
::open(&bar
.root()).unwrap();
502 let rev1
= repo
.revparse_single("HEAD").unwrap().id();
504 // Commit the changes and make sure we trigger a recompile
505 bar
.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
507 let rev2
= git
::commit(&repo
);
537 assert_eq!(bar::bar(), 1);
538 assert_eq!(baz::baz(), 2);
567 pub fn baz() -> i32 { bar::bar() }
572 foo
.cargo("build -v").run();
573 assert
!(foo
.bin("foo").is_file());
574 foo
.process(&foo
.bin("foo")).run();
579 let git_project
= git
::new("bar", |project
| {
581 .file("Cargo.toml", &basic_lib_manifest("bar"))
582 .file("src/bar.rs", "pub fn bar() {}")
594 authors = ["wycats@example.com"]
604 .file("src/main.rs", &main_file(r
#""{:?}", bar::bar()"#, &["bar"]))
607 // First time around we should compile both foo and bar
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) \
620 // Don't recompile the second time
621 p
.cargo("build").with_stdout("").run();
623 // Modify a file manually, shouldn't trigger a recompile
624 git_project
.change_file("src/bar.rs", r
#"pub fn bar() { println!("hello!"); }"#);
626 p
.cargo("build").with_stdout("").run();
629 .with_stderr(&format
!(
630 "[UPDATING] git repository `{}`",
635 p
.cargo("build").with_stdout("").run();
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();
643 println
!("compile after commit");
644 p
.cargo("build").with_stdout("").run();
645 p
.root().move_into_the_past();
647 // Update the dependency and carry on!
649 .with_stderr(&format
!(
650 "[UPDATING] git repository `{}`\n\
651 [UPDATING] bar v0.5.0 ([..]) -> #[..]\n\
656 println
!("going for the last compile");
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) \
667 // Make sure clean only cleans one dep
668 p
.cargo("clean -p foo").with_stdout("").run();
671 "[COMPILING] foo v0.5.0 ([CWD])\n\
672 [FINISHED] dev [unoptimized + debuginfo] target(s) \
679 fn update_with_shared_deps() {
680 let git_project
= git
::new("bar", |project
| {
682 .file("Cargo.toml", &basic_lib_manifest("bar"))
683 .file("src/bar.rs", "pub fn bar() {}")
693 authors = ["wycats@example.com"]
704 #[allow(unused_extern_crates)]
706 #[allow(unused_extern_crates)]
718 authors = ["wycats@example.com"]
727 .file("dep1/src/lib.rs", "")
735 authors = ["wycats@example.com"]
744 .file("dep2/src/lib.rs", "")
747 // First time around we should compile both foo and bar
749 .with_stderr(&format
!(
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(),
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();
770 // By default, not transitive updates
771 println
!("dep1 update");
772 p
.cargo("update -p dep1").with_stdout("").run();
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")
780 [ERROR] Unable to update [..]
783 precise value for git is not a git revision: 0.1.2
786 unable to parse OID - contains invalid characters; class=Invalid (3)
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())
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\
810 // Make sure we still only compile one version of the git repo
813 .with_stderr(&format
!(
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(),
824 // We should be able to update transitive deps
825 p
.cargo("update -p bar")
826 .with_stderr(&format
!(
827 "[UPDATING] git repository `{}`",
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"))
839 let git_project2
= git
::new("dep2", |project
| project
.file("lib.rs", "pub fn dep() {}"));
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"));
846 let project
= project
855 authors = ["wycats@example.com"]
866 "extern crate dep1; pub fn foo() { dep1::dep() }",
874 [UPDATING] git repository [..]
875 [UPDATING] git submodule `file://[..]/dep2`
876 [COMPILING] dep1 [..]
878 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
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"))
889 let git_project2
= git
::new("dep2", |project
| project
.file("lib.rs", "pub fn dep() {}"));
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"));
896 // now amend the first commit on git_project2 to make submodule ref point to not-found
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();
903 Some("refs/heads/master"),
907 Some("something something"),
921 authors = ["wycats@example.com"]
932 "extern crate dep1; pub fn foo() { dep1::dep() }",
936 let expected
= format
!(
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 [..]`
943 failed to load source for dependency `dep1`
949 failed to update submodule `src`
952 object not found - no match for id [..]
954 path2url(git_project
.root())
958 .with_stderr(expected
)
964 fn two_deps_only_update_one() {
965 let project
= project();
966 let git1
= git
::new("dep1", |project
| {
968 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
969 .file("src/lib.rs", "")
971 let git2
= git
::new("dep2", |project
| {
973 .file("Cargo.toml", &basic_manifest("dep2", "0.5.0"))
974 .file("src/lib.rs", "")
986 authors = ["wycats@example.com"]
997 .file("src/main.rs", "fn main() {}")
1000 fn oid_to_short_sha(oid
: git2
::Oid
) -> String
{
1001 oid
.to_string()[..8].to_string()
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
)
1009 println
!("dep1 head sha: {}", git_repo_head_sha(&git1
));
1010 println
!("dep2 head sha: {}", git_repo_head_sha(&git2
));
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",
1023 git1
.change_file("src/lib.rs", "pub fn foo() {}");
1024 let repo
= git2
::Repository
::open(&git1
.root()).unwrap();
1026 let oid
= git
::commit(&repo
);
1027 println
!("dep1 head sha: {}", oid_to_short_sha(oid
));
1029 p
.cargo("update -p dep1")
1030 .with_stderr(&format
!(
1031 "[UPDATING] git repository `{}`\n\
1032 [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
1040 fn stale_cached_version() {
1041 let bar
= git
::new("meta-dep", |project
| {
1043 .file("Cargo.toml", &basic_manifest("bar", "0.0.0"))
1044 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1047 // Update the git database in the cache with the current state of the git
1070 fn main() { assert_eq!(bar::bar(), 1) }
1075 foo
.cargo("build").run();
1076 foo
.process(&foo
.bin("foo")).run();
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();
1087 let rev
= repo
.revparse_single("HEAD").unwrap().id();
1097 'bar 0.0.0 (git+{url}#{hash})'
1103 source = 'git+{url}#{hash}'
1112 .with_stderr(&format
!(
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 [..]
1122 foo
.process(&foo
.bin("foo")).run();
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"))
1132 let git_project2
= git
::new("dep2", |project
| {
1133 project
.file("lib.rs", "pub fn dep() -> &'static str { \"project2\" }")
1136 let git_project3
= git
::new("dep3", |project
| {
1137 project
.file("lib.rs", "pub fn dep() -> &'static str { \"project3\" }")
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"));
1152 authors = ["wycats@example.com"]
1163 pub fn main() { println!(\"{}\", dep1::dep()) }
1168 println
!("first run");
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 \
1177 [RUNNING] `target/debug/foo[EXE]`\n",
1179 .with_stdout("project2\n")
1182 git_project
.change_file(
1185 "[submodule \"src\"]\n\tpath = src\n\turl={}",
1190 // Sync the submodule and reset it to the new remote.
1191 sub
.sync().unwrap();
1193 let subrepo
= sub
.open().unwrap();
1195 .remote_add_fetch("origin", "refs/heads/*:refs/heads/*")
1198 .remote_set_url("origin", &git_project3
.url().to_string())
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();
1206 sub
.add_to_index(true).unwrap();
1211 // Update the dependency and carry on!
1213 p
.cargo("update -v")
1215 .with_stderr(&format
!(
1216 "[UPDATING] git repository `{}`\n\
1217 [UPDATING] git submodule `file://[..]/dep3`\n\
1218 [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
1224 println
!("last run");
1227 "[COMPILING] dep1 v0.5.0 ([..])\n\
1228 [COMPILING] foo v0.5.0 ([..])\n\
1229 [FINISHED] dev [unoptimized + debuginfo] target(s) in \
1231 [RUNNING] `target/debug/foo[EXE]`\n",
1233 .with_stdout("project3\n")
1238 fn dev_deps_with_testing() {
1239 let p2
= git
::new("bar", |project
| {
1241 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1245 pub fn gimme() -> &'static str { "zoidberg" }
1259 authors = ["wycats@example.com"]
1261 [dev-dependencies.bar]
1276 #[test] fn foo() { bar::gimme(); }
1282 // Generate a lock file which did not use `bar` to compile, but had to update
1283 // `bar` to generate the lock file
1285 .with_stderr(&format
!(
1287 [UPDATING] git repository `{bar}`
1288 [COMPILING] foo v0.5.0 ([CWD])
1289 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1295 // Make sure we use the previous resolution of `bar` instead of updating it
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]",
1305 .with_stdout_contains("test tests::foo ... ok")
1310 fn git_build_cmd_freshness() {
1311 let foo
= git
::new("foo", |project
| {
1323 .file("build.rs", "fn main() {}")
1324 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1325 .file(".gitignore", "src/bar.rs")
1327 foo
.root().move_into_the_past();
1334 [COMPILING] foo v0.0.0 ([CWD])
1335 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1340 // Smoke test to make sure it doesn't compile again
1341 println
!("first pass");
1342 foo
.cargo("build").with_stdout("").run();
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();
1351 fn git_name_not_always_needed() {
1352 let p2
= git
::new("bar", |project
| {
1354 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1358 pub fn gimme() -> &'static str { "zoidberg" }
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");
1378 [dev-dependencies.bar]
1384 .file("src/main.rs", "fn main() {}")
1387 // Generate a lock file which did not use `bar` to compile, but had to update
1388 // `bar` to generate the lock file
1390 .with_stderr(&format
!(
1392 [UPDATING] git repository `{bar}`
1393 [COMPILING] foo v0.5.0 ([CWD])
1394 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1402 fn git_repo_changing_no_rebuild() {
1403 let bar
= git
::new("bar", |project
| {
1405 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1406 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1409 // Lock p1 to the first rev in the git repo
1427 .file("src/main.rs", "fn main() {}")
1428 .file("build.rs", "fn main() {}")
1430 p1
.root().move_into_the_past();
1432 .with_stderr(&format
!(
1434 [UPDATING] git repository `{bar}`
1437 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
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();
1449 // Lock p2 to the second rev
1466 .file("src/main.rs", "fn main() {}")
1469 .with_stderr(&format
!(
1471 [UPDATING] git repository `{bar}`
1474 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
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();
1486 fn git_dep_build_cmd() {
1487 let p
= git
::new("foo", |project
| {
1496 authors = ["wycats@example.com"]
1508 .file("src/foo.rs", &main_file(r
#""{}", bar::gimme()"#, &["bar"]))
1516 authors = ["wycats@example.com"]
1525 "bar/src/bar.rs.in",
1527 pub fn gimme() -> i32 { 0 }
1535 fs::copy("src/bar.rs.in", "src/bar.rs").unwrap();
1541 p
.root().join("bar").move_into_the_past();
1543 p
.cargo("build").run();
1545 p
.process(&p
.bin("foo")).with_stdout("0\n").run();
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 }");
1550 p
.cargo("build").run();
1552 p
.process(&p
.bin("foo")).with_stdout("1\n").run();
1556 fn fetch_downloads() {
1557 let bar
= git
::new("bar", |project
| {
1559 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1560 .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
1578 .file("src/main.rs", "fn main() {}")
1581 .with_stderr(&format
!(
1582 "[UPDATING] git repository `{url}`",
1587 p
.cargo("fetch").with_stdout("").run();
1591 fn warnings_in_git_dep() {
1592 let bar
= git
::new("bar", |project
| {
1594 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1595 .file("src/lib.rs", "fn unused() {}")
1613 .file("src/main.rs", "fn main() {}")
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",
1629 fn update_ambiguous() {
1630 let bar1
= git
::new("bar1", |project
| {
1632 .file("Cargo.toml", &basic_manifest("bar", "0.5.0"))
1633 .file("src/lib.rs", "")
1635 let bar2
= git
::new("bar2", |project
| {
1637 .file("Cargo.toml", &basic_manifest("bar", "0.6.0"))
1638 .file("src/lib.rs", "")
1640 let baz
= git
::new("baz", |project
| {
1649 authors = ["wycats@example.com"]
1657 .file("src/lib.rs", "")
1678 .file("src/main.rs", "fn main() {}")
1681 p
.cargo("generate-lockfile").run();
1682 p
.cargo("update -p bar")
1686 [ERROR] There are multiple `bar` packages in your project, and the specification `bar` \
1688 Please re-run this command with `-p <spec>` where `<spec>` is one of the \
1698 fn update_one_dep_in_repo_with_many_deps() {
1699 let bar
= git
::new("bar", |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", "")
1725 .file("src/main.rs", "fn main() {}")
1728 p
.cargo("generate-lockfile").run();
1729 p
.cargo("update -p bar")
1730 .with_stderr(&format
!("[UPDATING] git repository `{}`", bar
.url()))
1735 fn switch_deps_does_not_update_transitive() {
1736 let transitive
= git
::new("transitive", |project
| {
1738 .file("Cargo.toml", &basic_manifest("transitive", "0.5.0"))
1739 .file("src/lib.rs", "")
1741 let dep1
= git
::new("dep1", |project
| {
1750 authors = ["wycats@example.com"]
1752 [dependencies.transitive]
1758 .file("src/lib.rs", "")
1760 let dep2
= git
::new("dep2", |project
| {
1769 authors = ["wycats@example.com"]
1771 [dependencies.transitive]
1777 .file("src/lib.rs", "")
1795 .file("src/main.rs", "fn main() {}")
1799 .with_stderr(&format
!(
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 [..]
1813 // Update the dependency to point to the second repository, but this
1814 // shouldn't update the transitive dependency which is the same.
1831 .with_stderr(&format
!(
1833 [UPDATING] git repository `{}`
1834 [COMPILING] dep [..]
1835 [COMPILING] foo [..]
1836 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
1844 fn update_one_source_updates_all_packages_in_that_git_source() {
1845 let dep
= git
::new("dep", |project
| {
1859 .file("src/lib.rs", "")
1860 .file("a/Cargo.toml", &basic_manifest("a", "0.5.0"))
1861 .file("a/src/lib.rs", "")
1879 .file("src/main.rs", "fn main() {}")
1882 p
.cargo("build").run();
1884 let repo
= git2
::Repository
::open(&dep
.root()).unwrap();
1885 let rev1
= repo
.revparse_single("HEAD").unwrap().id();
1887 // Just be sure to change a file
1888 dep
.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
1892 p
.cargo("update -p dep").run();
1893 let lockfile
= p
.read_lockfile();
1895 !lockfile
.contains(&rev1
.to_string()),
1903 fn switch_sources() {
1904 let a1
= git
::new("a1", |project
| {
1906 .file("Cargo.toml", &basic_manifest("a", "0.5.0"))
1907 .file("src/lib.rs", "")
1909 let a2
= git
::new("a2", |project
| {
1911 .file("Cargo.toml", &basic_manifest("a", "0.5.1"))
1912 .file("src/lib.rs", "")
1927 .file("src/main.rs", "fn main() {}")
1942 .file("b/src/lib.rs", "pub fn main() {}")
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 [..]
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 [..]
1986 fn dont_require_submodules_are_checked_out() {
1987 let p
= project().build();
1988 let git1
= git
::new("dep1", |p
| {
1999 .file("build.rs", "fn main() {}")
2000 .file("src/lib.rs", "")
2003 let git2
= git
::new("dep2", |p
| p
);
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"));
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();
2015 git1
.cargo("build -v").cwd(&dst
).run();
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() {}")
2025 let a1
= git
::new("a1", |p
| {
2035 a = {{ git = '{}' }}
2040 .file("src/lib.rs", "extern crate a; pub fn a1() {}")
2054 a = {{ git = '{}' }}
2068 p
.cargo("test -v").run();
2072 fn lints_are_suppressed() {
2073 let a
= git
::new("a", |p
| {
2074 p
.file("Cargo.toml", &basic_manifest("a", "0.5.0")).file(
2093 a = {{ git = '{}' }}
2098 .file("src/lib.rs", "")
2104 [UPDATING] git repository `[..]`
2105 [COMPILING] a v0.5.0 ([..])
2106 [COMPILING] foo v0.0.1 ([..])
2107 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
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(
2136 a = {{ git = '{}' }}
2141 .file("src/lib.rs", "")
2147 [UPDATING] git repository `[..]`
2148 [COMPILING] a v0.5.0 ([..])
2149 [COMPILING] foo v0.0.1 ([..])
2150 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
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", "")
2174 a = {{ path = 'a' }}
2175 git = {{ git = '{}' }}
2180 .file("src/lib.rs", "")
2181 .file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
2182 .file("a/src/lib.rs", "")
2185 p
.cargo("build").run();
2197 git = {{ git = '{}' }}
2203 p
.cargo("build").run();
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", "")
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();
2220 &repo
.find_object(head
, None
).unwrap(),
2221 &repo
.signature().unwrap(),
2238 git1 = {{ git = '{0}', rev = 'v0.1.0' }}
2239 git2 = {{ git = '{0}', rev = 'v0.1.0' }}
2244 .file("src/lib.rs", "")
2247 p
.cargo("generate-lockfile").run();
2248 p
.cargo("build -v").run();
2252 fn include_overrides_gitignore() {
2253 // Make sure that `package.include` takes precedence over .gitignore.
2254 let p
= git
::new("foo", |repo
| {
2261 include = ["src/lib.rs", "ignored.txt", "Cargo.toml"]
2272 .file("src/lib.rs", "")
2273 .file("ignored.txt", "")
2274 .file("build.rs", "fn main() {}")
2277 p
.cargo("build").run();
2278 p
.change_file("ignored.txt", "Trigger rebuild.");
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 [..]
2289 p
.cargo("package --list --allow-dirty")
2302 fn invalid_git_dependency_manifest() {
2303 let project
= project();
2304 let git_project
= git
::new("dep1", |project
| {
2313 authors = ["carlhuda@example.com"]
2314 categories = ["algorithms"]
2315 categories = ["algorithms"]
2325 pub fn hello() -> &'static str {
2332 let project
= project
2341 authors = ["wycats@example.com"]
2352 &main_file(r
#""{}", dep1::hello()"#, &["dep1"]),
2356 let git_root
= git_project
.root();
2361 .with_stderr(&format
!(
2363 [UPDATING] git repository `{}`
2364 [ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([..])`
2367 failed to load source for dependency `dep1`
2373 failed to parse manifest at `[..]`
2376 could not parse input as TOML
2379 duplicate key: `categories` for key `project` at line 10 column 17",
2380 path2url(&git_root
),
2381 path2url(&git_root
),
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"))
2393 let git_project2
= git
::new("dep2", |project
| project
.file("lib.rs", ""));
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();
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"));
2408 let repo
= git2
::Repository
::open(&git_project2
.root()).unwrap();
2409 let url
= format
!("https://{}:{}/", addr
.ip(), addr
.port());
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();
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"));
2428 let project
= project
2439 dep1 = {{ git = '{}' }}
2444 .file("src/lib.rs", "")
2450 .with_stderr_contains(" failed to update submodule `src`")
2451 .with_stderr_contains(" failed to update submodule `bar`")
2456 .with_stderr_contains(" failed to update submodule `src`")
2457 .with_stderr_contains(" failed to update submodule `bar`")
2460 done
.store(true, Ordering
::SeqCst
);
2461 drop(TcpStream
::connect(&addr
));
2467 if disable_git_cli() {
2470 let project
= project();
2471 let git_project
= git
::new("dep1", |project
| {
2473 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
2474 .file("src/lib.rs", "")
2477 let project
= project
2488 dep1 = {{ git = '{}' }}
2493 .file("src/lib.rs", "")
2498 git-fetch-with-cli = true
2504 [UPDATING] git repository `[..]`
2505 [RUNNING] `git fetch [..]`
2506 [COMPILING] dep1 [..]
2507 [RUNNING] `rustc [..]`
2508 [COMPILING] foo [..]
2509 [RUNNING] `rustc [..]`
2513 project
.cargo("build -v").with_stderr(stderr
).run();
2517 fn templatedir_doesnt_cause_problems() {
2518 let git_project2
= git
::new("dep2", |project
| {
2520 .file("Cargo.toml", &basic_manifest("dep2", "0.5.0"))
2521 .file("src/lib.rs", "")
2523 let git_project
= git
::new("dep1", |project
| {
2525 .file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
2526 .file("src/lib.rs", "")
2539 dep1 = {{ git = '{}' }}
2544 .file("src/main.rs", "fn main() {}")
2548 paths
::home().join(".gitconfig"),
2565 p
.cargo("build").run();
2569 fn git_with_cli_force() {
2570 if disable_git_cli() {
2573 // Supports a force-pushed repo.
2574 let git_project
= git
::new("dep1", |project
| {
2576 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2577 .file("src/lib.rs", r
#"pub fn f() { println!("one"); }"#)
2590 dep1 = {{ git = "{}" }}
2595 .file("src
/main
.rs
", "fn main() { dep1::f(); }
")
2600 git
-fetch
-with
-cli
= true
2604 p.cargo("build
").run();
2605 p.rename_run("foo
", "foo1
").with_stdout("one
").run();
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"); }
"#);
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());
2620 Some(&t!(repo.find_tree(tree_id)))
2622 // Perform the fetch.
2623 p.cargo("update
").run();
2624 p.cargo("build
").run();
2625 p.rename_run("foo
", "foo2
").with_stdout("two
").run();
2629 fn git_fetch_cli_env_clean() {
2630 if disable_git_cli() {
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| {
2637 .file("Cargo
.toml
", &basic_manifest("dep1
", "0.5.0"))
2638 .file("src
/lib
.rs
", "")
2641 let git_proj = git::new("foo
", |project| {
2651 dep1
= {{ git = '{}'
}}
2656 .file("src
/lib
.rs
", "pub extern crate dep1
;")
2661 git
-fetch
-with
-cli
= true
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.
2671 .env("GIT_DIR
", git_proj.root().join(".git
"))
2676 fn dirty_submodule() {
2677 // `cargo package` warns for dirty file in submodule.
2678 let (git_project, repo) = git::new_repo("foo
", |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
")
2684 let git_project2 = git::new("src
", |project| {
2685 project.no_manifest().file("lib
.rs
", "pub fn f() {}
")
2688 let url = path2url(git_project2.root()).to_string();
2689 git::add_submodule(&repo, &url, Path::new("src
"));
2691 // Submodule added, but not committed.
2693 .cargo("package
--no
-verify
")
2697 [WARNING
] manifest has no
[..]
2699 [ERROR
] 1 files
in the working directory contain changes that were not yet committed into git
:
2703 to proceed despite
[..]
2709 git_project.cargo("package
--no
-verify
").run();
2711 // Modify file, check for warning.
2712 git_project.change_file("src
/lib
.rs
", "");
2714 .cargo("package
--no
-verify
")
2718 [WARNING
] manifest has no
[..]
2720 [ERROR
] 1 files
in the working directory contain changes that were not yet committed into git
:
2724 to proceed despite
[..]
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);
2734 git_project.cargo("package
--no
-verify
").run();
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
"));
2741 .cargo("package
--no
-verify
")
2745 [WARNING
] manifest has no
[..]
2747 [ERROR
] 1 files
in the working directory contain changes that were not yet committed into git
:
2751 to proceed despite
[..]
2756 // Commit the submodule addition.
2757 git::commit(&sub_repo);
2760 git_project.cargo("package
--no
-verify
").run();
2761 // Modify within nested submodule.
2762 git_project.change_file("src
/bar
/mod.rs
", "//test");
2764 .cargo("package --no-verify")
2768 [WARNING] manifest has no [..]
2770 [ERROR] 1 files in the working directory contain changes that were not yet committed into git:
2774 to proceed despite [..]
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
);
2786 git_project
.cargo("package --no-verify").run();
2790 fn default_not_master() {
2791 let project
= project();
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
| {
2797 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2798 .file("src/lib.rs", "pub fn foo() {}")
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();
2805 // Then create a commit on the new `main` branch so `master` and `main`
2807 git_project
.change_file("src/lib.rs", "");
2811 let project
= project
2821 dep1 = {{ git = '{}' }}
2826 .file("src/lib.rs", "pub fn foo() { dep1::foo() }")
2833 [UPDATING] git repository `[..]`
2834 [COMPILING] dep1 v0.5.0 ([..])
2835 [COMPILING] foo v0.5.0 ([..])
2836 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
2842 fn historical_lockfile_works() {
2843 let project
= project();
2845 let (git_project
, repo
) = git
::new_repo("dep1", |project
| {
2847 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2848 .file("src/lib.rs", "")
2850 let head_id
= repo
.head().unwrap().target().unwrap();
2852 let project
= project
2862 dep1 = {{ git = '{}', branch = 'master' }}
2867 .file("src/lib.rs", "")
2870 project
.cargo("build").run();
2871 project
.change_file(
2874 r
#"# This file is automatically @generated by Cargo.
2875 # It is not intended for manual editing.
2879 source = "git+{}#{}"
2894 .with_stderr("[FINISHED] [..]\n")
2899 fn historical_lockfile_works_with_vendor() {
2900 let project
= project();
2902 let (git_project
, repo
) = git
::new_repo("dep1", |project
| {
2904 .file("Cargo.toml", &basic_lib_manifest("dep1"))
2905 .file("src/lib.rs", "")
2907 let head_id
= repo
.head().unwrap().target().unwrap();
2909 let project
= project
2919 dep1 = {{ git = '{}', branch = 'master' }}
2924 .file("src/lib.rs", "")
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(
2932 r
#"# This file is automatically @generated by Cargo.
2933 # It is not intended for manual editing.
2937 source = "git+{}#{}"
2950 project
.cargo("build").run();