MinGW port pull request

36 views
Skip to first unread message

Johannes Sixt

unread,
Jun 20, 2008, 4:06:40 AM6/20/08
to Junio C Hamano, Git Mailing List, msysGit
From: Johannes Sixt <johann...@telecom.at>

Junio,

please pull the MinGW (Windows) port patch series from

git://repo.or.cz/git/mingw/j6t.git for-junio

The interdiff since I submitted the patch series

http://thread.gmane.org/gmane.comp.version-control.git/75250/focus=76276

is below.

This code base has been used in production since months, and editorial
issues have been ironed out since I submitted the series. The interdiff is
fairly small (it's mostly some new vsnprintf() fixes and a new utime()
wrapper). The interdiff does not show that we don't need to modify
git-clone.sh anymore ;) IMHO, this is material for 'next'.

At this point I would like to thank all contributors to the porting
effort. Some of your patches have been integrated in other patches in the
series, which now carry my authorship (that is, I'm the one to blame), but
I still have credited you in the commit message.


Here's the patch summary:

* Part 1: Get it going
01/38 Add compat/regex.[ch] and compat/fnmatch.[ch].
02/38 Compile some programs only conditionally.
03/38 Add target architecture MinGW.

With these patches we have a working git.exe that can successfully run
those builtins that need only read-access of the repository, like
git log, git diff, etc.

* Part 2: Working locally is possible
04/38 Windows: Use the Windows style PATH separator ';'.
05/38 Windows: Strip ".exe" from the program name.
06/38 Windows: Implement a wrapper of the open() function.
07/38 Windows: A minimal implemention of getpwuid().
08/38 Windows: always chmod(, 0666) before unlink().
09/38 Windows: Work around misbehaved rename().
10/38 setup.c: Prepare for Windows directory separators.
11/38 Windows: Treat Windows style path names.
12/38 Windows: Handle absolute paths in safe_create_leading_directories().
13/38 Windows: Implement gettimeofday().
14/38 Windows: Fix PRIuMAX definition.
15/38 Windows: Implement setitimer() and sigaction().

Now builtins that write to the repository work as long as they don't need
to spawn secondary processes.

* Part 3: Shell scripts and start_command()
16/38 Windows: Wrap execve so that shell scripts can be invoked.
17/38 Windows: A pipe() replacement whose ends are not inherited to
children.
18/38 Windows: Implement start_command().
19/38 Windows: Change the name of hook scripts to make them not
executable.

Now scripted tools and the builtins and standalone programs work that
depend on start_command().

* Part 4: Remote connections
20/38 Windows: A rudimentary poll() emulation.
21/38 Windows: Disambiguate DOS style paths from SSH URLs.
22/38 Windows: Implement asynchronous functions as threads.
23/38 Windows: Work around incompatible sort and find.
24/38 Windows: Implement wrappers for gethostbyname(), socket(), and
connect().

Remote connections, both push and fetch, using local transport as well as
connections via ssh and native git protocol work.

* Part 5: Optimizations
25/38 Windows: Implement a custom spawnve().
26/38 Windows: Add a new lstat and fstat implementation based on Win32
API.
27/38 Windows: Add a custom implementation for utime().
28/38 Windows: Use a customized struct stat that also has the st_blocks
member.

* Part 6: Tie up loose ends
29/38 Turn builtin_exec_path into a function.
30/38 Windows: Compute the fallback for exec_path from the program
invocation.
31/38 Windows: Use a relative default template_dir and ETC_GITCONFIG
32/38 When installing, be prepared that template_dir may be relative.
33/38 Windows: Make the pager work.
34/38 Windows: Work around an oddity when a pipe with no reader is written
to.
35/38 Windows: Make 'git help -a' work.
36/38 Windows: TMP and TEMP environment variables specify a temporary
directory.
37/38 Windows: Fix ntohl() related warnings about printf formatting
38/38 compat/pread.c: Add a forward declaration to fix a warning

This fixes some final remaining oddities, minor missing features, and
works around differences between POSIX and Windows.


Documentation/git.txt | 6 +-
Makefile | 49 ++-
cache.h | 2 +-
compat/fnmatch.c | 488 +++++++++++++++++
compat/fnmatch.h | 84 +++
compat/mingw.c | 1008 +++++++++++++++++++++++++++++++++++
compat/mingw.h | 208 ++++++++
compat/regex.c | 4927 ++++++++++++++++++++(lots...)
compat/regex.h | 490 +++++++++++++++++
compat/snprintf.c | 19 +-
connect.c | 2 +-
date.c | 2 +-
exec_cmd.c | 41 ++-
git-compat-util.h | 31 +-
git-sh-setup.sh | 13 +
git.c | 14 +
help.c | 33 +-
pager.c | 40 ++-
path.c | 7 +
run-command.c | 126 ++++-
run-command.h | 5 +
setup.c | 58 ++-
sha1_file.c | 14 +-
templates/Makefile | 11 +-
transport.c | 3 +-
upload-pack.c | 2 +
write_or_die.c | 7 +-
27 files changed, 7617 insertions(+), 73 deletions(-)

Interdiff follows (it's line wrapped, just for exposition):

diff --git a/Makefile b/Makefile
index 4ff82c9..ad4b779 100644
--- a/Makefile
+++ b/Makefile
@@ -1301,7 +1301,7 @@ remove-dashes:
ifeq ($(firstword $(subst /, ,$(template_dir))),..)
template_instdir = $(gitexecdir)/$(template_dir)
else
-template_instdir = $template_dir
+template_instdir = $(template_dir)
endif
export template_instdir

diff --git a/compat/mingw.c b/compat/mingw.c
index 7c8fd0e..ee26df9 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -175,6 +175,33 @@ int mingw_fstat(int fd, struct mingw_stat *buf)
return -1;
}

+static inline void time_t_to_filetime(time_t t, FILETIME *ft)
+{
+ long long winTime = t * 10000000LL + 116444736000000000LL;
+ ft->dwLowDateTime = winTime;
+ ft->dwHighDateTime = winTime >> 32;
+}
+
+int mingw_utime (const char *file_name, const struct utimbuf *times)
+{
+ FILETIME mft, aft;
+ int fh, rc;
+
+ /* must have write permission */
+ if ((fh = open(file_name, O_RDWR | O_BINARY)) < 0)
+ return -1;
+
+ time_t_to_filetime(times->modtime, &mft);
+ time_t_to_filetime(times->actime, &aft);
+ if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {
+ errno = EINVAL;
+ rc = -1;
+ } else
+ rc = 0;
+ close(fh);
+ return rc;
+}
+
unsigned int sleep (unsigned int seconds)
{
Sleep(seconds*1000);
@@ -353,7 +380,7 @@ static const char *quote_arg(const char *arg)
const char *p = arg;
if (!*p) force_quotes = 1;
while (*p) {
- if (isspace(*p) || *p == '*' || *p == '?')
+ if (isspace(*p) || *p == '*' || *p == '?' || *p == '{')
force_quotes = 1;
else if (*p == '"')
n++;
diff --git a/compat/mingw.h b/compat/mingw.h
index c7db345..6965e3f 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -24,6 +24,8 @@ typedef int pid_t;
#define SIGKILL 0
#define SIGCHLD 0
#define SIGPIPE 0
+#define SIGHUP 0
+#define SIGQUIT 0
#define SIGALRM 100

#define F_GETFD 1
@@ -174,6 +176,9 @@ int mingw_fstat(int fd, struct mingw_stat *buf);
static inline int mingw_stat(const char *file_name, struct mingw_stat *buf)
{ return mingw_lstat(file_name, buf); }

+int mingw_utime(const char *file_name, const struct utimbuf *times);
+#define utime mingw_utime
+
pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env);
void mingw_execvp(const char *cmd, char *const *argv);
#define execvp mingw_execvp
diff --git a/compat/snprintf.c b/compat/snprintf.c
index 480b66f..580966e 100644
--- a/compat/snprintf.c
+++ b/compat/snprintf.c
@@ -13,9 +13,13 @@
int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
{
char *s;
- int ret;
+ int ret = -1;

- ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
+ if (maxsize > 0) {
+ ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
+ /* Windows does not NUL-terminate if result fills buffer */
+ str[maxsize-1] = 0;
+ }
if (ret != -1)
return ret;

diff --git a/git-compat-util.h b/git-compat-util.h
index cdfd54d..46fc2d3 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -66,12 +66,12 @@
#include <fnmatch.h>
#include <assert.h>
#include <regex.h>
+#include <utime.h>
#ifndef __MINGW32__
#include <sys/wait.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
-#include <utime.h>
#ifndef NO_SYS_SELECT_H
#include <sys/select.h>
#endif
@@ -185,7 +185,7 @@ extern ssize_t git_pread(int fd, void *buf, size_t
count, off_t offset);
* This function is used in compat/pread.c. But we can't include
* cache.h there.
*/
-extern int read_in_full(int fd, void *buf, size_t count);
+extern ssize_t read_in_full(int fd, void *buf, size_t count);

#ifdef NO_SETENV
#define setenv gitsetenv
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 822aa6f..9cceb21 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -153,9 +153,5 @@ case $(uname -s) in
find () {
/usr/bin/find "$@"
}
- # sync is missing
- sync () {
- : # no implementation
- }
;;
esac
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 51d90a3..c861141 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -441,16 +441,3 @@ do
test_done
esac
done
-
-# Fix some commands on Windows
-case $(uname -s) in
-*MINGW*)
- # Windows has its own (incompatible) sort and find
- sort () {
- /usr/bin/sort "$@"
- }
- find () {
- /usr/bin/find "$@"
- }
- ;;
-esac

Junio C Hamano

unread,
Jun 21, 2008, 5:46:36 AM6/21/08
to Johannes Sixt, Git Mailing List, msysGit
Johannes Sixt <j.s...@viscovery.net> writes:

> please pull the MinGW (Windows) port patch series from
>
> git://repo.or.cz/git/mingw/j6t.git for-junio

Took a look. A quick impression.

* Too many whitespace breakages in borrowed compat/regex.[ch] are very
distracting.

* It is a very nice touch to rename sample templates to make sure they
are not executable (after all they are just samples).

* Shouldn't my_mktime() if exported out of date.c be named a bit better?

* The ifdef block in git.c::main() introduces decl-after-stmt which we
tend to avoid, but it is much worse to solve it by adding another ifdef
block just to enclose decl of char *bslash at the beginning of the
function. Perhaps enclose it in an extra block?

* In sanitary_path_copy(), you left "break;" after /* (1) */ but now that
"break" is not inside a switch() anymore, so you are breaking out of
something else, aren't you? -- Ah, the clean-up phase will be no-op in
that case because src points at '\0'. Tricky but looks correct ;-)

* There seem to be an unrelated general fix in upload-pack.c

* There are still too many ifdefs. I am wondering if the changes to
pager and process stuff is easier to manage in the longer term if they
are made into completely separate files (i.e. instead of linking
pager.o you would link mingw-pager.o). I dunno.

* There is an interaction with dr/ceiling topic that is already in 'next'
that needs to be resolved before we merge this in 'next'.

Parked in 'pu' for now but with a broken merge resolution.

Johannes Sixt

unread,
Jun 21, 2008, 5:18:47 PM6/21/08
to Junio C Hamano, msysGit, Git Mailing List
On Samstag, 21. Juni 2008, Junio C Hamano wrote:
> Johannes Sixt <j.s...@viscovery.net> writes:
> > please pull the MinGW (Windows) port patch series from
> >
> > git://repo.or.cz/git/mingw/j6t.git for-junio
>
> Took a look. A quick impression.
>
> * Too many whitespace breakages in borrowed compat/regex.[ch] are very
> distracting.

Will fixup, no problem.

> * It is a very nice touch to rename sample templates to make sure they
> are not executable (after all they are just samples).

Note that they are only renamed on Windows. Do you think it makes sense to
rename them on every platform?

I think I'll have to add a note in Documentation/githooks.txt for Windows that
mentions that the '.noexec' part must be removed.

> * Shouldn't my_mktime() if exported out of date.c be named a bit better?

How about tm_to_time_t()?

> * The ifdef block in git.c::main() introduces decl-after-stmt which we
> tend to avoid, but it is much worse to solve it by adding another ifdef
> block just to enclose decl of char *bslash at the beginning of the
> function. Perhaps enclose it in an extra block?

It does not in my version. IIRC, I was careful that it does not.

> * In sanitary_path_copy(), you left "break;" after /* (1) */ but now that
> "break" is not inside a switch() anymore, so you are breaking out of
> something else, aren't you? -- Ah, the clean-up phase will be no-op in
> that case because src points at '\0'. Tricky but looks correct ;-)

