@@ -3,15 +3,16 @@ 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
- use std:: sync:: Arc ;
7
6
use std:: task:: Poll ;
8
7
9
- use crate :: core:: compiler:: { BuildConfig , CompileMode , DefaultExecutor , Executor } ;
10
8
use crate :: core:: dependency:: DepKind ;
11
9
use crate :: core:: manifest:: Target ;
12
10
use crate :: core:: resolver:: CliFeatures ;
13
11
use 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 ;
15
16
use crate :: core:: { Package , PackageId , PackageSet , Resolve , SourceId } ;
16
17
use crate :: ops:: lockfile:: LOCKFILE_NAME ;
17
18
use crate :: ops:: registry:: { infer_registry, RegistryOrIndex } ;
@@ -20,20 +21,23 @@ use crate::sources::{PathSource, CRATES_IO_REGISTRY};
20
21
use crate :: util:: cache_lock:: CacheLockMode ;
21
22
use crate :: util:: context:: JobsConfig ;
22
23
use crate :: util:: errors:: CargoResult ;
24
+ use crate :: util:: human_readable_bytes;
25
+ use crate :: util:: restricted_names;
23
26
use 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 ;
27
31
use crate :: { drop_println, ops} ;
28
32
use anyhow:: { bail, Context as _} ;
29
33
use cargo_util:: paths;
30
- use flate2:: read:: GzDecoder ;
31
34
use flate2:: { Compression , GzBuilder } ;
32
- use tar:: { Archive , Builder , EntryType , Header , HeaderMode } ;
35
+ use tar:: { Builder , EntryType , Header , HeaderMode } ;
33
36
use tracing:: debug;
34
37
use unicase:: Ascii as UncasedAscii ;
35
38
36
39
mod vcs;
40
+ mod verify;
37
41
38
42
#[ derive( Clone ) ]
39
43
pub struct PackageOpts < ' gctx > {
@@ -250,7 +254,7 @@ fn do_package<'a>(
250
254
// are already all in the local registry overlay.
251
255
if opts. verify {
252
256
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)
254
258
. context ( "failed to verify package tarball" ) ?
255
259
}
256
260
}
@@ -926,160 +930,6 @@ pub fn check_yanked(
926
930
Ok ( ( ) )
927
931
}
928
932
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
-
1083
933
// It can often be the case that files of a particular name on one platform
1084
934
// can't actually be created on another platform. For example files with colons
1085
935
// in the name are allowed on Unix but not on Windows.
0 commit comments