Skip to content

Commit 928b956

Browse files
committed
Auto merge of #12248 - weihanglo:source-refactor, r=epage
refactor: registry data kinds cleanup
2 parents 49b6d9e + 008501a commit 928b956

File tree

9 files changed

+70
-92
lines changed

9 files changed

+70
-92
lines changed

src/cargo/core/package.rs

+4-28
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ use std::time::{Duration, Instant};
1010

1111
use anyhow::Context;
1212
use bytesize::ByteSize;
13-
use curl::easy::{Easy, HttpVersion};
13+
use curl::easy::Easy;
1414
use curl::multi::{EasyHandle, Multi};
1515
use lazycell::LazyCell;
16-
use log::{debug, warn};
16+
use log::debug;
1717
use semver::Version;
1818
use serde::Serialize;
1919

@@ -725,32 +725,8 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
725725
handle.http_headers(headers)?;
726726
}
727727

728-
// Enable HTTP/2 to be used as it'll allow true multiplexing which makes
729-
// downloads much faster.
730-
//
731-
// Currently Cargo requests the `http2` feature of the `curl` crate
732-
// which means it should always be built in. On OSX, however, we ship
733-
// cargo still linked against the system libcurl. Building curl with
734-
// ALPN support for HTTP/2 requires newer versions of OSX (the
735-
// SecureTransport API) than we want to ship Cargo for. By linking Cargo
736-
// against the system libcurl then older curl installations won't use
737-
// HTTP/2 but newer ones will. All that to basically say we ignore
738-
// errors here on OSX, but consider this a fatal error to not activate
739-
// HTTP/2 on all other platforms.
740-
if self.set.multiplexing {
741-
crate::try_old_curl!(handle.http_version(HttpVersion::V2), "HTTP2");
742-
} else {
743-
handle.http_version(HttpVersion::V11)?;
744-
}
745-
746-
// This is an option to `libcurl` which indicates that if there's a
747-
// bunch of parallel requests to the same host they all wait until the
748-
// pipelining status of the host is known. This means that we won't
749-
// initiate dozens of connections to crates.io, but rather only one.
750-
// Once the main one is opened we realized that pipelining is possible
751-
// and multiplexing is possible with static.crates.io. All in all this
752-
// reduces the number of connections down to a more manageable state.
753-
crate::try_old_curl!(handle.pipewait(true), "pipewait");
728+
// Enable HTTP/2 if possible.
729+
crate::try_old_curl_http2_pipewait!(self.set.multiplexing, handle);
754730

755731
handle.write_function(move |buf| {
756732
debug!("{} - {} bytes of data", token, buf.len());

src/cargo/core/package_id.rs

+5
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ impl PackageId {
196196
pub fn stable_hash(self, workspace: &Path) -> PackageIdStableHash<'_> {
197197
PackageIdStableHash(self, workspace)
198198
}
199+
200+
/// Filename of the `.crate` tarball, e.g., `once_cell-1.18.0.crate`.
201+
pub fn tarball_name(&self) -> String {
202+
format!("{}-{}.crate", self.name(), self.version())
203+
}
199204
}
200205

201206
pub struct PackageIdStableHash<'a>(PackageId, &'a Path);

src/cargo/ops/cargo_package.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ pub fn package_one(
127127
super::check_dep_has_version(dep, false)?;
128128
}
129129

