1
- use std:: collections:: { BTreeSet , HashMap , HashSet } ;
1
+ use std:: collections:: { BTreeSet , HashMap } ;
2
2
use std:: fs:: { self , File } ;
3
3
use std:: io:: prelude:: * ;
4
4
use std:: io:: SeekFrom ;
@@ -13,8 +13,9 @@ use crate::core::resolver::CliFeatures;
13
13
use crate :: core:: resolver:: HasDevUnits ;
14
14
use crate :: core:: { Feature , PackageIdSpecQuery , Shell , Verbosity , Workspace } ;
15
15
use crate :: core:: { Package , PackageId , PackageSet , Resolve , SourceId } ;
16
+ use crate :: ops:: registry:: infer_registry;
16
17
use crate :: sources:: registry:: index:: { IndexPackage , RegistryDependency } ;
17
- use crate :: sources:: { PathSource , SourceConfigMap , CRATES_IO_REGISTRY } ;
18
+ use crate :: sources:: { PathSource , CRATES_IO_REGISTRY } ;
18
19
use crate :: util:: cache_lock:: CacheLockMode ;
19
20
use crate :: util:: context:: JobsConfig ;
20
21
use crate :: util:: errors:: CargoResult ;
@@ -180,89 +181,35 @@ fn create_package(
180
181
/// packages that we're packaging: if we're packaging foo-bin and foo-lib, and foo-bin
181
182
/// depends on foo-lib, then the foo-lib entry in foo-bin's lockfile will depend on the
182
183
/// registry that we're building packages for.
183
- fn infer_registry (
184
+ fn get_registry (
184
185
gctx : & GlobalContext ,
185
186
pkgs : & [ & Package ] ,
186
187
reg_or_index : Option < RegistryOrIndex > ,
187
188
) -> 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
- }
189
+ let reg_or_index = match reg_or_index. clone ( ) {
190
+ Some ( r) => Some ( r) ,
191
+ None => infer_registry ( pkgs) ?,
232
192
} ;
233
193
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 ! (
194
+ // Validate the registry against the packages' allow-lists.
195
+ let reg = reg_or_index
196
+ . clone ( )
197
+ . unwrap_or_else ( || RegistryOrIndex :: Registry ( CRATES_IO_REGISTRY . to_owned ( ) ) ) ;
198
+ if let RegistryOrIndex :: Registry ( reg_name) = reg {
199
+ for pkg in pkgs {
200
+ if let Some ( allowed) = pkg. publish ( ) . as_ref ( ) {
201
+ if !allowed. iter ( ) . any ( |a| a == & reg_name) {
202
+ bail ! (
243
203
"`{}` cannot be packaged.\n \
244
204
The registry `{}` is not listed in the `package.publish` value in Cargo.toml.",
245
205
pkg. name( ) ,
246
206
reg_name
247
207
) ;
248
- }
249
208
}
250
209
}
251
210
}
252
211
}
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)
212
+ Ok ( ops:: registry:: get_source_id ( gctx, reg_or_index. as_ref ( ) ) ?. replacement )
266
213
}
267
214
268
215
/// Packages an entire workspace.
@@ -288,19 +235,34 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
288
235
// below, and will be validated during the verification step.
289
236
}
290
237
238
+ let deps = local_deps ( pkgs. iter ( ) . map ( |( p, f) | ( ( * p) . clone ( ) , f. clone ( ) ) ) ) ;
291
239
let just_pkgs: Vec < _ > = pkgs. iter ( ) . map ( |p| p. 0 ) . collect ( ) ;
292
- let publish_reg = infer_registry ( ws. gctx ( ) , & just_pkgs, opts. reg_or_index . clone ( ) ) ?;
293
- debug ! ( "packaging for registry {publish_reg}" ) ;
240
+
241
+ let sid = match get_registry ( ws. gctx ( ) , & just_pkgs, opts. reg_or_index . clone ( ) ) {
242
+ Ok ( sid) => {
243
+ debug ! ( "packaging for registry {}" , sid) ;
244
+ Some ( sid)
245
+ }
246
+ Err ( e) => {
247
+ if deps. has_no_dependencies ( ) && opts. reg_or_index . is_none ( ) {
248
+ // The publish registry doesn't matter unless there are local dependencies,
249
+ // so ignore any errors if we don't need it. If they explicitly passed a registry
250
+ // on the CLI, we check it no matter what.
251
+ None
252
+ } else {
253
+ return Err ( e) ;
254
+ }
255
+ }
256
+ } ;
294
257
295
258
let mut local_reg = if ws. gctx ( ) . cli_unstable ( ) . package_workspace {
296
259
let reg_dir = ws. target_dir ( ) . join ( "package" ) . join ( "tmp-registry" ) ;
297
- Some ( TmpRegistry :: new ( ws. gctx ( ) , reg_dir, publish_reg) ?)
260
+ sid. map ( |sid| TmpRegistry :: new ( ws. gctx ( ) , reg_dir, sid) )
261
+ . transpose ( ) ?
298
262
} else {
299
263
None
300
264
} ;
301
265
302
- let deps = local_deps ( pkgs. iter ( ) . map ( |( p, f) | ( ( * p) . clone ( ) , f. clone ( ) ) ) ) ;
303
-
304
266
// Packages need to be created in dependency order, because dependencies must
305
267
// be added to our local overlay before we can create lockfiles that depend on them.
306
268
let sorted_pkgs = deps. sort ( ) ;
@@ -354,6 +316,12 @@ impl LocalDependencies {
354
316
. map ( |name| self . packages [ & name] . clone ( ) )
355
317
. collect ( )
356
318
}
319
+
320
+ pub fn has_no_dependencies ( & self ) -> bool {
321
+ self . graph
322
+ . iter ( )
323
+ . all ( |node| self . graph . edges ( node) . next ( ) . is_none ( ) )
324
+ }
357
325
}
358
326
359
327
/// Build just the part of the dependency graph that's between the given packages,
0 commit comments