@@ -28,6 +28,7 @@ use super::{
28
28
} ;
29
29
use crate :: {
30
30
utils:: { fs_utils, CommandExt } ,
31
+ Error :: GenericError ,
31
32
Settings ,
32
33
} ;
33
34
@@ -173,6 +174,12 @@ fn copy_binaries_to_bundle(
173
174
/// Copies user-defined files to the app under Contents.
174
175
fn copy_custom_files_to_bundle ( bundle_directory : & Path , settings : & Settings ) -> crate :: Result < ( ) > {
175
176
for ( contents_path, path) in settings. macos ( ) . files . iter ( ) {
177
+ if !path. try_exists ( ) ? {
178
+ return Err ( GenericError ( format ! (
179
+ "Failed to copy {path:?} to {contents_path:?}. {path:?} does not exist."
180
+ ) ) ) ;
181
+ }
182
+
176
183
let contents_path = if contents_path. is_absolute ( ) {
177
184
contents_path. strip_prefix ( "/" ) . unwrap ( )
178
185
} else {
@@ -181,9 +188,13 @@ fn copy_custom_files_to_bundle(bundle_directory: &Path, settings: &Settings) ->
181
188
if path. is_file ( ) {
182
189
fs_utils:: copy_file ( path, & bundle_directory. join ( contents_path) )
183
190
. with_context ( || format ! ( "Failed to copy file {path:?} to {contents_path:?}" ) ) ?;
184
- } else {
191
+ } else if path . is_dir ( ) {
185
192
fs_utils:: copy_dir ( path, & bundle_directory. join ( contents_path) )
186
193
. with_context ( || format ! ( "Failed to copy directory {path:?} to {contents_path:?}" ) ) ?;
194
+ } else {
195
+ return Err ( GenericError ( format ! (
196
+ "{path:?} is not a file or directory."
197
+ ) ) ) ;
187
198
}
188
199
}
189
200
Ok ( ( ) )
@@ -405,9 +416,7 @@ fn copy_frameworks_to_bundle(
405
416
} else if framework. ends_with ( ".dylib" ) {
406
417
let src_path = PathBuf :: from ( framework) ;
407
418
if !src_path. exists ( ) {
408
- return Err ( crate :: Error :: GenericError ( format ! (
409
- "Library not found: {framework}"
410
- ) ) ) ;
419
+ return Err ( GenericError ( format ! ( "Library not found: {framework}" ) ) ) ;
411
420
}
412
421
let src_name = src_path. file_name ( ) . expect ( "Couldn't get library filename" ) ;
413
422
let dest_path = dest_dir. join ( src_name) ;
@@ -418,7 +427,7 @@ fn copy_frameworks_to_bundle(
418
427
} ) ;
419
428
continue ;
420
429
} else if framework. contains ( '/' ) {
421
- return Err ( crate :: Error :: GenericError ( format ! (
430
+ return Err ( GenericError ( format ! (
422
431
"Framework path should have .framework extension: {framework}"
423
432
) ) ) ;
424
433
}
@@ -436,7 +445,7 @@ fn copy_frameworks_to_bundle(
436
445
{
437
446
continue ;
438
447
}
439
- return Err ( crate :: Error :: GenericError ( format ! (
448
+ return Err ( GenericError ( format ! (
440
449
"Could not locate framework: {framework}"
441
450
) ) ) ;
442
451
}
@@ -529,3 +538,153 @@ fn add_nested_code_sign_path(src_path: &Path, dest_path: &Path, sign_paths: &mut
529
538
}
530
539
}
531
540
}
541
+
542
+ #[ cfg( test) ]
543
+ mod tests {
544
+ use super :: * ;
545
+ use crate :: bundle:: { BundleSettings , MacOsSettings , PackageSettings , SettingsBuilder } ;
546
+ use std:: {
547
+ collections:: HashMap ,
548
+ fs,
549
+ path:: { Path , PathBuf } ,
550
+ } ;
551
+
552
+ /// Helper that builds a `Settings` instance and bundle directory for tests.
553
+ /// It receives a mapping of bundle-relative paths to source paths and
554
+ /// returns the generated bundle directory and settings.
555
+ fn create_test_bundle (
556
+ project_dir : & Path ,
557
+ files : HashMap < PathBuf , PathBuf > ,
558
+ ) -> ( PathBuf , crate :: bundle:: Settings ) {
559
+ let macos_settings = MacOsSettings {
560
+ files,
561
+ ..Default :: default ( )
562
+ } ;
563
+
564
+ let settings = SettingsBuilder :: new ( )
565
+ . project_out_directory ( project_dir)
566
+ . package_settings ( PackageSettings {
567
+ product_name : "TestApp" . into ( ) ,
568
+ version : "0.1.0" . into ( ) ,
569
+ description : "test" . into ( ) ,
570
+ homepage : None ,
571
+ authors : None ,
572
+ default_run : None ,
573
+ } )
574
+ . bundle_settings ( BundleSettings {
575
+ macos : macos_settings,
576
+ ..Default :: default ( )
577
+ } )
578
+ . target ( "x86_64-apple-darwin" . into ( ) )
579
+ . build ( )
580
+ . expect ( "failed to build settings" ) ;
581
+
582
+ let bundle_dir = project_dir. join ( "TestApp.app/Contents" ) ;
583
+ fs:: create_dir_all ( & bundle_dir) . expect ( "failed to create bundle dir" ) ;
584
+
585
+ ( bundle_dir, settings)
586
+ }
587
+
588
+ #[ test]
589
+ fn test_copy_custom_file_to_bundle_file ( ) {
590
+ let tmp_dir = tempfile:: tempdir ( ) . expect ( "failed to create temp dir" ) ;
591
+
592
+ // Prepare a single file to copy.
593
+ let src_file = tmp_dir. path ( ) . join ( "sample.txt" ) ;
594
+ fs:: write ( & src_file, b"hello tauri" ) . expect ( "failed to write sample file" ) ;
595
+
596
+ let files_map = HashMap :: from ( [ ( PathBuf :: from ( "Resources/sample.txt" ) , src_file. clone ( ) ) ] ) ;
597
+
598
+ let ( bundle_dir, settings) = create_test_bundle ( tmp_dir. path ( ) , files_map) ;
599
+
600
+ copy_custom_files_to_bundle ( & bundle_dir, & settings)
601
+ . expect ( "copy_custom_files_to_bundle failed" ) ;
602
+
603
+ let dest_file = bundle_dir. join ( "Resources/sample.txt" ) ;
604
+ assert ! ( dest_file. exists( ) && dest_file. is_file( ) ) ;
605
+ assert_eq ! ( fs:: read_to_string( dest_file) . unwrap( ) , "hello tauri" ) ;
606
+ }
607
+
608
+ #[ test]
609
+ fn test_copy_custom_file_to_bundle_dir ( ) {
610
+ let tmp_dir = tempfile:: tempdir ( ) . expect ( "failed to create temp dir" ) ;
611
+
612
+ // Create a source directory with a nested file.
613
+ let src_dir = tmp_dir. path ( ) . join ( "assets" ) ;
614
+ fs:: create_dir_all ( & src_dir) . expect ( "failed to create assets directory" ) ;
615
+ let nested_file = src_dir. join ( "nested.txt" ) ;
616
+ fs:: write ( & nested_file, b"nested" ) . expect ( "failed to write nested file" ) ;
617
+
618
+ let files_map = HashMap :: from ( [ ( PathBuf :: from ( "MyAssets" ) , src_dir. clone ( ) ) ] ) ;
619
+
620
+ let ( bundle_dir, settings) = create_test_bundle ( tmp_dir. path ( ) , files_map) ;
621
+
622
+ copy_custom_files_to_bundle ( & bundle_dir, & settings)
623
+ . expect ( "copy_custom_files_to_bundle failed" ) ;
624
+
625
+ let dest_nested_file = bundle_dir. join ( "MyAssets/nested.txt" ) ;
626
+ assert ! (
627
+ dest_nested_file. exists( ) ,
628
+ "{dest_nested_file:?} does not exist"
629
+ ) ;
630
+ assert ! (
631
+ dest_nested_file. is_file( ) ,
632
+ "{dest_nested_file:?} is not a file"
633
+ ) ;
634
+ assert_eq ! (
635
+ fs:: read_to_string( dest_nested_file) . unwrap( ) . trim( ) ,
636
+ "nested"
637
+ ) ;
638
+ }
639
+
640
+ #[ test]
641
+ fn test_copy_custom_files_to_bundle_missing_source ( ) {
642
+ let tmp_dir = tempfile:: tempdir ( ) . expect ( "failed to create temp dir" ) ;
643
+
644
+ // Intentionally reference a non-existent path.
645
+ let missing_path = tmp_dir. path ( ) . join ( "does_not_exist.txt" ) ;
646
+
647
+ let files_map = HashMap :: from ( [ ( PathBuf :: from ( "Missing.txt" ) , missing_path) ] ) ;
648
+
649
+ let ( bundle_dir, settings) = create_test_bundle ( tmp_dir. path ( ) , files_map) ;
650
+
651
+ let result = copy_custom_files_to_bundle ( & bundle_dir, & settings) ;
652
+
653
+ assert ! ( result. is_err( ) ) ;
654
+ assert ! ( result. err( ) . unwrap( ) . to_string( ) . contains( "does not exist" ) ) ;
655
+ }
656
+
657
+ #[ test]
658
+ fn test_copy_custom_files_to_bundle_invalid_source ( ) {
659
+ let tmp_dir = tempfile:: tempdir ( ) . expect ( "failed to create temp dir" ) ;
660
+
661
+ let files_map = HashMap :: from ( [ ( PathBuf :: from ( "Invalid.txt" ) , PathBuf :: from ( "///" ) ) ] ) ;
662
+
663
+ let ( bundle_dir, settings) = create_test_bundle ( tmp_dir. path ( ) , files_map) ;
664
+
665
+ let result = copy_custom_files_to_bundle ( & bundle_dir, & settings) ;
666
+ assert ! ( result. is_err( ) ) ;
667
+ assert ! ( result
668
+ . err( )
669
+ . unwrap( )
670
+ . to_string( )
671
+ . contains( "Failed to copy directory" ) ) ;
672
+ }
673
+
674
+ #[ test]
675
+ fn test_copy_custom_files_to_bundle_dev_null ( ) {
676
+ let tmp_dir = tempfile:: tempdir ( ) . expect ( "failed to create temp dir" ) ;
677
+
678
+ let files_map = HashMap :: from ( [ ( PathBuf :: from ( "Invalid.txt" ) , PathBuf :: from ( "/dev/null" ) ) ] ) ;
679
+
680
+ let ( bundle_dir, settings) = create_test_bundle ( tmp_dir. path ( ) , files_map) ;
681
+
682
+ let result = copy_custom_files_to_bundle ( & bundle_dir, & settings) ;
683
+ assert ! ( result. is_err( ) ) ;
684
+ assert ! ( result
685
+ . err( )
686
+ . unwrap( )
687
+ . to_string( )
688
+ . contains( "is not a file or directory." ) ) ;
689
+ }
690
+ }
0 commit comments