Skip to content

Commit 3356b55

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 1273bef commit 3356b55

File tree

3 files changed

+15
-0
lines changed

3 files changed

+15
-0
lines changed

builtin/clean.c

+13
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ static const char *msg_remove = N_("Removing %s\n");
3434
static const char *msg_would_remove = N_("Would remove %s\n");
3535
static const char *msg_skip_git_dir = N_("Skipping repository %s\n");
3636
static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n");
37+
#ifndef CAN_UNLINK_MOUNT_POINTS
3738
static const char *msg_skip_mount_point = N_("Skipping mount point %s\n");
3839
static const char *msg_would_skip_mount_point = N_("Would skip mount point %s\n");
40+
#endif
3941
static const char *msg_warn_remove_failed = N_("failed to remove %s");
4042
static const char *msg_warn_lstat_failed = N_("could not lstat %s\n");
4143
static const char *msg_skip_cwd = N_("Refusing to remove current working directory\n");
@@ -178,13 +180,24 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
178180
}
179181

180182
if (is_mount_point(path)) {
183+
#ifndef CAN_UNLINK_MOUNT_POINTS
181184
if (!quiet) {
182185
quote_path(path->buf, prefix, &quoted, 0);
183186
printf(dry_run ?
184187
_(msg_would_skip_mount_point) :
185188
_(msg_skip_mount_point), quoted.buf);
186189
}
187190
*dir_gone = 0;
191+
#else
192+
if (!dry_run && unlink(path->buf)) {
193+
int saved_errno = errno;
194+
quote_path(path->buf, prefix, &quoted, 0);
195+
errno = saved_errno;
196+
warning_errno(_(msg_warn_remove_failed), quoted.buf);
197+
*dir_gone = 0;
198+
ret = -1;
199+
}
200+
#endif
188201

189202
goto out;
190203
}

compat/mingw.h

+1
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ static inline void convert_slashes(char *path)
452452
struct strbuf;
453453
int mingw_is_mount_point(struct strbuf *path);
454454
#define is_mount_point mingw_is_mount_point
455+
#define CAN_UNLINK_MOUNT_POINTS 1
455456
#define PATH_SEP ';'
456457
char *mingw_query_user_email(void);
457458
#define query_user_email mingw_query_user_email

t/t7300-clean.sh

+1
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ test_expect_success MINGW 'clean does not traverse mount points' '
795795
git init with-mountpoint &&
796796
cmd //c "mklink /j with-mountpoint\\mountpoint target" &&
797797
git -C with-mountpoint clean -dfx &&
798+
test_path_is_missing with-mountpoint/mountpoint &&
798799
test_path_is_file target/dont-clean-me
799800
'
800801

0 commit comments

Comments
 (0)