Fix initial multi-branch import.
[gitweb.git] / contrib / fast-import / git-p4
index efec0be32c41a9114dbf83f96ee12ad414e9bd05..e527734be5af0fef713a8d8241de57cb5f2cbb5e 100755 (executable)
@@ -168,6 +168,28 @@ def gitBranchExists(branch):
 def gitConfig(key):
     return read_pipe("git config %s" % key, ignore_error=True).strip()
 
+def findUpstreamBranchPoint():
+    settings = None
+    branchPoint = ""
+    parent = 0
+    while parent < 65535:
+        commit = "HEAD~%s" % parent
+        log = extractLogMessageFromGitCommit(commit)
+        settings = extractSettingsGitLog(log)
+        if not settings.has_key("depot-paths"):
+            parent = parent + 1
+            continue
+
+        names = read_pipe_lines("git name-rev \"--refs=refs/remotes/p4/*\" \"%s\"" % commit)
+        if len(names) <= 0:
+            continue
+
+        # strip away the beginning of 'HEAD~42 refs/remotes/p4/foo'
+        branchPoint = names[0].strip()[len(commit) + 1:]
+        break
+
+    return [branchPoint, settings]
+
 class Command:
     def __init__(self):
         self.usage = "usage: %prog [options]"
@@ -391,10 +413,10 @@ class P4Submit(Command):
         system(applyPatchCmd)
 
         for f in filesToAdd:
-            system("p4 add %s" % f)
+            system("p4 add \"%s\"" % f)
         for f in filesToDelete:
-            system("p4 revert %s" % f)
-            system("p4 delete %s" % f)
+            system("p4 revert \"%s\"" % f)
+            system("p4 delete \"%s\"" % f)
 
         logMessage = ""
         if not self.directSubmit:
@@ -494,25 +516,10 @@ class P4Submit(Command):
         else:
             return False
 
-        depotPath = ""
-        parent = 0
-        while parent < 65535:
-            commit = "HEAD~%s" % parent
-            log = extractLogMessageFromGitCommit(commit)
-            settings = extractSettingsGitLog(log)
-            if not settings.has_key("depot-paths"):
-                parent = parent + 1
-                continue
-
-            depotPath = settings['depot-paths'][0]
-
-            if len(self.origin) == 0:
-                names = read_pipe_lines("git name-rev '--refs=refs/remotes/p4/*' '%s'" % commit)
-                if len(names) > 0:
-                    # strip away the beginning of 'HEAD~42 refs/remotes/p4/foo'
-                    self.origin = names[0].strip()[len(commit) + 1:]
-
-            break
+        [upstream, settings] = findUpstreamBranchPoint()
+        depotPath = settings['depot-paths'][0]
+        if len(self.origin) == 0:
+            self.origin = upstream
 
         if self.verbose:
             print "Origin branch is " + self.origin
@@ -630,6 +637,7 @@ class P4Sync(Command):
         self.isWindows = (platform.system() == "Windows")
         self.keepRepoPath = False
         self.depotPaths = None
+        self.p4BranchesInGit = []
 
         if gitConfig("git-p4.syncFromOrigin") == "false":
             self.syncWithOrigin = False
@@ -718,6 +726,11 @@ class P4Sync(Command):
                 text += filedata[j]['data']
                 j += 1
 
+
+            if not stat.has_key('depotFile'):
+                sys.stderr.write("p4 print fails with: %s\n" % repr(stat))
+                continue
+
             contents[stat['depotFile']] = text
 
         for f in files:
@@ -760,12 +773,11 @@ class P4Sync(Command):
 
         self.gitStream.write("data <<EOT\n")
         self.gitStream.write(details["desc"])
-        self.gitStream.write("\n[git-p4: depot-paths = \"%s\": change = %s: "
-                             "options = %s]\n"
-                             % (','.join (branchPrefixes), details["change"],
-                                details['options']
-                                ))
-        self.gitStream.write("EOT\n\n")
+        self.gitStream.write("\n[git-p4: depot-paths = \"%s\": change = %s"
+                             % (','.join (branchPrefixes), details["change"]))
+        if len(details['options']) > 0:
+            self.gitStream.write(": options = %s" % details['options'])
+        self.gitStream.write("]\nEOT\n\n")
 
         if len(parent) > 0:
             if self.verbose:
@@ -904,13 +916,14 @@ class P4Sync(Command):
 
     def guessProjectName(self):
         for p in self.depotPaths:
-            return p [p.strip().rfind("/") + 1:]
+            if p.endswith("/"):
+                p = p[:-1]
+            p = p[p.strip().rfind("/") + 1:]
+            if not p.endswith("/"):
+               p += "/"
+            return p
 
     def getBranchMapping(self):
-
-        ## FIXME - what's a P4 projectName ?
-        self.projectName = self.guessProjectName()
-
         for info in p4CmdList("branches"):
             details = p4Cmd("branch -o %s" % info["branch"])
             viewIdx = 0
