Skip to content

Instantly share code, notes, and snippets.

@orgads
Created October 17, 2017 08:37
Show Gist options
  • Select an option

  • Save orgads/4dbfec4399e7f9b3b15562ba442243a4 to your computer and use it in GitHub Desktop.

Select an option

Save orgads/4dbfec4399e7f9b3b15562ba442243a4 to your computer and use it in GitHub Desktop.
From 279ba0e55bc33d2094dd0ba21347aa6758db4b2a Mon Sep 17 00:00:00 2001
From: Orgad Shaneh <orgads@gmail.com>
Date: Tue, 17 Oct 2017 11:33:31 +0300
Subject: [PATCH] Fix clean for files named NUL on Windows
Use absolute path with //./ prefix to allow deleting these files.
---
builtin/clean.c | 21 +++++++++++----------
strbuf.c | 3 +++
2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/builtin/clean.c b/builtin/clean.c
index 733b6d374..6b4f372dd 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -897,14 +897,14 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
- struct strbuf abs_path = STRBUF_INIT;
+ struct strbuf rel_path = STRBUF_INIT;
struct dir_struct dir;
struct pathspec pathspec;
struct strbuf buf = STRBUF_INIT;
struct string_list exclude_list = STRING_LIST_INIT_NODUP;
struct exclude_list *el;
struct string_list_item *item;
- const char *qname;
+ const char *qname, *abs_path;
struct option options[] = {
OPT__QUIET(&quiet, N_("do not print names of files removed")),
OPT__DRY_RUN(&dry_run, N_("dry run")),
@@ -985,7 +985,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (pathspec.nr && !matches)
continue;
- if (lstat(ent->name, &st))
+ if (lstat(absolute_path(ent->name), &st))
die_errno("Cannot lstat '%s'", ent->name);
if (S_ISDIR(st.st_mode) && !remove_directories &&
@@ -1009,27 +1009,28 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
struct stat st;
if (prefix)
- strbuf_addstr(&abs_path, prefix);
+ strbuf_addstr(&rel_path, prefix);
- strbuf_addstr(&abs_path, item->string);
+ strbuf_addstr(&rel_path, item->string);
+ abs_path = absolute_path(rel_path.buf);
/*
* we might have removed this as part of earlier
* recursive directory removal, so lstat() here could
* fail with ENOENT.
*/
- if (lstat(abs_path.buf, &st))
+ if (lstat(abs_path, &st))
continue;
if (S_ISDIR(st.st_mode)) {
- if (remove_dirs(&abs_path, prefix, rm_flags, dry_run, quiet, &gone))
+ if (remove_dirs(&rel_path, prefix, rm_flags, dry_run, quiet, &gone))
errors++;
if (gone && !quiet) {
qname = quote_path_relative(item->string, NULL, &buf);
printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
}
} else {
- res = dry_run ? 0 : unlink(abs_path.buf);
+ res = dry_run ? 0 : unlink(abs_path);
if (res) {
int saved_errno = errno;
qname = quote_path_relative(item->string, NULL, &buf);
@@ -1041,10 +1042,10 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
}
}
- strbuf_reset(&abs_path);
+ strbuf_reset(&rel_path);
}
- strbuf_release(&abs_path);
+ strbuf_release(&rel_path);
strbuf_release(&buf);
string_list_clear(&del_list, 0);
string_list_clear(&exclude_list, 0);
diff --git a/strbuf.c b/strbuf.c
index 323c49ceb..1ff3e259a 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -696,6 +696,9 @@ void strbuf_add_absolute_path(struct strbuf *sb, const char *path)
size_t orig_len = sb->len;
char *cwd = xgetcwd();
char *pwd = getenv("PWD");
+#ifdef _WIN32
+ strbuf_addstr(sb, "//./");
+#endif
if (pwd && strcmp(pwd, cwd) &&
!stat(cwd, &cwd_stat) &&
(cwd_stat.st_dev || cwd_stat.st_ino) &&
--
2.14.2.windows.3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment