Skip to content

Commit 5c2bf8a

Browse files
committed
Make cargo package's registry validation private again
1 parent 2f54df2 commit 5c2bf8a

File tree

2 files changed

+93
-86
lines changed

2 files changed

+93
-86
lines changed

src/cargo/ops/cargo_package.rs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::{BTreeSet, HashMap};
1+
use std::collections::{BTreeSet, HashMap, HashSet};
22
use std::fs::{self, File};
33
use std::io::prelude::*;
44
use std::io::SeekFrom;
@@ -13,9 +13,9 @@ use crate::core::resolver::CliFeatures;
1313
use crate::core::resolver::HasDevUnits;
1414
use crate::core::{Feature, PackageIdSpecQuery, Shell, Verbosity, Workspace};
1515
use crate::core::{Package, PackageId, PackageSet, Resolve, SourceId};
16-
use crate::ops::registry::infer_registry;
16+
use crate::ops::registry::{infer_registry, RegistryOrIndex};
1717
use crate::sources::registry::index::{IndexPackage, RegistryDependency};
18-
use crate::sources::PathSource;
18+
use crate::sources::{PathSource, SourceConfigMap, CRATES_IO_REGISTRY};
1919
use crate::util::cache_lock::CacheLockMode;
2020
use crate::util::context::JobsConfig;
2121
use crate::util::errors::CargoResult;
@@ -24,7 +24,7 @@ use crate::util::{
2424
self, human_readable_bytes, restricted_names, FileLock, Filesystem, GlobalContext, Graph,
2525
};
2626
use crate::{drop_println, ops};
27-
use anyhow::Context as _;
27+
use anyhow::{bail, Context as _};
2828
use cargo_util::paths;
2929
use flate2::read::GzDecoder;
3030
use flate2::{Compression, GzBuilder};
@@ -197,7 +197,7 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
197197
}
198198

199199
let just_pkgs: Vec<_> = pkgs.iter().map(|p| p.0).collect();
200-
let publish_reg = infer_registry(ws.gctx(), &just_pkgs, opts.reg_or_index.clone())?;
200+
let publish_reg = get_registry(ws.gctx(), &just_pkgs, opts.reg_or_index.clone())?;
201201
debug!("packaging for registry {publish_reg}");
202202

203203
let mut local_reg = if ws.gctx().cli_unstable().package_workspace {
@@ -246,6 +246,60 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
246246
Ok(outputs.into_iter().map(|x| x.2).collect())
247247
}
248248

249+
/// Determine which registry the packages are for.
250+
///
251+
/// The registry only affects the built packages if there are dependencies within the
252+
/// packages that we're packaging: if we're packaging foo-bin and foo-lib, and foo-bin
253+
/// depends on foo-lib, then the foo-lib entry in foo-bin's lockfile will depend on the
254+
/// registry that we're building packages for.
255+
pub(crate) fn get_registry(
256+
gctx: &GlobalContext,
257+
pkgs: &[&Package],
258+
reg_or_index: Option<RegistryOrIndex>,
259+
) -> CargoResult<SourceId> {
260+
let reg_or_index = match reg_or_index {
261+
Some(r) => Some(r),
262+
None => infer_registry(pkgs)?,
263+
};
264+
265+
let reg = reg_or_index
266+
.clone()
267+
.unwrap_or_else(|| RegistryOrIndex::Registry(CRATES_IO_REGISTRY.to_owned()));
268+
269+
// Validate the registry against the packages' allow-lists. For backwards compatibility, we
270+
// skip this if only a single package is being published (because in that case the registry
271+
// doesn't affect the packaging step).
272+
if pkgs.len() > 1 {
273+
if let RegistryOrIndex::Registry(reg_name) = &reg {
274+
for pkg in pkgs {
275+
if let Some(allowed) = pkg.publish().as_ref() {
276+
if !allowed.iter().any(|a| a == reg_name) {
277+
bail!(
278+
"`{}` cannot be packaged.\n\
279+
The registry `{}` is not listed in the `package.publish` value in Cargo.toml.",
280+
pkg.name(),
281+
reg_name
282+
);
283+
}
284+
}
285+
}
286+
}
287+
}
288+
289+
let sid = match reg {
290+
RegistryOrIndex::Index(url) => SourceId::for_registry(&url)?,
291+
RegistryOrIndex::Registry(reg) if reg == CRATES_IO_REGISTRY => SourceId::crates_io(gctx)?,
292+
RegistryOrIndex::Registry(reg) => SourceId::alt_registry(gctx, &reg)?,
293+
};
294+
295+
// Load source replacements that are built-in to Cargo.
296+
let sid = SourceConfigMap::empty(gctx)?
297+
.load(sid, &HashSet::new())?
298+
.replaced_source_id();
299+
300+
Ok(sid)
301+
}
302+
249303
/// Just the part of the dependency graph that's between the packages we're packaging.
250304
/// (Is the package name a good key? Does it uniquely identify packages?)
251305
#[derive(Clone, Debug, Default)]

src/cargo/ops/registry/mod.rs

Lines changed: 34 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use url::Url;
2121

