@@ -7,6 +7,7 @@ use std::{
77 ffi:: OsStr ,
88 fs:: FileType ,
99 io:: { BufRead , Write } ,
10+ iter:: once,
1011 path:: { Path , PathBuf } ,
1112 process:: Command ,
1213 str:: FromStr ,
@@ -15,7 +16,6 @@ use std::{
1516} ;
1617
1718use dunce:: canonicalize;
18- use glob:: glob;
1919use ignore:: gitignore:: { Gitignore , GitignoreBuilder } ;
2020use notify:: RecursiveMode ;
2121use notify_debouncer_full:: new_debouncer;
@@ -449,25 +449,15 @@ fn dev_options(
449449 }
450450}
451451
452- // Copied from https://github.com/rust-lang/cargo/blob/69255bb10de7f74511b5cef900a9d102247b6029/src/cargo/core/workspace.rs#L665
453- fn expand_member_path ( path : & Path ) -> crate :: Result < Vec < PathBuf > > {
454- let path = path. to_str ( ) . context ( "path is not UTF-8 compatible" ) ?;
455- let res = glob ( path) . with_context ( || format ! ( "failed to expand glob pattern for {path}" ) ) ?;
456- let res = res
457- . map ( |p| p. with_context ( || format ! ( "failed to expand glob pattern for {path}" ) ) )
458- . collect :: < Result < Vec < _ > , _ > > ( ) ?;
459- Ok ( res)
460- }
461-
462452fn get_watch_folders (
463453 additional_watch_folders : & [ PathBuf ] ,
464454 tauri_dir : & Path ,
465455) -> crate :: Result < Vec < PathBuf > > {
466- let workspace_path = get_workspace_dir ( tauri_dir) ?;
467-
468456 // We always want to watch the main tauri folder.
469457 let mut watch_folders = vec ! [ tauri_dir. to_path_buf( ) ] ;
470458
459+ watch_folders. extend ( get_in_workspace_dependency_paths ( tauri_dir) ?) ;
460+
471461 // Add the additional watch folders, resolving the path from the tauri path if it is relative
472462 watch_folders. extend ( additional_watch_folders. iter ( ) . filter_map ( |dir| {
473463 let path = if dir. is_absolute ( ) {
@@ -486,30 +476,6 @@ fn get_watch_folders(
486476 canonicalized
487477 } ) ) ;
488478
489- // We also try to watch workspace members, no matter if the tauri cargo project is the workspace root or a workspace member
490- let cargo_settings = CargoSettings :: load ( & workspace_path) ?;
491- if let Some ( members) = cargo_settings. workspace . and_then ( |w| w. members ) {
492- for p in members {
493- let p = workspace_path. join ( p) ;
494- match expand_member_path ( & p) {
495- // Sometimes expand_member_path returns an empty vec, for example if the path contains `[]` as in `C:/[abc]/project/`.
496- // Cargo won't complain unless theres a workspace.members config with glob patterns so we should support it too.
497- Ok ( expanded_paths) => {
498- if expanded_paths. is_empty ( ) {
499- watch_folders. push ( p) ;
500- } else {
501- watch_folders. extend ( expanded_paths) ;
502- }
503- }
504- Err ( err) => {
505- // If this fails cargo itself should fail too. But we still try to keep going with the unexpanded path.
506- log:: error!( "Error watching {}: {}" , p. display( ) , err) ;
507- watch_folders. push ( p) ;
508- }
509- } ;
510- }
511- }
512-
513479 Ok ( watch_folders)
514480}
515481
@@ -556,8 +522,13 @@ impl Rust {
556522
557523 let watch_folders = get_watch_folders ( additional_watch_folders, dirs. tauri ) ?;
558524
559- let common_ancestor = common_path:: common_path_all ( watch_folders. iter ( ) . map ( Path :: new) )
560- . expect ( "watch_folders should not be empty" ) ;
525+ let common_ancestor = common_path:: common_path_all (
526+ watch_folders
527+ . iter ( )
528+ . map ( Path :: new)
529+ . chain ( once ( self . app_settings . workspace_dir . as_path ( ) ) ) ,
530+ )
531+ . expect ( "watch_folders should not be empty" ) ;
561532 let ignore_matcher = build_ignore_matcher ( & common_ancestor) ;
562533
563534 let mut watcher = new_debouncer ( Duration :: from_secs ( 1 ) , None , move |r| {
@@ -692,7 +663,7 @@ pub struct TomlWorkspaceField {
692663#[ derive( Clone , Debug , Deserialize ) ]
693664struct WorkspaceSettings {
694665 /// the workspace members.
695- members : Option < Vec < String > > ,
666+ // members: Option<Vec<String>>,
696667 package : Option < WorkspacePackageSettings > ,
697668}
698669
@@ -779,6 +750,7 @@ pub struct RustAppSettings {
779750 cargo_config : CargoConfig ,
780751 target_triple : String ,
781752 target_platform : TargetPlatform ,
753+ workspace_dir : PathBuf ,
782754}
783755
784756#[ derive( Deserialize ) ]
@@ -1096,7 +1068,8 @@ impl RustAppSettings {
10961068 }
10971069 } ;
10981070
1099- let ws_package_settings = CargoSettings :: load ( & get_workspace_dir ( tauri_dir) ?)
1071+ let workspace_dir = get_workspace_dir ( tauri_dir) ?;
1072+ let ws_package_settings = CargoSettings :: load ( & workspace_dir)
11001073 . context ( "failed to load Cargo settings from workspace root" ) ?
11011074 . workspace
11021075 . and_then ( |v| v. package ) ;
@@ -1191,6 +1164,7 @@ impl RustAppSettings {
11911164 cargo_config,
11921165 target_triple,
11931166 target_platform,
1167+ workspace_dir,
11941168 } )
11951169 }
11961170
@@ -1210,6 +1184,23 @@ impl RustAppSettings {
12101184pub ( crate ) struct CargoMetadata {
12111185 pub ( crate ) target_directory : PathBuf ,
12121186 pub ( crate ) workspace_root : PathBuf ,
1187+ workspace_members : Vec < String > ,
1188+ packages : Vec < Package > ,
1189+ }
1190+
1191+ #[ derive( Deserialize ) ]
1192+ struct Package {
1193+ name : String ,
1194+ id : String ,
1195+ manifest_path : PathBuf ,
1196+ dependencies : Vec < Dependency > ,
1197+ }
1198+
1199+ #[ derive( Deserialize ) ]
1200+ struct Dependency {
1201+ name : String ,
1202+ /// Local package
1203+ path : Option < PathBuf > ,
12131204}
12141205
12151206pub ( crate ) fn get_cargo_metadata ( tauri_dir : & Path ) -> crate :: Result < CargoMetadata > {
@@ -1232,6 +1223,56 @@ pub(crate) fn get_cargo_metadata(tauri_dir: &Path) -> crate::Result<CargoMetadat
12321223 serde_json:: from_slice ( & output. stdout ) . context ( "failed to parse cargo metadata" )
12331224}
12341225
1226+ /// Get the tauri project crate's dependencies that are inside the workspace
1227+ fn get_in_workspace_dependency_paths ( tauri_dir : & Path ) -> crate :: Result < Vec < PathBuf > > {
1228+ let metadata = get_cargo_metadata ( tauri_dir) ?;
1229+ let tauri_project_manifest_path = tauri_dir. join ( "Cargo.toml" ) ;
1230+ let tauri_project_package = metadata
1231+ . packages
1232+ . iter ( )
1233+ . find ( |package| package. manifest_path == tauri_project_manifest_path)
1234+ . context ( "tauri project package doesn't exist in cargo metadata output `packages`" ) ?;
1235+
1236+ let workspace_packages = metadata
1237+ . workspace_members
1238+ . iter ( )
1239+ . map ( |member_package_id| {
1240+ metadata
1241+ . packages
1242+ . iter ( )
1243+ . find ( |package| package. id == * member_package_id)
1244+ . context ( "workspace member doesn't exist in cargo metadata output `packages`" )
1245+ } )
1246+ . collect :: < crate :: Result < Vec < _ > > > ( ) ?;
1247+
1248+ let mut found_dependency_paths = Vec :: new ( ) ;
1249+ find_dependencies (
1250+ tauri_project_package,
1251+ & workspace_packages,
1252+ & mut found_dependency_paths,
1253+ ) ;
1254+ Ok ( found_dependency_paths)
1255+ }
1256+
1257+ fn find_dependencies (
1258+ package : & Package ,
1259+ workspace_packages : & Vec < & Package > ,
1260+ found_dependency_paths : & mut Vec < PathBuf > ,
1261+ ) {
1262+ for dependency in & package. dependencies {
1263+ if let Some ( path) = & dependency. path {
1264+ if let Some ( package) = workspace_packages. iter ( ) . find ( |workspace_package| {
1265+ workspace_package. name == dependency. name
1266+ && path. join ( "Cargo.toml" ) == workspace_package. manifest_path
1267+ && !found_dependency_paths. contains ( path)
1268+ } ) {
1269+ found_dependency_paths. push ( path. to_owned ( ) ) ;
1270+ find_dependencies ( package, workspace_packages, found_dependency_paths) ;
1271+ }
1272+ }
1273+ }
1274+ }
1275+
12351276/// Get the cargo target directory based on the provided arguments.
12361277/// If "--target-dir" is specified in args, use it as the target directory (relative to current directory).
12371278/// Otherwise, use the target directory from cargo metadata.
0 commit comments