Merge branch 'master' of git://git.kernel.org/pub/scm/gitk/gitk
[gitweb.git] / contrib / fast-import / git-p4
index c7fc564a5b7bdf33b05550bf4b0afb2062f4c6c9..c80a6da2522b690e15f84fedf52a132078cd265a 100755 (executable)
@@ -71,6 +71,31 @@ def isP4Exec(kind):
     a plus sign, it is also executable"""
     return (re.search(r"(^[cku]?x)|\+.*x", kind) != None)
 
+def setP4ExecBit(file, mode):
+    # Reopens an already open file and changes the execute bit to match
+    # the execute bit setting in the passed in mode.
+
+    p4Type = "+x"
+
+    if not isModeExec(mode):
+        p4Type = getP4OpenedType(file)
+        p4Type = re.sub('^([cku]?)x(.*)', '\\1\\2', p4Type)
+        p4Type = re.sub('(.*?\+.*?)x(.*?)', '\\1\\2', p4Type)
+        if p4Type[-1] == "+":
+            p4Type = p4Type[0:-1]
+
+    system("p4 reopen -t %s %s" % (p4Type, file))
+
+def getP4OpenedType(file):
+    # Returns the perforce file type for the given file.
+
+    result = read_pipe("p4 opened %s" % file)
+    match = re.match(".*\((.+)\)$", result)
+    if match:
+        return match.group(1)
+    else:
+        die("Could not determine file type for %s" % file)
+
 def diffTreePattern():
     # This is a simple generator for the diff tree regex pattern. This could be
     # a class variable if this and parseDiffTreeEntry were a part of a class.
@@ -111,6 +136,14 @@ def parseDiffTreeEntry(entry):
         }
     return None
 
+def isModeExec(mode):
+    # Returns True if the given git mode represents an executable file,
+    # otherwise False.
+    return mode[-3:] == "755"
+
+def isModeExecChanged(src_mode, dst_mode):
+    return isModeExec(src_mode) != isModeExec(dst_mode)
+
 def p4CmdList(cmd, stdin=None, stdin_mode='w+b'):
     cmd = "p4 -G %s" % cmd
     if verbose:
@@ -538,15 +571,19 @@ class P4Submit(Command):
         filesToAdd = set()
         filesToDelete = set()
         editedFiles = set()
+        filesToChangeExecBit = {}
         for line in diff:
             diff = parseDiffTreeEntry(line)
             modifier = diff['status']
             path = diff['src']
             if modifier == "M":
                 system("p4 edit \"%s\"" % path)
+                if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
+                    filesToChangeExecBit[path] = diff['dst_mode']
                 editedFiles.add(path)
             elif modifier == "A":
                 filesToAdd.add(path)
+                filesToChangeExecBit[path] = diff['dst_mode']
                 if path in filesToDelete:
                     filesToDelete.remove(path)
             elif modifier == "D":
@@ -557,6 +594,8 @@ class P4Submit(Command):
                 src, dest = diff['src'], diff['dst']
                 system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest))
                 system("p4 edit \"%s\"" % (dest))
+                if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
+                    filesToChangeExecBit[dest] = diff['dst_mode']
                 os.unlink(dest)
                 editedFiles.add(dest)
                 filesToDelete.add(src)
@@ -609,6 +648,11 @@ class P4Submit(Command):
             system("p4 revert \"%s\"" % f)
             system("p4 delete \"%s\"" % f)
 
+        # Set/clear executable bits
+        for f in filesToChangeExecBit.keys():
+            mode = filesToChangeExecBit[f]
+            setP4ExecBit(f, mode)
+
         logMessage = ""
         if not self.directSubmit:
             logMessage = extractLogMessageFromGitCommit(id)
@@ -1097,7 +1141,7 @@ class P4Sync(Command):
 
         l = p4CmdList("labels %s..." % ' '.join (self.depotPaths))
         if len(l) > 0 and not self.silent:
-            print "Finding files belonging to labels in %s" % `self.depotPath`
+            print "Finding files belonging to labels in %s" % `self.depotPaths`
 
         for output in l:
             label = output["label"]
@@ -1163,6 +1207,15 @@ class P4Sync(Command):
         for branch in lostAndFoundBranches:
             self.knownBranches[branch] = branch
 
+    def getBranchMappingFromGitBranches(self):
+        branches = p4BranchesInGit(self.importIntoRemotes)
+        for branch in branches.keys():
+            if branch == "master":
+                branch = "main"
+            else:
+                branch = branch[len(self.projectName):]
+            self.knownBranches[branch] = branch
+
     def listExistingP4GitBranches(self):
         # branches holds mapping from name to commit
         branches = p4BranchesInGit(self.importIntoRemotes)
@@ -1497,8 +1550,10 @@ class P4Sync(Command):
             ## FIXME - what's a P4 projectName ?
             self.projectName = self.guessProjectName()
 
-            if not self.hasOrigin:
-                self.getBranchMapping();
+            if self.hasOrigin:
+                self.getBranchMappingFromGitBranches()
+            else:
+                self.getBranchMapping()
             if self.verbose:
                 print "p4-git branches: %s" % self.p4BranchesInGit
                 print "initial parents: %s" % self.initialParents