@@ -15,7 +15,7 @@ use crate::core::{Feature, PackageIdSpecQuery, Shell, Verbosity, Workspace};
15
15
use crate :: core:: { Package , PackageId , PackageSet , Resolve , SourceId } ;
16
16
use crate :: ops:: registry:: infer_registry;
17
17
use crate :: sources:: registry:: index:: { IndexPackage , RegistryDependency } ;
18
- use crate :: sources:: PathSource ;
18
+ use crate :: sources:: { PathSource , CRATES_IO_REGISTRY } ;
19
19
use crate :: util:: cache_lock:: CacheLockMode ;
20
20
use crate :: util:: context:: JobsConfig ;
21
21
use crate :: util:: errors:: CargoResult ;
@@ -24,7 +24,7 @@ use crate::util::{
24
24
self , human_readable_bytes, restricted_names, FileLock , Filesystem , GlobalContext , Graph ,
25
25
} ;
26
26
use crate :: { drop_println, ops} ;
27
- use anyhow:: Context as _;
27
+ use anyhow:: { bail , Context as _} ;
28
28
use cargo_util:: paths;
29
29
use flate2:: read:: GzDecoder ;
30
30
use flate2:: { Compression , GzBuilder } ;
@@ -33,6 +33,8 @@ use tar::{Archive, Builder, EntryType, Header, HeaderMode};
33
33
use tracing:: debug;
34
34
use unicase:: Ascii as UncasedAscii ;
35
35
36
+ use super :: RegistryOrIndex ;
37
+
36
38
#[ derive( Clone ) ]
37
39
pub struct PackageOpts < ' gctx > {
38
40
pub gctx : & ' gctx GlobalContext ,
@@ -173,6 +175,43 @@ fn create_package(
173
175
return Ok ( dst) ;
174
176
}
175
177
178
+ /// Determine which registry the packages are for.
179
+ ///
180
+ /// The registry only affects the built packages if there are dependencies within the
181
+ /// packages that we're packaging: if we're packaging foo-bin and foo-lib, and foo-bin
182
+ /// depends on foo-lib, then the foo-lib entry in foo-bin's lockfile will depend on the
183
+ /// registry that we're building packages for.
184
+ fn get_registry (
185
+ gctx : & GlobalContext ,
186
+ pkgs : & [ & Package ] ,
187
+ reg_or_index : Option < RegistryOrIndex > ,
188
+ ) -> CargoResult < SourceId > {
189
+ let reg_or_index = match reg_or_index. clone ( ) {
190
+ Some ( r) => Some ( r) ,
191
+ None => infer_registry ( pkgs) ?,
192
+ } ;
193
+
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 ! (
203
+ "`{}` cannot be packaged.\n \
204
+ The registry `{}` is not listed in the `package.publish` value in Cargo.toml.",
205
+ pkg. name( ) ,
206
+ reg_name
207
+ ) ;
208
+ }
209
+ }
210
+ }
211
+ }
212
+ Ok ( ops:: registry:: get_source_id ( gctx, reg_or_index. as_ref ( ) ) ?. replacement )
213
+ }
214
+
176
215
/// Packages an entire workspace.
177
216
///
178
217
/// Returns the generated package files. If `opts.list` is true, skips
@@ -196,19 +235,34 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
196
235
// below, and will be validated during the verification step.
197
236
}
198
237
238
+ let deps = local_deps ( pkgs. iter ( ) . map ( |( p, f) | ( ( * p) . clone ( ) , f. clone ( ) ) ) ) ;
199
239
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 ( ) ) ?;
201
- 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
+ } ;
202
257
203
258
let mut local_reg = if ws. gctx ( ) . cli_unstable ( ) . package_workspace {
204
259
let reg_dir = ws. target_dir ( ) . join ( "package" ) . join ( "tmp-registry" ) ;
205
- Some ( TmpRegistry :: new ( ws. gctx ( ) , reg_dir, publish_reg) ?)
260
+ sid. map ( |sid| TmpRegistry :: new ( ws. gctx ( ) , reg_dir, sid) )
261
+ . transpose ( ) ?
206
262
} else {
207
263
None
208
264
} ;
209
265
210
- let deps = local_deps ( pkgs. iter ( ) . map ( |( p, f) | ( ( * p) . clone ( ) , f. clone ( ) ) ) ) ;
211
-
212
266
// Packages need to be created in dependency order, because dependencies must
213
267
// be added to our local overlay before we can create lockfiles that depend on them.
214
268
let sorted_pkgs = deps. sort ( ) ;
@@ -262,6 +316,12 @@ impl LocalDependencies {
262
316
. map ( |name| self . packages [ & name] . clone ( ) )
263
317
. collect ( )
264
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
+ }
265
325
}
266
326
267
327
/// Build just the part of the dependency graph that's between the given packages,
0 commit comments