Merge origin.
authorHan-Wen Nienhuys <hanwen@google.com>
Wed, 23 May 2007 21:49:35 +0000 (18:49 -0300)
committerHan-Wen Nienhuys <hanwen@google.com>
Wed, 30 May 2007 16:46:25 +0000 (13:46 -0300)
1  2 
contrib/fast-import/git-p4
index b280e9774227100015cb3c6c8ae7448d0ce844f0,794286ee8e43394c93c0aae66d540efc2da8d26e..28ea53dea4c45fb3112bea175a4f91d5fe0e0d7d
@@@ -15,48 -15,48 +15,48 @@@ import r
  from sets import Set;
  
  gitdir = os.environ.get("GIT_DIR", "")
 -silent = True
 +verbose = False
  
  def write_pipe(c, str):
 -    if not silent:
 +    if verbose:
          sys.stderr.write('writing pipe: %s\n' % c)
  
      pipe = os.popen(c, 'w')
      val = pipe.write(str)
      if pipe.close():
-         sys.stderr.write('Command %s failed\n' % c)
+         sys.stderr.write('Command failed: %s' % c)
          sys.exit(1)
  
      return val
  
 -def read_pipe(c):
 -    if not silent:
 +def read_pipe(c, ignore_error=False):
 +    if verbose:
          sys.stderr.write('reading pipe: %s\n' % c)
  
      pipe = os.popen(c, 'rb')
      val = pipe.read()
 -    if pipe.close():
 -        sys.stderr.write('Command failed: %s' % c)
 +    if pipe.close() and not ignore_error:
-         sys.stderr.write('Command %s failed\n' % c)
++        sys.stderr.write('Command failed: %s\n' % c)
          sys.exit(1)
  
      return val
  
  
  def read_pipe_lines(c):
 -    if not silent:
 +    if verbose:
          sys.stderr.write('reading pipe: %s\n' % c)
      ## todo: check return status
      pipe = os.popen(c, 'rb')
      val = pipe.readlines()
      if pipe.close():
-         sys.stderr.write('Command %s failed\n' % c)
 -        sys.stderr.write('Command failed: %s' % c)
++        sys.stderr.write('Command failed: %s\n' % c)
          sys.exit(1)
  
      return val
  
  def system(cmd):
 -    if not silent:
 -        sys.stderr.write("executing %s" % cmd)
 +    if verbose:
 +        sys.stderr.write("executing %s\n" % cmd)
      if os.system(cmd) != 0:
          die("command failed: %s" % cmd)
  
@@@ -112,8 -112,7 +112,8 @@@ def currentGitBranch()
      return read_pipe("git name-rev HEAD").split(" ")[1].strip()
  
  def isValidGitDir(path):
 -    if os.path.exists(path + "/HEAD") and os.path.exists(path + "/refs") and os.path.exists(path + "/objects"):
 +    if (os.path.exists(path + "/HEAD")
 +        and os.path.exists(path + "/refs") and os.path.exists(path + "/objects")):
          return True;
      return False
  
