@@ -2,9 +2,13 @@ use crate::project::{Project, Target, TargetMap};
22use anyhow:: { bail, Ok , Result } ;
33use std:: path:: PathBuf ;
44
5+ use crate :: xcode;
56use libproc:: libproc:: proc_pid;
67use notify:: EventKind ;
8+ use serde_json:: json;
79use std:: process:: Stdio ;
10+ use tokio:: fs;
11+ use tokio:: io:: AsyncWriteExt ;
812use tokio:: process:: Command ;
913
1014/// Managed Workspace
@@ -20,7 +24,7 @@ pub struct Workspace {
2024
2125impl Workspace {
2226 /// Create new workspace from a path representing project root.
23- /// TODO: Support setting up projects with .xproj as well as xcworkspace
27+ /// TODO: Support projects with .xproj as well as xcworkspace
2428 pub async fn new ( root : & str ) -> Result < Self > {
2529 let root = PathBuf :: from ( root) ;
2630
@@ -30,10 +34,10 @@ impl Workspace {
3034 bail ! ( "project.yaml doesn't exist in '{:?}'" , root)
3135 }
3236
33- Project :: new_from_project_yml ( path) . await ?
37+ Project :: new_from_project_yml ( root . clone ( ) , path) . await ?
3438 } ;
3539
36- tracing:: info!( "[New:: {}]: {:?}" , project. name( ) , root) ;
40+ tracing:: info!( "Managing [ {}] {:?}" , project. name( ) , root) ;
3741
3842 Ok ( Self {
3943 root,
@@ -52,7 +56,7 @@ impl Workspace {
5256 let name = self . project . name ( ) ;
5357 self . clients . retain ( |& pid| {
5458 if proc_pid:: name ( pid) . is_err ( ) {
55- tracing:: debug!( "[Update:: {}]: Remove Client: {pid}" , name) ;
59+ tracing:: debug!( "[{}]: Remove Client: {pid}" , name) ;
5660 false
5761 } else {
5862 true
@@ -65,7 +69,7 @@ impl Workspace {
6569 // Remove no longer active clients
6670 self . update_clients ( ) ;
6771 // NOTE: Implicitly assuming that pid is indeed a valid pid
68- tracing:: debug!( "[Update:: {}] Add Client: {pid}" , self . name( ) ) ;
72+ tracing:: debug!( "[{}] Add Client: {pid}" , self . name( ) ) ;
6973 self . clients . push ( pid)
7074 }
7175
@@ -86,45 +90,65 @@ impl Workspace {
8690 self . project . targets ( ) . get ( target_name)
8791 }
8892
89- /// Checks whether current workspace is xcodegen project.
90- pub fn is_xcodegen_project ( & self ) -> bool {
91- /*
92- TODO: support otherways to identify xcodegen project
93- Some would have xcodegen config as json file or
94- have different location to where they store xcodegen project config.
95- */
96- self . root . join ( "project.yml" ) . exists ( )
97- }
98-
9993 /// Regenerate compiled commands and xcodeGen if project.yml exists
100- pub async fn on_dirctory_change ( & self , _path : PathBuf , _event : EventKind ) -> Result < ( ) > {
94+ pub async fn on_dirctory_change ( & mut self , path : PathBuf , _event : EventKind ) -> Result < ( ) > {
10195 if self . is_xcodegen_project ( ) {
102- /*
103- FIXME: make xCodeGen binary path configurable.
104-
105- Current implementation will not work unless the user has xcodeGen located in
106- `~/.mint/bin/xcodegen`. Should either make it configurable as well as support a
107- number of paths by default.
108- */
109- let xcodegen_path = dirs:: home_dir ( ) . unwrap ( ) . join ( ".mint/bin/xcodegen" ) ;
110- let xcodegen = Command :: new ( xcodegen_path)
111- . current_dir ( self . root . clone ( ) )
112- . stdout ( Stdio :: null ( ) )
113- . arg ( "generate" )
114- . spawn ( )
115- . expect ( "Failed to start xcodeGen." )
116- . wait ( )
117- . await
118- . expect ( "Failed to run xcodeGen." ) ;
119-
120- if xcodegen. success ( ) {
121- tracing:: info!( "Generated {}.xcodeproj" , self . name( ) ) ;
96+ let is_config_file = path. file_name ( ) . unwrap ( ) . eq ( "project" ) ;
97+ self . update_xcodeproj ( is_config_file) . await ?;
98+ }
99+
100+ xcode:: ensure_server_config_file ( & self . root ) . await ?;
101+ xcode:: update_compiled_commands ( & self . root , self . project . fresh_build ( ) . await ?) . await ?;
102+
103+ Ok ( ( ) )
104+ }
105+
106+ /// Update .compile commands
107+ pub async fn update_xcodeproj ( & mut self , update_config : bool ) -> Result < ( ) > {
108+ /*
109+ FIXME: make xCodeGen binary path configurable.
110+
111+ Current implementation will not work unless the user has xcodeGen located in
112+ `~/.mint/bin/xcodegen`. Should either make it configurable as well as support a
113+ number of paths by default.
114+ */
115+ let xcodegen_path = dirs:: home_dir ( ) . unwrap ( ) . join ( ".mint/bin/xcodegen" ) ;
116+ let xcodegen = Command :: new ( xcodegen_path)
117+ . current_dir ( self . root . clone ( ) )
118+ . stdout ( Stdio :: null ( ) )
119+ . arg ( "generate" )
120+ . spawn ( )
121+ . expect ( "Failed to start xcodeGen." )
122+ . wait ( )
123+ . await
124+ . expect ( "Failed to run xcodeGen." ) ;
125+
126+ if xcodegen. success ( ) {
127+ tracing:: info!( "Updated {}.xcodeproj" , self . name( ) ) ;
128+ if update_config {
129+ tracing:: debug!( "Updated internal state.{}.project" , self . name( ) ) ;
130+ let path = self . xcodegen_config_path ( ) ;
131+ self . project = Project :: new_from_project_yml ( self . root . clone ( ) , path) . await ?;
122132 }
123133 }
124134
125135 Ok ( ( ) )
126136 }
127137
138+ /// Checks whether current workspace is xcodegen project.
139+ pub fn is_xcodegen_project ( & self ) -> bool {
140+ self . xcodegen_config_path ( ) . exists ( )
141+ }
142+
143+ pub fn xcodegen_config_path ( & self ) -> PathBuf {
144+ /*
145+ TODO: support otherways to identify xcodegen project
146+
147+ Some would have xcodegen config as json file or
148+ have different location to where they store xcodegen project config.
149+ */
150+ self . root . join ( "project.yml" )
151+ }
128152 pub fn get_ignore_patterns ( & self ) -> Option < Vec < String > > {
129153 if self . is_xcodegen_project ( ) {
130154 return Some ( self . project . config ( ) . ignore . clone ( ) ) ;
0 commit comments