Merge branch 'js/mingw-tests'
authorJunio C Hamano <gitster@pobox.com>
Wed, 17 Feb 2016 18:13:28 +0000 (10:13 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 17 Feb 2016 18:13:29 +0000 (10:13 -0800)
Test scripts have been updated to remove assumptions that are not
portable between Git for POSIX and Git for Windows, or to skip ones
with expectations that are not satisfiable on Git for Windows.

* js/mingw-tests: (21 commits)
gitignore: ignore generated test-fake-ssh executable
mingw: do not bother to test funny file names
mingw: skip a test in t9130 that cannot pass on Windows
mingw: handle the missing POSIXPERM prereq in t9124
mingw: avoid illegal filename in t9118
mingw: mark t9100's test cases with appropriate prereqs
t0008: avoid absolute path
mingw: work around pwd issues in the tests
mingw: fix t9700's assumption about directory separators
mingw: skip test in t1508 that fails due to path conversion
tests: turn off git-daemon tests if FIFOs are not available
mingw: disable mkfifo-based tests
mingw: accomodate t0060-path-utils for MSYS2
mingw: fix t5601-clone.sh
mingw: let lstat() fail with errno == ENOTDIR when appropriate
mingw: try to delete target directory before renaming
mingw: prepare the TMPDIR environment variable for shell scripts
mingw: factor out Windows specific environment setup
Git.pm: stop assuming that absolute paths start with a slash
mingw: do not trust MSYS2's MinGW gettext.sh
...

1  2 
Makefile
compat/mingw.c
t/t0060-path-utils.sh
t/t3600-rm.sh
t/t5601-clone.sh
t/t9100-git-svn-basic.sh
t/t9118-git-svn-funky-branch-names.sh
t/t9130-git-svn-authors-file.sh
t/test-lib.sh
diff --combined Makefile
index fc2f1ab2c31820513758514cd445fc63521b1d19,800049214644d31b3a8ce2d0f81f309195a864e6..10566d648175fc561fde6a1498996e2bb43b880d
+++ b/Makefile
@@@ -583,6 -583,7 +583,7 @@@ TEST_PROGRAMS_NEED_X += test-delt
  TEST_PROGRAMS_NEED_X += test-dump-cache-tree
  TEST_PROGRAMS_NEED_X += test-dump-split-index
  TEST_PROGRAMS_NEED_X += test-dump-untracked-cache
+ TEST_PROGRAMS_NEED_X += test-fake-ssh
  TEST_PROGRAMS_NEED_X += test-genrandom
  TEST_PROGRAMS_NEED_X += test-hashmap
  TEST_PROGRAMS_NEED_X += test-index-version
@@@ -2025,7 -2026,6 +2026,7 @@@ $(VCSSVN_LIB): $(VCSSVN_OBJS
  
  export DEFAULT_EDITOR DEFAULT_PAGER
  
 +.PHONY: doc man html info pdf
  doc:
        $(MAKE) -C Documentation all
  
@@@ -2069,7 -2069,6 +2070,7 @@@ po/git.pot: $(GENERATED_H) FORC
                $(LOCALIZED_PERL)
        mv $@+ $@
  
 +.PHONY: pot
  pot: po/git.pot
  
  POFILES := $(wildcard po/*.po)
@@@ -2279,7 -2278,6 +2280,7 @@@ mergetools_instdir_SQ = $(subst ','\'',
  
  install_bindir_programs := $(patsubst %,%$X,$(BINDIR_PROGRAMS_NEED_X)) $(BINDIR_PROGRAMS_NO_X)
  
 +.PHONY: profile-install profile-fast-install
  profile-install: profile
        $(MAKE) install
  
@@@ -2346,8 -2344,6 +2347,8 @@@ endi
        done && \
        ./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
  
 +.PHONY: install-gitweb install-doc install-man install-html install-info install-pdf
 +.PHONY: quick-install-doc quick-install-man quick-install-html
  install-gitweb:
        $(MAKE) -C gitweb install
  
@@@ -2407,7 -2403,6 +2408,7 @@@ rpm: dis
  
  htmldocs = git-htmldocs-$(GIT_VERSION)
  manpages = git-manpages-$(GIT_VERSION)
 +.PHONY: dist-doc distclean
  dist-doc:
        $(RM) -r .doc-tmp-dir
        mkdir .doc-tmp-dir
@@@ -2476,8 -2471,6 +2477,8 @@@ ALL_COMMANDS += gi
  ALL_COMMANDS += gitk
  ALL_COMMANDS += gitweb
  ALL_COMMANDS += git-gui git-citool
 +
 +.PHONY: check-docs
  check-docs::
        @(for v in $(ALL_COMMANDS); \
        do \
@@@ -2522,7 -2515,6 +2523,7 @@@ check-builtins:
  ### Test suite coverage testing
  #
  .PHONY: coverage coverage-clean coverage-compile coverage-test coverage-report
 +.PHONY: coverage-untested-functions cover_db cover_db_html
  .PHONY: coverage-clean-results
  
  coverage:
diff --combined compat/mingw.c
index 77a51d3f72ebf8a3fa53b72e93b26f4e60c710b8,545e952a588bd536a4cd462d0a95ed0d778f4901..fbe69b874b06259e1d699572ace7dd8d2c4667c6
@@@ -454,6 -454,39 +454,39 @@@ static inline time_t filetime_to_time_t
        return (time_t)(filetime_to_hnsec(ft) / 10000000);
  }
  
+ /**
+  * Verifies that safe_create_leading_directories() would succeed.
+  */
+ static int has_valid_directory_prefix(wchar_t *wfilename)
+ {
+       int n = wcslen(wfilename);
+       while (n > 0) {
+               wchar_t c = wfilename[--n];
+               DWORD attributes;
+               if (!is_dir_sep(c))
+                       continue;
+               wfilename[n] = L'\0';
+               attributes = GetFileAttributesW(wfilename);
+               wfilename[n] = c;
+               if (attributes == FILE_ATTRIBUTE_DIRECTORY ||
+                               attributes == FILE_ATTRIBUTE_DEVICE)
+                       return 1;
+               if (attributes == INVALID_FILE_ATTRIBUTES)
+                       switch (GetLastError()) {
+                       case ERROR_PATH_NOT_FOUND:
+                               continue;
+                       case ERROR_FILE_NOT_FOUND:
+                               /* This implies parent directory exists. */
+                               return 1;
+                       }
+               return 0;
+       }
+       return 1;
+ }
  /* 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.
@@@ -514,6 -547,12 +547,12 @@@ static int do_lstat(int follow, const c
        case ERROR_NOT_ENOUGH_MEMORY:
                errno = ENOMEM;
                break;
+       case ERROR_PATH_NOT_FOUND:
+               if (!has_valid_directory_prefix(wfilename)) {
+                       errno = ENOTDIR;
+                       break;
+               }
+               /* fallthru */
        default:
                errno = ENOENT;
                break;
@@@ -1603,7 -1642,12 +1642,12 @@@ repeat
        if (gle == ERROR_ACCESS_DENIED &&
            (attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
                if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
-                       errno = EISDIR;
+                       DWORD attrsold = GetFileAttributesW(wpold);
+                       if (attrsold == INVALID_FILE_ATTRIBUTES ||
+                           !(attrsold & FILE_ATTRIBUTE_DIRECTORY))
+                               errno = EISDIR;
+                       else if (!_wrmdir(wpnew))
+                               goto repeat;
                        return -1;
                }
                if ((attrs & FILE_ATTRIBUTE_READONLY) &&
@@@ -1935,31 -1979,28 +1979,31 @@@ pid_t waitpid(pid_t pid, int *status, i
        return -1;
  }
  
 +int mingw_skip_dos_drive_prefix(char **path)
 +{
 +      int ret = has_dos_drive_prefix(*path);
 +      *path += ret;
 +      return ret;
 +}
 +
  int mingw_offset_1st_component(const char *path)
  {
 -      int offset = 0;
 -      if (has_dos_drive_prefix(path))
 -              offset = 2;
 +      char *pos = (char *)path;
  
        /* unc paths */
 -      else if (is_dir_sep(path[0]) && is_dir_sep(path[1])) {
 -
 +      if (!skip_dos_drive_prefix(&pos) &&
 +                      is_dir_sep(pos[0]) && is_dir_sep(pos[1])) {
                /* skip server name */
 -              char *pos = strpbrk(path + 2, "\\/");
 +              pos = strpbrk(pos + 2, "\\/");
                if (!pos)
                        return 0; /* Error: malformed unc path */
  
                do {
                        pos++;
                } while (*pos && !is_dir_sep(*pos));
 -
 -              offset = pos - path;
        }
  
 -      return offset + is_dir_sep(path[offset]);
 +      return pos + is_dir_sep(*pos) - path;
  }
  
  int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)
@@@ -2047,6 -2088,37 +2091,37 @@@ int xwcstoutf(char *utf, const wchar_t 
        return -1;
  }
  
+ static void setup_windows_environment()
+ {
+       char *tmp = getenv("TMPDIR");
+       /* on Windows it is TMP and TEMP */
+       if (!tmp) {
+               if (!(tmp = getenv("TMP")))
+                       tmp = getenv("TEMP");
+               if (tmp) {
+                       setenv("TMPDIR", tmp, 1);
+                       tmp = getenv("TMPDIR");
+               }
+       }
+       if (tmp) {
+               /*
+                * Convert all dir separators to forward slashes,
+                * to help shell commands called from the Git
+                * executable (by not mistaking the dir separators
+                * for escape characters).
+                */
+               for (; *tmp; tmp++)
+                       if (*tmp == '\\')
+                               *tmp = '/';
+       }
+       /* simulate TERM to enable auto-color (see color.c) */
+       if (!getenv("TERM"))
+               setenv("TERM", "cygwin", 1);
+ }
  /*
   * Disable MSVCRT command line wildcard expansion (__getmainargs called from
   * mingw startup code, see init.c in mingw runtime).
@@@ -2125,19 -2197,7 +2200,7 @@@ void mingw_startup(
        qsort(environ, i, sizeof(char*), compareenv);
  
        /* fix Windows specific environment settings */
-       /* on Windows it is TMP and TEMP */
-       if (!mingw_getenv("TMPDIR")) {
-               const char *tmp = mingw_getenv("TMP");
-               if (!tmp)
-                       tmp = mingw_getenv("TEMP");
-               if (tmp)
-                       setenv("TMPDIR", tmp, 1);
-       }
-       /* simulate TERM to enable auto-color (see color.c) */
-       if (!getenv("TERM"))
-               setenv("TERM", "cygwin", 1);
+       setup_windows_environment();
  
        /* initialize critical section for waitpid pinfo_t list */
        InitializeCriticalSection(&pinfo_cs);
diff --combined t/t0060-path-utils.sh
index f0152a7ab4aabd4f47f546c038efcd8503adc9a4,602b08b1416d27d837737019ba615b65149e5fe9..8532a028e7c814057fe0bb7fd87addbd5dc90392
@@@ -36,12 -36,21 +36,21 @@@ if test $rootoff = 2; the
        rootoff=        # we are on Unix
  else
        rootoff=$(($rootoff-1))
+       # In MSYS2, the root directory "/" is translated into a Windows
+       # directory *with* trailing slash. Let's test for that and adjust
+       # our expected longest ancestor length accordingly.
+       case "$(test-path-utils print_path /)" in
+       */) rootslash=1;;
+       *) rootslash=0;;
+       esac
  fi
  
  ancestor() {
        # We do some math with the expected ancestor length.
        expected=$3
        if test -n "$rootoff" && test "x$expected" != x-1; then
+               expected=$(($expected-$rootslash))
+               test $expected -lt 0 ||
                expected=$(($expected+$rootoff))
        fi
        test_expect_success "longest ancestor: $1 $2 => $expected" \
@@@ -59,9 -68,6 +68,9 @@@ case $(uname -s) i
        ;;
  esac
  
 +test_expect_success basename 'test-path-utils basename'
 +test_expect_success dirname 'test-path-utils dirname'
 +
  norm_path "" ""
  norm_path . ""
  norm_path ./ ""
diff --combined t/t3600-rm.sh
index 2e47a2bfd8c99988d536483a0c01d8b81396c5b5,11e7526488b052f8c314d8309503bbfdfa49e7bf..d046d98aec61748ad936515807f28f77600f630e
@@@ -14,7 -14,7 +14,7 @@@ test_expect_success 
       git add -- foo bar baz 'space embedded' -q &&
       git commit -m 'add normal files'"
  
- if touch -- 'tab      embedded' 'newline
+ if test_have_prereq !MINGW && touch -- 'tab   embedded' 'newline
  embedded' 2>/dev/null
  then
        test_set_prereq FUNNYNAMES
@@@ -115,7 -115,7 +115,7 @@@ test_expect_success '"rm" command print
        git add test-file &&
        git commit -m "add file for rm test" &&
        git rm test-file > rm-output &&
 -      test `grep "^rm " rm-output | wc -l` = 1 &&
 +      test $(grep "^rm " rm-output | wc -l) = 1 &&
        rm -f test-file rm-output &&
        git commit -m "remove file from rm test"
  '
@@@ -125,7 -125,7 +125,7 @@@ test_expect_success '"rm" command suppr
        git add test-file &&
        git commit -m "add file for rm --quiet test" &&
        git rm --quiet test-file > rm-output &&
 -      test `wc -l < rm-output` = 0 &&
 +      test $(wc -l < rm-output) = 0 &&
        rm -f test-file rm-output &&
        git commit -m "remove file from rm --quiet test"
  '
diff --combined t/t5601-clone.sh
index 669ec9ba811fedeca820c4454b490e975b03bfca,e40fc2673f9c78d6702f0573518804162611c87f..c1efb8e445402cccdddda987e1eafad4d4bb75f9
@@@ -4,6 -4,9 +4,9 @@@ test_description=clon
  
  . ./test-lib.sh
  
+ X=
+ test_have_prereq !MINGW || X=.exe
  test_expect_success setup '
  
        rm -fr .git &&
@@@ -65,29 -68,6 +68,29 @@@ test_expect_success 'clone respects GIT
  
  '
  
 +test_expect_success 'clone from hooks' '
 +
 +      test_create_repo r0 &&
 +      cd r0 &&
 +      test_commit initial &&
 +      cd .. &&
 +      git init r1 &&
 +      cd r1 &&
 +      cat >.git/hooks/pre-commit <<-\EOF &&
 +      #!/bin/sh
 +      git clone ../r0 ../r2
 +      exit 1
 +      EOF
 +      chmod u+x .git/hooks/pre-commit &&
 +      : >file &&
 +      git add file &&
 +      test_must_fail git commit -m invoke-hook &&
 +      cd .. &&
 +      test_cmp r0/.git/HEAD r2/.git/HEAD &&
 +      test_cmp r0/initial.t r2/initial.t
 +
 +'
 +
  test_expect_success 'clone creates intermediate directories' '
  
        git clone src long/path/to/dst &&
@@@ -244,7 -224,7 +247,7 @@@ test_expect_success 'clone separate git
  '
  
  test_expect_success 'clone separate gitdir: output' '
 -      echo "gitdir: `pwd`/realgitdir" >expected &&
 +      echo "gitdir: $(pwd)/realgitdir" >expected &&
        test_cmp expected dst/.git
  '
  
@@@ -305,14 -285,9 +308,9 @@@ test_expect_success 'clone checking ou
  
  setup_ssh_wrapper () {
        test_expect_success 'setup ssh wrapper' '
-               write_script "$TRASH_DIRECTORY/ssh-wrapper" <<-\EOF &&
-               echo >>"$TRASH_DIRECTORY/ssh-output" "ssh: $*" &&
-               # throw away all but the last argument, which should be the
-               # command
-               while test $# -gt 1; do shift; done
-               eval "$1"
-               EOF
-               GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper" &&
+               cp "$GIT_BUILD_DIR/test-fake-ssh$X" \
+                       "$TRASH_DIRECTORY/ssh-wrapper$X" &&
+               GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper$X" &&
                export GIT_SSH &&
                export TRASH_DIRECTORY &&
                >"$TRASH_DIRECTORY"/ssh-output
  }
  
  copy_ssh_wrapper_as () {
-       cp "$TRASH_DIRECTORY/ssh-wrapper" "$1" &&
-       GIT_SSH="$1" &&
+       cp "$TRASH_DIRECTORY/ssh-wrapper$X" "${1%$X}$X" &&
+       GIT_SSH="${1%$X}$X" &&
        export GIT_SSH
  }
  
diff --combined t/t9100-git-svn-basic.sh
index 258d9b8cefb6bbf81a64098d57db03f7c1da90c6,5464b5bd14c41d583701f094c2a6e2885ab48e4a..56acc1e70eea8498ba1e5546a6f3cb6126a135b1
@@@ -30,8 -30,7 +30,7 @@@ test_expect_success 
                echo "deep dir" >dir/a/b/c/d/e/file &&
                mkdir bar &&
                echo "zzz" >bar/zzz &&
-               echo "#!/bin/sh" >exec.sh &&
-               chmod +x exec.sh &&
+               write_script exec.sh </dev/null &&
                svn_cmd import -m "import for git svn" . "$svnrepo" >/dev/null
        ) &&
        rm -rf import &&
@@@ -117,7 -116,7 +116,7 @@@ test_expect_success "$name" 
  
  
  name='remove executable bit from a file'
- test_expect_success "$name" '
+ test_expect_success POSIXPERM "$name" '
        rm -f "$GIT_DIR"/index &&
        git checkout -f -b mybranch5 ${remotes_git_svn} &&
        chmod -x exec.sh &&
  
  
  name='add executable bit back file'
- test_expect_success "$name" '
+ test_expect_success POSIXPERM "$name" '
        chmod +x exec.sh &&
        git update-index exec.sh &&
        git commit -m "$name" &&
  
  
  name='executable file becomes a symlink to file'
- test_expect_success "$name" '
+ test_expect_success SYMLINKS "$name" '
        rm exec.sh &&
        ln -s file exec.sh &&
        git update-index exec.sh &&
  
  name='new symlink is added to a file that was also just made executable'
  
- test_expect_success "$name" '
+ test_expect_success POSIXPERM,SYMLINKS "$name" '
        chmod +x file &&
        ln -s file exec-2.sh &&
        git update-index --add file exec-2.sh &&
        test -h "$SVN_TREE"/exec-2.sh'
  
  name='modify a symlink to become a file'
- test_expect_success "$name" '
+ test_expect_success POSIXPERM,SYMLINKS "$name" '
        echo git help >help &&
        rm exec-2.sh &&
        cp help exec-2.sh &&
  name="commit with UTF-8 message: locale: $GIT_SVN_LC_ALL"
  LC_ALL="$GIT_SVN_LC_ALL"
  export LC_ALL
- test_expect_success UTF8 "$name" "
+ # This test relies on the previous test, hence requires POSIXPERM,SYMLINKS
+ test_expect_success UTF8,POSIXPERM,SYMLINKS "$name" "
        echo '# hello' >> exec-2.sh &&
        git update-index exec-2.sh &&
        git commit -m 'éï∏' &&
@@@ -214,7 -214,7 +214,7 @@@ tree d667270a1f7b109f5eb3aaea21ede14b56
  tree 8f51f74cf0163afc9ad68a4b1537288c4558b5a4
  EOF
  
- test_expect_success "$name" "test_cmp a expected"
+ test_expect_success POSIXPERM,SYMLINKS "$name" "test_cmp a expected"
  
  test_expect_success 'exit if remote refs are ambigious' "
          git config --add svn-remote.svn.fetch \
@@@ -265,18 -265,18 +265,18 @@@ test_expect_success 'able to dcommit t
        git update-index --add d &&
        git commit -m '/bar/d should be in the log' &&
        git svn dcommit -i bar &&
 -      test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" &&
 +      test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" &&
        mkdir newdir &&
        echo new > newdir/dir &&
        git update-index --add newdir/dir &&
        git commit -m 'add a new directory' &&
        git svn dcommit -i bar &&
 -      test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" &&
 +      test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" &&
        echo foo >> newdir/dir &&
        git update-index newdir/dir &&
        git commit -m 'modify a file in new directory' &&
        git svn dcommit -i bar &&
 -      test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\"
 +      test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\"
        "
  
  test_expect_success 'dcommit should not fail with a touched file' '
@@@ -295,7 -295,7 +295,7 @@@ test_expect_success 'able to set-tree t
        git update-index d &&
        git commit -m 'update /bar/d' &&
        git svn set-tree -i bar HEAD &&
 -      test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\"
 +      test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\"
        "
  
  test_expect_success 'git-svn works in a bare repository' '
index a2219154b89393effa51f87b3be56706728b6572,5c9c0f87d385f5a6d62dceeeed5204756a2070a9..ecb1fed147d206c7d1a3ac43f9d82110e9514e66
@@@ -23,8 -23,11 +23,11 @@@ test_expect_success 'setup svnrepo' 
                      "$svnrepo/pr ject/branches/$scary_uri" &&
        svn_cmd cp -m "leading dot" "$svnrepo/pr ject/trunk" \
                        "$svnrepo/pr ject/branches/.leading_dot" &&
-       svn_cmd cp -m "trailing dot" "$svnrepo/pr ject/trunk" \
-                       "$svnrepo/pr ject/branches/trailing_dot." &&
+       if test_have_prereq !MINGW
+       then
+               svn_cmd cp -m "trailing dot" "$svnrepo/pr ject/trunk" \
+                       "$svnrepo/pr ject/branches/trailing_dot."
+       fi &&
        svn_cmd cp -m "trailing .lock" "$svnrepo/pr ject/trunk" \
                        "$svnrepo/pr ject/branches/trailing_dotlock.lock" &&
        svn_cmd cp -m "reflog" "$svnrepo/pr ject/trunk" \
@@@ -35,7 -38,7 +38,7 @@@
  # SVN 1.7 will truncate "not-a%40{0]" to just "not-a".
  # Look at what SVN wound up naming the branch and use that.
  # Be sure to escape the @ if it shows up.
 -non_reflog=`svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/'`
 +non_reflog=$(svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/')
  
  test_expect_success 'test clone with funky branch names' '
        git svn clone -s "$svnrepo/pr ject" project &&
                git rev-parse "refs/remotes/origin/more%20fun%20plugin!" &&
                git rev-parse "refs/remotes/origin/$scary_ref" &&
                git rev-parse "refs/remotes/origin/%2Eleading_dot" &&
-               git rev-parse "refs/remotes/origin/trailing_dot%2E" &&
+               if test_have_prereq !MINGW
+               then
+                       git rev-parse "refs/remotes/origin/trailing_dot%2E"
+               fi &&
                git rev-parse "refs/remotes/origin/trailing_dotlock%2Elock" &&
                git rev-parse "refs/remotes/origin/$non_reflog"
        )
index d306b77c31e6a73cc777b71eba1f69090093c0dc,0a9cd87136a7c7637095391a314407ffe653cc2f..41264818ccdd85abb4b0a17c8a508d4bcbfe57f5
@@@ -26,7 -26,7 +26,7 @@@ test_expect_success 'start import with 
  test_expect_success 'imported 2 revisions successfully' '
        (
                cd x
 -              test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 2 &&
 +              test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 2 &&
                git rev-list -1 --pretty=raw refs/remotes/git-svn | \
                  grep "^author BBBBBBB BBBBBBB <bb@example\.com> " &&
                git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
@@@ -43,7 -43,7 +43,7 @@@ test_expect_success 'continues to impor
        (
                cd x
                git svn fetch --authors-file=../svn-authors &&
 -              test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 4 &&
 +              test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 4 &&
                git rev-list -1 --pretty=raw refs/remotes/git-svn | \
                  grep "^author DDDDDDD DDDDDDD <dd@example\.com> " &&
                git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
@@@ -73,8 -73,8 +73,8 @@@ tmp_config_get () 
  test_expect_success 'failure happened without negative side effects' '
        (
                cd aa-work &&
 -              test 6 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" &&
 -              test 6 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`"
 +              test 6 -eq "$(tmp_config_get svn-remote.svn.branches-maxRev)" &&
 +              test 6 -eq "$(tmp_config_get svn-remote.svn.tags-maxRev)"
        )
        '
  
@@@ -86,12 -86,12 +86,12 @@@ test_expect_success 'fetch continues af
        (
                cd aa-work &&
                git svn fetch --authors-file=../svn-authors &&
 -              test 8 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" &&
 -              test 8 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`"
 +              test 8 -eq "$(tmp_config_get svn-remote.svn.branches-maxRev)" &&
 +              test 8 -eq "$(tmp_config_get svn-remote.svn.tags-maxRev)"
        )
        '
  
- test_expect_success 'fresh clone with svn.authors-file in config' '
+ test_expect_success !MINGW 'fresh clone with svn.authors-file in config' '
        (
                rm -r "$GIT_DIR" &&
                test x = x"$(git config svn.authorsfile)" &&
diff --combined t/test-lib.sh
index 51e4a88c333463e23957eb07139b01a3de1a1a0e,32ac1a69360c7cd733e302e9628285e5df255454..0b47eb6bb299492d31111c94557c216bb3f32c7f
@@@ -907,11 -907,9 +907,11 @@@ yes () 
                y="$*"
        fi
  
 -      while echo "$y"
 +      i=0
 +      while test $i -lt 99
        do
 -              :
 +              echo "$y"
 +              i=$(($i+1))
        done
  }
  
@@@ -1000,7 -998,7 +1000,7 @@@ test_i18ngrep () 
  test_lazy_prereq PIPE '
        # test whether the filesystem supports FIFOs
        case $(uname -s) in
-       CYGWIN*)
+       CYGWIN*|MINGW*)
                false
                ;;
        *)
@@@ -1056,28 -1054,20 +1056,28 @@@ test_lazy_prereq NOT_ROOT 
        test "$uid" != 0
  '
  
 -# On a filesystem that lacks SANITY, a file can be deleted even if
 -# the containing directory doesn't have write permissions, or a file
 -# can be accessed even if the containing directory doesn't have read
 -# or execute permissions, causing our tests that validate that Git
 -# works sensibly in such situations.
 +# SANITY is about "can you correctly predict what the filesystem would
 +# do by only looking at the permission bits of the files and
 +# directories?"  A typical example of !SANITY is running the test
 +# suite as root, where a test may expect "chmod -r file && cat file"
 +# to fail because file is supposed to be unreadable after a successful
 +# chmod.  In an environment (i.e. combination of what filesystem is
 +# being used and who is running the tests) that lacks SANITY, you may
 +# be able to delete or create a file when the containing directory
 +# doesn't have write permissions, or access a file even if the
 +# containing directory doesn't have read or execute permissions.
 +
  test_lazy_prereq SANITY '
        mkdir SANETESTD.1 SANETESTD.2 &&
  
        chmod +w SANETESTD.1 SANETESTD.2 &&
        >SANETESTD.1/x 2>SANETESTD.2/x &&
        chmod -w SANETESTD.1 &&
 +      chmod -r SANETESTD.1/x &&
        chmod -rx SANETESTD.2 ||
        error "bug in test sript: cannot prepare SANETESTD"
  
 +      ! test -r SANETESTD.1/x &&
        ! rm SANETESTD.1/x && ! test -f SANETESTD.2/x
        status=$?