From 1e6719438f2e75a540747c3f689711da717c3315 Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Wed, 16 Dec 2009 22:20:55 +0100 Subject: [PATCH] core.hidedotfiles: hide '.git' dir by default At least for cross-platform projects, it makes sense to hide the files starting with a dot, as this is the behavior on Unix/MacOSX. However, at least Eclipse has problems interpreting the hidden flag correctly, so the default is to hide only the .git/ directory. The config setting core.hideDotFiles therefore supports not only 'true' and 'false', but also 'dotGitOnly'. [jes: clarified the commit message, made git init respect the setting by marking the .git/ directory only after reading the config, and added documentation, and rebased on top of current junio/next] Signed-off-by: Erik Faye-Lund Signed-off-by: Johannes Schindelin --- Documentation/config.txt | 6 +++++ builtin/init-db.c | 1 + cache.h | 7 +++++ compat/mingw.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++-- compat/mingw.h | 8 +++--- config.c | 9 +++++++ environment.c | 1 + git-compat-util.h | 4 +++ 8 files changed, 96 insertions(+), 6 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index dc4e83b103..a864088266 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -154,6 +154,12 @@ The default is true, except linkgit:git-clone[1] or linkgit:git-init[1] will probe and set core.fileMode false if appropriate when the repository is created. +core.hideDotFiles:: + (Windows-only) If true (which is the default), mark newly-created + directories and files whose name starts with a dot as hidden. + If 'dotGitOnly', only the .git/ directory is hidden, but no other + files starting with a dot. + core.ignoreCygwinFSTricks:: This option is only used by Cygwin implementation of Git. If false, the Cygwin stat() and lstat() functions are used. This may be useful diff --git a/builtin/init-db.c b/builtin/init-db.c index 0271285fad..ea6ea8b431 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -312,6 +312,7 @@ int init_db(const char *template_dir, unsigned int flags) check_repository_format(); reinit = create_default_files(template_dir); + mark_as_git_dir(get_git_dir()); sha1_dir = get_object_directory(); len = strlen(sha1_dir); diff --git a/cache.h b/cache.h index 1e690d1240..1b354b5b51 100644 --- a/cache.h +++ b/cache.h @@ -552,6 +552,13 @@ extern int fsync_object_files; extern int core_preload_index; extern int core_apply_sparse_checkout; +enum hide_dotfiles_type { + HIDE_DOTFILES_FALSE = 0, + HIDE_DOTFILES_TRUE, + HIDE_DOTFILES_DOTGITONLY, +}; +extern enum hide_dotfiles_type hide_dotfiles; + enum safe_crlf { SAFE_CRLF_FALSE = 0, SAFE_CRLF_FAIL = 1, diff --git a/compat/mingw.c b/compat/mingw.c index f2d9e1fd97..9f6df8762d 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2,6 +2,9 @@ #include "win32.h" #include #include "../strbuf.h" +#include "../cache.h" + +unsigned int _CRT_fmode = _O_BINARY; int err_win_to_posix(DWORD winerr) { @@ -116,6 +119,38 @@ int err_win_to_posix(DWORD winerr) return error; } +static int make_hidden(const char *path) +{ + DWORD attribs = GetFileAttributes(path); + if (SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN | attribs)) + return 0; + errno = err_win_to_posix(GetLastError()); + return -1; +} + +void mingw_mark_as_git_dir(const char *dir) +{ + if (hide_dotfiles != HIDE_DOTFILES_FALSE && make_hidden(dir)) + warning("Failed to make '%s' hidden", dir); +} + +#undef mkdir +int mingw_mkdir(const char *path, int mode) +{ + int ret = mkdir(path); + if (!ret && hide_dotfiles == HIDE_DOTFILES_TRUE) { + /* + * In Windows a file or dir starting with a dot is not + * automatically hidden. So lets mark it as hidden when + * such a directory is created. + */ + const char *start = basename((char*)path); + if (*start == '.') + return make_hidden(path); + } + return ret; +} + #undef open int mingw_open (const char *filename, int oflags, ...) { @@ -137,6 +172,17 @@ int mingw_open (const char *filename, int oflags, ...) if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) errno = EISDIR; } + if ((oflags & O_CREAT) && fd >= 0 && + hide_dotfiles == HIDE_DOTFILES_TRUE) { + /* + * In Windows a file or dir starting with a dot is not + * automatically hidden. So lets mark it as hidden when + * such a file is created. + */ + const char *start = basename((char*)filename); + if (*start == '.' && make_hidden(filename)) + warning("Could not mark '%s' as hidden.", filename); + } return fd; } @@ -160,17 +206,33 @@ ssize_t mingw_write(int fd, const void *buf, size_t count) #undef fopen FILE *mingw_fopen (const char *filename, const char *otype) { + int hide = 0; + FILE *file; + if (hide_dotfiles == HIDE_DOTFILES_TRUE && + basename((char*)filename)[0] == '.') + hide = access(filename, F_OK); if (!strcmp(filename, "/dev/null")) filename = "nul"; - return fopen(filename, otype); + file = fopen(filename, otype); + if (file && hide && make_hidden(filename)) + warning("Could not mark '%s' as hidden.", filename); + return file; } #undef freopen FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream) { + int hide = 0; + FILE *file; + if (hide_dotfiles == HIDE_DOTFILES_TRUE && + basename((char*)filename)[0] == '.') + hide = access(filename, F_OK); if (filename && !strcmp(filename, "/dev/null")) filename = "nul"; - return freopen(filename, otype, stream); + file = freopen(filename, otype, stream); + if (file && hide && make_hidden(filename)) + warning("Could not mark '%s' as hidden.", filename); + return file; } /* diff --git a/compat/mingw.h b/compat/mingw.h index 74c799ad38..7bbef44210 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -116,10 +116,7 @@ static inline int fcntl(int fd, int cmd, ...) * simple adaptors */ -static inline int mingw_mkdir(const char *path, int mode) -{ - return mkdir(path); -} +int mingw_mkdir(const char *path, int mode); #define mkdir mingw_mkdir static inline int mingw_unlink(const char *pathname) @@ -280,6 +277,9 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format 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 + /* * helpers */ diff --git a/config.c b/config.c index cdcf5836c6..42e94f991b 100644 --- a/config.c +++ b/config.c @@ -595,6 +595,15 @@ static int git_default_core_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.hidedotfiles")) { + if (value && !strcasecmp(value, "dotgitonly")) { + hide_dotfiles = HIDE_DOTFILES_DOTGITONLY; + return 0; + } + hide_dotfiles = git_config_bool(var, value); + return 0; + } + /* Add other config variables here and to Documentation/config.txt. */ return 0; } diff --git a/environment.c b/environment.c index 83d38d3c23..ee3243c3d6 100644 --- a/environment.c +++ b/environment.c @@ -53,6 +53,7 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE; char *notes_ref_name; int grafts_replace_parents = 1; int core_apply_sparse_checkout; +enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY; /* Parallel index stat data preload? */ int core_preload_index = 0; diff --git a/git-compat-util.h b/git-compat-util.h index fe845ae639..930cc5c217 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -505,4 +505,8 @@ int rmdir_or_warn(const char *path); */ int remove_or_warn(unsigned int mode, const char *path); +#ifndef mark_as_git_dir +#define mark_as_git_dir(x) /* noop */ +#endif + #endif -- 2.11.4.GIT