Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit 9af43a3

Browse files
committed
Merge 'hide-dotgit' into HEAD
2 parents ffa9869 + f8b7f55 commit 9af43a3

File tree

8 files changed

+111
-0
lines changed

8 files changed

+111
-0
lines changed

Documentation/config.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,12 @@ The default is true, except linkgit:git-clone[1] or linkgit:git-init[1]
212212
will probe and set core.fileMode false if appropriate when the
213213
repository is created.
214214

215+
core.hideDotFiles::
216+
(Windows-only) If true (which is the default), mark newly-created
217+
directories and files whose name starts with a dot as hidden.
218+
If 'dotGitOnly', only the .git/ directory is hidden, but no other
219+
files starting with a dot.
220+
215221
core.ignorecase::
216222
If true, this option enables various workarounds to enable
217223
Git to work better on filesystems that are not case sensitive,

builtin/init-db.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ int init_db(const char *template_dir, unsigned int flags)
385385
check_repository_format();
386386

387387
reinit = create_default_files(template_dir);
388+
mark_as_git_dir(get_git_dir());
388389

389390
create_object_directory();
390391

cache.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,13 @@ extern int precomposed_unicode;
641641
extern char comment_line_char;
642642
extern int auto_comment_line_char;
643643

644+
enum hide_dotfiles_type {
645+
HIDE_DOTFILES_FALSE = 0,
646+
HIDE_DOTFILES_TRUE,
647+
HIDE_DOTFILES_DOTGITONLY,
648+
};
649+
extern enum hide_dotfiles_type hide_dotfiles;
650+
644651
enum branch_track {
645652
BRANCH_TRACK_UNSPECIFIED = -1,
646653
BRANCH_TRACK_NEVER = 0,

compat/mingw.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "../cache.h"
88

99
static const int delay[] = { 0, 1, 10, 20, 40 };
10+
unsigned int _CRT_fmode = _O_BINARY;
1011

1112
int err_win_to_posix(DWORD winerr)
1213
{
@@ -284,13 +285,44 @@ int mingw_rmdir(const char *pathname)
284285
return ret;
285286
}
286287

288+
static int make_hidden(const wchar_t *path)
289+
{
290+
DWORD attribs = GetFileAttributesW(path);
291+
if (SetFileAttributesW(path, FILE_ATTRIBUTE_HIDDEN | attribs))
292+
return 0;
293+
errno = err_win_to_posix(GetLastError());
294+
return -1;
295+
}
296+
297+
void mingw_mark_as_git_dir(const char *dir)
298+
{
299+
wchar_t wdir[MAX_PATH];
300+
if (hide_dotfiles != HIDE_DOTFILES_FALSE && !is_bare_repository())
301+
if (xutftowcs_path(wdir, dir) < 0 || make_hidden(wdir))
302+
warning("Failed to make '%s' hidden", dir);
303+
git_config_set("core.hideDotFiles",
304+
hide_dotfiles == HIDE_DOTFILES_FALSE ? "false" :
305+
(hide_dotfiles == HIDE_DOTFILES_DOTGITONLY ?
306+
"dotGitOnly" : "true"));
307+
}
308+
287309
int mingw_mkdir(const char *path, int mode)
288310
{
289311
int ret;
290312
wchar_t wpath[MAX_PATH];
291313
if (xutftowcs_path(wpath, path) < 0)
292314
return -1;
293315
ret = _wmkdir(wpath);
316+
if (!ret && hide_dotfiles == HIDE_DOTFILES_TRUE) {
317+
/*
318+
* In Windows a file or dir starting with a dot is not
319+
* automatically hidden. So lets mark it as hidden when
320+
* such a directory is created.
321+
*/
322+
const char *start = basename((char*)path);
323+
if (*start == '.')
324+
return make_hidden(wpath);
325+
}
294326
return ret;
295327
}
296328

@@ -317,6 +349,17 @@ int mingw_open (const char *filename, int oflags, ...)
317349
if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
318350
errno = EISDIR;
319351
}
352+
if ((oflags & O_CREAT) && fd >= 0 &&
353+
hide_dotfiles == HIDE_DOTFILES_TRUE) {
354+
/*
355+
* In Windows a file or dir starting with a dot is not
356+
* automatically hidden. So lets mark it as hidden when
357+
* such a file is created.
358+
*/
359+
const char *start = basename((char*)filename);
360+
if (*start == '.' && make_hidden(wfilename))
361+
warning("Could not mark '%s' as hidden.", filename);
362+
}
320363
return fd;
321364
}
322365

