Skip to content

Commit 3bb0536

Browse files
committed
Auto merge of #4770 - chabapok:master, r=alexcrichton
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)
2 parents 24aa3ca + 3ed3497 commit 3bb0536

File tree

14 files changed

+438
-8
lines changed

14 files changed

+438
-8
lines changed

src/cargo/core/features.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ impl Features {
232232
pub struct CliUnstable {
233233
pub print_im_a_teapot: bool,
234234
pub unstable_options: bool,
235+
pub offline: bool,
235236
}
236237

237238
impl CliUnstable {
@@ -262,6 +263,7 @@ impl CliUnstable {
262263
match k {
263264
"print-im-a-teapot" => self.print_im_a_teapot = parse_bool(v)?,
264265
"unstable-options" => self.unstable_options = true,
266+
"offline" => self.offline = true,
265267
_ => bail!("unknown `-Z` flag specified: {}", k),
266268
}
267269

src/cargo/core/resolver/mod.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
722722
None => return Err(activation_error(&cx, registry, &parent,
723723
&dep,
724724
cx.prev_active(&dep),
725-
&candidates)),
725+
&candidates, config)),
726726
Some(candidate) => candidate,
727727
}
728728
}
@@ -788,7 +788,8 @@ fn activation_error(cx: &Context,
788788
parent: &Summary,
789789
dep: &Dependency,
790790
prev_active: &[Summary],
791-
candidates: &[Candidate]) -> CargoError {
791+
candidates: &[Candidate],
792+
config: Option<&Config>) -> CargoError {
792793
if !candidates.is_empty() {
793794
let mut msg = format!("failed to select a version for `{}` \
794795
(required by `{}`):\n\
@@ -843,7 +844,7 @@ fn activation_error(cx: &Context,
843844
b.version().cmp(a.version())
844845
});
845846

846-
let msg = if !candidates.is_empty() {
847+
let mut msg = if !candidates.is_empty() {
847848
let versions = {
848849
let mut versions = candidates.iter().take(3).map(|cand| {
849850
cand.version().to_string()
@@ -886,6 +887,15 @@ fn activation_error(cx: &Context,
886887
dep.version_req())
887888
};
888889

890+
if let Some(config) = config {
891+
if config.cli_unstable().offline {
892+
msg.push_str("\nAs a reminder, you're using offline mode (-Z offline) \
893+
which can sometimes cause surprising resolution failures, \
894+
if this error is too confusing you may with to retry \
895+
without the offline flag.");
896+
}
897+
}
898+
889899
format_err!("{}", msg)
890900
}
891901

src/cargo/ops/cargo_generate_lockfile.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions)
3737
bail!("you can't generate a lockfile for an empty workspace.")
3838
}
3939

40+
if opts.config.cli_unstable().offline {
41+
bail!("you can't update in the offline mode");
42+
}
43+
4044
let previous_resolve = match ops::load_pkg_lockfile(ws)? {
4145
Some(resolve) => resolve,
4246
None => return generate_lockfile(ws),

src/cargo/ops/lockfile.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()>
7676
}
7777

7878
if !ws.config().lock_update_allowed() {
79+
if ws.config().cli_unstable().offline {
80+
bail!("can't update in the offline mode");
81+
}
82+
7983
let flag = if ws.config().network_allowed() {"--locked"} else {"--frozen"};
8084
bail!("the lock file needs to be updated but {} was passed to \
8185
prevent this", flag);

src/cargo/ops/registry.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,13 @@ pub fn registry(config: &Config,
263263

264264
/// Create a new HTTP handle with appropriate global configuration for cargo.
265265
pub fn http_handle(config: &Config) -> CargoResult<Easy> {
266-
if !config.network_allowed() {
266+
if config.frozen() {
267267
bail!("attempting to make an HTTP request, but --frozen was \
268268
specified")
269269
}
270+
if !config.network_allowed() {
271+
bail!("can't make HTTP request in the offline mode")
272+
}
270273

271274
// The timeout option for libcurl by default times out the entire transfer,
272275
// but we probably don't want this. Instead we only set timeouts for the

src/cargo/sources/git/source.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ impl<'cfg> Source for GitSource<'cfg> {
151151

152152
let db_path = lock.parent().join("db").join(&self.ident);
153153

154+
if self.config.cli_unstable().offline && !db_path.exists() {
155+
bail!("can't checkout from '{}': you are in the offline mode (-Z offline)",
156+
self.remote.url());
157+
}
158+
154159
// Resolve our reference to an actual revision, and check if the
155160
// database already has that revision. If it does, we just load a
156161
// database pinned at that revision, and if we don't we issue an update
@@ -159,7 +164,7 @@ impl<'cfg> Source for GitSource<'cfg> {
159164
let should_update = actual_rev.is_err() ||
160165
self.source_id.precise().is_none();
161166

162-
let (db, actual_rev) = if should_update {
167+
let (db, actual_rev) = if should_update && !self.config.cli_unstable().offline {
163168
self.config.shell().status("Updating",
164169
format!("git repository `{}`", self.remote.url()))?;
165170

src/cargo/sources/git/utils.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,10 +615,13 @@ pub fn fetch(repo: &mut git2::Repository,
615615
url: &Url,
616616
refspec: &str,
617617
config: &Config) -> CargoResult<()> {
618-
if !config.network_allowed() {
618+
if config.frozen() {
619619
bail!("attempting to update a git repository, but --frozen \
620620
was specified")
621621
}
622+
if !config.network_allowed() {
623+
bail!("can't update a git repository in the offline mode")
624+
}
622625

623626
// If we're fetching from github, attempt github's special fast path for
624627
// testing if we've already got an up-to-date copy of the repository

src/cargo/sources/registry/index.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,20 @@ impl<'cfg> RegistryIndex<'cfg> {
110110
.map(|s| s.trim())
111111
.filter(|l| !l.is_empty());
112112

113+
let online = !self.config.cli_unstable().offline;
113114
// Attempt forwards-compatibility on the index by ignoring
114115
// everything that we ourselves don't understand, that should
115116
// allow future cargo implementations to break the
116117
// interpretation of each line here and older cargo will simply
117118
// ignore the new lines.
118119
ret.extend(lines.filter_map(|line| {
119-
self.parse_registry_package(line).ok()
120+
self.parse_registry_package(line).ok().and_then(|v|{
121+
if online || load.is_crate_downloaded(v.0.package_id()) {
122+
Some(v)
123+
} else {
124+
None
125+
}
126+
})
120127
}));
121128

122129
Ok(())

src/cargo/sources/registry/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ pub trait RegistryData {
249249
fn download(&mut self,
250250
pkg: &PackageId,
251251
checksum: &str) -> CargoResult<FileLock>;
252+
253+
fn is_crate_downloaded(&self, _pkg: &PackageId) -> bool { true }
252254
}
253255

254256
mod index;

src/cargo/sources/registry/remote.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
153153
}
154154

155155
fn update_index(&mut self) -> CargoResult<()> {
156+
if self.config.cli_unstable().offline {
157+
return Ok(());
158+
}
159+
156160
// Ensure that we'll actually be able to acquire an HTTP handle later on
157161
// once we start trying to download crates. This will weed out any
158162
// problems with `.cargo/config` configuration related to HTTP.
@@ -258,6 +262,20 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
258262
dst.seek(SeekFrom::Start(0))?;
259263
Ok(dst)
260264
}
265+
266+
267+
fn is_crate_downloaded(&self, pkg: &PackageId) -> bool {
268+
let filename = format!("{}-{}.crate", pkg.name(), pkg.version());
269+
let path = Path::new(&filename);
270+
271+
if let Ok(dst) = self.cache_path.open_ro(path, self.config, &filename) {
272+
if let Ok(meta) = dst.file().metadata(){
273+
return meta.len() > 0;
274+
}
275+
}
276+
false
277+
}
278+
261279
}
262280

263281
impl<'cfg> Drop for RemoteRegistry<'cfg> {

src/cargo/util/config.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,11 @@ impl Config {
504504
}
505505

506506
pub fn network_allowed(&self) -> bool {
507-
!self.frozen
507+
!self.frozen() && !self.cli_unstable().offline
508+
}
509+
510+
pub fn frozen(&self) -> bool {
511+
self.frozen
508512
}
509513

510514
pub fn lock_update_allowed(&self) -> bool {

0 commit comments

Comments
 (0)