Code

Different versions of p4 have different output for the where command ;(
[git.git] / contrib / fast-import / git-p4
index a5b6d94d1a162f8cbf4e0c1d9efa69e731cfb060..95037862072e98e82ca1a8219c02ca45db983b04 100755 (executable)
@@ -36,6 +36,22 @@ def p4Cmd(cmd):
         result.update(entry)
     return result;
 
+def p4Where(depotPath):
+    if not depotPath.endswith("/"):
+        depotPath += "/"
+    output = p4Cmd("where %s..." % depotPath)
+    clientPath = ""
+    if "path" in output:
+        clientPath = output.get("path")
+    elif "data" in output:
+        data = output.get("data")
+        lastSpace = data.rfind(" ")
+        clientPath = data[lastSpace + 1:]
+
+    if clientPath.endswith("..."):
+        clientPath = clientPath[:-3]
+    return clientPath
+
 def die(msg):
     sys.stderr.write(msg + "\n")
     sys.exit(1)
@@ -52,12 +68,49 @@ def system(cmd):
     if os.system(cmd) != 0:
         die("command failed: %s" % cmd)
 
+def extractLogMessageFromGitCommit(commit):
+    logMessage = ""
+    foundTitle = False
+    for log in os.popen("git-cat-file commit %s" % commit).readlines():
+       if not foundTitle:
+           if len(log) == 1:
+               foundTitle = 1
+           continue
+
+       logMessage += log
+    return logMessage
+
+def extractDepotPathAndChangeFromGitLog(log):
+    values = {}
+    for line in log.split("\n"):
+        line = line.strip()
+        if line.startswith("[git-p4:") and line.endswith("]"):
+            line = line[8:-1].strip()
+            for assignment in line.split(":"):
+                variable = assignment.strip()
+                value = ""
+                equalPos = assignment.find("=")
+                if equalPos != -1:
+                    variable = assignment[:equalPos].strip()
+                    value = assignment[equalPos + 1:].strip()
+                    if value.startswith("\"") and value.endswith("\""):
+                        value = value[1:-1]
+                values[variable] = value
+
+    return values.get("depot-path"), values.get("change")
+
+def gitBranchExists(branch):
+    if os.system("git-rev-parse %s 2>/dev/null >/dev/null" % branch) == 0:
+        return True
+    return False
+
 class Command:
     def __init__(self):
         self.usage = "usage: %prog [options]"
 
 class P4Debug(Command):
     def __init__(self):
+        Command.__init__(self)
         self.options = [
         ]
         self.description = "A tool to debug the output of p4 -G."
@@ -125,7 +178,7 @@ class P4Sync(Command):
         self.dryRun = False
         self.substFile = ""
         self.firstTime = True
-        self.origin = "origin"
+        self.origin = ""
         self.master = ""
         self.applyAsPatch = True
 
@@ -208,17 +261,9 @@ class P4Sync(Command):
             system("p4 revert %s" % f)
             system("p4 delete %s" % f)
 
-        logMessage = ""
-        foundTitle = False
-        for log in os.popen("git-cat-file commit %s" % id).readlines():
-            if not foundTitle:
-                if len(log) == 1:
-                    foundTitle = 1
-                continue
-
-            if len(logMessage) > 0:
-                logMessage += "\t"
-            logMessage += log
+        logMessage = extractLogMessageFromGitCommit(id)
+        logMessage = logMessage.replace("\n", "\n\t")
+        logMessage = logMessage[:-1]
 
         template = os.popen("p4 change -o").read()
 
@@ -275,6 +320,38 @@ class P4Sync(Command):
             print "Perforce submit template written as %s. Please review/edit and then use p4 submit -i < %s to submit directly!" % (fileName, fileName)
 
     def run(self, args):
+        global gitdir
+        # make gitdir absolute so we can cd out into the perforce checkout
+        gitdir = os.path.abspath(gitdir)
+        os.environ["GIT_DIR"] = gitdir
+        depotPath = ""
+        if gitBranchExists("p4"):
+            [depotPath, dummy] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("p4"))
+        if len(depotPath) == 0 and gitBranchExists("origin"):
+            [depotPath, dummy] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("origin"))
+
+        if len(depotPath) == 0:
+            print "Internal error: cannot locate perforce depot path from existing branches"
+            sys.exit(128)
+
+        clientPath = p4Where(depotPath)
+
+        if len(clientPath) == 0:
+            print "Error: Cannot locate perforce checkout of %s in client view" % depotPath
+            sys.exit(128)
+
+        print "Perforce checkout for depot path %s located at %s" % (depotPath, clientPath)
+        os.chdir(clientPath)
+        response = raw_input("Do you want to sync %s with p4 sync? (y/n)" % clientPath)
+        if response == "y" or response == "yes":
+            system("p4 sync ...")
+
+        if len(self.origin) == 0:
+            if gitBranchExists("p4"):
+                self.origin = "p4"
+            else:
+                self.origin = "origin"
+
         if self.reset:
             self.firstTime = True
 