I'm pretty certain that it is an omission. I'll remove the 'break' in the next
round. It's just unnecessarily tricky.

> * There seem to be an unrelated general fix in upload-pack.c

Yes, indeed. It's the fflush(pack_pipe) that could make a difference. I wonder
why this ever worked without it. Notice that traverse_commit_list calls
show_object() last, but show_object() never flushes pack_pipe. Are fdopen()ed
pipes line-buffered or unbuffered?

> * There are still too many ifdefs. I am wondering if the changes to
> pager and process stuff is easier to manage in the longer term if they
> are made into completely separate files (i.e. instead of linking
> pager.o you would link mingw-pager.o). I dunno.

I think that would not be helpful. Both parts need to be maintained, whether
they are in the same file or in different files. If they are in one file, and
someone needs to make a change, then there is a chance that a corresponding
change is made in the MINGW32 arm. If not then there is another chance that
the person would at least say "I don't know how to do it for MINGW32". But if
you separate the implementations completely, then both chances are missed
much easier.

To reduce #ifdef in other places I have some proposals. Please tell me which
you like or dislike:

* The #ifdef STRIP_EXTENSION can be removed with a conditional like this:

static const char ext[] = STRIP_EXTENSION; // "" or ".exe"
if (sizeof(ext) > 1) {
...
}

