{"thread":{"id":"14054","subject":"MinGW port pull request","startedAt":"2008-06-20T08:06:40Z","lastAt":"2008-06-24T13:01:13Z","messageCount":7,"participants":["Johannes Sixt","Junio C Hamano","Jim Raden"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"80444","messageId":"485B6510.3080201@viscovery.net","threadId":"14054","inReplyTo":null,"subject":"MinGW port pull request","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-06-20T08:06:40Z","receivedAt":"2008-06-20T08:06:40Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"From: Johannes Sixt <johannes.sixt@telecom.at>\n\nJunio,\n\nplease pull the MinGW (Windows) port patch series from\n\ngit://repo.or.cz/git/mingw/j6t.git for-junio\n\nThe interdiff since I submitted the patch series\n\n http://thread.gmane.org/gmane.comp.version-control.git/75250/focus=76276\n\nis below.\n\nThis code base has been used in production since months, and editorial\nissues have been ironed out since I submitted the series. The interdiff is\nfairly small (it's mostly some new vsnprintf() fixes and a new utime()\nwrapper). The interdiff does not show that we don't need to modify\ngit-clone.sh anymore ;) IMHO, this is material for 'next'.\n\nAt this point I would like to thank all contributors to the porting\neffort. Some of your patches have been integrated in other patches in the\nseries, which now carry my authorship (that is, I'm the one to blame), but\nI still have credited you in the commit message.\n\n\nHere's the patch summary:\n\n* Part 1: Get it going\n01/38 Add compat/regex.[ch] and compat/fnmatch.[ch].\n02/38 Compile some programs only conditionally.\n03/38 Add target architecture MinGW.\n\nWith these patches we have a working git.exe that can successfully run\nthose builtins that need only read-access of the repository, like\ngit log, git diff, etc.\n\n* Part 2: Working locally is possible\n04/38 Windows: Use the Windows style PATH separator ';'.\n05/38 Windows: Strip \".exe\" from the program name.\n06/38 Windows: Implement a wrapper of the open() function.\n07/38 Windows: A minimal implemention of getpwuid().\n08/38 Windows: always chmod(, 0666) before unlink().\n09/38 Windows: Work around misbehaved rename().\n10/38 setup.c: Prepare for Windows directory separators.\n11/38 Windows: Treat Windows style path names.\n12/38 Windows: Handle absolute paths in safe_create_leading_directories().\n13/38 Windows: Implement gettimeofday().\n14/38 Windows: Fix PRIuMAX definition.\n15/38 Windows: Implement setitimer() and sigaction().\n\nNow builtins that write to the repository work as long as they don't need\nto spawn secondary processes.\n\n* Part 3: Shell scripts and start_command()\n16/38 Windows: Wrap execve so that shell scripts can be invoked.\n17/38 Windows: A pipe() replacement whose ends are not inherited to\n      children.\n18/38 Windows: Implement start_command().\n19/38 Windows: Change the name of hook scripts to make them not\n      executable.\n\nNow scripted tools and the builtins and standalone programs work that\ndepend on start_command().\n\n* Part 4: Remote connections\n20/38 Windows: A rudimentary poll() emulation.\n21/38 Windows: Disambiguate DOS style paths from SSH URLs.\n22/38 Windows: Implement asynchronous functions as threads.\n23/38 Windows: Work around incompatible sort and find.\n24/38 Windows: Implement wrappers for gethostbyname(), socket(), and\n      connect().\n\nRemote connections, both push and fetch, using local transport as well as\nconnections via ssh and native git protocol work.\n\n* Part 5: Optimizations\n25/38 Windows: Implement a custom spawnve().\n26/38 Windows: Add a new lstat and fstat implementation based on Win32\n      API.\n27/38 Windows: Add a custom implementation for utime().\n28/38 Windows: Use a customized struct stat that also has the st_blocks\n      member.\n\n* Part 6: Tie up loose ends\n29/38 Turn builtin_exec_path into a function.\n30/38 Windows: Compute the fallback for exec_path from the program\n      invocation.\n31/38 Windows: Use a relative default template_dir and ETC_GITCONFIG\n32/38 When installing, be prepared that template_dir may be relative.\n33/38 Windows: Make the pager work.\n34/38 Windows: Work around an oddity when a pipe with no reader is written\n      to.\n35/38 Windows: Make 'git help -a' work.\n36/38 Windows: TMP and TEMP environment variables specify a temporary\n      directory.\n37/38 Windows: Fix ntohl() related warnings about printf formatting\n38/38 compat/pread.c: Add a forward declaration to fix a warning\n\nThis fixes some final remaining oddities, minor missing features, and\nworks around differences between POSIX and Windows.\n\n\n Documentation/git.txt |    6 +-\n Makefile              |   49 ++-\n cache.h               |    2 +-\n compat/fnmatch.c      |  488 +++++++++++++++++\n compat/fnmatch.h      |   84 +++\n compat/mingw.c        | 1008 +++++++++++++++++++++++++++++++++++\n compat/mingw.h        |  208 ++++++++\n compat/regex.c        | 4927 ++++++++++++++++++++(lots...)\n compat/regex.h        |  490 +++++++++++++++++\n compat/snprintf.c     |   19 +-\n connect.c             |    2 +-\n date.c                |    2 +-\n exec_cmd.c            |   41 ++-\n git-compat-util.h     |   31 +-\n git-sh-setup.sh       |   13 +\n git.c                 |   14 +\n help.c                |   33 +-\n pager.c               |   40 ++-\n path.c                |    7 +\n run-command.c         |  126 ++++-\n run-command.h         |    5 +\n setup.c               |   58 ++-\n sha1_file.c           |   14 +-\n templates/Makefile    |   11 +-\n transport.c           |    3 +-\n upload-pack.c         |    2 +\n write_or_die.c        |    7 +-\n 27 files changed, 7617 insertions(+), 73 deletions(-)\n\nInterdiff follows (it's line wrapped, just for exposition):\n\ndiff --git a/Makefile b/Makefile\nindex 4ff82c9..ad4b779 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1301,7 +1301,7 @@ remove-dashes:\n ifeq ($(firstword $(subst /, ,$(template_dir))),..)\n template_instdir = $(gitexecdir)/$(template_dir)\n else\n-template_instdir = $template_dir\n+template_instdir = $(template_dir)\n endif\n export template_instdir\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 7c8fd0e..ee26df9 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -175,6 +175,33 @@ int mingw_fstat(int fd, struct mingw_stat *buf)\n \treturn -1;\n }\n\n+static inline void time_t_to_filetime(time_t t, FILETIME *ft)\n+{\n+\tlong long winTime = t * 10000000LL + 116444736000000000LL;\n+\tft->dwLowDateTime = winTime;\n+\tft->dwHighDateTime = winTime >> 32;\n+}\n+\n+int mingw_utime (const char *file_name, const struct utimbuf *times)\n+{\n+\tFILETIME mft, aft;\n+\tint fh, rc;\n+\n+\t/* must have write permission */\n+\tif ((fh = open(file_name, O_RDWR | O_BINARY)) < 0)\n+\t\treturn -1;\n+\n+\ttime_t_to_filetime(times->modtime, &mft);\n+\ttime_t_to_filetime(times->actime, &aft);\n+\tif (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {\n+\t\terrno = EINVAL;\n+\t\trc = -1;\n+\t} else\n+\t\trc = 0;\n+\tclose(fh);\n+\treturn rc;\n+}\n+\n unsigned int sleep (unsigned int seconds)\n {\n \tSleep(seconds*1000);\n@@ -353,7 +380,7 @@ static const char *quote_arg(const char *arg)\n \tconst char *p = arg;\n \tif (!*p) force_quotes = 1;\n \twhile (*p) {\n-\t\tif (isspace(*p) || *p == '*' || *p == '?')\n+\t\tif (isspace(*p) || *p == '*' || *p == '?' || *p == '{')\n \t\t\tforce_quotes = 1;\n \t\telse if (*p == '\"')\n \t\t\tn++;\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex c7db345..6965e3f 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -24,6 +24,8 @@ typedef int pid_t;\n #define SIGKILL 0\n #define SIGCHLD 0\n #define SIGPIPE 0\n+#define SIGHUP 0\n+#define SIGQUIT 0\n #define SIGALRM 100\n\n #define F_GETFD 1\n@@ -174,6 +176,9 @@ int mingw_fstat(int fd, struct mingw_stat *buf);\n static inline int mingw_stat(const char *file_name, struct mingw_stat *buf)\n { return mingw_lstat(file_name, buf); }\n\n+int mingw_utime(const char *file_name, const struct utimbuf *times);\n+#define utime mingw_utime\n+\n pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env);\n void mingw_execvp(const char *cmd, char *const *argv);\n #define execvp mingw_execvp\ndiff --git a/compat/snprintf.c b/compat/snprintf.c\nindex 480b66f..580966e 100644\n--- a/compat/snprintf.c\n+++ b/compat/snprintf.c\n@@ -13,9 +13,13 @@\n int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)\n {\n \tchar *s;\n-\tint ret;\n+\tint ret = -1;\n\n-\tret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);\n+\tif (maxsize > 0) {\n+\t\tret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);\n+\t\t/* Windows does not NUL-terminate if result fills buffer */\n+\t\tstr[maxsize-1] = 0;\n+\t}\n \tif (ret != -1)\n \t\treturn ret;\n\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex cdfd54d..46fc2d3 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -66,12 +66,12 @@\n #include <fnmatch.h>\n #include <assert.h>\n #include <regex.h>\n+#include <utime.h>\n #ifndef __MINGW32__\n #include <sys/wait.h>\n #include <sys/poll.h>\n #include <sys/socket.h>\n #include <sys/ioctl.h>\n-#include <utime.h>\n #ifndef NO_SYS_SELECT_H\n #include <sys/select.h>\n #endif\n@@ -185,7 +185,7 @@ extern ssize_t git_pread(int fd, void *buf, size_t\ncount, off_t offset);\n  * This function is used in compat/pread.c.  But we can't include\n  * cache.h there.\n  */\n-extern int read_in_full(int fd, void *buf, size_t count);\n+extern ssize_t read_in_full(int fd, void *buf, size_t count);\n\n #ifdef NO_SETENV\n #define setenv gitsetenv\ndiff --git a/git-sh-setup.sh b/git-sh-setup.sh\nindex 822aa6f..9cceb21 100755\n--- a/git-sh-setup.sh\n+++ b/git-sh-setup.sh\n@@ -153,9 +153,5 @@ case $(uname -s) in\n \tfind () {\n \t\t/usr/bin/find \"$@\"\n \t}\n-\t# sync is missing\n-\tsync () {\n-\t\t:\t# no implementation\n-\t}\n \t;;\n esac\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 51d90a3..c861141 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -441,16 +441,3 @@ do\n \t\ttest_done\n \tesac\n done\n-\n-# Fix some commands on Windows\n-case $(uname -s) in\n-*MINGW*)\n-\t# Windows has its own (incompatible) sort and find\n-\tsort () {\n-\t\t/usr/bin/sort \"$@\"\n-\t}\n-\tfind () {\n-\t\t/usr/bin/find \"$@\"\n-\t}\n-\t;;\n-esac\n"},{"id":"80542","messageId":"7vskv79l37.fsf@gitster.siamese.dyndns.org","threadId":"14054","inReplyTo":"485B6510.3080201@viscovery.net","subject":"Re: MinGW port pull request","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-06-21T09:46:36Z","receivedAt":"2008-06-21T09:46:36Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j.sixt@viscovery.net> writes:\n\n> please pull the MinGW (Windows) port patch series from\n>\n> git://repo.or.cz/git/mingw/j6t.git for-junio\n\nTook a look.  A quick impression.\n\n * Too many whitespace breakages in borrowed compat/regex.[ch] are very\n   distracting.\n\n * It is a very nice touch to rename sample templates to make sure they\n   are not executable (after all they are just samples).\n\n * Shouldn't my_mktime() if exported out of date.c be named a bit better?\n\n * The ifdef block in git.c::main() introduces decl-after-stmt which we\n   tend to avoid, but it is much worse to solve it by adding another ifdef\n   block just to enclose decl of char *bslash at the beginning of the\n   function.  Perhaps enclose it in an extra block?\n\n * In sanitary_path_copy(), you left \"break;\" after /* (1) */ but now that\n   \"break\" is not inside a switch() anymore, so you are breaking out of\n   something else, aren't you?  -- Ah, the clean-up phase will be no-op in\n   that case because src points at '\\0'.  Tricky but looks correct ;-)\n\n * There seem to be an unrelated general fix in upload-pack.c\n\n * There are still too many ifdefs.  I am wondering if the changes to\n   pager and process stuff is easier to manage in the longer term if they\n   are made into completely separate files (i.e. instead of linking\n   pager.o you would link mingw-pager.o).  I dunno.\n\n * There is an interaction with dr/ceiling topic that is already in 'next'\n   that needs to be resolved before we merge this in 'next'.\n\nParked in 'pu' for now but with a broken merge resolution.\n"},{"id":"80564","messageId":"200806212318.47745.johannes.sixt@telecom.at","threadId":"14054","inReplyTo":"7vskv79l37.fsf@gitster.siamese.dyndns.org","subject":"Re: [msysGit] Re: MinGW port pull request","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-06-21T21:18:47Z","receivedAt":"2008-06-21T21:18:47Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Samstag, 21. Juni 2008, Junio C Hamano wrote:\n> Johannes Sixt <j.sixt@viscovery.net> writes:\n> > please pull the MinGW (Windows) port patch series from\n> >\n> > git://repo.or.cz/git/mingw/j6t.git for-junio\n>\n> Took a look.  A quick impression.\n>\n>  * Too many whitespace breakages in borrowed compat/regex.[ch] are very\n>    distracting.\n\nWill fixup, no problem.\n\n>  * It is a very nice touch to rename sample templates to make sure they\n>    are not executable (after all they are just samples).\n\nNote that they are only renamed on Windows. Do you think it makes sense to \nrename them on every platform?\n\nI think I'll have to add a note in Documentation/githooks.txt for Windows that \nmentions that the '.noexec' part must be removed.\n\n>  * Shouldn't my_mktime() if exported out of date.c be named a bit better?\n\nHow about tm_to_time_t()?\n\n>  * The ifdef block in git.c::main() introduces decl-after-stmt which we\n>    tend to avoid, but it is much worse to solve it by adding another ifdef\n>    block just to enclose decl of char *bslash at the beginning of the\n>    function.  Perhaps enclose it in an extra block?\n\nIt does not in my version. IIRC, I was careful that it does not.\n\n>  * In sanitary_path_copy(), you left \"break;\" after /* (1) */ but now that\n>    \"break\" is not inside a switch() anymore, so you are breaking out of\n>    something else, aren't you?  -- Ah, the clean-up phase will be no-op in\n>    that case because src points at '\\0'.  Tricky but looks correct ;-)\n\nI'm pretty certain that it is an omission. I'll remove the 'break' in the next \nround. It's just unnecessarily tricky.\n\n>  * There seem to be an unrelated general fix in upload-pack.c\n\nYes, indeed. It's the fflush(pack_pipe) that could make a difference. I wonder \nwhy this ever worked without it. Notice that traverse_commit_list calls \nshow_object() last, but show_object() never flushes pack_pipe. Are fdopen()ed \npipes line-buffered or unbuffered?\n\n>  * There are still too many ifdefs.  I am wondering if the changes to\n>    pager and process stuff is easier to manage in the longer term if they\n>    are made into completely separate files (i.e. instead of linking\n>    pager.o you would link mingw-pager.o).  I dunno.\n\nI think that would not be helpful. Both parts need to be maintained, whether \nthey are in the same file or in different files. If they are in one file, and \nsomeone needs to make a change, then there is a chance that a corresponding \nchange is made in the MINGW32 arm. If not then there is another chance that \nthe person would at least say \"I don't know how to do it for MINGW32\". But if \nyou separate the implementations completely, then both chances are missed \nmuch easier.\n\nTo reduce #ifdef in other places I have some proposals. Please tell me which \nyou like or dislike:\n\n* The #ifdef STRIP_EXTENSION can be removed with a conditional like this:\n\n\tstatic const char ext[] = STRIP_EXTENSION; // \"\" or \".exe\"\n\tif (sizeof(ext) > 1) {\n\t\t...\n\t}\n\n* The #ifdef in main() of git.c can be removed with a custom loop that checks \nfor is_dir_sep():\n\n\tslash = cmd + strlen(cmd);\n\twhile (slash > cmd && !is_dir_sep(*--slash))\n\t\t;\n\tif (slash >= cmd) {\t// was: if (slash) {\n\t\t...\n\n* We could wrap getenv(), so that the getenv(\"TEMPDIR\") in path.c does not \nneed to be followed up with getenv(\"TMP\") and getenv(\"TEMP\"). I'll do that.\n\n* The #ifdef in setup.c, prefix_filename() could easily be removed by using \nthe MINGW32 arm everywhere. This would penalize non-Windows, however, \nprefix_filename() is not performance critical.\n\n>  * There is an interaction with dr/ceiling topic that is already in 'next'\n>    that needs to be resolved before we merge this in 'next'.\n\nHow do you want me to proceed? Rebase on top of dr/ceiling? Wait until \ndr/ceiling is in master and rebase again? Merge it into my series? (I would \nmake the merge the last commit in my series.) I'm asking because support of \ndr/ceiling was not overwhelming.\n\n-- Hannes\n"},{"id":"80566","messageId":"5fc54b450806211421m64eee6e5l3622243e65f633a2@mail.gmail.com","threadId":"14054","inReplyTo":"200806212318.47745.johannes.sixt@telecom.at","subject":"Re: MinGW port pull request","fromName":"Jim Raden","fromEmail":"james.raden@gmail.com","sentAt":"2008-06-21T21:21:47Z","receivedAt":"2008-06-21T21:21:47Z","isPatch":false,"sender":{"key":"james.raden@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3783?v=4"},"body":"On Sat, Jun 21, 2008 at 5:18 PM, Johannes Sixt <johannes.sixt@telecom.at>\nwrote:\n\n>\n> >  * There are still too many ifdefs.  I am wondering if the changes to\n> >    pager and process stuff is easier to manage in the longer term if they\n> >    are made into completely separate files (i.e. instead of linking\n> >    pager.o you would link mingw-pager.o).  I dunno.\n>\n> I think that would not be helpful. Both parts need to be maintained,\n> whether\n> they are in the same file or in different files. If they are in one file,\n> and\n> someone needs to make a change, then there is a chance that a corresponding\n> change is made in the MINGW32 arm. If not then there is another chance that\n> the person would at least say \"I don't know how to do it for MINGW32\". But\n> if\n> you separate the implementations completely, then both chances are missed\n> much easier.\n>\n> I quite agree!!\n"},{"id":"80571","messageId":"7vve028nqe.fsf@gitster.siamese.dyndns.org","threadId":"14054","inReplyTo":"200806212318.47745.johannes.sixt@telecom.at","subject":"Re: [msysGit] Re: MinGW port pull request","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-06-21T21:47:05Z","receivedAt":"2008-06-21T21:47:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <johannes.sixt@telecom.at> writes:\n\n> * The #ifdef in setup.c, prefix_filename() could easily be removed by using \n> the MINGW32 arm everywhere. This would penalize non-Windows, however, \n> prefix_filename() is not performance critical.\n>\n>>  * There is an interaction with dr/ceiling topic that is already in 'next'\n>>    that needs to be resolved before we merge this in 'next'.\n>\n> How do you want me to proceed? Rebase on top of dr/ceiling? Wait until \n> dr/ceiling is in master and rebase again? Merge it into my series? (I would \n> make the merge the last commit in my series.) I'm asking because support of \n> dr/ceiling was not overwhelming.\n\nI personally feel MinGW branch is more important than ceiling work, not\njust because it targets far wider audience but because it affects a lot\nwider area.  j6t/mingw _will_ eventually graduate to master in some form\n(possibly after fixups that is needed to keep things working on non\nWindows environment), and dr/ceil may or may not.\n\nSo my preference would be to merge j6t/mingw into dr/ceil branch soon,\nresolve conflicts there, and merge the result to 'next' when j6t/mingw is\nmerged to 'next' at the same time.  And you can help with that merge when\nit happens.\n"},{"id":"80693","messageId":"485F8F04.6090802@viscovery.net","threadId":"14054","inReplyTo":"200806212318.47745.johannes.sixt@telecom.at","subject":"Re: MinGW port pull request","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-06-23T11:54:44Z","receivedAt":"2008-06-23T11:54:44Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"\nJohannes Sixt schrieb:\n> On Samstag, 21. Juni 2008, Junio C Hamano wrote:\n>> Johannes Sixt <j.sixt@viscovery.net> writes:\n>>> please pull the MinGW (Windows) port patch series from\n>>>\n>>> git://repo.or.cz/git/mingw/j6t.git for-junio\n\nI've updated the branch (it's still based on v1.5.6). Please pull again.\n\n>> Took a look.  A quick impression.\n>>\n>>  * Too many whitespace breakages in borrowed compat/regex.[ch] are very\n>>    distracting.\n> \n> Will fixup, no problem.\n\nDone.\n\n>>  * Shouldn't my_mktime() if exported out of date.c be named a bit better?\n> \n> How about tm_to_time_t()?\n\nDone. There's a new commit (for-junio~26) that does only the renaming.\n\n>>  * The ifdef block in git.c::main() introduces decl-after-stmt which we\n>>    tend to avoid, but it is much worse to solve it by adding another ifdef\n>>    block just to enclose decl of char *bslash at the beginning of the\n>>    function.  Perhaps enclose it in an extra block?\n\nThe #ifdef block is gone.\n\n>>  * In sanitary_path_copy(), you left \"break;\" after /* (1) */ but now that\n>>    \"break\" is not inside a switch() anymore, so you are breaking out of\n>>    something else, aren't you?  -- Ah, the clean-up phase will be no-op in\n>>    that case because src points at '\\0'.  Tricky but looks correct ;-)\n> \n> I'm pretty certain that it is an omission. I'll remove the 'break' in the next \n> round. It's just unnecessarily tricky.\n\nDone.\n\n>>  * There seem to be an unrelated general fix in upload-pack.c\n> \n> Yes, indeed. It's the fflush(pack_pipe) that could make a difference. I wonder \n> why this ever worked without it. Notice that traverse_commit_list calls \n> show_object() last, but show_object() never flushes pack_pipe. Are fdopen()ed \n> pipes line-buffered or unbuffered?\n\nI didn't change anything here because I don't know why the old code works\non *nix, and I only know that the change is *necessary* on Windows.\n\n> To reduce #ifdef in other places I have some proposals. Please tell me which \n> you like or dislike:\n> \n> * The #ifdef STRIP_EXTENSION can be removed with a conditional like this:\n> \n> \tstatic const char ext[] = STRIP_EXTENSION; // \"\" or \".exe\"\n> \tif (sizeof(ext) > 1) {\n> \t\t...\n> \t}\n\nDone.\n\n> * The #ifdef in main() of git.c can be removed with a custom loop that checks \n> for is_dir_sep():\n> \n> \tslash = cmd + strlen(cmd);\n> \twhile (slash > cmd && !is_dir_sep(*--slash))\n> \t\t;\n> \tif (slash >= cmd) {\t// was: if (slash) {\n> \t\t...\n\nDone in a similar way.\n\n> * We could wrap getenv(), so that the getenv(\"TEMPDIR\") in path.c does not \n> need to be followed up with getenv(\"TMP\") and getenv(\"TEMP\"). I'll do that.\n\nDone.\n\n> * The #ifdef in setup.c, prefix_filename() could easily be removed by using \n> the MINGW32 arm everywhere. This would penalize non-Windows, however, \n> prefix_filename() is not performance critical.\n\nNOT done.\n\n>>  * There is an interaction with dr/ceiling topic that is already in 'next'\n>>    that needs to be resolved before we merge this in 'next'.\n\nWill take care of this next; I'm running out of time now.\n\nThe interdiff follows; I created it with diff -b to hide the whitespace\nchanges. As you can see, there are a few more editorial changes in\ncompat/mingw.c (in comments and error texts only).\n\n-- Hannes\n\n\n compat/mingw.c    |   33 ++++++++++++++++++++++-----------\n compat/mingw.h    |    3 +++\n date.c            |   13 ++++++++-----\n git-compat-util.h |    5 +++++\n git.c             |   23 +++++++++++------------\n path.c            |    7 -------\n setup.c           |    1 -\n 7 files changed, 49 insertions(+), 36 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex ee26df9..3a05fe7 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -218,7 +218,6 @@ int mkstemp(char *template)\n\n int gettimeofday(struct timeval *tv, void *tz)\n {\n-\textern time_t my_mktime(struct tm *tm);\n \tSYSTEMTIME st;\n \tstruct tm tm;\n \tGetSystemTime(&st);\n@@ -228,7 +227,7 @@ int gettimeofday(struct timeval *tv, void *tz)\n \ttm.tm_hour = st.wHour;\n \ttm.tm_min = st.wMinute;\n \ttm.tm_sec = st.wSecond;\n-\ttv->tv_sec = my_mktime(&tm);\n+\ttv->tv_sec = tm_to_time_t(&tm);\n \tif (tv->tv_sec < 0)\n \t\treturn -1;\n \ttv->tv_usec = st.wMilliseconds*1000;\n@@ -367,6 +366,19 @@ char *mingw_getcwd(char *pointer, int len)\n \treturn ret;\n }\n\n+#undef getenv\n+char *mingw_getenv(const char *name)\n+{\n+\tchar *result = getenv(name);\n+\tif (!result && !strcmp(name, \"TMPDIR\")) {\n+\t\t/* on Windows it is TMP and TEMP */\n+\t\tresult = getenv(\"TMP\");\n+\t\tif (!result)\n+\t\t\tresult = getenv(\"TEMP\");\n+\t}\n+\treturn result;\n+}\n+\n /*\n  * See http://msdn2.microsoft.com/en-us/library/17w5ykft(vs.71).aspx\n  * (Parsing C++ Command-Line Arguments)\n@@ -895,13 +907,12 @@ static int one_shot;\n static sig_handler_t timer_fn = SIG_DFL;\n\n /* The timer works like this:\n- * The thread, ticktack(), is basically a trivial routine that most of the\n- * time only waits to receive the signal to terminate. The main thread\n- * tells the thread to terminate by setting the timer_event to the signalled\n+ * The thread, ticktack(), is a trivial routine that most of the time\n+ * only waits to receive the signal to terminate. The main thread tells\n+ * the thread to terminate by setting the timer_event to the signalled\n  * state.\n- * But ticktack() does not wait indefinitely; instead, it interrupts the\n- * wait state every now and then, namely exactly after timer's interval\n- * length. At these opportunities it calls the signal handler.\n+ * But ticktack() interrupts the wait state after the timer's interval\n+ * length to call the signal handler.\n  */\n\n static __stdcall unsigned ticktack(void *dummy)\n@@ -927,7 +938,7 @@ static int start_timer_thread(void)\n \t\t\t\terror(\"cannot start timer thread\");\n \t} else\n \t\treturn errno = ENOMEM,\n-\t\t\terror(\"cannot allocate resources timer\");\n+\t\t\terror(\"cannot allocate resources for timer\");\n \treturn 0;\n }\n\n@@ -962,11 +973,11 @@ int setitimer(int type, struct itimerval *in, struct\nitimerval *out)\n\n \tif (out != NULL)\n \t\treturn errno = EINVAL,\n-\t\t\terror(\"setitmer param 3 != NULL not implemented\");\n+\t\t\terror(\"setitimer param 3 != NULL not implemented\");\n \tif (!is_timeval_eq(&in->it_interval, &zero) &&\n \t    !is_timeval_eq(&in->it_interval, &in->it_value))\n \t\treturn errno = EINVAL,\n-\t\t\terror(\"setitmer: it_interval must be zero or eq it_value\");\n+\t\t\terror(\"setitimer: it_interval must be zero or eq it_value\");\n\n \tif (timer_thread)\n \t\tstop_timer_thread();\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 6965e3f..6bc049a 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -145,6 +145,9 @@ int mingw_open (const char *filename, int oflags, ...);\n char *mingw_getcwd(char *pointer, int len);\n #define getcwd mingw_getcwd\n\n+char *mingw_getenv(const char *name);\n+#define getenv mingw_getenv\n+\n struct hostent *mingw_gethostbyname(const char *host);\n #define gethostbyname mingw_gethostbyname\n\ndiff --git a/compat/regex.c b/compat/regex.c\nindex 1d39e08..87b33e4 100644\ndiff --git a/compat/regex.h b/compat/regex.h\nindex 408dd21..6eb64f1 100644\ndiff --git a/date.c b/date.c\nindex d6f8bf6..35a5257 100644\n--- a/date.c\n+++ b/date.c\n@@ -6,7 +6,10 @@\n\n #include \"cache.h\"\n\n-time_t my_mktime(struct tm *tm)\n+/*\n+ * This is like mktime, but without normalization of tm_wday and tm_yday.\n+ */\n+time_t tm_to_time_t(const struct tm *tm)\n {\n \tstatic const int mdays[] = {\n \t    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334\n@@ -67,7 +70,7 @@ static int local_tzoffset(unsigned long time)\n\n \tt = time;\n \tlocaltime_r(&t, &tm);\n-\tt_local = my_mktime(&tm);\n+\tt_local = tm_to_time_t(&tm);\n\n \tif (t_local < t) {\n \t\teastwest = -1;\n@@ -322,7 +325,7 @@ static int is_date(int year, int month, int day,\nstruct tm *now_tm, time_t now,\n \t\tif (!now_tm)\n \t\t\treturn 1;\n\n-\t\tspecified = my_mktime(r);\n+\t\tspecified = tm_to_time_t(r);\n\n \t\t/* Be it commit time or author time, it does not make\n \t\t * sense to specify timestamp way into the future.  Make\n@@ -572,7 +575,7 @@ int parse_date(const char *date, char *result, int maxlen)\n \t}\n\n \t/* mktime uses local timezone */\n-\tthen = my_mktime(&tm);\n+\tthen = tm_to_time_t(&tm);\n \tif (offset == -1)\n \t\toffset = (then - mktime(&tm)) / 60;\n\n@@ -611,7 +614,7 @@ void datestamp(char *buf, int bufsize)\n\n \ttime(&now);\n\n-\toffset = my_mktime(localtime(&now)) - now;\n+\toffset = tm_to_time_t(localtime(&now)) - now;\n \toffset /= 60;\n\n \tdate_string(now, offset, buf, bufsize);\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 46fc2d3..51823ae 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -114,6 +114,10 @@\n #define PATH_SEP ':'\n #endif\n\n+#ifndef STRIP_EXTENSION\n+#define STRIP_EXTENSION \"\"\n+#endif\n+\n #ifndef has_dos_drive_prefix\n #define has_dos_drive_prefix(path) 0\n #endif\n@@ -143,6 +147,7 @@ extern void set_error_routine(void (*routine)(const\nchar *err, va_list params));\n extern void set_warn_routine(void (*routine)(const char *warn, va_list\nparams));\n\n extern int prefixcmp(const char *str, const char *prefix);\n+extern time_t tm_to_time_t(const struct tm *tm);\n\n #ifdef NO_MMAP\n\ndiff --git a/git.c b/git.c\nindex a4b0a5e..871b93c 100644\n--- a/git.c\n+++ b/git.c\n@@ -369,15 +369,16 @@ static void handle_internal_command(int argc, const\nchar **argv)\n \t\t{ \"pack-refs\", cmd_pack_refs, RUN_SETUP },\n \t};\n \tint i;\n+\tstatic const char ext[] = STRIP_EXTENSION;\n\n-#ifdef STRIP_EXTENSION\n-\ti = strlen(argv[0]) - strlen(STRIP_EXTENSION);\n-\tif (i > 0 && !strcmp(argv[0] + i, STRIP_EXTENSION)) {\n+\tif (sizeof(ext) > 1) {\n+\t\ti = strlen(argv[0]) - strlen(ext);\n+\t\tif (i > 0 && !strcmp(argv[0] + i, ext)) {\n \t\tchar *argv0 = strdup(argv[0]);\n \t\targv[0] = cmd = argv0;\n \t\targv0[i] = '\\0';\n \t}\n-#endif\n+\t}\n\n \t/* Turn \"git cmd --help\" into \"git help cmd\" */\n \tif (argc > 1 && !strcmp(argv[1], \"--help\")) {\n@@ -395,8 +396,8 @@ static void handle_internal_command(int argc, const\nchar **argv)\n\n int main(int argc, const char **argv)\n {\n-\tconst char *cmd = argv[0] ? argv[0] : \"git-help\";\n-\tchar *slash = strrchr(cmd, '/');\n+\tconst char *cmd = argv[0] && *argv[0] ? argv[0] : \"git-help\";\n+\tchar *slash = (char *)cmd + strlen(cmd);\n \tconst char *cmd_path = NULL;\n \tint done_alias = 0;\n\n@@ -405,12 +406,10 @@ int main(int argc, const char **argv)\n \t * name, and the dirname as the default exec_path\n \t * if we don't have anything better.\n \t */\n-#ifdef __MINGW32__\n-\tchar *bslash = strrchr(cmd, '\\\\');\n-\tif (!slash || (bslash && bslash > slash))\n-\t\tslash = bslash;\n-#endif\n-\tif (slash) {\n+\tdo\n+\t\t--slash;\n+\twhile (cmd <= slash && !is_dir_sep(*slash));\n+\tif (cmd <= slash) {\n \t\t*slash++ = 0;\n \t\tcmd_path = cmd;\n \t\tcmd = slash;\ndiff --git a/path.c b/path.c\nindex 5da41c7..7a35a26 100644\n--- a/path.c\n+++ b/path.c\n@@ -75,13 +75,6 @@ int git_mkstemp(char *path, size_t len, const char\n*template)\n \tsize_t n;\n\n \ttmp = getenv(\"TMPDIR\");\n-#ifdef __MINGW32__\n-\t/* on Windows it is TMP and TEMP */\n-\tif (!tmp)\n-\t    tmp = getenv(\"TMP\");\n-\tif (!tmp)\n-\t    tmp = getenv(\"TEMP\");\n-#endif\n \tif (!tmp)\n \t\ttmp = \"/tmp\";\n \tn = snprintf(path, len, \"%s/%s\", tmp, template);\ndiff --git a/setup.c b/setup.c\nindex ec33147..8bb7b10 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -35,7 +35,6 @@ static int sanitary_path_copy(char *dst, const char *src)\n \t\t\tif (!src[1]) {\n \t\t\t\t/* (1) */\n \t\t\t\tsrc++;\n-\t\t\t\tbreak;\n \t\t\t} else if (is_dir_sep(src[1])) {\n \t\t\t\t/* (2) */\n \t\t\t\tsrc += 2;\n"},{"id":"80889","messageId":"4860F019.6090309@viscovery.net","threadId":"14054","inReplyTo":"7vskv79l37.fsf@gitster.siamese.dyndns.org","subject":"Re: MinGW port pull request","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-06-24T13:01:13Z","receivedAt":"2008-06-24T13:01:13Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"\nJunio C Hamano schrieb:\n>  * There is an interaction with dr/ceiling topic that is already in 'next'\n>    that needs to be resolved before we merge this in 'next'.\n> \n> Parked in 'pu' for now but with a broken merge resolution.\n\nPlease amend the merge commit by this to get the correct resolution:\nminoffset in the MinGW port and ceil_offset in dr/ceiling are used for the\nsame purpose where always ceil_offset == minoffset-1.\n\nWe need to adjust ceil_offset only if longest_ancestor_length() returned\n-1 (i.e. \"there is no prefix\") to skip the drive prefix (\"C:\"); because if\nthere was some prefix, then the return value will already have accounted\nfor the drive prefix.\n\n-- Hannes\n\ndiff --git a/setup.c b/setup.c\nindex 531f852..39f1648 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -382,7 +382,6 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \tconst char *gitdirenv;\n \tconst char *gitfile_dir;\n \tint len, offset, ceil_offset;\n-\tint minoffset = 0;\n\n \t/*\n \t * Let's assume that we are in a git repository.\n@@ -433,12 +432,10 @@ const char *setup_git_directory_gently(int\n\n \tif (!getcwd(cwd, sizeof(cwd)-1))\n \t\tdie(\"Unable to read current working directory\");\n-\tif (has_dos_drive_prefix(cwd))\n-\t\tminoffset = 2;\n\n \tceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);\n-\tif (ceil_offset < minoffset)\n-\t\tceil_offset = minoffset;\n+\tif (ceil_offset < 0 && has_dos_drive_prefix(cwd))\n+\t\tceil_offset = 1;\n\n \t/*\n \t * Test in the following order (relative to the cwd):\n"}]}