@@ -352,7 +429,7 @@ class GitSync(Command):
         self.knownBranches = Set()
         self.createdBranches = Set()
         self.committedChanges = Set()
-        self.branch = "master"
+        self.branch = ""
         self.detectBranches = False
         self.changesFile = ""
 
@@ -506,7 +583,7 @@ class GitSync(Command):
 
         self.gitStream.write("data <<EOT\n")
         self.gitStream.write(details["desc"])
-        self.gitStream.write("\n[git-p4: depot-path: \"%s\"; change: %s]\n" % (branchPrefix, details["change"]))
+        self.gitStream.write("\n[git-p4: depot-path = \"%s\": change = %s]\n" % (branchPrefix, details["change"]))
         self.gitStream.write("EOT\n\n")
 
         if len(parent) > 0:
@@ -679,14 +756,41 @@ class GitSync(Command):
             self.users[output["User"]] = output["FullName"] + " <" + output["Email"] + ">"
 
     def run(self, args):
+        self.globalPrefix = ""
+        self.changeRange = ""
+        self.initialParent = ""
+        self.tagLastChange = True
+
+        if len(self.branch) == 0:
+            self.branch = "p4"
+
+        if len(args) == 0:
+            if not gitBranchExists(self.branch) and gitBranchExists("origin"):
+                if not self.silent:
+                    print "Creating %s branch in git repository based on origin" % self.branch
+                system("git branch %s origin" % self.branch)
+
+            [self.previousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(self.branch))
+            if len(self.previousDepotPath) > 0 and len(p4Change) > 0:
+                p4Change = int(p4Change) + 1
+                self.globalPrefix = self.previousDepotPath
+                self.changeRange = "@%s,#head" % p4Change
+                self.initialParent = self.branch
+                self.tagLastChange = False
+                if not self.silent:
+                    print "Performing incremental import into %s git branch" % self.branch
+
         self.branch = "refs/heads/" + self.branch
-        self.globalPrefix = self.previousDepotPath = os.popen("git-repo-config --get p4.depotpath").read()
+
+        if len(self.globalPrefix) == 0:
+            self.globalPrefix = self.previousDepotPath = os.popen("git-repo-config --get p4.depotpath").read()
+
         if len(self.globalPrefix) != 0:
             self.globalPrefix = self.globalPrefix[:-1]
 
         if len(args) == 0 and len(self.globalPrefix) != 0:
             if not self.silent:
-                print "[using previously specified depot path %s]" % self.globalPrefix
+                print "Depot path: %s" % self.globalPrefix
         elif len(args) != 1:
             return False
         else:
@@ -695,10 +799,8 @@ class GitSync(Command):
                 sys.exit(1)
             self.globalPrefix = args[0]
 
-        self.changeRange = ""
         self.revision = ""
         self.users = {}
-        self.initialParent = ""
         self.lastChange = 0
         self.initialTag = ""
 
@@ -860,8 +962,9 @@ class GitSync(Command):
         if not self.silent:
             print ""
 
-        self.gitStream.write("reset refs/tags/p4/%s\n" % self.lastChange)
-        self.gitStream.write("from %s\n\n" % self.branch);
+        if self.tagLastChange:
+            self.gitStream.write("reset refs/tags/p4/%s\n" % self.lastChange)
+            self.gitStream.write("from %s\n\n" % self.branch);
 
 
         self.gitStream.close()