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 ;
5
5
use std:: path:: { Path , PathBuf } ;
6
6
use std:: sync:: Arc ;
7
7
use std:: task:: Poll ;
8
8
9
- use super :: RegistryOrIndex ;
10
9
use crate :: core:: compiler:: { BuildConfig , CompileMode , DefaultExecutor , Executor } ;
11
10
use crate :: core:: dependency:: DepKind ;
12
11
use crate :: core:: manifest:: Target ;
@@ -15,8 +14,9 @@ use crate::core::resolver::HasDevUnits;
15
14
use crate :: core:: { Feature , PackageIdSpecQuery , Shell , Verbosity , Workspace } ;
16
15
use crate :: core:: { Package , PackageId , PackageSet , Resolve , SourceId } ;
17
16
use crate :: ops:: lockfile:: LOCKFILE_NAME ;
17
+ use crate :: ops:: registry:: { infer_registry, RegistryOrIndex } ;
18
18
use crate :: sources:: registry:: index:: { IndexPackage , RegistryDependency } ;
19
- use crate :: sources:: { PathSource , SourceConfigMap , CRATES_IO_REGISTRY } ;
19
+ use crate :: sources:: { PathSource , CRATES_IO_REGISTRY } ;
20
20
use crate :: util:: cache_lock:: CacheLockMode ;
21
21
use crate :: util:: context:: JobsConfig ;
22
22
use crate :: util:: errors:: CargoResult ;
@@ -174,97 +174,6 @@ fn create_package(
174
174
return Ok ( dst) ;
175
175
}
176
176
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
-
268
177
/// Packages an entire workspace.
269
178
///
270
179
/// 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
293
202
// below, and will be validated during the verification step.
294
203
}
295
204
205
+ let deps = local_deps ( pkgs. iter ( ) . map ( |( p, f) | ( ( * p) . clone ( ) , f. clone ( ) ) ) ) ;
296
206
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
+ } ;
299
218
300
219
let mut local_reg = if ws. gctx ( ) . cli_unstable ( ) . package_workspace {
301
220
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 ( ) ?
303
223
} else {
304
224
None
305
225
} ;
306
226
307
- let deps = local_deps ( pkgs. iter ( ) . map ( |( p, f) | ( ( * p) . clone ( ) , f. clone ( ) ) ) ) ;
308
-
309
227
// Packages need to be created in dependency order, because dependencies must
310
228
// be added to our local overlay before we can create lockfiles that depend on them.
311
229
let sorted_pkgs = deps. sort ( ) ;
@@ -325,7 +243,9 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
325
243
} else {
326
244
let tarball = create_package ( ws, & pkg, ar_files, local_reg. as_ref ( ) ) ?;
327
245
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
+ }
329
249
}
330
250
outputs. push ( ( pkg, opts, tarball) ) ;
331
251
}
@@ -343,6 +263,46 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
343
263
Ok ( outputs. into_iter ( ) . map ( |x| x. 2 ) . collect ( ) )
344
264
}
345
265
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
+
346
306
/// Just the part of the dependency graph that's between the packages we're packaging.
347
307
/// (Is the package name a good key? Does it uniquely identify packages?)
348
308
#[ derive( Clone , Debug , Default ) ]
@@ -359,6 +319,12 @@ impl LocalDependencies {
359
319
. map ( |name| self . packages [ & name] . clone ( ) )
360
320
. collect ( )
361
321
}
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
+ }
362
328
}
363
329
364
330
/// Build just the part of the dependency graph that's between the given packages,
0 commit comments