mirror of
https://github.com/rust-lang/cargo
synced 2024-10-14 11:42:22 +00:00
add offline mode (-Z offline) with tests
This commit is contained in:
parent
c4003c4fbb
commit
ec5f78f933
|
@ -232,6 +232,7 @@ impl Features {
|
||||||
pub struct CliUnstable {
|
pub struct CliUnstable {
|
||||||
pub print_im_a_teapot: bool,
|
pub print_im_a_teapot: bool,
|
||||||
pub unstable_options: bool,
|
pub unstable_options: bool,
|
||||||
|
pub offline: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliUnstable {
|
impl CliUnstable {
|
||||||
|
@ -262,6 +263,7 @@ impl CliUnstable {
|
||||||
match k {
|
match k {
|
||||||
"print-im-a-teapot" => self.print_im_a_teapot = parse_bool(v)?,
|
"print-im-a-teapot" => self.print_im_a_teapot = parse_bool(v)?,
|
||||||
"unstable-options" => self.unstable_options = true,
|
"unstable-options" => self.unstable_options = true,
|
||||||
|
"offline" => self.offline = true,
|
||||||
_ => bail!("unknown `-Z` flag specified: {}", k),
|
_ => bail!("unknown `-Z` flag specified: {}", k),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -722,7 +722,7 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
|
||||||
None => return Err(activation_error(&cx, registry, &parent,
|
None => return Err(activation_error(&cx, registry, &parent,
|
||||||
&dep,
|
&dep,
|
||||||
cx.prev_active(&dep),
|
cx.prev_active(&dep),
|
||||||
&candidates)),
|
&candidates, config)),
|
||||||
Some(candidate) => candidate,
|
Some(candidate) => candidate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -788,7 +788,8 @@ fn activation_error(cx: &Context,
|
||||||
parent: &Summary,
|
parent: &Summary,
|
||||||
dep: &Dependency,
|
dep: &Dependency,
|
||||||
prev_active: &[Summary],
|
prev_active: &[Summary],
|
||||||
candidates: &[Candidate]) -> CargoError {
|
candidates: &[Candidate],
|
||||||
|
config: Option<&Config>) -> CargoError {
|
||||||
if !candidates.is_empty() {
|
if !candidates.is_empty() {
|
||||||
let mut msg = format!("failed to select a version for `{}` \
|
let mut msg = format!("failed to select a version for `{}` \
|
||||||
(required by `{}`):\n\
|
(required by `{}`):\n\
|
||||||
|
@ -843,7 +844,7 @@ fn activation_error(cx: &Context,
|
||||||
b.version().cmp(a.version())
|
b.version().cmp(a.version())
|
||||||
});
|
});
|
||||||
|
|
||||||
let msg = if !candidates.is_empty() {
|
let mut msg = if !candidates.is_empty() {
|
||||||
let versions = {
|
let versions = {
|
||||||
let mut versions = candidates.iter().take(3).map(|cand| {
|
let mut versions = candidates.iter().take(3).map(|cand| {
|
||||||
cand.version().to_string()
|
cand.version().to_string()
|
||||||
|
@ -886,6 +887,13 @@ fn activation_error(cx: &Context,
|
||||||
dep.version_req())
|
dep.version_req())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(config) = config {
|
||||||
|
if config.cli_unstable().offline {
|
||||||
|
msg.push_str("\nperhaps an error occurred because you are using \
|
||||||
|
the offline mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
format_err!("{}", msg)
|
format_err!("{}", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,10 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions)
|
||||||
bail!("you can't generate a lockfile for an empty workspace.")
|
bail!("you can't generate a lockfile for an empty workspace.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.config.cli_unstable().offline {
|
||||||
|
bail!("you can't update in the offline mode");
|
||||||
|
}
|
||||||
|
|
||||||
let previous_resolve = match ops::load_pkg_lockfile(ws)? {
|
let previous_resolve = match ops::load_pkg_lockfile(ws)? {
|
||||||
Some(resolve) => resolve,
|
Some(resolve) => resolve,
|
||||||
None => return generate_lockfile(ws),
|
None => return generate_lockfile(ws),
|
||||||
|
|
|
@ -76,6 +76,10 @@ pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()>
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ws.config().lock_update_allowed() {
|
if !ws.config().lock_update_allowed() {
|
||||||
|
if ws.config().cli_unstable().offline {
|
||||||
|
bail!("can't update in the offline mode");
|
||||||
|
}
|
||||||
|
|
||||||
let flag = if ws.config().network_allowed() {"--locked"} else {"--frozen"};
|
let flag = if ws.config().network_allowed() {"--locked"} else {"--frozen"};
|
||||||
bail!("the lock file needs to be updated but {} was passed to \
|
bail!("the lock file needs to be updated but {} was passed to \
|
||||||
prevent this", flag);
|
prevent this", flag);
|
||||||
|
|
|
@ -263,10 +263,13 @@ pub fn registry(config: &Config,
|
||||||
|
|
||||||
/// Create a new HTTP handle with appropriate global configuration for cargo.
|
/// Create a new HTTP handle with appropriate global configuration for cargo.
|
||||||
pub fn http_handle(config: &Config) -> CargoResult<Easy> {
|
pub fn http_handle(config: &Config) -> CargoResult<Easy> {
|
||||||
if !config.network_allowed() {
|
if config.frozen() {
|
||||||
bail!("attempting to make an HTTP request, but --frozen was \
|
bail!("attempting to make an HTTP request, but --frozen was \
|
||||||
specified")
|
specified")
|
||||||
}
|
}
|
||||||
|
if !config.network_allowed() {
|
||||||
|
bail!("can't make HTTP request in the offline mode")
|
||||||
|
}
|
||||||
|
|
||||||
// The timeout option for libcurl by default times out the entire transfer,
|
// The timeout option for libcurl by default times out the entire transfer,
|
||||||
// but we probably don't want this. Instead we only set timeouts for the
|
// but we probably don't want this. Instead we only set timeouts for the
|
||||||
|
|
|
@ -151,6 +151,10 @@ impl<'cfg> Source for GitSource<'cfg> {
|
||||||
|
|
||||||
let db_path = lock.parent().join("db").join(&self.ident);
|
let db_path = lock.parent().join("db").join(&self.ident);
|
||||||
|
|
||||||
|
if self.config.cli_unstable().offline && !db_path.exists() {
|
||||||
|
bail!("can't checkout from '{}': you are in the offline mode", self.remote.url());
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve our reference to an actual revision, and check if the
|
// Resolve our reference to an actual revision, and check if the
|
||||||
// database already has that revision. If it does, we just load a
|
// database already has that revision. If it does, we just load a
|
||||||
// database pinned at that revision, and if we don't we issue an update
|
// database pinned at that revision, and if we don't we issue an update
|
||||||
|
@ -159,7 +163,7 @@ impl<'cfg> Source for GitSource<'cfg> {
|
||||||
let should_update = actual_rev.is_err() ||
|
let should_update = actual_rev.is_err() ||
|
||||||
self.source_id.precise().is_none();
|
self.source_id.precise().is_none();
|
||||||
|
|
||||||
let (db, actual_rev) = if should_update {
|
let (db, actual_rev) = if should_update && !self.config.cli_unstable().offline {
|
||||||
self.config.shell().status("Updating",
|
self.config.shell().status("Updating",
|
||||||
format!("git repository `{}`", self.remote.url()))?;
|
format!("git repository `{}`", self.remote.url()))?;
|
||||||
|
|
||||||
|
|
|
@ -615,10 +615,13 @@ pub fn fetch(repo: &mut git2::Repository,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
refspec: &str,
|
refspec: &str,
|
||||||
config: &Config) -> CargoResult<()> {
|
config: &Config) -> CargoResult<()> {
|
||||||
if !config.network_allowed() {
|
if config.frozen() {
|
||||||
bail!("attempting to update a git repository, but --frozen \
|
bail!("attempting to update a git repository, but --frozen \
|
||||||
was specified")
|
was specified")
|
||||||
}
|
}
|
||||||
|
if !config.network_allowed() {
|
||||||
|
bail!("can't update a git repository in the offline mode")
|
||||||
|
}
|
||||||
|
|
||||||
// If we're fetching from github, attempt github's special fast path for
|
// If we're fetching from github, attempt github's special fast path for
|
||||||
// testing if we've already got an up-to-date copy of the repository
|
// testing if we've already got an up-to-date copy of the repository
|
||||||
|
|
|
@ -110,13 +110,20 @@ impl<'cfg> RegistryIndex<'cfg> {
|
||||||
.map(|s| s.trim())
|
.map(|s| s.trim())
|
||||||
.filter(|l| !l.is_empty());
|
.filter(|l| !l.is_empty());
|
||||||
|
|
||||||
|
let online = !self.config.cli_unstable().offline;
|
||||||
// Attempt forwards-compatibility on the index by ignoring
|
// Attempt forwards-compatibility on the index by ignoring
|
||||||
// everything that we ourselves don't understand, that should
|
// everything that we ourselves don't understand, that should
|
||||||
// allow future cargo implementations to break the
|
// allow future cargo implementations to break the
|
||||||
// interpretation of each line here and older cargo will simply
|
// interpretation of each line here and older cargo will simply
|
||||||
// ignore the new lines.
|
// ignore the new lines.
|
||||||
ret.extend(lines.filter_map(|line| {
|
ret.extend(lines.filter_map(|line| {
|
||||||
self.parse_registry_package(line).ok()
|
self.parse_registry_package(line).ok().and_then(|v|{
|
||||||
|
if online || load.is_crate_downloaded(v.0.package_id()) {
|
||||||
|
Some(v)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -249,6 +249,8 @@ pub trait RegistryData {
|
||||||
fn download(&mut self,
|
fn download(&mut self,
|
||||||
pkg: &PackageId,
|
pkg: &PackageId,
|
||||||
checksum: &str) -> CargoResult<FileLock>;
|
checksum: &str) -> CargoResult<FileLock>;
|
||||||
|
|
||||||
|
fn is_crate_downloaded(&self, _pkg: &PackageId) -> bool { true }
|
||||||
}
|
}
|
||||||
|
|
||||||
mod index;
|
mod index;
|
||||||
|
|
|
@ -153,6 +153,10 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_index(&mut self) -> CargoResult<()> {
|
fn update_index(&mut self) -> CargoResult<()> {
|
||||||
|
if self.config.cli_unstable().offline {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that we'll actually be able to acquire an HTTP handle later on
|
// Ensure that we'll actually be able to acquire an HTTP handle later on
|
||||||
// once we start trying to download crates. This will weed out any
|
// once we start trying to download crates. This will weed out any
|
||||||
// problems with `.cargo/config` configuration related to HTTP.
|
// problems with `.cargo/config` configuration related to HTTP.
|
||||||
|
@ -258,6 +262,20 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
|
||||||
dst.seek(SeekFrom::Start(0))?;
|
dst.seek(SeekFrom::Start(0))?;
|
||||||
Ok(dst)
|
Ok(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn is_crate_downloaded(&self, pkg: &PackageId) -> bool {
|
||||||
|
let filename = format!("{}-{}.crate", pkg.name(), pkg.version());
|
||||||
|
let path = Path::new(&filename);
|
||||||
|
|
||||||
|
if let Ok(dst) = self.cache_path.open_ro(path, self.config, &filename) {
|
||||||
|
if let Ok(meta) = dst.file().metadata(){
|
||||||
|
return meta.len() > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cfg> Drop for RemoteRegistry<'cfg> {
|
impl<'cfg> Drop for RemoteRegistry<'cfg> {
|
||||||
|
|
|
@ -504,7 +504,11 @@ impl Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn network_allowed(&self) -> bool {
|
pub fn network_allowed(&self) -> bool {
|
||||||
!self.frozen
|
!self.frozen() && !self.cli_unstable().offline
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn frozen(&self) -> bool {
|
||||||
|
self.frozen
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lock_update_allowed(&self) -> bool {
|
pub fn lock_update_allowed(&self) -> bool {
|
||||||
|
|
213
tests/build.rs
213
tests/build.rs
|
@ -15,6 +15,7 @@ use cargotest::support::paths::{CargoPathExt,root};
|
||||||
use cargotest::support::{ProjectBuilder};
|
use cargotest::support::{ProjectBuilder};
|
||||||
use cargotest::support::{project, execs, main_file, basic_bin_manifest};
|
use cargotest::support::{project, execs, main_file, basic_bin_manifest};
|
||||||
use cargotest::support::registry::Package;
|
use cargotest::support::registry::Package;
|
||||||
|
use cargotest::ChannelChanger;
|
||||||
use hamcrest::{assert_that, existing_file, existing_dir, is_not};
|
use hamcrest::{assert_that, existing_file, existing_dir, is_not};
|
||||||
use tempdir::TempDir;
|
use tempdir::TempDir;
|
||||||
|
|
||||||
|
@ -829,6 +830,218 @@ Did you mean `a`?"));
|
||||||
Did you mean `a`?"));
|
Did you mean `a`?"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cargo_compile_path_with_offline() {
|
||||||
|
let p = project("foo")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[package]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = []
|
||||||
|
|
||||||
|
[dependencies.bar]
|
||||||
|
path = "bar"
|
||||||
|
"#)
|
||||||
|
.file("src/lib.rs", "")
|
||||||
|
.file("bar/Cargo.toml", r#"
|
||||||
|
[package]
|
||||||
|
name = "bar"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = []
|
||||||
|
"#)
|
||||||
|
.file("bar/src/lib.rs", "")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
|
||||||
|
execs().with_status(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cargo_compile_with_downloaded_dependency_with_offline() {
|
||||||
|
Package::new("present_dep", "1.2.3")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "present_dep"
|
||||||
|
version = "1.2.3"
|
||||||
|
"#)
|
||||||
|
.file("src/lib.rs", "")
|
||||||
|
.publish();
|
||||||
|
|
||||||
|
{
|
||||||
|
// make package downloaded
|
||||||
|
let p = project("foo")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
present_dep = "1.2.3"
|
||||||
|
"#)
|
||||||
|
.file("src/lib.rs", "")
|
||||||
|
.build();
|
||||||
|
assert_that(p.cargo("build"),execs().with_status(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
let p2 = project("bar")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "bar"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
present_dep = "1.2.3"
|
||||||
|
"#)
|
||||||
|
.file("src/lib.rs", "")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_that(p2.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
|
||||||
|
execs().with_status(0)
|
||||||
|
.with_stderr_does_not_contain("Updating registry")
|
||||||
|
.with_stderr_does_not_contain("Downloading")
|
||||||
|
.with_stderr(format!("\
|
||||||
|
[COMPILING] present_dep v1.2.3
|
||||||
|
[COMPILING] bar v0.1.0 ({url})
|
||||||
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
|
||||||
|
url = p2.url())));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cargo_compile_offline_not_try_update() {
|
||||||
|
let p = project("bar")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "bar"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
not_cached_dep = "1.2.5"
|
||||||
|
"#)
|
||||||
|
.file("src/lib.rs", "")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
|
||||||
|
execs().with_status(101)
|
||||||
|
.with_stderr_does_not_contain("Updating registry")
|
||||||
|
.with_stderr_does_not_contain("Downloading")
|
||||||
|
.with_stderr("\
|
||||||
|
error: no matching package named `not_cached_dep` found (required by `bar`)
|
||||||
|
location searched: registry `[..]`
|
||||||
|
version required: ^1.2.5
|
||||||
|
perhaps an error occurred because you are using the offline mode"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compile_offline_without_maxvers_cached(){
|
||||||
|
Package::new("present_dep", "1.2.1").publish();
|
||||||
|
Package::new("present_dep", "1.2.2").publish();
|
||||||
|
|
||||||
|
Package::new("present_dep", "1.2.3")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "present_dep"
|
||||||
|
version = "1.2.3"
|
||||||
|
"#)
|
||||||
|
.file("src/lib.rs", r#"pub fn get_version()->&'static str {"1.2.3"}"#)
|
||||||
|
.publish();
|
||||||
|
|
||||||
|
Package::new("present_dep", "1.2.5")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "present_dep"
|
||||||
|
version = "1.2.5"
|
||||||
|
"#)
|
||||||
|
.file("src/lib.rs", r#"pub fn get_version(){"1.2.5"}"#)
|
||||||
|
.publish();
|
||||||
|
|
||||||
|
{
|
||||||
|
// make package cached
|
||||||
|
let p = project("foo")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
present_dep = "=1.2.3"
|
||||||
|
"#)
|
||||||
|
.file("src/lib.rs", "")
|
||||||
|
.build();
|
||||||
|
assert_that(p.cargo("build"),execs().with_status(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
let p2 = project("foo")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
present_dep = "1.2"
|
||||||
|
"#)
|
||||||
|
.file("src/main.rs", "\
|
||||||
|
extern crate present_dep;
|
||||||
|
fn main(){
|
||||||
|
println!(\"{}\", present_dep::get_version());
|
||||||
|
}")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_that(p2.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
|
||||||
|
execs().with_status(0)
|
||||||
|
.with_stderr(format!("\
|
||||||
|
[COMPILING] present_dep v1.2.3
|
||||||
|
[COMPILING] foo v0.1.0 ({url})
|
||||||
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
|
||||||
|
url = p2.url())));
|
||||||
|
|
||||||
|
assert_that(process(&p2.bin("foo")),
|
||||||
|
execs().with_status(0).with_stdout("1.2.3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compile_offline_while_transitive_dep_not_cached() {
|
||||||
|
let bar = Package::new("bar", "1.0.0");
|
||||||
|
let bar_path = bar.archive_dst();
|
||||||
|
bar.publish();
|
||||||
|
|
||||||
|
let mut content = Vec::new();
|
||||||
|
|
||||||
|
let mut file = File::open(bar_path.clone()).ok().unwrap();
|
||||||
|
let _ok = file.read_to_end(&mut content).ok().unwrap();
|
||||||
|
drop(file);
|
||||||
|
drop(File::create(bar_path.clone()).ok().unwrap() );
|
||||||
|
|
||||||
|
Package::new("foo", "0.1.0").dep("bar", "1.0.0").publish();
|
||||||
|
|
||||||
|
let p = project("transitive_load_test")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "transitive_load_test"
|
||||||
|
version = "0.0.1"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
foo = "0.1.0"
|
||||||
|
"#)
|
||||||
|
.file("src/main.rs", "fn main(){}")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// simulate download foo, but fail to download bar
|
||||||
|
let _out = p.cargo("build").exec_with_output();
|
||||||
|
|
||||||
|
drop( File::create(bar_path).ok().unwrap().write_all(&content) );
|
||||||
|
|
||||||
|
assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
|
||||||
|
execs().with_status(101)
|
||||||
|
.with_stderr_does_not_contain("Updating registry")
|
||||||
|
.with_stderr_does_not_contain("Downloading")
|
||||||
|
.with_stderr("\
|
||||||
|
error: no matching package named `bar` found (required by `foo`)
|
||||||
|
location searched: registry `[..]`
|
||||||
|
version required: = 1.0.0
|
||||||
|
perhaps an error occurred because you are using the offline mode"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compile_path_dep_then_change_version() {
|
fn compile_path_dep_then_change_version() {
|
||||||
let p = project("foo")
|
let p = project("foo")
|
||||||
|
|
138
tests/git.rs
138
tests/git.rs
|
@ -15,7 +15,9 @@ use cargo::util::process;
|
||||||
use cargotest::sleep_ms;
|
use cargotest::sleep_ms;
|
||||||
use cargotest::support::paths::{self, CargoPathExt};
|
use cargotest::support::paths::{self, CargoPathExt};
|
||||||
use cargotest::support::{git, project, execs, main_file, path2url};
|
use cargotest::support::{git, project, execs, main_file, path2url};
|
||||||
|
use cargotest::ChannelChanger;
|
||||||
use hamcrest::{assert_that,existing_file};
|
use hamcrest::{assert_that,existing_file};
|
||||||
|
use hamcrest::matchers::regex::matches_regex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cargo_compile_simple_git_dep() {
|
fn cargo_compile_simple_git_dep() {
|
||||||
|
@ -75,6 +77,142 @@ fn cargo_compile_simple_git_dep() {
|
||||||
execs().with_stdout("hello world\n"));
|
execs().with_stdout("hello world\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cargo_compile_forbird_git_httpsrepo_offline() {
|
||||||
|
|
||||||
|
let p = project("need_remote_repo")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "need_remote_repo"
|
||||||
|
version = "0.5.0"
|
||||||
|
authors = ["chabapok@example.com"]
|
||||||
|
|
||||||
|
[dependencies.dep1]
|
||||||
|
git = 'https://github.com/some_user/dep1.git'
|
||||||
|
"#)
|
||||||
|
.file("src/main.rs", "")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
|
||||||
|
execs().with_status(101).
|
||||||
|
with_stderr_does_not_contain("[UPDATING] git repository [..]").
|
||||||
|
with_stderr("\
|
||||||
|
error: failed to load source for a dependency on `dep1`
|
||||||
|
|
||||||
|
Caused by:
|
||||||
|
Unable to update https://github.com/some_user/dep1.git
|
||||||
|
|
||||||
|
Caused by:
|
||||||
|
can't checkout from 'https://github.com/some_user/dep1.git': you are in the offline mode"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cargo_compile_offline_with_cached_git_dep() {
|
||||||
|
let git_project = git::new("dep1", |project| {
|
||||||
|
project
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "dep1"
|
||||||
|
version = "0.5.0"
|
||||||
|
authors = ["chabapok@example.com"]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "dep1""#)
|
||||||
|
.file("src/lib.rs", r#"
|
||||||
|
pub static COOL_STR:&str = "cached git repo rev1";
|
||||||
|
"#)
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
let repo = git2::Repository::open(&git_project.root()).unwrap();
|
||||||
|
let rev1 = repo.revparse_single("HEAD").unwrap().id();
|
||||||
|
|
||||||
|
// Commit the changes and make sure we trigger a recompile
|
||||||
|
File::create(&git_project.root().join("src/lib.rs")).unwrap().write_all(br#"
|
||||||
|
pub static COOL_STR:&str = "cached git repo rev2";
|
||||||
|
"#).unwrap();
|
||||||
|
git::add(&repo);
|
||||||
|
let rev2 = git::commit(&repo);
|
||||||
|
|
||||||
|
{
|
||||||
|
// cache to regisrty rev1 and rev2
|
||||||
|
let prj = project("cache_git_dep")
|
||||||
|
.file("Cargo.toml", &format!(r#"
|
||||||
|
[project]
|
||||||
|
name = "cache_git_dep"
|
||||||
|
version = "0.5.0"
|
||||||
|
|
||||||
|
[dependencies.dep1]
|
||||||
|
git = '{}'
|
||||||
|
rev = "{}"
|
||||||
|
"#, git_project.url(), rev1.clone()))
|
||||||
|
.file("src/main.rs", "fn main(){}")
|
||||||
|
.build();
|
||||||
|
assert_that(prj.cargo("build"), execs().with_status(0));
|
||||||
|
|
||||||
|
File::create(&prj.root().join("Cargo.toml")).unwrap().write_all(
|
||||||
|
&format!(r#"
|
||||||
|
[project]
|
||||||
|
name = "cache_git_dep"
|
||||||
|
version = "0.5.0"
|
||||||
|
|
||||||
|
[dependencies.dep1]
|
||||||
|
git = '{}'
|
||||||
|
rev = "{}"
|
||||||
|
"#, git_project.url(), rev2.clone()).as_bytes()
|
||||||
|
).unwrap();
|
||||||
|
assert_that(prj.cargo("build"), execs().with_status(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
let project = project("foo")
|
||||||
|
.file("Cargo.toml", &format!(r#"
|
||||||
|
[project]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.5.0"
|
||||||
|
|
||||||
|
[dependencies.dep1]
|
||||||
|
git = '{}'
|
||||||
|
"#, git_project.url()))
|
||||||
|
.file("src/main.rs", &main_file(r#""hello from {}", dep1::COOL_STR"#, &["dep1"]))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let root = project.root();
|
||||||
|
let git_root = git_project.root();
|
||||||
|
|
||||||
|
assert_that(project.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
|
||||||
|
execs().with_stderr(format!("\
|
||||||
|
[COMPILING] dep1 v0.5.0 ({}#[..])
|
||||||
|
[COMPILING] foo v0.5.0 ({})
|
||||||
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
|
||||||
|
path2url(git_root),
|
||||||
|
path2url(root)
|
||||||
|
)));
|
||||||
|
|
||||||
|
assert_that(&project.bin("foo"), existing_file());
|
||||||
|
|
||||||
|
assert_that(process(&project.bin("foo")),
|
||||||
|
execs().with_stdout("hello from cached git repo rev2\n"));
|
||||||
|
|
||||||
|
drop( File::create(&project.root().join("Cargo.toml")).unwrap()
|
||||||
|
.write_all(&format!(r#"
|
||||||
|
[project]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.5.0"
|
||||||
|
|
||||||
|
[dependencies.dep1]
|
||||||
|
git = '{}'
|
||||||
|
rev = "{}"
|
||||||
|
"#, git_project.url(), rev1).as_bytes()).unwrap() );
|
||||||
|
|
||||||
|
let _out = project.cargo("build").masquerade_as_nightly_cargo()
|
||||||
|
.arg("-Zoffline").exec_with_output();
|
||||||
|
assert_that(process(&project.bin("foo")),
|
||||||
|
execs().with_stdout("hello from cached git repo rev1\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cargo_compile_git_dep_branch() {
|
fn cargo_compile_git_dep_branch() {
|
||||||
let project = project("foo");
|
let project = project("foo");
|
||||||
|
|
|
@ -552,6 +552,26 @@ fn update_lockfile() {
|
||||||
"));
|
"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn update_offline(){
|
||||||
|
use cargotest::ChannelChanger;
|
||||||
|
let p = project("foo")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[project]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = []
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bar = "*"
|
||||||
|
"#)
|
||||||
|
.file("src/main.rs", "fn main() {}")
|
||||||
|
.build();
|
||||||
|
assert_that(p.cargo("update").masquerade_as_nightly_cargo().arg("-Zoffline"),
|
||||||
|
execs().with_status(101).
|
||||||
|
with_stderr("error: you can't update in the offline mode[..]"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn dev_dependency_not_used() {
|
fn dev_dependency_not_used() {
|
||||||
let p = project("foo")
|
let p = project("foo")
|
||||||
|
|
Loading…
Reference in a new issue