{"thread":{"id":"12344","subject":"[PATCH 04/40] Windows: Use the Windows style PATH separator ';'.","startedAt":"2008-02-27T18:54:23Z","lastAt":"2008-03-12T23:06:06Z","messageCount":138,"participants":["Johannes Sixt","Marius Storm-Olsen","Martin Langhoff","Johannes Schindelin","Nguyen Thai Ngoc Duy","Paolo Bonzini","Paul Franz","Junio C Hamano","Govind Salinas","Brian Dessent","Robin Rosenberg","Mike Hommey","Reece Dunn","Jeff King","Kristian Høgsberg"],"isPatch":true,"patchVersion":1,"patchTotal":40},"messages":[{"id":"70106","messageId":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":null,"subject":"[PATCH 00/40] MinGW port","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:23Z","receivedAt":"2008-02-27T18:54:23Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"So here it is, the MinGW port of git.\nThis series is also available from\n\ngit://repo.or.cz/git/mingw/j6t.git upstream\nhttp://repo.or.cz/w/git/mingw/j6t.git?a=shortlog;h=upstream\n\nJunio, please do *not* pull/apply this series into your tree(s) until we\nhave verified that forks on repo.or.cz do not lose objects anymore when\nbranches are rewound.\n\n\nWhat this series achieves:\n\n- An almost complete set of git tools running natively on Windows.\n\n- Functional git-gui and gitk.\n\n\nWhat is missing:\n\n- perl scripts don't work. We have a hack in the port tree, but I haven't\n  yet taken the time to clean it up enough.\n\n- The test suite does not pass because of missing features like symbolic\n  links. Again we have adjusted the tests in the port tree so that the\n  test suite can be completed unattended.\n\n\nI've arranged the patches in a few subsets. They are different from what\nDscho had proposed some weeks ago when I announced the series for the\nfirst time because I felt this topical partitioning makes more sense.\n\n\n* Part 1: Get it going\n01/40 Add compat/regex.[ch] and compat/fnmatch.[ch].\n02/40 Compile some programs only conditionally.\n03/40 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 7 files changed, 6222 insertions(+), 5 deletions(-)\n\n\n* Part 2: Working locally is possible\n04/40 Windows: Use the Windows style PATH separator ';'.\n05/40 Windows: Strip \".exe\" from the program name.\n06/40 Windows: Implement a wrapper of the open() function.\n07/40 Windows: A minimal implemention of getpwuid().\n08/40 Windows: always chmod(, 0666) before unlink().\n09/40 Windows: Work around misbehaved rename().\n10/40 Windows: Treat Windows style path names.\n11/40 Windows: Handle absolute paths in safe_create_leading_directories().\n12/40 Windows: Implement gettimeofday().\n13/40 Windows: Fix PRIuMAX definition.\n14/40 Windows: Implement setitimer() and sigaction().\n15/40 Windows: A work-around for a misbehaved vsnprintf.\n\nNow builtins that write to the repository work as long as they don't need\nto spawn secondary processes.\n\n 10 files changed, 347 insertions(+), 20 deletions(-)\n\n\n* Part 3: Shell scripts and start_command()\n16/40 Windows: Wrap execve so that shell scripts can be invoked.\n17/40 Windows: A pipe() replacement whose ends are not inherited to children.\n18/40 Windows: Implement start_command().\n19/40 Windows: Change the name of hook scripts to make them not executable.\n\nNow scripted tools and the builtins and standalone programs work that\ndepend on start_command().\n\n 5 files changed, 391 insertions(+), 16 deletions(-)\n\n\n* Part 4: Remote connections\n20/40 Windows: A rudimentary poll() emulation.\n21/40 Windows: Disambiguate DOS style paths from SSH URLs.\n22/40 Windows: Implement asynchronous functions as threads.\n23/40 Windows: Local clone must use the drive letter in absolute paths.\n24/40 Windows: Work around incompatible sort and find.\n25/40 Windows: Implement a cpio emulation in git-clone.sh.\n26/40 Windows: Implement wrappers for gethostbyname(), socket(), and connect().\n\nRemote connections, both push and fetch, using local transport as well as\nconnections via ssh and native git protocol work.\n\n 9 files changed, 233 insertions(+), 3 deletions(-)\n\n\n* Part 5: Optimizations\n27/40 Windows: Implement a custom spawnve().\n28/40 Windows: Add a new lstat and fstat implementation based on Win32 API.\n29/40 Windows: Use a customized struct stat that also has the st_blocks member.\n\n 3 files changed, 370 insertions(+), 10 deletions(-)\n\n\n* Part 6: Tie up loose ends\n30/40 Turn builtin_exec_path into a function.\n31/40 Compute the ultimate fallback for exec_path from the program invocation.\n32/40 Windows: Use a relative default template_dir and ETC_GITCONFIG\n33/40 When installing, be prepared that template_dir may be relative.\n34/40 Windows: Make the pager work.\n35/40 Windows: Work around an oddity when a pipe with no reader is written to.\n36/40 Avoid the \"dup dance\" in wt_status_print_verbose() when possible.\n37/40 Windows: Make 'git help -a' work.\n38/40 Windows: TMP and TEMP environment variables specify a temporary directory.\n39/40 Windows: Fix ntohl() related warnings about printf formatting\n40/40 compat/pread.c: Add foward decl to fix warning\n\nThis fixes some final remaining oddities, minor missing features, and\nworks around differences between POSIX and Windows.\n\n 11 files changed, 154 insertions(+), 21 deletions(-)\n\n\n* Diffstat excluding 01/40 (which adds 5989 lines)\n\n Documentation/git.txt |    6 +-\n Makefile              |   48 +++-\n cache.h               |    4 +\n compat/mingw.c        | 1018 +++++++++++++++++++++++++++++++++++++++++++++++++\n connect.c             |    8 +-\n date.c                |    2 +-\n exec_cmd.c            |   43 ++-\n git-clone.sh          |   52 +++-\n git-compat-util.h     |  221 +++++++++++-\n git-sh-setup.sh       |   17 +\n git.c                 |   14 +\n gitk-git/Makefile     |    4 +\n gitk-git/gitk         |    1 +\n help.c                |   38 ++-\n pager.c               |   40 ++-\n path.c                |    7 +\n run-command.c         |  118 ++++++-\n run-command.h         |    5 +\n setup.c               |   59 +++-\n sha1_file.c           |   18 +-\n t/test-lib.sh         |   13 +\n templates/Makefile    |   16 +-\n upload-pack.c         |    2 +\n write_or_die.c        |    7 +-\n wt-status.c           |   12 +-\n 25 files changed, 1713 insertions(+), 60 deletions(-)\n\n-- Hannes\n"},{"id":"70103","messageId":"1204138503-6126-2-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 01/40] Add compat/regex.[ch] and compat/fnmatch.[ch].","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:24Z","receivedAt":"2008-02-27T18:54:24Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"We don't have fnmatch and regular expressions on Windows. We borrow\nfnmatch.[ch] from the GNU C library (license is LGPL 2 or later) and\nGNU regexp (regexp.c[ch], license is GPL 2 or later). Note that regexp.c\nwas changed slightly to avoid warnings with gcc.\n\nWe make the addition of these files an extra commit so as not to clutter\nthe next commits.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n This patch is intentially broken.  There's no need to comment on the\n details of the files that it adds.\n\n -- Hannes\n\n compat/fnmatch.c |  488 ++++++\n compat/fnmatch.h |   84 +\n compat/regex.c   | 4927 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\n compat/regex.h   |  490 ++++++\n 4 files changed, 5989 insertions(+), 0 deletions(-)\n create mode 100644 compat/fnmatch.c\n create mode 100644 compat/fnmatch.h\n create mode 100644 compat/regex.c\n create mode 100644 compat/regex.h\n\ndiff --git a/compat/fnmatch.c b/compat/fnmatch.c\nnew file mode 100644\nindex 0000000..1f4ead5\n--- /dev/null\n+++ b/compat/fnmatch.c\n@@ -0,0 +1,488 @@\nThis patch is intentionally broken.\ndiff --git a/compat/fnmatch.h b/compat/fnmatch.h\nnew file mode 100644\nindex 0000000..cc3ec37\n--- /dev/null\n+++ b/compat/fnmatch.h\n@@ -0,0 +1,84 @@\nThis patch is intentionally broken.\ndiff --git a/compat/regex.c b/compat/regex.c\nnew file mode 100644\nindex 0000000..1d39e08\n--- /dev/null\n+++ b/compat/regex.c\n@@ -0,0 +1,4927 @@\nThis patch is intentionally broken.\ndiff --git a/compat/regex.h b/compat/regex.h\nnew file mode 100644\nindex 0000000..408dd21\n--- /dev/null\n+++ b/compat/regex.h\n@@ -0,0 +1,490 @@\nThis patch is intentionally broken.\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70102","messageId":"1204138503-6126-3-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 02/40] Compile some programs only conditionally.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:25Z","receivedAt":"2008-02-27T18:54:25Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On MinGW, we won't compile some programs.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n Makefile |    8 ++++++--\n 1 files changed, 6 insertions(+), 2 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex d33a556..870a862 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -255,7 +255,6 @@ PROGRAMS = \\\n \tgit-fetch-pack$X \\\n \tgit-hash-object$X git-index-pack$X \\\n \tgit-fast-import$X \\\n-\tgit-daemon$X \\\n \tgit-merge-index$X git-mktag$X git-mktree$X git-patch-id$X \\\n \tgit-receive-pack$X \\\n \tgit-send-pack$X git-shell$X \\\n@@ -264,7 +263,7 @@ PROGRAMS = \\\n \tgit-update-server-info$X \\\n \tgit-upload-pack$X \\\n \tgit-pack-redundant$X git-var$X \\\n-\tgit-merge-tree$X git-imap-send$X \\\n+\tgit-merge-tree$X \\\n \tgit-merge-recursive$X \\\n \t$(EXTRA_PROGRAMS)\n \n@@ -583,6 +582,11 @@ ifdef ZLIB_PATH\n endif\n EXTLIBS += -lz\n \n+ifndef NO_EXTRA_PROGRAMS\n+\tEXTRA_PROGRAMS += \\\n+\t\tgit-daemon$X \\\n+\t\tgit-imap-send$X\n+endif\n ifndef NO_OPENSSL\n \tOPENSSL_LIBSSL = -lssl\n \tifdef OPENSSLDIR\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70105","messageId":"1204138503-6126-4-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:26Z","receivedAt":"2008-02-27T18:54:26Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"With this change GIT can be compiled and linked using MinGW. Builtins\nthat only read the repository such as the log family and grep already\nwork.\n\nSimple stubs are provided for a number of functions that the Windows C\nruntime does not offer. They will be completed in later patches.\n\nDmitry Kakurin pointed out that access(..., X_OK) would always fails on\nVista and suggested the -D__USE_MINGW_ACCESS workaround.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n Makefile          |   25 +++++++++\n compat/mingw.c    |   57 ++++++++++++++++++++\n git-compat-util.h |  148 +++++++++++++++++++++++++++++++++++++++++++++++++++-\n 3 files changed, 227 insertions(+), 3 deletions(-)\n create mode 100644 compat/mingw.c\n\ndiff --git a/Makefile b/Makefile\nindex 870a862..bc8a487 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -522,6 +522,31 @@ ifeq ($(uname_S),HP-UX)\n \tNO_HSTRERROR = YesPlease\n \tNO_SYS_SELECT_H = YesPlease\n endif\n+ifneq (,$(findstring MINGW,$(uname_S)))\n+\tNO_MMAP = YesPlease\n+\tNO_PREAD = YesPlease\n+\tNO_OPENSSL = YesPlease\n+\tNO_CURL = YesPlease\n+\tNO_SYMLINK_HEAD = YesPlease\n+\tNO_IPV6 = YesPlease\n+\tNO_SETENV = YesPlease\n+\tNO_UNSETENV = YesPlease\n+\tNO_STRCASESTR = YesPlease\n+\tNO_STRLCPY = YesPlease\n+\tNO_MEMMEM = YesPlease\n+\tNEEDS_LIBICONV = YesPlease\n+\tOLD_ICONV = YesPlease\n+\tNO_C99_FORMAT = YesPlease\n+\tNO_STRTOUMAX = YesPlease\n+\tNO_MKDTEMP = YesPlease\n+\tNO_SVN_TESTS = YesPlease\n+\tNO_PERL_MAKEMAKER = YesPlease\n+\tNO_EXTRA_PROGRAMS = YesPlease\n+\tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat\n+\tCOMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o\n+\tEXTLIBS += -lws2_32\n+\tX = .exe\n+endif\n ifneq (,$(findstring arm,$(uname_M)))\n \tARM_SHA1 = YesPlease\n endif\ndiff --git a/compat/mingw.c b/compat/mingw.c\nnew file mode 100644\nindex 0000000..0c87e43\n--- /dev/null\n+++ b/compat/mingw.c\n@@ -0,0 +1,57 @@\n+#include \"../git-compat-util.h\"\n+\n+unsigned int _CRT_fmode = _O_BINARY;\n+\n+unsigned int sleep (unsigned int seconds)\n+{\n+\tSleep(seconds*1000);\n+\treturn 0;\n+}\n+\n+int mkstemp(char *template)\n+{\n+\tchar *filename = mktemp(template);\n+\tif (filename == NULL)\n+\t\treturn -1;\n+\treturn open(filename, O_RDWR | O_CREAT, 0600);\n+}\n+\n+int gettimeofday(struct timeval *tv, void *tz)\n+{\n+\treturn 0;\n+}\n+\n+int poll(struct pollfd *ufds, unsigned int nfds, int timeout)\n+{\n+\treturn 0;\n+}\n+\n+struct tm *gmtime_r(const time_t *timep, struct tm *result)\n+{\n+\t/* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */\n+\tmemcpy(result, gmtime(timep), sizeof(struct tm));\n+\treturn result;\n+}\n+\n+struct tm *localtime_r(const time_t *timep, struct tm *result)\n+{\n+\t/* localtime() in MSVCRT.DLL is thread-safe, but not reentrant */\n+\tmemcpy(result, localtime(timep), sizeof(struct tm));\n+\treturn result;\n+}\n+\n+struct passwd *getpwuid(int uid)\n+{\n+\tstatic struct passwd p;\n+\treturn &p;\n+}\n+\n+int setitimer(int type, struct itimerval *in, struct itimerval *out)\n+{\n+\treturn 0;\n+}\n+\n+int sigaction(int sig, struct sigaction *in, struct sigaction *out)\n+{\n+\treturn 0;\n+}\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 2a40703..b1f3f92 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -63,16 +63,17 @@\n #include <sys/time.h>\n #include <time.h>\n #include <signal.h>\n-#include <sys/wait.h>\n #include <fnmatch.h>\n+#include <assert.h>\n+#include <regex.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 #ifndef NO_SYS_SELECT_H\n #include <sys/select.h>\n #endif\n-#include <assert.h>\n-#include <regex.h>\n #include <netinet/in.h>\n #include <netinet/tcp.h>\n #include <arpa/inet.h>\n@@ -88,6 +89,7 @@\n #include <grp.h>\n #define _ALL_SOURCE 1\n #endif\n+#endif\t/* !__MINGW32__ */\n \n #ifndef NO_ICONV\n #include <iconv.h>\n@@ -357,6 +359,10 @@ static inline FILE *xfdopen(int fd, const char *mode)\n \treturn stream;\n }\n \n+#ifdef __MINGW32__\n+int mkstemp(char *template);\n+#endif\n+\n static inline int xmkstemp(char *template)\n {\n \tint fd;\n@@ -437,4 +443,140 @@ void git_qsort(void *base, size_t nmemb, size_t size,\n #define qsort git_qsort\n #endif\n \n+#ifdef __MINGW32__\n+\n+#include <winsock2.h>\n+\n+/*\n+ * things that are not available in header files\n+ */\n+\n+typedef int pid_t;\n+#define hstrerror strerror\n+\n+#define S_IFLNK    0120000 /* Symbolic link */\n+#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)\n+#define S_ISSOCK(x) 0\n+#define S_IRGRP 0\n+#define S_IWGRP 0\n+#define S_IXGRP 0\n+#define S_ISGID 0\n+#define S_IROTH 0\n+#define S_IXOTH 0\n+\n+#define WIFEXITED(x) ((unsigned)(x) < 259)\t/* STILL_ACTIVE */\n+#define WEXITSTATUS(x) ((x) & 0xff)\n+#define WIFSIGNALED(x) ((unsigned)(x) > 259)\n+\n+#define SIGKILL 0\n+#define SIGCHLD 0\n+#define SIGPIPE 0\n+#define SIGALRM 100\n+\n+#define F_GETFD 1\n+#define F_SETFD 2\n+#define FD_CLOEXEC 0x1\n+\n+struct passwd {\n+\tchar *pw_name;\n+\tchar *pw_gecos;\n+\tchar *pw_dir;\n+};\n+\n+struct pollfd {\n+\tint fd;           /* file descriptor */\n+\tshort events;     /* requested events */\n+\tshort revents;    /* returned events */\n+};\n+#define POLLIN 1\n+#define POLLHUP 2\n+\n+typedef void (__cdecl *sig_handler_t)(int);\n+struct sigaction {\n+\tsig_handler_t sa_handler;\n+\tunsigned sa_flags;\n+};\n+#define sigemptyset(x) (void)0\n+#define SA_RESTART 0\n+\n+struct itimerval {\n+\tstruct timeval it_value, it_interval;\n+};\n+#define ITIMER_REAL 0\n+\n+#define st_blocks st_size/512\t/* will be cleaned up later */\n+#define lstat stat\n+\n+/*\n+ * trivial stubs\n+ */\n+\n+static inline int readlink(const char *path, char *buf, size_t bufsiz)\n+{ errno = ENOSYS; return -1; }\n+static inline int symlink(const char *oldpath, const char *newpath)\n+{ errno = ENOSYS; return -1; }\n+static inline int link(const char *oldpath, const char *newpath)\n+{ errno = ENOSYS; return -1; }\n+static inline int fchmod(int fildes, mode_t mode)\n+{ errno = ENOSYS; return -1; }\n+static inline int fork(void)\n+{ errno = ENOSYS; return -1; }\n+static inline unsigned int alarm(unsigned int seconds)\n+{ return 0; }\n+static inline int fsync(int fd)\n+{ return 0; }\n+static inline int getppid(void)\n+{ return 1; }\n+static inline void sync(void)\n+{}\n+static inline int getuid()\n+{ return 1; }\n+static inline struct passwd *getpwnam(const char *name)\n+{ return NULL; }\n+static inline int fcntl(int fd, int cmd, long arg)\n+{\n+\tif (cmd == F_GETFD || cmd == F_SETFD)\n+\t\treturn 0;\n+\terrno = EINVAL;\n+\treturn -1;\n+}\n+\n+/*\n+ * simple adaptors\n+ */\n+\n+static inline int mingw_mkdir(const char *path, int mode)\n+{\n+\treturn mkdir(path);\n+}\n+#define mkdir mingw_mkdir\n+\n+static inline int waitpid(pid_t pid, unsigned *status, unsigned options)\n+{\n+\tif (options == 0)\n+\t\treturn _cwait(status, pid, 0);\n+\terrno = EINVAL;\n+\treturn -1;\n+}\n+\n+\n+static inline int pipe(int filedes[2])\n+{ return _pipe(filedes, 8192, 0); }\n+\n+/*\n+ * implementations of missing functions\n+ */\n+\n+unsigned int sleep (unsigned int seconds);\n+int gettimeofday(struct timeval *tv, void *tz);\n+int poll(struct pollfd *ufds, unsigned int nfds, int timeout);\n+struct tm *gmtime_r(const time_t *timep, struct tm *result);\n+struct tm *localtime_r(const time_t *timep, struct tm *result);\n+int getpagesize(void);\t/* defined in MinGW's libgcc.a */\n+struct passwd *getpwuid(int uid);\n+int setitimer(int type, struct itimerval *in, struct itimerval *out);\n+int sigaction(int sig, struct sigaction *in, struct sigaction *out);\n+\n+#endif /* __MINGW32__ */\n+\n #endif\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70101","messageId":"1204138503-6126-5-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 04/40] Windows: Use the Windows style PATH separator ';'.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:27Z","receivedAt":"2008-02-27T18:54:27Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n Documentation/git.txt |    6 +++---\n exec_cmd.c            |    4 ++++\n sha1_file.c           |    4 ++++\n 3 files changed, 11 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git.txt b/Documentation/git.txt\nindex d57bed6..b2a5b60 100644\n--- a/Documentation/git.txt\n+++ b/Documentation/git.txt\n@@ -382,9 +382,9 @@ git so take care if using Cogito etc.\n 'GIT_ALTERNATE_OBJECT_DIRECTORIES'::\n \tDue to the immutable nature of git objects, old objects can be\n \tarchived into shared, read-only directories. This variable\n-\tspecifies a \":\" separated list of git object directories which\n-\tcan be used to search for git objects. New objects will not be\n-\twritten to these directories.\n+\tspecifies a \":\" separated (on Windows \";\" separated) list\n+\tof git object directories which can be used to search for git\n+\tobjects. New objects will not be written to these directories.\n \n 'GIT_DIR'::\n \tIf the 'GIT_DIR' environment variable is set then it\ndiff --git a/exec_cmd.c b/exec_cmd.c\nindex e189cac..343545d 100644\n--- a/exec_cmd.c\n+++ b/exec_cmd.c\n@@ -37,7 +37,11 @@ static void add_path(struct strbuf *out, const char *path)\n \t\telse\n \t\t\tstrbuf_addstr(out, make_absolute_path(path));\n \n+#ifdef __MINGW32__\n+\t\tstrbuf_addch(out, ';');\n+#else\n \t\tstrbuf_addch(out, ':');\n+#endif\n \t}\n }\n \ndiff --git a/sha1_file.c b/sha1_file.c\nindex 1ddb96b..453bc43 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -389,7 +389,11 @@ void prepare_alt_odb(void)\n \tif (!alt) alt = \"\";\n \n \talt_odb_tail = &alt_odb_list;\n+#ifdef __MINGW32__\n+\tlink_alt_odb_entries(alt, alt + strlen(alt), ';', NULL, 0);\n+#else\n \tlink_alt_odb_entries(alt, alt + strlen(alt), ':', NULL, 0);\n+#endif\n \n \tread_info_alternates(get_object_directory(), 0);\n }\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70104","messageId":"1204138503-6126-6-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 05/40] Windows: Strip \".exe\" from the program name.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:28Z","receivedAt":"2008-02-27T18:54:28Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Before we can successfully parse a builtin command from the program name\nwe must strip off unneeded parts, that is, the file extension.\nAdditionally, we must take Windows style path names into account.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n Makefile |    1 +\n git.c    |   14 ++++++++++++++\n 2 files changed, 15 insertions(+), 0 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex bc8a487..069939f 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -543,6 +543,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_PERL_MAKEMAKER = YesPlease\n \tNO_EXTRA_PROGRAMS = YesPlease\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat\n+\tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o\n \tEXTLIBS += -lws2_32\n \tX = .exe\ndiff --git a/git.c b/git.c\nindex 0cb8688..32166a4 100644\n--- a/git.c\n+++ b/git.c\n@@ -372,6 +372,15 @@ static void handle_internal_command(int argc, const char **argv)\n \t};\n \tint i;\n \n+#ifdef STRIP_EXTENSION\n+\ti = strlen(argv[0]) - strlen(STRIP_EXTENSION);\n+\tif (i > 0 && !strcmp(argv[0] + i, STRIP_EXTENSION)) {\n+\t\tchar *argv0 = strdup(argv[0]);\n+\t\targv[0] = cmd = argv0;\n+\t\targv0[i] = '\\0';\n+\t}\n+#endif\n+\n \t/* Turn \"git cmd --help\" into \"git help cmd\" */\n \tif (argc > 1 && !strcmp(argv[1], \"--help\")) {\n \t\targv[1] = argv[0];\n@@ -398,6 +407,11 @@ 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 \t\t*slash++ = 0;\n \t\tcmd_path = cmd;\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70107","messageId":"1204138503-6126-7-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 06/40] Windows: Implement a wrapper of the open() function.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:29Z","receivedAt":"2008-02-27T18:54:29Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"The wrapper does two things:\n- Requests to open /dev/null are redirected to open the nul pseudo file.\n- A request to open a file that currently exists as a directory on\n  Windows fails with EACCES; this is changed to EISDIR.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c    |   20 ++++++++++++++++++++\n git-compat-util.h |    7 +++++++\n 2 files changed, 27 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 0c87e43..faa6df3 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -2,6 +2,26 @@\n \n unsigned int _CRT_fmode = _O_BINARY;\n \n+#undef open\n+int mingw_open (const char *filename, int oflags, ...)\n+{\n+\tva_list args;\n+\tunsigned mode;\n+\tva_start(args, oflags);\n+\tmode = va_arg(args, int);\n+\tva_end(args);\n+\n+\tif (!strcmp(filename, \"/dev/null\"))\n+\t\tfilename = \"nul\";\n+\tint fd = open(filename, oflags, mode);\n+\tif (fd < 0 && (oflags & O_CREAT) && errno == EACCES) {\n+\t\tDWORD attrs = GetFileAttributes(filename);\n+\t\tif (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))\n+\t\t\terrno = EISDIR;\n+\t}\n+\treturn fd;\n+}\n+\n unsigned int sleep (unsigned int seconds)\n {\n \tSleep(seconds*1000);\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex b1f3f92..672c074 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -577,6 +577,13 @@ struct passwd *getpwuid(int uid);\n int setitimer(int type, struct itimerval *in, struct itimerval *out);\n int sigaction(int sig, struct sigaction *in, struct sigaction *out);\n \n+/*\n+ * replacements of existing functions\n+ */\n+\n+int mingw_open (const char *filename, int oflags, ...);\n+#define open mingw_open\n+\n #endif /* __MINGW32__ */\n \n #endif\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70118","messageId":"1204138503-6126-8-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 07/40] Windows: A minimal implemention of getpwuid().","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:30Z","receivedAt":"2008-02-27T18:54:30Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"getpwuid() is implemented just enough that GIT does not issue errors.\nSince the information that it returns is not very useful, users are\nrequired to set up user.name and user.email configuration.\n\nAll uses of getpwuid() are like getpwuid(getuid()), hence, the return value\nof getuid() is irrelevant and the uid parameter is not even looked at.\n\nSide note: getpwnam() is only used to resolve '~' and '~username' paths,\nwhich is an idiom not known on Windows, hence, we don't implement it.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c |    8 ++++++++\n 1 files changed, 8 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex faa6df3..0c1d0e4 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -62,7 +62,15 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)\n \n struct passwd *getpwuid(int uid)\n {\n+\tstatic char user_name[100];\n \tstatic struct passwd p;\n+\n+\tDWORD len = sizeof(user_name);\n+\tif (!GetUserName(user_name, &len))\n+\t\treturn NULL;\n+\tp.pw_name = user_name;\n+\tp.pw_gecos = \"unknown\";\n+\tp.pw_dir = NULL;\n \treturn &p;\n }\n \n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70108","messageId":"1204138503-6126-9-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 08/40] Windows: always chmod(, 0666) before unlink().","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:31Z","receivedAt":"2008-02-27T18:54:31Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"From: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n\nFrom: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n\nOn Windows, a read-only files cannot be deleted. To make sure that\ndeletion does not fail because of this, always call chmod() before\nunlink().\n\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n git-compat-util.h |    8 ++++++++\n 1 files changed, 8 insertions(+), 0 deletions(-)\n\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 672c074..06ac2c1 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -551,6 +551,14 @@ static inline int mingw_mkdir(const char *path, int mode)\n }\n #define mkdir mingw_mkdir\n \n+static inline int mingw_unlink(const char *pathname)\n+{\n+\t/* read-only files cannot be removed */\n+\tchmod(pathname, 0666);\n+\treturn unlink(pathname);\n+}\n+#define unlink mingw_unlink\n+\n static inline int waitpid(pid_t pid, unsigned *status, unsigned options)\n {\n \tif (options == 0)\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70109","messageId":"1204138503-6126-10-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 09/40] Windows: Work around misbehaved rename().","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:32Z","receivedAt":"2008-02-27T18:54:32Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Windows's rename() is based on the MoveFile() API, which fails if the\ndestination exists. Here we work around the problem by using MoveFileEx().\nFurthermore, the posixly correct error is returned if the destination is\na directory.\n\nThe implementation is still slightly incomplete, however, because of the\nmissing error code translation: We assume that the failure is due to\npermissions.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c    |   25 +++++++++++++++++++++++++\n git-compat-util.h |    3 +++\n 2 files changed, 28 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 0c1d0e4..733ef87 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -60,6 +60,31 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)\n \treturn result;\n }\n \n+#undef rename\n+int mingw_rename(const char *pold, const char *pnew)\n+{\n+\t/*\n+\t * Try native rename() first to get errno right.\n+\t * It is based on MoveFile(), which cannot overwrite existing files.\n+\t */\n+\tif (!rename(pold, pnew))\n+\t\treturn 0;\n+\tif (errno != EEXIST)\n+\t\treturn -1;\n+\tif (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))\n+\t\treturn 0;\n+\t/* TODO: translate more errors */\n+\tif (GetLastError() == ERROR_ACCESS_DENIED) {\n+\t\tDWORD attrs = GetFileAttributes(pnew);\n+\t\tif (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {\n+\t\t\terrno = EISDIR;\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\terrno = EACCES;\n+\treturn -1;\n+}\n+\n struct passwd *getpwuid(int uid)\n {\n \tstatic char user_name[100];\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 06ac2c1..f44a287 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -592,6 +592,9 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out);\n int mingw_open (const char *filename, int oflags, ...);\n #define open mingw_open\n \n+int mingw_rename(const char*, const char*);\n+#define rename mingw_rename\n+\n #endif /* __MINGW32__ */\n \n #endif\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70113","messageId":"1204138503-6126-11-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 10/40] Windows: Treat Windows style path names.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:33Z","receivedAt":"2008-02-27T18:54:33Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"GIT's guts work with a forward slash as a path separators. We do not change\nthat. Rather we make sure that only \"normalized\" paths enter the depths\nof the machinery.\n\nWe have to translate backslashes to forward slashes in the prefix and in\ncommand line arguments. Fortunately, all of them are passed through\nfunctions in setup.c.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n cache.h           |    4 +++\n compat/mingw.c    |   16 ++++++++++++++\n git-compat-util.h |    3 ++\n setup.c           |   59 +++++++++++++++++++++++++++++++++++++++++++---------\n 4 files changed, 71 insertions(+), 11 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex e1000bc..3e4e10a 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -441,7 +441,11 @@ int safe_create_leading_directories(char *path);\n char *enter_repo(char *path, int strict);\n static inline int is_absolute_path(const char *path)\n {\n+#ifndef __MINGW32__\n \treturn path[0] == '/';\n+#else\n+\treturn path[0] == '/' || (path[0] && path[1] == ':');\n+#endif\n }\n const char *make_absolute_path(const char *path);\n \ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 733ef87..71bca96 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -60,6 +60,22 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)\n \treturn result;\n }\n \n+#undef getcwd\n+char *mingw_getcwd(char *pointer, int len)\n+{\n+\tchar *ret = getcwd(pointer, len);\n+\tif (!ret)\n+\t\treturn ret;\n+\tif (pointer[0] != 0 && pointer[1] == ':') {\n+\t\tint i;\n+\t\tfor (i = 2; pointer[i]; i++)\n+\t\t\t/* Thanks, Bill. You'll burn in hell for that. */\n+\t\t\tif (pointer[i] == '\\\\')\n+\t\t\t\tpointer[i] = '/';\n+\t}\n+\treturn ret;\n+}\n+\n #undef rename\n int mingw_rename(const char *pold, const char *pnew)\n {\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex f44a287..3b57464 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -592,6 +592,9 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out);\n int mingw_open (const char *filename, int oflags, ...);\n #define open mingw_open\n \n+char *mingw_getcwd(char *pointer, int len);\n+#define getcwd mingw_getcwd\n+\n int mingw_rename(const char*, const char*);\n #define rename mingw_rename\n \ndiff --git a/setup.c b/setup.c\nindex dc247a8..77cc461 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -4,13 +4,26 @@\n static int inside_git_dir = -1;\n static int inside_work_tree = -1;\n \n+#ifdef __MINGW32__\n+static inline int is_dir_sep(char c) { return c == '/' || c == '\\\\'; }\n+#else\n+static inline int is_dir_sep(char c) { return c == '/'; }\n+#endif\n+\n static int sanitary_path_copy(char *dst, const char *src)\n {\n \tchar *dst0 = dst;\n \n-\tif (*src == '/') {\n+#ifdef __MINGW32__\n+\tif (isalpha(*src) && src[1] == ':') {\n+\t\t*dst++ = *src++;\n+\t\t*dst++ = *src++;\n+\t\tdst0 = dst;\n+\t}\n+#endif\n+\tif (is_dir_sep(*src)) {\n \t\t*dst++ = '/';\n-\t\twhile (*src == '/')\n+\t\twhile (is_dir_sep(*src))\n \t\t\tsrc++;\n \t}\n \n@@ -32,9 +45,12 @@ static int sanitary_path_copy(char *dst, const char *src)\n \t\t\t\tsrc++;\n \t\t\t\tbreak;\n \t\t\tcase '/':\n+#ifdef __MINGW32__\n+\t\t\tcase '\\\\':\n+#endif\n \t\t\t\t/* (2) */\n \t\t\t\tsrc += 2;\n-\t\t\t\twhile (*src == '/')\n+\t\t\t\twhile (is_dir_sep(*src))\n \t\t\t\t\tsrc++;\n \t\t\t\tcontinue;\n \t\t\tcase '.':\n@@ -44,9 +60,12 @@ static int sanitary_path_copy(char *dst, const char *src)\n \t\t\t\t\tsrc += 2;\n \t\t\t\t\tgoto up_one;\n \t\t\t\tcase '/':\n+#ifdef __MINGW32__\n+\t\t\t\tcase '\\\\':\n+#endif\n \t\t\t\t\t/* (4) */\n \t\t\t\t\tsrc += 3;\n-\t\t\t\t\twhile (*src == '/')\n+\t\t\t\t\twhile (is_dir_sep(*src))\n \t\t\t\t\t\tsrc++;\n \t\t\t\t\tgoto up_one;\n \t\t\t\t}\n@@ -54,11 +73,11 @@ static int sanitary_path_copy(char *dst, const char *src)\n \t\t}\n \n \t\t/* copy up to the next '/', and eat all '/' */\n-\t\twhile ((c = *src++) != '\\0' && c != '/')\n+\t\twhile ((c = *src++) != '\\0' && !is_dir_sep(c))\n \t\t\t*dst++ = c;\n-\t\tif (c == '/') {\n-\t\t\t*dst++ = c;\n-\t\t\twhile (c == '/')\n+\t\tif (is_dir_sep(c)) {\n+\t\t\t*dst++ = '/';\n+\t\t\twhile (is_dir_sep(c))\n \t\t\t\tc = *src++;\n \t\t\tsrc--;\n \t\t} else if (!c)\n@@ -77,7 +96,7 @@ static int sanitary_path_copy(char *dst, const char *src)\n \t\t\tif (dst <= dst0)\n \t\t\t\tbreak;\n \t\t\tc = *dst--;\n-\t\t\tif (c == '/') {\n+\t\t\tif (c == '/') {\t/* MinGW: cannot be '\\\\' anymore */\n \t\t\t\tdst += 2;\n \t\t\t\tbreak;\n \t\t\t}\n@@ -126,10 +145,23 @@ const char *prefix_path(const char *prefix, int len, const char *path)\n const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)\n {\n \tstatic char path[PATH_MAX];\n+#ifndef __MINGW32__\n \tif (!pfx || !*pfx || is_absolute_path(arg))\n \t\treturn arg;\n \tmemcpy(path, pfx, pfx_len);\n \tstrcpy(path + pfx_len, arg);\n+#else\n+\tchar *p;\n+\t/* don't add prefix to absolute paths, but still replace '\\' by '/' */\n+\tif (is_absolute_path(arg))\n+\t\tpfx_len = 0;\n+\telse\n+\t\tmemcpy(path, pfx, pfx_len);\n+\tstrcpy(path + pfx_len, arg);\n+\tfor (p = path + pfx_len; *p; p++)\n+\t\tif (*p == '\\\\')\n+\t\t\t*p = '/';\n+#endif\n \treturn path;\n }\n \n@@ -322,6 +354,7 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \tstatic char cwd[PATH_MAX+1];\n \tconst char *gitdirenv;\n \tint len, offset;\n+\tint minoffset = 0;\n \n \t/*\n \t * If GIT_DIR is set explicitly, we're not going\n@@ -364,6 +397,10 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \n \tif (!getcwd(cwd, sizeof(cwd)-1))\n \t\tdie(\"Unable to read current working directory\");\n+#ifdef __MINGW32__\n+\tif (cwd[1] == ':')\n+\t\tminoffset = 2;\n+#endif\n \n \t/*\n \t * Test in the following order (relative to the cwd):\n@@ -388,7 +425,7 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t}\n \t\tchdir(\"..\");\n \t\tdo {\n-\t\t\tif (!offset) {\n+\t\t\tif (offset <= minoffset) {\n \t\t\t\tif (nongit_ok) {\n \t\t\t\t\tif (chdir(cwd))\n \t\t\t\t\t\tdie(\"Cannot come back to cwd\");\n@@ -397,7 +434,7 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t\t\t}\n \t\t\t\tdie(\"Not a git repository\");\n \t\t\t}\n-\t\t} while (cwd[--offset] != '/');\n+\t\t} while (offset > minoffset && cwd[--offset] != '/');\n \t}\n \n \tinside_git_dir = 0;\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70132","messageId":"1204138503-6126-12-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 11/40] Windows: Handle absolute paths in safe_create_leading_directories().","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:34Z","receivedAt":"2008-02-27T18:54:34Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"In this function we must be careful to handle drive-local paths else there\nis a danger that it runs into an infinite loop.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n sha1_file.c |   14 ++++++++++----\n 1 files changed, 10 insertions(+), 4 deletions(-)\n\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 453bc43..0c60849 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -83,14 +83,20 @@ int get_sha1_hex(const char *hex, unsigned char *sha1)\n \treturn 0;\n }\n \n+static inline int offset_1st_component(const char *path)\n+{\n+#ifdef __MINGW32__\n+\tif (isalpha(path[0]) && path[1] == ':')\n+\t\treturn 2 + (path[2] == '/');\n+#endif\n+\treturn *path == '/';\n+}\n+\n int safe_create_leading_directories(char *path)\n {\n-\tchar *pos = path;\n+\tchar *pos = path + offset_1st_component(path);\n \tstruct stat st;\n \n-\tif (is_absolute_path(path))\n-\t\tpos++;\n-\n \twhile (pos) {\n \t\tpos = strchr(pos, '/');\n \t\tif (!pos)\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70125","messageId":"1204138503-6126-13-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 12/40] Windows: Implement gettimeofday().","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:35Z","receivedAt":"2008-02-27T18:54:35Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"For this purpose we make my_mktime of date.c public and use it to convert\na struct tm to a time_t.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c |   14 ++++++++++++++\n date.c         |    2 +-\n 2 files changed, 15 insertions(+), 1 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 71bca96..24f783b 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -38,6 +38,20 @@ 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+\ttm.tm_year = st.wYear-1900;\n+\ttm.tm_mon = st.wMonth-1;\n+\ttm.tm_mday = st.wDay;\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+\tif (tv->tv_sec < 0)\n+\t\treturn -1;\n+\ttv->tv_usec = st.wMilliseconds*1000;\n \treturn 0;\n }\n \ndiff --git a/date.c b/date.c\nindex 8f70500..9c16eae 100644\n--- a/date.c\n+++ b/date.c\n@@ -6,7 +6,7 @@\n \n #include \"cache.h\"\n \n-static time_t my_mktime(struct tm *tm)\n+time_t my_mktime(struct tm *tm)\n {\n \tstatic const int mdays[] = {\n \t    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70138","messageId":"1204138503-6126-14-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 13/40] Windows: Fix PRIuMAX definition.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:36Z","receivedAt":"2008-02-27T18:54:36Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Since GIT calls into Microsoft's MSVCRT.DLL, it must use the printf\nformat that this DLL uses for 64-bit integers, which is %I64u instead\nof %llu.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n git-compat-util.h |    4 ++++\n 1 files changed, 4 insertions(+), 0 deletions(-)\n\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 3b57464..c576f5a 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -103,7 +103,11 @@\n #endif\n \n #ifndef PRIuMAX\n+#ifndef __MINGW32__\n #define PRIuMAX \"llu\"\n+#else\n+#define PRIuMAX \"I64u\"\n+#endif\n #endif\n \n #ifdef __GNUC__\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70124","messageId":"1204138503-6126-15-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 14/40] Windows: Implement setitimer() and sigaction().","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:37Z","receivedAt":"2008-02-27T18:54:37Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"The timer is implemented using a thread that calls the signal handler\nat regular intervals.\n\nWe also replace Windows's signal() function because we must intercept\nthat SIGALRM is set (which is used when a timer is canceled).\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c    |  111 ++++++++++++++++++++++++++++++++++++++++++++++++++++-\n git-compat-util.h |    3 +\n 2 files changed, 113 insertions(+), 1 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 24f783b..4888a03 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -129,12 +129,121 @@ struct passwd *getpwuid(int uid)\n \treturn &p;\n }\n \n-int setitimer(int type, struct itimerval *in, struct itimerval *out)\n+static HANDLE timer_event;\n+static HANDLE timer_thread;\n+static int timer_interval;\n+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+ * 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+ */\n+\n+static __stdcall unsigned ticktack(void *dummy)\n+{\n+\twhile (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {\n+\t\tif (timer_fn == SIG_DFL)\n+\t\t\tdie(\"Alarm\");\n+\t\tif (timer_fn != SIG_IGN)\n+\t\t\ttimer_fn(SIGALRM);\n+\t\tif (one_shot)\n+\t\t\tbreak;\n+\t}\n+\treturn 0;\n+}\n+\n+static int start_timer_thread(void)\n {\n+\ttimer_event = CreateEvent(NULL, FALSE, FALSE, NULL);\n+\tif (timer_event) {\n+\t\ttimer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);\n+\t\tif (!timer_thread )\n+\t\t\treturn errno = ENOMEM,\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 \treturn 0;\n }\n \n+static void stop_timer_thread(void)\n+{\n+\tif (timer_event)\n+\t\tSetEvent(timer_event);\t/* tell thread to terminate */\n+\tif (timer_thread) {\n+\t\tint rc = WaitForSingleObject(timer_thread, 1000);\n+\t\tif (rc == WAIT_TIMEOUT)\n+\t\t\terror(\"timer thread did not terminate timely\");\n+\t\telse if (rc != WAIT_OBJECT_0)\n+\t\t\terror(\"waiting for timer thread failed: %lu\",\n+\t\t\t      GetLastError());\n+\t\tCloseHandle(timer_thread);\n+\t}\n+\tif (timer_event)\n+\t\tCloseHandle(timer_event);\n+\ttimer_event = NULL;\n+\ttimer_thread = NULL;\n+}\n+\n+static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *i2)\n+{\n+\treturn i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec;\n+}\n+\n+int setitimer(int type, struct itimerval *in, struct itimerval *out)\n+{\n+\tstatic const struct timeval zero;\n+\tstatic int atexit_done;\n+\n+\tif (out != NULL)\n+\t\treturn errno = EINVAL,\n+\t\t\terror(\"setitmer 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+\n+\tif (timer_thread)\n+\t\tstop_timer_thread();\n+\n+\tif (is_timeval_eq(&in->it_value, &zero) &&\n+\t    is_timeval_eq(&in->it_interval, &zero))\n+\t\treturn 0;\n+\n+\ttimer_interval = in->it_value.tv_sec * 1000 + in->it_value.tv_usec / 1000;\n+\tone_shot = is_timeval_eq(&in->it_interval, &zero);\n+\tif (!atexit_done) {\n+\t\tatexit(stop_timer_thread);\n+\t\tatexit_done = 1;\n+\t}\n+\treturn start_timer_thread();\n+}\n+\n int sigaction(int sig, struct sigaction *in, struct sigaction *out)\n {\n+\tif (sig != SIGALRM)\n+\t\treturn errno = EINVAL,\n+\t\t\terror(\"sigaction only implemented for SIGALRM\");\n+\tif (out != NULL)\n+\t\treturn errno = EINVAL,\n+\t\t\terror(\"sigaction: param 3 != NULL not implemented\");\n+\n+\ttimer_fn = in->sa_handler;\n \treturn 0;\n }\n+\n+#undef signal\n+sig_handler_t mingw_signal(int sig, sig_handler_t handler)\n+{\n+\tif (sig != SIGALRM)\n+\t\treturn signal(sig, handler);\n+\tsig_handler_t old = timer_fn;\n+\ttimer_fn = handler;\n+\treturn old;\n+}\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex c576f5a..483ace2 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -602,6 +602,9 @@ char *mingw_getcwd(char *pointer, int len);\n int mingw_rename(const char*, const char*);\n #define rename mingw_rename\n \n+sig_handler_t mingw_signal(int sig, sig_handler_t handler);\n+#define signal mingw_signal\n+\n #endif /* __MINGW32__ */\n \n #endif\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70136","messageId":"1204138503-6126-16-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 15/40] Windows: A work-around for a misbehaved vsnprintf.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:38Z","receivedAt":"2008-02-27T18:54:38Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Windows, vsnprintf deviates in two regards from the \"usual\" behavior\nthat its callers in GIT expect:\n\n- It returns -1 if the buffer is too small instead of the number of\n  characters that the operation produces.\n\n- The size parameter is the number of characters to write, which does not\n  include the trailing NUL byte, instead of the available space.\n\nThis wrapper computes the needed buffer size by trying various sizes with\nexponential growth. A large growth factor is used so as only few trials are\nrequired if a really large result needs to be stored.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c    |   34 ++++++++++++++++++++++++++++++++++\n git-compat-util.h |    3 +++\n 2 files changed, 37 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 4888a03..77e4b83 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -115,6 +115,40 @@ int mingw_rename(const char *pold, const char *pnew)\n \treturn -1;\n }\n \n+#undef vsnprintf\n+/* Note that the size parameter specifies the available space, i.e.\n+ * includes the trailing NUL byte; but Windows's vsnprintf expects the\n+ * number of characters to write without the trailing NUL.\n+ */\n+\n+/* This is out of line because it uses alloca() behind the scenes,\n+ * which must not be called in a loop (alloca() reclaims the allocations\n+ * only at function exit).\n+ */\n+static int try_vsnprintf(size_t size, const char *fmt, va_list args)\n+{\n+\tchar buf[size];\t/* gcc-ism */\n+\treturn vsnprintf(buf, size-1, fmt, args);\n+}\n+\n+int mingw_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)\n+{\n+\tint len;\n+\tif (size > 0) {\n+\t\tlen = vsnprintf(buf, size-1, fmt, args);\n+\t\tif (len >= 0)\n+\t\t\treturn len;\n+\t}\n+\t/* ouch, buffer too small; need to compute the size */\n+\tif (size < 250)\n+\t\tsize = 250;\n+\tdo {\n+\t\tsize *= 4;\n+\t\tlen = try_vsnprintf(size, fmt, args);\n+\t} while (len < 0);\n+\treturn len;\n+}\n+\n struct passwd *getpwuid(int uid)\n {\n \tstatic char user_name[100];\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 483ace2..6fa93b6 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -602,6 +602,9 @@ char *mingw_getcwd(char *pointer, int len);\n int mingw_rename(const char*, const char*);\n #define rename mingw_rename\n \n+int mingw_vsnprintf(char *buf, size_t size, const char *fmt, va_list args);\n+#define vsnprintf mingw_vsnprintf\n+\n sig_handler_t mingw_signal(int sig, sig_handler_t handler);\n #define signal mingw_signal\n \n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70116","messageId":"1204138503-6126-17-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 16/40] Windows: Wrap execve so that shell scripts can be invoked.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:39Z","receivedAt":"2008-02-27T18:54:39Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"When an external git command is invoked, it can be a Bourne shell script.\nThis patch looks into the command file to see whether it is one.\nIn this case, the command line is rearranged to invoke the shell\nwith the proper arguments.\n\nWith this change, scripted git commands work. Command line arguments\nto those scripts cannot be complex (contain spaces or double-quotes), yet.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c    |  246 +++++++++++++++++++++++++++++++++++++++++++++++++++++\n git-compat-util.h |    3 +\n 2 files changed, 249 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 77e4b83..9d03ea5 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -90,6 +90,252 @@ char *mingw_getcwd(char *pointer, int len)\n \treturn ret;\n }\n \n+static const char *parse_interpreter(const char *cmd)\n+{\n+\tstatic char buf[100];\n+\tchar *p, *opt;\n+\tint n, fd;\n+\n+\t/* don't even try a .exe */\n+\tn = strlen(cmd);\n+\tif (n >= 4 && !strcasecmp(cmd+n-4, \".exe\"))\n+\t\treturn NULL;\n+\n+\tfd = open(cmd, O_RDONLY);\n+\tif (fd < 0)\n+\t\treturn NULL;\n+\tn = read(fd, buf, sizeof(buf)-1);\n+\tclose(fd);\n+\tif (n < 4)\t/* at least '#!/x' and not error */\n+\t\treturn NULL;\n+\n+\tif (buf[0] != '#' || buf[1] != '!')\n+\t\treturn NULL;\n+\tbuf[n] = '\\0';\n+\tp = strchr(buf, '\\n');\n+\tif (!p)\n+\t\treturn NULL;\n+\n+\t*p = '\\0';\n+\tif (!(p = strrchr(buf+2, '/')) && !(p = strrchr(buf+2, '\\\\')))\n+\t\treturn NULL;\n+\t/* strip options */\n+\tif ((opt = strchr(p+1, ' ')))\n+\t\t*opt = '\\0';\n+\treturn p+1;\n+}\n+\n+/*\n+ * Splits the PATH into parts.\n+ */\n+static char **get_path_split(void)\n+{\n+\tchar *p, **path, *envpath = getenv(\"PATH\");\n+\tint i, n = 0;\n+\n+\tif (!envpath || !*envpath)\n+\t\treturn NULL;\n+\n+\tenvpath = xstrdup(envpath);\n+\tp = envpath;\n+\twhile (p) {\n+\t\tchar *dir = p;\n+\t\tp = strchr(p, ';');\n+\t\tif (p) *p++ = '\\0';\n+\t\tif (*dir) {\t/* not earlier, catches series of ; */\n+\t\t\t++n;\n+\t\t}\n+\t}\n+\tif (!n)\n+\t\treturn NULL;\n+\n+\tpath = xmalloc((n+1)*sizeof(char*));\n+\tp = envpath;\n+\ti = 0;\n+\tdo {\n+\t\tif (*p)\n+\t\t\tpath[i++] = xstrdup(p);\n+\t\tp = p+strlen(p)+1;\n+\t} while (i < n);\n+\tpath[i] = NULL;\n+\n+\tfree(envpath);\n+\n+\treturn path;\n+}\n+\n+static void free_path_split(char **path)\n+{\n+\tif (!path)\n+\t\treturn;\n+\n+\tchar **p = path;\n+\twhile (*p)\n+\t\tfree(*p++);\n+\tfree(path);\n+}\n+\n+/*\n+ * exe_only means that we only want to detect .exe files, but not scripts\n+ * (which do not have an extension)\n+ */\n+static char *lookup_prog(const char *dir, const char *cmd, int isexe, int exe_only)\n+{\n+\tchar path[MAX_PATH];\n+\tsnprintf(path, sizeof(path), \"%s/%s.exe\", dir, cmd);\n+\n+\tif (!isexe && access(path, F_OK) == 0)\n+\t\treturn xstrdup(path);\n+\tpath[strlen(path)-4] = '\\0';\n+\tif ((!exe_only || isexe) && access(path, F_OK) == 0)\n+\t\treturn xstrdup(path);\n+\treturn NULL;\n+}\n+\n+/*\n+ * Determines the absolute path of cmd using the the split path in path.\n+ * If cmd contains a slash or backslash, no lookup is performed.\n+ */\n+static char *path_lookup(const char *cmd, char **path, int exe_only)\n+{\n+\tchar *prog = NULL;\n+\tint len = strlen(cmd);\n+\tint isexe = len >= 4 && !strcasecmp(cmd+len-4, \".exe\");\n+\n+\tif (strchr(cmd, '/') || strchr(cmd, '\\\\'))\n+\t\tprog = xstrdup(cmd);\n+\n+\twhile (!prog && *path)\n+\t\tprog = lookup_prog(*path++, cmd, isexe, exe_only);\n+\n+\treturn prog;\n+}\n+\n+static int try_shell_exec(const char *cmd, char *const *argv, char **env)\n+{\n+\tconst char *interpr = parse_interpreter(cmd);\n+\tchar **path;\n+\tchar *prog;\n+\tint pid = 0;\n+\n+\tif (!interpr)\n+\t\treturn 0;\n+\tpath = get_path_split();\n+\tprog = path_lookup(interpr, path, 1);\n+\tif (prog) {\n+\t\tint argc = 0;\n+\t\tconst char **argv2;\n+\t\twhile (argv[argc]) argc++;\n+\t\targv2 = xmalloc(sizeof(*argv) * (argc+2));\n+\t\targv2[0] = (char *)interpr;\n+\t\targv2[1] = (char *)cmd;\t/* full path to the script file */\n+\t\tmemcpy(&argv2[2], &argv[1], sizeof(*argv) * argc);\n+\t\tpid = spawnve(_P_NOWAIT, prog, argv2, (const char **)env);\n+\t\tif (pid >= 0) {\n+\t\t\tint status;\n+\t\t\tif (waitpid(pid, &status, 0) < 0)\n+\t\t\t\tstatus = 255;\n+\t\t\texit(status);\n+\t\t}\n+\t\tpid = 1;\t/* indicate that we tried but failed */\n+\t\tfree(prog);\n+\t\tfree(argv2);\n+\t}\n+\tfree_path_split(path);\n+\treturn pid;\n+}\n+\n+static void mingw_execve(const char *cmd, char *const *argv, char *const *env)\n+{\n+\t/* check if git_command is a shell script */\n+\tif (!try_shell_exec(cmd, argv, (char **)env)) {\n+\t\tint pid, status;\n+\n+\t\tpid = spawnve(_P_NOWAIT, cmd, (const char **)argv, (const char **)env);\n+\t\tif (pid < 0)\n+\t\t\treturn;\n+\t\tif (waitpid(pid, &status, 0) < 0)\n+\t\t\tstatus = 255;\n+\t\texit(status);\n+\t}\n+}\n+\n+void mingw_execvp(const char *cmd, char *const *argv)\n+{\n+\tchar **path = get_path_split();\n+\tchar *prog = path_lookup(cmd, path, 0);\n+\n+\tif (prog) {\n+\t\tmingw_execve(prog, argv, environ);\n+\t\tfree(prog);\n+\t} else\n+\t\terrno = ENOENT;\n+\n+\tfree_path_split(path);\n+}\n+\n+char **copy_environ()\n+{\n+\tchar **env;\n+\tint i = 0;\n+\twhile (environ[i])\n+\t\ti++;\n+\tenv = xmalloc((i+1)*sizeof(*env));\n+\tfor (i = 0; environ[i]; i++)\n+\t\tenv[i] = xstrdup(environ[i]);\n+\tenv[i] = NULL;\n+\treturn env;\n+}\n+\n+void free_environ(char **env)\n+{\n+\tint i;\n+\tfor (i = 0; env[i]; i++)\n+\t\tfree(env[i]);\n+\tfree(env);\n+}\n+\n+static int lookup_env(char **env, const char *name, size_t nmln)\n+{\n+\tint i;\n+\n+\tfor (i = 0; env[i]; i++) {\n+\t\tif (0 == strncmp(env[i], name, nmln)\n+\t\t    && '=' == env[i][nmln])\n+\t\t\t/* matches */\n+\t\t\treturn i;\n+\t}\n+\treturn -1;\n+}\n+\n+/*\n+ * If name contains '=', then sets the variable, otherwise it unsets it\n+ */\n+char **env_setenv(char **env, const char *name)\n+{\n+\tchar *eq = strchrnul(name, '=');\n+\tint i = lookup_env(env, name, eq-name);\n+\n+\tif (i < 0) {\n+\t\tif (*eq) {\n+\t\t\tfor (i = 0; env[i]; i++)\n+\t\t\t\t;\n+\t\t\tenv = xrealloc(env, (i+2)*sizeof(*env));\n+\t\t\tenv[i] = xstrdup(name);\n+\t\t\tenv[i+1] = NULL;\n+\t\t}\n+\t}\n+\telse {\n+\t\tfree(env[i]);\n+\t\tif (*eq)\n+\t\t\tenv[i] = xstrdup(name);\n+\t\telse\n+\t\t\tfor (; env[i]; i++)\n+\t\t\t\tenv[i] = env[i+1];\n+\t}\n+\treturn env;\n+}\n+\n #undef rename\n int mingw_rename(const char *pold, const char *pnew)\n {\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 6fa93b6..e191a46 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -605,6 +605,9 @@ int mingw_rename(const char*, const char*);\n int mingw_vsnprintf(char *buf, size_t size, const char *fmt, va_list args);\n #define vsnprintf mingw_vsnprintf\n \n+void mingw_execvp(const char *cmd, char *const *argv);\n+#define execvp mingw_execvp\n+\n sig_handler_t mingw_signal(int sig, sig_handler_t handler);\n #define signal mingw_signal\n \n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70130","messageId":"1204138503-6126-18-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 17/40] Windows: A pipe() replacement whose ends are not inherited to children.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:40Z","receivedAt":"2008-02-27T18:54:40Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Unix the idiom to use a pipe is as follows:\n\n    pipe(fd);\n    pid = fork();\n    if (!pid) {\n        dup2(fd[1], 1);\n        close(fd[1]);\n        close(fd[0]);\n        ...\n     }\n     close(fd[1]);\n\ni.e. the child process closes the both pipe ends after duplicating one\nto the file descriptors where they are needed.\n\nOn Windows, which does not have fork(), we never have an opportunity to\n(1) duplicate a pipe end in the child, (2) close unused pipe ends. Instead,\nwe must use this idiom:\n\n    save1 = dup(1);\n    pipe(fd);\n    dup2(fd[1], 1);\n    spawn(...);\n    dup2(save1, 1);\n    close(fd[1]);\n\ni.e. save away the descriptor at the destination slot, replace by the pipe\nend, spawn process, restore the saved file.\n\nBut there is a problem: Notice that the child did not only inherit the\ndup2()ed descriptor, but also *both* original pipe ends. Although the one\nend that was dup()ed could be closed before the spawn(), we cannot close\nthe other end - the child inherits it, no matter what.\n\nThe solution is to generate non-inheritable pipes. At the first glance,\nthis looks strange: The purpose of pipes is usually to be inherited to\nchild processes. But notice that in the course of actions as outlined\nabove, the pipe descriptor that we want to inherit to the child is\ndup2()ed, and as it so happens, Windows's dup2() creates inheritable\nduplicates.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c    |   45 +++++++++++++++++++++++++++++++++++++++++++++\n git-compat-util.h |    5 +----\n 2 files changed, 46 insertions(+), 4 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 9d03ea5..fe6f6ce 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -55,6 +55,51 @@ int gettimeofday(struct timeval *tv, void *tz)\n \treturn 0;\n }\n \n+int pipe(int filedes[2])\n+{\n+\tint fd;\n+\tHANDLE h[2], parent;\n+\n+\tif (_pipe(filedes, 8192, 0) < 0)\n+\t\treturn -1;\n+\n+\tparent = GetCurrentProcess();\n+\n+\tif (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[0]),\n+\t\t\tparent, &h[0], 0, FALSE, DUPLICATE_SAME_ACCESS)) {\n+\t\tclose(filedes[0]);\n+\t\tclose(filedes[1]);\n+\t\treturn -1;\n+\t}\n+\tif (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[1]),\n+\t\t\tparent, &h[1], 0, FALSE, DUPLICATE_SAME_ACCESS)) {\n+\t\tclose(filedes[0]);\n+\t\tclose(filedes[1]);\n+\t\tCloseHandle(h[0]);\n+\t\treturn -1;\n+\t}\n+\tfd = _open_osfhandle((int)h[0], O_NOINHERIT);\n+\tif (fd < 0) {\n+\t\tclose(filedes[0]);\n+\t\tclose(filedes[1]);\n+\t\tCloseHandle(h[0]);\n+\t\tCloseHandle(h[1]);\n+\t\treturn -1;\n+\t}\n+\tclose(filedes[0]);\n+\tfiledes[0] = fd;\n+\tfd = _open_osfhandle((int)h[1], O_NOINHERIT);\n+\tif (fd < 0) {\n+\t\tclose(filedes[0]);\n+\t\tclose(filedes[1]);\n+\t\tCloseHandle(h[1]);\n+\t\treturn -1;\n+\t}\n+\tclose(filedes[1]);\n+\tfiledes[1] = fd;\n+\treturn 0;\n+}\n+\n int poll(struct pollfd *ufds, unsigned int nfds, int timeout)\n {\n \treturn 0;\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex e191a46..170c279 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -571,14 +571,11 @@ static inline int waitpid(pid_t pid, unsigned *status, unsigned options)\n \treturn -1;\n }\n \n-\n-static inline int pipe(int filedes[2])\n-{ return _pipe(filedes, 8192, 0); }\n-\n /*\n  * implementations of missing functions\n  */\n \n+int pipe(int filedes[2]);\n unsigned int sleep (unsigned int seconds);\n int gettimeofday(struct timeval *tv, void *tz);\n int poll(struct pollfd *ufds, unsigned int nfds, int timeout);\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70134","messageId":"1204138503-6126-19-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 18/40] Windows: Implement start_command().","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:41Z","receivedAt":"2008-02-27T18:54:41Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Windows, we have spawnv() variants to run a child process instead of\nfork()/exec(). In order to attach pipe ends to stdin, stdout, and stderr,\nwe have to use this idiom:\n\n    save1 = dup(1);\n    dup2(pipe[1], 1);\n    spawnv();\n    dup2(save1, 1);\n    close(pipe[1]);\n\nassuming that the descriptors created by pipe() are not inheritable.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n git-compat-util.h |    8 +++++\n run-command.c     |   89 +++++++++++++++++++++++++++++++++++++++++++++++------\n 2 files changed, 87 insertions(+), 10 deletions(-)\n\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 170c279..046891d 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -608,6 +608,14 @@ void mingw_execvp(const char *cmd, char *const *argv);\n sig_handler_t mingw_signal(int sig, sig_handler_t handler);\n #define signal mingw_signal\n \n+/*\n+ * helpers\n+ */\n+\n+char **copy_environ(void);\n+void free_environ(char **env);\n+char **env_setenv(char **env, const char *name);\n+\n #endif /* __MINGW32__ */\n \n #endif\ndiff --git a/run-command.c b/run-command.c\nindex 476d00c..873f6d0 100644\n--- a/run-command.c\n+++ b/run-command.c\n@@ -53,17 +53,8 @@ int start_command(struct child_process *cmd)\n \t\tcmd->err = fderr[0];\n \t}\n \n+#ifndef __MINGW32__\n \tcmd->pid = fork();\n-\tif (cmd->pid < 0) {\n-\t\tif (need_in)\n-\t\t\tclose_pair(fdin);\n-\t\tif (need_out)\n-\t\t\tclose_pair(fdout);\n-\t\tif (need_err)\n-\t\t\tclose_pair(fderr);\n-\t\treturn -ERR_RUN_COMMAND_FORK;\n-\t}\n-\n \tif (!cmd->pid) {\n \t\tif (cmd->no_stdin)\n \t\t\tdup_devnull(0);\n@@ -112,6 +103,84 @@ int start_command(struct child_process *cmd)\n \t\t}\n \t\tdie(\"exec %s failed.\", cmd->argv[0]);\n \t}\n+#else\n+\tint s0 = -1, s1 = -1, s2 = -1;\t/* backups of stdin, stdout, stderr */\n+\tconst char *sargv0 = cmd->argv[0];\n+\tchar **env = environ;\n+\tstruct strbuf git_cmd;\n+\n+\tif (cmd->no_stdin) {\n+\t\ts0 = dup(0);\n+\t\tdup_devnull(0);\n+\t} else if (need_in) {\n+\t\ts0 = dup(0);\n+\t\tdup2(fdin[0], 0);\n+\t} else if (cmd->in) {\n+\t\ts0 = dup(0);\n+\t\tdup2(cmd->in, 0);\n+\t}\n+\n+\tif (cmd->no_stdout) {\n+\t\ts1 = dup(1);\n+\t\tdup_devnull(1);\n+\t} else if (cmd->stdout_to_stderr) {\n+\t\ts1 = dup(1);\n+\t\tdup2(2, 1);\n+\t} else if (need_out) {\n+\t\ts1 = dup(1);\n+\t\tdup2(fdout[1], 1);\n+\t} else if (cmd->out > 1) {\n+\t\ts1 = dup(1);\n+\t\tdup2(cmd->out, 1);\n+\t}\n+\n+\tif (cmd->no_stderr) {\n+\t\ts2 = dup(2);\n+\t\tdup_devnull(2);\n+\t} else if (need_err) {\n+\t\ts2 = dup(2);\n+\t\tdup2(fderr[1], 2);\n+\t}\n+\n+\tif (cmd->dir)\n+\t\tdie(\"chdir in start_command() not implemented\");\n+\tif (cmd->env) {\n+\t\tenv = copy_environ();\n+\t\tfor (; *cmd->env; cmd->env++)\n+\t\t\tenv = env_setenv(env, *cmd->env);\n+\t}\n+\n+\tif (cmd->git_cmd) {\n+\t\tstrbuf_init(&git_cmd, 0);\n+\t\tstrbuf_addf(&git_cmd, \"git-%s\", cmd->argv[0]);\n+\t\tcmd->argv[0] = git_cmd.buf;\n+\t}\n+\n+\tcmd->pid = spawnvpe(_P_NOWAIT, cmd->argv[0], cmd->argv, (const char **)env);\n+\n+\tif (cmd->env)\n+\t\tfree_environ(env);\n+\tif (cmd->git_cmd)\n+\t\tstrbuf_release(&git_cmd);\n+\n+\tcmd->argv[0] = sargv0;\n+\tif (s0 >= 0)\n+\t\tdup2(s0, 0), close(s0);\n+\tif (s1 >= 0)\n+\t\tdup2(s1, 1), close(s1);\n+\tif (s2 >= 0)\n+\t\tdup2(s2, 2), close(s2);\n+#endif\n+\n+\tif (cmd->pid < 0) {\n+\t\tif (need_in)\n+\t\t\tclose_pair(fdin);\n+\t\tif (need_out)\n+\t\t\tclose_pair(fdout);\n+\t\tif (need_err)\n+\t\t\tclose_pair(fderr);\n+\t\treturn -ERR_RUN_COMMAND_FORK;\n+\t}\n \n \tif (need_in)\n \t\tclose(fdin[0]);\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70110","messageId":"1204138503-6126-20-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 19/40] Windows: Change the name of hook scripts to make them not executable.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:42Z","receivedAt":"2008-02-27T18:54:42Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Since on Windows there is no 'executable' bit whose absence would deny\nexecution of a script, we must change the hook scripts' names entirely\nto inhibit that they can be invoked by the tools.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n Makefile           |    3 ++-\n templates/Makefile |    8 +++++++-\n 2 files changed, 9 insertions(+), 2 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 069939f..7d4a591 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -547,6 +547,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o\n \tEXTLIBS += -lws2_32\n \tX = .exe\n+\tNOEXECTEMPL = .noexec\n endif\n ifneq (,$(findstring arm,$(uname_M)))\n \tARM_SHA1 = YesPlease\n@@ -849,7 +850,7 @@ ifndef NO_TCLTK\n \t$(QUIET_SUBDIR0)gitk-git $(QUIET_SUBDIR1) all\n endif\n \t$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all\n-\t$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1)\n+\t$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) NOEXECTEMPL='$(NOEXECTEMPL)'\n \n strip: $(PROGRAMS) git$X\n \t$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X\ndiff --git a/templates/Makefile b/templates/Makefile\nindex ebd3a62..b341105 100644\n--- a/templates/Makefile\n+++ b/templates/Makefile\n@@ -10,6 +10,8 @@ RM ?= rm -f\n prefix ?= $(HOME)\n template_dir ?= $(prefix)/share/git-core/templates\n # DESTDIR=\n+# set NOEXECTEMPL to non-empty to change the names of hook scripts\n+# so that the tools will not find them\n \n # Shell quote (do not use $(call) to accommodate ancient setups);\n DESTDIR_SQ = $(subst ','\\'',$(DESTDIR))\n@@ -32,7 +34,11 @@ boilerplates.made : $(bpsrc)\n \t\tmkdir -p blt/$$dir && \\\n \t\tcase \"$$boilerplate\" in \\\n \t\t*--) ;; \\\n-\t\t*) cp $$boilerplate blt/$$dst ;; \\\n+\t\t*) if test -n \"$$(sed -ne '/^#!\\//p' -e '1q' < \"$$boilerplate\")\"; then \\\n+\t\t\tcp \"$$boilerplate\" \"blt/$${dst}$(NOEXECTEMPL)\"; \\\n+\t\t   else \\\n+\t\t\tcp \"$$boilerplate\" \"blt/$$dst\"; \\\n+\t\t   fi ;; \\\n \t\tesac || exit; \\\n \tdone && \\\n \tdate >$@\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70135","messageId":"1204138503-6126-21-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 20/40] Windows: A rudimentary poll() emulation.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:43Z","receivedAt":"2008-02-27T18:54:43Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"This emulation of poll() is by far not general. It assumes that the\nfds that are to be waited for are connected to pipes. The pipes are\npolled in a loop until data becomes available in at least one of them.\nIf only a single fd is waited for, the implementation actually does\nnot wait at all, but assumes that a subsequent read() will block.\n\nIn order not to needlessly burn CPU time, the CPU is yielded to other\nprocesses before the next round in the poll loop using Sleep(0). Note that\nany sleep timeout greater than zero will reduce the efficiency by a\nmagnitude.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 55 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex fe6f6ce..837d741 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -102,6 +102,61 @@ int pipe(int filedes[2])\n \n int poll(struct pollfd *ufds, unsigned int nfds, int timeout)\n {\n+\tint i, pending;\n+\n+\tif (timeout != -1)\n+\t\treturn errno = EINVAL, error(\"poll timeout not supported\");\n+\n+\t/* When there is only one fd to wait for, then we pretend that\n+\t * input is available and let the actual wait happen when the\n+\t * caller invokes read().\n+\t */\n+\tif (nfds == 1) {\n+\t\tif (!(ufds[0].events & POLLIN))\n+\t\t\treturn errno = EINVAL, error(\"POLLIN not set\");\n+\t\tufds[0].revents = POLLIN;\n+\t\treturn 0;\n+\t}\n+\n+repeat:\n+\tpending = 0;\n+\tfor (i = 0; i < nfds; i++) {\n+\t\tDWORD avail = 0;\n+\t\tHANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd);\n+\t\tif (h == INVALID_HANDLE_VALUE)\n+\t\t\treturn -1;\t/* errno was set */\n+\n+\t\tif (!(ufds[i].events & POLLIN))\n+\t\t\treturn errno = EINVAL, error(\"POLLIN not set\");\n+\n+\t\t/* this emulation works only for pipes */\n+\t\tif (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) {\n+\t\t\tint err = GetLastError();\n+\t\t\tif (err == ERROR_BROKEN_PIPE) {\n+\t\t\t\tufds[i].revents = POLLHUP;\n+\t\t\t\tpending++;\n+\t\t\t} else {\n+\t\t\t\terrno = EINVAL;\n+\t\t\t\treturn error(\"PeekNamedPipe failed,\"\n+\t\t\t\t\t\" GetLastError: %u\", err);\n+\t\t\t}\n+\t\t} else if (avail) {\n+\t\t\tufds[i].revents = POLLIN;\n+\t\t\tpending++;\n+\t\t} else\n+\t\t\tufds[i].revents = 0;\n+\t}\n+\tif (!pending) {\n+\t\t/* The only times that we spin here is when the process\n+\t\t * that is connected through the pipes is waiting for\n+\t\t * its own input data to become available. But since\n+\t\t * the process (pack-objects) is itself CPU intensive,\n+\t\t * it will happily pick up the time slice that we are\n+\t\t * relinguishing here.\n+\t\t */\n+\t\tSleep(0);\n+\t\tgoto repeat;\n+\t}\n \treturn 0;\n }\n \n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70111","messageId":"1204138503-6126-22-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 21/40] Windows: Disambiguate DOS style paths from SSH URLs.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:44Z","receivedAt":"2008-02-27T18:54:44Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"If on Windows a path is specified as C:/path, then this is also a valid\nSSH URL. To disambiguate between the two interpretations we require that\na SSH URL must have a host name with at least two characters.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n connect.c |    8 +++++++-\n 1 files changed, 7 insertions(+), 1 deletions(-)\n\ndiff --git a/connect.c b/connect.c\nindex 5ac3572..7e18ac8 100644\n--- a/connect.c\n+++ b/connect.c\n@@ -529,7 +529,13 @@ struct child_process *git_connect(int fd[2], const char *url_orig,\n \t\tend = host;\n \n \tpath = strchr(end, c);\n-\tif (path) {\n+#ifdef __MINGW32__\n+\t/* host must have at least 2 chars to catch DOS C:/path */\n+\tif (path && path - end > 1)\n+#else\n+\tif (path)\n+#endif\n+\t{\n \t\tif (c == ':') {\n \t\t\tprotocol = PROTO_SSH;\n \t\t\t*path++ = '\\0';\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70128","messageId":"1204138503-6126-23-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:45Z","receivedAt":"2008-02-27T18:54:45Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"In upload-pack we must explicitly close the output channel of rev-list.\n(On Unix, the channel is closed automatically because process that runs\nrev-list terminates.)\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n run-command.c |   29 ++++++++++++++++++++++++++++-\n run-command.h |    5 +++++\n upload-pack.c |    2 ++\n 3 files changed, 35 insertions(+), 1 deletions(-)\n\ndiff --git a/run-command.c b/run-command.c\nindex 873f6d0..3834f86 100644\n--- a/run-command.c\n+++ b/run-command.c\n@@ -276,13 +276,23 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const\n \treturn run_command(&cmd);\n }\n \n+#ifdef __MINGW32__\n+static __stdcall unsigned run_thread(void *data)\n+{\n+\tstruct async *async = data;\n+\treturn async->proc(async->fd_for_proc, async->data);\n+}\n+#endif\n+\n int start_async(struct async *async)\n {\n \tint pipe_out[2];\n \n \tif (pipe(pipe_out) < 0)\n \t\treturn error(\"cannot create pipe: %s\", strerror(errno));\n+\tasync->out = pipe_out[0];\n \n+#ifndef __MINGW32__\n \tasync->pid = fork();\n \tif (async->pid < 0) {\n \t\terror(\"fork (async) failed: %s\", strerror(errno));\n@@ -293,16 +303,33 @@ int start_async(struct async *async)\n \t\tclose(pipe_out[0]);\n \t\texit(!!async->proc(pipe_out[1], async->data));\n \t}\n-\tasync->out = pipe_out[0];\n \tclose(pipe_out[1]);\n+#else\n+\tasync->fd_for_proc = pipe_out[1];\n+\tasync->tid = (HANDLE) _beginthreadex(NULL, 0, run_thread, async, 0, NULL);\n+\tif (!async->tid) {\n+\t\terror(\"cannot create thread: %s\", strerror(errno));\n+\t\tclose_pair(pipe_out);\n+\t\treturn -1;\n+\t}\n+#endif\n \treturn 0;\n }\n \n int finish_async(struct async *async)\n {\n+#ifndef __MINGW32__\n \tint ret = 0;\n \n \tif (wait_or_whine(async->pid))\n \t\tret = error(\"waitpid (async) failed\");\n+#else\n+\tDWORD ret = 0;\n+\tif (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)\n+\t\tret = error(\"waiting for thread failed: %lu\", GetLastError());\n+\telse if (!GetExitCodeThread(async->tid, &ret))\n+\t\tret = error(\"cannot get thread exit code: %lu\", GetLastError());\n+\tCloseHandle(async->tid);\n+#endif\n \treturn ret;\n }\ndiff --git a/run-command.h b/run-command.h\nindex 1fc781d..0bbac86 100644\n--- a/run-command.h\n+++ b/run-command.h\n@@ -60,7 +60,12 @@ struct async {\n \tint (*proc)(int fd, void *data);\n \tvoid *data;\n \tint out;\t/* caller reads from here and closes it */\n+#ifndef __MINGW32__\n \tpid_t pid;\n+#else\n+\tHANDLE tid;\n+\tint fd_for_proc;\n+#endif\n };\n \n int start_async(struct async *async);\ndiff --git a/upload-pack.c b/upload-pack.c\nindex b26d053..3c99c8d 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -133,6 +133,8 @@ static int do_rev_list(int fd, void *create_full_pack)\n \t\tdie(\"revision walk setup failed\");\n \tmark_edges_uninteresting(revs.commits, &revs, show_edge);\n \ttraverse_commit_list(&revs, show_commit, show_object);\n+\tfflush(pack_pipe);\n+\tfclose(pack_pipe);\n \treturn 0;\n }\n \n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70131","messageId":"1204138503-6126-24-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 23/40] Windows: Local clone must use the drive letter in absolute paths.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:46Z","receivedAt":"2008-02-27T18:54:46Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"The default of pwd of MSYS's bash and /bin/pwd are to use /c/rest/of/path\nnotation instead of c:/rest/of/path. But the former is not supported\nby programs that use the standard C runtime (instead of MSYS's\nruntime). Hence, we must make sure that only drive letter notations\nare generated by using pwd's -W option.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n git-clone.sh |   21 ++++++++++++++++++++-\n 1 files changed, 20 insertions(+), 1 deletions(-)\n\ndiff --git a/git-clone.sh b/git-clone.sh\nindex 0d686c3..640e29d 100755\n--- a/git-clone.sh\n+++ b/git-clone.sh\n@@ -32,6 +32,25 @@ die() {\n \texit 1\n }\n \n+# Fix some commands on Windows\n+case $(uname -s) in\n+*MINGW*)\n+\t# pwd must return a path with a drive letter\n+\tbin_pwd() {\n+\t\t# there are no symlinks to resolve: /bin/pwd is not needed\n+\t\tbuiltin pwd -W\n+\t}\n+\tpwd() {\n+\t\tbuiltin pwd -W\n+\t}\n+\t;;\n+*)\n+\tbin_pwd() {\n+\t\t/bin/pwd\n+\t}\n+\t;;\n+esac\n+\n usage() {\n \texec \"$0\" -h\n }\n@@ -40,7 +59,7 @@ eval \"$(echo \"$OPTIONS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\n \n get_repo_base() {\n \t(\n-\t\tcd \"`/bin/pwd`\" &&\n+\t\tcd \"$(bin_pwd)\" &&\n \t\tcd \"$1\" || cd \"$1.git\" &&\n \t\t{\n \t\t\tcd .git\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70119","messageId":"1204138503-6126-25-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 24/40] Windows: Work around incompatible sort and find.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:47Z","receivedAt":"2008-02-27T18:54:47Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"If the PATH lists the Windows system directories before the MSYS\ndirectories, Windows's own incompatible sort and find commands would be\npicked up. We implement these commands as functions and call the real\ntools by absolute path.\n\nAlso add a dummy implementation of sync to avoid an error in git-repack.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n git-clone.sh    |    4 ++++\n git-sh-setup.sh |   17 +++++++++++++++++\n t/test-lib.sh   |   13 +++++++++++++\n 3 files changed, 34 insertions(+), 0 deletions(-)\n\ndiff --git a/git-clone.sh b/git-clone.sh\nindex 640e29d..1fc5c92 100755\n--- a/git-clone.sh\n+++ b/git-clone.sh\n@@ -35,6 +35,10 @@ die() {\n # Fix some commands on Windows\n case $(uname -s) in\n *MINGW*)\n+\t# Windows has its own (incompatible) find\n+\tfind () {\n+\t\t/usr/bin/find \"$@\"\n+\t}\n \t# pwd must return a path with a drive letter\n \tbin_pwd() {\n \t\t# there are no symlinks to resolve: /bin/pwd is not needed\ndiff --git a/git-sh-setup.sh b/git-sh-setup.sh\nindex a44b1c7..822aa6f 100755\n--- a/git-sh-setup.sh\n+++ b/git-sh-setup.sh\n@@ -142,3 +142,20 @@ then\n \t}\n \t: ${GIT_OBJECT_DIRECTORY=\"$GIT_DIR/objects\"}\n fi\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# 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 83889c4..e2010d5 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -366,3 +366,16 @@ 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-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70126","messageId":"1204138503-6126-26-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 25/40] Windows: Implement a cpio emulation in git-clone.sh.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:48Z","receivedAt":"2008-02-27T18:54:48Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"We use 'xargs cp' to emulate 'cpio -pumd'.\n\ncpio is fed from the output of 'find --depth' without filtering out\ndirectories. We don't need to copy directories except the empty ones, so\nwe need to filter out non-empty directories. Then we can use 'cp -r' and\nit will not actually recurse anything.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n git-clone.sh |   27 +++++++++++++++++++++++++++\n 1 files changed, 27 insertions(+), 0 deletions(-)\n\ndiff --git a/git-clone.sh b/git-clone.sh\nindex 1fc5c92..87fc0fb 100755\n--- a/git-clone.sh\n+++ b/git-clone.sh\n@@ -39,6 +39,33 @@ case $(uname -s) in\n \tfind () {\n \t\t/usr/bin/find \"$@\"\n \t}\n+\t# need an emulation of cpio\n+\tcpio() {\n+\t\tcase \"$1\" in\n+\t\t-pumd)\tcp_arg=-pr;;\n+\t\t-pumdl)\tcp_arg=-lr;;\n+\t\t*)\tdie \"cpio $1 unexpected\";;\n+\t\tesac\n+\t\t# copy only files and empty directories\n+\t\tprev=\n+\t\twhile read f; do\n+\t\t\tif test -d \"$f\"; then\n+\t\t\t\t# here we assume that directories are listed after\n+\t\t\t\t# its files (aka 'find -depth'), hence, a directory\n+\t\t\t\t# that is not empty will be a leading sub-string\n+\t\t\t\t# of the preceding entry\n+\t\t\t\tcase \"$prev\" in\n+\t\t\t\t\"$f\"/* ) ;;\n+\t\t\t\t*)\techo \"$f\";;\n+\t\t\t\tesac\n+\t\t\telse\n+\t\t\t\techo \"$f\"\n+\t\t\tfi\n+\t\t\tprev=\"$f\"\n+\t\tdone |\n+\t\txargs --no-run-if-empty \\\n+\t\t\tcp $cp_arg --target-directory=\"$2\" --parents\n+\t}\n \t# pwd must return a path with a drive letter\n \tbin_pwd() {\n \t\t# there are no symlinks to resolve: /bin/pwd is not needed\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70139","messageId":"1204138503-6126-27-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 26/40] Windows: Implement wrappers for gethostbyname(), socket(), and connect().","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:49Z","receivedAt":"2008-02-27T18:54:49Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"gethostbyname() is the first function that calls into the Winsock library,\nand it is wrapped only to initialize the library.\n\nsocket() is wrapped for two reasons:\n- Windows's socket() creates things that are like low-level file handles,\n  and they must be converted into file descriptors first.\n- And these handles cannot be used with plain ReadFile()/WriteFile()\n  because they are opened for \"overlapped IO\". We have to use WSASocket()\n  to create non-overlapped IO sockets.\n\nconnect() must be wrapped because Windows's connect() expects the low-level\nsockets, not file descriptors, and we must first unwrap the file descriptor\nbefore we can pass it on to Windows's connect().\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c    |   46 ++++++++++++++++++++++++++++++++++++++++++++++\n git-compat-util.h |    9 +++++++++\n 2 files changed, 55 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 837d741..1260be8 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -436,6 +436,52 @@ char **env_setenv(char **env, const char *name)\n \treturn env;\n }\n \n+/* this is the first function to call into WS_32; initialize it */\n+#undef gethostbyname\n+struct hostent *mingw_gethostbyname(const char *host)\n+{\n+\tWSADATA wsa;\n+\n+\tif (WSAStartup(MAKEWORD(2,2), &wsa))\n+\t\tdie(\"unable to initialize winsock subsystem, error %d\",\n+\t\t\tWSAGetLastError());\n+\tatexit((void(*)(void)) WSACleanup);\n+\treturn gethostbyname(host);\n+}\n+\n+int mingw_socket(int domain, int type, int protocol)\n+{\n+\tint sockfd;\n+\tSOCKET s = WSASocket(domain, type, protocol, NULL, 0, 0);\n+\tif (s == INVALID_SOCKET) {\n+\t\t/*\n+\t\t * WSAGetLastError() values are regular BSD error codes\n+\t\t * biased by WSABASEERR.\n+\t\t * However, strerror() does not know about networking\n+\t\t * specific errors, which are values beginning at 38 or so.\n+\t\t * Therefore, we choose to leave the biased error code\n+\t\t * in errno so that _if_ someone looks up the code somewhere,\n+\t\t * then it is at least the number that are usually listed.\n+\t\t */\n+\t\terrno = WSAGetLastError();\n+\t\treturn -1;\n+\t}\n+\t/* convert into a file descriptor */\n+\tif ((sockfd = _open_osfhandle(s, O_RDWR|O_BINARY)) < 0) {\n+\t\tclosesocket(s);\n+\t\treturn error(\"unable to make a socket file descriptor: %s\",\n+\t\t\tstrerror(errno));\n+\t}\n+\treturn sockfd;\n+}\n+\n+#undef connect\n+int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)\n+{\n+\tSOCKET s = (SOCKET)_get_osfhandle(sockfd);\n+\treturn connect(s, sa, sz);\n+}\n+\n #undef rename\n int mingw_rename(const char *pold, const char *pnew)\n {\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 046891d..0324789 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -596,6 +596,15 @@ int mingw_open (const char *filename, int oflags, ...);\n char *mingw_getcwd(char *pointer, int len);\n #define getcwd mingw_getcwd\n \n+struct hostent *mingw_gethostbyname(const char *host);\n+#define gethostbyname mingw_gethostbyname\n+\n+int mingw_socket(int domain, int type, int protocol);\n+#define socket mingw_socket\n+\n+int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);\n+#define connect mingw_connect\n+\n int mingw_rename(const char*, const char*);\n #define rename mingw_rename\n \n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70137","messageId":"1204138503-6126-28-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 27/40] Windows: Implement a custom spawnve().","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:50Z","receivedAt":"2008-02-27T18:54:50Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"The problem with Windows's own implementation is that it tries to be\nclever when a console program is invoked from a GUI application: In this\ncase it sometimes automatically allocates a new console window. As a\nconsequence, the IO channels of the spawned program are directed to the\nconsole, but the invoking application listens on channels that are now\ndirected to nowhere.\n\nIn this implementation we use the lowlevel facilities of CreateProcess(),\nwhich offers a flag to tell the system not to open a console. As a side\neffect, only stdin, stdout, and stderr channels will be accessible from\nC programs that are spawned. Other channels (file handles, pipe handles,\netc.) are still inherited by the spawned program, but it doesn't get\nenough information to access them.\n\nJohannes Schindelin integrated path quoting and unified the various\n*execv* and *spawnv* helpers.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c    |  203 +++++++++++++++++++++++++++++++++++++++++++++++++++--\n git-compat-util.h |    1 +\n run-command.c     |    2 +-\n 3 files changed, 199 insertions(+), 7 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 1260be8..146c170 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1,4 +1,5 @@\n #include \"../git-compat-util.h\"\n+#include \"../strbuf.h\"\n \n unsigned int _CRT_fmode = _O_BINARY;\n \n@@ -190,6 +191,65 @@ char *mingw_getcwd(char *pointer, int len)\n \treturn ret;\n }\n \n+/*\n+ * See http://msdn2.microsoft.com/en-us/library/17w5ykft(vs.71).aspx\n+ * (Parsing C++ Command-Line Arguments)\n+ */\n+static const char *quote_arg(const char *arg)\n+{\n+\t/* count chars to quote */\n+\tint len = 0, n = 0;\n+\tint force_quotes = 0;\n+\tchar *q, *d;\n+\tconst char *p = arg;\n+\tif (!*p) force_quotes = 1;\n+\twhile (*p) {\n+\t\tif (isspace(*p) || *p == '*' || *p == '?')\n+\t\t\tforce_quotes = 1;\n+\t\telse if (*p == '\"')\n+\t\t\tn++;\n+\t\telse if (*p == '\\\\') {\n+\t\t\tint count = 0;\n+\t\t\twhile (*p == '\\\\') {\n+\t\t\t\tcount++;\n+\t\t\t\tp++;\n+\t\t\t\tlen++;\n+\t\t\t}\n+\t\t\tif (*p == '\"')\n+\t\t\t\tn += count*2 + 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tlen++;\n+\t\tp++;\n+\t}\n+\tif (!force_quotes && n == 0)\n+\t\treturn arg;\n+\n+\t/* insert \\ where necessary */\n+\td = q = xmalloc(len+n+3);\n+\t*d++ = '\"';\n+\twhile (*arg) {\n+\t\tif (*arg == '\"')\n+\t\t\t*d++ = '\\\\';\n+\t\telse if (*arg == '\\\\') {\n+\t\t\tint count = 0;\n+\t\t\twhile (*arg == '\\\\') {\n+\t\t\t\tcount++;\n+\t\t\t\t*d++ = *arg++;\n+\t\t\t}\n+\t\t\tif (*arg == '\"') {\n+\t\t\t\twhile (count-- > 0)\n+\t\t\t\t\t*d++ = '\\\\';\n+\t\t\t\t*d++ = '\\\\';\n+\t\t\t}\n+\t\t}\n+\t\t*d++ = *arg++;\n+\t}\n+\t*d++ = '\"';\n+\t*d++ = 0;\n+\treturn q;\n+}\n+\n static const char *parse_interpreter(const char *cmd)\n {\n \tstatic char buf[100];\n@@ -311,6 +371,138 @@ static char *path_lookup(const char *cmd, char **path, int exe_only)\n \treturn prog;\n }\n \n+static int env_compare(const void *a, const void *b)\n+{\n+\tchar *const *ea = a;\n+\tchar *const *eb = b;\n+\treturn strcasecmp(*ea, *eb);\n+}\n+\n+static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,\n+\t\t\t   int prepend_cmd)\n+{\n+\tSTARTUPINFO si;\n+\tPROCESS_INFORMATION pi;\n+\tstruct strbuf envblk, args;\n+\tunsigned flags;\n+\tBOOL ret;\n+\n+\t/* Determine whether or not we are associated to a console */\n+\tHANDLE cons = CreateFile(\"CONOUT$\", GENERIC_WRITE,\n+\t\t\tFILE_SHARE_WRITE, NULL, OPEN_EXISTING,\n+\t\t\tFILE_ATTRIBUTE_NORMAL, NULL);\n+\tif (cons == INVALID_HANDLE_VALUE) {\n+\t\t/* There is no console associated with this process.\n+\t\t * Since the child is a console process, Windows\n+\t\t * would normally create a console window. But\n+\t\t * since we'll be redirecting std streams, we do\n+\t\t * not need the console.\n+\t\t */\n+\t\tflags = CREATE_NO_WINDOW;\n+\t} else {\n+\t\t/* There is already a console. If we specified\n+\t\t * CREATE_NO_WINDOW here, too, Windows would\n+\t\t * disassociate the child from the console.\n+\t\t * Go figure!\n+\t\t */\n+\t\tflags = 0;\n+\t\tCloseHandle(cons);\n+\t}\n+\tmemset(&si, 0, sizeof(si));\n+\tsi.cb = sizeof(si);\n+\tsi.dwFlags = STARTF_USESTDHANDLES;\n+\tsi.hStdInput = (HANDLE) _get_osfhandle(0);\n+\tsi.hStdOutput = (HANDLE) _get_osfhandle(1);\n+\tsi.hStdError = (HANDLE) _get_osfhandle(2);\n+\n+\t/* concatenate argv, quoting args as we go */\n+\tstrbuf_init(&args, 0);\n+\tif (prepend_cmd) {\n+\t\tchar *quoted = (char *)quote_arg(cmd);\n+\t\tstrbuf_addstr(&args, quoted);\n+\t\tif (quoted != cmd)\n+\t\t\tfree(quoted);\n+\t}\n+\tfor (; *argv; argv++) {\n+\t\tchar *quoted = (char *)quote_arg(*argv);\n+\t\tif (*args.buf)\n+\t\t\tstrbuf_addch(&args, ' ');\n+\t\tstrbuf_addstr(&args, quoted);\n+\t\tif (quoted != *argv)\n+\t\t\tfree(quoted);\n+\t}\n+\n+\tif (env) {\n+\t\tint count = 0;\n+\t\tchar **e, **sorted_env;\n+\n+\t\tfor (e = env; *e; e++)\n+\t\t\tcount++;\n+\n+\t\t/* environment must be sorted */\n+\t\tsorted_env = xmalloc(sizeof(*sorted_env) * (count + 1));\n+\t\tmemcpy(sorted_env, env, sizeof(*sorted_env) * (count + 1));\n+\t\tqsort(sorted_env, count, sizeof(*sorted_env), env_compare);\n+\n+\t\tstrbuf_init(&envblk, 0);\n+\t\tfor (e = sorted_env; *e; e++) {\n+\t\t\tstrbuf_addstr(&envblk, *e);\n+\t\t\tstrbuf_addch(&envblk, '\\0');\n+\t\t}\n+\t\tfree(sorted_env);\n+\t}\n+\n+\tmemset(&pi, 0, sizeof(pi));\n+\tret = CreateProcess(cmd, args.buf, NULL, NULL, TRUE, flags,\n+\t\tenv ? envblk.buf : NULL, NULL, &si, &pi);\n+\n+\tif (env)\n+\t\tstrbuf_release(&envblk);\n+\tstrbuf_release(&args);\n+\n+\tif (!ret) {\n+\t\terrno = ENOENT;\n+\t\treturn -1;\n+\t}\n+\tCloseHandle(pi.hThread);\n+\treturn (pid_t)pi.hProcess;\n+}\n+\n+pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env)\n+{\n+\tpid_t pid;\n+\tchar **path = get_path_split();\n+\tchar *prog = path_lookup(cmd, path, 0);\n+\n+\tif (!prog) {\n+\t\terrno = ENOENT;\n+\t\tpid = -1;\n+\t}\n+\telse {\n+\t\tconst char *interpr = parse_interpreter(prog);\n+\n+\t\tif (interpr) {\n+\t\t\tconst char *argv0 = argv[0];\n+\t\t\tchar *iprog = path_lookup(interpr, path, 1);\n+\t\t\targv[0] = prog;\n+\t\t\tif (!iprog) {\n+\t\t\t\terrno = ENOENT;\n+\t\t\t\tpid = -1;\n+\t\t\t}\n+\t\t\telse {\n+\t\t\t\tpid = mingw_spawnve(iprog, argv, env, 1);\n+\t\t\t\tfree(iprog);\n+\t\t\t}\n+\t\t\targv[0] = argv0;\n+\t\t}\n+\t\telse\n+\t\t\tpid = mingw_spawnve(prog, argv, env, 0);\n+\t\tfree(prog);\n+\t}\n+\tfree_path_split(path);\n+\treturn pid;\n+}\n+\n static int try_shell_exec(const char *cmd, char *const *argv, char **env)\n {\n \tconst char *interpr = parse_interpreter(cmd);\n@@ -326,11 +518,10 @@ static int try_shell_exec(const char *cmd, char *const *argv, char **env)\n \t\tint argc = 0;\n \t\tconst char **argv2;\n \t\twhile (argv[argc]) argc++;\n-\t\targv2 = xmalloc(sizeof(*argv) * (argc+2));\n-\t\targv2[0] = (char *)interpr;\n-\t\targv2[1] = (char *)cmd;\t/* full path to the script file */\n-\t\tmemcpy(&argv2[2], &argv[1], sizeof(*argv) * argc);\n-\t\tpid = spawnve(_P_NOWAIT, prog, argv2, (const char **)env);\n+\t\targv2 = xmalloc(sizeof(*argv) * (argc+1));\n+\t\targv2[0] = (char *)cmd;\t/* full path to the script file */\n+\t\tmemcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);\n+\t\tpid = mingw_spawnve(prog, argv2, env, 1);\n \t\tif (pid >= 0) {\n \t\t\tint status;\n \t\t\tif (waitpid(pid, &status, 0) < 0)\n@@ -351,7 +542,7 @@ static void mingw_execve(const char *cmd, char *const *argv, char *const *env)\n \tif (!try_shell_exec(cmd, argv, (char **)env)) {\n \t\tint pid, status;\n \n-\t\tpid = spawnve(_P_NOWAIT, cmd, (const char **)argv, (const char **)env);\n+\t\tpid = mingw_spawnve(cmd, (const char **)argv, (char **)env, 0);\n \t\tif (pid < 0)\n \t\t\treturn;\n \t\tif (waitpid(pid, &status, 0) < 0)\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 0324789..570eb10 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -611,6 +611,7 @@ int mingw_rename(const char*, const char*);\n int mingw_vsnprintf(char *buf, size_t size, const char *fmt, va_list args);\n #define vsnprintf mingw_vsnprintf\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\n \ndiff --git a/run-command.c b/run-command.c\nindex 3834f86..5ed338c 100644\n--- a/run-command.c\n+++ b/run-command.c\n@@ -156,7 +156,7 @@ int start_command(struct child_process *cmd)\n \t\tcmd->argv[0] = git_cmd.buf;\n \t}\n \n-\tcmd->pid = spawnvpe(_P_NOWAIT, cmd->argv[0], cmd->argv, (const char **)env);\n+\tcmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);\n \n \tif (cmd->env)\n \t\tfree_environ(env);\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70133","messageId":"1204138503-6126-29-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 28/40] Windows: Add a new lstat and fstat implementation based on Win32 API.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:51Z","receivedAt":"2008-02-27T18:54:51Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"From: Marius Storm-Olsen <mstormo_git@storm-olsen.com>\n\nFrom: Marius Storm-Olsen <mstormo_git@storm-olsen.com>\n\nThis gives us a significant speedup when adding, committing and stat'ing files.\nAlso, since Windows doesn't really handle symlinks, we let stat just uses lstat.\nWe also need to replace fstat, since our implementation and the standard stat()\nfunctions report slightly different timestamps, possibly due to timezones.\n\nWe simply report UTC in our implementation, and do our FILETIME to time_t\nconversion based on the document at http://support.microsoft.com/kb/167296.\n\nWith Moe's repo structure (100K files in 100 dirs, containing 2-4 bytes)\n    mkdir bummer && cd bummer; for ((i=0;i<100;i++)); do\n      mkdir $i && pushd $i;\n        for ((j=0;j<1000;j++)); do echo \"$j\" >$j; done;\n      popd;\n    done\n\nWe get the following performance boost:\n\n    With normal lstat & stat  Custom lstat/fstat\n    ------------------------  ------------------------\n    Command: git init         Command: git init\n    ------------------------  ------------------------\n    real    0m 0.047s          real   0m 0.063s\n    user    0m 0.031s          user   0m 0.015s\n    sys     0m 0.000s          sys    0m 0.015s\n    ------------------------  ------------------------\n    Command: git add .        Command: git add .\n    ------------------------  ------------------------\n    real    0m19.390s         real    0m12.031s       1.6x\n    user    0m 0.015s         user    0m 0.031s\n    sys     0m 0.030s         sys     0m 0.000s\n    ------------------------  ------------------------\n    Command: git commit -a..  Command: git commit -a..\n    ------------------------  ------------------------\n    real    0m30.812s         real    0m16.875s       1.8x\n    user    0m 0.015s         user    0m 0.015s\n    sys     0m 0.000s         sys     0m 0.015s\n    ------------------------  ------------------------\n    3x Command: git-status    3x Command: git-status\n    ------------------------  ------------------------\n    real    0m11.860s         real    0m 5.266s       2.2x\n    user    0m 0.015s         user    0m 0.015s\n    sys     0m 0.015s         sys     0m 0.015s\n\n    real    0m11.703s         real    0m 5.234s\n    user    0m 0.015s         user    0m 0.015s\n    sys     0m 0.000s         sys     0m 0.000s\n\n    real    0m11.672s         real    0m 5.250s\n    user    0m 0.031s         user    0m 0.015s\n    sys     0m 0.000s         sys     0m 0.000s\n    ------------------------  ------------------------\n    Command: git commit...    Command: git commit...\n    (single file)             (single file)\n    ------------------------  ------------------------\n    real    0m14.234s         real    0m 7.735s       1.8x\n    user    0m 0.015s         user    0m 0.031s\n    sys     0m 0.000s         sys     0m 0.000s\n\nSigned-off-by: Marius Storm-Olsen <mstormo_git@storm-olsen.com>\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c    |  132 +++++++++++++++++++++++++++++++++++++++++++++++++++++\n git-compat-util.h |   10 ++++-\n 2 files changed, 141 insertions(+), 1 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 146c170..d44fbb3 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -23,6 +23,138 @@ int mingw_open (const char *filename, int oflags, ...)\n \treturn fd;\n }\n \n+static inline time_t filetime_to_time_t(const FILETIME *ft)\n+{\n+\tlong long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;\n+\twinTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */\n+\twinTime /= 10000000;\t\t /* Nano to seconds resolution */\n+\treturn (time_t)winTime;\n+}\n+\n+extern int _getdrive( void );\n+/* We keep the do_lstat code in a separate function to avoid recursion.\n+ * When a path ends with a slash, the stat will fail with ENOENT. In\n+ * this case, we strip the trailing slashes and stat again.\n+ */\n+static int do_lstat(const char *file_name, struct stat *buf)\n+{\n+\tWIN32_FILE_ATTRIBUTE_DATA fdata;\n+\n+\tif (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) {\n+\t\tint fMode = S_IREAD;\n+\t\tif (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\n+\t\t\tfMode |= S_IFDIR;\n+\t\telse\n+\t\t\tfMode |= S_IFREG;\n+\t\tif (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))\n+\t\t\tfMode |= S_IWRITE;\n+\n+\t\tbuf->st_ino = 0;\n+\t\tbuf->st_gid = 0;\n+\t\tbuf->st_uid = 0;\n+\t\tbuf->st_nlink = 1;\n+\t\tbuf->st_mode = fMode;\n+\t\tbuf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */\n+\t\tbuf->st_dev = buf->st_rdev = (_getdrive() - 1);\n+\t\tbuf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));\n+\t\tbuf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));\n+\t\tbuf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));\n+\t\terrno = 0;\n+\t\treturn 0;\n+\t}\n+\n+\tswitch (GetLastError()) {\n+\tcase ERROR_ACCESS_DENIED:\n+\tcase ERROR_SHARING_VIOLATION:\n+\tcase ERROR_LOCK_VIOLATION:\n+\tcase ERROR_SHARING_BUFFER_EXCEEDED:\n+\t\terrno = EACCES;\n+\t\tbreak;\n+\tcase ERROR_BUFFER_OVERFLOW:\n+\t\terrno = ENAMETOOLONG;\n+\t\tbreak;\n+\tcase ERROR_NOT_ENOUGH_MEMORY:\n+\t\terrno = ENOMEM;\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = ENOENT;\n+\t\tbreak;\n+\t}\n+\treturn -1;\n+}\n+\n+/* We provide our own lstat/fstat functions, since the provided\n+ * lstat/fstat functions are so slow. These stat functions are\n+ * tailored for Git's usage (read: fast), and are not meant to be\n+ * complete. Note that Git stat()s are redirected to mingw_lstat()\n+ * too, since Windows doesn't really handle symlinks that well.\n+ */\n+int mingw_lstat(const char *file_name, struct stat *buf)\n+{\n+\tint namelen;\n+\tstatic char alt_name[PATH_MAX];\n+\n+\tif (!do_lstat(file_name, buf))\n+\t\treturn 0;\n+\n+\t/* if file_name ended in a '/', Windows returned ENOENT;\n+\t * try again without trailing slashes\n+\t */\n+\tif (errno != ENOENT)\n+\t\treturn -1;\n+\n+\tnamelen = strlen(file_name);\n+\tif (namelen && file_name[namelen-1] != '/')\n+\t\treturn -1;\n+\twhile (namelen && file_name[namelen-1] == '/')\n+\t\t--namelen;\n+\tif (!namelen || namelen >= PATH_MAX)\n+\t\treturn -1;\n+\n+\tmemcpy(alt_name, file_name, namelen);\n+\talt_name[namelen] = 0;\n+\treturn do_lstat(alt_name, buf);\n+}\n+\n+#undef fstat\n+int mingw_fstat(int fd, struct stat *buf)\n+{\n+\tHANDLE fh = (HANDLE)_get_osfhandle(fd);\n+\tBY_HANDLE_FILE_INFORMATION fdata;\n+\n+\tif (fh == INVALID_HANDLE_VALUE) {\n+\t\terrno = EBADF;\n+\t\treturn -1;\n+\t}\n+\t/* direct non-file handles to MS's fstat() */\n+\tif (GetFileType(fh) != FILE_TYPE_DISK)\n+\t\treturn fstat(fd, buf);\n+\n+\tif (GetFileInformationByHandle(fh, &fdata)) {\n+\t\tint fMode = S_IREAD;\n+\t\tif (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\n+\t\t\tfMode |= S_IFDIR;\n+\t\telse\n+\t\t\tfMode |= S_IFREG;\n+\t\tif (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))\n+\t\t\tfMode |= S_IWRITE;\n+\n+\t\tbuf->st_ino = 0;\n+\t\tbuf->st_gid = 0;\n+\t\tbuf->st_uid = 0;\n+\t\tbuf->st_nlink = 1;\n+\t\tbuf->st_mode = fMode;\n+\t\tbuf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */\n+\t\tbuf->st_dev = buf->st_rdev = (_getdrive() - 1);\n+\t\tbuf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));\n+\t\tbuf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));\n+\t\tbuf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));\n+\t\treturn 0;\n+\t}\n+\terrno = EBADF;\n+\treturn -1;\n+}\n+\n unsigned int sleep (unsigned int seconds)\n {\n \tSleep(seconds*1000);\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 570eb10..0583a1f 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -509,7 +509,6 @@ struct itimerval {\n #define ITIMER_REAL 0\n \n #define st_blocks st_size/512\t/* will be cleaned up later */\n-#define lstat stat\n \n /*\n  * trivial stubs\n@@ -608,6 +607,15 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);\n int mingw_rename(const char*, const char*);\n #define rename mingw_rename\n \n+/* Use mingw_lstat() instead of lstat()/stat() and\n+ * mingw_fstat() instead of fstat() on Windows.\n+ */\n+int mingw_lstat(const char *file_name, struct stat *buf);\n+int mingw_fstat(int fd, struct stat *buf);\n+#define fstat mingw_fstat\n+#define lstat mingw_lstat\n+#define stat(x,y) mingw_lstat(x,y)\n+\n int mingw_vsnprintf(char *buf, size_t size, const char *fmt, va_list args);\n #define vsnprintf mingw_vsnprintf\n \n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70123","messageId":"1204138503-6126-30-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 29/40] Windows: Use a customized struct stat that also has the st_blocks member.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:52Z","receivedAt":"2008-02-27T18:54:52Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Windows's struct stat does not have a st_blocks member. Since we already\nhave our own stat/lstat/fstat implementations, we can just as well use\na customized struct stat. This patch introduces just that, and also fills\nin the st_blocks member. On the other hand, we don't provide members that\nare never used.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c    |   36 ++++++++++++++++++++++++++++--------\n git-compat-util.h |   18 +++++++++++++-----\n 2 files changed, 41 insertions(+), 13 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex d44fbb3..0888288 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -31,6 +31,11 @@ static inline time_t filetime_to_time_t(const FILETIME *ft)\n \treturn (time_t)winTime;\n }\n \n+static inline size_t size_to_blocks(size_t s)\n+{\n+\treturn (s+511)/512;\n+}\n+\n extern int _getdrive( void );\n /* We keep the do_lstat code in a separate function to avoid recursion.\n  * When a path ends with a slash, the stat will fail with ENOENT. In\n@@ -52,10 +57,10 @@ static int do_lstat(const char *file_name, struct stat *buf)\n \t\tbuf->st_ino = 0;\n \t\tbuf->st_gid = 0;\n \t\tbuf->st_uid = 0;\n-\t\tbuf->st_nlink = 1;\n \t\tbuf->st_mode = fMode;\n \t\tbuf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */\n-\t\tbuf->st_dev = buf->st_rdev = (_getdrive() - 1);\n+\t\tbuf->st_blocks = size_to_blocks(buf->st_size);\n+\t\tbuf->st_dev = _getdrive() - 1;\n \t\tbuf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));\n \t\tbuf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));\n \t\tbuf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));\n@@ -89,7 +94,7 @@ static int do_lstat(const char *file_name, struct stat *buf)\n  * complete. Note that Git stat()s are redirected to mingw_lstat()\n  * too, since Windows doesn't really handle symlinks that well.\n  */\n-int mingw_lstat(const char *file_name, struct stat *buf)\n+int mingw_lstat(const char *file_name, struct mingw_stat *buf)\n {\n \tint namelen;\n \tstatic char alt_name[PATH_MAX];\n@@ -117,7 +122,8 @@ int mingw_lstat(const char *file_name, struct stat *buf)\n }\n \n #undef fstat\n-int mingw_fstat(int fd, struct stat *buf)\n+#undef stat\n+int mingw_fstat(int fd, struct mingw_stat *buf)\n {\n \tHANDLE fh = (HANDLE)_get_osfhandle(fd);\n \tBY_HANDLE_FILE_INFORMATION fdata;\n@@ -127,8 +133,22 @@ int mingw_fstat(int fd, struct stat *buf)\n \t\treturn -1;\n \t}\n \t/* direct non-file handles to MS's fstat() */\n-\tif (GetFileType(fh) != FILE_TYPE_DISK)\n-\t\treturn fstat(fd, buf);\n+\tif (GetFileType(fh) != FILE_TYPE_DISK) {\n+\t\tstruct stat st;\n+\t\tif (fstat(fd, &st))\n+\t\t\treturn -1;\n+\t\tbuf->st_ino = st.st_ino;\n+\t\tbuf->st_gid = st.st_gid;\n+\t\tbuf->st_uid = st.st_uid;\n+\t\tbuf->st_mode = st.st_mode;\n+\t\tbuf->st_size = st.st_size;\n+\t\tbuf->st_blocks = size_to_blocks(buf->st_size);\n+\t\tbuf->st_dev = st.st_dev;\n+\t\tbuf->st_atime = st.st_atime;\n+\t\tbuf->st_mtime = st.st_mtime;\n+\t\tbuf->st_ctime = st.st_ctime;\n+\t\treturn 0;\n+\t}\n \n \tif (GetFileInformationByHandle(fh, &fdata)) {\n \t\tint fMode = S_IREAD;\n@@ -142,10 +162,10 @@ int mingw_fstat(int fd, struct stat *buf)\n \t\tbuf->st_ino = 0;\n \t\tbuf->st_gid = 0;\n \t\tbuf->st_uid = 0;\n-\t\tbuf->st_nlink = 1;\n \t\tbuf->st_mode = fMode;\n \t\tbuf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */\n-\t\tbuf->st_dev = buf->st_rdev = (_getdrive() - 1);\n+\t\tbuf->st_blocks = size_to_blocks(buf->st_size);\n+\t\tbuf->st_dev = _getdrive() - 1;\n \t\tbuf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));\n \t\tbuf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));\n \t\tbuf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 0583a1f..4a53b3b 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -508,8 +508,6 @@ struct itimerval {\n };\n #define ITIMER_REAL 0\n \n-#define st_blocks st_size/512\t/* will be cleaned up later */\n-\n /*\n  * trivial stubs\n  */\n@@ -609,12 +607,22 @@ int mingw_rename(const char*, const char*);\n \n /* Use mingw_lstat() instead of lstat()/stat() and\n  * mingw_fstat() instead of fstat() on Windows.\n+ * struct stat is redefined because it lacks the st_blocks member.\n  */\n-int mingw_lstat(const char *file_name, struct stat *buf);\n-int mingw_fstat(int fd, struct stat *buf);\n+struct mingw_stat {\n+\tunsigned st_mode;\n+\ttime_t st_mtime, st_atime, st_ctime;\n+\tunsigned st_dev, st_ino, st_uid, st_gid;\n+\tsize_t st_size;\n+\tsize_t st_blocks;\n+};\n+int mingw_lstat(const char *file_name, struct mingw_stat *buf);\n+int mingw_fstat(int fd, struct mingw_stat *buf);\n #define fstat mingw_fstat\n #define lstat mingw_lstat\n-#define stat(x,y) mingw_lstat(x,y)\n+#define stat mingw_stat\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_vsnprintf(char *buf, size_t size, const char *fmt, va_list args);\n #define vsnprintf mingw_vsnprintf\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70121","messageId":"1204138503-6126-31-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 30/40] Turn builtin_exec_path into a function.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:53Z","receivedAt":"2008-02-27T18:54:53Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"builtin_exec_path returns the hard-coded installation path, which is used\nas the ultimate fallback to look for git commands. Making it into a function\nenables us in a follow-up patch to return a computed value instead of just\na constant string.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n exec_cmd.c |   10 +++++++---\n 1 files changed, 7 insertions(+), 3 deletions(-)\n\ndiff --git a/exec_cmd.c b/exec_cmd.c\nindex 343545d..3f3fa79 100644\n--- a/exec_cmd.c\n+++ b/exec_cmd.c\n@@ -4,9 +4,13 @@\n #define MAX_ARGS\t32\n \n extern char **environ;\n-static const char *builtin_exec_path = GIT_EXEC_PATH;\n static const char *argv_exec_path;\n \n+static const char *builtin_exec_path(void)\n+{\n+\treturn GIT_EXEC_PATH;\n+}\n+\n void git_set_argv_exec_path(const char *exec_path)\n {\n \targv_exec_path = exec_path;\n@@ -26,7 +30,7 @@ const char *git_exec_path(void)\n \t\treturn env;\n \t}\n \n-\treturn builtin_exec_path;\n+\treturn builtin_exec_path();\n }\n \n static void add_path(struct strbuf *out, const char *path)\n@@ -54,7 +58,7 @@ void setup_path(const char *cmd_path)\n \n \tadd_path(&new_path, argv_exec_path);\n \tadd_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));\n-\tadd_path(&new_path, builtin_exec_path);\n+\tadd_path(&new_path, builtin_exec_path());\n \tadd_path(&new_path, cmd_path);\n \n \tif (old_path)\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70122","messageId":"1204138503-6126-32-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 31/40] Compute the ultimate fallback for exec_path from the program invocation.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:54Z","receivedAt":"2008-02-27T18:54:54Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Since on Windows the user is fairly free where to install programs, we\ncannot rely on a hard-coded path. We use the program name to derive the\ninstallation directory and use that as exec_path.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n exec_cmd.c |   29 +++++++++++++++++++++++++++++\n 1 files changed, 29 insertions(+), 0 deletions(-)\n\ndiff --git a/exec_cmd.c b/exec_cmd.c\nindex 3f3fa79..6d2f740 100644\n--- a/exec_cmd.c\n+++ b/exec_cmd.c\n@@ -8,7 +8,36 @@ static const char *argv_exec_path;\n \n static const char *builtin_exec_path(void)\n {\n+#ifndef __MINGW32__\n \treturn GIT_EXEC_PATH;\n+#else\n+\tint len;\n+\tchar *p, *q, *sl;\n+\tstatic char *ep;\n+\tif (ep)\n+\t\treturn ep;\n+\n+\tlen = strlen(_pgmptr);\n+\tif (len < 2)\n+\t\treturn ep = \".\";\n+\n+\tp = ep = xmalloc(len+1);\n+\tq = _pgmptr;\n+\tsl = NULL;\n+\t/* copy program name, turn '\\\\' into '/', skip last part */\n+\twhile ((*p = *q)) {\n+\t\tif (*q == '\\\\' || *q == '/') {\n+\t\t\t*p = '/';\n+\t\t\tsl = p;\n+\t\t}\n+\t\tp++, q++;\n+\t}\n+\tif (sl)\n+\t\t*sl = '\\0';\n+\telse\n+\t\tep[0] = '.', ep[1] = '\\0';\n+\treturn ep;\n+#endif\n }\n \n void git_set_argv_exec_path(const char *exec_path)\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70127","messageId":"1204138503-6126-33-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 32/40] Windows: Use a relative default template_dir and ETC_GITCONFIG","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:55Z","receivedAt":"2008-02-27T18:54:55Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"With this definition the templates and system config file will be found\nirrespective of the installation location.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n Makefile |    2 ++\n 1 files changed, 2 insertions(+), 0 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 7d4a591..15b13c0 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -548,6 +548,8 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tEXTLIBS += -lws2_32\n \tX = .exe\n \tNOEXECTEMPL = .noexec\n+\ttemplate_dir = ../share/git-core/templates/\n+\tETC_GITCONFIG = ../etc/gitconfig\n endif\n ifneq (,$(findstring arm,$(uname_M)))\n \tARM_SHA1 = YesPlease\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70129","messageId":"1204138503-6126-34-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 33/40] When installing, be prepared that template_dir may be relative.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:56Z","receivedAt":"2008-02-27T18:54:56Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Since the Makefile in the template/ subdirectory is only used to install\nthe templates, we do not simply pass down the setting of template_dir\nwhen it is relative, but construct the intended destination in a new\nvariable: A relative template_dir is relative to gitexecdir.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n Makefile           |    9 ++++++++-\n templates/Makefile |    8 ++++----\n 2 files changed, 12 insertions(+), 5 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 15b13c0..53a4e2a 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -197,7 +197,7 @@ GITWEB_FAVICON = git-favicon.png\n GITWEB_SITE_HEADER =\n GITWEB_SITE_FOOTER =\n \n-export prefix bindir gitexecdir sharedir template_dir htmldir sysconfdir\n+export prefix bindir gitexecdir sharedir htmldir sysconfdir\n \n CC = gcc\n AR = ar\n@@ -1094,6 +1094,13 @@ remove-dashes:\n \n ### Installation rules\n \n+ifeq ($(firstword $(subst /, ,$(template_dir))),..)\n+template_instdir = $(gitexecdir)/$(template_dir)\n+else\n+template_instdir = $template_dir\n+endif\n+export template_instdir\n+\n install: all\n \t$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'\n \t$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexecdir_SQ)'\ndiff --git a/templates/Makefile b/templates/Makefile\nindex b341105..eb08702 100644\n--- a/templates/Makefile\n+++ b/templates/Makefile\n@@ -8,14 +8,14 @@ INSTALL ?= install\n TAR ?= tar\n RM ?= rm -f\n prefix ?= $(HOME)\n-template_dir ?= $(prefix)/share/git-core/templates\n+template_instdir ?= $(prefix)/share/git-core/templates\n # DESTDIR=\n # set NOEXECTEMPL to non-empty to change the names of hook scripts\n # so that the tools will not find them\n \n # Shell quote (do not use $(call) to accommodate ancient setups);\n DESTDIR_SQ = $(subst ','\\'',$(DESTDIR))\n-template_dir_SQ = $(subst ','\\'',$(template_dir))\n+template_instdir_SQ = $(subst ','\\'',$(template_instdir))\n \n all: boilerplates.made custom\n \n@@ -52,6 +52,6 @@ clean:\n \t$(RM) -r blt boilerplates.made\n \n install: all\n-\t$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(template_dir_SQ)'\n+\t$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(template_instdir_SQ)'\n \t(cd blt && $(TAR) cf - .) | \\\n-\t(cd '$(DESTDIR_SQ)$(template_dir_SQ)' && $(TAR) xf -)\n+\t(cd '$(DESTDIR_SQ)$(template_instdir_SQ)' && $(TAR) xf -)\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70120","messageId":"1204138503-6126-35-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 34/40] Windows: Make the pager work.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:57Z","receivedAt":"2008-02-27T18:54:57Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Since we have neither fork() nor exec(), we have to spawn the pager and\nfeed it with the program's output.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n pager.c |   40 ++++++++++++++++++++++++++++++++++++++--\n 1 files changed, 38 insertions(+), 2 deletions(-)\n\ndiff --git a/pager.c b/pager.c\nindex ca002f9..3f7f8c1 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -1,12 +1,13 @@\n #include \"cache.h\"\n \n /*\n- * This is split up from the rest of git so that we might do\n- * something different on Windows, for example.\n+ * This is split up from the rest of git so that we can do\n+ * something different on Windows.\n  */\n \n static int spawned_pager;\n \n+#ifndef __MINGW32__\n static void run_pager(const char *pager)\n {\n \t/*\n@@ -22,11 +23,31 @@ static void run_pager(const char *pager)\n \texeclp(pager, pager, NULL);\n \texecl(\"/bin/sh\", \"sh\", \"-c\", pager, NULL);\n }\n+#else\n+#include \"run-command.h\"\n+\n+static const char *pager_argv[] = { \"sh\", \"-c\", NULL, NULL };\n+static struct child_process pager_process = {\n+\t.argv = pager_argv,\n+\t.in = -1\n+};\n+static void wait_for_pager(void)\n+{\n+\tfflush(stdout);\n+\tfflush(stderr);\n+\t/* signal EOF to pager */\n+\tclose(1);\n+\tclose(2);\n+\tfinish_command(&pager_process);\n+}\n+#endif\n \n void setup_pager(void)\n {\n+#ifndef __MINGW32__\n \tpid_t pid;\n \tint fd[2];\n+#endif\n \tconst char *pager = getenv(\"GIT_PAGER\");\n \n \tif (!isatty(1))\n@@ -45,6 +66,7 @@ void setup_pager(void)\n \n \tspawned_pager = 1; /* means we are emitting to terminal */\n \n+#ifndef __MINGW32__\n \tif (pipe(fd) < 0)\n \t\treturn;\n \tpid = fork();\n@@ -72,6 +94,20 @@ void setup_pager(void)\n \trun_pager(pager);\n \tdie(\"unable to execute pager '%s'\", pager);\n \texit(255);\n+#else\n+\t/* spawn the pager */\n+\tpager_argv[2] = pager;\n+\tif (start_command(&pager_process))\n+\t\treturn;\n+\n+\t/* original process continues, but writes to the pipe */\n+\tdup2(pager_process.in, 1);\n+\tdup2(pager_process.in, 2);\n+\tclose(pager_process.in);\n+\n+\t/* this makes sure that the parent terminates after the pager */\n+\tatexit(wait_for_pager);\n+#endif\n }\n \n int pager_in_use(void)\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70115","messageId":"1204138503-6126-36-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 35/40] Windows: Work around an oddity when a pipe with no reader is written to.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:58Z","receivedAt":"2008-02-27T18:54:58Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Windows, write() is implemented using WriteFile(). After the reader\nclosed its end of the pipe, the first WriteFile() returns\nERROR_BROKEN_PIPE (which translates to EPIPE), subsequent WriteFile()s\nreturn ERROR_NO_DATA, which is translated to EINVAL.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n write_or_die.c |    7 ++++++-\n 1 files changed, 6 insertions(+), 1 deletions(-)\n\ndiff --git a/write_or_die.c b/write_or_die.c\nindex e125e11..f3b8566 100644\n--- a/write_or_die.c\n+++ b/write_or_die.c\n@@ -34,7 +34,12 @@ void maybe_flush_or_die(FILE *f, const char *desc)\n \t\t\treturn;\n \t}\n \tif (fflush(f)) {\n-\t\tif (errno == EPIPE)\n+\t\t/*\n+\t\t * On Windows, EPIPE is returned only by the first write()\n+\t\t * after the reading end has closed its handle; subsequent\n+\t\t * write()s return EINVAL.\n+\t\t */\n+\t\tif (errno == EPIPE || errno == EINVAL)\n \t\t\texit(0);\n \t\tdie(\"write failure on %s: %s\", desc, strerror(errno));\n \t}\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70117","messageId":"1204138503-6126-37-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 36/40] Avoid the \"dup dance\" in wt_status_print_verbose() when possible.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:54:59Z","receivedAt":"2008-02-27T18:54:59Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"If the status output already goes to stdout, then it is not necessary to\nredirect stdout for the diff machinery. (This case hangs on Windows for\nunknown reasons.)\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n wt-status.c |   12 +++++++-----\n 1 files changed, 7 insertions(+), 5 deletions(-)\n\ndiff --git a/wt-status.c b/wt-status.c\nindex 32d780a..e4999ea 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -312,15 +312,17 @@ static void wt_status_print_untracked(struct wt_status *s)\n static void wt_status_print_verbose(struct wt_status *s)\n {\n \tstruct rev_info rev;\n-\tint saved_stdout;\n+\tint saved_stdout = -1;\n \n \tfflush(s->fp);\n \n \t/* Sigh, the entire diff machinery is hardcoded to output to\n \t * stdout.  Do the dup-dance...*/\n-\tsaved_stdout = dup(STDOUT_FILENO);\n-\tif (saved_stdout < 0 ||dup2(fileno(s->fp), STDOUT_FILENO) < 0)\n-\t\tdie(\"couldn't redirect stdout\\n\");\n+\tif (fileno(s->fp) != STDOUT_FILENO) {\n+\t\tsaved_stdout = dup(STDOUT_FILENO);\n+\t\tif (saved_stdout < 0 ||dup2(fileno(s->fp), STDOUT_FILENO) < 0)\n+\t\t\tdie(\"couldn't redirect stdout\\n\");\n+\t}\n \n \tinit_revisions(&rev, NULL);\n \tsetup_revisions(0, NULL, &rev, s->reference);\n@@ -330,7 +332,7 @@ static void wt_status_print_verbose(struct wt_status *s)\n \n \tfflush(stdout);\n \n-\tif (dup2(saved_stdout, STDOUT_FILENO) < 0)\n+\tif (saved_stdout >= 0 && dup2(saved_stdout, STDOUT_FILENO) < 0)\n \t\tdie(\"couldn't restore stdout\\n\");\n \tclose(saved_stdout);\n }\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70112","messageId":"1204138503-6126-38-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 37/40] Windows: Make 'git help -a' work.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:55:00Z","receivedAt":"2008-02-27T18:55:00Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"git help -a scans the PATH for git commands. On Windows it failed for two\nreasons:\n\n- The PATH separator is ';', not ':' on Windows.\n\n- stat() does not set the executabe bit.\n\nWe now open the file and guess whether it is executable.\n\nThe result of the guess is good enough for the list of git commands, but\nit is of no use for a general stat() implementation because (1) it is a\nguess, (2) the user has no way to influence the outcome (via chmod or\nsimilar), and (3) it would reduce stat() performance by an unacceptable\namount. Therefore, this strategy is a special-case local to help.c.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n help.c |   38 +++++++++++++++++++++++++++++++++-----\n 1 files changed, 33 insertions(+), 5 deletions(-)\n\ndiff --git a/help.c b/help.c\nindex 8143dcd..0248c76 100644\n--- a/help.c\n+++ b/help.c\n@@ -163,6 +163,32 @@ static void pretty_print_string_list(struct cmdnames *cmds, int longest)\n \t}\n }\n \n+static int is_executable(const char *name)\n+{\n+\tstruct stat st;\n+\n+\tif (stat(name, &st) || /* stat, not lstat */\n+\t    !S_ISREG(st.st_mode))\n+\t\treturn 0;\n+\n+#ifdef __MINGW32__\n+\t/* cannot trust the executable bit, peek into the file instead */\n+\tchar buf[3] = { 0 };\n+\tint n;\n+\tint fd = open(name, O_RDONLY);\n+\tst.st_mode &= ~S_IXUSR;\n+\tif (fd >= 0) {\n+\t\tn = read(fd, buf, 2);\n+\t\tif (n == 2)\n+\t\t\t/* DOS executables start with \"MZ\" */\n+\t\t\tif (!strcmp(buf, \"#!\") || !strcmp(buf, \"MZ\"))\n+\t\t\t\tst.st_mode |= S_IXUSR;\n+\t\tclose(fd);\n+\t}\n+#endif\n+\treturn st.st_mode & S_IXUSR;\n+}\n+\n static unsigned int list_commands_in_dir(struct cmdnames *cmds,\n \t\t\t\t\t const char *path)\n {\n@@ -176,15 +202,12 @@ static unsigned int list_commands_in_dir(struct cmdnames *cmds,\n \t\treturn 0;\n \n \twhile ((de = readdir(dir)) != NULL) {\n-\t\tstruct stat st;\n \t\tint entlen;\n \n \t\tif (prefixcmp(de->d_name, prefix))\n \t\t\tcontinue;\n \n-\t\tif (stat(de->d_name, &st) || /* stat, not lstat */\n-\t\t    !S_ISREG(st.st_mode) ||\n-\t\t    !(st.st_mode & S_IXUSR))\n+\t\tif (!is_executable(de->d_name))\n \t\t\tcontinue;\n \n \t\tentlen = strlen(de->d_name) - prefix_len;\n@@ -208,6 +231,11 @@ static void list_commands(void)\n \tconst char *env_path = getenv(\"PATH\");\n \tchar *paths, *path, *colon;\n \tconst char *exec_path = git_exec_path();\n+#ifdef __MINGW32__\n+\tchar sep = ';';\n+#else\n+\tchar sep = ':';\n+#endif\n \n \tif (exec_path)\n \t\tlongest = list_commands_in_dir(&main_cmds, exec_path);\n@@ -219,7 +247,7 @@ static void list_commands(void)\n \n \tpath = paths = xstrdup(env_path);\n \twhile (1) {\n-\t\tif ((colon = strchr(path, ':')))\n+\t\tif ((colon = strchr(path, sep)))\n \t\t\t*colon = 0;\n \n \t\tlen = list_commands_in_dir(&other_cmds, path);\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70114","messageId":"1204138503-6126-39-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 38/40] Windows: TMP and TEMP environment variables specify a temporary directory.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:55:01Z","receivedAt":"2008-02-27T18:55:01Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n path.c |    7 +++++++\n 1 files changed, 7 insertions(+), 0 deletions(-)\n\ndiff --git a/path.c b/path.c\nindex 4260952..7f18539 100644\n--- a/path.c\n+++ b/path.c\n@@ -75,6 +75,13 @@ int git_mkstemp(char *path, size_t len, const char *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);\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70140","messageId":"1204138503-6126-40-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 39/40] Windows: Fix ntohl() related warnings about printf formatting","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:55:02Z","receivedAt":"2008-02-27T18:55:02Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"From: Steffen Prohaska <prohaska@zib.de>\n\nFrom: Steffen Prohaska <prohaska@zib.de>\n\nOn Windows, ntohl() returns unsigned long.  On Unix it returns\nuint32_t.  This makes choosing a suitable printf format string\nhard.\n\nThis commit introduces a mingw specific helper function\ngit_ntohl() that casts to unsigned int before returning.  This\nmakes gcc's printf format check happy.  It should be safe because\nwe expect ntohl to use 32-bit numbers.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n git-compat-util.h |    4 ++++\n 1 files changed, 4 insertions(+), 0 deletions(-)\n\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 4a53b3b..5ecdd40 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -631,6 +631,10 @@ 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\n \n+static inline unsigned int git_ntohl(unsigned int x)\n+{ return (unsigned int)ntohl(x); }\n+#define ntohl git_ntohl\n+\n sig_handler_t mingw_signal(int sig, sig_handler_t handler);\n #define signal mingw_signal\n \n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70141","messageId":"1204138503-6126-41-git-send-email-johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"[PATCH 40/40] compat/pread.c: Add foward decl to fix warning","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-27T18:55:03Z","receivedAt":"2008-02-27T18:55:03Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"From: Steffen Prohaska <prohaska@zib.de>\n\nFrom: Steffen Prohaska <prohaska@zib.de>\n\nread_in_full() is used in compat/pread.c.  read_in_full() is\ndeclared in cache.h. But we can't include cache.h because too\nmany macros are defined there.  Using read_in_full() without\nincluding cache.h is dangerous because we wouldn't recognize if\nits prototyp changed.  gcc issues a warning about that.\n\nThis commit adds a forward decl to git-compat-util.h.\ngit-compat-util.h is included by compat/pread.c _and_ cache.h.\nHence, changes in cache.h would be detected.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n git-compat-util.h |    4 ++++\n 1 files changed, 4 insertions(+), 0 deletions(-)\n\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 5ecdd40..4a8df8e 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -168,6 +168,10 @@ extern int git_munmap(void *start, size_t length);\n #define pread git_pread\n extern ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);\n #endif\n+/* Forward decl that will remind us if its twin in cache.h changes.\n+   This function in used in compat/pread.c.  But we can't include\n+   cache.h there. */\n+extern int read_in_full(int fd, void *buf, size_t count);\n \n #ifdef NO_SETENV\n #define setenv gitsetenv\n-- \n1.5.4.1.126.ge5a7d\n"},{"id":"70163","messageId":"47C5DDC0.8060004@trolltech.com","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 00/40] MinGW port","fromName":"Marius Storm-Olsen","fromEmail":"marius@trolltech.com","sentAt":"2008-02-27T22:01:36Z","receivedAt":"2008-02-27T22:01:36Z","isPatch":true,"sender":{"key":"marius@trolltech.com","avatar":"https://gravatar.com/avatar/a40071d8f651862c6ab10bd7996f0ad84d94f06c0399de9e3fa4f06beb390a71?d=mp&s=160"},"body":"Johannes Sixt wrote:\n> So here it is, the MinGW port of git.\n...\n> I've arranged the patches in a few subsets. They are different from\n> what Dscho had proposed some weeks ago when I announced the series\n> for the first time because I felt this topical partitioning makes\n> more sense.\n...\n> * Diffstat excluding 01/40 (which adds 5989 lines)\n...\n> 25 files changed, 1713 insertions(+), 60 deletions(-)\n\nI just have to say, MASSIVE work Hannes! Thank you so much for your \nefforts in making the MinGW port the great port that it is!\n\nYou too Dscho, and the rest of the MSys Git team! ;-)\n\n--\n.marius\n\n"},{"id":"70179","messageId":"46a038f90802271534p37869c58oe79b959b4919c603@mail.gmail.com","threadId":"12344","inReplyTo":"47C5DDC0.8060004@trolltech.com","subject":"Re: [PATCH 00/40] MinGW port","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2008-02-27T23:34:14Z","receivedAt":"2008-02-27T23:34:14Z","isPatch":true,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On Thu, Feb 28, 2008 at 11:01 AM, Marius Storm-Olsen\n<marius@trolltech.com> wrote:\n>  I just have to say, MASSIVE work Hannes! Thank you so much for your\n>  efforts in making the MinGW port the great port that it is!\n>\n>  You too Dscho, and the rest of the MSys Git team! ;-)\n\nIndeed. Amazing stuff. I do some occasional work on Windows, and it is\na sheer pleasure to use msys git. Simple install, it just works, and\nit is fast fast FAST. Hats off!\n\n\n\nm\n"},{"id":"70181","messageId":"alpine.LSU.1.00.0802272342350.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-2-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 01/40] Add compat/regex.[ch] and compat/fnmatch.[ch].","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-27T23:43:08Z","receivedAt":"2008-02-27T23:43:08Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n>  This patch is intentially broken.  There's no need to comment on the\n>  details of the files that it adds.\n\nHeh.\n\nYou mean to say: \"all bugs you find here are _not_ ours!\" ;-)\n\nCiao,\nDscho\n"},{"id":"70183","messageId":"alpine.LSU.1.00.0802272351580.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 00/40] MinGW port","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-27T23:58:30Z","receivedAt":"2008-02-27T23:58:30Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> - perl scripts don't work. We have a hack in the port tree, but I haven't\n>   yet taken the time to clean it up enough.\n\nAFAICT the perl scripts work in msysGit.\n\n> - The test suite does not pass because of missing features like symbolic\n>   links. Again we have adjusted the tests in the port tree so that the\n>   test suite can be completed unattended.\n\nWe have patches in msysGit for that.  Maybe they should come _before_ the \nMinGW series?\n\n> I've arranged the patches in a few subsets. They are different from what \n> Dscho had proposed some weeks ago when I announced the series for the \n> first time because I felt this topical partitioning makes more sense.\n\nFWIW I like your partitioning very much!\n\n> 27/40 Windows: Implement a custom spawnve().\n\nAFAIR this is needed to call git from git-gui, because of that fscked-up \nsemantics of Windows' CreateProcess().\n\nI'll try to review the patches in the next days, but I have no doubt that \nthere is not much to complain about.\n\nThanks, Hannes, for all your valuable and persistent work on mingw.git!\n\nCiao,\nDscho\n"},{"id":"70203","messageId":"fcaeb9bf0802271938n2eeb63f3h3787a0a20f739031@mail.gmail.com","threadId":"12344","inReplyTo":"46a038f90802271534p37869c58oe79b959b4919c603@mail.gmail.com","subject":"Re: [PATCH 00/40] MinGW port","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-28T03:38:50Z","receivedAt":"2008-02-28T03:38:50Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Feb 28, 2008 at 6:34 AM, Martin Langhoff\n<martin.langhoff@gmail.com> wrote:\n> On Thu, Feb 28, 2008 at 11:01 AM, Marius Storm-Olsen\n>  <marius@trolltech.com> wrote:\n>  >  I just have to say, MASSIVE work Hannes! Thank you so much for your\n>  >  efforts in making the MinGW port the great port that it is!\n>  >\n>  >  You too Dscho, and the rest of the MSys Git team! ;-)\n>\n>  Indeed. Amazing stuff. I do some occasional work on Windows, and it is\n>  a sheer pleasure to use msys git. Simple install, it just works, and\n>  it is fast fast FAST. Hats off!\n\nYeah. I've been waiting this moment for too long. Thanks all.\n-- \nDuy\n"},{"id":"70227","messageId":"47C67E1A.5030304@gnu.org","threadId":"12344","inReplyTo":"1204138503-6126-5-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 04/40] Windows: Use the Windows style PATH separator ';'.","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-02-28T09:25:46Z","receivedAt":"2008-02-28T09:25:46Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"\n> +#ifdef __MINGW32__\n> +\t\tstrbuf_addch(out, ';');\n> +#else\n>  \t\tstrbuf_addch(out, ':');\n> +#endif\n\nWhy not adding a PATH_SEPARATOR #define?\n\nPaolo\n"},{"id":"70228","messageId":"47C680A4.6050309@gnu.org","threadId":"12344","inReplyTo":"1204138503-6126-21-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 20/40] Windows: A rudimentary poll() emulation.","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-02-28T09:36:36Z","receivedAt":"2008-02-28T09:36:36Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"Johannes Sixt wrote:\n> This emulation of poll() is by far not general. It assumes that the\n> fds that are to be waited for are connected to pipes. The pipes are\n> polled in a loop until data becomes available in at least one of them.\n> If only a single fd is waited for, the implementation actually does\n> not wait at all, but assumes that a subsequent read() will block.\n\nFor the future, would it be better to first use WaitForMultipleObjects, \nand then use PeekNamedPipe to find which handles have data on it? \nThat's how the mingw port of GNU Smalltalk does it.\n\nPaolo\n"},{"id":"70231","messageId":"47C6839B.6090408@gnu.org","threadId":"12344","inReplyTo":"1204138503-6126-34-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 33/40] When installing, be prepared that template_dir may be relative.","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-02-28T09:49:15Z","receivedAt":"2008-02-28T09:49:15Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"\n> +ifeq ($(firstword $(subst /, ,$(template_dir))),..)\n> +template_instdir = $(gitexecdir)/$(template_dir)\n> +else\n> +template_instdir = $template_dir\n> +endif\n> +export template_instdir\n\nThis is just a little more versatile:\n\nifeq ($(firstword $(subst /,\n,ALONE-IF-ABSOLUTE$(template_dir))),ALONE-IF-ABSOLUTE)\ntemplate_instdir = $template_dir\nelse\ntemplate_instdir = $(gitexecdir)/$(template_dir)\nendif\nexport template_instdir\n\nPaolo\n"},{"id":"70232","messageId":"47C68443.5090409@gnu.org","threadId":"12344","inReplyTo":"1204138503-6126-38-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 37/40] Windows: Make 'git help -a' work.","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-02-28T09:52:03Z","receivedAt":"2008-02-28T09:52:03Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"> +#ifdef __MINGW32__\n> +\tchar sep = ';';\n> +#else\n> +\tchar sep = ':';\n> +#endif\n\nAha! When I replied to patch 4/40 I knew there would be one more. :-)\n\nPaolo\n"},{"id":"70244","messageId":"alpine.LSU.1.00.0802281146050.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-3-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 02/40] Compile some programs only conditionally.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T11:57:44Z","receivedAt":"2008-02-28T11:57:44Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> On MinGW, we won't compile some programs.\n\nThis explanation is good (even if I recall that we compile git-daemon.exe \njust fine now).\n\n> @@ -264,7 +263,7 @@ PROGRAMS = \\\n>  \tgit-update-server-info$X \\\n>  \tgit-upload-pack$X \\\n>  \tgit-pack-redundant$X git-var$X \\\n> -\tgit-merge-tree$X git-imap-send$X \\\n> +\tgit-merge-tree$X \\\n\nWe do not compile git-imap-send because MinGW lacks socketpair() and \ngetpass().  Why not say it explicitely, and have a NO_SOCKETPAIR variable?  \nLikewise, for git-daemon we should say NO_SYSLOG.\n\n> +ifndef NO_EXTRA_PROGRAMS\n\nThe name NO_EXTRA_PROGRAMS is definitely not illustrating the reasons why \nwe exclude those programs, so I'd rather not have this patch as-is.\n\nNOTE: I think that both programs are fixable, but only git-daemon is \nimportant enough that I would like to see patch of the \"daemon\" branch in \n4msysgit.git cherry picked into this series (maybe we should implement a \ncompat/syslog.c using the ReportEvent() function of the win32 API?).\n\nCiao,\nDscho\n"},{"id":"70245","messageId":"alpine.LSU.1.00.0802281159550.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-4-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T12:05:11Z","receivedAt":"2008-02-28T12:05:11Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> +int gettimeofday(struct timeval *tv, void *tz)\n> +{\n> +\treturn 0;\n> +}\n\nShould it not return -1, for failure?  (I know, I know, probably a few \nprograms do not work, then, but it is not correct that it succeeded.)\n\nThe same goes for a few other functions.\n\n> diff --git a/git-compat-util.h b/git-compat-util.h\n> index 2a40703..b1f3f92 100644\n> --- a/git-compat-util.h\n> +++ b/git-compat-util.h\n> @@ -357,6 +359,10 @@ static inline FILE *xfdopen(int fd, const char *mode)\n>  \treturn stream;\n>  }\n>  \n> +#ifdef __MINGW32__\n> +int mkstemp(char *template);\n> +#endif\n> +\n>  static inline int xmkstemp(char *template)\n>  {\n>  \tint fd;\n\nCould we have this...\n\n> @@ -437,4 +443,140 @@ void git_qsort(void *base, size_t nmemb, size_t size,\n>  #define qsort git_qsort\n>  #endif\n>  \n> +#ifdef __MINGW32__\n> +\n> +#include <winsock2.h>\n> +\n> +/*\n> + * things that are not available in header files\n> + */\n> +\n> [...]\n\n... and this in compat/mingw.h?  And then, we'd only have\n\n#ifdef __MINGW32__\n#include \"mingw.h\"\n#endif\n\nin git-compat-util.h?\n\nCiao,\nDscho\n"},{"id":"70246","messageId":"alpine.LSU.1.00.0802281208410.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-9-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 08/40] Windows: always chmod(, 0666) before unlink().","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T12:09:55Z","receivedAt":"2008-02-28T12:09:55Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> From: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n> \n> On Windows, a read-only files cannot be deleted. To make sure that\n> deletion does not fail because of this, always call chmod() before\n> unlink().\n\nMay I request that this embarrassing typo be fixed before applying? (\"a \nread-only files\" -> \"read-only files\".)\n\nThanks,\nDscho\n"},{"id":"70247","messageId":"alpine.LSU.1.00.0802281212140.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-11-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 10/40] Windows: Treat Windows style path names.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T12:18:50Z","receivedAt":"2008-02-28T12:18:50Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> diff --git a/cache.h b/cache.h\n> index e1000bc..3e4e10a 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -441,7 +441,11 @@ int safe_create_leading_directories(char *path);\n>  char *enter_repo(char *path, int strict);\n>  static inline int is_absolute_path(const char *path)\n>  {\n> +#ifndef __MINGW32__\n>  \treturn path[0] == '/';\n> +#else\n> +\treturn path[0] == '/' || (path[0] && path[1] == ':');\n\nMaybe \"(isalpha(path[0]) && ...)\"?\n\nAnd maybe make this an inline function in git-compat-util.h, like this?\n\nstatic inline int has_dos_drive_prefix(const char *path)\n{\n#ifdef __MINGW32__\n\treturn isalpha(*path) && path[1] == ':';\n#else\n\treturn 0;\n#endif\n}\n\n> diff --git a/setup.c b/setup.c\n> index dc247a8..77cc461 100644\n> --- a/setup.c\n> +++ b/setup.c\n> @@ -4,13 +4,26 @@\n>  static int inside_git_dir = -1;\n>  static int inside_work_tree = -1;\n>  \n> +#ifdef __MINGW32__\n> +static inline int is_dir_sep(char c) { return c == '/' || c == '\\\\'; }\n> +#else\n> +static inline int is_dir_sep(char c) { return c == '/'; }\n> +#endif\n\nI think if you rename it to is_dir_separator(), you can put it into \ngit-compat-util.h, right after the PATH_SEPARATOR Paolo suggested.\n\nThanks,\nDscho\n"},{"id":"70248","messageId":"alpine.LSU.1.00.0802281220470.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-14-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 13/40] Windows: Fix PRIuMAX definition.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T12:21:35Z","receivedAt":"2008-02-28T12:21:35Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> diff --git a/git-compat-util.h b/git-compat-util.h\n> index 3b57464..c576f5a 100644\n> --- a/git-compat-util.h\n> +++ b/git-compat-util.h\n> @@ -103,7 +103,11 @@\n>  #endif\n>  \n>  #ifndef PRIuMAX\n> +#ifndef __MINGW32__\n>  #define PRIuMAX \"llu\"\n> +#else\n> +#define PRIuMAX \"I64u\"\n> +#endif\n>  #endif\n\nWould this not be better as a patch to Makefile, extending the \nCOMPAT_CFLAGS with -DPRIuMAX=\\\"I64u\\\"?\n\nCiao,\nDscho\n"},{"id":"70251","messageId":"47C6AFA4.9040304@gnu.org","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281159550.22527@racer.site","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-02-28T12:57:08Z","receivedAt":"2008-02-28T12:57:08Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"Johannes Schindelin wrote:\n> Hi,\n> \n> On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> \n>> +int gettimeofday(struct timeval *tv, void *tz)\n>> +{\n>> +\treturn 0;\n>> +}\n> \n> Should it not return -1, for failure?  (I know, I know, probably a few \n> programs do not work, then, but it is not correct that it succeeded.)\n\nFWIW, this is overwritten by later patches in the series anyway.\n\nAll the other suggestions that Dscho wrote about, make a lot of sense to \nme too.\n\nPaolo\n"},{"id":"70259","messageId":"alpine.LSU.1.00.0802281455440.22527@racer.site","threadId":"12344","inReplyTo":"47C6AFA4.9040304@gnu.org","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T14:56:24Z","receivedAt":"2008-02-28T14:56:24Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Paolo Bonzini wrote:\n\n> Johannes Schindelin wrote:\n> \n> > On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > \n> > > +int gettimeofday(struct timeval *tv, void *tz)\n> > > +{\n> > > +\treturn 0;\n> > > +}\n> > \n> > Should it not return -1, for failure?  (I know, I know, probably a few\n> > programs do not work, then, but it is not correct that it succeeded.)\n> \n> FWIW, this is overwritten by later patches in the series anyway.\n\nYes, I know that.  But the whole point of having a nice patch series is to \nhave proper revisions, and IMO returning 0 here is not correct.\n\nCiao,\nDscho\n"},{"id":"70262","messageId":"alpine.LSU.1.00.0802281519300.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-20-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 19/40] Windows: Change the name of hook scripts to make them not executable.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T15:20:23Z","receivedAt":"2008-02-28T15:20:23Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> -\t\t*) cp $$boilerplate blt/$$dst ;; \\\n> +\t\t*) if test -n \"$$(sed -ne '/^#!\\//p' -e '1q' < \"$$boilerplate\")\"; then \\\n> +\t\t\tcp \"$$boilerplate\" \"blt/$${dst}$(NOEXECTEMPL)\"; \\\n> +\t\t   else \\\n> +\t\t\tcp \"$$boilerplate\" \"blt/$$dst\"; \\\n> +\t\t   fi ;; \\\n\nWhy not just append .noexec to all of the hooks?\n\nCiao,\nDscho\n\n"},{"id":"70264","messageId":"alpine.LSU.1.00.0802281522190.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-22-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 21/40] Windows: Disambiguate DOS style paths from SSH URLs.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T15:22:53Z","receivedAt":"2008-02-28T15:22:53Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> diff --git a/connect.c b/connect.c\n> index 5ac3572..7e18ac8 100644\n> --- a/connect.c\n> +++ b/connect.c\n> @@ -529,7 +529,13 @@ struct child_process *git_connect(int fd[2], const char *url_orig,\n>  \t\tend = host;\n>  \n>  \tpath = strchr(end, c);\n> -\tif (path) {\n> +#ifdef __MINGW32__\n> +\t/* host must have at least 2 chars to catch DOS C:/path */\n> +\tif (path && path - end > 1)\n> +#else\n> +\tif (path)\n> +#endif\n> +\t{\n\nThis could be un-#ifdef'ed by using the has_dos_drive_prefix() function I \nsuggested earlier.\n\nCiao,\nDscho\n\n"},{"id":"70265","messageId":"alpine.LSU.1.00.0802281525510.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-23-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T15:28:34Z","receivedAt":"2008-02-28T15:28:34Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> In upload-pack we must explicitly close the output channel of rev-list. \n> (On Unix, the channel is closed automatically because process that runs \n> rev-list terminates.)\n\nWhen I read this patch, my impression was that it litters the source code \nwith #ifdef's.  IMO this makes the code less readable, and as a \nconsequence easer to fsck up.\n\nUnfortunately, I have no idea how to help that, other than implementing \ncompat/thread.[ch], abstracting the thread functions, and introducing a \nNO_FORK Makefile variable and preprocessor constant.\n\nHmpf.\n\nCiao,\nDscho\n\n"},{"id":"70266","messageId":"alpine.LSU.1.00.0802281530190.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-24-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 23/40] Windows: Local clone must use the drive letter in absolute paths.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T15:31:00Z","receivedAt":"2008-02-28T15:31:00Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> The default of pwd of MSYS's bash and /bin/pwd are to use \n> /c/rest/of/path notation instead of c:/rest/of/path. But the former is \n> not supported by programs that use the standard C runtime (instead of \n> MSYS's runtime). Hence, we must make sure that only drive letter \n> notations are generated by using pwd's -W option.\n\nI guess that this patch will be obsolete when we have builtin clone.  So I \nhave no objection to this pretty local workaround until then.\n\nCiao,\nDscho\n\n"},{"id":"70267","messageId":"alpine.LSU.1.00.0802281535210.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-28-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 27/40] Windows: Implement a custom spawnve().","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T15:36:15Z","receivedAt":"2008-02-28T15:36:15Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> diff --git a/git-compat-util.h b/git-compat-util.h\n> index 0324789..570eb10 100644\n> --- a/git-compat-util.h\n> +++ b/git-compat-util.h\n> @@ -611,6 +611,7 @@ int mingw_rename(const char*, const char*);\n>  int mingw_vsnprintf(char *buf, size_t size, const char *fmt, va_list args);\n>  #define vsnprintf mingw_vsnprintf\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\n>  \n> diff --git a/run-command.c b/run-command.c\n> index 3834f86..5ed338c 100644\n> --- a/run-command.c\n> +++ b/run-command.c\n> @@ -156,7 +156,7 @@ int start_command(struct child_process *cmd)\n>  \t\tcmd->argv[0] = git_cmd.buf;\n>  \t}\n>  \n> -\tcmd->pid = spawnvpe(_P_NOWAIT, cmd->argv[0], cmd->argv, (const char **)env);\n> +\tcmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);\n\nShould this not be \"#define spawnvpe mingw_spanvpe\" in git-compat-util.h \ninstead?\n\nCiao,\nDscho\n\n"},{"id":"70268","messageId":"alpine.LSU.1.00.0802281542000.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-34-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 33/40] When installing, be prepared that template_dir may be relative.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T15:45:22Z","receivedAt":"2008-02-28T15:45:22Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> @@ -1094,6 +1094,13 @@ remove-dashes:\n>  \n>  ### Installation rules\n>  \n> +ifeq ($(firstword $(subst /, ,$(template_dir))),..)\n\nHow portable is \"firstword\"?  Would it not be better to use\n\nifneq ($(patsubst ../%,,$(template_dir)),)\n\nHmm?\n\nCiao,\nDscho\n"},{"id":"70269","messageId":"alpine.LSU.1.00.0802281547560.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-37-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 36/40] Avoid the \"dup dance\" in wt_status_print_verbose() when possible.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T15:48:58Z","receivedAt":"2008-02-28T15:48:58Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> If the status output already goes to stdout, then it is not necessary to \n> redirect stdout for the diff machinery. (This case hangs on Windows for \n> unknown reasons.)\n\nJust in case people like a diff machinery that can output somewhere else \nthan stdout, I have a patch to do that, and also a corresponding patch to \navoid the dup dance.\n\nCiao,\nDscho\n\n"},{"id":"70270","messageId":"alpine.LSU.1.00.0802281551110.22527@racer.site","threadId":"12344","inReplyTo":"1204138503-6126-41-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 40/40] compat/pread.c: Add foward decl to fix warning","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T15:51:34Z","receivedAt":"2008-02-28T15:51:34Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Johannes Sixt wrote:\n\n> +   This function in used in compat/pread.c.  But we can't include\n\ns/ in / is /\n\nThanks,\nDscho\n\n"},{"id":"70273","messageId":"fq6lko$skq$1@ger.gmane.org","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281542000.22527@racer.site","subject":"Re: [PATCH 33/40] When installing, be prepared that template_dir may be relative.","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-02-28T15:57:13Z","receivedAt":"2008-02-28T15:57:13Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"\n>> +ifeq ($(firstword $(subst /, ,$(template_dir))),..)\n> \n> How portable is \"firstword\"?  Would it not be better to use\n\nAt least make 3.78.1 (1999), search func_firstword in \nhttp://snipurl.com/20lle (Google Code Search).\n\nPaolo\n\n"},{"id":"70285","messageId":"47C6F40A.4010703@comcast.net","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281525510.22527@racer.site","subject":"Re: [PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Paul Franz","fromEmail":"thefranz@comcast.net","sentAt":"2008-02-28T17:48:58Z","receivedAt":"2008-02-28T17:48:58Z","isPatch":true,"sender":{"key":"thefranz@comcast.net","avatar":null},"body":"This reminds me of a crazy idea and I know it would be quite a bit of \nwork. Do you think it would be possible to change git to use Apache's \napr library? The benefit would be that the cross platform stuff is \nalready written. I understand that it would not be tweaked to be \noptimized for git's usage. But it would allow people to focus on the \nheart of the git and not the way git interacts with the OS level stuff.  \nObviously, the scripts that make up part of git are not as portable but \nthat is a different animal unless you want to either support a cross \nplatform scripting language as part of git.\n\nAs I said it is a crazy idea.\n\nPaul Franz\n\nJohannes Schindelin wrote:\n> Hi,\n>\n> On Wed, 27 Feb 2008, Johannes Sixt wrote:\n>\n>   \n>> In upload-pack we must explicitly close the output channel of rev-list. \n>> (On Unix, the channel is closed automatically because process that runs \n>> rev-list terminates.)\n>>     \n>\n> When I read this patch, my impression was that it litters the source code \n> with #ifdef's.  IMO this makes the code less readable, and as a \n> consequence easer to fsck up.\n>\n> Unfortunately, I have no idea how to help that, other than implementing \n> compat/thread.[ch], abstracting the thread functions, and introducing a \n> NO_FORK Makefile variable and preprocessor constant.\n>\n> Hmpf.\n>\n> Ciao,\n> Dscho\n>\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n>\n>   \n\n-- \n\n-------------------------------------------\n\nThere are seven sins in the world.\n     Wealth without work.\n     Pleasure without conscience.\n     Knowledge without character.\n     Commerce without morality.\n     Science without humanity.\n     Worship without sacrifice.\n     Politics without principle.\n\n   -- Mohandas Gandhi\n\n-------------------------------------------\n\n"},{"id":"70287","messageId":"7vhcftj75f.fsf@gitster.siamese.dyndns.org","threadId":"12344","inReplyTo":"1204138503-6126-5-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 04/40] Windows: Use the Windows style PATH separator ';'.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-28T17:57:32Z","receivedAt":"2008-02-28T17:57:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <johannes.sixt@telecom.at> writes:\n\n> diff --git a/exec_cmd.c b/exec_cmd.c\n> index e189cac..343545d 100644\n> --- a/exec_cmd.c\n> +++ b/exec_cmd.c\n> @@ -37,7 +37,11 @@ static void add_path(struct strbuf *out, const char *path)\n>  \t\telse\n>  \t\t\tstrbuf_addstr(out, make_absolute_path(path));\n>  \n> +#ifdef __MINGW32__\n> +\t\tstrbuf_addch(out, ';');\n> +#else\n>  \t\tstrbuf_addch(out, ':');\n> +#endif\n>  \t}\n>  }\n\nIf it were only these two places it might be Ok, but together\nwith 10/40 you may want to do\n\n        #if WINDOWS\n        #define PATH_SEP ';'\n        #else\n        #define PATH_SEP ':'\n        #endif\n\nin a header so that the C files do not have to suffer.\n\n"},{"id":"70299","messageId":"200802282130.10225.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281146050.22527@racer.site","subject":"Re: [PATCH 02/40] Compile some programs only conditionally.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-28T20:30:10Z","receivedAt":"2008-02-28T20:30:10Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Thursday 28 February 2008 12:57, Johannes Schindelin wrote:\n> Hi,\n>\n> On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > On MinGW, we won't compile some programs.\n>\n> This explanation is good (even if I recall that we compile git-daemon.exe\n> just fine now).\n>\n> > @@ -264,7 +263,7 @@ PROGRAMS = \\\n> >  \tgit-update-server-info$X \\\n> >  \tgit-upload-pack$X \\\n> >  \tgit-pack-redundant$X git-var$X \\\n> > -\tgit-merge-tree$X git-imap-send$X \\\n> > +\tgit-merge-tree$X \\\n>\n> We do not compile git-imap-send because MinGW lacks socketpair() and\n> getpass().  Why not say it explicitely, and have a NO_SOCKETPAIR variable?\n> Likewise, for git-daemon we should say NO_SYSLOG.\n\nWhere are NO_WNOHANG, NO_GETPASS, NO_SELECT, NO_SIGCHLD, NO_EXECVE etc in your \nlist? A condition on MINGW32 is certainly sufficient.\n\n> > +ifndef NO_EXTRA_PROGRAMS\n>\n> The name NO_EXTRA_PROGRAMS is definitely not illustrating the reasons why\n> we exclude those programs, so I'd rather not have this patch as-is.\n\nI agree.\n\n> NOTE: I think that both programs are fixable, but only git-daemon is\n> important enough that I would like to see patch of the \"daemon\" branch in\n> 4msysgit.git cherry picked into this series (maybe we should implement a\n> compat/syslog.c using the ReportEvent() function of the win32 API?).\n\nopenlog() etc. is only one problem in git-daemon. It also depends on SIGCHLD, \na non-blocking waitpid, and a lot more. The patch that is in 4msysgit.git \nallows only a single connection, IIRC, after which it terminates. But I also \nthink that git-daemon can be made more complete on Windows, but it certainly \nrequires a major surgery.\n\n-- Hannes\n"},{"id":"70303","messageId":"200802282140.30654.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281159550.22527@racer.site","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-28T20:40:30Z","receivedAt":"2008-02-28T20:40:30Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Thursday 28 February 2008 13:05, Johannes Schindelin wrote:\n> Hi,\n>\n> On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > +int gettimeofday(struct timeval *tv, void *tz)\n> > +{\n> > +\treturn 0;\n> > +}\n>\n> Should it not return -1, for failure?  (I know, I know, probably a few\n> programs do not work, then, but it is not correct that it succeeded.)\n>\n> The same goes for a few other functions.\n\nAgreed. The return value of these functions should not make a difference at \nthis stage in the patch series anyway.\n\n> > +#ifdef __MINGW32__\n> > +int mkstemp(char *template);\n> > +#endif\n> > +\n> >  static inline int xmkstemp(char *template)\n> >  {\n> >  \tint fd;\n>\n> Could we have this...\n\nNo, becauser xmkstemp needs the forward declaration of mkstemp(). But we could \nmake it unconditional.\n\n> ... and this in compat/mingw.h?  And then, we'd only have\n>\n> #ifdef __MINGW32__\n> #include \"mingw.h\"\n> #endif\n>\n> in git-compat-util.h?\n\nI thought about this, but I decided against it:  git-compat-util.h is the \nplace to look for compatibility functions. A file compat/mingw.h only \nintroduces an extra indirection and only *hides* stuff instead of making it \nobvious.\n\n-- Hannes\n"},{"id":"70304","messageId":"200802282143.19322.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"47C67E1A.5030304@gnu.org","subject":"Re: [PATCH 04/40] Windows: Use the Windows style PATH separator ';'.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-28T20:43:19Z","receivedAt":"2008-02-28T20:43:19Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Thursday 28 February 2008 10:25, Paolo Bonzini wrote:\n> > +#ifdef __MINGW32__\n> > +\t\tstrbuf_addch(out, ';');\n> > +#else\n> >  \t\tstrbuf_addch(out, ':');\n> > +#endif\n>\n> Why not adding a PATH_SEPARATOR #define?\n\nBecause IMO it is obfuscating:\n\n1. When you read through the code and see PATH_SEPARATOR, you still have\nto go look how it's defined. Why? Because you always will ask: Is this \nabout ':' vs. ';' or '/' vs. '\\\\'?\n\n2. When you look for where \":\" or \";\" are treated, you'll end up at the\n#define. Then you need an extra step to search for PATH_SEPARATOR.\n\n-- Hannes\n"},{"id":"70305","messageId":"200802282145.08883.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281220470.22527@racer.site","subject":"Re: [PATCH 13/40] Windows: Fix PRIuMAX definition.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-28T20:45:08Z","receivedAt":"2008-02-28T20:45:08Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Thursday 28 February 2008 13:21, Johannes Schindelin wrote:\n> On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> >  #ifndef PRIuMAX\n> > +#ifndef __MINGW32__\n> >  #define PRIuMAX \"llu\"\n> > +#else\n> > +#define PRIuMAX \"I64u\"\n> > +#endif\n> >  #endif\n>\n> Would this not be better as a patch to Makefile, extending the\n> COMPAT_CFLAGS with -DPRIuMAX=\\\"I64u\\\"?\n\nMe likes this!\n\n-- Hannes\n"},{"id":"70307","messageId":"200802282148.47485.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281519300.22527@racer.site","subject":"Re: [PATCH 19/40] Windows: Change the name of hook scripts to make them not executable.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-28T20:48:47Z","receivedAt":"2008-02-28T20:48:47Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Thursday 28 February 2008 16:20, Johannes Schindelin wrote:\n> On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > -\t\t*) cp $$boilerplate blt/$$dst ;; \\\n> > +\t\t*) if test -n \"$$(sed -ne '/^#!\\//p' -e '1q' < \"$$boilerplate\")\"; then\n> > \\ +\t\t\tcp \"$$boilerplate\" \"blt/$${dst}$(NOEXECTEMPL)\"; \\\n> > +\t\t   else \\\n> > +\t\t\tcp \"$$boilerplate\" \"blt/$$dst\"; \\\n> > +\t\t   fi ;; \\\n>\n> Why not just append .noexec to all of the hooks?\n\nBecause some of the files are not hooks. Or do you mean to check for the files \nhooks--* explicitly?\n\n-- Hannes\n"},{"id":"70308","messageId":"200802282149.36748.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"47C680A4.6050309@gnu.org","subject":"Re: [PATCH 20/40] Windows: A rudimentary poll() emulation.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-28T20:49:36Z","receivedAt":"2008-02-28T20:49:36Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Thursday 28 February 2008 10:36, Paolo Bonzini wrote:\n> Johannes Sixt wrote:\n> > This emulation of poll() is by far not general. It assumes that the\n> > fds that are to be waited for are connected to pipes. The pipes are\n> > polled in a loop until data becomes available in at least one of them.\n> > If only a single fd is waited for, the implementation actually does\n> > not wait at all, but assumes that a subsequent read() will block.\n>\n> For the future, would it be better to first use WaitForMultipleObjects,\n> and then use PeekNamedPipe to find which handles have data on it?\n> That's how the mingw port of GNU Smalltalk does it.\n\nI tried but I failed. If you can show me code where WaitForMultipleObjects\nworks on handles that MSVCRT.DLL's open() created, I'll gladly accept it!\n\n-- Hannes\n"},{"id":"70309","messageId":"200802282151.29272.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281522190.22527@racer.site","subject":"Re: [PATCH 21/40] Windows: Disambiguate DOS style paths from SSH URLs.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-28T20:51:29Z","receivedAt":"2008-02-28T20:51:29Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Thursday 28 February 2008 16:22, Johannes Schindelin wrote:\n> On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > +#ifdef __MINGW32__\n> > +\t/* host must have at least 2 chars to catch DOS C:/path */\n> > +\tif (path && path - end > 1)\n> > +#else\n> > +\tif (path)\n> > +#endif\n> > +\t{\n>\n> This could be un-#ifdef'ed by using the has_dos_drive_prefix() function I\n> suggested earlier.\n\nAh, great! I'm convinced.\n\n-- Hannes\n"},{"id":"70313","messageId":"200802282201.06802.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281525510.22527@racer.site","subject":"Re: [PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-28T21:01:06Z","receivedAt":"2008-02-28T21:01:06Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Thursday 28 February 2008 16:28, Johannes Schindelin wrote:\n> Hi,\n>\n> On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > In upload-pack we must explicitly close the output channel of rev-list.\n> > (On Unix, the channel is closed automatically because process that runs\n> > rev-list terminates.)\n>\n> When I read this patch, my impression was that it litters the source code\n> with #ifdef's.  IMO this makes the code less readable, and as a\n> consequence easer to fsck up.\n>\n> Unfortunately, I have no idea how to help that, other than implementing\n> compat/thread.[ch], abstracting the thread functions, and introducing a\n> NO_FORK Makefile variable and preprocessor constant.\n>\n> Hmpf.\n\nThe number of #ifdef/#endif is already at a minimum unless you are willing to \nhave entire functions in separate #ifdef/#else/#endif branches. Whether to \nhave compat/thread.[ch] or not is just a question of whether you want to have \nasynchronous functions in threads also on Unix or not.\n\n-- Hannes\n"},{"id":"70314","messageId":"200802282204.20168.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281535210.22527@racer.site","subject":"Re: [PATCH 27/40] Windows: Implement a custom spawnve().","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-28T21:04:20Z","receivedAt":"2008-02-28T21:04:20Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Thursday 28 February 2008 16:36, Johannes Schindelin wrote:\n> On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > -\tcmd->pid = spawnvpe(_P_NOWAIT, cmd->argv[0], cmd->argv, (const \nchar**)env); \n> > +\tcmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);\n>\n> Should this not be \"#define spawnvpe mingw_spanvpe\" in git-compat-util.h\n> instead?\n\nNo. We don't mimic the API of the original spawnvpe. Why obfuscate this fact?\n\n-- Hannes\n"},{"id":"70315","messageId":"200802282212.02683.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281542000.22527@racer.site","subject":"Re: [PATCH 33/40] When installing, be prepared that template_dir may be relative.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-28T21:12:02Z","receivedAt":"2008-02-28T21:12:02Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Thursday 28 February 2008 16:45, Johannes Schindelin wrote:\n> Hi,\n>\n> On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > @@ -1094,6 +1094,13 @@ remove-dashes:\n> >\n> >  ### Installation rules\n> >\n> > +ifeq ($(firstword $(subst /, ,$(template_dir))),..)\n>\n> How portable is \"firstword\"?  Would it not be better to use\n\nHow portable is \"patsubst\"? ;)\n\n> ifneq ($(patsubst ../%,,$(template_dir)),)\n\nThis programming language is sort of write-only, so I don't know because I \ncan't read it ;) If you have tested your version and it works and you have \nthought through all consequences (like how does it work if \ntemplate_dir=/a/../b), why not?\n\n-- Hannes\n"},{"id":"70333","messageId":"alpine.LSU.1.00.0802290046180.22527@racer.site","threadId":"12344","inReplyTo":"200802282130.10225.johannes.sixt@telecom.at","subject":"Re: [PATCH 02/40] Compile some programs only conditionally.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T00:47:39Z","receivedAt":"2008-02-29T00:47:39Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Johannes Sixt wrote:\n\n> On Thursday 28 February 2008 12:57, Johannes Schindelin wrote:\n>\n> > On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > > On MinGW, we won't compile some programs.\n> >\n> > This explanation is good (even if I recall that we compile \n> > git-daemon.exe just fine now).\n> >\n> > > @@ -264,7 +263,7 @@ PROGRAMS = \\\n> > >  \tgit-update-server-info$X \\\n> > >  \tgit-upload-pack$X \\\n> > >  \tgit-pack-redundant$X git-var$X \\\n> > > -\tgit-merge-tree$X git-imap-send$X \\\n> > > +\tgit-merge-tree$X \\\n> >\n> > We do not compile git-imap-send because MinGW lacks socketpair() and \n> > getpass().  Why not say it explicitely, and have a NO_SOCKETPAIR \n> > variable? Likewise, for git-daemon we should say NO_SYSLOG.\n> \n> Where are NO_WNOHANG, NO_GETPASS, NO_SELECT, NO_SIGCHLD, NO_EXECVE etc \n> in your list? A condition on MINGW32 is certainly sufficient.\n\nJust pick the most difficult one.  But just saying \"this does not work on \nMinGW32\" does not help people who want to help.\n\n> > NOTE: I think that both programs are fixable, but only git-daemon is \n> > important enough that I would like to see patch of the \"daemon\" branch \n> > in 4msysgit.git cherry picked into this series (maybe we should \n> > implement a compat/syslog.c using the ReportEvent() function of the \n> > win32 API?).\n> \n> openlog() etc. is only one problem in git-daemon. It also depends on \n> SIGCHLD, a non-blocking waitpid, and a lot more. The patch that is in \n> 4msysgit.git allows only a single connection, IIRC, after which it \n> terminates. But I also think that git-daemon can be made more complete \n> on Windows, but it certainly requires a major surgery.\n\nOkay, I did not look closely enough.  But even a single-connection daemon \nis better than no daemon, no?\n\nCiao,\nDscho\n\n"},{"id":"70335","messageId":"alpine.LSU.1.00.0802290105150.22527@racer.site","threadId":"12344","inReplyTo":"200802282140.30654.johannes.sixt@telecom.at","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:07:37Z","receivedAt":"2008-02-29T01:07:37Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Johannes Sixt wrote:\n\n> On Thursday 28 February 2008 13:05, Johannes Schindelin wrote:\n> >\n> > On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > \n> > > +#ifdef __MINGW32__\n> > > +int mkstemp(char *template);\n> > > +#endif\n> > > +\n> > >  static inline int xmkstemp(char *template)\n> > >  {\n> > >  \tint fd;\n> >\n> > Could we have this...\n> \n> No, becauser xmkstemp needs the forward declaration of mkstemp(). But we \n> could make it unconditional.\n\nActually, I was thinking of including it at the same spot where you \ndeclare mkstemp conditionally.  (Of course, since I spotted very well that \nyou need that declaration for xmkstemp().)\n\n> I thought about this, but I decided against it:  git-compat-util.h is \n> the place to look for compatibility functions. A file compat/mingw.h \n> only introduces an extra indirection and only *hides* stuff instead of \n> making it obvious.\n\nWell, the thing is, there are quite a few definitions and declarations \nthat are _only_ _ever_ interesting if you are on MinGW32.\n\nSo maybe it is a good idea to hide it to all the other users.\n\nCiao,\nDscho\n\n"},{"id":"70336","messageId":"alpine.LSU.1.00.0802290108530.22527@racer.site","threadId":"12344","inReplyTo":"200802282143.19322.johannes.sixt@telecom.at","subject":"Re: [PATCH 04/40] Windows: Use the Windows style PATH separator ';'.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:09:35Z","receivedAt":"2008-02-29T01:09:35Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Johannes Sixt wrote:\n\n> On Thursday 28 February 2008 10:25, Paolo Bonzini wrote:\n> > > +#ifdef __MINGW32__\n> > > +\t\tstrbuf_addch(out, ';');\n> > > +#else\n> > >  \t\tstrbuf_addch(out, ':');\n> > > +#endif\n> >\n> > Why not adding a PATH_SEPARATOR #define?\n> \n> Because IMO it is obfuscating:\n> \n> 1. When you read through the code and see PATH_SEPARATOR, you still have\n> to go look how it's defined. Why? Because you always will ask: Is this \n> about ':' vs. ';' or '/' vs. '\\\\'?\n> \n> 2. When you look for where \":\" or \";\" are treated, you'll end up at the\n> #define. Then you need an extra step to search for PATH_SEPARATOR.\n\nIMO these are not good arguments.  If they were, we could not typedef \nsize_t and socklen_t, either.\n\nCiao,\nDscho\n\n"},{"id":"70337","messageId":"alpine.LSU.1.00.0802290110320.22527@racer.site","threadId":"12344","inReplyTo":"200802282148.47485.johannes.sixt@telecom.at","subject":"Re: [PATCH 19/40] Windows: Change the name of hook scripts to make them not executable.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:11:03Z","receivedAt":"2008-02-29T01:11:03Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Johannes Sixt wrote:\n\n> On Thursday 28 February 2008 16:20, Johannes Schindelin wrote:\n> > On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > > -\t\t*) cp $$boilerplate blt/$$dst ;; \\\n> > > +\t\t*) if test -n \"$$(sed -ne '/^#!\\//p' -e '1q' < \"$$boilerplate\")\"; then\n> > > \\ +\t\t\tcp \"$$boilerplate\" \"blt/$${dst}$(NOEXECTEMPL)\"; \\\n> > > +\t\t   else \\\n> > > +\t\t\tcp \"$$boilerplate\" \"blt/$$dst\"; \\\n> > > +\t\t   fi ;; \\\n> >\n> > Why not just append .noexec to all of the hooks?\n> \n> Because some of the files are not hooks.\n\nThen you have to make sure even more urgently that only the hooks are \ntreated that way.\n\nCiao,\nDscho\n\n"},{"id":"70338","messageId":"alpine.LSU.1.00.0802290112340.22527@racer.site","threadId":"12344","inReplyTo":"200802282201.06802.johannes.sixt@telecom.at","subject":"Re: [PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:17:39Z","receivedAt":"2008-02-29T01:17:39Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Johannes Sixt wrote:\n\n> On Thursday 28 February 2008 16:28, Johannes Schindelin wrote:\n>\n> > On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > > In upload-pack we must explicitly close the output channel of \n> > > rev-list. (On Unix, the channel is closed automatically because \n> > > process that runs rev-list terminates.)\n> >\n> > When I read this patch, my impression was that it litters the source \n> > code with #ifdef's.  IMO this makes the code less readable, and as a \n> > consequence easer to fsck up.\n> >\n> > Unfortunately, I have no idea how to help that, other than \n> > implementing compat/thread.[ch], abstracting the thread functions, and \n> > introducing a NO_FORK Makefile variable and preprocessor constant.\n> >\n> > Hmpf.\n> \n> The number of #ifdef/#endif is already at a minimum unless you are \n> willing to have entire functions in separate #ifdef/#else/#endif \n> branches. Whether to have compat/thread.[ch] or not is just a question \n> of whether you want to have asynchronous functions in threads also on \n> Unix or not.\n\nWell, my idea was that Git's code looks as good as it does now not only \nbecause the functions are well written, but because the \nconditionally-compiled code is not classified by _platform_ but by \n_reason_.\n\nFor example, we do not write that on FreeBSD, we do this and that, but \nwe define for FreeBSD that there is no strlcpy(), and if NO_STRLCPY is \ndefined, we implement it.\n\nLikewise, I would prefer to have it in the code here _not_ that we do this \nand that on MinGW32, but that in the absence of a usable fork(), we \nrequire certain functions (declared in compat/thread.h, for example), and \nuse them.\n\nBut I know this is a lot of work, so I hoped for a better solution, that \nstill excites my \"elegance neuron\".\n\nCiao,\nDscho\n\n"},{"id":"70339","messageId":"alpine.LSU.1.00.0802290117540.22527@racer.site","threadId":"12344","inReplyTo":"200802282204.20168.johannes.sixt@telecom.at","subject":"Re: [PATCH 27/40] Windows: Implement a custom spawnve().","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:18:45Z","receivedAt":"2008-02-29T01:18:45Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Johannes Sixt wrote:\n\n> On Thursday 28 February 2008 16:36, Johannes Schindelin wrote:\n> > On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > > -\tcmd->pid = spawnvpe(_P_NOWAIT, cmd->argv[0], cmd->argv, (const \n> char**)env); \n> > > +\tcmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);\n> >\n> > Should this not be \"#define spawnvpe mingw_spanvpe\" in git-compat-util.h\n> > instead?\n> \n> No. We don't mimic the API of the original spawnvpe. Why obfuscate this fact?\n\nOops.  I forgot that.  Maybe we do not want to call the function \nmingw_spawnvpe(), then?  (That fact is what made me believe that the \n#define was a good idea, after all.)\n\nCiao,\nDscho\n\n"},{"id":"70340","messageId":"alpine.LSU.1.00.0802290119340.22527@racer.site","threadId":"12344","inReplyTo":"200802282212.02683.johannes.sixt@telecom.at","subject":"Re: [PATCH 33/40] When installing, be prepared that template_dir may be relative.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:21:17Z","receivedAt":"2008-02-29T01:21:17Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Johannes Sixt wrote:\n\n> On Thursday 28 February 2008 16:45, Johannes Schindelin wrote:\n>\n> > On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > > @@ -1094,6 +1094,13 @@ remove-dashes:\n> > >\n> > >  ### Installation rules\n> > >\n> > > +ifeq ($(firstword $(subst /, ,$(template_dir))),..)\n> >\n> > How portable is \"firstword\"?  Would it not be better to use\n> \n> How portable is \"patsubst\"? ;)\n> \n> > ifneq ($(patsubst ../%,,$(template_dir)),)\n> \n> This programming language is sort of write-only, so I don't know because \n> I can't read it ;) If you have tested your version and it works and you \n> have thought through all consequences (like how does it work if \n> template_dir=/a/../b), why not?\n\nI did not think through all consequences, but hoped that some knowledgable \nperson could tell me that/if I am wrong in my assumption that patsubst is \nolder than firstword.\n\nSince I encountered \"firstword\" for the very first time today, I thought \nit might be younger than \"patsubst\", which I met plenty a times.\n\nCiao,\nDscho\n\n"},{"id":"70341","messageId":"alpine.LSU.1.00.0802290122110.22527@racer.site","threadId":"12344","inReplyTo":"47C6F40A.4010703@comcast.net","subject":"Re: [PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:27:25Z","receivedAt":"2008-02-29T01:27:25Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Paul Franz wrote:\n\n> Do you think it would be possible to change git to use Apache's apr \n> library?\n\nPossible?  Yes.\n\nSensible?  That's another issue.  For one, we already rely on a pretty \ngood POSIX shell support.  That is not something helped by APR.\n\nSo if we already need a POSIX shell, we might just as well rely on a \n(kind of) POSIX environment.\n\nBesides, I cannot say that I found compiling APR in msysGit _easy_.\n\nSo if there are as many disadvantages as I suspect, and as few advantages, \nas I suspect, too, I think it would be a waste of time to bother to port \nGit to APR.\n\nBesides, I think there are -- again, as always when things seem to be only \nfun -- legal issues.  I do not know the details, but there are people who \nsay that APL is incompatible with GPL (v2).\n\nNot that I care too much about those bastards who devised licenses just to \nmake my life miserable.  But them lawyer types have ways to _make_ my \nlife miserable.  So I avoid those kind of problems.  I guess you could \ncall this \"collateral legal damage\".\n\nCiao,\nDscho\n\n"},{"id":"70348","messageId":"47C76407.3090804@comcast.net","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802290122110.22527@racer.site","subject":"Re: [PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Paul Franz","fromEmail":"thefranz@comcast.net","sentAt":"2008-02-29T01:46:47Z","receivedAt":"2008-02-29T01:46:47Z","isPatch":true,"sender":{"key":"thefranz@comcast.net","avatar":null},"body":"True there are the legal issues. And it is not known if it would help on \nother platforms. My may concern is Windows because if git could be made \navailable without some of msysGit's requirements. It would definitely \nmake it more palletable (sp?) to that community which is a large chunk \nof developers, including my own work environment. I would love to switch \nfrom ClearCase to git but there are issues. One of them is integration \nwith the Windows environment.\n\nAnother concern is performance penalty of using non-native calls under \nWindows and that is one of the problems that I was hoping the using APR \nwould solve. I figure if it is good enough to support the network stuff \nunder Windows well maybe it would be good for git too.\n\nPaul Franz\n\nJohannes Schindelin wrote:\n> Hi,\n>\n> On Thu, 28 Feb 2008, Paul Franz wrote:\n>\n>   \n>> Do you think it would be possible to change git to use Apache's apr \n>> library?\n>>     \n>\n> Possible?  Yes.\n>\n> Sensible?  That's another issue.  For one, we already rely on a pretty \n> good POSIX shell support.  That is not something helped by APR.\n>\n> So if we already need a POSIX shell, we might just as well rely on a \n> (kind of) POSIX environment.\n>\n> Besides, I cannot say that I found compiling APR in msysGit _easy_.\n>\n> So if there are as many disadvantages as I suspect, and as few advantages, \n> as I suspect, too, I think it would be a waste of time to bother to port \n> Git to APR.\n>\n> Besides, I think there are -- again, as always when things seem to be only \n> fun -- legal issues.  I do not know the details, but there are people who \n> say that APL is incompatible with GPL (v2).\n>\n> Not that I care too much about those bastards who devised licenses just to \n> make my life miserable.  But them lawyer types have ways to _make_ my \n> life miserable.  So I avoid those kind of problems.  I guess you could \n> call this \"collateral legal damage\".\n>\n> Ciao,\n> Dscho\n>\n>\n>   \n\n-- \n\n-------------------------------------------\n\nThere are seven sins in the world.\n     Wealth without work.\n     Pleasure without conscience.\n     Knowledge without character.\n     Commerce without morality.\n     Science without humanity.\n     Worship without sacrifice.\n     Politics without principle.\n\n   -- Mohandas Gandhi\n\n-------------------------------------------\n\n"},{"id":"70349","messageId":"alpine.LSU.1.00.0802290150440.22527@racer.site","threadId":"12344","inReplyTo":"47C76407.3090804@comcast.net","subject":"Re: [PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:54:41Z","receivedAt":"2008-02-29T01:54:41Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\n[top-posting?]\n\nOn Thu, 28 Feb 2008, Paul Franz wrote:\n\n> True there are the legal issues. And it is not known if it would help on \n> other platforms. My may concern is Windows because if git could be made \n> available without some of msysGit's requirements. It would definitely \n> make it more palletable (sp?) to that community which is a large chunk \n> of developers, including my own work environment. I would love to switch \n> from ClearCase to git but there are issues. One of them is integration \n> with the Windows environment.\n\nI think that you do not help the effort to bring Git to Windows, by \nsuggesting even more work, for dubitable benefits.\n\nAnd that is what I think of APR here.\n\nNOTE: my only experience with APR on Windows is to get git-svn to compile, \nand there it was not only a PITA.  The result is _SLOW_.\n\n> Another concern is performance penalty of using non-native calls under \n> Windows and that is one of the problems that I was hoping the using APR \n> would solve. I figure if it is good enough to support the network stuff \n> under Windows well maybe it would be good for git too.\n\nThe problems with Git and Windows are not network related.  They are with \nWindows' pitiful performance when it comes to spawn processes.\n\nIMO your efforts to help Git on Windows would be better spent on the \nmsysGit list, where you would learn about the real issues we face.\n\nCiao,\nDscho\n\n"},{"id":"70360","messageId":"47C77720.2080405@comcast.net","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802290150440.22527@racer.site","subject":"Re: [PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Paul Franz","fromEmail":"thefranz@comcast.net","sentAt":"2008-02-29T03:08:16Z","receivedAt":"2008-02-29T03:08:16Z","isPatch":true,"sender":{"key":"thefranz@comcast.net","avatar":null},"body":"\n\nJohannes Schindelin wrote:\n> Hi,\n>\n> [top-posting?]\n>   \n\nIs there something wrong with it?\n> On Thu, 28 Feb 2008, Paul Franz wrote:\n>\n>   \n>> True there are the legal issues. And it is not known if it would help on \n>> other platforms. My may concern is Windows because if git could be made \n>> available without some of msysGit's requirements. It would definitely \n>> make it more palletable (sp?) to that community which is a large chunk \n>> of developers, including my own work environment. I would love to switch \n>> from ClearCase to git but there are issues. One of them is integration \n>> with the Windows environment.\n>>     \n>\n> I think that you do not help the effort to bring Git to Windows, by \n> suggesting even more work, for dubitable benefits.\n>\n> And that is what I think of APR here.\n>\n> NOTE: my only experience with APR on Windows is to get git-svn to compile, \n> and there it was not only a PITA.  The result is _SLOW_.\n>   \n\nThanks for the info.\n>   \n>> Another concern is performance penalty of using non-native calls under \n>> Windows and that is one of the problems that I was hoping the using APR \n>> would solve. I figure if it is good enough to support the network stuff \n>> under Windows well maybe it would be good for git too.\n>>     \n>\n> The problems with Git and Windows are not network related.  They are with \n> Windows' pitiful performance when it comes to spawn processes.\n>   \nWhich makes me believe that it sounds like git depends on spawning \nprocesses being cheap.\n> IMO your efforts to help Git on Windows would be better spent on the \n> msysGit list, where you would learn about the real issues we face.\n>   \n\nExcuse my ignorance,  could you tell me where the mysGit list is, so \nthat I can subscribe?\n\n> Ciao,\n> Dscho\n>\n>\n>   \n-- \n\n-------------------------------------------\n\nThere are seven sins in the world.\n     Wealth without work.\n     Pleasure without conscience.\n     Knowledge without character.\n     Commerce without morality.\n     Science without humanity.\n     Worship without sacrifice.\n     Politics without principle.\n\n   -- Mohandas Gandhi\n\n-------------------------------------------\n\n"},{"id":"70367","messageId":"7v7igodwth.fsf@gitster.siamese.dyndns.org","threadId":"12344","inReplyTo":"47C77720.2080405@comcast.net","subject":"Re: [PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-29T07:51:54Z","receivedAt":"2008-02-29T07:51:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Paul Franz <thefranz@comcast.net> writes:\n\n> Johannes Schindelin wrote:\n>> Hi,\n>>\n>> [top-posting?]\n>\n> Is there something wrong with it?\n\nYes.  Please do not do it.\n"},{"id":"70368","messageId":"47C7BAEE.2020408@gnu.org","threadId":"12344","inReplyTo":"200802282143.19322.johannes.sixt@telecom.at","subject":"Re: [PATCH 04/40] Windows: Use the Windows style PATH separator ';'.","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-02-29T07:57:34Z","receivedAt":"2008-02-29T07:57:34Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"Johannes Sixt wrote:\n> On Thursday 28 February 2008 10:25, Paolo Bonzini wrote:\n>>> +#ifdef __MINGW32__\n>>> +\t\tstrbuf_addch(out, ';');\n>>> +#else\n>>>  \t\tstrbuf_addch(out, ':');\n>>> +#endif\n>> Why not adding a PATH_SEPARATOR #define?\n> \n> Because IMO it is obfuscating:\n> \n> 1. When you read through the code and see PATH_SEPARATOR, you still have\n> to go look how it's defined. Why? Because you always will ask: Is this \n> about ':' vs. ';' or '/' vs. '\\\\'?\n\nOne is a DIR_SEPARATOR, the other is a PATH_SEPARATOR.  It's a matter of \nconventions.\n\nPaolo\n"},{"id":"70375","messageId":"alpine.LSU.1.00.0802291023060.22527@racer.site","threadId":"12344","inReplyTo":"47C77720.2080405@comcast.net","subject":"Re: [PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T10:26:31Z","receivedAt":"2008-02-29T10:26:31Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Paul Franz wrote:\n\n> Johannes Schindelin wrote:\n> \n> > [top-posting?]\n> \n> Is there something wrong with it?\n\nMy favourite way to describe it (a quote):\n\n+A: Because it messes up the order in which people normally read text.\n+Q: Why is top-posting such a bad thing?\n+A: Top-posting.\n+Q: What is the most annoying thing on usenet and in e-mail?\n\n> > The problems with Git and Windows are not network related.  They are \n> > with Windows' pitiful performance when it comes to spawn processes.\n>\n> Which makes me believe that it sounds like git depends on spawning \n> processes being cheap.\n\nYes, like everything that relies on being scriptable.\n\n> > IMO your efforts to help Git on Windows would be better spent on the \n> > msysGit list, where you would learn about the real issues we face.\n> \n> Excuse my ignorance, could you tell me where the mysGit list is, so that \n> I can subscribe?\n\nIt is referenced right on the first page on\n\n\thttp://msysgit.googlecode.com/\n\nunder the keyword \"Groups:\".\n\nHth,\nDscho\n\n"},{"id":"70380","messageId":"47C7F059.8070307@comcast.net","threadId":"12344","inReplyTo":"7v7igodwth.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 22/40] Windows: Implement asynchronous functions as threads.","fromName":"Paul Franz","fromEmail":"thefranz@comcast.net","sentAt":"2008-02-29T11:45:29Z","receivedAt":"2008-02-29T11:45:29Z","isPatch":true,"sender":{"key":"thefranz@comcast.net","avatar":null},"body":"\n\nJunio C Hamano wrote:\n> Paul Franz <thefranz@comcast.net> writes:\n>\n>   \n>> Johannes Schindelin wrote:\n>>     \n>>> Hi,\n>>>\n>>> [top-posting?]\n>>>       \n>> Is there something wrong with it?\n>>     \n>\n> Yes.  Please do not do it.\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n>\n>   \nThanks. Noted for future reference.\n\n-- \n\n-------------------------------------------\n\nThere are seven sins in the world.\n     Wealth without work.\n     Pleasure without conscience.\n     Knowledge without character.\n     Commerce without morality.\n     Science without humanity.\n     Worship without sacrifice.\n     Politics without principle.\n\n   -- Mohandas Gandhi\n\n-------------------------------------------\n\n"},{"id":"70383","messageId":"alpine.LSU.1.00.0802291214160.22527@racer.site","threadId":"12344","inReplyTo":"47C7BAEE.2020408@gnu.org","subject":"Re: [PATCH 04/40] Windows: Use the Windows style PATH separator ';'.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T12:19:48Z","receivedAt":"2008-02-29T12:19:48Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 29 Feb 2008, Paolo Bonzini wrote:\n\n> Johannes Sixt wrote:\n> > On Thursday 28 February 2008 10:25, Paolo Bonzini wrote:\n> > > > +#ifdef __MINGW32__\n> > > > +\t\tstrbuf_addch(out, ';');\n> > > > +#else\n> > > >  \t\tstrbuf_addch(out, ':');\n> > > > +#endif\n> > > Why not adding a PATH_SEPARATOR #define?\n> > \n> > Because IMO it is obfuscating:\n> > \n> > 1. When you read through the code and see PATH_SEPARATOR, you still have\n> > to go look how it's defined. Why? Because you always will ask: Is this about\n> > ':' vs. ';' or '/' vs. '\\\\'?\n> \n> One is a DIR_SEPARATOR, the other is a PATH_SEPARATOR.  It's a matter of\n> conventions.\n\nI agree that it would be good, also for documentation purposes, to add the \n#defines.\n\nHowever, there is something ugly waiting for us: we often have\n\n\tcase '/':\n\nand for Windows, this needs to add\n\n\tcase '\\\\':\n\nNow, we could #define CASE_DIR_SEPARATOR, which expands to \"case '/': case \n'\\\\':\" on Windows, but I am prepared to let Windows uglify our source code \nonly so far *does the famous imitation of Linus where he puts two finger \nso close that you cannot see between them*.\n\nCiao,\nDscho\n\n"},{"id":"70385","messageId":"47C7FE7B.3030309@gnu.org","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802291214160.22527@racer.site","subject":"Re: [PATCH 04/40] Windows: Use the Windows style PATH separator ';'.","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-02-29T12:45:47Z","receivedAt":"2008-02-29T12:45:47Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"\n> However, there is something ugly waiting for us: we often have\n> \n> \tcase '/':\n> \n> and for Windows, this needs to add\n> \n> \tcase '\\\\':\n\nMore often than in an \"if\" statement (so you can add IS_DIR_SEPARATOR \nwhich is much less ugly than CASE_DIR_SEPARATOR)?\n\nPaolo\n"},{"id":"70387","messageId":"alpine.LSU.1.00.0802291257150.22527@racer.site","threadId":"12344","inReplyTo":"47C7FE7B.3030309@gnu.org","subject":"Re: [PATCH 04/40] Windows: Use the Windows style PATH separator ';'.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T12:59:07Z","receivedAt":"2008-02-29T12:59:07Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 29 Feb 2008, Paolo Bonzini wrote:\n\n> > However, there is something ugly waiting for us: we often have\n> > \n> > \tcase '/':\n> > \n> > and for Windows, this needs to add\n> > \n> > \tcase '\\\\':\n> \n> More often than in an \"if\" statement (so you can add IS_DIR_SEPARATOR \n> which is much less ugly than CASE_DIR_SEPARATOR)?\n\nI have not grepped through the patches (as yourself, I am too lazy), but I \nremember seeing the \"case\" case in two instances, and I do not remember \nseeing the \"if\" case.\n\nIn the end, I think suggesting something like PATH_SEPARATOR is good.  But \ninsisting on it without working on it is less good.\n\nSo I think that it is up to Hannes now; he got enough input, and he has a \nfine sense of taste, so he will do the Right Thing.\n\nCiao,\nDscho\n\n"},{"id":"70416","messageId":"200802292158.12398.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802290046180.22527@racer.site","subject":"Re: [PATCH 02/40] Compile some programs only conditionally.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-29T20:58:11Z","receivedAt":"2008-02-29T20:58:11Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Friday 29 February 2008 01:47, Johannes Schindelin wrote:\n> On Thu, 28 Feb 2008, Johannes Sixt wrote:\n> > openlog() etc. is only one problem in git-daemon. It also depends on\n> > SIGCHLD, a non-blocking waitpid, and a lot more. The patch that is in\n> > 4msysgit.git allows only a single connection, IIRC, after which it\n> > terminates. But I also think that git-daemon can be made more complete\n> > on Windows, but it certainly requires a major surgery.\n>\n> Okay, I did not look closely enough.  But even a single-connection daemon\n> is better than no daemon, no?\n\nIn principle, yes. But:\n\n- git-fetch needs two connections if there are new tags in the source repo.\n\n- The daemon patches in 4msysgit.git could be prettier, they certainly would \nnot pass your scrutiny.\n\ngit-daemon is not my itch at this time, so I won't scratch it.\n\n-- Hannes\n"},{"id":"70418","messageId":"200802292203.56899.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802290105150.22527@racer.site","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-29T21:03:56Z","receivedAt":"2008-02-29T21:03:56Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Friday 29 February 2008 02:07, Johannes Schindelin wrote:\n> On Thu, 28 Feb 2008, Johannes Sixt wrote:\n> > I thought about this, but I decided against it:  git-compat-util.h is\n> > the place to look for compatibility functions. A file compat/mingw.h\n> > only introduces an extra indirection and only *hides* stuff instead of\n> > making it obvious.\n>\n> Well, the thing is, there are quite a few definitions and declarations\n> that are _only_ _ever_ interesting if you are on MinGW32.\n>\n> So maybe it is a good idea to hide it to all the other users.\n\nYou get compat/mingw.h, but you don't get a zillion NO_<insert feature here>. \nThe two are pretty much exclusive anyway. Deal?\n\n-- Hannes\n"},{"id":"70425","messageId":"5d46db230802291347u5f286dadw6b532abf82c0cff7@mail.gmail.com","threadId":"12344","inReplyTo":"200802292216.25014.johannes.sixt@telecom.at","subject":"Re: [PATCH 20/40] Windows: A rudimentary poll() emulation.","fromName":"Govind Salinas","fromEmail":"blix@sophiasuchtig.com","sentAt":"2008-02-29T21:47:12Z","receivedAt":"2008-02-29T21:47:12Z","isPatch":true,"sender":{"key":"blix@sophiasuchtig.com","avatar":null},"body":"On 2/29/08, Johannes Sixt <johannes.sixt@telecom.at> wrote:\n> On Friday 29 February 2008 05:19, Govind Salinas wrote:\n>  > On Thu, Feb 28, 2008 at 2:49 PM, Johannes Sixt <johannes.sixt@telecom.at>\n>  wrote:\n>  > > On Thursday 28 February 2008 10:36, Paolo Bonzini wrote:\n>\n> > >  > For the future, would it be better to first use\n>  > >  > WaitForMultipleObjects, and then use PeekNamedPipe to find which\n>  > >  > handles have data on it? That's how the mingw port of GNU Smalltalk\n>  > >  > does it.\n>  > >\n>  > >  I tried but I failed. If you can show me code where\n>      ^^^^^^^^^^^^^^^^^^^^^\n>  > > WaitForMultipleObjects works on handles that MSVCRT.DLL's open() created,\n>  > > I'll gladly accept it!\n>  >\n>  > I haven't tried it myself, but you can look at _get_osfhandle\n>  >\n>  > http://msdn2.microsoft.com/en-us/library/ks2530z6(VS.71).aspx\n>  >\n>  > of course you would need to keep a mapping from the handle to the fd.\n>  > Or _open_osfhandle might work the other way, I don't know if it will\n>  > necessarily return the same descriptor.\n>  >\n>  > http://msdn2.microsoft.com/en-us/library/bdts1c9x(VS.71).aspx\n>\n>\n> Fscking basics, this. How do you go from here to WaitForMultipleObjects?\n>\nWell, I could have sworn that named pipe handles were in the waitable\nlist, but after looking again, they are not.\n\nHowever, I did find\n\nhttp://msdn2.microsoft.com/en-us/library/aa365603(VS.85).aspx\n\nwhich suggests you can pass these handles to ReadFile and if you include an\nOVERLAPPED struct in the call, it will return an event handle to wait on which\nyou can then use to wait.\n\nSorry for the false lead.\n\nHTH,\nGovind.\n"},{"id":"70428","messageId":"alpine.LSU.1.00.0802292153210.22527@racer.site","threadId":"12344","inReplyTo":"200802292158.12398.johannes.sixt@telecom.at","subject":"Re: [PATCH 02/40] Compile some programs only conditionally.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T21:53:51Z","receivedAt":"2008-02-29T21:53:51Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 29 Feb 2008, Johannes Sixt wrote:\n\n> On Friday 29 February 2008 01:47, Johannes Schindelin wrote:\n> > On Thu, 28 Feb 2008, Johannes Sixt wrote:\n> > > openlog() etc. is only one problem in git-daemon. It also depends on\n> > > SIGCHLD, a non-blocking waitpid, and a lot more. The patch that is in\n> > > 4msysgit.git allows only a single connection, IIRC, after which it\n> > > terminates. But I also think that git-daemon can be made more complete\n> > > on Windows, but it certainly requires a major surgery.\n> >\n> > Okay, I did not look closely enough.  But even a single-connection daemon\n> > is better than no daemon, no?\n> \n> In principle, yes. But:\n> \n> - git-fetch needs two connections if there are new tags in the source repo.\n> \n> - The daemon patches in 4msysgit.git could be prettier, they certainly would \n> not pass your scrutiny.\n\nRight.\n\n> git-daemon is not my itch at this time, so I won't scratch it.\n\nRight.  I will mail the correct person.\n\nCiao,\nDscho\n\n"},{"id":"70430","messageId":"alpine.LSU.1.00.0802292154110.22527@racer.site","threadId":"12344","inReplyTo":"200802292203.56899.johannes.sixt@telecom.at","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T21:54:24Z","receivedAt":"2008-02-29T21:54:24Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 29 Feb 2008, Johannes Sixt wrote:\n\n> On Friday 29 February 2008 02:07, Johannes Schindelin wrote:\n> > On Thu, 28 Feb 2008, Johannes Sixt wrote:\n> > > I thought about this, but I decided against it:  git-compat-util.h is\n> > > the place to look for compatibility functions. A file compat/mingw.h\n> > > only introduces an extra indirection and only *hides* stuff instead of\n> > > making it obvious.\n> >\n> > Well, the thing is, there are quite a few definitions and declarations\n> > that are _only_ _ever_ interesting if you are on MinGW32.\n> >\n> > So maybe it is a good idea to hide it to all the other users.\n> \n> You get compat/mingw.h, but you don't get a zillion NO_<insert feature here>. \n> The two are pretty much exclusive anyway. Deal?\n\nDeal.\n\nCiao,\nDscho\n\n"},{"id":"70434","messageId":"200802292316.16935.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"5d46db230802291347u5f286dadw6b532abf82c0cff7@mail.gmail.com","subject":"Re: [PATCH 20/40] Windows: A rudimentary poll() emulation.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-02-29T22:16:16Z","receivedAt":"2008-02-29T22:16:16Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Friday 29 February 2008 22:47, Govind Salinas wrote:\n> On 2/29/08, Johannes Sixt <johannes.sixt@telecom.at> wrote:\n> > On Friday 29 February 2008 05:19, Govind Salinas wrote:\n> >  > On Thu, Feb 28, 2008 at 2:49 PM, Johannes Sixt\n> >  > <johannes.sixt@telecom.at>\n> >\n> >  wrote:\n> >  > > On Thursday 28 February 2008 10:36, Paolo Bonzini wrote:\n> > > >  > For the future, would it be better to first use\n> > > >  >\n> >  > >  > WaitForMultipleObjects, and then use PeekNamedPipe to find which\n> >  > >  > handles have data on it? That's how the mingw port of GNU\n> >  > >  > Smalltalk does it.\n> >  > >\n> >  > >  I tried but I failed. If you can show me code where\n> >\n> >      ^^^^^^^^^^^^^^^^^^^^^\n> >\n> >  > > WaitForMultipleObjects works on handles that MSVCRT.DLL's open()\n> >  > > created, I'll gladly accept it!\n> >  >\n> >  > I haven't tried it myself, but you can look at _get_osfhandle\n> >  >\n> >  > http://msdn2.microsoft.com/en-us/library/ks2530z6(VS.71).aspx\n> >  >\n> >  > of course you would need to keep a mapping from the handle to the fd.\n> >  > Or _open_osfhandle might work the other way, I don't know if it will\n> >  > necessarily return the same descriptor.\n> >  >\n> >  > http://msdn2.microsoft.com/en-us/library/bdts1c9x(VS.71).aspx\n> >\n> > Fscking basics, this. How do you go from here to WaitForMultipleObjects?\n>\n> Well, I could have sworn that named pipe handles were in the waitable\n> list, but after looking again, they are not.\n>\n> However, I did find\n>\n> http://msdn2.microsoft.com/en-us/library/aa365603(VS.85).aspx\n>\n> which suggests you can pass these handles to ReadFile and if you include an\n> OVERLAPPED struct in the call, it will return an event handle to wait on\n> which you can then use to wait.\n\nI've read the documentation. Try it. Come back when you succeed.\n\n-- Hannes\n"},{"id":"70445","messageId":"47C89298.F6F8253D@dessent.net","threadId":"12344","inReplyTo":"5d46db230802291347u5f286dadw6b532abf82c0cff7@mail.gmail.com","subject":"Re: [PATCH 20/40] Windows: A rudimentary poll() emulation.","fromName":"Brian Dessent","fromEmail":"brian@dessent.net","sentAt":"2008-02-29T23:17:44Z","receivedAt":"2008-02-29T23:17:44Z","isPatch":true,"sender":{"key":"brian@dessent.net","avatar":null},"body":"Govind Salinas wrote:\n\n> http://msdn2.microsoft.com/en-us/library/aa365603(VS.85).aspx\n> \n> which suggests you can pass these handles to ReadFile and if you include an\n> OVERLAPPED struct in the call, it will return an event handle to wait on which\n> you can then use to wait.\n\nThat only applies if the handle has been opened with\nFILE_FLAG_OVERLAPPED.\n\nBrian\n"},{"id":"70536","messageId":"200803011648.38296.robin.rosenberg@dewire.com","threadId":"12344","inReplyTo":"200802282149.36748.johannes.sixt@telecom.at","subject":"Re: [PATCH 20/40] Windows: A rudimentary poll() emulation.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-03-01T15:48:38Z","receivedAt":"2008-03-01T15:48:38Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Den Thursday 28 February 2008 21.49.36 skrev Johannes Sixt:\n> On Thursday 28 February 2008 10:36, Paolo Bonzini wrote:\n> > For the future, would it be better to first use WaitForMultipleObjects,\n> > and then use PeekNamedPipe to find which handles have data on it?\n> > That's how the mingw port of GNU Smalltalk does it.\n>\n> I tried but I failed. If you can show me code where WaitForMultipleObjects\n> works on handles that MSVCRT.DLL's open() created, I'll gladly accept it!\n\nHave you checked _get_osfhandle? There's a warning though in the knowledgebase\nwith number 99173, though. There's also another function that works the other \nway, _open_osfhandle.\n\n-- robin\n\n"},{"id":"70547","messageId":"200803012024.23286.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"200803011648.38296.robin.rosenberg@dewire.com","subject":"Re: [PATCH 20/40] Windows: A rudimentary poll() emulation.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-03-01T19:24:23Z","receivedAt":"2008-03-01T19:24:23Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Saturday 01 March 2008 16:48, Robin Rosenberg wrote:\n> Den Thursday 28 February 2008 21.49.36 skrev Johannes Sixt:\n> > On Thursday 28 February 2008 10:36, Paolo Bonzini wrote:\n> > > For the future, would it be better to first use WaitForMultipleObjects,\n> > > and then use PeekNamedPipe to find which handles have data on it?\n> > > That's how the mingw port of GNU Smalltalk does it.\n> >\n> > I tried but I failed. If you can show me code where\n> > WaitForMultipleObjects works on handles that MSVCRT.DLL's open() created,\n> > I'll gladly accept it!\n>\n> Have you checked _get_osfhandle? There's a warning though in the\n> knowledgebase with number 99173, though. There's also another function that\n> works the other way, _open_osfhandle.\n\nHandwaving you are! This stuff is well-known. Show me code.\n\n-- Hannes\n"},{"id":"70700","messageId":"200803022220.59711.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"1204138503-6126-1-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH 00/40] MinGW port","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-03-02T21:20:59Z","receivedAt":"2008-03-02T21:20:59Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Wednesday 27 February 2008 19:54, Johannes Sixt wrote:\n> So here it is, the MinGW port of git.\n> This series is also available from\n>\n> git://repo.or.cz/git/mingw/j6t.git upstream\n> http://repo.or.cz/w/git/mingw/j6t.git?a=shortlog;h=upstream\n\nI've integrated the feedback that I received in this series. Thanks to \nhas_dos_drive_prefix() as suggested by Dscho quite a number of #ifdef's could \nbe removed. Below is the interdiff between the old and the new state. \nHowever, I have not yet moved stuff out of git-compat-util.h into \ncompat/mingw.h to keep this message readable. I'll do that later after I have \nrebased the series on top of the latest git.git master.\n\nBTW, the last hunk in the interdiff is a new bug-fix.\n\n-- Hannes\n\ndiff --git a/Makefile b/Makefile\nindex 53a4e2a..2ea53c0 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -265,6 +265,7 @@ PROGRAMS = \\\n \tgit-pack-redundant$X git-var$X \\\n \tgit-merge-tree$X \\\n \tgit-merge-recursive$X \\\n+\t$(POSIX_ONLY_PROGRAMS) \\\n \t$(EXTRA_PROGRAMS)\n \n # Empty...\n@@ -541,9 +542,11 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_MKDTEMP = YesPlease\n \tNO_SVN_TESTS = YesPlease\n \tNO_PERL_MAKEMAKER = YesPlease\n-\tNO_EXTRA_PROGRAMS = YesPlease\n+\tNO_POSIX_ONLY_PROGRAMS = YesPlease\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat\n+\tCOMPAT_CFLAGS += -DPATH_SEP=\"';'\"\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n+\tCOMPAT_CFLAGS += -DPRIuMAX=\\\"I64u\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o\n \tEXTLIBS += -lws2_32\n \tX = .exe\n@@ -611,8 +614,8 @@ ifdef ZLIB_PATH\n endif\n EXTLIBS += -lz\n \n-ifndef NO_EXTRA_PROGRAMS\n-\tEXTRA_PROGRAMS += \\\n+ifndef NO_POSIX_ONLY_PROGRAMS\n+\tPOSIX_ONLY_PROGRAMS = \\\n \t\tgit-daemon$X \\\n \t\tgit-imap-send$X\n endif\ndiff --git a/cache.h b/cache.h\nindex 3e4e10a..781fa40 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -441,11 +441,7 @@ int safe_create_leading_directories(char *path);\n char *enter_repo(char *path, int strict);\n static inline int is_absolute_path(const char *path)\n {\n-#ifndef __MINGW32__\n-\treturn path[0] == '/';\n-#else\n-\treturn path[0] == '/' || (path[0] && path[1] == ':');\n-#endif\n+\treturn path[0] == '/' || has_dos_drive_prefix(path);\n }\n const char *make_absolute_path(const char *path);\n \ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 0888288..6733727 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -330,16 +330,13 @@ struct tm *localtime_r(const time_t *timep, struct tm \n*result)\n #undef getcwd\n char *mingw_getcwd(char *pointer, int len)\n {\n+\tint i;\n \tchar *ret = getcwd(pointer, len);\n \tif (!ret)\n \t\treturn ret;\n-\tif (pointer[0] != 0 && pointer[1] == ':') {\n-\t\tint i;\n-\t\tfor (i = 2; pointer[i]; i++)\n-\t\t\t/* Thanks, Bill. You'll burn in hell for that. */\n-\t\t\tif (pointer[i] == '\\\\')\n-\t\t\t\tpointer[i] = '/';\n-\t}\n+\tfor (i = 0; pointer[i]; i++)\n+\t\tif (pointer[i] == '\\\\')\n+\t\t\tpointer[i] = '/';\n \treturn ret;\n }\n \ndiff --git a/connect.c b/connect.c\nindex 7e18ac8..cb81b8c 100644\n--- a/connect.c\n+++ b/connect.c\n@@ -529,13 +529,7 @@ struct child_process *git_connect(int fd[2], const char \n*url_orig,\n \t\tend = host;\n \n \tpath = strchr(end, c);\n-#ifdef __MINGW32__\n-\t/* host must have at least 2 chars to catch DOS C:/path */\n-\tif (path && path - end > 1)\n-#else\n-\tif (path)\n-#endif\n-\t{\n+\tif (path && !has_dos_drive_prefix(end)) {\n \t\tif (c == ':') {\n \t\t\tprotocol = PROTO_SSH;\n \t\t\t*path++ = '\\0';\ndiff --git a/exec_cmd.c b/exec_cmd.c\nindex 6d2f740..84db7ee 100644\n--- a/exec_cmd.c\n+++ b/exec_cmd.c\n@@ -70,11 +70,7 @@ static void add_path(struct strbuf *out, const char *path)\n \t\telse\n \t\t\tstrbuf_addstr(out, make_absolute_path(path));\n \n-#ifdef __MINGW32__\n-\t\tstrbuf_addch(out, ';');\n-#else\n-\t\tstrbuf_addch(out, ':');\n-#endif\n+\t\tstrbuf_addch(out, PATH_SEP);\n \t}\n }\n \ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 4a8df8e..3ea0d91 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -103,11 +103,11 @@\n #endif\n \n #ifndef PRIuMAX\n-#ifndef __MINGW32__\n #define PRIuMAX \"llu\"\n-#else\n-#define PRIuMAX \"I64u\"\n #endif\n+\n+#ifndef PATH_SEP\n+#define PATH_SEP ':'\n #endif\n \n #ifdef __GNUC__\n@@ -168,9 +168,11 @@ extern int git_munmap(void *start, size_t length);\n #define pread git_pread\n extern ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);\n #endif\n-/* Forward decl that will remind us if its twin in cache.h changes.\n-   This function in used in compat/pread.c.  But we can't include\n-   cache.h there. */\n+/*\n+ * Forward decl that will remind us if its twin in cache.h changes.\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 \n #ifdef NO_SETENV\n@@ -650,6 +652,18 @@ char **copy_environ(void);\n void free_environ(char **env);\n char **env_setenv(char **env, const char *name);\n \n+static inline int has_dos_drive_prefix(const char *path)\n+{\n+\treturn isalpha(*path) && path[1] == ':';\n+}\n+\n+#else /* __MINGW32__ */\n+\n+static inline int has_dos_drive_prefix(const char *path)\n+{\n+\treturn 0;\n+}\n+\n #endif /* __MINGW32__ */\n \n #endif\ndiff --git a/help.c b/help.c\nindex 0248c76..b53c6d7 100644\n--- a/help.c\n+++ b/help.c\n@@ -231,11 +231,6 @@ static void list_commands(void)\n \tconst char *env_path = getenv(\"PATH\");\n \tchar *paths, *path, *colon;\n \tconst char *exec_path = git_exec_path();\n-#ifdef __MINGW32__\n-\tchar sep = ';';\n-#else\n-\tchar sep = ':';\n-#endif\n \n \tif (exec_path)\n \t\tlongest = list_commands_in_dir(&main_cmds, exec_path);\n@@ -247,7 +242,7 @@ static void list_commands(void)\n \n \tpath = paths = xstrdup(env_path);\n \twhile (1) {\n-\t\tif ((colon = strchr(path, sep)))\n+\t\tif ((colon = strchr(path, PATH_SEP)))\n \t\t\t*colon = 0;\n \n \t\tlen = list_commands_in_dir(&other_cmds, path);\ndiff --git a/setup.c b/setup.c\nindex 77cc461..212763f 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -12,15 +12,14 @@ static inline int is_dir_sep(char c) { return c == '/'; }\n \n static int sanitary_path_copy(char *dst, const char *src)\n {\n-\tchar *dst0 = dst;\n+\tchar *dst0;\n \n-#ifdef __MINGW32__\n-\tif (isalpha(*src) && src[1] == ':') {\n+\tif (has_dos_drive_prefix(src)) {\n \t\t*dst++ = *src++;\n \t\t*dst++ = *src++;\n-\t\tdst0 = dst;\n \t}\n-#endif\n+\tdst0 = dst;\n+\n \tif (is_dir_sep(*src)) {\n \t\t*dst++ = '/';\n \t\twhile (is_dir_sep(*src))\n@@ -39,30 +38,22 @@ static int sanitary_path_copy(char *dst, const char *src)\n \t\t * (4) \"../\"          -- strip one, eat slash and continue.\n \t\t */\n \t\tif (c == '.') {\n-\t\t\tswitch (src[1]) {\n-\t\t\tcase '\\0':\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\tcase '/':\n-#ifdef __MINGW32__\n-\t\t\tcase '\\\\':\n-#endif\n+\t\t\t} else if (is_dir_sep(src[1])) {\n \t\t\t\t/* (2) */\n \t\t\t\tsrc += 2;\n \t\t\t\twhile (is_dir_sep(*src))\n \t\t\t\t\tsrc++;\n \t\t\t\tcontinue;\n-\t\t\tcase '.':\n-\t\t\t\tswitch (src[2]) {\n-\t\t\t\tcase '\\0':\n+\t\t\t} else if (src[1] == '.') {\n+\t\t\t\tif (!src[2]) {\n \t\t\t\t\t/* (3) */\n \t\t\t\t\tsrc += 2;\n \t\t\t\t\tgoto up_one;\n-\t\t\t\tcase '/':\n-#ifdef __MINGW32__\n-\t\t\t\tcase '\\\\':\n-#endif\n+\t\t\t\t} else if (is_dir_sep(src[2])) {\n \t\t\t\t\t/* (4) */\n \t\t\t\t\tsrc += 3;\n \t\t\t\t\twhile (is_dir_sep(*src))\n@@ -397,10 +388,8 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \n \tif (!getcwd(cwd, sizeof(cwd)-1))\n \t\tdie(\"Unable to read current working directory\");\n-#ifdef __MINGW32__\n-\tif (cwd[1] == ':')\n+\tif (has_dos_drive_prefix(cwd))\n \t\tminoffset = 2;\n-#endif\n \n \t/*\n \t * Test in the following order (relative to the cwd):\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 0c60849..fa34c75 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -85,10 +85,8 @@ int get_sha1_hex(const char *hex, unsigned char *sha1)\n \n static inline int offset_1st_component(const char *path)\n {\n-#ifdef __MINGW32__\n-\tif (isalpha(path[0]) && path[1] == ':')\n+\tif (has_dos_drive_prefix(path))\n \t\treturn 2 + (path[2] == '/');\n-#endif\n \treturn *path == '/';\n }\n \n@@ -395,11 +393,7 @@ void prepare_alt_odb(void)\n \tif (!alt) alt = \"\";\n \n \talt_odb_tail = &alt_odb_list;\n-#ifdef __MINGW32__\n-\tlink_alt_odb_entries(alt, alt + strlen(alt), ';', NULL, 0);\n-#else\n-\tlink_alt_odb_entries(alt, alt + strlen(alt), ':', NULL, 0);\n-#endif\n+\tlink_alt_odb_entries(alt, alt + strlen(alt), PATH_SEP, NULL, 0);\n \n \tread_info_alternates(get_object_directory(), 0);\n }\ndiff --git a/templates/Makefile b/templates/Makefile\nindex eb08702..6c0da7a 100644\n--- a/templates/Makefile\n+++ b/templates/Makefile\n@@ -34,11 +34,8 @@ boilerplates.made : $(bpsrc)\n \t\tmkdir -p blt/$$dir && \\\n \t\tcase \"$$boilerplate\" in \\\n \t\t*--) ;; \\\n-\t\t*) if test -n \"$$(sed -ne '/^#!\\//p' -e '1q' < \"$$boilerplate\")\"; then \\\n-\t\t\tcp \"$$boilerplate\" \"blt/$${dst}$(NOEXECTEMPL)\"; \\\n-\t\t   else \\\n-\t\t\tcp \"$$boilerplate\" \"blt/$$dst\"; \\\n-\t\t   fi ;; \\\n+\t\thooks--*) cp $$boilerplate blt/$${dst}$(NOEXECTEMPL) ;; \\\n+\t\t*) cp $$boilerplate blt/$$dst ;; \\\n \t\tesac || exit; \\\n \tdone && \\\n \tdate >$@\ndiff --git a/transport.c b/transport.c\nindex 397983d..266a6cc 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -692,7 +692,8 @@ static int is_local(const char *url)\n {\n \tconst char *colon = strchr(url, ':');\n \tconst char *slash = strchr(url, '/');\n-\treturn !colon || (slash && slash < colon);\n+\treturn !colon || (slash && slash < colon) ||\n+\t\thas_dos_drive_prefix(url);\n }\n \n static int is_file(const char *url)\n"},{"id":"70707","messageId":"alpine.LSU.1.00.0803022200070.22527@racer.site","threadId":"12344","inReplyTo":"200803022220.59711.johannes.sixt@telecom.at","subject":"Re: [PATCH 00/40] MinGW port","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-02T22:07:17Z","receivedAt":"2008-03-02T22:07:17Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 2 Mar 2008, Johannes Sixt wrote:\n\n> On Wednesday 27 February 2008 19:54, Johannes Sixt wrote:\n> > So here it is, the MinGW port of git.\n> > This series is also available from\n> >\n> > git://repo.or.cz/git/mingw/j6t.git upstream\n> > http://repo.or.cz/w/git/mingw/j6t.git?a=shortlog;h=upstream\n> \n> I've integrated the feedback that I received in this series. Thanks to \n> has_dos_drive_prefix() as suggested by Dscho quite a number of #ifdef's \n> could be removed. Below is the interdiff between the old and the new \n> state. However, I have not yet moved stuff out of git-compat-util.h into \n> compat/mingw.h to keep this message readable. I'll do that later after I \n> have rebased the series on top of the latest git.git master.\n\nThanks!\n\nAnd especially thanks for the interdiff, it makes reviewing much easier \n;-)\n\n> diff --git a/Makefile b/Makefile\n> index 53a4e2a..2ea53c0 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -265,6 +265,7 @@ PROGRAMS = \\\n>  \tgit-pack-redundant$X git-var$X \\\n>  \tgit-merge-tree$X \\\n>  \tgit-merge-recursive$X \\\n> +\t$(POSIX_ONLY_PROGRAMS) \\\n>  \t$(EXTRA_PROGRAMS)\n\nClever name!  But shouldn't EXTRA_PROGRAMS go?\n\n> diff --git a/compat/mingw.c b/compat/mingw.c\n> index 0888288..6733727 100644\n> --- a/compat/mingw.c\n> +++ b/compat/mingw.c\n> @@ -330,16 +330,13 @@ struct tm *localtime_r(const time_t *timep, struct tm \n> *result)\n>  #undef getcwd\n>  char *mingw_getcwd(char *pointer, int len)\n>  {\n> +\tint i;\n>  \tchar *ret = getcwd(pointer, len);\n>  \tif (!ret)\n>  \t\treturn ret;\n> -\tif (pointer[0] != 0 && pointer[1] == ':') {\n> -\t\tint i;\n> -\t\tfor (i = 2; pointer[i]; i++)\n> -\t\t\t/* Thanks, Bill. You'll burn in hell for that. */\n> -\t\t\tif (pointer[i] == '\\\\')\n> -\t\t\t\tpointer[i] = '/';\n> -\t}\n> +\tfor (i = 0; pointer[i]; i++)\n> +\t\tif (pointer[i] == '\\\\')\n> +\t\t\tpointer[i] = '/';\n\nBoo.  My nice comment.  You just deleted it.  ;-)\n\n> diff --git a/templates/Makefile b/templates/Makefile\n> index eb08702..6c0da7a 100644\n> --- a/templates/Makefile\n> +++ b/templates/Makefile\n> @@ -34,11 +34,8 @@ boilerplates.made : $(bpsrc)\n>  \t\tmkdir -p blt/$$dir && \\\n>  \t\tcase \"$$boilerplate\" in \\\n>  \t\t*--) ;; \\\n> -\t\t*) if test -n \"$$(sed -ne '/^#!\\//p' -e '1q' < \"$$boilerplate\")\"; then \\\n> -\t\t\tcp \"$$boilerplate\" \"blt/$${dst}$(NOEXECTEMPL)\"; \\\n> -\t\t   else \\\n> -\t\t\tcp \"$$boilerplate\" \"blt/$$dst\"; \\\n> -\t\t   fi ;; \\\n> +\t\thooks--*) cp $$boilerplate blt/$${dst}$(NOEXECTEMPL) ;; \\\n> +\t\t*) cp $$boilerplate blt/$$dst ;; \\\n\nNice!  (IOW much better than what I suggested.)\n\n> diff --git a/transport.c b/transport.c\n> index 397983d..266a6cc 100644\n> --- a/transport.c\n> +++ b/transport.c\n> @@ -692,7 +692,8 @@ static int is_local(const char *url)\n>  {\n>  \tconst char *colon = strchr(url, ':');\n>  \tconst char *slash = strchr(url, '/');\n> -\treturn !colon || (slash && slash < colon);\n> +\treturn !colon || (slash && slash < colon) ||\n> +\t\thas_dos_drive_prefix(url);\n\nThis must be the bug fix ;-)\n\nI like it!\n\nThanks,\nDscho\n\n"},{"id":"70821","messageId":"200803031934.25569.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803022200070.22527@racer.site","subject":"Re: [PATCH 00/40] MinGW port","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-03-03T18:34:25Z","receivedAt":"2008-03-03T18:34:25Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Sunday 02 March 2008 23:07, Johannes Schindelin wrote:\n> On Sun, 2 Mar 2008, Johannes Sixt wrote:\n> > diff --git a/Makefile b/Makefile\n> > index 53a4e2a..2ea53c0 100644\n> > --- a/Makefile\n> > +++ b/Makefile\n> > @@ -265,6 +265,7 @@ PROGRAMS = \\\n> >  \tgit-pack-redundant$X git-var$X \\\n> >  \tgit-merge-tree$X \\\n> >  \tgit-merge-recursive$X \\\n> > +\t$(POSIX_ONLY_PROGRAMS) \\\n> >  \t$(EXTRA_PROGRAMS)\n>\n> Clever name!  But shouldn't EXTRA_PROGRAMS go?\n\nNo. It was there before I messed around with it.\n\n> > -\t\t\t/* Thanks, Bill. You'll burn in hell for that. */\n>\n> Boo.  My nice comment.  You just deleted it.  ;-)\n\nIt's not my fault, I swear it. It went like this: I erased the line, but then \nchanged my mind and hit Undo. But then I thought, this is a serious project, \nwe don't need such language. And hit Redo. Which made me think again... So I \nsaid to my little rascal, who was playing Lego: \"Say 'stop'\", and I hit Undo \nand Redo as fast as I could. And when he said \"Stop\", oh well, I had just hit \nRedo. So here we have it - no longer.\n\n;-)\n\n-- Hannes\n"},{"id":"71124","messageId":"200803052221.12495.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0802281159550.22527@racer.site","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-03-05T21:21:12Z","receivedAt":"2008-03-05T21:21:12Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Thursday 28 February 2008 13:05, Johannes Schindelin wrote:\n> On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > --- a/git-compat-util.h\n> > +++ b/git-compat-util.h\n> > @@ -357,6 +359,10 @@ static inline FILE *xfdopen(int fd, const char\n> > *mode) return stream;\n> >  }\n> >\n> > +#ifdef __MINGW32__\n> > +int mkstemp(char *template);\n> > +#endif\n> > +\n> >  static inline int xmkstemp(char *template)\n> >  {\n> >  \tint fd;\n>\n> Could we have this...\n>\n> > @@ -437,4 +443,140 @@ void git_qsort(void *base, size_t nmemb, size_t\n> > size, #define qsort git_qsort\n> >  #endif\n> >\n> > +#ifdef __MINGW32__\n> > +\n> > +#include <winsock2.h>\n> > +\n> > +/*\n> > + * things that are not available in header files\n> > + */\n> > +\n> > [...]\n>\n> ... and this in compat/mingw.h?  And then, we'd only have\n>\n> #ifdef __MINGW32__\n> #include \"mingw.h\"\n> #endif\n>\n> in git-compat-util.h?\n\nI've now created compat/mingw.h. Below is the interdiff. Of course, it mostly \nonly moves code around. But you might want to look at at mkstemp, PATH_SEP, \nPRIuMAX, and has_dos_drive_prefix. Notice also that I include compat/mingw.h \nearly in git-compat-util.h instead of late.\n\nSTRIP_EXTENSION could also be moved into compat/mingw.h, but I decided not to \ndo so because I think that macros that code outside of git-compat-util.h \nchecks for using #ifdef should be found in Makefile.\n\n-- Hannes\n\ndiff --git a/Makefile b/Makefile\nindex 88a52bf..af74566 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -548,9 +548,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_PERL_MAKEMAKER = YesPlease\n \tNO_POSIX_ONLY_PROGRAMS = YesPlease\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat\n-\tCOMPAT_CFLAGS += -DPATH_SEP=\"';'\"\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n-\tCOMPAT_CFLAGS += -DPRIuMAX=\\\"I64u\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o\n \tEXTLIBS += -lws2_32\n \tX = .exe\ndiff --git a/compat/mingw.h b/compat/mingw.h\nnew file mode 100644\nindex 0000000..d92c631\n--- /dev/null\n+++ b/compat/mingw.h\n@@ -0,0 +1,210 @@\n+#include <winsock2.h>\n+\n+/*\n+ * things that are not available in header files\n+ */\n+\n+typedef int pid_t;\n+#define hstrerror strerror\n+\n+#define S_IFLNK    0120000 /* Symbolic link */\n+#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)\n+#define S_ISSOCK(x) 0\n+#define S_IRGRP 0\n+#define S_IWGRP 0\n+#define S_IXGRP 0\n+#define S_ISGID 0\n+#define S_IROTH 0\n+#define S_IXOTH 0\n+\n+#define WIFEXITED(x) ((unsigned)(x) < 259)\t/* STILL_ACTIVE */\n+#define WEXITSTATUS(x) ((x) & 0xff)\n+#define WIFSIGNALED(x) ((unsigned)(x) > 259)\n+\n+#define SIGKILL 0\n+#define SIGCHLD 0\n+#define SIGPIPE 0\n+#define SIGALRM 100\n+\n+#define F_GETFD 1\n+#define F_SETFD 2\n+#define FD_CLOEXEC 0x1\n+\n+struct passwd {\n+\tchar *pw_name;\n+\tchar *pw_gecos;\n+\tchar *pw_dir;\n+};\n+\n+struct pollfd {\n+\tint fd;           /* file descriptor */\n+\tshort events;     /* requested events */\n+\tshort revents;    /* returned events */\n+};\n+#define POLLIN 1\n+#define POLLHUP 2\n+\n+typedef void (__cdecl *sig_handler_t)(int);\n+struct sigaction {\n+\tsig_handler_t sa_handler;\n+\tunsigned sa_flags;\n+};\n+#define sigemptyset(x) (void)0\n+#define SA_RESTART 0\n+\n+struct itimerval {\n+\tstruct timeval it_value, it_interval;\n+};\n+#define ITIMER_REAL 0\n+\n+/*\n+ * trivial stubs\n+ */\n+\n+static inline int readlink(const char *path, char *buf, size_t bufsiz)\n+{ errno = ENOSYS; return -1; }\n+static inline int symlink(const char *oldpath, const char *newpath)\n+{ errno = ENOSYS; return -1; }\n+static inline int link(const char *oldpath, const char *newpath)\n+{ errno = ENOSYS; return -1; }\n+static inline int fchmod(int fildes, mode_t mode)\n+{ errno = ENOSYS; return -1; }\n+static inline int fork(void)\n+{ errno = ENOSYS; return -1; }\n+static inline unsigned int alarm(unsigned int seconds)\n+{ return 0; }\n+static inline int fsync(int fd)\n+{ return 0; }\n+static inline int getppid(void)\n+{ return 1; }\n+static inline void sync(void)\n+{}\n+static inline int getuid()\n+{ return 1; }\n+static inline struct passwd *getpwnam(const char *name)\n+{ return NULL; }\n+static inline int fcntl(int fd, int cmd, long arg)\n+{\n+\tif (cmd == F_GETFD || cmd == F_SETFD)\n+\t\treturn 0;\n+\terrno = EINVAL;\n+\treturn -1;\n+}\n+\n+/*\n+ * simple adaptors\n+ */\n+\n+static inline int mingw_mkdir(const char *path, int mode)\n+{\n+\treturn mkdir(path);\n+}\n+#define mkdir mingw_mkdir\n+\n+static inline int mingw_unlink(const char *pathname)\n+{\n+\t/* read-only files cannot be removed */\n+\tchmod(pathname, 0666);\n+\treturn unlink(pathname);\n+}\n+#define unlink mingw_unlink\n+\n+static inline int waitpid(pid_t pid, unsigned *status, unsigned options)\n+{\n+\tif (options == 0)\n+\t\treturn _cwait(status, pid, 0);\n+\terrno = EINVAL;\n+\treturn -1;\n+}\n+\n+/*\n+ * implementations of missing functions\n+ */\n+\n+int pipe(int filedes[2]);\n+unsigned int sleep (unsigned int seconds);\n+int mkstemp(char *template);\n+int gettimeofday(struct timeval *tv, void *tz);\n+int poll(struct pollfd *ufds, unsigned int nfds, int timeout);\n+struct tm *gmtime_r(const time_t *timep, struct tm *result);\n+struct tm *localtime_r(const time_t *timep, struct tm *result);\n+int getpagesize(void);\t/* defined in MinGW's libgcc.a */\n+struct passwd *getpwuid(int uid);\n+int setitimer(int type, struct itimerval *in, struct itimerval *out);\n+int sigaction(int sig, struct sigaction *in, struct sigaction *out);\n+\n+/*\n+ * replacements of existing functions\n+ */\n+\n+int mingw_open (const char *filename, int oflags, ...);\n+#define open mingw_open\n+\n+char *mingw_getcwd(char *pointer, int len);\n+#define getcwd mingw_getcwd\n+\n+struct hostent *mingw_gethostbyname(const char *host);\n+#define gethostbyname mingw_gethostbyname\n+\n+int mingw_socket(int domain, int type, int protocol);\n+#define socket mingw_socket\n+\n+int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);\n+#define connect mingw_connect\n+\n+int mingw_rename(const char*, const char*);\n+#define rename mingw_rename\n+\n+/* Use mingw_lstat() instead of lstat()/stat() and\n+ * mingw_fstat() instead of fstat() on Windows.\n+ * struct stat is redefined because it lacks the st_blocks member.\n+ */\n+struct mingw_stat {\n+\tunsigned st_mode;\n+\ttime_t st_mtime, st_atime, st_ctime;\n+\tunsigned st_dev, st_ino, st_uid, st_gid;\n+\tsize_t st_size;\n+\tsize_t st_blocks;\n+};\n+int mingw_lstat(const char *file_name, struct mingw_stat *buf);\n+int mingw_fstat(int fd, struct mingw_stat *buf);\n+#define fstat mingw_fstat\n+#define lstat mingw_lstat\n+#define stat mingw_stat\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_vsnprintf(char *buf, size_t size, const char *fmt, va_list args);\n+#define vsnprintf mingw_vsnprintf\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\n+\n+static inline unsigned int git_ntohl(unsigned int x)\n+{ return (unsigned int)ntohl(x); }\n+#define ntohl git_ntohl\n+\n+sig_handler_t mingw_signal(int sig, sig_handler_t handler);\n+#define signal mingw_signal\n+\n+/*\n+ * git specific compatibility\n+ */\n+\n+static inline int has_dos_drive_prefix(const char *path)\n+{\n+\treturn isalpha(*path) && path[1] == ':';\n+}\n+#define has_dos_drive_prefix has_dos_drive_prefix\n+\n+#define PATH_SEP ';'\n+#define PRIuMAX \"I64u\"\n+\n+/*\n+ * helpers\n+ */\n+\n+char **copy_environ(void);\n+void free_environ(char **env);\n+char **env_setenv(char **env, const char *name);\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 3ea0d91..1ee7357 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -89,7 +89,10 @@\n #include <grp.h>\n #define _ALL_SOURCE 1\n #endif\n-#endif\t/* !__MINGW32__ */\n+#else \t/* __MINGW32__ */\n+/* pull in Windows compatibility stuff */\n+#include \"compat/mingw.h\"\n+#endif\t/* __MINGW32__ */\n \n #ifndef NO_ICONV\n #include <iconv.h>\n@@ -110,6 +113,10 @@\n #define PATH_SEP ':'\n #endif\n \n+#ifndef has_dos_drive_prefix\n+#define has_dos_drive_prefix(path) 0\n+#endif\n+\n #ifdef __GNUC__\n #define NORETURN __attribute__((__noreturn__))\n #else\n@@ -369,10 +376,6 @@ static inline FILE *xfdopen(int fd, const char *mode)\n \treturn stream;\n }\n \n-#ifdef __MINGW32__\n-int mkstemp(char *template);\n-#endif\n-\n static inline int xmkstemp(char *template)\n {\n \tint fd;\n@@ -453,217 +456,4 @@ void git_qsort(void *base, size_t nmemb, size_t size,\n #define qsort git_qsort\n #endif\n \n-#ifdef __MINGW32__\n-\n-#include <winsock2.h>\n-\n-/*\n- * things that are not available in header files\n- */\n-\n-typedef int pid_t;\n-#define hstrerror strerror\n-\n-#define S_IFLNK    0120000 /* Symbolic link */\n-#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)\n-#define S_ISSOCK(x) 0\n-#define S_IRGRP 0\n-#define S_IWGRP 0\n-#define S_IXGRP 0\n-#define S_ISGID 0\n-#define S_IROTH 0\n-#define S_IXOTH 0\n-\n-#define WIFEXITED(x) ((unsigned)(x) < 259)\t/* STILL_ACTIVE */\n-#define WEXITSTATUS(x) ((x) & 0xff)\n-#define WIFSIGNALED(x) ((unsigned)(x) > 259)\n-\n-#define SIGKILL 0\n-#define SIGCHLD 0\n-#define SIGPIPE 0\n-#define SIGALRM 100\n-\n-#define F_GETFD 1\n-#define F_SETFD 2\n-#define FD_CLOEXEC 0x1\n-\n-struct passwd {\n-\tchar *pw_name;\n-\tchar *pw_gecos;\n-\tchar *pw_dir;\n-};\n-\n-struct pollfd {\n-\tint fd;           /* file descriptor */\n-\tshort events;     /* requested events */\n-\tshort revents;    /* returned events */\n-};\n-#define POLLIN 1\n-#define POLLHUP 2\n-\n-typedef void (__cdecl *sig_handler_t)(int);\n-struct sigaction {\n-\tsig_handler_t sa_handler;\n-\tunsigned sa_flags;\n-};\n-#define sigemptyset(x) (void)0\n-#define SA_RESTART 0\n-\n-struct itimerval {\n-\tstruct timeval it_value, it_interval;\n-};\n-#define ITIMER_REAL 0\n-\n-/*\n- * trivial stubs\n- */\n-\n-static inline int readlink(const char *path, char *buf, size_t bufsiz)\n-{ errno = ENOSYS; return -1; }\n-static inline int symlink(const char *oldpath, const char *newpath)\n-{ errno = ENOSYS; return -1; }\n-static inline int link(const char *oldpath, const char *newpath)\n-{ errno = ENOSYS; return -1; }\n-static inline int fchmod(int fildes, mode_t mode)\n-{ errno = ENOSYS; return -1; }\n-static inline int fork(void)\n-{ errno = ENOSYS; return -1; }\n-static inline unsigned int alarm(unsigned int seconds)\n-{ return 0; }\n-static inline int fsync(int fd)\n-{ return 0; }\n-static inline int getppid(void)\n-{ return 1; }\n-static inline void sync(void)\n-{}\n-static inline int getuid()\n-{ return 1; }\n-static inline struct passwd *getpwnam(const char *name)\n-{ return NULL; }\n-static inline int fcntl(int fd, int cmd, long arg)\n-{\n-\tif (cmd == F_GETFD || cmd == F_SETFD)\n-\t\treturn 0;\n-\terrno = EINVAL;\n-\treturn -1;\n-}\n-\n-/*\n- * simple adaptors\n- */\n-\n-static inline int mingw_mkdir(const char *path, int mode)\n-{\n-\treturn mkdir(path);\n-}\n-#define mkdir mingw_mkdir\n-\n-static inline int mingw_unlink(const char *pathname)\n-{\n-\t/* read-only files cannot be removed */\n-\tchmod(pathname, 0666);\n-\treturn unlink(pathname);\n-}\n-#define unlink mingw_unlink\n-\n-static inline int waitpid(pid_t pid, unsigned *status, unsigned options)\n-{\n-\tif (options == 0)\n-\t\treturn _cwait(status, pid, 0);\n-\terrno = EINVAL;\n-\treturn -1;\n-}\n-\n-/*\n- * implementations of missing functions\n- */\n-\n-int pipe(int filedes[2]);\n-unsigned int sleep (unsigned int seconds);\n-int gettimeofday(struct timeval *tv, void *tz);\n-int poll(struct pollfd *ufds, unsigned int nfds, int timeout);\n-struct tm *gmtime_r(const time_t *timep, struct tm *result);\n-struct tm *localtime_r(const time_t *timep, struct tm *result);\n-int getpagesize(void);\t/* defined in MinGW's libgcc.a */\n-struct passwd *getpwuid(int uid);\n-int setitimer(int type, struct itimerval *in, struct itimerval *out);\n-int sigaction(int sig, struct sigaction *in, struct sigaction *out);\n-\n-/*\n- * replacements of existing functions\n- */\n-\n-int mingw_open (const char *filename, int oflags, ...);\n-#define open mingw_open\n-\n-char *mingw_getcwd(char *pointer, int len);\n-#define getcwd mingw_getcwd\n-\n-struct hostent *mingw_gethostbyname(const char *host);\n-#define gethostbyname mingw_gethostbyname\n-\n-int mingw_socket(int domain, int type, int protocol);\n-#define socket mingw_socket\n-\n-int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);\n-#define connect mingw_connect\n-\n-int mingw_rename(const char*, const char*);\n-#define rename mingw_rename\n-\n-/* Use mingw_lstat() instead of lstat()/stat() and\n- * mingw_fstat() instead of fstat() on Windows.\n- * struct stat is redefined because it lacks the st_blocks member.\n- */\n-struct mingw_stat {\n-\tunsigned st_mode;\n-\ttime_t st_mtime, st_atime, st_ctime;\n-\tunsigned st_dev, st_ino, st_uid, st_gid;\n-\tsize_t st_size;\n-\tsize_t st_blocks;\n-};\n-int mingw_lstat(const char *file_name, struct mingw_stat *buf);\n-int mingw_fstat(int fd, struct mingw_stat *buf);\n-#define fstat mingw_fstat\n-#define lstat mingw_lstat\n-#define stat mingw_stat\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_vsnprintf(char *buf, size_t size, const char *fmt, va_list args);\n-#define vsnprintf mingw_vsnprintf\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\n-\n-static inline unsigned int git_ntohl(unsigned int x)\n-{ return (unsigned int)ntohl(x); }\n-#define ntohl git_ntohl\n-\n-sig_handler_t mingw_signal(int sig, sig_handler_t handler);\n-#define signal mingw_signal\n-\n-/*\n- * helpers\n- */\n-\n-char **copy_environ(void);\n-void free_environ(char **env);\n-char **env_setenv(char **env, const char *name);\n-\n-static inline int has_dos_drive_prefix(const char *path)\n-{\n-\treturn isalpha(*path) && path[1] == ':';\n-}\n-\n-#else /* __MINGW32__ */\n-\n-static inline int has_dos_drive_prefix(const char *path)\n-{\n-\treturn 0;\n-}\n-\n-#endif /* __MINGW32__ */\n"},{"id":"71132","messageId":"alpine.LSU.1.00.0803052317350.15786@racer.site","threadId":"12344","inReplyTo":"200803052221.12495.johannes.sixt@telecom.at","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-05T22:18:53Z","receivedAt":"2008-03-05T22:18:53Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 5 Mar 2008, Johannes Sixt wrote:\n\n> On Thursday 28 February 2008 13:05, Johannes Schindelin wrote:\n> > On Wed, 27 Feb 2008, Johannes Sixt wrote:\n> > > --- a/git-compat-util.h\n> > > +++ b/git-compat-util.h\n> > > @@ -357,6 +359,10 @@ static inline FILE *xfdopen(int fd, const char\n> > > *mode) return stream;\n> > >  }\n> > >\n> > > +#ifdef __MINGW32__\n> > > +int mkstemp(char *template);\n> > > +#endif\n> > > +\n> > >  static inline int xmkstemp(char *template)\n> > >  {\n> > >  \tint fd;\n> >\n> > Could we have this...\n> >\n> > > @@ -437,4 +443,140 @@ void git_qsort(void *base, size_t nmemb, size_t\n> > > size, #define qsort git_qsort\n> > >  #endif\n> > >\n> > > +#ifdef __MINGW32__\n> > > +\n> > > +#include <winsock2.h>\n> > > +\n> > > +/*\n> > > + * things that are not available in header files\n> > > + */\n> > > +\n> > > [...]\n> >\n> > ... and this in compat/mingw.h?  And then, we'd only have\n> >\n> > #ifdef __MINGW32__\n> > #include \"mingw.h\"\n> > #endif\n> >\n> > in git-compat-util.h?\n> \n> I've now created compat/mingw.h. Below is the interdiff. Of course, it \n> mostly only moves code around. But you might want to look at at mkstemp, \n> PATH_SEP, PRIuMAX, and has_dos_drive_prefix. Notice also that I include \n> compat/mingw.h early in git-compat-util.h instead of late.\n\nThanks!\n\nWith this, I think I have nothing to add to your series (except maybe an \nAcked-by: where it applies, or a Reviewed-by:, but I think that this \nwould only be a burden on our maintainer).\n\nCiao,\nDscho\n\n"},{"id":"71133","messageId":"7vir00lski.fsf@gitster.siamese.dyndns.org","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803052317350.15786@racer.site","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-05T22:22:21Z","receivedAt":"2008-03-05T22:22:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> Thanks!\n>\n> With this, I think I have nothing to add to your series (except maybe an \n> Acked-by: where it applies, or a Reviewed-by:, but I think that this \n> would only be a burden on our maintainer).\n\nI think Reviewed-by: would indeed be a very good addition to our\npatch flow convention, borrowing from the kernel folks.\n"},{"id":"71134","messageId":"alpine.LSU.1.00.0803052327570.15786@racer.site","threadId":"12344","inReplyTo":"7vir00lski.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-05T22:28:15Z","receivedAt":"2008-03-05T22:28:15Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 5 Mar 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > Thanks!\n> >\n> > With this, I think I have nothing to add to your series (except maybe an \n> > Acked-by: where it applies, or a Reviewed-by:, but I think that this \n> > would only be a burden on our maintainer).\n> \n> I think Reviewed-by: would indeed be a very good addition to our\n> patch flow convention, borrowing from the kernel folks.\n\nYou mean you have more people to blame, then? ;-)\n\nCiao,\nDscho\n\n"},{"id":"71139","messageId":"7v1w6olr84.fsf@gitster.siamese.dyndns.org","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803052327570.15786@racer.site","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-05T22:51:23Z","receivedAt":"2008-03-05T22:51:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n>> I think Reviewed-by: would indeed be a very good addition to our\n>> patch flow convention, borrowing from the kernel folks.\n>\n> You mean you have more people to blame, then? ;-)\n\nNo.  The procedure would help me keep my impatience from making\nme merge patches that have not been adequately reviewed on the\nlist.\n\nRecently, I ended up wasting two nights because I was not\ncareful enough earlier, when I was short of time and apparent\nbacklog was beginning to get larger and larger.\n\nI queued some patches from the backlog to 'next' saying \"ah,\nthey look good enough, people will notice breakages anyway,\" but\nthe breakage was not caught until 'master' got broken.\n\nNot good.  And the list is not to blame.\n\nBy merging to 'next' I am sending a message that I think they\nhave been adequately reviewed (either by me or by people whose\njudgement I trust), so I shouldn't have applied them to 'next'\nin the first place.  I instead should have ignored them, and\nwaited until I had enough time and concentration to properly\nreview them.  Or until somebody else did --- by that time,\nhopefully other people might have commented on them, saying\n\"these look all ok to me\", or \"ah that's crap\".\n\nThese wasted two nights was all my fault, and as a result, there\nare more patches on the list archive that I have seen (notice I\ndid not say \"have read\") that are unapplied.\n\nAs to those \"more patches on the list that are unapplied\", I'll\nkeep them unapplied for now, until there are positive feedbacks\non them.\n\nThe positive feedback may come from myself.  I am not saying I\nwill stop reviewing and/or applying patches nobody else\ncommented on.\n"},{"id":"71153","messageId":"alpine.LSU.1.00.0803060105250.15786@racer.site","threadId":"12344","inReplyTo":"7v1w6olr84.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-06T00:11:16Z","receivedAt":"2008-03-06T00:11:16Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 5 Mar 2008, Junio C Hamano wrote:\n\n> Recently, I ended up wasting two nights because I was not careful enough \n> earlier, when I was short of time and apparent backlog was beginning to \n> get larger and larger.\n> \n> I queued some patches from the backlog to 'next' saying \"ah, they look \n> good enough, people will notice breakages anyway,\" but the breakage was \n> not caught until 'master' got broken.\n> \n> Not good.  And the list is not to blame.\n\nAh, but I think that you are too harsh onto yourself.  Recently, there was \na surge of patches, mainly because 1.5.4 was held of -- but for a good \nreason: 1.5.4 was not ready before the point in time where you decided to \nrelease it.\n\nIf at all, the list is to blame, for just sending patches, but not \nreviewing them.\n\nNow, personally I know that I am not half as good a reviewer as you are, \nsince you catch way more bugs than me, just by looking at the patch.\n\nBut still, \"many eyes make bugs shallow\" is a principle to be heeded \n_everywhere_.\n\nSo I'd say: if you think that you are short of time, and patches have not \nbeen reviewed properly, do not assume it _your sole_ responsibility to \nreview the patches.  Make it known that other people have to step in (even \nif it is a mediocre reviewer like me).  Do not overload yourself.\n\nSo my comment about the \"blame\" was really tongue-in-cheek.  Please do not \ntake it for anything but a joke.\n\nAnd when I say that I think you are a kick-ass maintainer, I _mean_ it.\n\n'nuff said,\nDscho\n"},{"id":"71159","messageId":"alpine.LSU.1.00.0803060212170.15786@racer.site","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803052327570.15786@racer.site","subject":"[PATCH 1/2] Add strbuf_initf()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-06T01:14:43Z","receivedAt":"2008-03-06T01:14:43Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThe most common use of addf() was to init a strbuf and addf() right away.\nSince it is so common, it makes sense to have a function strbuf_initf()\nto wrap both calls into one.\n\nUnfortunately, C (and cpp) has no way to make this easy without code\nduplication, as we need to va_init() in strbuf_addf() possibly a few\ntimes.  So the code for addf() is copied.  Fortunately, the code is\npretty short, so not too much had to be copied as-is.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tOn Wed, 5 Mar 2008, Johannes Schindelin wrote:\n\n\t> On Wed, 5 Mar 2008, Junio C Hamano wrote:\n\t> \n\t> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\t> > \n\t> > > [... I'd submit my ] a Reviewed-by:, but I think that this \n\t> > > would only be a burden on our maintainer.\n\t> > \n\t> > I think Reviewed-by: would indeed be a very good addition to \n\t> > our patch flow convention, borrowing from the kernel folks.\n\t> \n\t> You mean you have more people to blame, then? ;-)\n\n\tWell, it was meant as a joke...\n\n\tAnyway, here is a start of a patch series that should help the \n\tKing Penguin...\n\n\tstrbuf_initf() is something I long planned to do; Kristian just \n\tpushed me over the edge.\n\n strbuf.c |   23 +++++++++++++++++++++++\n strbuf.h |    2 ++\n 2 files changed, 25 insertions(+), 0 deletions(-)\n\ndiff --git a/strbuf.c b/strbuf.c\nindex 5afa8f3..067d55a 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -147,6 +147,29 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)\n \tstrbuf_setlen(sb, sb->len + len);\n }\n \n+void strbuf_initf(struct strbuf *sb, const char *fmt, ...)\n+{\n+\tint len;\n+\tva_list ap;\n+\n+\tstrbuf_init(sb, strlen(fmt) + 64);\n+\tva_start(ap, fmt);\n+\tlen = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);\n+\tva_end(ap);\n+\tif (len < 0)\n+\t\tdie(\"your vsnprintf is broken\");\n+\tif (len > strbuf_avail(sb)) {\n+\t\tstrbuf_grow(sb, len);\n+\t\tva_start(ap, fmt);\n+\t\tlen = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);\n+\t\tva_end(ap);\n+\t\tif (len > strbuf_avail(sb)) {\n+\t\t\tdie(\"this should not happen, your snprintf is broken\");\n+\t\t}\n+\t}\n+\tstrbuf_setlen(sb, sb->len + len);\n+}\n+\n void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,\n \t\t   void *context)\n {\ndiff --git a/strbuf.h b/strbuf.h\nindex faec229..eaf2409 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -108,6 +108,8 @@ extern void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,\n \n __attribute__((format(printf,2,3)))\n extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);\n+__attribute__((format(printf,2,3)))\n+extern void strbuf_initf(struct strbuf *sb, const char *fmt, ...);\n \n extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);\n /* XXX: if read fails, any partial read is undone */\n-- \n1.5.4.3.571.g9aec3\n\n"},{"id":"71160","messageId":"alpine.LSU.1.00.0803060214520.15786@racer.site","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803052327570.15786@racer.site","subject":"[PATCH 2/2] format-patch: add --reviewed-by=<ident>","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-06T01:15:24Z","receivedAt":"2008-03-06T01:15:24Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nNow you can conveniently add lines with format-patch, adding missing\nReviewed-by: lines (if it is already present at the end of the commit\nmessage, it will not be repeated).\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tAnd this is the actual patch...\n\n\tIt is just a patch for format-patch... the patch for git-am should \n\tbe trivial.\n\n Documentation/git-format-patch.txt |    5 ++++\n builtin-log.c                      |    9 +++++++\n log-tree.c                         |   44 +++++++++++++++++++++++++++++++++++-\n revision.h                         |    1 +\n t/t4014-format-patch.sh            |   26 +++++++++++++++++++++\n 5 files changed, 84 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex b5207b7..da52720 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -11,6 +11,7 @@ SYNOPSIS\n [verse]\n 'git-format-patch' [-k] [-o <dir> | --stdout] [--thread]\n \t\t   [--attach[=<boundary>] | --inline[=<boundary>]]\n+\t\t   [--reviewed-by=<ident>]\n \t\t   [-s | --signoff] [<common diff options>]\n \t\t   [-n | --numbered | -N | --no-numbered]\n \t\t   [--start-number <n>] [--numbered-files]\n@@ -96,6 +97,10 @@ include::diff-options.txt[]\n \tDo not strip/add '[PATCH]' from the first line of the\n \tcommit log message.\n \n+--reviewed-by=<ident>::\n+\tAdd `Reviewed-by:` line to the commit message, using\n+\tthe given identity.\n+\n -s|--signoff::\n \tAdd `Signed-off-by:` line to the commit message, using\n \tthe committer identity of yourself.\ndiff --git a/builtin-log.c b/builtin-log.c\nindex fe8fc6f..90573b3 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -753,6 +753,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \tconst char *in_reply_to = NULL;\n \tstruct patch_ids ids;\n \tchar *add_signoff = NULL;\n+\tstruct path_list add_reviewed_by = { NULL, 0, 0, 0 };\n \tstruct strbuf buf;\n \n \tgit_config(git_format_config);\n@@ -821,6 +822,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t\t\tdie(\"bogos committer info %s\\n\", committer);\n \t\t\tadd_signoff = xmemdupz(committer, endpos - committer + 1);\n \t\t}\n+\t\telse if (!prefixcmp(argv[i], \"--reviewed-by=\")) {\n+\t\t\tstruct strbuf buf;\n+\n+\t\t\tstrbuf_initf(&buf, \"Reviewed-by: %s\", argv[i] + 14);\n+\t\t\tpath_list_append(strbuf_detach(&buf, NULL),\n+\t\t\t\t\t&add_reviewed_by);\n+\t\t}\n \t\telse if (!strcmp(argv[i], \"--attach\")) {\n \t\t\trev.mime_boundary = git_version_string;\n \t\t\trev.no_inline = 1;\n@@ -994,6 +1002,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tstart_number--;\n \t}\n \trev.add_signoff = add_signoff;\n+\trev.add_reviewed_by = &add_reviewed_by;\n \twhile (0 <= --nr) {\n \t\tint shown;\n \t\tcommit = list[nr];\ndiff --git a/log-tree.c b/log-tree.c\nindex 608f697..36621ab 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -3,6 +3,7 @@\n #include \"commit.h\"\n #include \"log-tree.h\"\n #include \"reflog-walk.h\"\n+#include \"path-list.h\"\n \n struct decoration name_decoration = { \"object names\" };\n \n@@ -79,6 +80,34 @@ static int detect_any_signoff(char *letter, int size)\n \treturn seen_head && seen_name;\n }\n \n+static void append_reviewed_by(struct strbuf *sb, struct path_list *reviewed)\n+{\n+\tstruct path_list already_reviewed = { NULL, 0, 0, 0 };\n+\tint i, eol = sb->len + 1;\n+\n+\t/* find the last Reviewed-by: lines */\n+\tfor (i = eol - 2; i > 0; i--)\n+\t\tif (i == 0 || sb->buf[i - 1] == '\\n') {\n+\t\t\tif (!prefixcmp(sb->buf + i, \"Reviewed-by:\"))\n+\t\t\t\tpath_list_insert(xstrndup(sb->buf + i,\n+\t\t\t\t\t\t\teol - i - 1),\n+\t\t\t\t\t\t&already_reviewed);\n+\t\t\telse if (eol - i > 1)\n+\t\t\t\tbreak;\n+\t\t\teol = i;\n+\t\t}\n+\n+\tfor (i = 0; i < reviewed->nr; i++) {\n+\t\tconst char *line = reviewed->items[i].path;\n+\t\tif (!path_list_has_path(&already_reviewed, line))\n+\t\t\tstrbuf_addf(sb, \"%s\\n\", line);\n+\t}\n+\n+\t/* all strings were xstrndup()ed, clean them up */\n+\talready_reviewed.strdup_paths = 1;\n+\tpath_list_clear(&already_reviewed, 0);\n+}\n+\n static void append_signoff(struct strbuf *sb, const char *signoff)\n {\n \tstatic const char signed_off_by[] = \"Signed-off-by: \";\n@@ -137,6 +166,16 @@ static int has_non_ascii(const char *s)\n \treturn 0;\n }\n \n+static int path_list_has_non_ascii(struct path_list *list)\n+{\n+\tint i;\n+\n+\tfor (i = 0; list && i < list->nr; i++)\n+\t\tif (has_non_ascii(list->items[i].path))\n+\t\t\treturn 1;\n+\treturn 0;\n+}\n+\n void log_write_email_headers(struct rev_info *opt, const char *name,\n \t\t\t     const char **subject_p, const char **extra_headers_p)\n {\n@@ -301,8 +340,11 @@ void show_log(struct rev_info *opt, const char *sep)\n \tstrbuf_init(&msgbuf, 0);\n \tpretty_print_commit(opt->commit_format, commit, &msgbuf,\n \t\t\t    abbrev, subject, extra_headers, opt->date_mode,\n-\t\t\t    has_non_ascii(opt->add_signoff));\n+\t\t\t    has_non_ascii(opt->add_signoff) ||\n+\t\t\t    path_list_has_non_ascii(opt->add_reviewed_by));\n \n+\tif (opt->add_reviewed_by && opt->add_reviewed_by->nr)\n+\t\tappend_reviewed_by(&msgbuf, opt->add_reviewed_by);\n \tif (opt->add_signoff)\n \t\tappend_signoff(&msgbuf, opt->add_signoff);\n \tif (opt->show_log_size)\ndiff --git a/revision.h b/revision.h\nindex c8b3b94..eb4cc3b 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -78,6 +78,7 @@ struct rev_info {\n \tchar\t\t*message_id;\n \tconst char\t*ref_message_id;\n \tconst char\t*add_signoff;\n+\tstruct path_list *add_reviewed_by;\n \tconst char\t*extra_headers;\n \tconst char\t*log_reencode;\n \tconst char\t*subject_prefix;\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex b2b7a8d..e2ff94f 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -230,4 +230,30 @@ test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n \n '\n \n+cat > expect << EOF\n+\n+Reviewed-by: Ken Robinson\n+\n+Reviewed-by: Sergey Rachmaninov\n+\n+Reviewed-by: Ronny O Sullivan\n+Reviewed-by: Mickey Mouse\n+Reviewed-by: Mahatma Gandhi\n+EOF\n+\n+test_expect_success '--reviewed-by' '\n+\n+\techo reviewed > foo &&\n+\ttest_tick &&\n+\tgit commit -m \"Reviewed\" -m \"Reviewed-by: Ken Robinson\" \\\n+\t\t-m \"Reviewed-by: Sergey Rachmaninov\" \\\n+\t\t-m \"Reviewed-by: Ronny O Sullivan\" foo &&\n+\tgit format-patch --reviewed-by=\"Mickey Mouse\" \\\n+\t\t--reviewed-by=\"Sergey Rachmaninov\" \\\n+\t\t--reviewed-by=\"Mahatma Gandhi\" -1 HEAD &&\n+\tsed -e \"1,/^Cc: /d\" -e \"/^---/,\\$d\" < 0001-Reviewed.patch > output &&\n+\tgit diff expect output\n+\n+'\n+\n test_done\n-- \n1.5.4.3.571.g9aec3\n\n\n"},{"id":"71169","messageId":"7v8x0wh8x7.fsf@gitster.siamese.dyndns.org","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803060214520.15786@racer.site","subject":"Re: [PATCH 2/2] format-patch: add --reviewed-by=<ident>","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-06T02:40:20Z","receivedAt":"2008-03-06T02:40:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n>  'git-format-patch' [-k] [-o <dir> | --stdout] [--thread]\n>  \t\t   [--attach[=<boundary>] | --inline[=<boundary>]]\n> +\t\t   [--reviewed-by=<ident>]\n>  \t\t   [-s | --signoff] [<common diff options>]\n>  \t\t   [-n | --numbered | -N | --no-numbered]\n>  \t\t   [--start-number <n>] [--numbered-files]\n\nWhat's the expected workflow this patch intends to help?\n\n - You see a patch by somebody, you look at it deeply, you apply to your\n   tree (presumably with your own Signed-off-by).\n\n - You inspect the result further, and decide it is good.\n\n - You format-patch with the option, which would now have a Reviewed-by:\n   too.\n\n - You send it out.\n\nIf so, it might make sense to simply always use the committer ident.\n\nIf the person who adds the reviewed-by is trusted so much that her\nreviewed-by counts, the commits might even be transfered with \"Please\npull\".  In such a case, the workflow might become:\n\n - You see a patch by somebody, you look at it deeply, you apply to your\n   tree (presumably with your own Signed-off-by).\n\n - You inspect the result further, and decide it is good.\n\n - You run \"rebase --add-reviewed-by\" to prepare a series on a branch to\n   be pulled from.\n\n - You send a request-pull.\n\nIn that workflow, it would also make sense to use the committer ident.\n\nI am trying to come up with a plausible workflow that wants to add\nsomebody else's reviewed-by.\n\n - You send out your patch to the list.  People give comments, you reroll,\n   you get more comments, eventually people say \"Ah, that's good, Ack.\"\n   and/or \"I am not the primary person who knows this area, but I reviewed\n   it and I know my reviewed-by would count, so here is my Ok\".\n\n - You format-patch the final version, with Acked-by and Reviewed-by\n   adding other people's names.\n\nThen I think it makes sense to take names of other people if that is the\ncase.\n\nYou probably meant that that is the expected workflow, as you can give\nmore than one of these options.\n\nBut people who read the documentation should not have to guess.\n\n> diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\n> index b2b7a8d..e2ff94f 100755\n> --- a/t/t4014-format-patch.sh\n> +++ b/t/t4014-format-patch.sh\n> @@ -230,4 +230,30 @@ test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n>  \n>  '\n>  \n> +cat > expect << EOF\n> +\n> +Reviewed-by: Ken Robinson\n> +\n> +Reviewed-by: Sergey Rachmaninov\n> +\n> +Reviewed-by: Ronny O Sullivan\n> +Reviewed-by: Mickey Mouse\n> +Reviewed-by: Mahatma Gandhi\n> +EOF\n> +\n> +test_expect_success '--reviewed-by' '\n> +\n> +\techo reviewed > foo &&\n> +\ttest_tick &&\n> +\tgit commit -m \"Reviewed\" -m \"Reviewed-by: Ken Robinson\" \\\n> +\t\t-m \"Reviewed-by: Sergey Rachmaninov\" \\\n> +\t\t-m \"Reviewed-by: Ronny O Sullivan\" foo &&\n> +\tgit format-patch --reviewed-by=\"Mickey Mouse\" \\\n> +\t\t--reviewed-by=\"Sergey Rachmaninov\" \\\n> +\t\t--reviewed-by=\"Mahatma Gandhi\" -1 HEAD &&\n> +\tsed -e \"1,/^Cc: /d\" -e \"/^---/,\\$d\" < 0001-Reviewed.patch > output &&\n> +\tgit diff expect output\n> +\n> +'\n\nWhy not use a single -m for the first three reviewed-bys, instead of\nmaking them into separate paragraphs using multiple -m?\n\n"},{"id":"71199","messageId":"20080306063331.GA7325@glandium.org","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803060212170.15786@racer.site","subject":"Re: [PATCH 1/2] Add strbuf_initf()","fromName":"Mike Hommey","fromEmail":"mh@glandium.org","sentAt":"2008-03-06T06:33:31Z","receivedAt":"2008-03-06T06:33:31Z","isPatch":true,"sender":{"key":"mh@glandium.org","avatar":"https://avatars.githubusercontent.com/u/1038527?v=4"},"body":"On Thu, Mar 06, 2008 at 02:14:43AM +0100, Johannes Schindelin wrote:\n> \n> The most common use of addf() was to init a strbuf and addf() right away.\n> Since it is so common, it makes sense to have a function strbuf_initf()\n> to wrap both calls into one.\n> \n> Unfortunately, C (and cpp) has no way to make this easy without code\n> duplication, as we need to va_init() in strbuf_addf() possibly a few\n> times.  So the code for addf() is copied.  Fortunately, the code is\n> pretty short, so not too much had to be copied as-is.\n\nThe problem with code duplication is not about code size, but more about\nnot forgetting to fix bugs in all incarnations of the duplicated code.\n\nIs it so ugly to use a macro ?\n\nMike\n"},{"id":"71212","messageId":"3f4fd2640803060103i7fce7578ka40b5b4cc23a577f@mail.gmail.com","threadId":"12344","inReplyTo":"20080306063331.GA7325@glandium.org","subject":"Re: [PATCH 1/2] Add strbuf_initf()","fromName":"Reece Dunn","fromEmail":"msclrhd@googlemail.com","sentAt":"2008-03-06T09:03:31Z","receivedAt":"2008-03-06T09:03:31Z","isPatch":true,"sender":{"key":"msclrhd@googlemail.com","avatar":null},"body":"On 06/03/2008, Mike Hommey <mh@glandium.org> wrote:\n> On Thu, Mar 06, 2008 at 02:14:43AM +0100, Johannes Schindelin wrote:\n>  >\n>  > The most common use of addf() was to init a strbuf and addf() right away.\n>  > Since it is so common, it makes sense to have a function strbuf_initf()\n>  > to wrap both calls into one.\n>  >\n>  > Unfortunately, C (and cpp) has no way to make this easy without code\n>  > duplication, as we need to va_init() in strbuf_addf() possibly a few\n>  > times.  So the code for addf() is copied.  Fortunately, the code is\n>  > pretty short, so not too much had to be copied as-is.\n>\n>\n> The problem with code duplication is not about code size, but more about\n>  not forgetting to fix bugs in all incarnations of the duplicated code.\n>\n>  Is it so ugly to use a macro ?\n\nWhy not have a strbuf_vaddf and strbuf_vinitf that take a va_arg as a\nparameter. This would mean that you don't have code duplication, and\nit is flexible enough if you want to add more customisations in the\nfuture. No macro needed. This is what the printf/scanf family of\nfunctions do.\n\n- Reece\n"},{"id":"71219","messageId":"alpine.LSU.1.00.0803061130460.15786@racer.site","threadId":"12344","inReplyTo":"7v8x0wh8x7.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 2/2] format-patch: add --reviewed-by=<ident>","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-06T10:40:32Z","receivedAt":"2008-03-06T10:40:32Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 5 Mar 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> >  'git-format-patch' [-k] [-o <dir> | --stdout] [--thread]\n> >  \t\t   [--attach[=<boundary>] | --inline[=<boundary>]]\n> > +\t\t   [--reviewed-by=<ident>]\n> >  \t\t   [-s | --signoff] [<common diff options>]\n> >  \t\t   [-n | --numbered | -N | --no-numbered]\n> >  \t\t   [--start-number <n>] [--numbered-files]\n> \n> What's the expected workflow this patch intends to help?\n> \n> [...]\n>\n> I am trying to come up with a plausible workflow that wants to add \n> somebody else's reviewed-by.\n> \n>  - You send out your patch to the list.  People give comments, you \n>    reroll, you get more comments, eventually people say \"Ah, that's \n>    good, Ack.\"  and/or \"I am not the primary person who knows this area, \n>    but I reviewed it and I know my reviewed-by would count, so here is \n>    my Ok\".\n> \n>  - You format-patch the final version, with Acked-by and Reviewed-by \n>    adding other people's names.\n> \n> Then I think it makes sense to take names of other people if that is the\n> case.\n\nYes, exactly.  That was the usage I had in mind.\n\nThe problem with the two others you suggested (basically that the reviewer \nherself sends out another patch series) is a little fragile, since a \nmalicous reviewer could add/modify code, but for nice reviewers, it is \nbetter in that you know which code was reviewed.\n\nSo I'd rather have it not resent by the reviewer as a patch series, but I \nthink that pulling it is fine, since it is much easier to verify (with log \n--cherry-pick) that no code was tampered with by the reviewer.\n\n> You probably meant that that is the expected workflow, as you can give \n> more than one of these options.\n> \n> But people who read the documentation should not have to guess.\n\nFrankly, I did not make up my mind on the other workflows, I only wanted \nto make the maintainer's life (yours) easier.\n\nI have no problem posting several revisions of this patch, or scrap it \naltogether... as somebody recently said, we even joke around here via \npatches ;-)\n\n> > diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\n> > index b2b7a8d..e2ff94f 100755\n> > --- a/t/t4014-format-patch.sh\n> > +++ b/t/t4014-format-patch.sh\n> > @@ -230,4 +230,30 @@ test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n> >  \n> >  '\n> >  \n> > +cat > expect << EOF\n> > +\n> > +Reviewed-by: Ken Robinson\n> > +\n> > +Reviewed-by: Sergey Rachmaninov\n> > +\n> > +Reviewed-by: Ronny O Sullivan\n> > +Reviewed-by: Mickey Mouse\n> > +Reviewed-by: Mahatma Gandhi\n> > +EOF\n> > +\n> > +test_expect_success '--reviewed-by' '\n> > +\n> > +\techo reviewed > foo &&\n> > +\ttest_tick &&\n> > +\tgit commit -m \"Reviewed\" -m \"Reviewed-by: Ken Robinson\" \\\n> > +\t\t-m \"Reviewed-by: Sergey Rachmaninov\" \\\n> > +\t\t-m \"Reviewed-by: Ronny O Sullivan\" foo &&\n> > +\tgit format-patch --reviewed-by=\"Mickey Mouse\" \\\n> > +\t\t--reviewed-by=\"Sergey Rachmaninov\" \\\n> > +\t\t--reviewed-by=\"Mahatma Gandhi\" -1 HEAD &&\n> > +\tsed -e \"1,/^Cc: /d\" -e \"/^---/,\\$d\" < 0001-Reviewed.patch > output &&\n> > +\tgit diff expect output\n> > +\n> > +'\n> \n> Why not use a single -m for the first three reviewed-bys, instead of\n> making them into separate paragraphs using multiple -m?\n\nI am always unsure how to embed newlines in strings in a shell script \n(except with single-ticks), and besides, I do not like breaking the \nindentation.  But I could make it a temporary file... Hmm?\n\nCiao,\nDscho\n\n"},{"id":"71225","messageId":"alpine.LSU.1.00.0803061148180.15786@racer.site","threadId":"12344","inReplyTo":"20080306063331.GA7325@glandium.org","subject":"Re: [PATCH 1/2] Add strbuf_initf()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-06T10:53:28Z","receivedAt":"2008-03-06T10:53:28Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 6 Mar 2008, Mike Hommey wrote:\n\n> On Thu, Mar 06, 2008 at 02:14:43AM +0100, Johannes Schindelin wrote:\n> > \n> > The most common use of addf() was to init a strbuf and addf() right \n> > away. Since it is so common, it makes sense to have a function \n> > strbuf_initf() to wrap both calls into one.\n> > \n> > Unfortunately, C (and cpp) has no way to make this easy without code \n> > duplication, as we need to va_init() in strbuf_addf() possibly a few \n> > times.  So the code for addf() is copied.  Fortunately, the code is \n> > pretty short, so not too much had to be copied as-is.\n> \n> The problem with code duplication is not about code size, but more about \n> not forgetting to fix bugs in all incarnations of the duplicated code.\n\nYes, I know.\n\n> Is it so ugly to use a macro ?\n\nAFAIR it is unportable to have a macro\n\n#define strbuf_initf(buf, fmt, ...) \\\n\t(strbuf_init(buf, strlen(fmt) + 64), strbuf_addf(buf, fmt, args);) \n\n(GNU cpp groks it, but what about the others?)\n\nOr you mean the whole body of the implementation of strbuf_addf()?  Now, \n_that_ would be ugly.\n\nCiao,\nDscho\n\n"},{"id":"71226","messageId":"alpine.LSU.1.00.0803061153400.15786@racer.site","threadId":"12344","inReplyTo":"3f4fd2640803060103i7fce7578ka40b5b4cc23a577f@mail.gmail.com","subject":"Re: [PATCH 1/2] Add strbuf_initf()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-06T10:55:05Z","receivedAt":"2008-03-06T10:55:05Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 6 Mar 2008, Reece Dunn wrote:\n\n> On 06/03/2008, Mike Hommey <mh@glandium.org> wrote:\n> > On Thu, Mar 06, 2008 at 02:14:43AM +0100, Johannes Schindelin wrote:\n> >  >\n> >  > The most common use of addf() was to init a strbuf and addf() right \n> >  > away. Since it is so common, it makes sense to have a function \n> >  > strbuf_initf() to wrap both calls into one.\n> >  >\n> >  > Unfortunately, C (and cpp) has no way to make this easy without \n> >  > code duplication, as we need to va_init() in strbuf_addf() possibly \n> >  > a few times.  So the code for addf() is copied.  Fortunately, the \n> >  > code is pretty short, so not too much had to be copied as-is.\n> >\n> >\n> > The problem with code duplication is not about code size, but more \n> > about not forgetting to fix bugs in all incarnations of the duplicated \n> > code.\n> >\n> > Is it so ugly to use a macro ?\n> \n> Why not have a strbuf_vaddf and strbuf_vinitf that take a va_arg as a \n> parameter. This would mean that you don't have code duplication, and it \n> is flexible enough if you want to add more customisations in the future. \n> No macro needed. This is what the printf/scanf family of functions do.\n\nThe problem is that we have to restart va_list() if the buffer was too \nsmall.\n\nSo your suggestion is out, unless you suggest to implement the whole \nprintf mechanism... which I hope you're not.\n\nCiao,\nDscho\n\n"},{"id":"71238","messageId":"3f4fd2640803060353w70651522w4b3896b8106b01c0@mail.gmail.com","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803061153400.15786@racer.site","subject":"Re: [PATCH 1/2] Add strbuf_initf()","fromName":"Reece Dunn","fromEmail":"msclrhd@googlemail.com","sentAt":"2008-03-06T11:53:50Z","receivedAt":"2008-03-06T11:53:50Z","isPatch":true,"sender":{"key":"msclrhd@googlemail.com","avatar":null},"body":"On 06/03/2008, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n>\n>  On Thu, 6 Mar 2008, Reece Dunn wrote:\n>\n>  > On 06/03/2008, Mike Hommey <mh@glandium.org> wrote:\n>  > > On Thu, Mar 06, 2008 at 02:14:43AM +0100, Johannes Schindelin wrote:\n>  > >  >\n>  > >  > The most common use of addf() was to init a strbuf and addf() right\n>  > >  > away. Since it is so common, it makes sense to have a function\n>  > >  > strbuf_initf() to wrap both calls into one.\n>  > >  >\n>  > >  > Unfortunately, C (and cpp) has no way to make this easy without\n>  > >  > code duplication, as we need to va_init() in strbuf_addf() possibly\n>  > >  > a few times.  So the code for addf() is copied.  Fortunately, the\n>  > >  > code is pretty short, so not too much had to be copied as-is.\n>  > >\n>  > >\n>  > > The problem with code duplication is not about code size, but more\n>  > > about not forgetting to fix bugs in all incarnations of the duplicated\n>  > > code.\n>  > >\n>  > > Is it so ugly to use a macro ?\n>  >\n>  > Why not have a strbuf_vaddf and strbuf_vinitf that take a va_arg as a\n>  > parameter. This would mean that you don't have code duplication, and it\n>  > is flexible enough if you want to add more customisations in the future.\n>  > No macro needed. This is what the printf/scanf family of functions do.\n>\n>\n> The problem is that we have to restart va_list() if the buffer was too\n>  small.\n\nOk.\n\n>  So your suggestion is out, unless you suggest to implement the whole\n>  printf mechanism... which I hope you're not.\n\nNo, that was not my intention. My intention was that they were simple\nforwarding functions that handled the va_start and va_end calls.\n\nIs it possible to pass a void * to a strbuf_vaddf function that you\ncan pass to va_start, so you can then restart the va_list?\n\n- Reece\n"},{"id":"71240","messageId":"20080306120909.GA7518@sigill.intra.peff.net","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803061148180.15786@racer.site","subject":"Re: [PATCH 1/2] Add strbuf_initf()","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-06T12:09:10Z","receivedAt":"2008-03-06T12:09:10Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 06, 2008 at 11:53:28AM +0100, Johannes Schindelin wrote:\n\n> AFAIR it is unportable to have a macro\n> \n> #define strbuf_initf(buf, fmt, ...) \\\n> \t(strbuf_init(buf, strlen(fmt) + 64), strbuf_addf(buf, fmt, args);) \n> \n> (GNU cpp groks it, but what about the others?)\n\nC99 has variable-argument macros, but C89 does not. I have no idea in\npractice how many of the compilers git targets support them (in one form\nor another).\n\n-Peff\n"},{"id":"71246","messageId":"alpine.LSU.1.00.0803061319590.15786@racer.site","threadId":"12344","inReplyTo":"3f4fd2640803060353w70651522w4b3896b8106b01c0@mail.gmail.com","subject":"Re: [PATCH 1/2] Add strbuf_initf()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-06T12:52:57Z","receivedAt":"2008-03-06T12:52:57Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 6 Mar 2008, Reece Dunn wrote:\n\n> On 06/03/2008, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n>\n> >  On Thu, 6 Mar 2008, Reece Dunn wrote:\n> >\n> >  > On 06/03/2008, Mike Hommey <mh@glandium.org> wrote:\n> >  > > On Thu, Mar 06, 2008 at 02:14:43AM +0100, Johannes Schindelin wrote:\n> >  > >  >\n> >  > >  > The most common use of addf() was to init a strbuf and addf() \n> >  > >  > right away. Since it is so common, it makes sense to have a \n> >  > >  > function strbuf_initf() to wrap both calls into one.\n> >  > >  >\n> >  > >  > Unfortunately, C (and cpp) has no way to make this easy \n> >  > >  > without code duplication, as we need to va_init() in \n> >  > >  > strbuf_addf() possibly a few times.  So the code for addf() is \n> >  > >  > copied.  Fortunately, the code is pretty short, so not too \n> >  > >  > much had to be copied as-is.\n> >  >\n> >  > Why not have a strbuf_vaddf and strbuf_vinitf that take a va_arg as \n> >  > a parameter. This would mean that you don't have code duplication, \n> >  > and it is flexible enough if you want to add more customisations in \n> >  > the future. No macro needed. This is what the printf/scanf family \n> >  > of functions do.\n> \n> Is it possible to pass a void * to a strbuf_vaddf function that you can \n> pass to va_start, so you can then restart the va_list?\n\nAFAIU va_list() works on the stack (on less register-challenged systems \nthan x86, the first parameters are possibly passed as registers, too, but \nit has to resort to the stack at a certain number of parameters).\n\nSince the stack is also used (at least on register-challenged yadda yadda) \nto store the return address, va_list() would most likely pick that up, \ntoo.\n\nNow, that just _might_ still work, since the printf() family determines \nthe number of arguments from the format string.\n\nBut then there are machines which are _not_ completely stack-based, for \nexample SPARC.  IIRC the first 8 parameters are passed by a so-called \nregister window, which changes with each function call.\n\nSo no, I think there is no portable way to pass them around.\n\nOf course, having a simple implementation for addf() _not_ using \nvsnprintf() could help, too (and make the process more efficient, \nprobably).\n\nI thought.\n\nThe formats we'd have to support are:\n\n$ git grep strbuf_addf |\n\tsed -e 's/^[^\"]*\"\\([^\"]*\\)\".*$/\\1/' -e 's/%%//g' -e 's/%/\\\n&/g' | sed -n -e 's/\\(%[^a-zA-Z]*[a-zA-Z]\\).*/\\1/p' | sort | uniq\n\n%02X\n%06o\n%c\n%d\n%l\n%o\n%s\n%.*s\n%u\n\nSo it does not look too bad.  'X', 'o', 'd', 'l' and 'u', possibly with a \nsize specifier (left 0-padded), 'c' and 's' (possibly with a length \nparameter).\n\nThe implementation wouldn't be _too_ short, I'd say, but doable.\n\nCiao,\nDscho\n\n"},{"id":"71252","messageId":"alpine.LSU.1.00.0803061727120.3941@racer.site","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803061319590.15786@racer.site","subject":"[PATCH 1/2 v2] Add strbuf_vaddf(), use it in strbuf_addf(), and add strbuf_initf()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-06T16:29:50Z","receivedAt":"2008-03-06T16:29:50Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThe most common use of addf() was to init a strbuf and addf() right away.\nSince it is so common, it makes sense to have a function strbuf_initf() to\nwrap both calls into one.\n\nTo do that, we implement a (really minimal) vaddf() lookalike to\nvsprintf().\n\nAt the moment, it only handles %u, %i, %d, %l, %o, %x and %X with size\nindicators '<number>', ' <number>' and '0<number>', as well as %c and %s,\nthe latter with size indicators '.*' in addition to the same size\nindicators as for numbers.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tOn Thu, 6 Mar 2008, Johannes Schindelin wrote:\n\n\t> Of course, having a simple implementation for addf() _not_ using \n\t> vsnprintf() could help, too (and make the process more efficient, \n\t> probably).\n\n\tHaving thought about this a bit, I came up with this \n\timplementation (replacing my earlier PATCH 1/2).  It is by far not \n\tcomplete, but that is exactly the idea: we do not _need_ a fully-fledged \n\tprintf() implementation.\n\n\tBesides, it was fun.\n\n .gitignore       |    1 +\n Makefile         |    4 +-\n strbuf.c         |  134 +++++++++++++++++++++++++++++++++++++++++++++++------\n strbuf.h         |    3 +\n t/t0000-basic.sh |    8 +++\n test-strbuf.c    |   17 +++++++\n 6 files changed, 150 insertions(+), 17 deletions(-)\n create mode 100644 test-strbuf.c\n\ndiff --git a/.gitignore b/.gitignore\nindex 219759f..c0ecd41 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -152,6 +152,7 @@ test-genrandom\n test-match-trees\n test-parse-options\n test-sha1\n+test-strbuf\n common-cmds.h\n *.tar.gz\n *.dsc\ndiff --git a/Makefile b/Makefile\nindex cd0b294..58f6238 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1052,7 +1052,7 @@ endif\n \n ### Testing rules\n \n-TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X\n+TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X test-strbuf$X\n \n all:: $(TEST_PROGRAMS)\n \n@@ -1071,6 +1071,8 @@ test-delta$X: diff-delta.o patch-delta.o\n \n test-parse-options$X: parse-options.o\n \n+test-strbuf$X: strbuf.o\n+\n .PRECIOUS: $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))\n \n test-%$X: test-%.o $(GITLIBS)\ndiff --git a/strbuf.c b/strbuf.c\nindex 5afa8f3..5ad89a8 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -123,28 +123,130 @@ void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)\n \tstrbuf_setlen(sb, sb->len + len);\n }\n \n+static int number_length(unsigned long number, long base)\n+{\n+\tint length = 1;\n+\twhile (number >= base) {\n+\t\tnumber /= base;\n+\t\tlength++;\n+\t}\n+\treturn length;\n+}\n+\n+/*\n+ * Only supports %u, %i, %d, %l, %o, %x and %X with size indicators\n+ *   '<number>', '0<number>', and ' <number>',\n+ * as well as %c,\n+ * and %s with size indicators '<number>', ' <number>' and '.*'.\n+ */\n+void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)\n+{\n+\twhile (*fmt) {\n+\t\tchar fill = '\\0';\n+\t\tint size = -1, max_size = -1;\n+\t\tchar *p = (char *)fmt;\n+\n+\t\tif (*p != '%' || *(++p) == '%') {\n+\t\t\tstrbuf_addch(sb, *p++);\n+\t\t\tfmt = p;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (*p == ' ' || *p == '0')\n+\t\t\tfill = *p++;\n+\t\tif (isdigit(*p))\n+\t\t\tsize = (int)strtol(p, &p, 10);\n+\t\telse if (!prefixcmp(p, \".*\")) {\n+\t\t\tmax_size = va_arg(ap, int);\n+\t\t\tp += 2;\n+\t\t}\n+\t\tswitch (*p) {\n+\t\tcase 's': {\n+\t\t\tconst char *s = va_arg(ap, const char *);\n+\t\t\tif (fill) {\n+\t\t\t\tint len = size - strlen(s);\n+\t\t\t\twhile (len-- > 0)\n+\t\t\t\t\tstrbuf_addch(sb, fill);\n+\t\t\t}\n+\t\t\twhile (*s && max_size--)\n+\t\t\t\tstrbuf_addch(sb, *s++);\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 'c':\n+\t\t\tstrbuf_addch(sb, va_arg(ap, int));\n+\t\t\tbreak;\n+\t\tcase 'u':\n+\t\tcase 'i':\n+\t\tcase 'l':\n+\t\tcase 'd':\n+\t\tcase 'o':\n+\t\tcase 'x':\n+\t\tcase 'X': {\n+\t\t\tint base = *p == 'x' || *p == 'X' ? 16 :\n+\t\t\t\t*p == 'o' ? 8 : 10;\n+\t\t\tint negative = 0, len;\n+\t\t\tunsigned long number, power;\n+\n+\t\t\tif (*p == 'u')\n+\t\t\t\tnumber = va_arg(ap, unsigned int);\n+\t\t\telse {\n+\t\t\t\tlong signed_number;\n+\t\t\t\tif (*p == 'l')\n+\t\t\t\t\tsigned_number = va_arg(ap, long);\n+\t\t\t\telse\n+\t\t\t\t\tsigned_number = va_arg(ap, int);\n+\t\t\t\tif (signed_number < 0) {\n+\t\t\t\t\tnegative = 1;\n+\t\t\t\t\tnumber = -signed_number;\n+\t\t\t\t} else\n+\t\t\t\t\tnumber = signed_number;\n+\t\t\t}\n+\n+\t\t\t/* pad */\n+\t\t\tlen = number_length(number, base);\n+\t\t\twhile (size-- > len + negative)\n+\t\t\t\tstrbuf_addch(sb, fill ? fill : ' ');\n+\t\t\tif (negative)\n+\t\t\t\tstrbuf_addch(sb, '-');\n+\n+\t\t\t/* output number */\n+\t\t\tpower = 1;\n+\t\t\twhile (len-- > 1)\n+\t\t\t\tpower *= base;\n+\t\t\twhile (power) {\n+\t\t\t\tint digit = number / power;\n+\t\t\t\tstrbuf_addch(sb, digit < 10 ? '0' + digit\n+\t\t\t\t\t: *p + 'A' - 'X' + digit - 10);\n+\t\t\t\tnumber -= digit * power;\n+\t\t\t\tpower /= base;\n+\t\t\t}\n+\n+\t\t\tbreak;\n+\t\t}\n+\t\tdefault:\n+\t\t\t/* unknown / invalid format: copy verbatim */\n+\t\t\tstrbuf_insert(sb, sb->len, fmt, p - fmt + 1);\n+\t\t}\n+\t\tfmt = p + (*p != '\\0');\n+\t}\n+}\n+\n void strbuf_addf(struct strbuf *sb, const char *fmt, ...)\n {\n-\tint len;\n \tva_list ap;\n \n-\tif (!strbuf_avail(sb))\n-\t\tstrbuf_grow(sb, 64);\n \tva_start(ap, fmt);\n-\tlen = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);\n+\tstrbuf_vaddf(sb, fmt, ap);\n+\tva_end(ap);\n+}\n+\n+void strbuf_initf(struct strbuf *sb, const char *fmt, ...)\n+{\n+\tva_list ap;\n+\n+\tstrbuf_init(sb, strlen(fmt) + 64);\n+\tva_start(ap, fmt);\n+\tstrbuf_vaddf(sb, fmt, ap);\n \tva_end(ap);\n-\tif (len < 0)\n-\t\tdie(\"your vsnprintf is broken\");\n-\tif (len > strbuf_avail(sb)) {\n-\t\tstrbuf_grow(sb, len);\n-\t\tva_start(ap, fmt);\n-\t\tlen = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);\n-\t\tva_end(ap);\n-\t\tif (len > strbuf_avail(sb)) {\n-\t\t\tdie(\"this should not happen, your snprintf is broken\");\n-\t\t}\n-\t}\n-\tstrbuf_setlen(sb, sb->len + len);\n }\n \n void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,\ndiff --git a/strbuf.h b/strbuf.h\nindex faec229..d7c7aaf 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -106,8 +106,11 @@ extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);\n typedef size_t (*expand_fn_t) (struct strbuf *sb, const char *placeholder, void *context);\n extern void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn, void *context);\n \n+extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list args);\n __attribute__((format(printf,2,3)))\n extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);\n+__attribute__((format(printf,2,3)))\n+extern void strbuf_initf(struct strbuf *sb, const char *fmt, ...);\n \n extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);\n /* XXX: if read fails, any partial read is undone */\ndiff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\nindex 27b54cb..c1d4639 100755\n--- a/t/t0000-basic.sh\n+++ b/t/t0000-basic.sh\n@@ -311,6 +311,14 @@ test_expect_success 'absolute path works as expected' '\n \ttest \"$sym\" = \"$(test-absolute-path $dir2/syml)\"\n '\n \n+test_expect_success 'strbuf_initf() works as expected' '\n+\n+\teval $(test-strbuf) &&\n+\ttest ! -z \"$result\" &&\n+\ttest \"$result\" = \"$expect\"\n+\n+'\n+\n test_expect_success 'very long name in the index handled sanely' '\n \n \ta=a && # 1\ndiff --git a/test-strbuf.c b/test-strbuf.c\nnew file mode 100644\nindex 0000000..479fa08\n--- /dev/null\n+++ b/test-strbuf.c\n@@ -0,0 +1,17 @@\n+#include \"cache.h\"\n+#include \"strbuf.h\"\n+\n+int main(int argc, char **argv)\n+{\n+\tstruct strbuf buf;\n+#define TEST_FORMAT \\\n+\t\"'%%%.*s,%x,%05X,%u,%i,% 4d,%3d,%c,%3d'\", \\\n+\t5, \"Hello, World!\", 27, 27, -1, -1, 1, 5, ':', 1234\n+\n+\tstrbuf_initf(&buf, TEST_FORMAT);\n+\tprintf(\"result=%s\\n\", buf.buf);\n+\tprintf(\"expect=\" TEST_FORMAT);\n+\tstrbuf_release(&buf);\n+\n+\treturn 0;\n+}\n-- \n1.5.4.3.571.g9aec3.dirty\n\n"},{"id":"71253","messageId":"47D01E0D.1090801@viscovery.net","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803061727120.3941@racer.site","subject":"Re: [PATCH 1/2 v2] Add strbuf_vaddf(), use it in strbuf_addf(), and add strbuf_initf()","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-03-06T16:38:37Z","receivedAt":"2008-03-06T16:38:37Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Johannes Schindelin schrieb:\n> The most common use of addf() was to init a strbuf and addf() right away.\n> Since it is so common, it makes sense to have a function strbuf_initf() to\n> wrap both calls into one.\n> \n> To do that, we implement a (really minimal) vaddf() lookalike to\n> vsprintf().\n> \n> At the moment, it only handles %u, %i, %d, %l, %o, %x and %X with size\n> indicators '<number>', ' <number>' and '0<number>', as well as %c and %s,\n> the latter with size indicators '.*' in addition to the same size\n> indicators as for numbers.\n\nWTF?\n\nYou did not cater for PRIuMAX, which is %llu except on Windows, where it\nis %I64u. We can make it %llu on Windows only if we can ensure that none\nof its uses ends up in a regular *printf function!\n\n-- Hannes\n\n"},{"id":"71254","messageId":"47D02019.4000500@viscovery.net","threadId":"12344","inReplyTo":"47D01E0D.1090801@viscovery.net","subject":"Re: [PATCH 1/2 v2] Add strbuf_vaddf(), use it in strbuf_addf(), and add strbuf_initf()","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-03-06T16:47:21Z","receivedAt":"2008-03-06T16:47:21Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Johannes Sixt schrieb:\n> You did not cater for PRIuMAX, which is %llu except on Windows, where it\n> is %I64u. We can make it %llu on Windows only if we can ensure that none\n> of its uses ends up in a regular *printf function!\n\nOh, well, PRIuMAX is *only* used in regular *printf and in die() calls.\nThat's fine, too.\n\n-- Hannes\n\n"},{"id":"71257","messageId":"alpine.LSU.1.00.0803061755080.3941@racer.site","threadId":"12344","inReplyTo":"47D02019.4000500@viscovery.net","subject":"Re: [PATCH 1/2 v2] Add strbuf_vaddf(), use it in strbuf_addf(), and add strbuf_initf()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-06T16:59:20Z","receivedAt":"2008-03-06T16:59:20Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 6 Mar 2008, Johannes Sixt wrote:\n\n> Johannes Sixt schrieb:\n> > You did not cater for PRIuMAX, which is %llu except on Windows, where \n> > it is %I64u. We can make it %llu on Windows only if we can ensure that \n> > none of its uses ends up in a regular *printf function!\n> \n> Oh, well, PRIuMAX is *only* used in regular *printf and in die() calls. \n> That's fine, too.\n\nHey, no problem.  I used my earlier analysis to find the _minimal_ set of \nformats needed to get Git running without that vsnprintf().\n\nThe idea is, of course, to enhance vaddf() as needed (if at all).\n\nNote: I did not even bother trying to convert any vsnprintf() users except \nfor strbuf_addf() to that interface: it should be relatively easy, but \nthere are quite a few sites (even using strbuf, but not addf() because \nonly a va_list is available), so it is left as an exercise to the reader \n;-)\n\nCiao,\nDscho\n\n"},{"id":"71263","messageId":"1204827539.10084.9.camel@gaara.boston.redhat.com","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803061153400.15786@racer.site","subject":"Re: [PATCH 1/2] Add strbuf_initf()","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2008-03-06T18:18:59Z","receivedAt":"2008-03-06T18:18:59Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"On Thu, 2008-03-06 at 11:55 +0100, Johannes Schindelin wrote:\n> Hi,\n> \n> On Thu, 6 Mar 2008, Reece Dunn wrote:\n> \n> > On 06/03/2008, Mike Hommey <mh@glandium.org> wrote:\n> > > On Thu, Mar 06, 2008 at 02:14:43AM +0100, Johannes Schindelin wrote:\n> > >  >\n> > >  > The most common use of addf() was to init a strbuf and addf() right \n> > >  > away. Since it is so common, it makes sense to have a function \n> > >  > strbuf_initf() to wrap both calls into one.\n> > >  >\n> > >  > Unfortunately, C (and cpp) has no way to make this easy without \n> > >  > code duplication, as we need to va_init() in strbuf_addf() possibly \n> > >  > a few times.  So the code for addf() is copied.  Fortunately, the \n> > >  > code is pretty short, so not too much had to be copied as-is.\n> > >\n> > >\n> > > The problem with code duplication is not about code size, but more \n> > > about not forgetting to fix bugs in all incarnations of the duplicated \n> > > code.\n> > >\n> > > Is it so ugly to use a macro ?\n> > \n> > Why not have a strbuf_vaddf and strbuf_vinitf that take a va_arg as a \n> > parameter. This would mean that you don't have code duplication, and it \n> > is flexible enough if you want to add more customisations in the future. \n> > No macro needed. This is what the printf/scanf family of functions do.\n> \n> The problem is that we have to restart va_list() if the buffer was too \n> small.\n\nI think we've spent more time debating va_copy than it would take for\nsomebody to just lift the implementation and checks from something like\nglib.  But the recent patch for vsnprintf[1] doesn't actually fix the\nproblem of reusing va_args in the general case; the va_list argument,\nap, is undefined after the vsnprintf() call, yet it calls it in a loop.\nJust bite the bullet and pull in va_copy.  ﻿Of course, I'm just adding\nto the debate here and not sending patches :/\n\n> So your suggestion is out, unless you suggest to implement the whole \n> printf mechanism... which I hope you're not.\n\nIt's not a terrible idea, honestly.  There are several mature vsnprintf\nimplementations out there under friendly licenses.  We could just stick\nit in compat/.  It's the only way to do reliable, cross platform\nvsnprintf, in my experience.  And the issue with %I64u vs %llu could be\nhandle by implementing both, as Wayne Davison suggests.\n\nKristian\n\n[1] Message-Id: ﻿200803051646.13343.michal.rokos@nextsoft.cz from Michal Rokos\n\n"},{"id":"71262","messageId":"alpine.LSU.1.00.0803061925370.3941@racer.site","threadId":"12344","inReplyTo":"1204827539.10084.9.camel@gaara.boston.redhat.com","subject":"Re: [PATCH 1/2] Add strbuf_initf()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-06T18:26:50Z","receivedAt":"2008-03-06T18:26:50Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 6 Mar 2008, Kristian Høgsberg wrote:\n\n> On Thu, 2008-03-06 at 11:55 +0100, Johannes Schindelin wrote:\n>\n> > So your suggestion is out, unless you suggest to implement the whole \n> > printf mechanism... which I hope you're not.\n> \n> It's not a terrible idea, honestly.\n\nHeh.  Yeah, I actually posted a start...\n\n> There are several mature vsnprintf implementations out there under \n> friendly licenses.  We could just stick it in compat/.  It's the only \n> way to do reliable, cross platform vsnprintf, in my experience.  And the \n> issue with %I64u vs %llu could be handle by implementing both, as Wayne \n> Davison suggests.\n\nSure, we could always copy from somewhere else.  My rationale was that I \nhad fun writing it, and that we do not really need a full printf() \nimplementation.\n\nCiao,\nDscho\n"},{"id":"71264","messageId":"1204828515.10084.16.camel@gaara.boston.redhat.com","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803061925370.3941@racer.site","subject":"Re: [PATCH 1/2] Add strbuf_initf()","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2008-03-06T18:35:15Z","receivedAt":"2008-03-06T18:35:15Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"On Thu, 2008-03-06 at 19:26 +0100, Johannes Schindelin wrote:\n> Hi,\n> \n> On Thu, 6 Mar 2008, Kristian Høgsberg wrote:\n> \n> > On Thu, 2008-03-06 at 11:55 +0100, Johannes Schindelin wrote:\n> >\n> > > So your suggestion is out, unless you suggest to implement the whole \n> > > printf mechanism... which I hope you're not.\n> > \n> > It's not a terrible idea, honestly.\n> \n> Heh.  Yeah, I actually posted a start...\n> \n> > There are several mature vsnprintf implementations out there under \n> > friendly licenses.  We could just stick it in compat/.  It's the only \n> > way to do reliable, cross platform vsnprintf, in my experience.  And the \n> > issue with %I64u vs %llu could be handle by implementing both, as Wayne \n> > Davison suggests.\n> \n> Sure, we could always copy from somewhere else.  My rationale was that I \n> had fun writing it, and that we do not really need a full printf() \n> implementation.\n\nThat's how it always starts... \"We just need %d and %s! It'll take me\nhalf an hour!\"  I know because, I've it a number of times myself ;)\nJust pull in the rsync one, don't waste time on this.\n\nKristian\n\n\n"},{"id":"71266","messageId":"20080306191008.GA11635@glandium.org","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803061925370.3941@racer.site","subject":"Re: [PATCH 1/2] Add strbuf_initf()","fromName":"Mike Hommey","fromEmail":"mh@glandium.org","sentAt":"2008-03-06T19:10:08Z","receivedAt":"2008-03-06T19:10:08Z","isPatch":true,"sender":{"key":"mh@glandium.org","avatar":"https://avatars.githubusercontent.com/u/1038527?v=4"},"body":"On Thu, Mar 06, 2008 at 07:26:50PM +0100, Johannes Schindelin wrote:\n> Hi,\n> \n> On Thu, 6 Mar 2008, Kristian Høgsberg wrote:\n> \n> > On Thu, 2008-03-06 at 11:55 +0100, Johannes Schindelin wrote:\n> >\n> > > So your suggestion is out, unless you suggest to implement the whole \n> > > printf mechanism... which I hope you're not.\n> > \n> > It's not a terrible idea, honestly.\n> \n> Heh.  Yeah, I actually posted a start...\n> \n> > There are several mature vsnprintf implementations out there under \n> > friendly licenses.  We could just stick it in compat/.  It's the only \n> > way to do reliable, cross platform vsnprintf, in my experience.  And the \n> > issue with %I64u vs %llu could be handle by implementing both, as Wayne \n> > Davison suggests.\n> \n> Sure, we could always copy from somewhere else.  My rationale was that I \n> had fun writing it, and that we do not really need a full printf() \n> implementation.\n\nAnd vsnprintf is a mess accross systems, returning -1 when not expected.\nI even had the surprise to get an interesting bug in liferea/libxml2 due\nto glibc's vsnprintf returning -1 in some obscure cases.\n\nMike\n"},{"id":"71275","messageId":"200803062138.32743.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803052317350.15786@racer.site","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-03-06T20:38:32Z","receivedAt":"2008-03-06T20:38:32Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Wednesday 05 March 2008 23:18, Johannes Schindelin wrote:\n> On Wed, 5 Mar 2008, Johannes Sixt wrote:\n> > I've now created compat/mingw.h. Below is the interdiff. Of course, it\n> > mostly only moves code around. But you might want to look at at mkstemp,\n> > PATH_SEP, PRIuMAX, and has_dos_drive_prefix. Notice also that I include\n> > compat/mingw.h early in git-compat-util.h instead of late.\n>\n> Thanks!\n>\n> With this, I think I have nothing to add to your series (except maybe an\n> Acked-by: where it applies, or a Reviewed-by:, but I think that this\n> would only be a burden on our maintainer).\n\nThank you!\n\nI now wait for vsnprintf patches and the recent start_command patch to hit \nmaster, then I'll do a final rebase and fix-up before I consider the series \nready for inclusion into git.git.\n\n-- Hannes\n"},{"id":"71756","messageId":"200803112230.57004.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"200803052221.12495.johannes.sixt@telecom.at","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-03-11T21:30:56Z","receivedAt":"2008-03-11T21:30:56Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Wednesday 05 March 2008 22:21, Johannes Sixt wrote:\n> I've now created compat/mingw.h. Below is the interdiff. Of course, it\n> mostly only moves code around. But you might want to look at at mkstemp,\n> PATH_SEP, PRIuMAX, and has_dos_drive_prefix. Notice also that I include\n> compat/mingw.h early in git-compat-util.h instead of late.\n\nI must admit I was very sloppy with the previous round. I had to make \nhas_dos_drive_prefix a macro; otherwise we would get numerous warnings \nabout \"undeclared function isalpha\", because the declaration appears later in \ngit-compat-util.h.\n\nOn the positive side, we can now reuse Michal's vsnprintf wrapper, which fixes \nsnprintf, too, (which was not the case previously). Note that on Windows we \nhave to adjust the size parameter.\n\nThere's also a change in the setup of stderr in start_command() that \ncorresponds to ce2cf27adc. And I made is_dir_sep into a conditional macro \nsimilar to has_dos_drive_prefix to get rid of another #ifdef/#endif.\n\n-- Hannes\n\nHere's the interdiff:\n\ndiff --git a/Makefile b/Makefile\nindex 68d60e7..6619523 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -309,7 +309,7 @@ LIB_H = \\\n \ttree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \\\n \tutf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \\\n \tmailmap.h remote.h parse-options.h transport.h diffcore.h hash.h fsck.h \\\n-\tpack-revindex.h\n+\tpack-revindex.h compat/mingw.h\n \n DIFF_OBJS = \\\n \tdiff.o diff-lib.o diffcore-break.o diffcore-order.o \\\n@@ -549,10 +549,12 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_C99_FORMAT = YesPlease\n \tNO_STRTOUMAX = YesPlease\n \tNO_MKDTEMP = YesPlease\n+\tSNPRINTF_RETURNS_BOGUS = YesPlease\n \tNO_SVN_TESTS = YesPlease\n \tNO_PERL_MAKEMAKER = YesPlease\n \tNO_POSIX_ONLY_PROGRAMS = YesPlease\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat\n+\tCOMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o\n \tEXTLIBS += -lws2_32\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 6733727..7c8fd0e 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -847,40 +847,6 @@ int mingw_rename(const char *pold, const char *pnew)\n \treturn -1;\n }\n \n-#undef vsnprintf\n-/* Note that the size parameter specifies the available space, i.e.\n- * includes the trailing NUL byte; but Windows's vsnprintf expects the\n- * number of characters to write without the trailing NUL.\n- */\n-\n-/* This is out of line because it uses alloca() behind the scenes,\n- * which must not be called in a loop (alloca() reclaims the allocations\n- * only at function exit).\n- */\n-static int try_vsnprintf(size_t size, const char *fmt, va_list args)\n-{\n-\tchar buf[size];\t/* gcc-ism */\n-\treturn vsnprintf(buf, size-1, fmt, args);\n-}\n-\n-int mingw_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)\n-{\n-\tint len;\n-\tif (size > 0) {\n-\t\tlen = vsnprintf(buf, size-1, fmt, args);\n-\t\tif (len >= 0)\n-\t\t\treturn len;\n-\t}\n-\t/* ouch, buffer too small; need to compute the size */\n-\tif (size < 250)\n-\t\tsize = 250;\n-\tdo {\n-\t\tsize *= 4;\n-\t\tlen = try_vsnprintf(size, fmt, args);\n-\t} while (len < 0);\n-\treturn len;\n-}\n-\n struct passwd *getpwuid(int uid)\n {\n \tstatic char user_name[100];\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex d92c631..c7db345 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -174,9 +174,6 @@ 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_vsnprintf(char *buf, size_t size, const char *fmt, va_list args);\n-#define vsnprintf mingw_vsnprintf\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\n@@ -192,12 +189,8 @@ sig_handler_t mingw_signal(int sig, sig_handler_t \nhandler);\n  * git specific compatibility\n  */\n \n-static inline int has_dos_drive_prefix(const char *path)\n-{\n-\treturn isalpha(*path) && path[1] == ':';\n-}\n-#define has_dos_drive_prefix has_dos_drive_prefix\n-\n+#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')\n+#define is_dir_sep(c) ((c) == '/' || (c) == '\\\\')\n #define PATH_SEP ';'\n #define PRIuMAX \"I64u\"\n \ndiff --git a/compat/snprintf.c b/compat/snprintf.c\nindex dbfc2d6..480b66f 100644\n--- a/compat/snprintf.c\n+++ b/compat/snprintf.c\n@@ -1,12 +1,21 @@\n #include \"../git-compat-util.h\"\n \n+/*\n+ * The size parameter specifies the available space, i.e. includes\n+ * the trailing NUL byte; but Windows's vsnprintf expects the\n+ * number of characters to write without the trailing NUL.\n+ */\n+#ifndef SNPRINTF_SIZE_CORR\n+#define SNPRINTF_SIZE_CORR 0\n+#endif\n+\n #undef vsnprintf\n int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)\n {\n \tchar *s;\n \tint ret;\n \n-\tret = vsnprintf(str, maxsize, format, ap);\n+\tret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);\n \tif (ret != -1)\n \t\treturn ret;\n \n@@ -20,7 +29,7 @@ int git_vsnprintf(char *str, size_t maxsize, const char \n*format, va_list ap)\n \t\tif (! str)\n \t\t\tbreak;\n \t\ts = str;\n-\t\tret = vsnprintf(str, maxsize, format, ap);\n+\t\tret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);\n \t}\n \tfree(s);\n \treturn ret;\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 08f764e..2889146 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -117,6 +117,10 @@\n #define has_dos_drive_prefix(path) 0\n #endif\n \n+#ifndef is_dir_sep\n+#define is_dir_sep(c) ((c) == '/')\n+#endif\n+\n #ifdef __GNUC__\n #define NORETURN __attribute__((__noreturn__))\n #else\ndiff --git a/run-command.c b/run-command.c\nindex aba2bf2..2ce8c2b 100644\n--- a/run-command.c\n+++ b/run-command.c\n@@ -132,6 +132,14 @@ int start_command(struct child_process *cmd)\n \t\tdup2(cmd->in, 0);\n \t}\n \n+\tif (cmd->no_stderr) {\n+\t\ts2 = dup(2);\n+\t\tdup_devnull(2);\n+\t} else if (need_err) {\n+\t\ts2 = dup(2);\n+\t\tdup2(fderr[1], 2);\n+\t}\n+\n \tif (cmd->no_stdout) {\n \t\ts1 = dup(1);\n \t\tdup_devnull(1);\n@@ -146,14 +154,6 @@ int start_command(struct child_process *cmd)\n \t\tdup2(cmd->out, 1);\n \t}\n \n-\tif (cmd->no_stderr) {\n-\t\ts2 = dup(2);\n-\t\tdup_devnull(2);\n-\t} else if (need_err) {\n-\t\ts2 = dup(2);\n-\t\tdup2(fderr[1], 2);\n-\t}\n-\n \tif (cmd->dir)\n \t\tdie(\"chdir in start_command() not implemented\");\n \tif (cmd->env) {\ndiff --git a/setup.c b/setup.c\nindex d1a862e..eea1038 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -4,12 +4,6 @@\n static int inside_git_dir = -1;\n static int inside_work_tree = -1;\n \n-#ifdef __MINGW32__\n-static inline int is_dir_sep(char c) { return c == '/' || c == '\\\\'; }\n-#else\n-static inline int is_dir_sep(char c) { return c == '/'; }\n-#endif\n-\n static int sanitary_path_copy(char *dst, const char *src)\n {\n \tchar *dst0;\n"},{"id":"71757","messageId":"alpine.LSU.1.00.0803120028130.3873@racer.site","threadId":"12344","inReplyTo":"200803112230.57004.johannes.sixt@telecom.at","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-11T23:28:51Z","receivedAt":"2008-03-11T23:28:51Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 11 Mar 2008, Johannes Sixt wrote:\n\n> On the positive side, we can now reuse Michal's vsnprintf wrapper, which \n> fixes snprintf, too, (which was not the case previously). Note that on \n> Windows we have to adjust the size parameter.\n\nActually, I have to admit that I like strbuf_vaddf() more and more.  \nAnything you would wish me to implement there?\n\nCiao,\nDscho\n"},{"id":"71876","messageId":"200803122359.30411.johannes.sixt@telecom.at","threadId":"12344","inReplyTo":"alpine.LSU.1.00.0803120028130.3873@racer.site","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2008-03-12T22:59:30Z","receivedAt":"2008-03-12T22:59:30Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Wednesday 12 March 2008 00:28, Johannes Schindelin wrote:\n> On Tue, 11 Mar 2008, Johannes Sixt wrote:\n> > On the positive side, we can now reuse Michal's vsnprintf wrapper, which\n> > fixes snprintf, too, (which was not the case previously). Note that on\n> > Windows we have to adjust the size parameter.\n>\n> Actually, I have to admit that I like strbuf_vaddf() more and more.\n> Anything you would wish me to implement there?\n\nOnly that you keep an eye on PRIuMAX; if it is ever used in a format string of \nstrbuf_vaddf() then you ought to implement %I64u as well as %llu. ;)\n\n-- Hannes\n"},{"id":"71877","messageId":"alpine.LSU.1.00.0803130005560.1656@racer.site","threadId":"12344","inReplyTo":"200803122359.30411.johannes.sixt@telecom.at","subject":"Re: [PATCH 03/40] Add target architecture MinGW.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-12T23:06:06Z","receivedAt":"2008-03-12T23:06:06Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 12 Mar 2008, Johannes Sixt wrote:\n\n> On Wednesday 12 March 2008 00:28, Johannes Schindelin wrote:\n> > On Tue, 11 Mar 2008, Johannes Sixt wrote:\n> > > On the positive side, we can now reuse Michal's vsnprintf wrapper, \n> > > which fixes snprintf, too, (which was not the case previously). Note \n> > > that on Windows we have to adjust the size parameter.\n> >\n> > Actually, I have to admit that I like strbuf_vaddf() more and more. \n> > Anything you would wish me to implement there?\n> \n> Only that you keep an eye on PRIuMAX; if it is ever used in a format \n> string of strbuf_vaddf() then you ought to implement %I64u as well as \n> %llu. ;)\n\nSure!\n\nCiao,\nDscho\n"}]}