Skip to content

Commit 7b7b1fc

Browse files
committed
clean: remove mount points when possible
Windows' equivalent to "bind mounts", NTFS junction points, can be unlinked without affecting the mount target. This is clearly what users expect to happen when they call `git clean -dfx` in a worktree that contains NTFS junction points: the junction should be removed, and the target directory of said junction should be left alone (unless it is inside the worktree). Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 8a1d3c0 commit 7b7b1fc

File tree

3 files changed

+15
-0
lines changed

3 files changed

+15
-0
lines changed

builtin/clean.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ static const char *msg_remove = N_("Removing %s\n");
3737
static const char *msg_would_remove = N_("Would remove %s\n");
3838
static const char *msg_skip_git_dir = N_("Skipping repository %s\n");
3939
static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n");
40+
#ifndef CAN_UNLINK_MOUNT_POINTS
4041
static const char *msg_skip_mount_point = N_("Skipping mount point %s\n");
4142
static const char *msg_would_skip_mount_point = N_("Would skip mount point %s\n");
43+
#endif
4244
static const char *msg_warn_remove_failed = N_("failed to remove %s");
4345
static const char *msg_warn_lstat_failed = N_("could not lstat %s\n");
4446
static const char *msg_skip_cwd = N_("Refusing to remove current working directory\n");
@@ -184,13 +186,24 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
184186
}
185187

186188
if (is_mount_point(path)) {
189+
#ifndef CAN_UNLINK_MOUNT_POINTS
187190
if (!quiet) {
188191
quote_path(path->buf, prefix, &quoted, 0);
189192
printf(dry_run ?
190193
_(msg_would_skip_mount_point) :
191194
_(msg_skip_mount_point), quoted.buf);
192195
}
193196
*dir_gone = 0;
197+
#else
198+
if (!dry_run && unlink(path->buf)) {
199+
int saved_errno = errno;
200+
quote_path(path->buf, prefix, &quoted, 0);
201+
errno = saved_errno;
202+
warning_errno(_(msg_warn_remove_failed), quoted.buf);
203+
*dir_gone = 0;
204+
ret = -1;
205+
}
206+
#endif
194207

195208
goto out;
196209
}

compat/mingw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ static inline void convert_slashes(char *path)
457457
struct strbuf;
458458
int mingw_is_mount_point(struct strbuf *path);
459459
#define is_mount_point mingw_is_mount_point
460+
#define CAN_UNLINK_MOUNT_POINTS 1
460461
#define PATH_SEP ';'
461462
char *mingw_query_user_email(void);
462463
#define query_user_email mingw_query_user_email

t/t7300-clean.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,7 @@ test_expect_success MINGW 'clean does not traverse mount points' '
806806
git init with-mountpoint &&
807807
cmd //c "mklink /j with-mountpoint\\mountpoint target" &&
808808
git -C with-mountpoint clean -dfx &&
809+
test_path_is_missing with-mountpoint/mountpoint &&
809810
test_path_is_file target/dont-clean-me
810811
'
811812

0 commit comments

Comments
 (0)