@@ -348,27 +391,39 @@ int mingw_fgetc(FILE *stream)
348391
#undef fopen
349392
FILE *mingw_fopen (const char *filename, const char *otype)
350393
{
394+
int hide = 0;
351395
FILE *file;
352396
wchar_t wfilename[MAX_PATH], wotype[4];
397+
if (hide_dotfiles == HIDE_DOTFILES_TRUE &&
398+
basename((char*)filename)[0] == '.')
399+
hide = access(filename, F_OK);
353400
if (filename && !strcmp(filename, "/dev/null"))
354401
filename = "nul";
355402
if (xutftowcs_path(wfilename, filename) < 0 ||
356403
xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
357404
return NULL;
358405
file = _wfopen(wfilename, wotype);
406+
if (file && hide && make_hidden(wfilename))
407+
warning("Could not mark '%s' as hidden.", filename);
359408
return file;
360409
}
361410

362411
FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
363412
{
413+
int hide = 0;
364414
FILE *file;
365415
wchar_t wfilename[MAX_PATH], wotype[4];
416+
if (hide_dotfiles == HIDE_DOTFILES_TRUE &&
417+
basename((char*)filename)[0] == '.')
418+
hide = access(filename, F_OK);
366419
if (filename && !strcmp(filename, "/dev/null"))
367420
filename = "nul";
368421
if (xutftowcs_path(wfilename, filename) < 0 ||
369422
xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
370423
return NULL;
371424
file = _wfreopen(wfilename, wotype, stream);
425+
if (file && hide && make_hidden(wfilename))
426+
warning("Could not mark '%s' as hidden.", filename);
372427
return file;
373428
}
374429

config.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,15 @@ static int git_default_core_config(const char *var, const char *value)
872872
return 0;
873873
}
874874

875+
if (!strcmp(var, "core.hidedotfiles")) {
876+
if (value && !strcasecmp(value, "dotgitonly")) {
877+
hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
878+
return 0;
879+
}
880+
hide_dotfiles = git_config_bool(var, value);
881+
return 0;
882+
}
883+
875884
/* Add other config variables here and to Documentation/config.txt. */
876885
return 0;
877886
}

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ int merge_log_config = -1;
6363
int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
6464
struct startup_info *startup_info;
6565
unsigned long pack_size_limit_cfg;
66+
enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
6667

6768
/*
6869
* The character that begins a commented line in user-editable file

git-compat-util.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,4 +790,8 @@ struct tm *git_gmtime_r(const time_t *, struct tm *);
790790
#define gmtime_r git_gmtime_r
791791
#endif
792792

793+
#ifndef mark_as_git_dir
794+
#define mark_as_git_dir(x) /* noop */
795+
#endif
796+
793797
#endif

t/t0001-init.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,4 +332,32 @@ test_expect_success SYMLINKS 're-init to move gitdir symlink' '
332332
test_path_is_dir realgitdir/refs
333333
'
334334

335+
# Tests for the hidden file attribute on windows
336+
is_hidden () {
337+
test "1" -eq "$(echo puts [file attributes $1 -hidden]|tclsh)"
338+
}
339+
340+
test_expect_success MINGW 'plain hidden' '
341+
rm -rf newdir &&
342+
(
343+
unset GIT_DIR GIT_WORK_TREE
344+
mkdir newdir &&
345+
cd newdir &&
346+
git init &&
347+
is_hidden .git
348+
) &&
349+
check_config newdir/.git false unset
350+
'
351+
352+
test_expect_success MINGW 'plain bare not hidden' '
353+
rm -rf newdir
354+
(
355+
unset GIT_DIR GIT_WORK_TREE GIT_CONFIG
356+
mkdir newdir &&
357+
cd newdir &&
358+
git --bare init
359+
) &&
360+
! is_hidden newdir
361+
'
362+
335363
test_done

0 commit comments

Comments
 (0)