From 9c65c3077da54857cc3c5b6fd161b0cbf1d20448 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 | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ config.c | 9 +++++++++ environment.c | 1 + git-compat-util.h | 4 ++++ 7 files changed, 80 insertions(+) diff --git a/Documentation/config.txt b/Documentation/config.txt index c26a7c8469..9ce009f216 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -213,6 +213,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.ignorecase:: If true, this option enables various workarounds to enable Git to work better on filesystems that are not case sensitive, diff --git a/builtin/init-db.c b/builtin/init-db.c index c7c76bbf21..b96ed9e545 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -385,6 +385,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()); create_object_directory(); diff --git a/cache.h b/cache.h index ebe9a405d8..2ab5dd45b2 100644 --- a/cache.h +++ b/cache.h @@ -594,6 +594,13 @@ extern int precomposed_unicode; */ extern char comment_line_char; +enum hide_dotfiles_type { + HIDE_DOTFILES_FALSE = 0, + HIDE_DOTFILES_TRUE, + HIDE_DOTFILES_DOTGITONLY, +}; +extern enum hide_dotfiles_type hide_dotfiles; + enum branch_track { BRANCH_TRACK_UNSPECIFIED = -1, BRANCH_TRACK_NEVER = 0, diff --git a/compat/mingw.c b/compat/mingw.c index 79bac118ba..d2c17c7024 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -4,8 +4,10 @@ #include #include "../strbuf.h" #include "../run-command.h" +#include "../cache.h" static const int delay[] = { 0, 1, 10, 20, 40 }; +unsigned int _CRT_fmode = _O_BINARY; int err_win_to_posix(DWORD winerr) { @@ -283,6 +285,23 @@ int mingw_rmdir(const char *pathname) return ret; } +static int make_hidden(const wchar_t *path) +{ + DWORD attribs = GetFileAttributesW(path); + if (SetFileAttributesW(path, FILE_ATTRIBUTE_HIDDEN | attribs)) + return 0; + errno = err_win_to_posix(GetLastError()); + return -1; +} + +void mingw_mark_as_git_dir(const char *dir) +{ + wchar_t wdir[MAX_PATH]; + if (hide_dotfiles != HIDE_DOTFILES_FALSE && !is_bare_repository()) + if (xutftowcs_path(wdir, dir) < 0 || make_hidden(wdir)) + warning("Failed to make '%s' hidden", dir); +} + int mingw_mkdir(const char *path, int mode) { int ret; @@ -290,6 +309,16 @@ int mingw_mkdir(const char *path, int mode) if (xutftowcs_path(wpath, path) < 0) return -1; ret = _wmkdir(wpath); + 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(wpath); + } return ret; } @@ -316,6 +345,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(wfilename)) + warning("Could not mark '%s' as hidden.", filename); + } return fd; } @@ -347,27 +387,39 @@ int mingw_fgetc(FILE *stream) #undef fopen FILE *mingw_fopen (const char *filename, const char *otype) { + int hide = 0; FILE *file; wchar_t wfilename[MAX_PATH], wotype[4]; + if (hide_dotfiles == HIDE_DOTFILES_TRUE && + basename((char*)filename)[0] == '.') + hide = access(filename, F_OK); if (filename && !strcmp(filename, "/dev/null")) filename = "nul"; if (xutftowcs_path(wfilename, filename) < 0 || xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0) return NULL; file = _wfopen(wfilename, wotype); + if (file && hide && make_hidden(wfilename)) + warning("Could not mark '%s' as hidden.", filename); return file; } FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream) { + int hide = 0; FILE *file; wchar_t wfilename[MAX_PATH], wotype[4]; + if (hide_dotfiles == HIDE_DOTFILES_TRUE && + basename((char*)filename)[0] == '.') + hide = access(filename, F_OK); if (filename && !strcmp(filename, "/dev/null")) filename = "nul"; if (xutftowcs_path(wfilename, filename) < 0 || xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0) return NULL; file = _wfreopen(wfilename, wotype, stream); + if (file && hide && make_hidden(wfilename)) + warning("Could not mark '%s' as hidden.", filename); return file; } diff --git a/config.c b/config.c index 314d8ee740..65b6038479 100644 --- a/config.c +++ b/config.c @@ -885,6 +885,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 4a3437d8a6..3663cbc5b4 100644 --- a/environment.c +++ b/environment.c @@ -63,6 +63,7 @@ int merge_log_config = -1; int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */ struct startup_info *startup_info; unsigned long pack_size_limit_cfg; +enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY; /* * The character that begins a commented line in user-editable file diff --git a/git-compat-util.h b/git-compat-util.h index d493a8c67a..34bb73dbc8 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -728,4 +728,8 @@ struct tm *git_gmtime_r(const time_t *, struct tm *); #define gmtime_r git_gmtime_r #endif +#ifndef mark_as_git_dir +#define mark_as_git_dir(x) /* noop */ +#endif + #endif -- 2.11.4.GIT