Skip to content

Commit

Permalink
clean: remove mount points when possible
Browse files Browse the repository at this point in the history
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 <johannes.schindelin@gmx.de>
  • Loading branch information
dscho committed Sep 24, 2024
1 parent d806221 commit 8bb6c1e
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 0 deletions.
13 changes: 13 additions & 0 deletions builtin/clean.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ static const char *msg_remove = N_("Removing %s\n");
static const char *msg_would_remove = N_("Would remove %s\n");
static const char *msg_skip_git_dir = N_("Skipping repository %s\n");
static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n");
#ifndef CAN_UNLINK_MOUNT_POINTS
static const char *msg_skip_mount_point = N_("Skipping mount point %s\n");
static const char *msg_would_skip_mount_point = N_("Would skip mount point %s\n");
#endif
static const char *msg_warn_remove_failed = N_("failed to remove %s");
static const char *msg_warn_lstat_failed = N_("could not lstat %s\n");
static const char *msg_skip_cwd = N_("Refusing to remove current working directory\n");
Expand Down Expand Up @@ -185,13 +187,24 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
}

if (is_mount_point(path)) {
#ifndef CAN_UNLINK_MOUNT_POINTS
if (!quiet) {
quote_path(path->buf, prefix, &quoted, 0);
printf(dry_run ?
_(msg_would_skip_mount_point) :
_(msg_skip_mount_point), quoted.buf);
}
*dir_gone = 0;
#else
if (!dry_run && unlink(path->buf)) {
int saved_errno = errno;
quote_path(path->buf, prefix, &quoted, 0);
errno = saved_errno;
warning_errno(_(msg_warn_remove_failed), quoted.buf);
*dir_gone = 0;
ret = -1;
}
#endif

goto out;
}
Expand Down
1 change: 1 addition & 0 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ static inline void convert_slashes(char *path)
struct strbuf;
int mingw_is_mount_point(struct strbuf *path);
#define is_mount_point mingw_is_mount_point
#define CAN_UNLINK_MOUNT_POINTS 1
#define PATH_SEP ';'
char *mingw_query_user_email(void);
#define query_user_email mingw_query_user_email
Expand Down
1 change: 1 addition & 0 deletions t/t7300-clean.sh
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,7 @@ test_expect_success MINGW 'clean does not traverse mount points' '
git init with-mountpoint &&
cmd //c "mklink /j with-mountpoint\\mountpoint target" &&
git -C with-mountpoint clean -dfx &&
test_path_is_missing with-mountpoint/mountpoint &&
test_path_is_file target/dont-clean-me
'

Expand Down

0 comments on commit 8bb6c1e

Please sign in to comment.