* The #ifdef in main() of git.c can be removed with a custom loop that checks
for is_dir_sep():

slash = cmd + strlen(cmd);
while (slash > cmd && !is_dir_sep(*--slash))
;
if (slash >= cmd) { // was: if (slash) {
...

* We could wrap getenv(), so that the getenv("TEMPDIR") in path.c does not
need to be followed up with getenv("TMP") and getenv("TEMP"). I'll do that.

* The #ifdef in setup.c, prefix_filename() could easily be removed by using
the MINGW32 arm everywhere. This would penalize non-Windows, however,
prefix_filename() is not performance critical.

> * There is an interaction with dr/ceiling topic that is already in 'next'
> that needs to be resolved before we merge this in 'next'.

How do you want me to proceed? Rebase on top of dr/ceiling? Wait until
dr/ceiling is in master and rebase again? Merge it into my series? (I would
make the merge the last commit in my series.) I'm asking because support of
dr/ceiling was not overwhelming.

-- Hannes

Jim Raden

unread,
Jun 21, 2008, 5:21:47 PM6/21/08
to johann...@telecom.at, Junio C Hamano, msysGit, Git Mailing List
On Sat, Jun 21, 2008 at 5:18 PM, Johannes Sixt <johann...@telecom.at> wrote:

>  * There are still too many ifdefs.  I am wondering if the changes to
>    pager and process stuff is easier to manage in the longer term if they
>    are made into completely separate files (i.e. instead of linking
>    pager.o you would link mingw-pager.o).  I dunno.

I think that would not be helpful. Both parts need to be maintained, whether
they are in the same file or in different files. If they are in one file, and
someone needs to make a change, then there is a chance that a corresponding
change is made in the MINGW32 arm. If not then there is another chance that
the person would at least say "I don't know how to do it for MINGW32". But if
you separate the implementations completely, then both chances are missed
much easier.

I quite agree!!

Junio C Hamano

unread,
Jun 21, 2008, 5:47:05 PM6/21/08
to Johannes Sixt, msysGit, Git Mailing List
Johannes Sixt <johann...@telecom.at> writes:

> * The #ifdef in setup.c, prefix_filename() could easily be removed by using
> the MINGW32 arm everywhere. This would penalize non-Windows, however,
> prefix_filename() is not performance critical.
>
>> * There is an interaction with dr/ceiling topic that is already in 'next'
>> that needs to be resolved before we merge this in 'next'.
>
> How do you want me to proceed? Rebase on top of dr/ceiling? Wait until
> dr/ceiling is in master and rebase again? Merge it into my series? (I would
> make the merge the last commit in my series.) I'm asking because support of
> dr/ceiling was not overwhelming.

I personally feel MinGW branch is more important than ceiling work, not
just because it targets far wider audience but because it affects a lot
wider area. j6t/mingw _will_ eventually graduate to master in some form
(possibly after fixups that is needed to keep things working on non
Windows environment), and dr/ceil may or may not.

So my preference would be to merge j6t/mingw into dr/ceil branch soon,
resolve conflicts there, and merge the result to 'next' when j6t/mingw is
merged to 'next' at the same time. And you can help with that merge when
it happens.

Johannes Sixt

unread,
Jun 23, 2008, 7:54:44 AM6/23/08
to Junio C Hamano, msysGit, Git Mailing List
Johannes Sixt schrieb:

> On Samstag, 21. Juni 2008, Junio C Hamano wrote:
>> Johannes Sixt <j.s...@viscovery.net> writes:
>>> please pull the MinGW (Windows) port patch series from
>>>
>>> git://repo.or.cz/git/mingw/j6t.git for-junio

I've updated the branch (it's still based on v1.5.6). Please pull again.

