Skip to content

Commit

Permalink
Auto merge of #4770 - chabapok:master, r=alexcrichton
Browse files Browse the repository at this point in the history
Add an "-Z offline" flag to Cargo, altering it's dependency resolution behavior

This PR is implementation of the #4686 (without "Populating the global cache" feature)
  • Loading branch information
bors committed Jan 9, 2018
2 parents 24aa3ca + 3ed3497 commit 3bb0536
Show file tree
Hide file tree
Showing 14 changed files with 438 additions and 8 deletions.
2 changes: 2 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ impl Features {
pub struct CliUnstable {
pub print_im_a_teapot: bool,
pub unstable_options: bool,
pub offline: bool,
}

impl CliUnstable {
Expand Down Expand Up @@ -262,6 +263,7 @@ impl CliUnstable {
match k {
"print-im-a-teapot" => self.print_im_a_teapot = parse_bool(v)?,
"unstable-options" => self.unstable_options = true,
"offline" => self.offline = true,
_ => bail!("unknown `-Z` flag specified: {}", k),
}

Expand Down
16 changes: 13 additions & 3 deletions src/cargo/core/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
None => return Err(activation_error(&cx, registry, &parent,
&dep,
cx.prev_active(&dep),
&candidates)),
&candidates, config)),
Some(candidate) => candidate,
}
}
Expand Down Expand Up @@ -788,7 +788,8 @@ fn activation_error(cx: &Context,
parent: &Summary,
dep: &Dependency,
prev_active: &[Summary],
candidates: &[Candidate]) -> CargoError {
candidates: &[Candidate],
config: Option<&Config>) -> CargoError {
if !candidates.is_empty() {
let mut msg = format!("failed to select a version for `{}` \
(required by `{}`):\n\
Expand Down Expand Up @@ -843,7 +844,7 @@ fn activation_error(cx: &Context,
b.version().cmp(a.version())
});

let msg = if !candidates.is_empty() {
let mut msg = if !candidates.is_empty() {
let versions = {
let mut versions = candidates.iter().take(3).map(|cand| {
cand.version().to_string()
Expand Down Expand Up @@ -886,6 +887,15 @@ fn activation_error(cx: &Context,
dep.version_req())
};

if let Some(config) = config {
if config.cli_unstable().offline {
msg.push_str("\nAs a reminder, you're using offline mode (-Z offline) \
which can sometimes cause surprising resolution failures, \
if this error is too confusing you may with to retry \
without the offline flag.");
}
}

format_err!("{}", msg)
}

Expand Down
4 changes: 4 additions & 0 deletions src/cargo/ops/cargo_generate_lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions)
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)? {
Some(resolve) => resolve,
None => return generate_lockfile(ws),
Expand Down
4 changes: 4 additions & 0 deletions src/cargo/ops/lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()>
}

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"};
bail!("the lock file needs to be updated but {} was passed to \
prevent this", flag);
Expand Down
5 changes: 4 additions & 1 deletion src/cargo/ops/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,13 @@ pub fn registry(config: &Config,

/// Create a new HTTP handle with appropriate global configuration for cargo.
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 \
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,
// but we probably don't want this. Instead we only set timeouts for the
Expand Down
7 changes: 6 additions & 1 deletion src/cargo/sources/git/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ impl<'cfg> Source for GitSource<'cfg> {

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 (-Z offline)",
self.remote.url());
}

// Resolve our reference to an actual revision, and check if the
// 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
Expand All @@ -159,7 +164,7 @@ impl<'cfg> Source for GitSource<'cfg> {
let should_update = actual_rev.is_err() ||
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",
format!("git repository `{}`", self.remote.url()))?;

Expand Down
5 changes: 4 additions & 1 deletion src/cargo/sources/git/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,10 +615,13 @@ pub fn fetch(repo: &mut git2::Repository,
url: &Url,
refspec: &str,
config: &Config) -> CargoResult<()> {
if !config.network_allowed() {
if config.frozen() {
bail!("attempting to update a git repository, but --frozen \
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
// testing if we've already got an up-to-date copy of the repository
Expand Down
9 changes: 8 additions & 1 deletion src/cargo/sources/registry/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,20 @@ impl<'cfg> RegistryIndex<'cfg> {
.map(|s| s.trim())
.filter(|l| !l.is_empty());

let online = !self.config.cli_unstable().offline;
// Attempt forwards-compatibility on the index by ignoring
// everything that we ourselves don't understand, that should
// allow future cargo implementations to break the
// interpretation of each line here and older cargo will simply
// ignore the new lines.
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(())
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/sources/registry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ pub trait RegistryData {
fn download(&mut self,
pkg: &PackageId,
checksum: &str) -> CargoResult<FileLock>;

fn is_crate_downloaded(&self, _pkg: &PackageId) -> bool { true }
}

mod index;
Expand Down
18 changes: 18 additions & 0 deletions src/cargo/sources/registry/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
}

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
// once we start trying to download crates. This will weed out any
// problems with `.cargo/config` configuration related to HTTP.
Expand Down Expand Up @@ -258,6 +262,20 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
dst.seek(SeekFrom::Start(0))?;
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> {
Expand Down
6 changes: 5 additions & 1 deletion src/cargo/util/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,11 @@ impl Config {
}

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 {
Expand Down
Loading

0 comments on commit 3bb0536

Please sign in to comment.