2222
use crate::core::{Package, PackageId, SourceId};
2323
use crate::sources::source::Source;
24-
use crate::sources::{RegistrySource, SourceConfigMap, CRATES_IO_REGISTRY};
24+
use crate::sources::{RegistrySource, SourceConfigMap};
2525
use crate::util::auth;
2626
use crate::util::cache_lock::CacheLockMode;
2727
use crate::util::context::{GlobalContext, PathAndArgs};
@@ -191,7 +191,7 @@ fn registry(
191191
///
192192
/// The return value is a pair of `SourceId`s: The first may be a built-in replacement of
193193
/// crates.io (such as index.crates.io), while the second is always the original source.
194-
fn get_source_id(
194+
pub(crate) fn get_source_id(
195195
gctx: &GlobalContext,
196196
reg_or_index: Option<&RegistryOrIndex>,
197197
) -> CargoResult<RegistrySourceIds> {
@@ -324,87 +324,40 @@ pub(crate) struct RegistrySourceIds {
324324
}
325325

326326
/// If this set of packages has an unambiguous publish registry, find it.
327-
pub(crate) fn infer_registry(
328-
gctx: &GlobalContext,
329-
pkgs: &[&Package],
330-
reg_or_index: Option<RegistryOrIndex>,
331-
) -> CargoResult<SourceId> {
332-
let reg_or_index = match reg_or_index {
333-
Some(r) => r,
334-
None => {
335-
if pkgs[1..].iter().all(|p| p.publish() == pkgs[0].publish()) {
336-
// If all packages have the same publish settings, we take that as the default.
337-
match pkgs[0].publish().as_deref() {
338-
Some([unique_pkg_reg]) => RegistryOrIndex::Registry(unique_pkg_reg.to_owned()),
339-
None | Some([]) => RegistryOrIndex::Registry(CRATES_IO_REGISTRY.to_owned()),
340-
Some([reg, ..]) if pkgs.len() == 1 => {
341-
// For backwards compatibility, avoid erroring if there's only one package.
342-
// The registry doesn't affect packaging in this case.
343-
RegistryOrIndex::Registry(reg.to_owned())
344-
}
345-
Some(regs) => {
346-
let mut regs: Vec<_> = regs.iter().map(|s| format!("\"{}\"", s)).collect();
347-
regs.sort();
348-
regs.dedup();
349-
// unwrap: the match block ensures that there's more than one reg.
350-
let (last_reg, regs) = regs.split_last().unwrap();
351-
bail!(
352-
"--registry is required to disambiguate between {} or {} registries",
353-
regs.join(", "),
354-
last_reg
355-
)
356-
}
357-
}
358-
} else {
359-
let common_regs = pkgs
360-
.iter()
361-
// `None` means "all registries", so drop them instead of including them
362-
// in the intersection.
363-
.filter_map(|p| p.publish().as_deref())
364-
.map(|p| p.iter().collect::<HashSet<_>>())
365-
.reduce(|xs, ys| xs.intersection(&ys).cloned().collect())
366-
.unwrap_or_default();
367-
if common_regs.is_empty() {
368-
bail!("conflicts between `package.publish` fields in the selected packages");
369-
} else {
370-
bail!(
371-
"--registry is required because not all `package.publish` settings agree",
372-
);
373-
}
327+
pub(crate) fn infer_registry(pkgs: &[&Package]) -> CargoResult<Option<RegistryOrIndex>> {
328+
if pkgs[1..].iter().all(|p| p.publish() == pkgs[0].publish()) {
329+
// If all packages have the same publish settings, we take that as the default.
330+
match pkgs[0].publish().as_deref() {
331+
Some([unique_pkg_reg]) => {
332+
Ok(Some(RegistryOrIndex::Registry(unique_pkg_reg.to_owned())))
374333
}
375-
}
376-
};
377-
378-
// Validate the registry against the packages' allow-lists. For backwards compatibility, we
379-
// skip this if only a single package is being published (because in that case the registry
380-
// doesn't affect the packaging step).
381-
if pkgs.len() > 1 {
382-
if let RegistryOrIndex::Registry(reg_name) = &reg_or_index {
383-
for pkg in pkgs {
384-
if let Some(allowed) = pkg.publish().as_ref() {
385-
if !allowed.iter().any(|a| a == reg_name) {
386-
bail!(
387-
"`{}` cannot be packaged.\n\
388-
The registry `{}` is not listed in the `package.publish` value in Cargo.toml.",
389-
pkg.name(),
390-
reg_name
391-
);
392-
}
393-
}
334+
None | Some([]) => Ok(None),
335+
Some(regs) => {
336+
let mut regs: Vec<_> = regs.iter().map(|s| format!("\"{}\"", s)).collect();
337+
regs.sort();
338+
regs.dedup();
339+
// unwrap: the match block ensures that there's more than one reg.
340+
let (last_reg, regs) = regs.split_last().unwrap();
341+
bail!(
342+
"--registry is required to disambiguate between {} or {} registries",
343+
regs.join(", "),
344+
last_reg
345+
)
394346
}
395347
}
348+
} else {
349+
let common_regs = pkgs
350+
.iter()
351+
// `None` means "all registries", so drop them instead of including them
352+
// in the intersection.
353+
.filter_map(|p| p.publish().as_deref())
354+
.map(|p| p.iter().collect::<HashSet<_>>())
355+
.reduce(|xs, ys| xs.intersection(&ys).cloned().collect())
356+
.unwrap_or_default();
357+
if common_regs.is_empty() {
358+
bail!("conflicts between `package.publish` fields in the selected packages");
359+
} else {
360+
bail!("--registry is required because not all `package.publish` settings agree",);
361+
}
396362
}
397-
398-
let sid = match reg_or_index {
399-
RegistryOrIndex::Index(url) => SourceId::for_registry(&url)?,
400-
RegistryOrIndex::Registry(reg) if reg == CRATES_IO_REGISTRY => SourceId::crates_io(gctx)?,
401-
RegistryOrIndex::Registry(reg) => SourceId::alt_registry(gctx, &reg)?,
402-
};
403-
404-
// Load source replacements that are built-in to Cargo.
405-
let sid = SourceConfigMap::empty(gctx)?
406-
.load(sid, &HashSet::new())?
407-
.replaced_source_id();
408-
409-
Ok(sid)
410363
}

0 commit comments

Comments
 (0)