Skip to content

Commit e74a3a5

Browse files
committed
fix(vendor): unpack from local-registry cache path
In rust-lang#15514, Cargo starts direct-extraction from `.crate` tarball in `$CARGO_HOME/registry/cache` when vendoring. This is fine with remote registrires but not for local registries, as local registries' tarball are stored along with index. This fix abstracts `cache_path` to `RegistryData` trait, so every registry source type can define its own locationa of tarball cache. Note that for local-registry when accessing either index or cache, the assumption is that file lock of the index and cache directory need to be externally synchronized. Cargo doesn't take care of it.
1 parent d12d8b7 commit e74a3a5

5 files changed

Lines changed: 47 additions & 21 deletions

File tree

src/cargo/sources/registry/http_remote.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,10 @@ impl<'gctx> RegistryData for HttpRegistry<'gctx> {
472472
&self.index_path
473473
}
474474

475+
fn cache_path(&self) -> &Filesystem {
476+
&self.cache_path
477+
}
478+
475479
fn assert_index_locked<'a>(&self, path: &'a Filesystem) -> &'a Path {
476480
self.gctx
477481
.assert_package_cache_locked(CacheLockMode::DownloadExclusive, path)

src/cargo/sources/registry/local.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ impl<'gctx> RegistryData for LocalRegistry<'gctx> {
9595
&self.index_path
9696
}
9797

98+
fn cache_path(&self) -> &Filesystem {
99+
&self.root
100+
}
101+
98102
fn assert_index_locked<'a>(&self, path: &'a Filesystem) -> &'a Path {
99103
// Note that the `*_unlocked` variant is used here since we're not
100104
// modifying the index and it's required to be externally synchronized.

src/cargo/sources/registry/mod.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,6 @@ pub struct RegistrySource<'gctx> {
248248
source_id: SourceId,
249249
/// The path where crate files are extracted (`$CARGO_HOME/registry/src/$REG-HASH`).
250250
src_path: Filesystem,
251-
/// Path to the cache of `.crate` files (`$CARGO_HOME/registry/cache/$REG-HASH`).
252-
cache_path: Filesystem,
253251
/// Local reference to [`GlobalContext`] for convenience.
254252
gctx: &'gctx GlobalContext,
255253
/// Abstraction for interfacing to the different registry kinds.
@@ -355,6 +353,12 @@ pub trait RegistryData {
355353
/// (remote = git, http & local = files).
356354
fn index_path(&self) -> &Filesystem;
357355

356+
/// Returns the path of the directory that stores the cache of `.crate` files.
357+
///
358+
/// The directory is currently expected to contain a flat list of all `.crate` files,
359+
/// named `<package-name>-<version>.crate`.
360+
fn cache_path(&self) -> &Filesystem;
361+
358362
/// Loads the JSON for a specific named package from the index.
359363
///
360364
/// * `root` is the root path to the index.
@@ -534,7 +538,6 @@ impl<'gctx> RegistrySource<'gctx> {
534538
RegistrySource {
535539
name: name.into(),
536540
src_path: gctx.registry_source_path().join(name),
537-
cache_path: gctx.registry_cache_path().join(name),
538541
gctx,
539542
source_id,
540543
index: index::RegistryIndex::new(source_id, ops.index_path(), gctx),
@@ -665,17 +668,20 @@ impl<'gctx> RegistrySource<'gctx> {
665668
/// Returns the path to the crate tarball directory,
666669
/// which is always `<unpack_dir>/<pkg>-<version>`.
667670
///
668-
/// This holds an assumption that the associated tarball already exists.
671+
/// This holds some assumptions
672+
///
673+
/// * The associated tarball already exists
674+
/// * If this is a local registry,
675+
/// the package cache lock must be externally externally synchronized.
676+
/// Cargo does not take care of it being locked or not.
669677
pub fn unpack_package_in(
670678
&self,
671679
pkg: &PackageId,
672680
unpack_dir: &Path,
673681
include: &dyn Fn(&Path) -> bool,
674682
) -> CargoResult<PathBuf> {
675-
let path = self.cache_path.join(pkg.tarball_name());
676-
let path = self
677-
.gctx
678-
.assert_package_cache_locked(CacheLockMode::DownloadExclusive, &path);
683+
let path = self.ops.cache_path().join(pkg.tarball_name());
684+
let path = self.ops.assert_index_locked(&path);
679685
let dst = unpack_dir.join(format!("{}-{}", pkg.name(), pkg.version()));
680686
let tarball =
681687
File::open(path).with_context(|| format!("failed to open {}", path.display()))?;

src/cargo/sources/registry/remote.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ impl<'gctx> RegistryData for RemoteRegistry<'gctx> {
233233
&self.index_path
234234
}
235235

236+
fn cache_path(&self) -> &Filesystem {
237+
&self.cache_path
238+
}
239+
236240
fn assert_index_locked<'a>(&self, path: &'a Filesystem) -> &'a Path {
237241
self.gctx
238242
.assert_package_cache_locked(CacheLockMode::DownloadExclusive, path)

tests/testsuite/vendor.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2123,7 +2123,6 @@ fn vendor_rename_fallback() {
21232123

21242124
#[cargo_test]
21252125
fn vendor_local_registry() {
2126-
21272126
// A regression test for rust-lang/cargo#16412
21282127
let root = paths::root();
21292128
fs::create_dir(root.join(".cargo")).unwrap();
@@ -2137,7 +2136,8 @@ fn vendor_local_registry() {
21372136
[source.my-awesome-local-registry]
21382137
local-registry = 'registry'
21392138
"#,
2140-
).unwrap();
2139+
)
2140+
.unwrap();
21412141

21422142
Package::new("bar", "0.0.0")
21432143
.local(true)
@@ -2156,28 +2156,36 @@ fn vendor_local_registry() {
21562156
bar = "0.0.0"
21572157
"#,
21582158
)
2159-
.file(
2160-
"src/lib.rs",
2161-
"pub fn foo() { bar::bar(); }",
2162-
)
2159+
.file("src/lib.rs", "pub fn foo() { bar::bar(); }")
21632160
.build();
21642161

21652162
p.cargo("vendor --respect-source-config")
2166-
.with_status(101)
21672163
.with_stderr_data(str![[r#"
21682164
[LOCKING] 1 package to latest compatible version
21692165
[UNPACKING] bar v0.0.0 (registry `[ROOT]/registry`)
21702166
Vendoring bar v0.0.0 ([ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.0) to vendor/bar
2171-
[ERROR] failed to sync
2172-
2173-
Caused by:
2174-
failed to open [ROOT]/home/.cargo/registry/cache/-[HASH]/bar-0.0.0.crate
2167+
To use vendored sources, add this to your .cargo/config.toml for this project:
21752168
2176-
Caused by:
2177-
[NOT_FOUND]
21782169
21792170
"#]])
21802171
.run();
2172+
2173+
assert_e2e().eq(
2174+
p.read_file("vendor/bar/Cargo.toml"),
2175+
str![[r#"
2176+
2177+
[package]
2178+
name = "bar"
2179+
version = "0.0.0"
2180+
authors = []
2181+
2182+
"#]],
2183+
);
2184+
2185+
assert_e2e().eq(
2186+
p.read_file("vendor/bar/src/lib.rs"),
2187+
str!["pub fn bar() {}"],
2188+
);
21812189
}
21822190

21832191
#[cargo_test]

0 commit comments

Comments
 (0)