Merge branch 'pw/git-p4-on-cygwin'
authorJunio C Hamano <gitster@pobox.com>
Mon, 4 Feb 2013 18:25:30 +0000 (10:25 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 4 Feb 2013 18:25:30 +0000 (10:25 -0800)
Improve "git p4" on Cygwin.

* pw/git-p4-on-cygwin: (21 commits)
git p4: introduce gitConfigBool
git p4: avoid shell when calling git config
git p4: avoid shell when invoking git config --get-all
git p4: avoid shell when invoking git rev-list
git p4: avoid shell when mapping users
git p4: disable read-only attribute before deleting
git p4 test: use test_chmod for cygwin
git p4: cygwin p4 client does not mark read-only
git p4 test: avoid wildcard * in windows
git p4 test: use LineEnd unix in windows tests too
git p4 test: newline handling
git p4: scrub crlf for utf16 files on windows
git p4: remove unreachable windows \r\n conversion code
git p4 test: translate windows paths for cygwin
git p4 test: start p4d inside its db dir
git p4 test: use client_view in t9806
git p4 test: avoid loop in client_view
git p4 test: use client_view to build the initial client
git p4: generate better error message for bad depot path
git p4: remove unused imports
...

git-p4.py
t/lib-git-p4.sh
t/t9800-git-p4-basic.sh
t/t9802-git-p4-filetype.sh
t/t9806-git-p4-options.sh
t/t9807-git-p4-submit.sh
t/t9809-git-p4-client-view.sh
t/t9812-git-p4-wildcards.sh
t/t9815-git-p4-submit-fail.sh
t/test-lib.sh
index 625a3968c29f3097148788e8289b067f3c83a441..647f11020257598a8245eb1e84f64b80a2c55aca 100755 (executable)
--- a/git-p4.py
+++ b/git-p4.py
@@ -7,16 +7,21 @@
 #            2007 Trolltech ASA
 # License: MIT <http://www.opensource.org/licenses/mit-license.php>
 #
-
 import sys
 if sys.hexversion < 0x02040000:
     # The limiter is the subprocess module
     sys.stderr.write("git-p4: requires Python 2.4 or later.\n")
     sys.exit(1)
-
-import optparse, os, marshal, subprocess, shelve
-import tempfile, getopt, os.path, time, platform
-import re, shutil
+import os
+import optparse
+import marshal
+import subprocess
+import tempfile
+import time
+import platform
+import re
+import shutil
+import stat
 
 try:
     from subprocess import CalledProcessError
@@ -185,6 +190,22 @@ def p4_system(cmd):
     if retcode:
         raise CalledProcessError(retcode, real_cmd)
 
+_p4_version_string = None
+def p4_version_string():
+    """Read the version string, showing just the last line, which
+       hopefully is the interesting version bit.
+
+       $ p4 -V
+       Perforce - The Fast Software Configuration Management System.
+       Copyright 1995-2011 Perforce Software.  All rights reserved.
+       Rev. P4/NTX86/2011.1/393975 (2011/12/16).
+    """
+    global _p4_version_string
+    if not _p4_version_string:
+        a = p4_read_pipe_lines(["-V"])
+        _p4_version_string = a[-1].rstrip()
+    return _p4_version_string
+
 def p4_integrate(src, dest):
     p4_system(["integrate", "-Dt", wildcard_encode(src), wildcard_encode(dest)])
 
@@ -558,18 +579,30 @@ def gitBranchExists(branch):
     return proc.wait() == 0;
 
 _gitConfig = {}
-def gitConfig(key, args = None): # set args to "--bool", for instance
+
+def gitConfig(key):
+    if not _gitConfig.has_key(key):
+        cmd = [ "git", "config", key ]
+        s = read_pipe(cmd, ignore_error=True)
+        _gitConfig[key] = s.strip()
+    return _gitConfig[key]
+
+def gitConfigBool(key):
+    """Return a bool, using git config --bool.  It is True only if the
+       variable is set to true, and False if set to false or not present
+       in the config."""
+
     if not _gitConfig.has_key(key):
-        argsFilter = ""
-        if args != None:
-            argsFilter = "%s " % args
-        cmd = "git config %s%s" % (argsFilter, key)
-        _gitConfig[key] = read_pipe(cmd, ignore_error=True).strip()
+        cmd = [ "git", "config", "--bool", key ]
+        s = read_pipe(cmd, ignore_error=True)
+        v = s.strip()
+        _gitConfig[key] = v == "true"
     return _gitConfig[key]
 
 def gitConfigList(key):
     if not _gitConfig.has_key(key):
-        _gitConfig[key] = read_pipe("git config --get-all %s" % key, ignore_error=True).strip().split(os.linesep)
+        s = read_pipe(["git", "config", "--get-all", key], ignore_error=True)
+        _gitConfig[key] = s.strip().split(os.linesep)
     return _gitConfig[key]
 
 def p4BranchesInGit(branchesAreInRemotes=True):
@@ -716,8 +749,7 @@ def p4PathStartsWith(path, prefix):
     #
     # we may or may not have a problem. If you have core.ignorecase=true,
     # we treat DirA and dira as the same directory
-    ignorecase = gitConfig("core.ignorecase", "--bool") == "true"
-    if ignorecase:
+    if gitConfigBool("core.ignorecase"):
         return path.lower().startswith(prefix.lower())
     return path.startswith(prefix)
 
@@ -954,7 +986,7 @@ def __init__(self):
         self.usage += " [name of git branch to submit into perforce depot]"
         self.origin = ""
         self.detectRenames = False
-        self.preserveUser = gitConfig("git-p4.preserveUser").lower() == "true"
+        self.preserveUser = gitConfigBool("git-p4.preserveUser")
         self.dry_run = False
         self.prepare_p4_only = False
         self.conflict_behavior = None
@@ -1049,7 +1081,8 @@ def patchRCSKeywords(self, file, pattern):
     def p4UserForCommit(self,id):
         # Return the tuple (perforce user,git email) for a given git commit id
         self.getUserMapFromPerforceServer()
-        gitEmail = read_pipe("git log --max-count=1 --format='%%ae' %s" % id)
+        gitEmail = read_pipe(["git", "log", "--max-count=1",
+                              "--format=%ae", id])
         gitEmail = gitEmail.strip()
         if not self.emails.has_key(gitEmail):
             return (None,gitEmail)
@@ -1062,7 +1095,7 @@ def checkValidP4Users(self,commits):
             (user,email) = self.p4UserForCommit(id)
             if not user:
                 msg = "Cannot find p4 user for email %s in commit %s." % (email, id)
-                if gitConfig('git-p4.allowMissingP4Users').lower() == "true":
+                if gitConfigBool("git-p4.allowMissingP4Users"):
                     print "%s" % msg
                 else:
                     die("Error: %s\nSet git-p4.allowMissingP4Users to true to allow this." % msg)
@@ -1157,7 +1190,7 @@ def edit_template(self, template_file):
            message.  Return true if okay to continue with the submit."""
 
         # if configured to skip the editing part, just submit
-        if gitConfig("git-p4.skipSubmitEdit") == "true":
+        if gitConfigBool("git-p4.skipSubmitEdit"):
             return True
 
         # look at the modification time, to check later if the user saved
@@ -1173,7 +1206,7 @@ def edit_template(self, template_file):
 
         # If the file was not saved, prompt to see if this patch should
         # be skipped.  But skip this verification step if configured so.
-        if gitConfig("git-p4.skipSubmitEditCheck") == "true":
+        if gitConfigBool("git-p4.skipSubmitEditCheck"):
             return True
 
         # modification time updated means user saved the file
@@ -1231,6 +1264,9 @@ def applyCommit(self, id):
                     p4_edit(dest)
                     pureRenameCopy.discard(dest)
                     filesToChangeExecBit[dest] = diff['dst_mode']
+                if self.isWindows:
+                    # turn off read-only attribute
+                    os.chmod(dest, stat.S_IWRITE)
                 os.unlink(dest)
                 editedFiles.add(dest)
             elif modifier == "R":
@@ -1249,6 +1285,8 @@ def applyCommit(self, id):
                         p4_edit(dest)   # with move: already open, writable
                     filesToChangeExecBit[dest] = diff['dst_mode']
                 if not self.p4HasMoveCommand:
+                    if self.isWindows:
+                        os.chmod(dest, stat.S_IWRITE)
                     os.unlink(dest)
                     filesToDelete.add(src)
                 editedFiles.add(dest)
@@ -1268,7 +1306,7 @@ def applyCommit(self, id):
 
             # Patch failed, maybe it's just RCS keyword woes. Look through
             # the patch to see if that's possible.
-            if gitConfig("git-p4.attemptRCSCleanup","--bool") == "true":
+            if gitConfigBool("git-p4.attemptRCSCleanup"):
                 file = None
                 pattern = None
                 kwfiles = {}
@@ -1289,6 +1327,10 @@ def applyCommit(self, id):
                 for file in kwfiles:
                     if verbose:
                         print "zapping %s with %s" % (line,pattern)
+                    # File is being deleted, so not open in p4.  Must
+                    # disable the read-only bit on windows.
+                    if self.isWindows and file not in editedFiles:
+                        os.chmod(file, stat.S_IWRITE)
                     self.patchRCSKeywords(file, kwfiles[file])
                     fixed_rcs_keywords = True
 
@@ -1559,7 +1601,7 @@ def run(self, args):
             sys.exit(128)
 
         self.useClientSpec = False
-        if gitConfig("git-p4.useclientspec", "--bool") == "true":
+        if gitConfigBool("git-p4.useclientspec"):
             self.useClientSpec = True
         if self.useClientSpec:
             self.clientSpecDirs = getClientSpec()
@@ -1595,11 +1637,11 @@ def run(self, args):
         self.check()
 
         commits = []
-        for line in read_pipe_lines("git rev-list --no-merges %s..%s" % (self.origin, self.master)):
+        for line in read_pipe_lines(["git", "rev-list", "--no-merges", "%s..%s" % (self.origin, self.master)]):
             commits.append(line.strip())
         commits.reverse()
 
-        if self.preserveUser or (gitConfig("git-p4.skipUserNameCheck") == "true"):
+        if self.preserveUser or gitConfigBool("git-p4.skipUserNameCheck"):
             self.checkAuthorship = False
         else:
             self.checkAuthorship = True
@@ -1635,7 +1677,7 @@ def run(self, args):
         else:
             self.diffOpts += " -C%s" % detectCopies
 
-        if gitConfig("git-p4.detectCopiesHarder", "--bool") == "true":
+        if gitConfigBool("git-p4.detectCopiesHarder"):
             self.diffOpts += " --find-copies-harder"
 
         #
@@ -1719,7 +1761,7 @@ def run(self, args):
                                            "--format=format:%h %s",  c])
                 print "You will have to do 'git p4 sync' and rebase."
 
-        if gitConfig("git-p4.exportLabels", "--bool") == "true":
+        if gitConfigBool("git-p4.exportLabels"):
             self.exportLabels = True
 
         if self.exportLabels:
@@ -1989,7 +2031,6 @@ def __init__(self):
         self.syncWithOrigin = True
         self.importIntoRemotes = True
         self.maxChanges = ""
-        self.isWindows = (platform.system() == "Windows")
         self.keepRepoPath = False
         self.depotPaths = None
         self.p4BranchesInGit = []
@@ -2134,7 +2175,14 @@ def streamOneP4File(self, file, contents):
             # operations.  utf16 is converted to ascii or utf8, perhaps.
             # But ascii text saved as -t utf16 is completely mangled.
             # Invoke print -o to get the real contents.
+            #
+            # On windows, the newlines will always be mangled by print, so put
+            # them back too.  This is not needed to the cygwin windows version,
+            # just the native "NT" type.
+            #
             text = p4_read_pipe(['print', '-q', '-o', '-', file['depotFile']])
+            if p4_version_string().find("/NT") >= 0:
+                text = text.replace("\r\n", "\n")
             contents = [ text ]
 
         if type_base == "apple":
@@ -2150,15 +2198,6 @@ def streamOneP4File(self, file, contents):
             print "\nIgnoring apple filetype file %s" % file['depotFile']
             return
 
-        # Perhaps windows wants unicode, utf16 newlines translated too;
-        # but this is not doing it.
-        if self.isWindows and type_base == "text":
-            mangled = []
-            for data in contents:
-                data = data.replace("\r\n", "\n")
-                mangled.append(data)
-            contents = mangled
-
         # Note that we do not try to de-mangle keywords on utf16 files,
         # even though in theory somebody may want that.
         pattern = p4_keywords_regexp_for_type(type_base, type_mods)
@@ -2636,7 +2675,8 @@ def importNewBranch(self, branch, maxChange):
 
     def searchParent(self, parent, branch, target):
         parentFound = False
-        for blob in read_pipe_lines(["git", "rev-list", "--reverse", "--no-merges", parent]):
+        for blob in read_pipe_lines(["git", "rev-list", "--reverse",
+                                     "--no-merges", parent]):
             blob = blob.strip()
             if len(read_pipe(["git", "diff-tree", blob, target])) == 0:
                 parentFound = True
@@ -2707,7 +2747,7 @@ def importChanges(self, changes):
 
                         blob = None
                         if len(parent) > 0:
-                            tempBranch = os.path.join(self.tempBranchLocation, "%d" % (change))
+                            tempBranch = "%s/%d" % (self.tempBranchLocation, change)
                             if self.verbose:
                                 print "Creating temporary branch: " + tempBranch
                             self.commit(description, filesForCommit, tempBranch)
@@ -2821,7 +2861,7 @@ def run(self, args):
             # will use this after clone to set the variable
             self.useClientSpec_from_options = True
         else:
-            if gitConfig("git-p4.useclientspec", "--bool") == "true":
+            if gitConfigBool("git-p4.useclientspec"):
                 self.useClientSpec = True
         if self.useClientSpec:
             self.clientSpecDirs = getClientSpec()
@@ -3061,7 +3101,7 @@ def run(self, args):
                             sys.stdout.write("%s " % b)
                         sys.stdout.write("\n")
 
-        if gitConfig("git-p4.importLabels", "--bool") == "true":
+        if gitConfigBool("git-p4.importLabels"):
             self.importLabels = True
 
         if self.importLabels:
@@ -3179,6 +3219,7 @@ def run(self, args):
         self.cloneExclude = ["/"+p for p in self.cloneExclude]
         for p in depotPaths:
             if not p.startswith("//"):
+                sys.stderr.write('Depot paths must start with "//": %s\n' % p)
                 return False
 
         if not self.cloneDestination:
index 7061dce7e5de2f67e60fe6c42c40519f29cad4a1..2098b9ba053b09b00ed4382aa55ea0802d749d89 100644 (file)
@@ -8,7 +8,8 @@ TEST_NO_CREATE_REPO=NoThanks
 
 . ./test-lib.sh
 
-if ! test_have_prereq PYTHON; then
+if ! test_have_prereq PYTHON
+then
        skip_all='skipping git p4 tests; python not available'
        test_done
 fi
@@ -17,6 +18,24 @@ fi
        test_done
 }
 
+# On cygwin, the NT version of Perforce can be used.  When giving
+# it paths, either on the command-line or in client specifications,
+# be sure to use the native windows form.
+#
+# Older versions of perforce were available compiled natively for
+# cygwin.  Those do not accept native windows paths, so make sure
+# not to convert for them.
+native_path() {
+       path="$1" &&
+       if test_have_prereq CYGWIN && ! p4 -V | grep -q CYGWIN
+       then
+               path=$(cygpath --windows "$path")
+       else
+               path=$(test-path-utils real_path "$path")
+       fi &&
+       echo "$path"
+}
+
 # Try to pick a unique port: guess a large number, then hope
 # no more than one of each test is running.
 #
@@ -32,7 +51,7 @@ P4EDITOR=:
 export P4PORT P4CLIENT P4EDITOR
 
 db="$TRASH_DIRECTORY/db"
-cli=$(test-path-utils real_path "$TRASH_DIRECTORY/cli")
+cli="$TRASH_DIRECTORY/cli"
 git="$TRASH_DIRECTORY/git"
 pidfile="$TRASH_DIRECTORY/p4d.pid"
 
@@ -40,8 +59,11 @@ start_p4d() {
        mkdir -p "$db" "$cli" "$git" &&
        rm -f "$pidfile" &&
        (
-               p4d -q -r "$db" -p $P4DPORT &
-               echo $! >"$pidfile"
+               cd "$db" &&
+               {
+                       p4d -q -p $P4DPORT &
+                       echo $! >"$pidfile"
+               }
        ) &&
 
        # This gives p4d a long time to start up, as it can be
@@ -74,15 +96,8 @@ start_p4d() {
        fi
 
        # build a client
-       (
-               cd "$cli" &&
-               p4 client -i <<-EOF
-               Client: client
-               Description: client
-               Root: $cli
-               View: //depot/... //client/...
-               EOF
-       )
+       client_view "//depot/... //client/..." &&
+
        return 0
 }
 
@@ -123,13 +138,26 @@ marshal_dump() {
 client_view() {
        (
                cat <<-EOF &&
-               Client: client
-               Description: client
+               Client: $P4CLIENT
+               Description: $P4CLIENT
                Root: $cli
+               AltRoots: $(native_path "$cli")
+               LineEnd: unix
                View:
                EOF
-               for arg ; do
-                       printf "\t$arg\n"
-               done
+               printf "\t%s\n" "$@"
        ) | p4 client -i
 }
+
+is_cli_file_writeable() {
+       # cygwin version of p4 does not set read-only attr,
+       # will be marked 444 but -w is true
+       file="$1" &&
+       if test_have_prereq CYGWIN && p4 -V | grep -q CYGWIN
+       then
+               stat=$(stat --format=%a "$file") &&
+               test $stat = 644
+       else
+               test -w "$file"
+       fi
+}
index 166e75209fb561f975a4c01f800f845e15ababae..665607c9cbe5a07f83d4ae4c769060108bddbd9c 100755 (executable)
@@ -30,6 +30,11 @@ test_expect_success 'basic git p4 clone' '
        )
 '
 
+test_expect_success 'depot typo error' '
+       test_must_fail git p4 clone --dest="$git" /depot 2>errs &&
+       grep "Depot paths must start with" errs
+'
+
 test_expect_success 'git p4 clone @all' '
        git p4 clone --dest="$git" //depot@all &&
        test_when_finished cleanup_git &&
index aae1a3f816eb0f57f84053d74246a8db7d7529d8..eeefa6790454d83bfb4ce740f7b1843c6a71c79c 100755 (executable)
@@ -8,6 +8,123 @@ test_expect_success 'start p4d' '
        start_p4d
 '
 
+#
+# This series of tests checks newline handling  Both p4 and
+# git store newlines as \n, and have options to choose how
+# newlines appear in checked-out files.
+#
+test_expect_success 'p4 client newlines, unix' '
+       (
+               cd "$cli" &&
+               p4 client -o | sed "/LineEnd/s/:.*/:unix/" | p4 client -i &&
+               printf "unix\ncrlf\n" >f-unix &&
+               printf "unix\r\ncrlf\r\n" >f-unix-as-crlf &&
+               p4 add -t text f-unix &&
+               p4 submit -d f-unix &&
+
+               # LineEnd: unix; should be no change after sync
+               cp f-unix f-unix-orig &&
+               p4 sync -f &&
+               test_cmp f-unix-orig f-unix &&
+
+               # make sure stored in repo as unix newlines
+               # use sed to eat python-appened newline
+               p4 -G print //depot/f-unix | marshal_dump data 2 |\
+                   sed \$d >f-unix-p4-print &&
+               test_cmp f-unix-orig f-unix-p4-print &&
+
+               # switch to win, make sure lf -> crlf
+               p4 client -o | sed "/LineEnd/s/:.*/:win/" | p4 client -i &&
+               p4 sync -f &&
+               test_cmp f-unix-as-crlf f-unix
+       )
+'
+
+test_expect_success 'p4 client newlines, win' '
+       (
+               cd "$cli" &&
+               p4 client -o | sed "/LineEnd/s/:.*/:win/" | p4 client -i &&
+               printf "win\r\ncrlf\r\n" >f-win &&
+               printf "win\ncrlf\n" >f-win-as-lf &&
+               p4 add -t text f-win &&
+               p4 submit -d f-win &&
+
+               # LineEnd: win; should be no change after sync
+               cp f-win f-win-orig &&
+               p4 sync -f &&
+               test_cmp f-win-orig f-win &&
+
+               # make sure stored in repo as unix newlines
+               # use sed to eat python-appened newline
+               p4 -G print //depot/f-win | marshal_dump data 2 |\
+                   sed \$d >f-win-p4-print &&
+               test_cmp f-win-as-lf f-win-p4-print &&
+
+               # switch to unix, make sure lf -> crlf
+               p4 client -o | sed "/LineEnd/s/:.*/:unix/" | p4 client -i &&
+               p4 sync -f &&
+               test_cmp f-win-as-lf f-win
+       )
+'
+
+test_expect_success 'ensure blobs store only lf newlines' '
+       test_when_finished cleanup_git &&
+       (
+               cd "$git" &&
+               git init &&
+               git p4 sync //depot@all &&
+
+               # verify the files in .git are stored only with newlines
+               o=$(git ls-tree p4/master -- f-unix | cut -f1 | cut -d\  -f3) &&
+               git cat-file blob $o >f-unix-blob &&
+               test_cmp "$cli"/f-unix-orig f-unix-blob &&
+
+               o=$(git ls-tree p4/master -- f-win | cut -f1 | cut -d\  -f3) &&
+               git cat-file blob $o >f-win-blob &&
+               test_cmp "$cli"/f-win-as-lf f-win-blob &&
+
+               rm f-unix-blob f-win-blob
+       )
+'
+
+test_expect_success 'gitattributes setting eol=lf produces lf newlines' '
+       test_when_finished cleanup_git &&
+       (
+               # checkout the files and make sure core.eol works as planned
+               cd "$git" &&
+               git init &&
+               echo "* eol=lf" >.gitattributes &&
+               git p4 sync //depot@all &&
+               git checkout master &&
+               test_cmp "$cli"/f-unix-orig f-unix &&
+               test_cmp "$cli"/f-win-as-lf f-win
+       )
+'
+
+test_expect_success 'gitattributes setting eol=crlf produces crlf newlines' '
+       test_when_finished cleanup_git &&
+       (
+               # checkout the files and make sure core.eol works as planned
+               cd "$git" &&
+               git init &&
+               echo "* eol=crlf" >.gitattributes &&
+               git p4 sync //depot@all &&
+               git checkout master &&
+               test_cmp "$cli"/f-unix-as-crlf f-unix &&
+               test_cmp "$cli"/f-win-orig f-win
+       )
+'
+
+test_expect_success 'crlf cleanup' '
+       (
+               cd "$cli" &&
+               rm f-unix-orig f-unix-as-crlf &&
+               rm f-win-orig f-win-as-lf &&
+               p4 client -o | sed "/LineEnd/s/:.*/:unix/" | p4 client -i &&
+               p4 sync -f
+       )
+'
+
 test_expect_success 'utf-16 file create' '
        (
                cd "$cli" &&
index 4f077eeca86946aa897f15e9f1729f9d0588cfb9..254d428b73fe4983298f57e0d87405002abdfbc2 100755 (executable)
@@ -214,40 +214,33 @@ test_expect_success 'clone --use-client-spec' '
                exec >/dev/null &&
                test_must_fail git p4 clone --dest="$git" --use-client-spec
        ) &&
-       cli2=$(test-path-utils real_path "$TRASH_DIRECTORY/cli2") &&
+       # build a different client
+       cli2="$TRASH_DIRECTORY/cli2" &&
        mkdir -p "$cli2" &&
        test_when_finished "rmdir \"$cli2\"" &&
-       (
-               cd "$cli2" &&
-               p4 client -i <<-EOF
-               Client: client2
-               Description: client2
-               Root: $cli2
-               View: //depot/sub/... //client2/bus/...
-               EOF
-       ) &&
        test_when_finished cleanup_git &&
        (
+               # group P4CLIENT and cli changes in a sub-shell
                P4CLIENT=client2 &&
-               git p4 clone --dest="$git" --use-client-spec //depot/...
-       ) &&
-       (
-               cd "$git" &&
-               test_path_is_file bus/dir/f4 &&
-               test_path_is_missing file1
-       ) &&
-       cleanup_git &&
-
-       # same thing again, this time with variable instead of option
-       (
-               cd "$git" &&
-               git init &&
-               git config git-p4.useClientSpec true &&
-               P4CLIENT=client2 &&
-               git p4 sync //depot/... &&
-               git checkout -b master p4/master &&
-               test_path_is_file bus/dir/f4 &&
-               test_path_is_missing file1
+               cli="$cli2" &&
+               client_view "//depot/sub/... //client2/bus/..." &&
+               git p4 clone --dest="$git" --use-client-spec //depot/... &&
+               (
+                       cd "$git" &&
+                       test_path_is_file bus/dir/f4 &&
+                       test_path_is_missing file1
+               ) &&
+               cleanup_git &&
+               # same thing again, this time with variable instead of option
+               (
+                       cd "$git" &&
+                       git init &&
+                       git config git-p4.useClientSpec true &&
+                       git p4 sync //depot/... &&
+                       git checkout -b master p4/master &&
+                       test_path_is_file bus/dir/f4 &&
+                       test_path_is_missing file1
+               )
        )
 '
 
index 0ae048f29f548eac6cfa37fbabcd9b7f80440515..1fb7bc7cf98bdbdf89491c687e6347cda673d720 100755 (executable)
@@ -17,6 +17,16 @@ test_expect_success 'init depot' '
        )
 '
 
+test_expect_failure 'is_cli_file_writeable function' '
+       (
+               cd "$cli" &&
+               echo a >a &&
+               is_cli_file_writeable a &&
+               ! is_cli_file_writeable file1 &&
+               rm a
+       )
+'
+
 test_expect_success 'submit with no client dir' '
        test_when_finished cleanup_git &&
        git p4 clone --dest="$git" //depot &&
@@ -200,7 +210,7 @@ test_expect_success 'submit copy' '
        (
                cd "$cli" &&
                test_path_is_file file5.ta &&
-               test ! -w file5.ta
+               ! is_cli_file_writeable file5.ta
        )
 '
 
@@ -219,7 +229,7 @@ test_expect_success 'submit rename' '
                cd "$cli" &&
                test_path_is_missing file6.t &&
                test_path_is_file file6.ta &&
-               test ! -w file6.ta
+               ! is_cli_file_writeable file6.ta
        )
 '
 
index 281be29174b8b4fea854d72c663eaa2d46b00259..77f63492d90e61500e6665ba447fbbad7a8c7b3b 100755 (executable)
@@ -196,7 +196,7 @@ test_expect_success 'exclusion single file' '
 
 test_expect_success 'overlay wildcard' '
        client_view "//depot/dir1/... //client/cli/..." \
-                   "+//depot/dir2/... //client/cli/...\n" &&
+                   "+//depot/dir2/... //client/cli/..." &&
        files="cli/file11 cli/file12 cli/file21 cli/file22" &&
        client_verify $files &&
        test_when_finished cleanup_git &&
@@ -333,7 +333,7 @@ test_expect_success 'subdir clone, submit copy' '
        (
                cd "$cli" &&
                test_path_is_file dir1/file11a &&
-               test ! -w dir1/file11a
+               ! is_cli_file_writeable dir1/file11a
        )
 '
 
@@ -353,7 +353,7 @@ test_expect_success 'subdir clone, submit rename' '
                cd "$cli" &&
                test_path_is_missing dir1/file13 &&
                test_path_is_file dir1/file13a &&
-               test ! -w dir1/file13a
+               ! is_cli_file_writeable dir1/file13a
        )
 '
 
@@ -365,7 +365,10 @@ test_expect_success 'wildcard files submit back to p4, client-spec case' '
        (
                cd "$git" &&
                echo git-wild-hash >dir1/git-wild#hash &&
-               echo git-wild-star >dir1/git-wild\*star &&
+               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               then
+                       echo git-wild-star >dir1/git-wild\*star
+               fi &&
                echo git-wild-at >dir1/git-wild@at &&
                echo git-wild-percent >dir1/git-wild%percent &&
                git add dir1/git-wild* &&
@@ -376,7 +379,10 @@ test_expect_success 'wildcard files submit back to p4, client-spec case' '
        (
                cd "$cli" &&
                test_path_is_file dir1/git-wild#hash &&
-               test_path_is_file dir1/git-wild\*star &&
+               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               then
+                       test_path_is_file dir1/git-wild\*star
+               fi &&
                test_path_is_file dir1/git-wild@at &&
                test_path_is_file dir1/git-wild%percent
        ) &&
index 143d41305785090837bcd233cf67f0d57dfcff44..67633257f3fccb2408d678759bce87f7a58acd0a 100755 (executable)
@@ -14,7 +14,10 @@ test_expect_success 'add p4 files with wildcards in the names' '
                printf "file2\nhas\nsome\nrandom\ntext\n" >file2 &&
                p4 add file2 &&
                echo file-wild-hash >file-wild#hash &&
-               echo file-wild-star >file-wild\*star &&
+               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               then
+                       echo file-wild-star >file-wild\*star
+               fi &&
                echo file-wild-at >file-wild@at &&
                echo file-wild-percent >file-wild%percent &&
                p4 add -f file-wild* &&
@@ -28,7 +31,10 @@ test_expect_success 'wildcard files git p4 clone' '
        (
                cd "$git" &&
                test -f file-wild#hash &&
-               test -f file-wild\*star &&
+               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               then
+                       test -f file-wild\*star
+               fi &&
                test -f file-wild@at &&
                test -f file-wild%percent
        )
@@ -40,7 +46,10 @@ test_expect_success 'wildcard files submit back to p4, add' '
        (
                cd "$git" &&
                echo git-wild-hash >git-wild#hash &&
-               echo git-wild-star >git-wild\*star &&
+               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               then
+                       echo git-wild-star >git-wild\*star
+               fi &&
                echo git-wild-at >git-wild@at &&
                echo git-wild-percent >git-wild%percent &&
                git add git-wild* &&
@@ -51,7 +60,10 @@ test_expect_success 'wildcard files submit back to p4, add' '
        (
                cd "$cli" &&
                test_path_is_file git-wild#hash &&
-               test_path_is_file git-wild\*star &&
+               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               then
+                       test_path_is_file git-wild\*star
+               fi &&
                test_path_is_file git-wild@at &&
                test_path_is_file git-wild%percent
        )
@@ -63,7 +75,10 @@ test_expect_success 'wildcard files submit back to p4, modify' '
        (
                cd "$git" &&
                echo new-line >>git-wild#hash &&
-               echo new-line >>git-wild\*star &&
+               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               then
+                       echo new-line >>git-wild\*star
+               fi &&
                echo new-line >>git-wild@at &&
                echo new-line >>git-wild%percent &&
                git add git-wild* &&
@@ -74,7 +89,10 @@ test_expect_success 'wildcard files submit back to p4, modify' '
        (
                cd "$cli" &&
                test_line_count = 2 git-wild#hash &&
-               test_line_count = 2 git-wild\*star &&
+               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               then
+                       test_line_count = 2 git-wild\*star
+               fi &&
                test_line_count = 2 git-wild@at &&
                test_line_count = 2 git-wild%percent
        )
@@ -87,7 +105,7 @@ test_expect_success 'wildcard files submit back to p4, copy' '
                cd "$git" &&
                cp file2 git-wild-cp#hash &&
                git add git-wild-cp#hash &&
-               cp git-wild\*star file-wild-3 &&
+               cp git-wild#hash file-wild-3 &&
                git add file-wild-3 &&
                git commit -m "wildcard copies" &&
                git config git-p4.detectCopies true &&
@@ -134,7 +152,10 @@ test_expect_success 'wildcard files submit back to p4, delete' '
        (
                cd "$cli" &&
                test_path_is_missing git-wild#hash &&
-               test_path_is_missing git-wild\*star &&
+               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               then
+                       test_path_is_missing git-wild\*star
+               fi &&
                test_path_is_missing git-wild@at &&
                test_path_is_missing git-wild%percent
        )
index d2b7b3d98d77a18657f536af54b159230a1ea057..1243d96092ad5c6a66d66ee9debc399649ffa0a2 100755 (executable)
@@ -405,8 +405,8 @@ test_expect_success 'cleanup chmod after submit cancel' '
        git p4 clone --dest="$git" //depot &&
        (
                cd "$git" &&
-               chmod u+x text &&
-               chmod u-x text+x &&
+               test_chmod +x text &&
+               test_chmod -x text+x &&
                git add text text+x &&
                git commit -m "chmod texts" &&
                echo n | test_expect_code 1 git p4 submit
@@ -415,10 +415,13 @@ test_expect_success 'cleanup chmod after submit cancel' '
                cd "$cli" &&
                test_path_is_file text &&
                ! p4 fstat -T action text &&
-               stat --format=%A text | egrep ^-r-- &&
                test_path_is_file text+x &&
                ! p4 fstat -T action text+x &&
-               stat --format=%A text+x | egrep ^-r-x
+               if test_have_prereq NOT_CYGWIN
+               then
+                       stat --format=%A text | egrep ^-r-- &&
+                       stat --format=%A text+x | egrep ^-r-x
+               fi
        )
 '
 
index 1a6c4ab08cd5adb56869855913272ec42eceb45f..9e7f6b424d77ee88c3cd36507cd421a437ec7bfa 100644 (file)
@@ -666,12 +666,14 @@ case $(uname -s) in
        # backslashes in pathspec are converted to '/'
        # exec does not inherit the PID
        test_set_prereq MINGW
+       test_set_prereq NOT_CYGWIN
        test_set_prereq SED_STRIPS_CR
        ;;
 *CYGWIN*)
        test_set_prereq POSIXPERM
        test_set_prereq EXECKEEPSPID
        test_set_prereq NOT_MINGW
+       test_set_prereq CYGWIN
        test_set_prereq SED_STRIPS_CR
        ;;
 *)
@@ -679,6 +681,7 @@ case $(uname -s) in
        test_set_prereq BSLASHPSPEC
        test_set_prereq EXECKEEPSPID
        test_set_prereq NOT_MINGW
+       test_set_prereq NOT_CYGWIN
        ;;
 esac