@@ -47,6 +47,26 @@ static int git_worktree_config(const char *var, const char *value, void *cb)
47
47
return git_default_config (var , value , cb );
48
48
}
49
49
50
+ static int delete_git_dir (const char * id )
51
+ {
52
+ struct strbuf sb = STRBUF_INIT ;
53
+ int ret ;
54
+
55
+ strbuf_addstr (& sb , git_common_path ("worktrees/%s" , id ));
56
+ ret = remove_dir_recursively (& sb , 0 );
57
+ if (ret < 0 && errno == ENOTDIR )
58
+ ret = unlink (sb .buf );
59
+ if (ret )
60
+ error_errno (_ ("failed to delete '%s'" ), sb .buf );
61
+ strbuf_release (& sb );
62
+ return ret ;
63
+ }
64
+
65
+ static void delete_worktrees_dir_if_empty (void )
66
+ {
67
+ rmdir (git_path ("worktrees" )); /* ignore failed removal */
68
+ }
69
+
50
70
static int prune_worktree (const char * id , struct strbuf * reason )
51
71
{
52
72
struct stat st ;
@@ -116,10 +136,8 @@ static int prune_worktree(const char *id, struct strbuf *reason)
116
136
static void prune_worktrees (void )
117
137
{
118
138
struct strbuf reason = STRBUF_INIT ;
119
- struct strbuf path = STRBUF_INIT ;
120
139
DIR * dir = opendir (git_path ("worktrees" ));
121
140
struct dirent * d ;
122
- int ret ;
123
141
if (!dir )
124
142
return ;
125
143
while ((d = readdir (dir )) != NULL ) {
@@ -132,18 +150,12 @@ static void prune_worktrees(void)
132
150
printf ("%s\n" , reason .buf );
133
151
if (show_only )
134
152
continue ;
135
- git_path_buf (& path , "worktrees/%s" , d -> d_name );
136
- ret = remove_dir_recursively (& path , 0 );
137
- if (ret < 0 && errno == ENOTDIR )
138
- ret = unlink (path .buf );
139
- if (ret )
140
- error_errno (_ ("failed to remove '%s'" ), path .buf );
153
+ delete_git_dir (d -> d_name );
141
154
}
142
155
closedir (dir );
143
156
if (!show_only )
144
- rmdir ( git_path ( "worktrees" ) );
157
+ delete_worktrees_dir_if_empty ( );
145
158
strbuf_release (& reason );
146
- strbuf_release (& path );
147
159
}
148
160
149
161
static int prune (int ac , const char * * av , const char * prefix )
@@ -212,6 +224,43 @@ static const char *worktree_basename(const char *path, int *olen)
212
224
return name ;
213
225
}
214
226
227
+ static void validate_worktree_add (const char * path , const struct add_opts * opts )
228
+ {
229
+ struct worktree * * worktrees ;
230
+ struct worktree * wt ;
231
+ int locked ;
232
+
233
+ if (file_exists (path ) && !is_empty_dir (path ))
234
+ die (_ ("'%s' already exists" ), path );
235
+
236
+ worktrees = get_worktrees (0 );
237
+ /*
238
+ * find_worktree()'s suffix matching may undesirably find the main
239
+ * rather than a linked worktree (for instance, when the basenames
240
+ * of the main worktree and the one being created are the same).
241
+ * We're only interested in linked worktrees, so skip the main
242
+ * worktree with +1.
243
+ */
244
+ wt = find_worktree (worktrees + 1 , NULL , path );
245
+ if (!wt )
246
+ goto done ;
247
+
248
+ locked = !!is_worktree_locked (wt );
249
+ if ((!locked && opts -> force ) || (locked && opts -> force > 1 )) {
250
+ if (delete_git_dir (wt -> id ))
251
+ die (_ ("unable to re-add worktree '%s'" ), path );
252
+ goto done ;
253
+ }
254
+
255
+ if (locked )
256
+ die (_ ("'%s' is a missing but locked worktree;\nuse 'add -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear" ), path );
257
+ else
258
+ die (_ ("'%s' is a missing but already registered worktree;\nuse 'add -f' to override, or 'prune' or 'remove' to clear" ), path );
259
+
260
+ done :
261
+ free_worktrees (worktrees );
262
+ }
263
+
215
264
static int add_worktree (const char * path , const char * refname ,
216
265
const struct add_opts * opts )
217
266
{
@@ -226,8 +275,7 @@ static int add_worktree(const char *path, const char *refname,
226
275
struct commit * commit = NULL ;
227
276
int is_branch = 0 ;
228
277
229
- if (file_exists (path ) && !is_empty_dir (path ))
230
- die (_ ("'%s' already exists" ), path );
278
+ validate_worktree_add (path , opts );
231
279
232
280
/* is 'refname' a branch or commit? */
233
281
if (!opts -> detach && !strbuf_check_branch_ref (& symref , refname ) &&
@@ -697,13 +745,17 @@ static void validate_no_submodules(const struct worktree *wt)
697
745
698
746
static int move_worktree (int ac , const char * * av , const char * prefix )
699
747
{
748
+ int force = 0 ;
700
749
struct option options [] = {
750
+ OPT__FORCE (& force ,
751
+ N_ ("force move even if worktree is dirty or locked" ),
752
+ PARSE_OPT_NOCOMPLETE ),
701
753
OPT_END ()
702
754
};
703
755
struct worktree * * worktrees , * wt ;
704
756
struct strbuf dst = STRBUF_INIT ;
705
757
struct strbuf errmsg = STRBUF_INIT ;
706
- const char * reason ;
758
+ const char * reason = NULL ;
707
759
char * path ;
708
760
709
761
ac = parse_options (ac , av , prefix , options , worktree_usage , 0 );
@@ -734,12 +786,13 @@ static int move_worktree(int ac, const char **av, const char *prefix)
734
786
735
787
validate_no_submodules (wt );
736
788
737
- reason = is_worktree_locked (wt );
789
+ if (force < 2 )
790
+ reason = is_worktree_locked (wt );
738
791
if (reason ) {
739
792
if (* reason )
740
- die (_ ("cannot move a locked working tree, lock reason: %s" ),
793
+ die (_ ("cannot move a locked working tree, lock reason: %s\nuse 'move -f -f' to override or unlock first " ),
741
794
reason );
742
- die (_ ("cannot move a locked working tree" ));
795
+ die (_ ("cannot move a locked working tree;\nuse 'move -f -f' to override or unlock first " ));
743
796
}
744
797
if (validate_worktree (wt , & errmsg , 0 ))
745
798
die (_ ("validation failed, cannot move working tree: %s" ),
@@ -822,32 +875,18 @@ static int delete_git_work_tree(struct worktree *wt)
822
875
return ret ;
823
876
}
824
877
825
- static int delete_git_dir (struct worktree * wt )
826
- {
827
- struct strbuf sb = STRBUF_INIT ;
828
- int ret = 0 ;
829
-
830
- strbuf_addstr (& sb , git_common_path ("worktrees/%s" , wt -> id ));
831
- if (remove_dir_recursively (& sb , 0 )) {
832
- error_errno (_ ("failed to delete '%s'" ), sb .buf );
833
- ret = -1 ;
834
- }
835
- strbuf_release (& sb );
836
- return ret ;
837
- }
838
-
839
878
static int remove_worktree (int ac , const char * * av , const char * prefix )
840
879
{
841
880
int force = 0 ;
842
881
struct option options [] = {
843
882
OPT__FORCE (& force ,
844
- N_ ("force removing even if the worktree is dirty" ),
883
+ N_ ("force removal even if worktree is dirty or locked " ),
845
884
PARSE_OPT_NOCOMPLETE ),
846
885
OPT_END ()
847
886
};
848
887
struct worktree * * worktrees , * wt ;
849
888
struct strbuf errmsg = STRBUF_INIT ;
850
- const char * reason ;
889
+ const char * reason = NULL ;
851
890
int ret = 0 ;
852
891
853
892
ac = parse_options (ac , av , prefix , options , worktree_usage , 0 );
@@ -860,12 +899,13 @@ static int remove_worktree(int ac, const char **av, const char *prefix)
860
899
die (_ ("'%s' is not a working tree" ), av [0 ]);
861
900
if (is_main_worktree (wt ))
862
901
die (_ ("'%s' is a main working tree" ), av [0 ]);
863
- reason = is_worktree_locked (wt );
902
+ if (force < 2 )
903
+ reason = is_worktree_locked (wt );
864
904
if (reason ) {
865
905
if (* reason )
866
- die (_ ("cannot remove a locked working tree, lock reason: %s" ),
906
+ die (_ ("cannot remove a locked working tree, lock reason: %s\nuse 'remove -f -f' to override or unlock first " ),
867
907
reason );
868
- die (_ ("cannot remove a locked working tree" ));
908
+ die (_ ("cannot remove a locked working tree;\nuse 'remove -f -f' to override or unlock first " ));
869
909
}
870
910
if (validate_worktree (wt , & errmsg , WT_VALIDATE_WORKTREE_MISSING_OK ))
871
911
die (_ ("validation failed, cannot remove working tree: %s" ),
@@ -882,7 +922,8 @@ static int remove_worktree(int ac, const char **av, const char *prefix)
882
922
* continue on even if ret is non-zero, there's no going back
883
923
* from here.
884
924
*/
885
- ret |= delete_git_dir (wt );
925
+ ret |= delete_git_dir (wt -> id );
926
+ delete_worktrees_dir_if_empty ();
886
927
887
928
free_worktrees (worktrees );
888
929
return ret ;
0 commit comments