Merge branch 'work/pt/for-junio' of git://repo.or.cz/git/mingw/4msysgit

* 'work/pt/for-junio' of git://repo.or.cz/git/mingw/4msysgit:
  Add MinGW-specific execv() override.
  Fix Windows-specific macro redefinition warning.
  Fix 'clone' failure at DOS root directory.
  mingw: do not crash on open(NULL, ...)
  git-am: fix detection of absolute paths for windows
  Side-step MSYS-specific path "corruption" leading to t5560 failure.
  Side-step sed line-ending "corruption" leading to t6038 failure.
  Skip 'git archive --remote' test on msysGit
  Do not strip CR when grepping HTTP headers.
  Skip t1300.70 and 71 on msysGit.
  merge-octopus: Work around environment issue on Windows
  MinGW: Report errors when failing to launch the html browser.
  MinGW: fix stat() and lstat() implementations for handling symlinks
  MinGW: Add missing file mode bit defines
  MinGW: Use pid_t more consequently, introduce uid_t for greater compatibility
This commit is contained in:
Junio C Hamano 2010-10-05 08:43:59 -07:00
commit 931c103320
12 changed files with 122 additions and 36 deletions

View File

@ -108,10 +108,14 @@ const char *make_nonrelative_path(const char *path)
if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
die("Too long path: %.*s", 60, path);
} else {
size_t len;
const char *fmt;
const char *cwd = get_pwd_cwd();
if (!cwd)
die_errno("Cannot determine the current working directory");
if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
len = strlen(cwd);
fmt = (len > 0 && is_dir_sep(cwd[len-1])) ? "%s%s" : "%s/%s";
if (snprintf(buf, PATH_MAX, fmt, cwd, path) >= PATH_MAX)
die("Too long path: %.*s", 60, path);
}
return buf;

View File

@ -127,7 +127,7 @@ int mingw_open (const char *filename, int oflags, ...)
mode = va_arg(args, int);
va_end(args);
if (!strcmp(filename, "/dev/null"))
if (filename && !strcmp(filename, "/dev/null"))
filename = "nul";
fd = open(filename, oflags, mode);
@ -160,7 +160,7 @@ ssize_t mingw_write(int fd, const void *buf, size_t count)
#undef fopen
FILE *mingw_fopen (const char *filename, const char *otype)
{
if (!strcmp(filename, "/dev/null"))
if (filename && !strcmp(filename, "/dev/null"))
filename = "nul";
return fopen(filename, otype);
}
@ -192,8 +192,11 @@ static inline time_t filetime_to_time_t(const FILETIME *ft)
/* We keep the do_lstat code in a separate function to avoid recursion.
* When a path ends with a slash, the stat will fail with ENOENT. In
* this case, we strip the trailing slashes and stat again.
*
* If follow is true then act like stat() and report on the link
* target. Otherwise report on the link itself.
*/
static int do_lstat(const char *file_name, struct stat *buf)
static int do_lstat(int follow, const char *file_name, struct stat *buf)
{
WIN32_FILE_ATTRIBUTE_DATA fdata;
@ -209,6 +212,25 @@ static int do_lstat(const char *file_name, struct stat *buf)
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
WIN32_FIND_DATAA findbuf;
HANDLE handle = FindFirstFileA(file_name, &findbuf);
if (handle != INVALID_HANDLE_VALUE) {
if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
(findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
if (follow) {
char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
buf->st_size = readlink(file_name, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
} else {
buf->st_mode = S_IFLNK;
}
buf->st_mode |= S_IREAD;
if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
buf->st_mode |= S_IWRITE;
}
FindClose(handle);
}
}
return 0;
}
return -1;
@ -220,12 +242,12 @@ static int do_lstat(const char *file_name, struct stat *buf)
* complete. Note that Git stat()s are redirected to mingw_lstat()
* too, since Windows doesn't really handle symlinks that well.
*/
int mingw_lstat(const char *file_name, struct stat *buf)
static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
{
int namelen;
static char alt_name[PATH_MAX];
if (!do_lstat(file_name, buf))
if (!do_lstat(follow, file_name, buf))
return 0;
/* if file_name ended in a '/', Windows returned ENOENT;
@ -244,7 +266,16 @@ int mingw_lstat(const char *file_name, struct stat *buf)
memcpy(alt_name, file_name, namelen);
alt_name[namelen] = 0;
return do_lstat(alt_name, buf);
return do_lstat(follow, alt_name, buf);
}
int mingw_lstat(const char *file_name, struct stat *buf)
{
return do_stat_internal(0, file_name, buf);
}
int mingw_stat(const char *file_name, struct stat *buf)
{
return do_stat_internal(1, file_name, buf);
}
#undef fstat
@ -873,6 +904,11 @@ void mingw_execvp(const char *cmd, char *const *argv)
free_path_split(path);
}
void mingw_execv(const char *cmd, char *const *argv)
{
mingw_execve(cmd, argv, environ);
}
static char **copy_environ(void)
{
char **env;
@ -1386,6 +1422,7 @@ void mingw_open_html(const char *unixpath)
const char *, const char *, const char *, INT);
T ShellExecute;
HMODULE shell32;
int r;
shell32 = LoadLibrary("shell32.dll");
if (!shell32)
@ -1395,9 +1432,12 @@ void mingw_open_html(const char *unixpath)
die("cannot run browser");
printf("Launching default browser to display HTML ...\n");
ShellExecute(NULL, "open", htmlpath, NULL, "\\", 0);
r = (int)ShellExecute(NULL, "open", htmlpath, NULL, "\\", SW_SHOWNORMAL);
FreeLibrary(shell32);
/* see the MSDN documentation referring to the result codes here */
if (r <= 32) {
die("failed to launch browser for %.*s", MAX_PATH, unixpath);
}
}
int link(const char *oldpath, const char *newpath)

