Skip to content

Commit 37812e3

Browse files
committed
Split infer_registry into inference and validation parts.
1 parent 7919bda commit 37812e3

File tree

1 file changed

+89
-87
lines changed

1 file changed

+89
-87
lines changed

src/cargo/ops/cargo_package.rs

Lines changed: 89 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use std::path::{Path, PathBuf};
66
use std::sync::Arc;
77
use std::task::Poll;
88

9-
use super::RegistryOrIndex;
109
use crate::core::compiler::{BuildConfig, CompileMode, DefaultExecutor, Executor};
1110
use crate::core::dependency::DepKind;
1211
use crate::core::manifest::Target;
@@ -15,6 +14,7 @@ use crate::core::resolver::HasDevUnits;
1514
use crate::core::{Feature, PackageIdSpecQuery, Shell, Verbosity, Workspace};
1615
use crate::core::{Package, PackageId, PackageSet, Resolve, SourceId};
1716
use crate::ops::lockfile::LOCKFILE_NAME;
17+
use crate::ops::registry::RegistryOrIndex;
1818
use crate::sources::registry::index::{IndexPackage, RegistryDependency};
1919
use crate::sources::{PathSource, SourceConfigMap, CRATES_IO_REGISTRY};
2020
use crate::util::cache_lock::CacheLockMode;
@@ -174,95 +174,43 @@ fn create_package(
174174
return Ok(dst);
175175
}
176176

177-
/// Determine which registry the packages are for.
178-
///
179-
/// The registry only affects the built packages if there are dependencies within the
180-
/// packages that we're packaging: if we're packaging foo-bin and foo-lib, and foo-bin
181-
/// depends on foo-lib, then the foo-lib entry in foo-bin's lockfile will depend on the
182-
/// registry that we're building packages for.
183-
fn infer_registry(
184-
gctx: &GlobalContext,
185-
pkgs: &[&Package],
186-
reg_or_index: Option<RegistryOrIndex>,
187-
) -> CargoResult<SourceId> {
188-
let reg_or_index = match reg_or_index {
189-
Some(r) => r,
190-
None => {
191-
if pkgs[1..].iter().all(|p| p.publish() == pkgs[0].publish()) {
192-
// If all packages have the same publish settings, we take that as the default.
193-
match pkgs[0].publish().as_deref() {
194-
Some([unique_pkg_reg]) => RegistryOrIndex::Registry(unique_pkg_reg.to_owned()),
195-
None | Some([]) => RegistryOrIndex::Registry(CRATES_IO_REGISTRY.to_owned()),
196-
Some([reg, ..]) if pkgs.len() == 1 => {
197-
// For backwards compatibility, avoid erroring if there's only one package.
198-
// The registry doesn't affect packaging in this case.
199-
RegistryOrIndex::Registry(reg.to_owned())
200-
}
201-
Some(regs) => {
202-
let mut regs: Vec<_> = regs.iter().map(|s| format!("\"{}\"", s)).collect();
203-
regs.sort();
204-
regs.dedup();
205-
// unwrap: the match block ensures that there's more than one reg.
206-
let (last_reg, regs) = regs.split_last().unwrap();
207-
bail!(
208-
"--registry is required to disambiguate between {} or {} registries",
209-
regs.join(", "),
210-
last_reg
211-
)
212-
}
213-
}
214-
} else {
215-
let common_regs = pkgs
216-
.iter()
217-
// `None` means "all registries", so drop them instead of including them
218-
// in the intersection.
219-
.filter_map(|p| p.publish().as_deref())
220-
.map(|p| p.iter().collect::<HashSet<_>>())
221-
.reduce(|xs, ys| xs.intersection(&ys).cloned().collect())
222-
.unwrap_or_default();
223-
if common_regs.is_empty() {
224-
bail!("conflicts between `package.publish` fields in the selected packages");
225-
} else {
226-
bail!(
227-
"--registry is required because not all `package.publish` settings agree",
228-
);
229-
}
177+
/// If this set of packages has an unambiguous publish registry, find it.
178+
pub(crate) fn infer_registry(pkgs: &[&Package]) -> CargoResult<Option<RegistryOrIndex>> {
179+
if pkgs[1..].iter().all(|p| p.publish() == pkgs[0].publish()) {
180+
// If all packages have the same publish settings, we take that as the default.
181+
match pkgs[0].publish().as_deref() {
182+
Some([unique_pkg_reg]) => {
183+
Ok(Some(RegistryOrIndex::Registry(unique_pkg_reg.to_owned())))
230184
}
231-
}
232-
};
233-
234-
// Validate the registry against the packages' allow-lists. For backwards compatibility, we
235-
// skip this if only a single package is being published (because in that case the registry
236-
// doesn't affect the packaging step).
237-
if pkgs.len() > 1 {
238-
if let RegistryOrIndex::Registry(reg_name) = &reg_or_index {
239-
for pkg in pkgs {
240-
if let Some(allowed) = pkg.publish().as_ref() {
241-
if !allowed.iter().any(|a| a == reg_name) {
242-
bail!(
243-
"`{}` cannot be packaged.\n\
244-
The registry `{}` is not listed in the `package.publish` value in Cargo.toml.",
245-
pkg.name(),
246-
reg_name
247-
);
248-
}
249-
}
185+
None | Some([]) => Ok(None),
186+
Some(regs) => {
187+
let mut regs: Vec<_> = regs.iter().map(|s| format!("\"{}\"", s)).collect();
188+
regs.sort();
189+
regs.dedup();
190+
// unwrap: the match block ensures that there's more than one reg.
191+
let (last_reg, regs) = regs.split_last().unwrap();
192+
bail!(
193+
"--registry is required to disambiguate between {} or {} registries",
194+
regs.join(", "),
195+
last_reg
196+
)
250197
}
251198
}
199+
} else {
200+
let common_regs = pkgs
201+
.iter()
202+
// `None` means "all registries", so drop them instead of including them
203+
// in the intersection.
204+
.filter_map(|p| p.publish().as_deref())
205+
.map(|p| p.iter().collect::<HashSet<_>>())
206+
.reduce(|xs, ys| xs.intersection(&ys).cloned().collect())
207+
.unwrap_or_default();
208+
if common_regs.is_empty() {
209+
bail!("conflicts between `package.publish` fields in the selected packages");
210+
} else {
211+
bail!("--registry is required because not all `package.publish` settings agree",);
212+
}
252213
}
253-
254-
let sid = match reg_or_index {
255-
RegistryOrIndex::Index(url) => SourceId::for_registry(&url)?,
256-
RegistryOrIndex::Registry(reg) if reg == CRATES_IO_REGISTRY => SourceId::crates_io(gctx)?,
257-
RegistryOrIndex::Registry(reg) => SourceId::alt_registry(gctx, &reg)?,
258-
};
259-
260-
// Load source replacements that are built-in to Cargo.
261-
let sid = SourceConfigMap::empty(gctx)?
262-
.load(sid, &HashSet::new())?
263-
.replaced_source_id();
264-
265-
Ok(sid)
266214
}
267215

268216
/// Packages an entire workspace.
@@ -294,7 +242,7 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
294242
}
295243

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

300248
let mut local_reg = if ws.gctx().cli_unstable().package_workspace {
@@ -343,6 +291,60 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
343291
Ok(outputs.into_iter().map(|x| x.2).collect())
344292
}
345293

294+
/// Determine which registry the packages are for.
295+
///
296+
/// The registry only affects the built packages if there are dependencies within the
297+
/// packages that we're packaging: if we're packaging foo-bin and foo-lib, and foo-bin
298+
/// depends on foo-lib, then the foo-lib entry in foo-bin's lockfile will depend on the
299+
/// registry that we're building packages for.
300+
pub(crate) fn get_registry(
301+
gctx: &GlobalContext,
302+
pkgs: &[&Package],
303+
reg_or_index: Option<RegistryOrIndex>,
304+
) -> CargoResult<SourceId> {
305+
let reg_or_index = match reg_or_index {
306+
Some(r) => Some(r),
307+
None => infer_registry(pkgs)?,
308+
};
309+
310+
let reg = reg_or_index
311+
.clone()
312+
.unwrap_or_else(|| RegistryOrIndex::Registry(CRATES_IO_REGISTRY.to_owned()));
313+
314+
// Validate the registry against the packages' allow-lists. For backwards compatibility, we
315+
// skip this if only a single package is being published (because in that case the registry
316+
// doesn't affect the packaging step).
317+
if pkgs.len() > 1 {
318+
if let RegistryOrIndex::Registry(reg_name) = &reg {
319+
for pkg in pkgs {
320+
if let Some(allowed) = pkg.publish().as_ref() {
321+
if !allowed.iter().any(|a| a == reg_name) {
322+
bail!(
323+
"`{}` cannot be packaged.\n\
324+
The registry `{}` is not listed in the `package.publish` value in Cargo.toml.",
325+
pkg.name(),
326+
reg_name
327+
);
328+
}
329+
}
330+
}
331+
}
332+
}
333+
334+
let sid = match reg {
335+
RegistryOrIndex::Index(url) => SourceId::for_registry(&url)?,
336+
RegistryOrIndex::Registry(reg) if reg == CRATES_IO_REGISTRY => SourceId::crates_io(gctx)?,
337+
RegistryOrIndex::Registry(reg) => SourceId::alt_registry(gctx, &reg)?,
338+
};
339+
340+
// Load source replacements that are built-in to Cargo.
341+
let sid = SourceConfigMap::empty(gctx)?
342+
.load(sid, &HashSet::new())?
343+
.replaced_source_id();
344+
345+
Ok(sid)
346+
}
347+
346348
/// Just the part of the dependency graph that's between the packages we're packaging.
347349
/// (Is the package name a good key? Does it uniquely identify packages?)
348350
#[derive(Clone, Debug, Default)]

0 commit comments

Comments
 (0)