@@@ -134,34 -133,31 +134,34 @@@ def extractLogMessageFromGitCommit(comm
         logMessage += log
      return logMessage
  
 -def extractDepotPathAndChangeFromGitLog(log):
 +def extractSettingsGitLog(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")
 +        m = re.search (r"^ *\[git-p4: (.*)\]$", line)
 +        if not m:
 +            continue
 +
 +        assignments = m.group(1).split (':')
 +        for a in assignments:
 +            vals = a.split ('=')
 +            key = vals[0].strip()
 +            val = ('='.join (vals[1:])).strip()
 +            if val.endswith ('\"') and val.startswith('"'):
 +                val = val[1:-1]
 +
 +            values[key] = val
 +
 +    values['depot-paths'] = values.get("depot-paths").split(',')
 +    return values
  
  def gitBranchExists(branch):
 -    proc = subprocess.Popen(["git", "rev-parse", branch], stderr=subprocess.PIPE, stdout=subprocess.PIPE);
 +    proc = subprocess.Popen(["git", "rev-parse", branch],
 +                            stderr=subprocess.PIPE, stdout=subprocess.PIPE);
      return proc.wait() == 0;
  
  def gitConfig(key):
 -    return os.popen("git config %s" % key, "rb").read()[:-1]
 +    return read_pipe("git config %s" % key, ignore_error=True).strip()
  
  class Command:
      def __init__(self):
@@@ -172,8 -168,7 +172,8 @@@ class P4Debug(Command)
      def __init__(self):
          Command.__init__(self)
          self.options = [
 -        ]
 +            optparse.make_option("--verbose", dest="verbose", action="store_true"),
 +            ]
          self.description = "A tool to debug the output of p4 -G."
          self.needsGit = False
  
@@@ -213,30 -208,21 +213,30 @@@ class P4RollBack(Command)
                  line = line.strip()
                  ref = refPrefix + line
                  log = extractLogMessageFromGitCommit(ref)
 -                depotPath, change = extractDepotPathAndChangeFromGitLog(log)
 +                settings = extractSettingsGitLog(log)
 +
 +                depotPaths = settings['depot-paths']
 +                change = settings['change']
 +
                  changed = False
  
 -                if len(p4Cmd("changes -m 1 %s...@%s" % (depotPath, maxChange))) == 0:
 +                if len(p4Cmd("changes -m 1 "  + ' '.join (['%s...@%s' % (p, maxChange)
 +                                                           for p in depotPaths]))) == 0:
                      print "Branch %s did not exist at change %s, deleting." % (ref, maxChange)
                      system("git update-ref -d %s `git rev-parse %s`" % (ref, ref))
                      continue
  
 -                while len(change) > 0 and int(change) > maxChange:
 +                while change and int(change) > maxChange:
                      changed = True
                      if self.verbose:
                          print "%s is at %s ; rewinding towards %s" % (ref, change, maxChange)
                      system("git update-ref %s \"%s^\"" % (ref, ref))
                      log = extractLogMessageFromGitCommit(ref)
 -                    depotPath, change = extractDepotPathAndChangeFromGitLog(log)
 +                    settings =  extractSettingsGitLog(log)
 +
 +
 +                    depotPaths = settings['depot-paths']
 +                    change = settings['change']
  
                  if changed:
                      print "%s rewound to %s" % (ref, change)
@@@ -248,7 -234,6 +248,7 @@@ class P4Submit(Command)
          Command.__init__(self)
          self.options = [
                  optparse.make_option("--continue", action="store_false", dest="firstTime"),
 +                optparse.make_option("--verbose", dest="verbose", action="store_true"),
                  optparse.make_option("--origin", dest="origin"),
                  optparse.make_option("--reset", action="store_true", dest="reset"),
                  optparse.make_option("--log-substitutions", dest="substFile"),
              return False
  
          depotPath = ""
 +        settings = None
          if gitBranchExists("p4"):
 -            [depotPath, dummy] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("p4"))
 +            settings = extractSettingsGitLog(extractLogMessageFromGitCommit("p4"))
          if len(depotPath) == 0 and gitBranchExists("origin"):
 -            [depotPath, dummy] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("origin"))
 +            settings = extractSettingsGitLog(extractLogMessageFromGitCommit("origin"))
 +        depotPaths = settings['depot-paths']
  
          if len(depotPath) == 0:
              print "Internal error: cannot locate perforce depot path from existing branches"