>> Took a look. A quick impression.
>>
>> * Too many whitespace breakages in borrowed compat/regex.[ch] are very
>> distracting.
>
> Will fixup, no problem.

Done.

>> * Shouldn't my_mktime() if exported out of date.c be named a bit better?
>
> How about tm_to_time_t()?

Done. There's a new commit (for-junio~26) that does only the renaming.

>> * The ifdef block in git.c::main() introduces decl-after-stmt which we
>> tend to avoid, but it is much worse to solve it by adding another ifdef
>> block just to enclose decl of char *bslash at the beginning of the
>> function. Perhaps enclose it in an extra block?

The #ifdef block is gone.

>> * In sanitary_path_copy(), you left "break;" after /* (1) */ but now that
>> "break" is not inside a switch() anymore, so you are breaking out of
>> something else, aren't you? -- Ah, the clean-up phase will be no-op in
>> that case because src points at '\0'. Tricky but looks correct ;-)
>
> I'm pretty certain that it is an omission. I'll remove the 'break' in the next
> round. It's just unnecessarily tricky.

Done.

>> * There seem to be an unrelated general fix in upload-pack.c
>
> Yes, indeed. It's the fflush(pack_pipe) that could make a difference. I wonder
> why this ever worked without it. Notice that traverse_commit_list calls
> show_object() last, but show_object() never flushes pack_pipe. Are fdopen()ed
> pipes line-buffered or unbuffered?

