From 62fd2b03a5abf2186cd71a5ddaf7f38187305ae9 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Wed, 3 Jul 2024 22:33:19 +0800 Subject: [PATCH] refactor: move info into registry mod Added a new API called get_source_id_with_package_id. --- src/bin/cargo/commands/info.rs | 2 +- src/cargo/ops/mod.rs | 2 +- .../ops/{cargo_info => registry/info}/mod.rs | 185 +++--------------- .../ops/{cargo_info => registry/info}/view.rs | 29 ++- src/cargo/ops/registry/login.rs | 11 +- src/cargo/ops/registry/mod.rs | 75 ++++++- src/cargo/ops/registry/owner.rs | 4 +- src/cargo/ops/registry/publish.rs | 12 +- src/cargo/ops/registry/search.rs | 5 +- src/cargo/ops/registry/yank.rs | 4 +- 10 files changed, 137 insertions(+), 192 deletions(-) rename src/cargo/ops/{cargo_info => registry/info}/mod.rs (56%) rename src/cargo/ops/{cargo_info => registry/info}/view.rs (93%) diff --git a/src/bin/cargo/commands/info.rs b/src/bin/cargo/commands/info.rs index 833c03221d7e..3bd90707e38d 100644 --- a/src/bin/cargo/commands/info.rs +++ b/src/bin/cargo/commands/info.rs @@ -1,4 +1,4 @@ -use cargo::ops::cargo_info::info; +use cargo::ops::info; use cargo::util::command_prelude::*; use cargo_util_schemas::core::PackageIdSpec; diff --git a/src/cargo/ops/mod.rs b/src/cargo/ops/mod.rs index f3b303d8e208..7f126d74cfae 100644 --- a/src/cargo/ops/mod.rs +++ b/src/cargo/ops/mod.rs @@ -24,6 +24,7 @@ pub use self::cargo_update::write_manifest_upgrades; pub use self::cargo_update::UpdateOptions; pub use self::fix::{fix, fix_exec_rustc, fix_get_proxy_lock_addr, FixOptions}; pub use self::lockfile::{load_pkg_lockfile, resolve_to_string, write_pkg_lockfile}; +pub use self::registry::info; pub use self::registry::modify_owners; pub use self::registry::publish; pub use self::registry::registry_login; @@ -46,7 +47,6 @@ pub(crate) mod cargo_compile; pub mod cargo_config; mod cargo_doc; mod cargo_fetch; -pub mod cargo_info; mod cargo_install; mod cargo_new; mod cargo_output_metadata; diff --git a/src/cargo/ops/cargo_info/mod.rs b/src/cargo/ops/registry/info/mod.rs similarity index 56% rename from src/cargo/ops/cargo_info/mod.rs rename to src/cargo/ops/registry/info/mod.rs index 7f1074ad4487..bfcfcee1e965 100644 --- a/src/cargo/ops/cargo_info/mod.rs +++ b/src/cargo/ops/registry/info/mod.rs @@ -1,29 +1,21 @@ -mod view; - -use std::collections::HashSet; -use std::task::Poll; - -use anyhow::{bail, Context}; +use anyhow::bail; use cargo_credential::Operation; use cargo_util_schemas::core::{PackageIdSpec, PartialVersion}; -use crates_io::Registry as CratesIoRegistry; use crates_io::User; use crate::core::registry::PackageRegistry; -use crate::core::{ - Dependency, Package, PackageId, PackageIdSpecQuery, Registry, SourceId, Workspace, -}; -use crate::ops::cargo_info::view::pretty_view; -use crate::ops::registry::RegistryOrIndex; +use crate::core::{Dependency, Package, PackageId, PackageIdSpecQuery, Registry, Workspace}; +use crate::ops::registry::info::view::pretty_view; +use crate::ops::registry::{get_source_id_with_package_id, RegistryOrIndex, RegistrySourceIds}; use crate::ops::resolve_ws; -use crate::sources::source::{QueryKind, Source}; -use crate::sources::{IndexSummary, RegistrySource, SourceConfigMap}; -use crate::util::auth::{auth_token, AuthorizationErrorReason}; +use crate::sources::source::QueryKind; +use crate::sources::{IndexSummary, SourceConfigMap}; use crate::util::cache_lock::CacheLockMode; use crate::util::command_prelude::root_manifest; -use crate::util::network::http::http_handle; use crate::{CargoResult, GlobalContext}; +mod view; + pub fn info( spec: &PackageIdSpec, gctx: &GlobalContext, @@ -46,7 +38,8 @@ pub fn info( .and_then(|path| ws.members().find(|p| p.manifest_path() == path)) }); let (mut package_id, is_member) = find_pkgid_in_ws(nearest_package, ws.as_ref(), spec); - let (use_package_source_id, source_ids) = get_source_id(gctx, reg_or_index, package_id)?; + let (use_package_source_id, source_ids) = + get_source_id_with_package_id(gctx, package_id, reg_or_index.as_ref())?; // If we don't use the package's source, we need to query the package ID from the specified registry. if !use_package_source_id { package_id = None; @@ -84,7 +77,12 @@ pub fn info( let package = registry.get(&[package_id])?; let package = package.get_one(package_id)?; - let owners = try_list_owners(gctx, source_ids, package_id.name().as_str())?; + let owners = try_list_owners( + gctx, + &source_ids, + reg_or_index.as_ref(), + package_id.name().as_str(), + )?; pretty_view( package, &summaries, @@ -210,22 +208,25 @@ fn query_summaries( // Try to list the login and name of all owners of a crate. fn try_list_owners( gctx: &GlobalContext, - source_ids: RegistrySourceIds, + source_ids: &RegistrySourceIds, + reg_or_index: Option<&RegistryOrIndex>, package_name: &str, ) -> CargoResult>> { // Only remote registries support listing owners. if !source_ids.original.is_remote_registry() { return Ok(None); } - let registry = api_registry(gctx, source_ids)?; - match registry { - Some(mut registry) => { - let owners = registry.list_owners(package_name)?; - let names = owners.iter().map(get_username).collect(); - Ok(Some(names)) - } - None => Ok(None), - } + let mut registry = super::registry( + gctx, + source_ids, + None, + reg_or_index, + false, + Some(Operation::Read), + )?; + let owners = registry.list_owners(package_name)?; + let names = owners.iter().map(get_username).collect(); + Ok(Some(names)) } fn get_username(u: &User) -> String { @@ -239,134 +240,6 @@ fn get_username(u: &User) -> String { ) } -struct RegistrySourceIds { - /// Use when looking up the auth token, or writing out `Cargo.lock` - original: SourceId, - /// Use when interacting with the source (querying / publishing , etc) - /// - /// The source for crates.io may be replaced by a built-in source for accessing crates.io with - /// the sparse protocol, or a source for the testing framework (when the replace_crates_io - /// function is used) - /// - /// User-defined source replacement is not applied. - /// Note: This will be utilized when interfacing with the registry API. - replacement: SourceId, -} - -fn get_source_id( - gctx: &GlobalContext, - reg_or_index: Option, - package_id: Option, -) -> CargoResult<(bool, RegistrySourceIds)> { - let (use_package_source_id, sid) = match (®_or_index, package_id) { - (None, Some(package_id)) => (true, package_id.source_id()), - (None, None) => (false, SourceId::crates_io(gctx)?), - (Some(RegistryOrIndex::Index(url)), None) => (false, SourceId::for_registry(url)?), - (Some(RegistryOrIndex::Registry(r)), None) => (false, SourceId::alt_registry(gctx, r)?), - (Some(reg_or_index), Some(package_id)) => { - let sid = match reg_or_index { - RegistryOrIndex::Index(url) => SourceId::for_registry(url)?, - RegistryOrIndex::Registry(r) => SourceId::alt_registry(gctx, r)?, - }; - let package_source_id = package_id.source_id(); - // Same registry, use the package's source. - if sid == package_source_id { - (true, sid) - } else { - let pkg_source_replacement_sid = SourceConfigMap::new(gctx)? - .load(package_source_id, &HashSet::new())? - .replaced_source_id(); - // Use the package's source if the specified registry is a replacement for the package's source. - if pkg_source_replacement_sid == sid { - (true, package_source_id) - } else { - (false, sid) - } - } - } - }; - // Load source replacements that are built-in to Cargo. - let builtin_replacement_sid = SourceConfigMap::empty(gctx)? - .load(sid, &HashSet::new())? - .replaced_source_id(); - let replacement_sid = SourceConfigMap::new(gctx)? - .load(sid, &HashSet::new())? - .replaced_source_id(); - // Check if the user has configured source-replacement for the registry we are querying. - if reg_or_index.is_none() && replacement_sid != builtin_replacement_sid { - // Neither --registry nor --index was passed and the user has configured source-replacement. - if let Some(replacement_name) = replacement_sid.alt_registry_key() { - bail!("crates-io is replaced with remote registry {replacement_name};\ninclude `--registry {replacement_name}` or `--registry crates-io`"); - } else { - bail!("crates-io is replaced with non-remote-registry source {replacement_sid};\ninclude `--registry crates-io` to use crates.io"); - } - } else { - Ok(( - use_package_source_id, - RegistrySourceIds { - original: sid, - replacement: builtin_replacement_sid, - }, - )) - } -} - -// Try to get the crates.io registry which is used to access the registry API. -// If the user is not logged in, the function will return None. -fn api_registry( - gctx: &GlobalContext, - source_ids: RegistrySourceIds, -) -> CargoResult> { - let cfg = { - let mut src = RegistrySource::remote(source_ids.replacement, &HashSet::new(), gctx)?; - let cfg = loop { - match src.config()? { - Poll::Pending => src - .block_until_ready() - .with_context(|| format!("failed to update {}", source_ids.replacement))?, - Poll::Ready(cfg) => break cfg, - } - }; - cfg.expect("remote registries must have config") - }; - // This should only happen if the user has a custom registry configured. - // Some registries may not have API support. - let api_host = match cfg.api { - Some(api_host) => api_host, - None => return Ok(None), - }; - let token = match auth_token( - gctx, - &source_ids.original, - None, - Operation::Read, - vec![], - false, - ) { - Ok(token) => Some(token), - Err(err) => { - // If the token is missing, it means the user is not logged in. - // We don't want to show an error in this case. - if err.to_string().contains( - (AuthorizationErrorReason::TokenMissing) - .to_string() - .as_str(), - ) { - return Ok(None); - } - return Err(err); - } - }; - - let handle = http_handle(gctx)?; - Ok(Some(CratesIoRegistry::new_handle( - api_host, - token, - handle, - cfg.auth_required, - ))) -} - fn validate_locked_and_frozen_options( package_id: Option, gctx: &GlobalContext, diff --git a/src/cargo/ops/cargo_info/view.rs b/src/cargo/ops/registry/info/view.rs similarity index 93% rename from src/cargo/ops/cargo_info/view.rs rename to src/cargo/ops/registry/info/view.rs index 06ecd5913e2d..81f01e3a2aa9 100644 --- a/src/cargo/ops/cargo_info/view.rs +++ b/src/cargo/ops/registry/info/view.rs @@ -1,7 +1,9 @@ use std::collections::HashMap; use std::io::Write; +use crate::core::FeatureValue; use crate::util::style::{ERROR, HEADER, LITERAL, NOP, NOTE, WARN}; +use crate::util::OptVersionReq; use crate::{ core::{ dependency::DepKind, shell::Verbosity, Dependency, FeatureMap, Package, PackageId, SourceId, @@ -244,12 +246,10 @@ fn print_deps( .filter_map(|(n, _)| features.get(n)) .flatten() .filter_map(|f| match f { - crate::core::FeatureValue::Feature(_) => None, - crate::core::FeatureValue::Dep { dep_name } => Some(dep_name), - crate::core::FeatureValue::DepFeature { dep_name, weak, .. } if *weak => { - Some(dep_name) - } - crate::core::FeatureValue::DepFeature { .. } => None, + FeatureValue::Feature(_) => None, + FeatureValue::Dep { dep_name } => Some(dep_name), + FeatureValue::DepFeature { dep_name, weak, .. } if *weak => Some(dep_name), + FeatureValue::DepFeature { .. } => None, }) .any(|dep_name| *dep_name == dependency.name_in_toml()) { @@ -297,15 +297,13 @@ fn print_deps( Ok(()) } -fn pretty_req(req: &crate::util::OptVersionReq) -> String { +fn pretty_req(req: &OptVersionReq) -> String { let mut rendered = req.to_string(); let strip_prefix = match req { - crate::util::OptVersionReq::Any => false, - crate::util::OptVersionReq::Req(req) - | crate::util::OptVersionReq::Locked(_, req) - | crate::util::OptVersionReq::Precise(_, req) => { - req.comparators.len() == 1 && rendered.starts_with('^') - } + OptVersionReq::Any => false, + OptVersionReq::Req(req) + | OptVersionReq::Locked(_, req) + | OptVersionReq::Precise(_, req) => req.comparators.len() == 1 && rendered.starts_with('^'), }; if strip_prefix { rendered.remove(0); @@ -469,9 +467,8 @@ fn resolve_features( continue; }; for activated in current_activated.iter().rev().filter_map(|f| match f { - crate::core::FeatureValue::Feature(name) => Some(name), - crate::core::FeatureValue::Dep { .. } - | crate::core::FeatureValue::DepFeature { .. } => None, + FeatureValue::Feature(name) => Some(name), + FeatureValue::Dep { .. } | FeatureValue::DepFeature { .. } => None, }) { let Some(status) = resolved.get_mut(activated) else { continue; diff --git a/src/cargo/ops/registry/login.rs b/src/cargo/ops/registry/login.rs index 0db134a6da60..4087317bb281 100644 --- a/src/cargo/ops/registry/login.rs +++ b/src/cargo/ops/registry/login.rs @@ -26,8 +26,15 @@ pub fn registry_login( ) -> CargoResult<()> { let source_ids = get_source_id(gctx, reg_or_index)?; - let login_url = match registry(gctx, token_from_cmdline.clone(), reg_or_index, false, None) { - Ok((registry, _)) => Some(format!("{}/me", registry.host())), + let login_url = match registry( + gctx, + &source_ids, + token_from_cmdline.clone(), + reg_or_index, + false, + None, + ) { + Ok(registry) => Some(format!("{}/me", registry.host())), Err(e) if e.is::() => e .downcast::() .unwrap() diff --git a/src/cargo/ops/registry/mod.rs b/src/cargo/ops/registry/mod.rs index eb49dccb4d97..7a8d46db5b59 100644 --- a/src/cargo/ops/registry/mod.rs +++ b/src/cargo/ops/registry/mod.rs @@ -2,6 +2,7 @@ //! //! [1]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html +mod info; mod login; mod logout; mod owner; @@ -18,7 +19,7 @@ use cargo_credential::{Operation, Secret}; use crates_io::Registry; use url::Url; -use crate::core::SourceId; +use crate::core::{PackageId, SourceId}; use crate::sources::source::Source; use crate::sources::{RegistrySource, SourceConfigMap}; use crate::util::auth; @@ -27,6 +28,7 @@ use crate::util::context::{GlobalContext, PathAndArgs}; use crate::util::errors::CargoResult; use crate::util::network::http::http_handle; +pub use self::info::info; pub use self::login::registry_login; pub use self::logout::registry_logout; pub use self::owner::modify_owners; @@ -116,13 +118,12 @@ impl RegistryCredentialConfig { /// * `token_required`: If `true`, the token will be set. fn registry( gctx: &GlobalContext, + source_ids: &RegistrySourceIds, token_from_cmdline: Option>, reg_or_index: Option<&RegistryOrIndex>, force_update: bool, token_required: Option>, -) -> CargoResult<(Registry, RegistrySourceIds)> { - let source_ids = get_source_id(gctx, reg_or_index)?; - +) -> CargoResult { let is_index = reg_or_index.map(|v| v.is_index()).unwrap_or_default(); if is_index && token_required.is_some() && token_from_cmdline.is_none() { bail!("command-line argument --index requires --token to be specified"); @@ -165,9 +166,11 @@ fn registry( None }; let handle = http_handle(gctx)?; - Ok(( - Registry::new_handle(api_host, token, handle, cfg.auth_required), - source_ids, + Ok(Registry::new_handle( + api_host, + token, + handle, + cfg.auth_required, )) } @@ -215,6 +218,64 @@ fn get_source_id( } } +fn get_source_id_with_package_id( + gctx: &GlobalContext, + package_id: Option, + reg_or_index: Option<&RegistryOrIndex>, +) -> CargoResult<(bool, RegistrySourceIds)> { + let (use_package_source_id, sid) = match (®_or_index, package_id) { + (None, Some(package_id)) => (true, package_id.source_id()), + (None, None) => (false, SourceId::crates_io(gctx)?), + (Some(RegistryOrIndex::Index(url)), None) => (false, SourceId::for_registry(url)?), + (Some(RegistryOrIndex::Registry(r)), None) => (false, SourceId::alt_registry(gctx, r)?), + (Some(reg_or_index), Some(package_id)) => { + let sid = match reg_or_index { + RegistryOrIndex::Index(url) => SourceId::for_registry(url)?, + RegistryOrIndex::Registry(r) => SourceId::alt_registry(gctx, r)?, + }; + let package_source_id = package_id.source_id(); + // Same registry, use the package's source. + if sid == package_source_id { + (true, sid) + } else { + let pkg_source_replacement_sid = SourceConfigMap::new(gctx)? + .load(package_source_id, &HashSet::new())? + .replaced_source_id(); + // Use the package's source if the specified registry is a replacement for the package's source. + if pkg_source_replacement_sid == sid { + (true, package_source_id) + } else { + (false, sid) + } + } + } + }; + // Load source replacements that are built-in to Cargo. + let builtin_replacement_sid = SourceConfigMap::empty(gctx)? + .load(sid, &HashSet::new())? + .replaced_source_id(); + let replacement_sid = SourceConfigMap::new(gctx)? + .load(sid, &HashSet::new())? + .replaced_source_id(); + // Check if the user has configured source-replacement for the registry we are querying. + if reg_or_index.is_none() && replacement_sid != builtin_replacement_sid { + // Neither --registry nor --index was passed and the user has configured source-replacement. + if let Some(replacement_name) = replacement_sid.alt_registry_key() { + bail!("crates-io is replaced with remote registry {replacement_name};\ninclude `--registry {replacement_name}` or `--registry crates-io`"); + } else { + bail!("crates-io is replaced with non-remote-registry source {replacement_sid};\ninclude `--registry crates-io` to use crates.io"); + } + } else { + Ok(( + use_package_source_id, + RegistrySourceIds { + original: sid, + replacement: builtin_replacement_sid, + }, + )) + } +} + struct RegistrySourceIds { /// Use when looking up the auth token, or writing out `Cargo.lock` original: SourceId, diff --git a/src/cargo/ops/registry/owner.rs b/src/cargo/ops/registry/owner.rs index 106410311393..c2aab7a9f264 100644 --- a/src/cargo/ops/registry/owner.rs +++ b/src/cargo/ops/registry/owner.rs @@ -36,8 +36,10 @@ pub fn modify_owners(gctx: &GlobalContext, opts: &OwnersOptions) -> CargoResult< let operation = Operation::Owners { name: &name }; - let (mut registry, _) = super::registry( + let source_ids = super::get_source_id(gctx, opts.reg_or_index.as_ref())?; + let mut registry = super::registry( gctx, + &source_ids, opts.token.as_ref().map(Secret::as_deref), opts.reg_or_index.as_ref(), true, diff --git a/src/cargo/ops/registry/publish.rs b/src/cargo/ops/registry/publish.rs index ac7e4f459310..4ce5e36a50ae 100644 --- a/src/cargo/ops/registry/publish.rs +++ b/src/cargo/ops/registry/publish.rs @@ -130,14 +130,16 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> { } val => val, }; - let (mut registry, reg_ids) = super::registry( + let source_ids = super::get_source_id(opts.gctx, reg_or_index.as_ref())?; + let mut registry = super::registry( opts.gctx, + &source_ids, opts.token.as_ref().map(Secret::as_deref), reg_or_index.as_ref(), true, Some(operation).filter(|_| !opts.dry_run), )?; - verify_dependencies(pkg, ®istry, reg_ids.original)?; + verify_dependencies(pkg, ®istry, source_ids.original)?; // Prepare a tarball, with a non-suppressible warning if metadata // is missing since this is being put online. @@ -169,7 +171,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> { }; registry.set_token(Some(auth::auth_token( &opts.gctx, - ®_ids.original, + &source_ids.original, None, operation, vec![], @@ -185,7 +187,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> { pkg, tarball.file(), &mut registry, - reg_ids.original, + source_ids.original, opts.dry_run, )?; if !opts.dry_run { @@ -198,7 +200,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> { }; if 0 < timeout { let timeout = Duration::from_secs(timeout); - wait_for_publish(opts.gctx, reg_ids.original, pkg, timeout)?; + wait_for_publish(opts.gctx, source_ids.original, pkg, timeout)?; } } diff --git a/src/cargo/ops/registry/search.rs b/src/cargo/ops/registry/search.rs index 9d1d1d5b0dcc..41e12e36e464 100644 --- a/src/cargo/ops/registry/search.rs +++ b/src/cargo/ops/registry/search.rs @@ -20,8 +20,9 @@ pub fn search( reg_or_index: Option, limit: u32, ) -> CargoResult<()> { - let (mut registry, source_ids) = - super::registry(gctx, None, reg_or_index.as_ref(), false, None)?; + let source_ids = super::get_source_id(gctx, reg_or_index.as_ref())?; + let mut registry = + super::registry(gctx, &source_ids, None, reg_or_index.as_ref(), false, None)?; let (crates, total_crates) = registry.search(query, limit).with_context(|| { format!( "failed to retrieve search results from the registry at {}", diff --git a/src/cargo/ops/registry/yank.rs b/src/cargo/ops/registry/yank.rs index 032939a75b33..2e92316457b5 100644 --- a/src/cargo/ops/registry/yank.rs +++ b/src/cargo/ops/registry/yank.rs @@ -47,8 +47,10 @@ pub fn yank( } }; - let (mut registry, _) = super::registry( + let source_ids = super::get_source_id(gctx, reg_or_index.as_ref())?; + let mut registry = super::registry( gctx, + &source_ids, token.as_ref().map(Secret::as_deref), reg_or_index.as_ref(), true,