Skip to content

Commit

Permalink
refactor: move info into registry mod
Browse files Browse the repository at this point in the history
Added a new API called get_source_id_with_package_id.
  • Loading branch information
Rustin170506 committed Jul 7, 2024
1 parent 476969f commit 62fd2b0
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 192 deletions.
2 changes: 1 addition & 1 deletion src/bin/cargo/commands/info.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
185 changes: 29 additions & 156 deletions src/cargo/ops/cargo_info/mod.rs → src/cargo/ops/registry/info/mod.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<Option<Vec<String>>> {
// 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 {
Expand All @@ -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<RegistryOrIndex>,
package_id: Option<PackageId>,
) -> CargoResult<(bool, RegistrySourceIds)> {
let (use_package_source_id, sid) = match (&reg_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<Option<CratesIoRegistry>> {
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<PackageId>,
gctx: &GlobalContext,
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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())
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 9 additions & 2 deletions src/cargo/ops/registry/login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<AuthorizationError>() => e
.downcast::<AuthorizationError>()
.unwrap()
Expand Down
Loading

0 comments on commit 62fd2b0

Please sign in to comment.