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:
Junio C Hamano
2016-05-26 13:17:23 -07:00
8 changed files with 147 additions and 3 deletions

View File

@ -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;
}

View 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.
*