77#include "parse-options.h"
88#include "config.h"
99#include "run-command.h"
10+ #include "simple-ipc.h"
11+ #include "fsmonitor-ipc.h"
12+ #include "fsmonitor-settings.h"
1013#include "refs.h"
1114#include "dir.h"
1215#include "packfile.h"
1316#include "help.h"
1417
15- /*
16- * Remove the deepest subdirectory in the provided path string. Path must not
17- * include a trailing path separator. Returns 1 if parent directory found,
18- * otherwise 0.
19- */
20- static int strbuf_parent_directory (struct strbuf * buf )
21- {
22- size_t len = buf -> len ;
23- size_t offset = offset_1st_component (buf -> buf );
24- char * path_sep = find_last_dir_sep (buf -> buf + offset );
25- strbuf_setlen (buf , path_sep ? path_sep - buf -> buf : offset );
26-
27- return buf -> len < len ;
28- }
29-
3018static void setup_enlistment_directory (int argc , const char * * argv ,
3119 const char * const * usagestr ,
3220 const struct option * options ,
3321 struct strbuf * enlistment_root )
3422{
3523 struct strbuf path = STRBUF_INIT ;
36- char * root ;
37- int enlistment_found = 0 ;
24+ int enlistment_is_repo_parent = 0 ;
25+ size_t len ;
3826
3927 if (startup_info -> have_repository )
4028 BUG ("gitdir already set up?!?" );
@@ -47,51 +35,36 @@ static void setup_enlistment_directory(int argc, const char **argv,
4735 strbuf_add_absolute_path (& path , argv [0 ]);
4836 if (!is_directory (path .buf ))
4937 die (_ ("'%s' does not exist" ), path .buf );
38+ if (chdir (path .buf ) < 0 )
39+ die_errno (_ ("could not switch to '%s'" ), path .buf );
5040 } else if (strbuf_getcwd (& path ) < 0 )
5141 die (_ ("need a working directory" ));
5242
5343 strbuf_trim_trailing_dir_sep (& path );
54- do {
55- const size_t len = path .len ;
5644
57- /* check if currently in enlistment root with src/ workdir */
58- strbuf_addstr (& path , "/src" );
59- if (is_nonbare_repository_dir (& path )) {
60- if (enlistment_root )
61- strbuf_add (enlistment_root , path .buf , len );
62-
63- enlistment_found = 1 ;
64- break ;
65- }
66-
67- /* reset to original path */
68- strbuf_setlen (& path , len );
69-
70- /* check if currently in workdir */
71- if (is_nonbare_repository_dir (& path )) {
72- if (enlistment_root ) {
73- /*
74- * If the worktree's directory's name is `src`, the enlistment is the
75- * parent directory, otherwise it is identical to the worktree.
76- */
77- root = strip_path_suffix (path .buf , "src" );
78- strbuf_addstr (enlistment_root , root ? root : path .buf );
79- free (root );
80- }
45+ /* check if currently in enlistment root with src/ workdir */
46+ len = path .len ;
47+ strbuf_addstr (& path , "/src" );
48+ if (is_nonbare_repository_dir (& path )) {
49+ enlistment_is_repo_parent = 1 ;
50+ if (chdir (path .buf ) < 0 )
51+ die_errno (_ ("could not switch to '%s'" ), path .buf );
52+ }
53+ strbuf_setlen (& path , len );
8154
82- enlistment_found = 1 ;
83- break ;
84- }
85- } while (strbuf_parent_directory (& path ));
55+ setup_git_directory ();
8656
87- if (!enlistment_found )
88- die (_ ("could not find enlistment root " ));
57+ if (!the_repository -> worktree )
58+ die (_ ("Scalar enlistments require a worktree " ));
8959
90- if (chdir (path .buf ) < 0 )
91- die_errno (_ ("could not switch to '%s'" ), path .buf );
60+ if (enlistment_root ) {
61+ if (enlistment_is_repo_parent )
62+ strbuf_addbuf (enlistment_root , & path );
63+ else
64+ strbuf_addstr (enlistment_root , the_repository -> worktree );
65+ }
9266
9367 strbuf_release (& path );
94- setup_git_directory ();
9568}
9669
9770static int run_git (const char * arg , ...)
@@ -113,13 +86,39 @@ static int run_git(const char *arg, ...)
11386 return res ;
11487}
11588
89+ struct scalar_config {
90+ const char * key ;
91+ const char * value ;
92+ int overwrite_on_reconfigure ;
93+ };
94+
95+ static int set_scalar_config (const struct scalar_config * config , int reconfigure )
96+ {
97+ char * value = NULL ;
98+ int res ;
99+
100+ if ((reconfigure && config -> overwrite_on_reconfigure ) ||
101+ git_config_get_string (config -> key , & value )) {
102+ trace2_data_string ("scalar" , the_repository , config -> key , "created" );
103+ res = git_config_set_gently (config -> key , config -> value );
104+ } else {
105+ trace2_data_string ("scalar" , the_repository , config -> key , "exists" );
106+ res = 0 ;
107+ }
108+
109+ free (value );
110+ return res ;
111+ }
112+
113+ static int have_fsmonitor_support (void )
114+ {
115+ return fsmonitor_ipc__is_supported () &&
116+ fsm_settings__get_reason (the_repository ) == FSMONITOR_REASON_OK ;
117+ }
118+
116119static int set_recommended_config (int reconfigure )
117120{
118- struct {
119- const char * key ;
120- const char * value ;
121- int overwrite_on_reconfigure ;
122- } config [] = {
121+ struct scalar_config config [] = {
123122 /* Required */
124123 { "am.keepCR" , "true" , 1 },
125124 { "core.FSCache" , "true" , 1 },
@@ -173,17 +172,16 @@ static int set_recommended_config(int reconfigure)
173172 char * value ;
174173
175174 for (i = 0 ; config [i ].key ; i ++ ) {
176- if ((reconfigure && config [i ].overwrite_on_reconfigure ) ||
177- git_config_get_string (config [i ].key , & value )) {
178- trace2_data_string ("scalar" , the_repository , config [i ].key , "created" );
179- if (git_config_set_gently (config [i ].key ,
180- config [i ].value ) < 0 )
181- return error (_ ("could not configure %s=%s" ),
182- config [i ].key , config [i ].value );
183- } else {
184- trace2_data_string ("scalar" , the_repository , config [i ].key , "exists" );
185- free (value );
186- }
175+ if (set_scalar_config (config + i , reconfigure ))
176+ return error (_ ("could not configure %s=%s" ),
177+ config [i ].key , config [i ].value );
178+ }
179+
180+ if (have_fsmonitor_support ()) {
181+ struct scalar_config fsmonitor = { "core.fsmonitor" , "true" };
182+ if (set_scalar_config (& fsmonitor , reconfigure ))
183+ return error (_ ("could not configure %s=%s" ),
184+ fsmonitor .key , fsmonitor .value );
187185 }
188186
189187 /*
@@ -234,28 +232,53 @@ static int add_or_remove_enlistment(int add)
234232 "scalar.repo" , the_repository -> worktree , NULL );
235233}
236234
235+ static int start_fsmonitor_daemon (void )
236+ {
237+ assert (have_fsmonitor_support ());
238+
239+ if (fsmonitor_ipc__get_state () != IPC_STATE__LISTENING )
240+ return run_git ("fsmonitor--daemon" , "start" , NULL );
241+
242+ return 0 ;
243+ }
244+
245+ static int stop_fsmonitor_daemon (void )
246+ {
247+ assert (have_fsmonitor_support ());
248+
249+ if (fsmonitor_ipc__get_state () == IPC_STATE__LISTENING )
250+ return run_git ("fsmonitor--daemon" , "stop" , NULL );
251+
252+ return 0 ;
253+ }
254+
237255static int register_dir (void )
238256{
239- int res = add_or_remove_enlistment (1 );
257+ if (add_or_remove_enlistment (1 ))
258+ return error (_ ("could not add enlistment" ));
240259
241- if (! res )
242- res = set_recommended_config ( 0 );
260+ if (set_recommended_config ( 0 ) )
261+ return error ( _ ( "could not set recommended config" ) );
243262
244- if (! res )
245- res = toggle_maintenance ( 1 );
263+ if (toggle_maintenance ( 1 ) )
264+ return error ( _ ( "could not turn on maintenance" ) );
246265
247- return res ;
266+ if (have_fsmonitor_support () && start_fsmonitor_daemon ()) {
267+ return error (_ ("could not start the FSMonitor daemon" ));
268+ }
269+
270+ return 0 ;
248271}
249272
250273static int unregister_dir (void )
251274{
252275 int res = 0 ;
253276
254- if (toggle_maintenance (0 ) < 0 )
255- res = -1 ;
277+ if (toggle_maintenance (0 ))
278+ res = error ( _ ( "could not turn off maintenance" )) ;
256279
257- if (add_or_remove_enlistment (0 ) < 0 )
258- res = -1 ;
280+ if (add_or_remove_enlistment (0 ))
281+ res = error ( _ ( "could not remove enlistment" )) ;
259282
260283 return res ;
261284}
@@ -336,25 +359,35 @@ static int delete_enlistment(struct strbuf *enlistment)
336359{
337360#ifdef WIN32
338361 struct strbuf parent = STRBUF_INIT ;
362+ size_t offset ;
363+ char * path_sep ;
339364#endif
340365
341366 if (unregister_dir ())
342- die (_ ("failed to unregister repository" ));
367+ return error (_ ("failed to unregister repository" ));
343368
344369#ifdef WIN32
345370 /*
346371 * Change the current directory to one outside of the enlistment so
347372 * that we may delete everything underneath it.
348373 */
349- strbuf_addbuf (& parent , enlistment );
350- strbuf_parent_directory (& parent );
351- if (chdir (parent .buf ) < 0 )
352- die_errno (_ ("could not switch to '%s'" ), parent .buf );
374+ offset = offset_1st_component (enlistment -> buf );
375+ path_sep = find_last_dir_sep (enlistment -> buf + offset );
376+ strbuf_add (& parent , enlistment -> buf ,
377+ path_sep ? path_sep - enlistment -> buf : offset );
378+ if (chdir (parent .buf ) < 0 ) {
379+ int res = error_errno (_ ("could not switch to '%s'" ), parent .buf );
380+ strbuf_release (& parent );
381+ return res ;
382+ }
353383 strbuf_release (& parent );
354384#endif
355385
386+ if (have_fsmonitor_support () && stop_fsmonitor_daemon ())
387+ return error (_ ("failed to stop the FSMonitor daemon" ));
388+
356389 if (remove_dir_recursively (enlistment , 0 ))
357- die (_ ("failed to delete enlistment directory" ));
390+ return error (_ ("failed to delete enlistment directory" ));
358391
359392 return 0 ;
360393}
0 commit comments