View File

@ -6,17 +6,30 @@
*/
typedef int pid_t;
typedef int uid_t;
#define hstrerror strerror
#define S_IFLNK 0120000 /* Symbolic link */
#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(x) 0
#ifndef _STAT_H_
#define S_IRUSR 0
#define S_IWUSR 0
#define S_IXUSR 0
#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
#endif
#define S_IRGRP 0
#define S_IWGRP 0
#define S_IXGRP 0
#define S_ISGID 0
#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
#define S_IROTH 0
#define S_IWOTH 0
#define S_IXOTH 0
#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
#define S_ISUID 0
#define S_ISGID 0
#define S_ISVTX 0
#define WIFEXITED(x) 1
#define WIFSIGNALED(x) 0
@ -65,6 +78,12 @@ struct itimerval {
};
#define ITIMER_REAL 0
/*
* sanitize preprocessor namespace polluted by Windows headers defining
* macros which collide with git local versions
*/
#undef HELP_COMMAND /* from winuser.h */
/*
* trivial stubs
*/
@ -75,17 +94,17 @@ static inline int symlink(const char *oldpath, const char *newpath)
{ errno = ENOSYS; return -1; }
static inline int fchmod(int fildes, mode_t mode)
{ errno = ENOSYS; return -1; }
static inline int fork(void)
static inline pid_t fork(void)
{ errno = ENOSYS; return -1; }
static inline unsigned int alarm(unsigned int seconds)
{ return 0; }
static inline int fsync(int fd)
{ return _commit(fd); }
static inline int getppid(void)
static inline pid_t getppid(void)
{ return 1; }
static inline void sync(void)
{}
static inline int getuid()
static inline uid_t getuid(void)
{ return 1; }
static inline struct passwd *getpwnam(const char *name)
{ return NULL; }
@ -117,7 +136,7 @@ static inline int mingw_unlink(const char *pathname)
}
#define unlink mingw_unlink
static inline int waitpid(pid_t pid, int *status, unsigned options)
static inline pid_t waitpid(pid_t pid, int *status, unsigned options)
{
if (options == 0)
return _cwait(status, pid, 0);
@ -158,7 +177,7 @@ int poll(struct pollfd *ufds, unsigned int nfds, int timeout);
struct tm *gmtime_r(const time_t *timep, struct tm *result);
struct tm *localtime_r(const time_t *timep, struct tm *result);
int getpagesize(void); /* defined in MinGW's libgcc.a */
struct passwd *getpwuid(int uid);
struct passwd *getpwuid(uid_t uid);
int setitimer(int type, struct itimerval *in, struct itimerval *out);
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
int link(const char *oldpath, const char *newpath);
@ -222,10 +241,11 @@ int mingw_getpagesize(void);
#ifndef ALREADY_DECLARED_STAT_FUNCS
#define stat _stati64
int mingw_lstat(const char *file_name, struct stat *buf);
int mingw_stat(const char *file_name, struct stat *buf);
int mingw_fstat(int fd, struct stat *buf);
#define fstat mingw_fstat
#define lstat mingw_lstat
#define _stati64(x,y) mingw_lstat(x,y)
#define _stati64(x,y) mingw_stat(x,y)
#endif
int mingw_utime(const char *file_name, const struct utimbuf *times);
@ -236,6 +256,8 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
int fhin, int fhout, int fherr);
void mingw_execvp(const char *cmd, char *const *argv);
#define execvp mingw_execvp
void mingw_execv(const char *cmd, char *const *argv);
#define execv mingw_execv
static inline unsigned int git_ntohl(unsigned int x)
{ return (unsigned int)ntohl(x); }

