help: make option --help open man pages only for Git commands
[gitweb.git] / compat / mingw.c
index 0413d5c3cdd128ca721c75b588dc557bdbb1f949..3fbfda5978b7bb715ab132283a69fa49384896e9 100644 (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;
 }
 
@@ -1856,48 +1930,6 @@ int mingw_raise(int sig)
        }
 }
 
-
-static const char *make_backslash_path(const char *path)
-{
-       static char buf[PATH_MAX + 1];
-       char *c;
-
-       if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-               die("Too long path: %.*s", 60, path);
-
-       for (c = buf; *c; c++) {
-               if (*c == '/')
-                       *c = '\\';
-       }
-       return buf;
-}
-
-void mingw_open_html(const char *unixpath)
-{
-       const char *htmlpath = make_backslash_path(unixpath);
-       typedef HINSTANCE (WINAPI *T)(HWND, const char *,
-                       const char *, const char *, const char *, INT);
-       T ShellExecute;
-       HMODULE shell32;
-       int r;
-
-       shell32 = LoadLibrary("shell32.dll");
-       if (!shell32)
-               die("cannot load shell32.dll");
-       ShellExecute = (T)GetProcAddress(shell32, "ShellExecuteA");
-       if (!ShellExecute)
-               die("cannot run browser");
-
-       printf("Launching default browser to display HTML ...\n");
-       r = HCAST(int, ShellExecute(NULL, "open", htmlpath,
-                               NULL, "\\", SW_SHOWNORMAL));
-       FreeLibrary(shell32);
-       /* see the MSDN documentation referring to the result codes here */
-       if (r <= 32) {
-               die("failed to launch browser for %.*s", MAX_PATH, unixpath);
-       }
-}
-
 int link(const char *oldpath, const char *newpath)
 {
        typedef BOOL (WINAPI *T)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
@@ -2088,7 +2120,7 @@ int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen)
        return -1;
 }
 
-static void setup_windows_environment()
+static void setup_windows_environment(void)
 {
        char *tmp = getenv("TMPDIR");
 
@@ -2130,7 +2162,7 @@ typedef struct {
 extern int __wgetmainargs(int *argc, wchar_t ***argv, wchar_t ***env, int glob,
                _startupinfo *si);
 
-static NORETURN void die_startup()
+static NORETURN void die_startup(void)
 {
        fputs("fatal: not enough memory for initialization", stderr);
        exit(128);
@@ -2150,7 +2182,7 @@ static char *wcstoutfdup_startup(char *buffer, const wchar_t *wcs, size_t len)
        return memcpy(malloc_startup(len), buffer, len);
 }
 
-void mingw_startup()
+void mingw_startup(void)
 {
        int i, maxlen, argc;
        char *buffer;