@@ -947,9 +960,9 @@ class P4Sync(Command):
             if not line.startswith('p4/') or line == "p4/HEAD":
                 continue
             branch = line
-            if self.importIntoRemotes:
-                # strip off p4
-                branch = re.sub ("^p4/", "", line)
+
+            # strip off p4
+            branch = re.sub ("^p4/", "", line)
 
             self.p4BranchesInGit.append(branch)
             self.initialParents[self.refPrefix + branch] = parseRevision(line)
@@ -959,14 +972,16 @@ class P4Sync(Command):
             print ("Creating/updating branch(es) in %s based on origin branch(es)"
                    % self.refPrefix)
 
+        originPrefix = "origin/p4/"
+
         for line in read_pipe_lines("git rev-parse --symbolic --remotes"):
             line = line.strip()
-            if (not line.startswith("origin/")) or line.endswith("HEAD\n"):
+            if (not line.startswith(originPrefix)) or line.endswith("HEAD"):
                 continue
 
-            headName = line[len("origin/"):]
+            headName = line[len(originPrefix):]
             remoteHead = self.refPrefix + headName
-            originHead = "origin/" + headName
+            originHead = line
 
             original = extractSettingsGitLog(extractLogMessageFromGitCommit(originHead))
             if (not original.has_key('depot-paths')
@@ -1019,7 +1034,9 @@ class P4Sync(Command):
         # map from branch depot path to parent branch
         self.knownBranches = {}
         self.initialParents = {}
-        self.hasOrigin = gitBranchExists("origin")
+        self.hasOrigin = gitBranchExists("origin") or gitBranchExists("origin/p4") or gitBranchExists("origin/p4/master")
+        if not self.syncWithOrigin:
+            self.hasOrigin = False
 
         if self.importIntoRemotes:
             self.refPrefix = "refs/remotes/p4/"
@@ -1141,7 +1158,11 @@ class P4Sync(Command):
             self.getLabels();
 
         if self.detectBranches:
-            self.getBranchMapping();
+            ## FIXME - what's a P4 projectName ?
+            self.projectName = self.guessProjectName()
+
+            if not self.hasOrigin:
+                self.getBranchMapping();
             if self.verbose:
                 print "p4-git branches: %s" % self.p4BranchesInGit
                 print "initial parents: %s" % self.initialParents
@@ -1162,7 +1183,7 @@ class P4Sync(Command):
         self.gitError = importProcess.stderr
 
         if self.revision:
-            print "Doing initial import of %s from revision %s" % (' '.join(self.depotPaths), self.revision)
+            print "Doing initial import of %s from revision %s into %s" % (' '.join(self.depotPaths), self.revision, self.branch)
 
             details = { "user" : "git perforce import user", "time" : int(time.time()) }
             details["desc"] = ("Initial import of %s from the state at revision %s"
@@ -1239,6 +1260,9 @@ class P4Sync(Command):
                     print "No changes to import!"
                 return True
 
+            if not self.silent and not self.detectBranches:
+                print "Import destination: %s" % self.branch
+
             self.updatedBranches = set()
 
             cnt = 1
@@ -1300,7 +1324,7 @@ class P4Sync(Command):
                                 parent = self.initialParents[branch]
                                 del self.initialParents[branch]
 
-                            self.commit(description, filesForCommit, branch, branchPrefix, parent)
+                            self.commit(description, filesForCommit, branch, [branchPrefix], parent)
                     else:
                         files = self.extractFilesFromCommit(description)
                         self.commit(description, files, self.branch, self.depotPaths,
@@ -1338,9 +1362,17 @@ class P4Rebase(Command):
     def run(self, args):
         sync = P4Sync()
         sync.run([])
-        print "Rebasing the current branch"
+
+        [upstream, settings] = findUpstreamBranchPoint()
+        if len(upstream) == 0:
+            die("Cannot find upstream branchpoint for rebase")
+
+        # the branchpoint may be p4/foo~3, so strip off the parent
+        upstream = re.sub("~[0-9]+$", "", upstream)
+
+        print "Rebasing the current branch onto %s" % upstream
         oldHead = read_pipe("git rev-parse HEAD").strip()
-        system("git rebase p4")
+        system("git rebase %s" % upstream)
         system("git diff-tree --stat --summary -M %s HEAD" % oldHead)
         return True
 
@@ -1387,7 +1419,8 @@ class P4Clone(P4Sync):
             self.cloneDestination = self.defaultDestination(args)
 
         print "Importing from %s into %s" % (', '.join(depotPaths), self.cloneDestination)
-        os.makedirs(self.cloneDestination)
+        if not os.path.exists(self.cloneDestination):
+            os.makedirs(self.cloneDestination)
         os.chdir(self.cloneDestination)
         system("git init")
         self.gitdir = os.getcwd() + "/.git"