@@ -3,15 +3,16 @@ use std::fs::{self, File};
33use std:: io:: prelude:: * ;
44use std:: io:: SeekFrom ;
55use std:: path:: { Path , PathBuf } ;
6- use std:: sync:: Arc ;
76use std:: task:: Poll ;
87
9- use crate :: core:: compiler:: { BuildConfig , CompileMode , DefaultExecutor , Executor } ;
108use crate :: core:: dependency:: DepKind ;
119use crate :: core:: manifest:: Target ;
1210use crate :: core:: resolver:: CliFeatures ;
1311use crate :: core:: resolver:: HasDevUnits ;
14- use crate :: core:: { Feature , PackageIdSpecQuery , Shell , Verbosity , Workspace } ;
12+ use crate :: core:: PackageIdSpecQuery ;
13+ use crate :: core:: Shell ;
14+ use crate :: core:: Verbosity ;
15+ use crate :: core:: Workspace ;
1516use crate :: core:: { Package , PackageId , PackageSet , Resolve , SourceId } ;
1617use crate :: ops:: lockfile:: LOCKFILE_NAME ;
1718use crate :: ops:: registry:: { infer_registry, RegistryOrIndex } ;
@@ -20,20 +21,23 @@ use crate::sources::{PathSource, CRATES_IO_REGISTRY};
2021use crate :: util:: cache_lock:: CacheLockMode ;
2122use crate :: util:: context:: JobsConfig ;
2223use crate :: util:: errors:: CargoResult ;
24+ use crate :: util:: human_readable_bytes;
25+ use crate :: util:: restricted_names;
2326use crate :: util:: toml:: prepare_for_publish;
24- use crate :: util:: {
25- self , human_readable_bytes, restricted_names, FileLock , Filesystem , GlobalContext , Graph ,
26- } ;
27+ use crate :: util:: FileLock ;
28+ use crate :: util:: Filesystem ;
29+ use crate :: util:: GlobalContext ;
30+ use crate :: util:: Graph ;
2731use crate :: { drop_println, ops} ;
2832use anyhow:: { bail, Context as _} ;
2933use cargo_util:: paths;
30- use flate2:: read:: GzDecoder ;
3134use flate2:: { Compression , GzBuilder } ;
32- use tar:: { Archive , Builder , EntryType , Header , HeaderMode } ;
35+ use tar:: { Builder , EntryType , Header , HeaderMode } ;
3336use tracing:: debug;
3437use unicase:: Ascii as UncasedAscii ;
3538
3639mod vcs;
40+ mod verify;
3741
3842#[ derive( Clone ) ]
3943pub struct PackageOpts < ' gctx > {
@@ -250,7 +254,7 @@ fn do_package<'a>(
250254 // are already all in the local registry overlay.
251255 if opts. verify {
252256 for ( pkg, opts, tarball) in & outputs {
253- run_verify ( ws, pkg, tarball, local_reg. as_ref ( ) , opts)
257+ verify :: run_verify ( ws, pkg, tarball, local_reg. as_ref ( ) , opts)
254258 . context ( "failed to verify package tarball" ) ?
255259 }
256260 }
@@ -926,160 +930,6 @@ pub fn check_yanked(
926930 Ok ( ( ) )
927931}
928932
929- fn run_verify (
930- ws : & Workspace < ' _ > ,
931- pkg : & Package ,
932- tar : & FileLock ,
933- local_reg : Option < & TmpRegistry < ' _ > > ,
934- opts : & PackageOpts < ' _ > ,
935- ) -> CargoResult < ( ) > {
936- let gctx = ws. gctx ( ) ;
937-
938- gctx. shell ( ) . status ( "Verifying" , pkg) ?;
939-
940- tar. file ( ) . seek ( SeekFrom :: Start ( 0 ) ) ?;
941- let f = GzDecoder :: new ( tar. file ( ) ) ;
942- let dst = tar
943- . parent ( )
944- . join ( & format ! ( "{}-{}" , pkg. name( ) , pkg. version( ) ) ) ;
945- if dst. exists ( ) {
946- paths:: remove_dir_all ( & dst) ?;
947- }
948- let mut archive = Archive :: new ( f) ;
949- // We don't need to set the Modified Time, as it's not relevant to verification
950- // and it errors on filesystems that don't support setting a modified timestamp
951- archive. set_preserve_mtime ( false ) ;
952- archive. unpack ( dst. parent ( ) . unwrap ( ) ) ?;
953-
954- // Manufacture an ephemeral workspace to ensure that even if the top-level
955- // package has a workspace we can still build our new crate.
956- let id = SourceId :: for_path ( & dst) ?;
957- let mut src = PathSource :: new ( & dst, id, ws. gctx ( ) ) ;
958- let new_pkg = src. root_package ( ) ?;
959- let pkg_fingerprint = hash_all ( & dst) ?;
960- let mut ws = Workspace :: ephemeral ( new_pkg, gctx, None , true ) ?;
961- if let Some ( local_reg) = local_reg {
962- ws. add_local_overlay (
963- local_reg. upstream ,
964- local_reg. root . as_path_unlocked ( ) . to_owned ( ) ,
965- ) ;
966- }
967-
968- let rustc_args = if pkg
969- . manifest ( )
970- . unstable_features ( )
971- . require ( Feature :: public_dependency ( ) )
972- . is_ok ( )
973- || ws. gctx ( ) . cli_unstable ( ) . public_dependency
974- {
975- // FIXME: Turn this on at some point in the future
976- //Some(vec!["-D exported_private_dependencies".to_string()])
977- Some ( vec ! [ ] )
978- } else {
979- None
980- } ;
981-
982- let exec: Arc < dyn Executor > = Arc :: new ( DefaultExecutor ) ;
983- ops:: compile_with_exec (
984- & ws,
985- & ops:: CompileOptions {
986- build_config : BuildConfig :: new (
987- gctx,
988- opts. jobs . clone ( ) ,
989- opts. keep_going ,
990- & opts. targets ,
991- CompileMode :: Build ,
992- ) ?,
993- cli_features : opts. cli_features . clone ( ) ,
994- spec : ops:: Packages :: Packages ( Vec :: new ( ) ) ,
995- filter : ops:: CompileFilter :: Default {
996- required_features_filterable : true ,
997- } ,
998- target_rustdoc_args : None ,
999- target_rustc_args : rustc_args,
1000- target_rustc_crate_types : None ,
1001- rustdoc_document_private_items : false ,
1002- honor_rust_version : None ,
1003- } ,
1004- & exec,
1005- ) ?;
1006-
1007- // Check that `build.rs` didn't modify any files in the `src` directory.
1008- let ws_fingerprint = hash_all ( & dst) ?;
1009- if pkg_fingerprint != ws_fingerprint {
1010- let changes = report_hash_difference ( & pkg_fingerprint, & ws_fingerprint) ;
1011- anyhow:: bail!(
1012- "Source directory was modified by build.rs during cargo publish. \
1013- Build scripts should not modify anything outside of OUT_DIR.\n \
1014- {}\n \n \
1015- To proceed despite this, pass the `--no-verify` flag.",
1016- changes
1017- )
1018- }
1019-
1020- Ok ( ( ) )
1021- }
1022-
1023- fn hash_all ( path : & Path ) -> CargoResult < HashMap < PathBuf , u64 > > {
1024- fn wrap ( path : & Path ) -> CargoResult < HashMap < PathBuf , u64 > > {
1025- let mut result = HashMap :: new ( ) ;
1026- let walker = walkdir:: WalkDir :: new ( path) . into_iter ( ) ;
1027- for entry in walker. filter_entry ( |e| !( e. depth ( ) == 1 && e. file_name ( ) == "target" ) ) {
1028- let entry = entry?;
1029- let file_type = entry. file_type ( ) ;
1030- if file_type. is_file ( ) {
1031- let file = File :: open ( entry. path ( ) ) ?;
1032- let hash = util:: hex:: hash_u64_file ( & file) ?;
1033- result. insert ( entry. path ( ) . to_path_buf ( ) , hash) ;
1034- } else if file_type. is_symlink ( ) {
1035- let hash = util:: hex:: hash_u64 ( & fs:: read_link ( entry. path ( ) ) ?) ;
1036- result. insert ( entry. path ( ) . to_path_buf ( ) , hash) ;
1037- } else if file_type. is_dir ( ) {
1038- let hash = util:: hex:: hash_u64 ( & ( ) ) ;
1039- result. insert ( entry. path ( ) . to_path_buf ( ) , hash) ;
1040- }
1041- }
1042- Ok ( result)
1043- }
1044- let result = wrap ( path) . with_context ( || format ! ( "failed to verify output at {:?}" , path) ) ?;
1045- Ok ( result)
1046- }
1047-
1048- fn report_hash_difference ( orig : & HashMap < PathBuf , u64 > , after : & HashMap < PathBuf , u64 > ) -> String {
1049- let mut changed = Vec :: new ( ) ;
1050- let mut removed = Vec :: new ( ) ;
1051- for ( key, value) in orig {
1052- match after. get ( key) {
1053- Some ( after_value) => {
1054- if value != after_value {
1055- changed. push ( key. to_string_lossy ( ) ) ;
1056- }
1057- }
1058- None => removed. push ( key. to_string_lossy ( ) ) ,
1059- }
1060- }
1061- let mut added: Vec < _ > = after
1062- . keys ( )
1063- . filter ( |key| !orig. contains_key ( * key) )
1064- . map ( |key| key. to_string_lossy ( ) )
1065- . collect ( ) ;
1066- let mut result = Vec :: new ( ) ;
1067- if !changed. is_empty ( ) {
1068- changed. sort_unstable ( ) ;
1069- result. push ( format ! ( "Changed: {}" , changed. join( "\n \t " ) ) ) ;
1070- }
1071- if !added. is_empty ( ) {
1072- added. sort_unstable ( ) ;
1073- result. push ( format ! ( "Added: {}" , added. join( "\n \t " ) ) ) ;
1074- }
1075- if !removed. is_empty ( ) {
1076- removed. sort_unstable ( ) ;
1077- result. push ( format ! ( "Removed: {}" , removed. join( "\n \t " ) ) ) ;
1078- }
1079- assert ! ( !result. is_empty( ) , "unexpected empty change detection" ) ;
1080- result. join ( "\n " )
1081- }
1082-
1083933// It can often be the case that files of a particular name on one platform
1084934// can't actually be created on another platform. For example files with colons
1085935// in the name are allowed on Unix but not on Windows.
0 commit comments