I didn't change anything here because I don't know why the old code works
on *nix, and I only know that the change is *necessary* on Windows.

> To reduce #ifdef in other places I have some proposals. Please tell me which
> you like or dislike:
>
> * The #ifdef STRIP_EXTENSION can be removed with a conditional like this:
>
> static const char ext[] = STRIP_EXTENSION; // "" or ".exe"
> if (sizeof(ext) > 1) {
> ...
> }

Done.

> * The #ifdef in main() of git.c can be removed with a custom loop that checks
> for is_dir_sep():
>
> slash = cmd + strlen(cmd);
> while (slash > cmd && !is_dir_sep(*--slash))
> ;
> if (slash >= cmd) { // was: if (slash) {
> ...

Done in a similar way.

> * We could wrap getenv(), so that the getenv("TEMPDIR") in path.c does not
> need to be followed up with getenv("TMP") and getenv("TEMP"). I'll do that.

Done.

> * The #ifdef in setup.c, prefix_filename() could easily be removed by using
> the MINGW32 arm everywhere. This would penalize non-Windows, however,
> prefix_filename() is not performance critical.

NOT done.

>> * There is an interaction with dr/ceiling topic that is already in 'next'
>> that needs to be resolved before we merge this in 'next'.

Will take care of this next; I'm running out of time now.

The interdiff follows; I created it with diff -b to hide the whitespace
changes. As you can see, there are a few more editorial changes in
compat/mingw.c (in comments and error texts only).

-- Hannes


compat/mingw.c | 33 ++++++++++++++++++++++-----------
compat/mingw.h | 3 +++
date.c | 13 ++++++++-----
git-compat-util.h | 5 +++++
git.c | 23 +++++++++++------------
path.c | 7 -------
setup.c | 1 -
7 files changed, 49 insertions(+), 36 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index ee26df9..3a05fe7 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -218,7 +218,6 @@ int mkstemp(char *template)

int gettimeofday(struct timeval *tv, void *tz)
{
- extern time_t my_mktime(struct tm *tm);
SYSTEMTIME st;
struct tm tm;
GetSystemTime(&st);
@@ -228,7 +227,7 @@ int gettimeofday(struct timeval *tv, void *tz)
tm.tm_hour = st.wHour;
tm.tm_min = st.wMinute;
tm.tm_sec = st.wSecond;
- tv->tv_sec = my_mktime(&tm);
+ tv->tv_sec = tm_to_time_t(&tm);
if (tv->tv_sec < 0)
return -1;
tv->tv_usec = st.wMilliseconds*1000;
@@ -367,6 +366,19 @@ char *mingw_getcwd(char *pointer, int len)
return ret;
}

+#undef getenv
+char *mingw_getenv(const char *name)
+{
+ char *result = getenv(name);
+ if (!result && !strcmp(name, "TMPDIR")) {
+ /* on Windows it is TMP and TEMP */
+ result = getenv("TMP");
+ if (!result)
+ result = getenv("TEMP");
+ }
+ return result;
+}
+
/*
* See http://msdn2.microsoft.com/en-us/library/17w5ykft(vs.71).aspx
* (Parsing C++ Command-Line Arguments)
@@ -895,13 +907,12 @@ static int one_shot;
static sig_handler_t timer_fn = SIG_DFL;

/* The timer works like this:
- * The thread, ticktack(), is basically a trivial routine that most of the
- * time only waits to receive the signal to terminate. The main thread
- * tells the thread to terminate by setting the timer_event to the signalled
+ * The thread, ticktack(), is a trivial routine that most of the time
+ * only waits to receive the signal to terminate. The main thread tells
+ * the thread to terminate by setting the timer_event to the signalled
* state.
- * But ticktack() does not wait indefinitely; instead, it interrupts the
- * wait state every now and then, namely exactly after timer's interval
- * length. At these opportunities it calls the signal handler.
+ * But ticktack() interrupts the wait state after the timer's interval
+ * length to call the signal handler.
*/

static __stdcall unsigned ticktack(void *dummy)
@@ -927,7 +938,7 @@ static int start_timer_thread(void)
error("cannot start timer thread");
} else
return errno = ENOMEM,
- error("cannot allocate resources timer");
+ error("cannot allocate resources for timer");
return 0;
}

