-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an "-Z offline" flag to Cargo, altering it's dependency resolution behavior #4770
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @alexcrichton (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
Awesome, thanks @chabapok! Mind adding some tests here as well for crates.io/git/path dependencies? The tests would go into |
I'll try to do this. |
Oh I'm mostly just thinking that you'd test things like error messages if the network is reached out to (or needs to be reached out to) and also tests for things like one project populating the cache so another can use it in offline mode (even if a more updated version is available) |
git repository may be remote or local. |
Oh right yeah we've got support in tests to set up "path" git repositories and Cargo just currently treats any remote (be it actually on the filesystem or across the network) as a network operation, so we can use path git repos in tests for this sort of functionality. |
How to about to not treat Let's do it like this. If git url starts with
|
Working with local git repositories is done as suggested. Added some tests. Pls, check. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks and sorry for the delay in reviewing! Could you be sure to add a few more tests cases like these as well?
- The index says two versions exist. The max version isn't downloaded, however. A build should still succeed.
- Existing git checkouts should be used without being updated if the offline flag is passed
- Exercising the error in resolve where crates can't be loaded. For example the index says it has crates
foo
andbar
.foo
depends onbar
and while versions offoo
have been downloaded no versions ofbar
have been downloaded.
src/cargo/sources/git/utils.rs
Outdated
|
||
#[inline] | ||
pub fn is_local_filesystem(url: &Url) -> bool { | ||
url.scheme() == "file" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm could we avoid this special casing? I don't think this is actually used that much in practice and treating all URLs uniformly would make writing tests much easier I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review. I will improve the tests.
But i am not sure about treat all URLs uniformly.
As far, as i understand:
Now we did not distinguish between a local or network git repository.
But in offline mode, we would like to do this. We can allow to work with local repositories, but forbid to work with network repositories.
This can be useful for usual offline cases. For example, we have many projects A, B ... Z,that depends on the 'master' branch of our library LIB located in local filesystem.
We want to add some functionality to LIB without breaking many projects, and then use that functionality in some of our projects. We do not have network.
We do this in separate branch (for example, 'my_cool_feature'), as usually.
But after merge 'my_cool_feature' to 'master' branch of the LIB, projects A ... Z can not see top of the master.
There is no way to cache top of the master to the cargo cache without networking.
This will look strange: there is a local git repository - but we can not use it without network.
This code (and some other places in pr) is needed to handle this case.
If we remove this, the code and tests will be easier, but we will not be able to do this.
If we remove the pull-up from the local git repository into the cache, this will worsen usability.
It turns out that if this functionality is missing, we can develop binaries - but we can not use new changes in libraries in the offline mode.
Perhaps this case requires additional discussion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah for sure we could make this distinction but I've never in practice seen anyone using a local git repository. Instead these are just used in tests, where it's quite useful to use the local filesystem as if it were the network to be able to write tests against.
Perhaps let's not make a special distinction here and leave that to a future PR?
src/cargo/sources/git/source.rs
Outdated
@@ -160,6 +160,10 @@ impl<'cfg> Source for GitSource<'cfg> { | |||
self.source_id.precise().is_none(); | |||
|
|||
let (repo, actual_rev) = if should_update { | |||
if self.config.cli_unstable().offline && !is_local_filesystem(self.remote.url()) { | |||
bail!("Unable to fetch `{:?}`: you are in the offline mode", self.reference); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this may not be quite the behavior we want to have, instead if we're in offline mode we'll want to entirely skip the update of a git repository and move straight to checking it out below (if it already exists). I think we'll only want to return an error like this in the case that the database doesn't already exist.
@@ -506,7 +506,11 @@ impl Config { | |||
} | |||
|
|||
pub fn network_allowed(&self) -> bool { | |||
!self.frozen | |||
!self.frozen() && !self.cli_unstable().offline |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little worried about modifying this function which is already uses in a few other locations. For example I think this error message may no longer be right (or this one or this one). Perhaps these locations could use a central method to determine why the network isn't allowed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I think that these error messages should never happen during offline mode, right? In that offline mode should divert Cargo from executing code paths like that.
tests/build.rs
Outdated
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")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this use with_stderr
to match the output exactly?
tests/build.rs
Outdated
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")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this also use with_stderr
to match the output and error message exactly?
tests/build.rs
Outdated
|
||
#[test] | ||
fn cargo_compile_offline_not_try_update() { | ||
use cargotest::ChannelChanger; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's ok to move imports like this to the top of the file.
tests/git.rs
Outdated
execs().with_status(101). | ||
with_stderr_does_not_contain("[UPDATING] git repository [..]"). | ||
with_stderr_contains("\ | ||
[..]Unable to fetch `Branch(\"master\")`: you are in the offline mode[..]") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this also use with_stderr
to match the entire output?
Also could the output here perhaps get improved? The debug representation may not be the best thing to print out and present to users here.
tests/registry.rs
Outdated
.build(); | ||
assert_that(p.cargo("update").masquerade_as_nightly_cargo().arg("-Zoffline"), | ||
execs().with_status(101). | ||
with_stderr_contains("error: you can't update in the offline mode[..]")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this use with_stderr
to match the entire error output?
Depending on how new the kernel is on the Travis instances cargo gets built on, you might be able to use
|
@luser nice! I'd actually be totally down with implementing that today in Cargo when For kernel support we'd probably just use |
I had to rebase PR changes onto Changes (as proposed above):
Pls, check. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking fantastic @chabapok, thanks so much for the comprehensive tests! Just a few small nits but otherwise I think this is ready to merge!
tests/build.rs
Outdated
|
||
assert_that(p2.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"), | ||
execs().with_status(0) | ||
.with_stderr_does_not_contain("Updating registry") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're doing an exhaustive match of stderr below using with_stderr
, so it's ok when using that to omit any calls to does_not_contain
tests/build.rs
Outdated
.with_stderr_does_not_contain("Downloading") | ||
.with_stderr(format!("\ | ||
[COMPILING] present_dep v1.2.3 | ||
[COMPILING] bar v0.1.0 ({url}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's ok to avoid using {url}
and just use [..]
here (aka don't match that part of the output)
tests/build.rs
Outdated
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]", | ||
url = p2.url()))); | ||
|
||
assert_that(process(&p2.bin("foo")), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can probably combine this assertion with the above one by using cargo run
instead of cargo build
, but either's fine!
src/cargo/core/resolver/mod.rs
Outdated
if let Some(config) = config { | ||
if config.cli_unstable().offline { | ||
msg.push_str("\nperhaps an error occurred because you are using \ | ||
the offline mode"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we can perhaps elaborate on this a bit? Maybe something like:
as 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.
src/cargo/sources/git/source.rs
Outdated
@@ -151,6 +151,10 @@ 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", self.remote.url()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the -Z offline
flag be mentioned as part of this error message as well?
☔ The latest upstream changes (presumably #4919) made this pull request unmergeable. Please resolve the merge conflicts. |
Updates based on review. (and rebase to the current master because automerge confict) Pls, check. |
📌 Commit 3ed3497 has been approved by |
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)
☀️ Test successful - status-appveyor, status-travis |
This PR is implementation of the #4686 (without "Populating the global cache" feature)