View File

@ -444,12 +444,12 @@ else
set x
first=
}
case "$arg" in
/*)
set "$@" "$arg" ;;
*)
set "$@" "$prefix$arg" ;;
esac
if is_absolute_path "$arg"
then
set "$@" "$arg"
else
set "$@" "$prefix$arg"
fi
done
shift
fi

View File

@ -61,6 +61,11 @@ do
esac
eval pretty_name=\${GITHEAD_$SHA1:-$SHA1}
if test "$SHA1" = "$pretty_name"
then
SHA1_UP="$(echo "$SHA1" | tr a-z A-Z)"
eval pretty_name=\${GITHEAD_$SHA1_UP:-$pretty_name}
fi
common=$(git merge-base --all $SHA1 $MRC) ||
die "Unable to find common commit with $pretty_name"

View File

@ -209,5 +209,20 @@ case $(uname -s) in
find () {
/usr/bin/find "$@"
}
is_absolute_path () {
case "$1" in
[/\\]* | [A-Za-z]:*)
return 0 ;;
esac
return 1
}
;;
*)
is_absolute_path () {
case "$1" in
/*)
return 0 ;;
esac
return 1
}
esac

View File

@ -701,13 +701,13 @@ cat >expect <<\EOF
trailingtilde = foo~
EOF
test_expect_success 'set --path' '
test_expect_success NOT_MINGW 'set --path' '
git config --path path.home "~/" &&
git config --path path.normal "/dev/null" &&
git config --path path.trailingtilde "foo~" &&
test_cmp expect .git/config'
if test "${HOME+set}"
if test_have_prereq NOT_MINGW && test "${HOME+set}"
then
test_set_prereq HOMEVAR
fi
@ -730,7 +730,7 @@ cat >expect <<\EOF
foo~
EOF
test_expect_success 'get --path copes with unset $HOME' '
test_expect_success NOT_MINGW 'get --path copes with unset $HOME' '
(
unset HOME;
test_must_fail git config --get --path path.home \

View File

@ -94,7 +94,7 @@ test_expect_success 'git archive with --output' \
'git archive --output=b4.tar HEAD &&
test_cmp b.tar b4.tar'
test_expect_success 'git archive --remote' \
test_expect_success NOT_MINGW 'git archive --remote' \
'git archive --remote=. HEAD >b5.tar &&
test_cmp b.tar b5.tar'

View File

@ -4,14 +4,9 @@ test_description='test automatic tag following'
. ./test-lib.sh
case $(uname -s) in
*MINGW*)
if !test_have_prereq NOT_MINGW; then
say "GIT_DEBUG_SEND_PACK not supported - skipping tests"
;;
*)
test_set_prereq NOT_MINGW
;;
esac
fi
# End state of the repository:
#

View File

@ -5,11 +5,12 @@ test_description='test git-http-backend-noserver'
HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY"
test_have_prereq MINGW && export GREP_OPTIONS=-U
run_backend() {
echo "$2" |
QUERY_STRING="${1#*\?}" \
GIT_PROJECT_ROOT="$HTTPD_DOCUMENT_ROOT_PATH" \
PATH_INFO="${1%%\?*}" \
PATH_TRANSLATED="$HTTPD_DOCUMENT_ROOT_PATH/${1%%\?*}" \
git http-backend >act.out 2>act.err
}

View File

@ -14,6 +14,8 @@ test_description='CRLF merge conflict across text=auto change
. ./test-lib.sh
test_have_prereq MINGW && SED_OPTIONS=-b
test_expect_success setup '
git config core.autocrlf false &&
@ -60,7 +62,7 @@ test_expect_success setup '
test_expect_success 'set up fuzz_conflict() helper' '
fuzz_conflict() {
sed -e "s/^\([<>=]......\) .*/\1/" "$@"
sed $SED_OPTIONS -e "s/^\([<>=]......\) .*/\1/" "$@"
}
'

View File

@ -970,11 +970,13 @@ case $(uname -s) in
# no POSIX permissions
# backslashes in pathspec are converted to '/'
# exec does not inherit the PID
test_set_prereq MINGW
;;
*)
test_set_prereq POSIXPERM
test_set_prereq BSLASHPSPEC
test_set_prereq EXECKEEPSPID
test_set_prereq NOT_MINGW
;;
esac