@@ -962,11 +973,11 @@ int setitimer(int type, struct itimerval *in, struct
itimerval *out)

if (out != NULL)
return errno = EINVAL,
- error("setitmer param 3 != NULL not implemented");
+ error("setitimer param 3 != NULL not implemented");
if (!is_timeval_eq(&in->it_interval, &zero) &&
!is_timeval_eq(&in->it_interval, &in->it_value))
return errno = EINVAL,
- error("setitmer: it_interval must be zero or eq it_value");
+ error("setitimer: it_interval must be zero or eq it_value");

if (timer_thread)
stop_timer_thread();
diff --git a/compat/mingw.h b/compat/mingw.h
index 6965e3f..6bc049a 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -145,6 +145,9 @@ int mingw_open (const char *filename, int oflags, ...);
char *mingw_getcwd(char *pointer, int len);
#define getcwd mingw_getcwd

+char *mingw_getenv(const char *name);
+#define getenv mingw_getenv
+
struct hostent *mingw_gethostbyname(const char *host);
#define gethostbyname mingw_gethostbyname

diff --git a/compat/regex.c b/compat/regex.c
index 1d39e08..87b33e4 100644
diff --git a/compat/regex.h b/compat/regex.h
index 408dd21..6eb64f1 100644
diff --git a/date.c b/date.c
index d6f8bf6..35a5257 100644
--- a/date.c
+++ b/date.c
@@ -6,7 +6,10 @@

