Can this be avoided by using explicitly versioned dependencies?
Welllll... It could, were it not for one little hiccup. (to be discussed)
What about when there are no dependencies at all?
Rest assured, cargo
does not use the internet if you have no dependencies.
In reality, the way to avoid it is:
- Have a valid
Cargo.lock
containing at least entries for all of the crates you depend on (and their recursive dependencies). - Each dependency required by your crate (at the versions listed in Cargo.lock) must have been downloaded at least once in the past, so that it can be found in
~/.cargo/registry/src
.
This means that the times you are at biggest risk of requiring a network connection are when you are adding a dependency to a brand new crate.
$ cargo new lol
$ cd lol
$ echo 'clap = "2.0"' >>Cargo.toml
$ cargo build
Updating registry `https://github.com/rust-lang/crates.io-index`
warning: spurious network error (2 tries remaining): curl error: Couldn't resolve host 'github.com'
; class=Net (12)
warning: spurious network error (1 tries remaining): curl error: Couldn't resolve host 'github.com'
; class=Net (12)
error: failed to load source for a dependency on `clap`
Caused by:
Unable to update registry `https://github.com/rust-lang/crates.io-index`
Caused by:
failed to fetch `https://github.com/rust-lang/crates.io-index`
Caused by:
curl error: Couldn't resolve host 'github.com'
; class=Net (12)
The crates.
io index
Here is kinda the funny bit. If you haven't yet, go take a look inside ~/.cargo/registry/index
. You'll see:
$ ls ~/.cargo/registry/index/github.com-1ecc6299db9ec823/
1 ap bf c- config.json dd dv el fe ga gs hj ic iv jv ks lo me mv no oh oy pn qm rg ry sm tb tu ul vg wd wy xn yu zs
2 aq bg c3 cp de dw em ff gb gt hk id iw jw kt lp mf mx np oi oz po qn rh rz sn tc tv um vi we x- xo yy zw
3 ar bi c_ cq df dx en fg gc gu hl ie ix k2 ku lq mg my nq oj p- pp qo ri s- so td tw un vk wf x1 xp z3 zx
aa as bk ca cr dg dy ep fh gd gv hm if j4 k8 kv lr mh n- nr ok p0 pq qp rj s2 sp te tx up vl wg x2 xr za zy
ab at bl cb cs dh e1 er fi ge gw ho ig ja ka kw ls mi n2 ns ol p2 pr qr rl s3 sq tf ty ur vm wh x5 xs zb
ac au bm cc ct di e2 es fl gf gy hp ih jb kb ky lt mj n_ nt om pa ps qs rm s_ sr tg tz us vn wi x8 xt zc
ad av bn cd cu dj e3 et fm gg gz hs ik jc kc l2 lu mk na nu on pb pt qt rn sa ss th u2 ut vo wk xa xv zd
ae aw bo ce cv dk ea eu fn gh h2 ht il je kd l3 lv ml nb nv oo pc pu qu ro sb st ti ua uu vp wl xb xx ze
af ax bp cf cx dl eb ev fo gi ha hu im jh ke la lw mm nc ny op pd pv qw rp sc su tj ub uv vr wm xc xy zf
ag ay bq cg cy dm ec ex fp gj hb hw in ji kh lb ly mn nd o2 oq pe pw r1 rq sd sv tk uc ux vs wn xd xz zh
ah az br ch cz dn ed ey fr gl hc hy io jl ki lc lz mo ne oa or pf px r2 rr se sw tl ud v4 vt wo xe ya zi
ai b2 bs ci d- do ee ez fs gm hd i1 ip jm kl ld m3 mp nf ob os pg py ra rs sf sx tm ue v8 vu wp xf yd zk
ak ba bt cj d2 dp ef f1 ft gn he i2 iq jn km le m4 mq ng oc ot ph qa rb rt sg sy to uf va w5 wr xh ye zl
al bb bu cl d3 dr eg fa fu go hf i3 ir jo kn lf ma mr ni od ou pi qc rc ru sh sz tq ug vc w_ ws xi yi zm
am bc bw cm da ds eh fb fw gp hg i8 is jp ko li mb ms nl oe ov pk qd rd rv si t2 tr uh vd wa wt xk yk zo
an bd by cn db dt ei fc fx gq hh ia it js kq ll mc mt nm of ow pl qe re rw sk t_ ts ui ve wb wu xl yo zp
ao be bz co dc du ej fd g- gr hi ib iu ju kr lm md mu nn og ox pm qi rf rx sl ta tt uk vf wc ww xm yt zq
This is a complete, local copy of the crates.io index, used to resolve compatible versions of crates and their dependencies. Needless to say, this is what cargo uses when Cargo.lock is missing something and you're offline, right?
...if you thought that, you'd be wrong. What actually happens is that cargo
wants to make really really sure the registry is up to date before using it. So it tries to connect to the network, and dies if it cannot.
"well gee that sounds like a simple fix"
well gee there's also more to it than that
Suppose that the above "silly error" was fixed, so that cargo simply continued onward and used the local copy of the crates.
io index in whatever state it currently is when connecting to the network fails. This, unfortunately, would very likely cause it to pick versions of crates that you have never downloaded before!
- The last time I added
clap
as a dependency to a crate was months ago.cargo
picked the latest version at the time,clap-2.27.1
, and downloaded it. - Later, when adding e.g.
pretty-assertions
as a dependency to some other crate, cargo updated my local copy of the crates.
io index, causing it to learn about many new versions ofclap
. - Now, when
cargo
looks in my local offline copy of the index for a version ofclap
to add tolol
, it will pick the latest version it sees---say,2.31.0
. - It looks in the download cache, but
clap-2.31.0
is nowhere to be found! Uh oh, time to start downloading!
...ideally, when we are in offline mode, we would want cargo
to choose clap-2.27.1
, the one that exists in the download cache, so that downloading is not necessary. From reading the mentoring instructions linked in the first post, it appears that a good deal of the work necessary goes into fixing paper cuts like this.
Working around the limitations today
Original content
If you really need to get something up and running while you're offline, here's what you do.
- Find the biggest crate you've ever built on your local machine. Something with at least all of the dependencies you need.
- Copy its
Cargo.lock
over into the new crate. - Edit
Cargo.toml
if necessary to make sure the versions it lists in there are semver compatible with the ones available in the lockfile.
That's it. As long as all of the dependencies have an entry in there, you don't need to remove anything from the lockfile. When you do cargo build
it will add the missing entry for the current crate, and start building dependencies from the cached downloads.
(if you need to splice together multiple Cargo.locks, be careful; you'll need to edit it to make sure it does not contain multiple semver-compatible versions of any crate!)
Edit:
Offline mode has been implemented!
Thanks to @ehuss for correcting me on this: Offline mode was in fact implemented not too long after the posting of this thread, and is currently available through the flag -Z offline
on the nightly channel. Please give it a try!