From: Johannes Sixt <johannes.sixt@xxxxxxxxxx> Junio, please pull the MinGW (Windows) port patch series from git://repo.or.cz/git/mingw/j6t.git for-junio The interdiff since I submitted the patch series http://thread.gmane.org/gmane.comp.version-control.git/75250/focus=76276 is below. This code base has been used in production since months, and editorial issues have been ironed out since I submitted the series. The interdiff is fairly small (it's mostly some new vsnprintf() fixes and a new utime() wrapper). The interdiff does not show that we don't need to modify git-clone.sh anymore ;) IMHO, this is material for 'next'. At this point I would like to thank all contributors to the porting effort. Some of your patches have been integrated in other patches in the series, which now carry my authorship (that is, I'm the one to blame), but I still have credited you in the commit message. Here's the patch summary: * Part 1: Get it going 01/38 Add compat/regex.[ch] and compat/fnmatch.[ch]. 02/38 Compile some programs only conditionally. 03/38 Add target architecture MinGW. With these patches we have a working git.exe that can successfully run those builtins that need only read-access of the repository, like git log, git diff, etc. * Part 2: Working locally is possible 04/38 Windows: Use the Windows style PATH separator ';'. 05/38 Windows: Strip ".exe" from the program name. 06/38 Windows: Implement a wrapper of the open() function. 07/38 Windows: A minimal implemention of getpwuid(). 08/38 Windows: always chmod(, 0666) before unlink(). 09/38 Windows: Work around misbehaved rename(). 10/38 setup.c: Prepare for Windows directory separators. 11/38 Windows: Treat Windows style path names. 12/38 Windows: Handle absolute paths in safe_create_leading_directories(). 13/38 Windows: Implement gettimeofday(). 14/38 Windows: Fix PRIuMAX definition. 15/38 Windows: Implement setitimer() and sigaction(). Now builtins that write to the repository work as long as they don't need to spawn secondary processes. * Part 3: Shell scripts and start_command() 16/38 Windows: Wrap execve so that shell scripts can be invoked. 17/38 Windows: A pipe() replacement whose ends are not inherited to children. 18/38 Windows: Implement start_command(). 19/38 Windows: Change the name of hook scripts to make them not executable. Now scripted tools and the builtins and standalone programs work that depend on start_command(). * Part 4: Remote connections 20/38 Windows: A rudimentary poll() emulation. 21/38 Windows: Disambiguate DOS style paths from SSH URLs. 22/38 Windows: Implement asynchronous functions as threads. 23/38 Windows: Work around incompatible sort and find. 24/38 Windows: Implement wrappers for gethostbyname(), socket(), and connect(). Remote connections, both push and fetch, using local transport as well as connections via ssh and native git protocol work. * Part 5: Optimizations 25/38 Windows: Implement a custom spawnve(). 26/38 Windows: Add a new lstat and fstat implementation based on Win32 API. 27/38 Windows: Add a custom implementation for utime(). 28/38 Windows: Use a customized struct stat that also has the st_blocks member. * Part 6: Tie up loose ends 29/38 Turn builtin_exec_path into a function. 30/38 Windows: Compute the fallback for exec_path from the program invocation. 31/38 Windows: Use a relative default template_dir and ETC_GITCONFIG 32/38 When installing, be prepared that template_dir may be relative. 33/38 Windows: Make the pager work. 34/38 Windows: Work around an oddity when a pipe with no reader is written to. 35/38 Windows: Make 'git help -a' work. 36/38 Windows: TMP and TEMP environment variables specify a temporary directory. 37/38 Windows: Fix ntohl() related warnings about printf formatting 38/38 compat/pread.c: Add a forward declaration to fix a warning This fixes some final remaining oddities, minor missing features, and works around differences between POSIX and Windows. Documentation/git.txt | 6 +- Makefile | 49 ++- cache.h | 2 +- compat/fnmatch.c | 488 +++++++++++++++++ compat/fnmatch.h | 84 +++ compat/mingw.c | 1008 +++++++++++++++++++++++++++++++++++ compat/mingw.h | 208 ++++++++ compat/regex.c | 4927 ++++++++++++++++++++(lots...) compat/regex.h | 490 +++++++++++++++++ compat/snprintf.c | 19 +- connect.c | 2 +- date.c | 2 +- exec_cmd.c | 41 ++- git-compat-util.h | 31 +- git-sh-setup.sh | 13 + git.c | 14 + help.c | 33 +- pager.c | 40 ++- path.c | 7 + run-command.c | 126 ++++- run-command.h | 5 + setup.c | 58 ++- sha1_file.c | 14 +- templates/Makefile | 11 +- transport.c | 3 +- upload-pack.c | 2 + write_or_die.c | 7 +- 27 files changed, 7617 insertions(+), 73 deletions(-) Interdiff follows (it's line wrapped, just for exposition): diff --git a/Makefile b/Makefile index 4ff82c9..ad4b779 100644 --- a/Makefile +++ b/Makefile @@ -1301,7 +1301,7 @@ remove-dashes: ifeq ($(firstword $(subst /, ,$(template_dir))),..) template_instdir = $(gitexecdir)/$(template_dir) else -template_instdir = $template_dir +template_instdir = $(template_dir) endif export template_instdir diff --git a/compat/mingw.c b/compat/mingw.c index 7c8fd0e..ee26df9 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -175,6 +175,33 @@ int mingw_fstat(int fd, struct mingw_stat *buf) return -1; } +static inline void time_t_to_filetime(time_t t, FILETIME *ft) +{ + long long winTime = t * 10000000LL + 116444736000000000LL; + ft->dwLowDateTime = winTime; + ft->dwHighDateTime = winTime >> 32; +} + +int mingw_utime (const char *file_name, const struct utimbuf *times) +{ + FILETIME mft, aft; + int fh, rc; + + /* must have write permission */ + if ((fh = open(file_name, O_RDWR | O_BINARY)) < 0) + return -1; + + time_t_to_filetime(times->modtime, &mft); + time_t_to_filetime(times->actime, &aft); + if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) { + errno = EINVAL; + rc = -1; + } else + rc = 0; + close(fh); + return rc; +} + unsigned int sleep (unsigned int seconds) { Sleep(seconds*1000); @@ -353,7 +380,7 @@ static const char *quote_arg(const char *arg) const char *p = arg; if (!*p) force_quotes = 1; while (*p) { - if (isspace(*p) || *p == '*' || *p == '?') + if (isspace(*p) || *p == '*' || *p == '?' || *p == '{') force_quotes = 1; else if (*p == '"') n++; diff --git a/compat/mingw.h b/compat/mingw.h index c7db345..6965e3f 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -24,6 +24,8 @@ typedef int pid_t; #define SIGKILL 0 #define SIGCHLD 0 #define SIGPIPE 0 +#define SIGHUP 0 +#define SIGQUIT 0 #define SIGALRM 100 #define F_GETFD 1 @@ -174,6 +176,9 @@ int mingw_fstat(int fd, struct mingw_stat *buf); static inline int mingw_stat(const char *file_name, struct mingw_stat *buf) { return mingw_lstat(file_name, buf); } +int mingw_utime(const char *file_name, const struct utimbuf *times); +#define utime mingw_utime + pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env); void mingw_execvp(const char *cmd, char *const *argv); #define execvp mingw_execvp diff --git a/compat/snprintf.c b/compat/snprintf.c index 480b66f..580966e 100644 --- a/compat/snprintf.c +++ b/compat/snprintf.c @@ -13,9 +13,13 @@ int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap) { char *s; - int ret; + int ret = -1; - ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap); + if (maxsize > 0) { + ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap); + /* Windows does not NUL-terminate if result fills buffer */ + str[maxsize-1] = 0; + } if (ret != -1) return ret; diff --git a/git-compat-util.h b/git-compat-util.h index cdfd54d..46fc2d3 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -66,12 +66,12 @@ #include <fnmatch.h> #include <assert.h> #include <regex.h> +#include <utime.h> #ifndef __MINGW32__ #include <sys/wait.h> #include <sys/poll.h> #include <sys/socket.h> #include <sys/ioctl.h> -#include <utime.h> #ifndef NO_SYS_SELECT_H #include <sys/select.h> #endif @@ -185,7 +185,7 @@ extern ssize_t git_pread(int fd, void *buf, size_t count, off_t offset); * This function is used in compat/pread.c. But we can't include * cache.h there. */ -extern int read_in_full(int fd, void *buf, size_t count); +extern ssize_t read_in_full(int fd, void *buf, size_t count); #ifdef NO_SETENV #define setenv gitsetenv diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 822aa6f..9cceb21 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -153,9 +153,5 @@ case $(uname -s) in find () { /usr/bin/find "$@" } - # sync is missing - sync () { - : # no implementation - } ;; esac diff --git a/t/test-lib.sh b/t/test-lib.sh index 51d90a3..c861141 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -441,16 +441,3 @@ do test_done esac done - -# Fix some commands on Windows -case $(uname -s) in -*MINGW*) - # Windows has its own (incompatible) sort and find - sort () { - /usr/bin/sort "$@" - } - find () { - /usr/bin/find "$@" - } - ;; -esac -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html