#include "cache.h"

-time_t my_mktime(struct tm *tm)
+/*
+ * This is like mktime, but without normalization of tm_wday and tm_yday.
+ */
+time_t tm_to_time_t(const struct tm *tm)
{
static const int mdays[] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
@@ -67,7 +70,7 @@ static int local_tzoffset(unsigned long time)

t = time;
localtime_r(&t, &tm);
- t_local = my_mktime(&tm);
+ t_local = tm_to_time_t(&tm);

if (t_local < t) {
eastwest = -1;
@@ -322,7 +325,7 @@ static int is_date(int year, int month, int day,
struct tm *now_tm, time_t now,
if (!now_tm)
return 1;

- specified = my_mktime(r);
+ specified = tm_to_time_t(r);

/* Be it commit time or author time, it does not make
* sense to specify timestamp way into the future. Make
@@ -572,7 +575,7 @@ int parse_date(const char *date, char *result, int maxlen)
}

/* mktime uses local timezone */
- then = my_mktime(&tm);
+ then = tm_to_time_t(&tm);
if (offset == -1)
offset = (then - mktime(&tm)) / 60;

@@ -611,7 +614,7 @@ void datestamp(char *buf, int bufsize)

time(&now);

- offset = my_mktime(localtime(&now)) - now;
+ offset = tm_to_time_t(localtime(&now)) - now;
offset /= 60;

date_string(now, offset, buf, bufsize);
diff --git a/git-compat-util.h b/git-compat-util.h
index 46fc2d3..51823ae 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -114,6 +114,10 @@
#define PATH_SEP ':'
#endif

+#ifndef STRIP_EXTENSION
+#define STRIP_EXTENSION ""
+#endif
+
#ifndef has_dos_drive_prefix
#define has_dos_drive_prefix(path) 0
#endif
@@ -143,6 +147,7 @@ extern void set_error_routine(void (*routine)(const
char *err, va_list params));
extern void set_warn_routine(void (*routine)(const char *warn, va_list
params));

extern int prefixcmp(const char *str, const char *prefix);
+extern time_t tm_to_time_t(const struct tm *tm);

#ifdef NO_MMAP

diff --git a/git.c b/git.c
index a4b0a5e..871b93c 100644
--- a/git.c
+++ b/git.c
@@ -369,15 +369,16 @@ static void handle_internal_command(int argc, const
char **argv)
{ "pack-refs", cmd_pack_refs, RUN_SETUP },
};
int i;
+ static const char ext[] = STRIP_EXTENSION;

-#ifdef STRIP_EXTENSION
- i = strlen(argv[0]) - strlen(STRIP_EXTENSION);
- if (i > 0 && !strcmp(argv[0] + i, STRIP_EXTENSION)) {
+ if (sizeof(ext) > 1) {
+ i = strlen(argv[0]) - strlen(ext);
+ if (i > 0 && !strcmp(argv[0] + i, ext)) {
char *argv0 = strdup(argv[0]);
argv[0] = cmd = argv0;
argv0[i] = '\0';
}
-#endif
+ }

/* Turn "git cmd --help" into "git help cmd" */
if (argc > 1 && !strcmp(argv[1], "--help")) {
@@ -395,8 +396,8 @@ static void handle_internal_command(int argc, const
char **argv)

int main(int argc, const char **argv)
{
- const char *cmd = argv[0] ? argv[0] : "git-help";
- char *slash = strrchr(cmd, '/');
+ const char *cmd = argv[0] && *argv[0] ? argv[0] : "git-help";
+ char *slash = (char *)cmd + strlen(cmd);
const char *cmd_path = NULL;
int done_alias = 0;

@@ -405,12 +406,10 @@ int main(int argc, const char **argv)
* name, and the dirname as the default exec_path
* if we don't have anything better.
*/
-#ifdef __MINGW32__
- char *bslash = strrchr(cmd, '\\');
- if (!slash || (bslash && bslash > slash))
- slash = bslash;
-#endif
- if (slash) {
+ do
+ --slash;
+ while (cmd <= slash && !is_dir_sep(*slash));
+ if (cmd <= slash) {
*slash++ = 0;
cmd_path = cmd;
cmd = slash;
diff --git a/path.c b/path.c
index 5da41c7..7a35a26 100644
--- a/path.c
+++ b/path.c
@@ -75,13 +75,6 @@ int git_mkstemp(char *path, size_t len, const char
*template)
size_t n;

tmp = getenv("TMPDIR");
-#ifdef __MINGW32__
- /* on Windows it is TMP and TEMP */
- if (!tmp)
- tmp = getenv("TMP");
- if (!tmp)
- tmp = getenv("TEMP");
-#endif
if (!tmp)
tmp = "/tmp";
n = snprintf(path, len, "%s/%s", tmp, template);
diff --git a/setup.c b/setup.c
index ec33147..8bb7b10 100644
--- a/setup.c
+++ b/setup.c
@@ -35,7 +35,6 @@ static int sanitary_path_copy(char *dst, const char *src)
if (!src[1]) {
/* (1) */
src++;
- break;
} else if (is_dir_sep(src[1])) {
/* (2) */
src += 2;

Johannes Sixt

unread,
Jun 24, 2008, 9:01:13 AM6/24/08
to Junio C Hamano, Git Mailing List, msysGit
Junio C Hamano schrieb:

> * There is an interaction with dr/ceiling topic that is already in 'next'
> that needs to be resolved before we merge this in 'next'.
>
> Parked in 'pu' for now but with a broken merge resolution.

Please amend the merge commit by this to get the correct resolution:
minoffset in the MinGW port and ceil_offset in dr/ceiling are used for the
same purpose where always ceil_offset == minoffset-1.

We need to adjust ceil_offset only if longest_ancestor_length() returned
-1 (i.e. "there is no prefix") to skip the drive prefix ("C:"); because if
there was some prefix, then the return value will already have accounted
for the drive prefix.

-- Hannes

diff --git a/setup.c b/setup.c
index 531f852..39f1648 100644
--- a/setup.c
+++ b/setup.c
@@ -382,7 +382,6 @@ const char *setup_git_directory_gently(int *nongit_ok)
const char *gitdirenv;
const char *gitfile_dir;
int len, offset, ceil_offset;
- int minoffset = 0;

/*
* Let's assume that we are in a git repository.
@@ -433,12 +432,10 @@ const char *setup_git_directory_gently(int

if (!getcwd(cwd, sizeof(cwd)-1))
die("Unable to read current working directory");
- if (has_dos_drive_prefix(cwd))
- minoffset = 2;

ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
- if (ceil_offset < minoffset)
- ceil_offset = minoffset;
+ if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
+ ceil_offset = 1;

/*
* Test in the following order (relative to the cwd):

Reply all
Reply to author
Forward
0 new messages