@@@ -583,7 -566,7 +583,7 @@@ class P4Sync(Command)
                  optparse.make_option("--verbose", dest="verbose", action="store_true"),
                  optparse.make_option("--import-local", dest="importIntoRemotes", action="store_false"),
                  optparse.make_option("--max-changes", dest="maxChanges"),
 -                optparse.make_option("--keep-path", dest="keepRepoPath")
 +                optparse.make_option("--keep-path", dest="keepRepoPath", action='store_true')
          ]
          self.description = """Imports from Perforce into a git repository.\n
      example:
          self.importIntoRemotes = True
          self.maxChanges = ""
          self.isWindows = (platform.system() == "Windows")
 -        self.depotPath = None
          self.keepRepoPath = False
 +        self.depotPaths = None
  
          if gitConfig("git-p4.syncFromOrigin") == "false":
              self.syncWithOrigin = False
          fnum = 0
          while commit.has_key("depotFile%s" % fnum):
              path =  commit["depotFile%s" % fnum]
 -            if not path.startswith(self.depotPath):
 -    #            if not self.silent:
 -    #                print "\nchanged files: ignoring path %s outside of %s in change %s" % (path, self.depotPath, change)
 +
 +            found = [p for p in self.depotPaths
 +                     if path.startswith (p)]
 +            if not found:
                  fnum = fnum + 1
                  continue
  
              fnum = fnum + 1
          return files
  
 -    def stripRepoPath(self, path, prefix):
 +    def stripRepoPath(self, path, prefixes):
          if self.keepRepoPath:
 -            prefix = re.sub("^(//[^/]+/).*", r'\1', prefix)
 +            prefixes = [re.sub("^(//[^/]+/).*", r'\1', prefixes[0])]
 +
 +        for p in prefixes:
 +            if path.startswith(p):
 +                path = path[len(p):]
  
 -        return path[len(prefix):]
 +        return path
  
      def splitFilesIntoBranches(self, commit):
          branches = {}
          fnum = 0
          while commit.has_key("depotFile%s" % fnum):
              path =  commit["depotFile%s" % fnum]
 -            if not path.startswith(self.depotPath):
 -    #            if not self.silent:
 -    #                print "\nchanged files: ignoring path %s outside of %s in change %s" % (path, self.depotPath, change)
 +            found = [p for p in self.depotPaths
 +                     if path.startswith (p)]
 +            if not found:
                  fnum = fnum + 1
                  continue
  
              file["type"] = commit["type%s" % fnum]
              fnum = fnum + 1
  
 -            relPath = self.stripRepoPath(path, self.depotPath)
 +            relPath = self.stripRepoPath(path, self.depotPaths)
  
              for branch in self.knownBranches.keys():
  
  
          return branches
  
 -    def commit(self, details, files, branch, branchPrefix, parent = ""):
 +    def commit(self, details, files, branch, branchPrefixes, parent = ""):
          epoch = details["time"]
          author = details["user"]
  
  
          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-paths = \"%s\": change = %s: "
 +                             "options = %s]\n"
 +                             % (','.join (branchPrefixes), details["change"],
 +                                details['options']
 +                                ))
          self.gitStream.write("EOT\n\n")
  
          if len(parent) > 0:
  
          for file in files:
              path = file["path"]
 -            if not path.startswith(branchPrefix):
 -    #                print "\nchanged files: ignoring path %s outside of branch prefix %s in change %s" % (path, branchPrefix, details["change"])
 +
 +
 +            if not [p for p in branchPrefixes if path.startswith(p)]:
                  continue
              rev = file["rev"]
              depotPath = path + "#" + rev
 -            relPath = self.stripRepoPath(path, branchPrefix)
 +            relPath = self.stripRepoPath(path, branchPrefixes)
              action = file["action"]
  
              if file["type"] == "apple":
              if self.verbose:
                  print "Change %s is labelled %s" % (change, labelDetails)
  
 -            files = p4CmdList("files %s...@%s" % (branchPrefix, change))
 +            files = p4CmdList("files " + ' '.join (["%s...@%s" % (p, change)
 +                                                    for p in branchPrefixes]))
  
              if len(files) == len(labelRevisions):
  
      def getLabels(self):
          self.labels = {}
  
 -        l = p4CmdList("labels %s..." % self.depotPath)
 +        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.depotPath`
  
          for output in l:
              label = output["label"]
              newestChange = 0
              if self.verbose:
                  print "Querying files for label %s" % label
 -            for file in p4CmdList("files %s...@%s" % (self.depotPath, label)):
 +            for file in p4CmdList("files "
 +                                  +  ' '.join (["%s...@%s" % (p, label)
 +                                                for p in self.depotPaths])):
                  revisions[file["depotFile"]] = file["rev"]
                  change = int(file["change"])
                  if change > newestChange:
              print "Label changes: %s" % self.labels.keys()
  
      def getBranchMapping(self):
 +
 +        ## FIXME - what's a P4 projectName ?
          self.projectName = self.depotPath[self.depotPath.strip().rfind("/") + 1:]
  
          for info in p4CmdList("branches"):
              cmdline += " --branches"
  
          for line in read_pipe_lines(cmdline):
-             lie = line.strip()
-             if self.importIntoRemotes and ((not line.startswith("p4/")) or line == "p4/HEAD\n"):
+             line = line.strip()
+             if self.importIntoRemotes and ((not line.startswith("p4/")) or line == "p4/HEAD"):
                  continue
  
              if self.importIntoRemotes:
              print "Creating/updating branch(es) in %s based on origin branch(es)" % self.refPrefix
  
          for line in read_pipe_lines("git rev-parse --symbolic --remotes"):
 +            line = line.strip()
              if (not line.startswith("origin/")) or line.endswith("HEAD\n"):
                  continue
  
 -            headName = line[len("origin/"):-1]
 +            headName = line[len("origin/"):]
              remoteHead = self.refPrefix + headName
              originHead = "origin/" + headName
  
 -            [originPreviousDepotPath, originP4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(originHead))
 -            if len(originPreviousDepotPath) == 0 or len(originP4Change) == 0:
 +            original = extractSettingsGitLog(extractLogMessageFromGitCommit(originHead))
 +            if (not original.has_key('depot-paths')
 +                or not original.has_key('change')):
                  continue
  
              update = False
                      print "creating %s" % remoteHead
                  update = True
              else:
 -                [p4PreviousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(remoteHead))
 -                if len(p4Change) > 0:
 -                    if originPreviousDepotPath == p4PreviousDepotPath:
 -                        originP4Change = int(originP4Change)
 -                        p4Change = int(p4Change)
 +                settings =  extractSettingsGitLog(extractLogMessageFromGitCommit(remoteHead))
 +                if settings.has_key('change') > 0:
 +                    if settings['depot-paths'] == original['depot-paths']:
 +                        originP4Change = int(original['change'])
 +                        p4Change = int(settings['change'])
                          if originP4Change > p4Change:
 -                            print "%s (%s) is newer than %s (%s). Updating p4 branch from origin." % (originHead, originP4Change, remoteHead, p4Change)
 +                            print ("%s (%s) is newer than %s (%s). "
 +                                   "Updating p4 branch from origin."
 +                                   % (originHead, originP4Change,
 +                                      remoteHead, p4Change))
                              update = True
                      else:
 -                        print "Ignoring: %s was imported from %s while %s was imported from %s" % (originHead, originPreviousDepotPath, remoteHead, p4PreviousDepotPath)
 +                        print ("Ignoring: %s was imported from %s while "
 +                               "%s was imported from %s"
 +                               % (originHead, ','.join(original['depot-paths']),
 +                                  remoteHead, ','.join(settings['depot-paths'])))
  
              if update:
                  system("git update-ref %s %s" % (remoteHead, originHead))
  
 +    def updateOptionDict(self, d):
 +        option_keys = {}
 +        if self.keepRepoPath:
 +            option_keys['keepRepoPath'] = 1
 +
 +        d["options"] = ' '.join(sorted(option_keys.keys()))
 +
 +    def readOptions(self, d):
 +        self.keepRepoPath = (d.has_key('options')
 +                             and ('keepRepoPath' in d['options']))
 +
      def run(self, args):
 -        self.depotPath = ""
 +        self.depotPaths = []
          self.changeRange = ""
          self.initialParent = ""
 -        self.previousDepotPath = ""
 +        self.previousDepotPaths = []
  
          # map from branch depot path to parent branch
          self.knownBranches = {}
              if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes:
                  system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch))
  
 -        if len(args) == 0:
 +        ### FIXME
 +        if 1:
              if self.hasOrigin:
                  self.createOrUpdateBranchesFromOrigin()
              self.listExistingP4GitBranches()
              p4Change = 0
              for branch in self.p4BranchesInGit:
                  logMsg =  extractLogMessageFromGitCommit(self.refPrefix + branch)
 -                (depotPath, change) = extractDepotPathAndChangeFromGitLog(logMsg)
 +
 +                settings = extractSettingsGitLog(logMsg)
  
                  if self.verbose:
 -                    print "path %s change %s" % (depotPath, change)
 +                    print "path %s change %s" % (','.join(depotPaths), change)
  
 -                if len(depotPath) > 0 and len(change) > 0:
 -                    change = int(change) + 1
 +                self.readOptions(settings)
 +                if (settings.has_key('depot-paths')
 +                    and settings.has_key ('change')):
 +                    change = int(settings['change']) + 1
                      p4Change = max(p4Change, change)
  
 -                    if len(self.previousDepotPath) == 0:
 -                        self.previousDepotPath = depotPath
 +                    depotPaths = sorted(settings['depot-paths'])
 +                    if self.previousDepotPaths == []:
 +                        self.previousDepotPaths = depotPaths
                      else:
 -                        i = 0
 -                        l = min(len(self.previousDepotPath), len(depotPath))
 -                        while i < l and self.previousDepotPath[i] == depotPath[i]:
 -                            i = i + 1
 -                        self.previousDepotPath = self.previousDepotPath[:i]
 +                        paths = []
 +                        for (prev, cur) in zip(self.previousDepotPaths, depotPaths):
 +                            for i in range(0, max(len(cur), len(prev))):
 +                                if cur[i] <> prev[i]:
 +                                    break
 +
 +                            paths.append (cur[:i])
 +
 +                        self.previousDepotPaths = paths
  
              if p4Change > 0:
 -                self.depotPath = self.previousDepotPath
 +                self.depotPaths = sorted(self.previousDepotPaths)
                  self.changeRange = "@%s,#head" % p4Change
                  self.initialParent = parseRevision(self.branch)
                  if not self.silent and not self.detectBranches:
          if not self.branch.startswith("refs/"):
              self.branch = "refs/heads/" + self.branch
  
 -        if len(self.depotPath) != 0:
 -            self.depotPath = self.depotPath.strip()
 -
 -        if len(args) == 0 and len(self.depotPath) != 0:
 +        if len(args) == 0 and self.depotPaths:
              if not self.silent:
 -                print "Depot path: %s" % self.depotPath
 -        elif len(args) != 1:
 -            return False
 +                print "Depot paths: %s" % ' '.join(self.depotPaths)
          else:
 -            if len(self.depotPath) != 0 and self.depotPath != args[0]:
 +            if self.depotPaths and self.depotPaths != args:
                  print ("previous import used depot path %s and now %s was specified. "
 -                       "This doesn't work!" % (self.depotPath, args[0]))
 +                       "This doesn't work!" % (' '.join (self.depotPaths),
 +                                               ' '.join (args)))
                  sys.exit(1)
 -            self.depotPath = args[0]
 +
 +            self.depotPaths = sorted(args)
  
          self.revision = ""
          self.users = {}
  
 -        if self.depotPath.find("@") != -1:
 -            atIdx = self.depotPath.index("@")
 -            self.changeRange = self.depotPath[atIdx:]
 -            if self.changeRange == "@all":
 -                self.changeRange = ""
 -            elif self.changeRange.find(",") == -1:
 -                self.revision = self.changeRange
 -                self.changeRange = ""
 -            self.depotPath = self.depotPath[0:atIdx]
 -        elif self.depotPath.find("#") != -1:
 -            hashIdx = self.depotPath.index("#")
 -            self.revision = self.depotPath[hashIdx:]
 -            self.depotPath = self.depotPath[0:hashIdx]
 -        elif len(self.previousDepotPath) == 0:
 -            self.revision = "#head"
 -
 -        self.depotPath = re.sub ("\.\.\.$", "", self.depotPath)
 -        if not self.depotPath.endswith("/"):
 -            self.depotPath += "/"
 +        newPaths = []
 +        for p in self.depotPaths:
 +            if p.find("@") != -1:
 +                atIdx = p.index("@")
 +                self.changeRange = p[atIdx:]
 +                if self.changeRange == "@all":
 +                    self.changeRange = ""
 +                elif self.changeRange.find(",") == -1:
 +                    self.revision = self.changeRange
 +                    self.changeRange = ""
 +                p = p[0:atIdx]
 +            elif p.find("#") != -1:
 +                hashIdx = p.index("#")
 +                self.revision = p[hashIdx:]
 +                p = p[0:hashIdx]
 +            elif self.previousDepotPaths == []:
 +                self.revision = "#head"
 +
 +            p = re.sub ("\.\.\.$", "", p)
 +            if not p.endswith("/"):
 +                p += "/"
 +
 +            newPaths.append(p)
 +
 +        self.depotPaths = newPaths
 +
  
          self.loadUserMapFromCache()
          self.labels = {}
                  print "initial parents: %s" % self.initialParents
              for b in self.p4BranchesInGit:
                  if b != "master":
 +
 +                    ## FIXME
                      b = b[len(self.projectName):]
                  self.createdBranches.add(b)
  
          self.tz = "%+03d%02d" % (- time.timezone / 3600, ((- time.timezone % 3600) / 60))
  
          importProcess = subprocess.Popen(["git", "fast-import"],
 -                                         stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE);
 +                                         stdin=subprocess.PIPE, stdout=subprocess.PIPE,
 +                                         stderr=subprocess.PIPE);
          self.gitOutput = importProcess.stdout
          self.gitStream = importProcess.stdin
          self.gitError = importProcess.stderr
  
          if len(self.revision) > 0:
 -            print "Doing initial import of %s from revision %s" % (self.depotPath, self.revision)
 +            print "Doing initial import of %s from revision %s" % (' '.join(self.depotPaths), self.revision)
  
              details = { "user" : "git perforce import user", "time" : int(time.time()) }
              details["desc"] = ("Initial import of %s from the state at revision %s"
 -                               % (self.depotPath, self.revision))
 +                               % (' '.join(self.depotPaths), self.revision))
              details["change"] = self.revision
              newestRevision = 0
  
              fileCnt = 0
 -            for info in p4CmdList("files %s...%s" % (self.depotPath, self.revision)):
 +            for info in p4CmdList("files "
 +                                  +  ' '.join(["%s...%s"
 +                                               % (p, self.revision)
 +                                               for p in self.depotPaths])):
                  change = int(info["change"])
                  if change > newestRevision:
                      newestRevision = change
                  fileCnt = fileCnt + 1
  
              details["change"] = newestRevision
 -
 +            self.updateOptionDict(details)
              try:
 -                self.commit(details, self.extractFilesFromCommit(details), self.branch, self.depotPath)
 +                self.commit(details, self.extractFilesFromCommit(details), self.branch, self.depotPaths)
              except IOError:
                  print "IO error with git fast-import. Is your git version recent enough?"
                  print self.gitError.read()
                  changes.sort()
              else:
                  if self.verbose:
 -                    print "Getting p4 changes for %s...%s" % (self.depotPath, self.changeRange)
 -                output = read_pipe_lines("p4 changes %s...%s" % (self.depotPath, self.changeRange))
 +                    print "Getting p4 changes for %s...%s" % (`self.depotPaths`,
 +                                                              self.changeRange)
 +                assert self.depotPaths
 +                output = read_pipe_lines("p4 changes " + ' '.join (["%s...%s" % (p, self.changeRange)
 +                                                                    for p in self.depotPaths]))
  
                  for line in output:
                      changeNum = line.split(" ")[1]
              cnt = 1
              for change in changes:
                  description = p4Cmd("describe %s" % change)
 +                self.updateOptionDict(description)
  
                  if not self.silent:
                      sys.stdout.write("\rImporting revision %s (%s%%)" % (change, cnt * 100 / len(changes)))
                      if self.detectBranches:
                          branches = self.splitFilesIntoBranches(description)
                          for branch in branches.keys():
 -                            branchPrefix = self.depotPath + branch + "/"
 +                            ## HACK  --hwn
 +                            branchPrefix = self.depotPaths[0] + branch + "/"
  
                              parent = ""
  
                              if branch == "main":
                                  branch = "master"
                              else:
 +
 +                                ## FIXME
                                  branch = self.projectName + branch
  
                              if parent == "main":
                                  parent = "master"
                              elif len(parent) > 0:
 +                                ## FIXME
                                  parent = self.projectName + parent
  
                              branch = self.refPrefix + branch
                              self.commit(description, filesForCommit, branch, branchPrefix, parent)
                      else:
                          files = self.extractFilesFromCommit(description)
 -                        self.commit(description, files, self.branch, self.depotPath, self.initialParent)
 +                        self.commit(description, files, self.branch, self.depotPaths,
 +                                    self.initialParent)
                          self.initialParent = ""
                  except IOError:
                      print self.gitError.read()
@@@ -1274,12 -1195,7 +1274,12 @@@ class P4Clone(P4Sync)
      def __init__(self):
          P4Sync.__init__(self)
          self.description = "Creates a new git repository and imports from Perforce into it"
 -        self.usage = "usage: %prog [options] //depot/path[@revRange] [directory]"
 +        self.usage = "usage: %prog [options] //depot/path[@revRange]"
 +        self.options.append(
 +            optparse.make_option("--destination", dest="cloneDestination",
 +                                 action='store', default=None,
 +                                 help="where to leave result of the clone"))
 +        self.cloneDestination = None
          self.needsGit = False
  
      def run(self, args):
  
          if len(args) < 1:
              return False
 -        depotPath = args[0]
 -        destination = ""
 -        if len(args) == 2:
 -            destination = args[1]
 -        elif len(args) > 2:
 -            return False
  
 -        if not depotPath.startswith("//"):
 -            return False
 +        if self.keepRepoPath and not self.cloneDestination:
 +            sys.stderr.write("Must specify destination for --keep-path\n")
 +            sys.exit(1)
 +
 +        depotPaths = args
 +        for p in depotPaths:
 +            if not p.startswith("//"):
 +                return False
  
 -        depotDir = re.sub("(@[^@]*)$", "", depotPath)
 -        depotDir = re.sub("(#[^#]*)$", "", depotDir)
 -        depotDir = re.sub(r"\.\.\.$,", "", depotDir)
 -        depotDir = re.sub(r"/$", "", depotDir)
 +        if not self.cloneDestination:
 +            depotPath = args[0]
 +            depotDir = re.sub("(@[^@]*)$", "", depotPath)
 +            depotDir = re.sub("(#[^#]*)$", "", depotDir)
 +            depotDir = re.sub(r"\.\.\.$,", "", depotDir)
 +            depotDir = re.sub(r"/$", "", depotDir)
  
 -        if not destination:
 -            destination = os.path.split(depotDir)[1]
 +            self.cloneDestination = os.path.split(depotDir)[1]
  
 -        print "Importing from %s into %s" % (depotPath, destination)
 -        os.makedirs(destination)
 -        os.chdir(destination)
 +        print "Importing from %s into %s" % (`depotPaths`, self.cloneDestination)
 +        os.makedirs(self.cloneDestination)
 +        os.chdir(self.cloneDestination)
          system("git init")
          gitdir = os.getcwd() + "/.git"
 -        if not P4Sync.run(self, [depotPath]):
 +        if not P4Sync.run(self, depotPaths):
              return False
          if self.branch != "master":
              if gitBranchExists("refs/remotes/p4/master"):
@@@ -1348,60 -1263,53 +1348,60 @@@ commands = 
      "rollback" : P4RollBack()
  }
  
 -if len(sys.argv[1:]) == 0:
 -    printUsage(commands.keys())
 -    sys.exit(2)
 -
 -cmd = ""
 -cmdName = sys.argv[1]
 -try:
 -    cmd = commands[cmdName]
 -except KeyError:
 -    print "unknown command %s" % cmdName
 -    print ""
 -    printUsage(commands.keys())
 -    sys.exit(2)
 -
 -options = cmd.options
 -cmd.gitdir = gitdir
  
 -args = sys.argv[2:]
 +def main():
 +    if len(sys.argv[1:]) == 0:
 +        printUsage(commands.keys())
 +        sys.exit(2)
  
 -if len(options) > 0:
 -    options.append(optparse.make_option("--git-dir", dest="gitdir"))
 +    cmd = ""
 +    cmdName = sys.argv[1]
 +    try:
 +        cmd = commands[cmdName]
 +    except KeyError:
 +        print "unknown command %s" % cmdName
 +        print ""
 +        printUsage(commands.keys())
 +        sys.exit(2)
 +
 +    options = cmd.options
 +    cmd.gitdir = gitdir
 +
 +    args = sys.argv[2:]
 +
 +    if len(options) > 0:
 +        options.append(optparse.make_option("--git-dir", dest="gitdir"))
 +
 +        parser = optparse.OptionParser(cmd.usage.replace("%prog", "%prog " + cmdName),
 +                                       options,
 +                                       description = cmd.description,
 +                                       formatter = HelpFormatter())
 +
 +        (cmd, args) = parser.parse_args(sys.argv[2:], cmd);
 +    global verbose
 +    verbose = cmd.verbose
 +    if cmd.needsGit:
 +        gitdir = cmd.gitdir
 +        if len(gitdir) == 0:
 +            gitdir = ".git"
 +            if not isValidGitDir(gitdir):
 +                gitdir = read_pipe("git rev-parse --git-dir").strip()
 +                if os.path.exists(gitdir):
 +                    cdup = read_pipe("git rev-parse --show-cdup").strip()
 +                    if len(cdup) > 0:
 +                        os.chdir(cdup);
  
 -    parser = optparse.OptionParser(cmd.usage.replace("%prog", "%prog " + cmdName),
 -                                   options,
 -                                   description = cmd.description,
 -                                   formatter = HelpFormatter())
 +        if not isValidGitDir(gitdir):
 +            if isValidGitDir(gitdir + "/.git"):
 +                gitdir += "/.git"
 +            else:
 +                die("fatal: cannot locate git repository at %s" % gitdir)
  
 -    (cmd, args) = parser.parse_args(sys.argv[2:], cmd);
 +        os.environ["GIT_DIR"] = gitdir
  
 -if cmd.needsGit:
 -    gitdir = cmd.gitdir
 -    if len(gitdir) == 0:
 -        gitdir = ".git"
 -        if not isValidGitDir(gitdir):
 -            gitdir = read_pipe("git rev-parse --git-dir").strip()
 -            if os.path.exists(gitdir):
 -                cdup = read_pipe("git rev-parse --show-cdup").strip()
 -                if len(cdup) > 0:
 -                    os.chdir(cdup);
 -
 -    if not isValidGitDir(gitdir):
 -        if isValidGitDir(gitdir + "/.git"):
 -            gitdir += "/.git"
 -        else:
 -            die("fatal: cannot locate git repository at %s" % gitdir)
 +    if not cmd.run(args):
 +        parser.print_help()
  
 -    os.environ["GIT_DIR"] = gitdir
  
 -if not cmd.run(args):
 -    parser.print_help()
 +if __name__ == '__main__':
 +    main()