Merge branch 'js/windows-dotgit' into maint
On Windows, .git and optionally any files whose name starts with a dot are now marked as hidden, with a core.hideDotFiles knob to customize this behaviour. * js/windows-dotgit: mingw: remove unnecessary definition mingw: introduce the 'core.hideDotFiles' setting
This commit is contained in:
@ -286,6 +286,49 @@ int mingw_rmdir(const char *pathname)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int needs_hiding(const char *path)
|
||||
{
|
||||
const char *basename;
|
||||
|
||||
if (hide_dotfiles == HIDE_DOTFILES_FALSE)
|
||||
return 0;
|
||||
|
||||
/* We cannot use basename(), as it would remove trailing slashes */
|
||||
mingw_skip_dos_drive_prefix((char **)&path);
|
||||
if (!*path)
|
||||
return 0;
|
||||
|
||||
for (basename = path; *path; path++)
|
||||
if (is_dir_sep(*path)) {
|
||||
do {
|
||||
path++;
|
||||
} while (is_dir_sep(*path));
|
||||
/* ignore trailing slashes */
|
||||
if (*path)
|
||||
basename = path;
|
||||
}
|
||||
|
||||
if (hide_dotfiles == HIDE_DOTFILES_TRUE)
|
||||
return *basename == '.';
|
||||
|
||||
assert(hide_dotfiles == HIDE_DOTFILES_DOTGITONLY);
|
||||
return !strncasecmp(".git", basename, 4) &&
|
||||
(!basename[4] || is_dir_sep(basename[4]));
|
||||
}
|
||||
|
||||
static int set_hidden_flag(const wchar_t *path, int set)
|
||||
{
|
||||
DWORD original = GetFileAttributesW(path), modified;
|
||||
if (set)
|
||||
modified = original | FILE_ATTRIBUTE_HIDDEN;
|
||||
else
|
||||
modified = original & ~FILE_ATTRIBUTE_HIDDEN;
|
||||
if (original == modified || SetFileAttributesW(path, modified))
|
||||
return 0;
|
||||
errno = err_win_to_posix(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mingw_mkdir(const char *path, int mode)
|
||||
{
|
||||
int ret;
|
||||
@ -293,6 +336,8 @@ int mingw_mkdir(const char *path, int mode)
|
||||
if (xutftowcs_path(wpath, path) < 0)
|
||||
return -1;
|
||||
ret = _wmkdir(wpath);
|
||||
if (!ret && needs_hiding(path))
|
||||
return set_hidden_flag(wpath, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -319,6 +364,21 @@ int mingw_open (const char *filename, int oflags, ...)
|
||||
if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
|
||||
errno = EISDIR;
|
||||
}
|
||||
if ((oflags & O_CREAT) && needs_hiding(filename)) {
|
||||
/*
|
||||
* Internally, _wopen() uses the CreateFile() API which errors
|
||||
* out with an ERROR_ACCESS_DENIED if CREATE_ALWAYS was
|
||||
* specified and an already existing file's attributes do not
|
||||
* match *exactly*. As there is no mode or flag we can set that
|
||||
* would correspond to FILE_ATTRIBUTE_HIDDEN, let's just try
|
||||
* again *without* the O_CREAT flag (that corresponds to the
|
||||
* CREATE_ALWAYS flag of CreateFile()).
|
||||
*/
|
||||
if (fd < 0 && errno == EACCES)
|
||||
fd = _wopen(wfilename, oflags & ~O_CREAT, mode);
|
||||
if (fd >= 0 && set_hidden_flag(wfilename, 1))
|
||||
warning("could not mark '%s' as hidden.", filename);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
@ -350,6 +410,7 @@ int mingw_fgetc(FILE *stream)
|
||||
#undef fopen
|
||||
FILE *mingw_fopen (const char *filename, const char *otype)
|
||||
{
|
||||
int hide = needs_hiding(filename);
|
||||
FILE *file;
|
||||
wchar_t wfilename[MAX_PATH], wotype[4];
|
||||
if (filename && !strcmp(filename, "/dev/null"))
|
||||
@ -357,12 +418,19 @@ FILE *mingw_fopen (const char *filename, const char *otype)
|
||||
if (xutftowcs_path(wfilename, filename) < 0 ||
|
||||
xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
|
||||
return NULL;
|
||||
if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
|
||||
error("could not unhide %s", filename);
|
||||
return NULL;
|
||||
}
|
||||
file = _wfopen(wfilename, wotype);
|
||||
if (file && hide && set_hidden_flag(wfilename, 1))
|
||||
warning("could not mark '%s' as hidden.", filename);
|
||||
return file;
|
||||
}
|
||||
|
||||
FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
|
||||
{
|
||||
int hide = needs_hiding(filename);
|
||||
FILE *file;
|
||||
wchar_t wfilename[MAX_PATH], wotype[4];
|
||||
if (filename && !strcmp(filename, "/dev/null"))
|
||||
@ -370,7 +438,13 @@ FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
|
||||
if (xutftowcs_path(wfilename, filename) < 0 ||
|
||||
xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
|
||||
return NULL;
|
||||
if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
|
||||
error("could not unhide %s", filename);
|
||||
return NULL;
|
||||
}
|
||||
file = _wfreopen(wfilename, wotype, stream);
|
||||
if (file && hide && set_hidden_flag(wfilename, 1))
|
||||
warning("could not mark '%s' as hidden.", filename);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
@ -417,9 +417,6 @@ int mingw_offset_1st_component(const char *path);
|
||||
void mingw_open_html(const char *path);
|
||||
#define open_html mingw_open_html
|
||||
|
||||
void mingw_mark_as_git_dir(const char *dir);
|
||||
#define mark_as_git_dir mingw_mark_as_git_dir
|
||||
|
||||
/**
|
||||
* Converts UTF-8 encoded string to UTF-16LE.
|
||||
*
|
||||
|
Reference in New Issue
Block a user