1- use std:: collections:: { BTreeSet , HashMap , HashSet } ;
1+ use std:: collections:: { BTreeSet , HashMap } ;
22use std:: fs:: { self , File } ;
33use std:: io:: prelude:: * ;
44use std:: io:: SeekFrom ;
55use std:: path:: { Path , PathBuf } ;
66use std:: sync:: Arc ;
77use std:: task:: Poll ;
88
9- use super :: RegistryOrIndex ;
109use crate :: core:: compiler:: { BuildConfig , CompileMode , DefaultExecutor , Executor } ;
1110use crate :: core:: dependency:: DepKind ;
1211use crate :: core:: manifest:: Target ;
@@ -15,8 +14,9 @@ use crate::core::resolver::HasDevUnits;
1514use crate :: core:: { Feature , PackageIdSpecQuery , Shell , Verbosity , Workspace } ;
1615use crate :: core:: { Package , PackageId , PackageSet , Resolve , SourceId } ;
1716use crate :: ops:: lockfile:: LOCKFILE_NAME ;
17+ use crate :: ops:: registry:: { infer_registry, RegistryOrIndex } ;
1818use crate :: sources:: registry:: index:: { IndexPackage , RegistryDependency } ;
19- use crate :: sources:: { PathSource , SourceConfigMap , CRATES_IO_REGISTRY } ;
19+ use crate :: sources:: { PathSource , CRATES_IO_REGISTRY } ;
2020use crate :: util:: cache_lock:: CacheLockMode ;
2121use crate :: util:: context:: JobsConfig ;
2222use crate :: util:: errors:: CargoResult ;
@@ -174,97 +174,6 @@ 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- }
230- }
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- }
250- }
251- }
252- }
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)
266- }
267-
268177/// Packages an entire workspace.
269178///
270179/// Returns the generated package files. If `opts.list` is true, skips
@@ -293,19 +202,28 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
293202 // below, and will be validated during the verification step.
294203 }
295204
205+ let deps = local_deps ( pkgs. iter ( ) . map ( |( p, f) | ( ( * p) . clone ( ) , f. clone ( ) ) ) ) ;
296206 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 ( ) ) ?;
298- debug ! ( "packaging for registry {publish_reg}" ) ;
207+
208+ // The publish registry doesn't matter unless there are local dependencies,
209+ // so only try to get one if we need it. If they explicitly passed a
210+ // registry on the CLI, we check it no matter what.
211+ let sid = if deps. has_no_dependencies ( ) && opts. reg_or_index . is_none ( ) {
212+ None
213+ } else {
214+ let sid = get_registry ( ws. gctx ( ) , & just_pkgs, opts. reg_or_index . clone ( ) ) ?;
215+ debug ! ( "packaging for registry {}" , sid) ;
216+ Some ( sid)
217+ } ;
299218
300219 let mut local_reg = if ws. gctx ( ) . cli_unstable ( ) . package_workspace {
301220 let reg_dir = ws. target_dir ( ) . join ( "package" ) . join ( "tmp-registry" ) ;
302- Some ( TmpRegistry :: new ( ws. gctx ( ) , reg_dir, publish_reg) ?)
221+ sid. map ( |sid| TmpRegistry :: new ( ws. gctx ( ) , reg_dir, sid) )
222+ . transpose ( ) ?
303223 } else {
304224 None
305225 } ;
306226
307- let deps = local_deps ( pkgs. iter ( ) . map ( |( p, f) | ( ( * p) . clone ( ) , f. clone ( ) ) ) ) ;
308-
309227 // Packages need to be created in dependency order, because dependencies must
310228 // be added to our local overlay before we can create lockfiles that depend on them.
311229 let sorted_pkgs = deps. sort ( ) ;
@@ -325,7 +243,9 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
325243 } else {
326244 let tarball = create_package ( ws, & pkg, ar_files, local_reg. as_ref ( ) ) ?;
327245 if let Some ( local_reg) = local_reg. as_mut ( ) {
328- local_reg. add_package ( ws, & pkg, & tarball) ?;
246+ if pkg. publish ( ) != & Some ( Vec :: new ( ) ) {
247+ local_reg. add_package ( ws, & pkg, & tarball) ?;
248+ }
329249 }
330250 outputs. push ( ( pkg, opts, tarball) ) ;
331251 }
@@ -343,6 +263,46 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
343263 Ok ( outputs. into_iter ( ) . map ( |x| x. 2 ) . collect ( ) )
344264}
345265
266+ /// Determine which registry the packages are for.
267+ ///
268+ /// The registry only affects the built packages if there are dependencies within the
269+ /// packages that we're packaging: if we're packaging foo-bin and foo-lib, and foo-bin
270+ /// depends on foo-lib, then the foo-lib entry in foo-bin's lockfile will depend on the
271+ /// registry that we're building packages for.
272+ fn get_registry (
273+ gctx : & GlobalContext ,
274+ pkgs : & [ & Package ] ,
275+ reg_or_index : Option < RegistryOrIndex > ,
276+ ) -> CargoResult < SourceId > {
277+ let reg_or_index = match reg_or_index. clone ( ) {
278+ Some ( r) => Some ( r) ,
279+ None => infer_registry ( pkgs) ?,
280+ } ;
281+
282+ // Validate the registry against the packages' allow-lists.
283+ let reg = reg_or_index
284+ . clone ( )
285+ . unwrap_or_else ( || RegistryOrIndex :: Registry ( CRATES_IO_REGISTRY . to_owned ( ) ) ) ;
286+ if let RegistryOrIndex :: Registry ( reg_name) = reg {
287+ for pkg in pkgs {
288+ if let Some ( allowed) = pkg. publish ( ) . as_ref ( ) {
289+ // If allowed is empty (i.e. package.publish is false), we let it slide.
290+ // This allows packaging unpublishable packages (although packaging might
291+ // fail later if the unpublishable package is a dependency of something else).
292+ if !allowed. is_empty ( ) && !allowed. iter ( ) . any ( |a| a == & reg_name) {
293+ bail ! (
294+ "`{}` cannot be packaged.\n \
295+ The registry `{}` is not listed in the `package.publish` value in Cargo.toml.",
296+ pkg. name( ) ,
297+ reg_name
298+ ) ;
299+ }
300+ }
301+ }
302+ }
303+ Ok ( ops:: registry:: get_source_id ( gctx, reg_or_index. as_ref ( ) ) ?. replacement )
304+ }
305+
346306/// Just the part of the dependency graph that's between the packages we're packaging.
347307/// (Is the package name a good key? Does it uniquely identify packages?)
348308#[ derive( Clone , Debug , Default ) ]
@@ -359,6 +319,12 @@ impl LocalDependencies {
359319 . map ( |name| self . packages [ & name] . clone ( ) )
360320 . collect ( )
361321 }
322+
323+ pub fn has_no_dependencies ( & self ) -> bool {
324+ self . graph
325+ . iter ( )
326+ . all ( |node| self . graph . edges ( node) . next ( ) . is_none ( ) )
327+ }
362328}
363329
364330/// Build just the part of the dependency graph that's between the given packages,
0 commit comments