130-
let filename = format!("{}-{}.crate", pkg.name(), pkg.version());
130+
let filename = pkg.package_id().tarball_name();
131131
let dir = ws.target_dir().join("package");
132132
let mut dst = {
133133
let tmp = format!(".{}", filename);

src/cargo/sources/registry/download.rs

+5-12
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
//! [`RemoteRegistry`]: super::remote::RemoteRegistry
55
66
use anyhow::Context;
7+
use cargo_util::registry::make_dep_path;
78
use cargo_util::Sha256;
89

910
use crate::core::PackageId;
10-
use crate::sources::registry::make_dep_prefix;
1111
use crate::sources::registry::MaybeLock;
1212
use crate::sources::registry::RegistryConfig;
1313
use crate::util::auth;
@@ -25,11 +25,6 @@ const PREFIX_TEMPLATE: &str = "{prefix}";
2525
const LOWER_PREFIX_TEMPLATE: &str = "{lowerprefix}";
2626
const CHECKSUM_TEMPLATE: &str = "{sha256-checksum}";
2727

28-
/// Filename of the `.crate` tarball, e.g., `once_cell-1.18.0.crate`.
29-
pub(super) fn filename(pkg: PackageId) -> String {
30-
format!("{}-{}.crate", pkg.name(), pkg.version())
31-
}
32-
3328
/// Checks if `pkg` is downloaded and ready under the directory at `cache_path`.
3429
/// If not, returns a URL to download it from.
3530
///
@@ -41,8 +36,7 @@ pub(super) fn download(
4136
checksum: &str,
4237
registry_config: RegistryConfig,
4338
) -> CargoResult<MaybeLock> {
44-
let filename = filename(pkg);
45-
let path = cache_path.join(&filename);
39+
let path = cache_path.join(&pkg.tarball_name());
4640
let path = config.assert_package_cache_locked(&path);
4741

4842
// Attempt to open a read-only copy first to avoid an exclusive write
@@ -74,7 +68,7 @@ pub(super) fn download(
7468
)
7569
.unwrap();
7670
} else {
77-
let prefix = make_dep_prefix(&*pkg.name());
71+
let prefix = make_dep_path(&pkg.name(), true);
7872
url = url
7973
.replace(CRATE_TEMPLATE, &*pkg.name())
8074
.replace(VERSION_TEMPLATE, &pkg.version().to_string())
@@ -113,9 +107,8 @@ pub(super) fn finish_download(
113107
anyhow::bail!("failed to verify the checksum of `{}`", pkg)
114108
}
115109

116-
let filename = filename(pkg);
117110
cache_path.create_dir()?;
118-
let path = cache_path.join(&filename);
111+
let path = cache_path.join(&pkg.tarball_name());
119112
let path = config.assert_package_cache_locked(&path);
120113
let mut dst = OpenOptions::new()
121114
.create(true)
@@ -142,7 +135,7 @@ pub(super) fn is_crate_downloaded(
142135
config: &Config,
143136
pkg: PackageId,
144137
) -> bool {
145-
let path = cache_path.join(filename(pkg));
138+
let path = cache_path.join(pkg.tarball_name());
146139
let path = config.assert_package_cache_locked(&path);
147140
if let Ok(meta) = fs::metadata(path) {
148141
return meta.len() > 0;

src/cargo/sources/registry/http_remote.rs

+10-23
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Access to a HTTP-based crate registry. See [`HttpRegistry`] for details.
22
33
use crate::core::{PackageId, SourceId};
4-
use crate::ops::{self};
4+
use crate::ops;
55
use crate::sources::registry::download;
66
use crate::sources::registry::MaybeLock;
77
use crate::sources::registry::{LoadResponse, RegistryConfig, RegistryData};
@@ -11,9 +11,9 @@ use crate::util::network::sleep::SleepTracker;
1111
use crate::util::{auth, Config, Filesystem, IntoUrl, Progress, ProgressStyle};
1212
use anyhow::Context;
1313
use cargo_util::paths;
14-
use curl::easy::{Easy, HttpVersion, List};
14+
use curl::easy::{Easy, List};
1515
use curl::multi::{EasyHandle, Multi};
16-
use log::{debug, trace, warn};
16+
use log::{debug, trace};
1717
use std::cell::RefCell;
1818
use std::collections::{HashMap, HashSet};
1919
use std::fs::{self, File};
@@ -383,7 +383,7 @@ impl<'cfg> HttpRegistry<'cfg> {
383383
}
384384
let config_json_path = self
385385
.assert_index_locked(&self.index_path)
386-
.join("config.json");
386+
.join(RegistryConfig::NAME);
387387
match fs::read(&config_json_path) {
388388
Ok(raw_data) => match serde_json::from_slice(&raw_data) {
389389
Ok(json) => {
@@ -404,12 +404,12 @@ impl<'cfg> HttpRegistry<'cfg> {
404404
fn config(&mut self) -> Poll<CargoResult<&RegistryConfig>> {
405405
debug!("loading config");
406406
let index_path = self.assert_index_locked(&self.index_path);
407-
let config_json_path = index_path.join("config.json");
408-
if self.is_fresh(Path::new("config.json")) && self.config_cached()?.is_some() {
407+
let config_json_path = index_path.join(RegistryConfig::NAME);
408+
if self.is_fresh(Path::new(RegistryConfig::NAME)) && self.config_cached()?.is_some() {
409409
return Poll::Ready(Ok(self.registry_config.as_ref().unwrap()));
410410
}
411411

412-
match ready!(self.load(Path::new(""), Path::new("config.json"), None)?) {
412+
match ready!(self.load(Path::new(""), Path::new(RegistryConfig::NAME), None)?) {
413413
LoadResponse::Data {
414414
raw_data,
415415
index_version: _,
@@ -543,7 +543,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
543543
}
544544
StatusCode::Unauthorized
545545
if !self.auth_required
546-
&& path == Path::new("config.json")
546+
&& path == Path::new(RegistryConfig::NAME)
547547
&& self.config.cli_unstable().registry_auth =>
548548
{
549549
debug!("re-attempting request for config.json with authorization included.");
@@ -593,7 +593,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
593593
}
594594
}
595595

596-
if path != Path::new("config.json") {
596+
if path != Path::new(RegistryConfig::NAME) {
597597
self.auth_required = ready!(self.config()?).auth_required;
598598
} else if !self.auth_required {
599599
// Check if there's a cached config that says auth is required.
@@ -618,20 +618,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
618618
handle.follow_location(true)?;
619619

620620
// Enable HTTP/2 if possible.
621-
if self.multiplexing {
622-
crate::try_old_curl!(handle.http_version(HttpVersion::V2), "HTTP2");
623-
} else {
624-
handle.http_version(HttpVersion::V11)?;
625-
}
626-
627-
// This is an option to `libcurl` which indicates that if there's a
628-
// bunch of parallel requests to the same host they all wait until the
629-
// pipelining status of the host is known. This means that we won't
630-
// initiate dozens of connections to crates.io, but rather only one.
631-
// Once the main one is opened we realized that pipelining is possible
632-
// and multiplexing is possible with static.crates.io. All in all this
633-
// reduces the number of connections done to a more manageable state.
634-
crate::try_old_curl!(handle.pipewait(true), "pipewait");
621+
crate::try_old_curl_http2_pipewait!(self.multiplexing, handle);
635622

636623
let mut headers = List::new();
637624
// Include a header to identify the protocol. This allows the server to

src/cargo/sources/registry/local.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -167,17 +167,15 @@ impl<'cfg> RegistryData for LocalRegistry<'cfg> {
167167
}
168168

169169
fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult<MaybeLock> {
170-
let crate_file = format!("{}-{}.crate", pkg.name(), pkg.version());
171-
172170
// Note that the usage of `into_path_unlocked` here is because the local
173171
// crate files here never change in that we're not the one writing them,
174172
// so it's not our responsibility to synchronize access to them.
175-
let path = self.root.join(&crate_file).into_path_unlocked();
173+
let path = self.root.join(&pkg.tarball_name()).into_path_unlocked();
176174
let mut crate_file = paths::open(&path)?;
177175

178176
// If we've already got an unpacked version of this crate, then skip the
179177
// checksum below as it is in theory already verified.
180-
let dst = format!("{}-{}", pkg.name(), pkg.version());
178+
let dst = path.file_stem().unwrap();
181179
if self.src_path.join(dst).into_path_unlocked().exists() {
182180
return Ok(MaybeLock::Ready(crate_file));
183181
}

src/cargo/sources/registry/mod.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,11 @@ impl<'cfg> Source for RegistrySource<'cfg> {
856856
}
857857
}
858858

859+
impl RegistryConfig {
860+
/// File name of [`RegistryConfig`].
861+
const NAME: &str = "config.json";
862+
}
863+
859864
/// Get the maximum upack size that Cargo permits
860865
/// based on a given `size` of your compressed file.
861866
///
@@ -903,9 +908,3 @@ fn max_unpack_size(config: &Config, size: u64) -> u64 {
903908

904909
u64::max(max_unpack_size, size * max_compression_ratio as u64)
905910
}
906-
907-
/// Constructs a path to a dependency in the registry index on filesystem.
908-
/// See [`cargo_util::registry::make_dep_path`] for more.
909-
fn make_dep_prefix(name: &str) -> String {
910-
cargo_util::registry::make_dep_path(name, true)
911-
}

src/cargo/sources/registry/remote.rs

+3-14
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,9 @@ impl<'cfg> RemoteRegistry<'cfg> {
103103
/// Creates intermediate dirs and initialize the repository.
104104
fn repo(&self) -> CargoResult<&git2::Repository> {
105105
self.repo.try_borrow_with(|| {
106+
trace!("acquiring registry index lock");
106107
let path = self.config.assert_package_cache_locked(&self.index_path);
107108

108-
if let Ok(repo) = git2::Repository::open(&path) {
109-
trace!("opened a repo without a lock");
110-
return Ok(repo);
111-
}
112-
113-
trace!("acquiring registry index lock");
114109
match git2::Repository::open(&path) {
115110
Ok(repo) => Ok(repo),
116111
Err(_) => {
@@ -210,8 +205,6 @@ impl<'cfg> RemoteRegistry<'cfg> {
210205
}
211206
}
212207

213-
const LAST_UPDATED_FILE: &str = ".last-updated";
214-
215208
impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
216209
fn prepare(&self) -> CargoResult<()> {
217210
self.repo()?;
@@ -311,7 +304,7 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
311304
debug!("loading config");
312305
self.prepare()?;
313306
self.config.assert_package_cache_locked(&self.index_path);
314-
match ready!(self.load(Path::new(""), Path::new("config.json"), None)?) {
307+
match ready!(self.load(Path::new(""), Path::new(RegistryConfig::NAME), None)?) {
315308
LoadResponse::Data { raw_data, .. } => {
316309
trace!("config loaded");
317310
let mut cfg: RegistryConfig = serde_json::from_slice(&raw_data)?;
@@ -357,7 +350,7 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
357350
self.head.set(None);
358351
*self.tree.borrow_mut() = None;
359352
self.current_sha.set(None);
360-
let path = self.config.assert_package_cache_locked(&self.index_path);
353+
let _path = self.config.assert_package_cache_locked(&self.index_path);
361354
if !self.quiet {
362355
self.config
363356
.shell()
@@ -377,10 +370,6 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
377370
)
378371
.with_context(|| format!("failed to fetch `{}`", url))?;
379372

380-
// Create a dummy file to record the mtime for when we updated the
381-
// index.
382-
paths::create(&path.join(LAST_UPDATED_FILE))?;
383-
384373
Ok(())
385374
}
386375

src/cargo/util/network/mod.rs

+35-4
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,51 @@ impl<T> PollExt<T> for Poll<T> {
2020
}
2121
}
2222

23-
// When dynamically linked against libcurl, we want to ignore some failures
24-
// when using old versions that don't support certain features.
23+
/// When dynamically linked against libcurl, we want to ignore some failures
24+
/// when using old versions that don't support certain features.
2525
#[macro_export]
2626
macro_rules! try_old_curl {
2727
($e:expr, $msg:expr) => {
2828
let result = $e;
2929
if cfg!(target_os = "macos") {
3030
if let Err(e) = result {
31-
warn!("ignoring libcurl {} error: {}", $msg, e);
31+
::log::warn!("ignoring libcurl {} error: {}", $msg, e);
3232
}
3333
} else {
34+
use ::anyhow::Context;
3435
result.with_context(|| {
35-
anyhow::format_err!("failed to enable {}, is curl not built right?", $msg)
36+
::anyhow::format_err!("failed to enable {}, is curl not built right?", $msg)
3637
})?;
3738
}
3839
};
3940
}
41+
42+
/// Enable HTTP/2 and pipewait to be used as it'll allow true multiplexing
43+
/// which makes downloads much faster.
44+
///
45+
/// Currently Cargo requests the `http2` feature of the `curl` crate which
46+
/// means it should always be built in. On OSX, however, we ship cargo still
47+
/// linked against the system libcurl. Building curl with ALPN support for
48+
/// HTTP/2 requires newer versions of OSX (the SecureTransport API) than we
49+
/// want to ship Cargo for. By linking Cargo against the system libcurl then
50+
/// older curl installations won't use HTTP/2 but newer ones will. All that to
51+
/// basically say we ignore errors here on OSX, but consider this a fatal error
52+
/// to not activate HTTP/2 on all other platforms.
53+
///
54+
/// `pipewait` is an option which indicates that if there's a bunch of parallel
55+
/// requests to the same host they all wait until the pipelining status of the
56+
/// host is known. This means that we won't initiate dozens of connections but
57+
/// rather only one. Once the main one is opened we realized that pipelining is
58+
/// possible and multiplexing is possible. All in all this reduces the number
59+
/// of connections down to a more manageable state.
60+
#[macro_export]
61+
macro_rules! try_old_curl_http2_pipewait {
62+
($multiplexing:expr, $handle:expr) => {
63+
if $multiplexing {
64+
$crate::try_old_curl!($handle.http_version(curl::easy::HttpVersion::V2), "HTTP/2");
65+
} else {
66+
$handle.http_version(curl::easy::HttpVersion::V11)?;
67+
}
68+
$crate::try_old_curl!($handle.pipewait(true), "pipewait");
69+
};
70+
}

0 commit comments

Comments
 (0)