]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'ld/p4-changes-block-size'
authorJunio C Hamano <gitster@pobox.com>
Wed, 24 Jun 2015 19:21:56 +0000 (12:21 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 24 Jun 2015 19:21:57 +0000 (12:21 -0700)
More Perforce row number limit workaround for "git p4".

* ld/p4-changes-block-size:
  git-p4: fixing --changes-block-size handling
  git-p4: add tests for non-numeric revision range
  git-p4: test with limited p4 server results
  git-p4: additional testing of --changes-block-size

1  2 
git-p4.py

diff --combined git-p4.py
index 26ad4bcf77e36624e4261ae2dfd93ba637914b9d,73f05f0a88c2c32002994e2236481d7cb8800691..073f87bbfdc1dc7ebc3fe610e78709667f597d82
+++ b/git-p4.py
@@@ -43,6 -43,9 +43,9 @@@ verbose = Fals
  # Only labels/tags matching this will be imported/exported
  defaultLabelRegexp = r'[a-zA-Z0-9_\-.]+$'
  
+ # Grab changes in blocks of this many revisions, unless otherwise requested
+ defaultBlockSize = 512
  def p4_build_cmd(cmd):
      """Build a suitable p4 command line.
  
@@@ -249,6 -252,10 +252,10 @@@ def p4_reopen(type, f)
  def p4_move(src, dest):
      p4_system(["move", "-k", wildcard_encode(src), wildcard_encode(dest)])
  
+ def p4_last_change():
+     results = p4CmdList(["changes", "-m", "1"])
+     return int(results[0]['change'])
  def p4_describe(change):
      """Make sure it returns a valid result by checking for
         the presence of field "time".  Return a dict of the
@@@ -742,43 -749,77 +749,77 @@@ def createOrUpdateBranchesFromOrigin(lo
  def originP4BranchesExist():
          return gitBranchExists("origin") or gitBranchExists("origin/p4") or gitBranchExists("origin/p4/master")
  
- def p4ChangesForPaths(depotPaths, changeRange, block_size):
+ def p4ParseNumericChangeRange(parts):
+     changeStart = int(parts[0][1:])
+     if parts[1] == '#head':
+         changeEnd = p4_last_change()
+     else:
+         changeEnd = int(parts[1])
+     return (changeStart, changeEnd)
+ def chooseBlockSize(blockSize):
+     if blockSize:
+         return blockSize
+     else:
+         return defaultBlockSize
+ def p4ChangesForPaths(depotPaths, changeRange, requestedBlockSize):
      assert depotPaths
-     assert block_size
  
-     # Parse the change range into start and end
+     # Parse the change range into start and end. Try to find integer
+     # revision ranges as these can be broken up into blocks to avoid
+     # hitting server-side limits (maxrows, maxscanresults). But if
+     # that doesn't work, fall back to using the raw revision specifier
+     # strings, without using block mode.
      if changeRange is None or changeRange == '':
-         changeStart = '@1'
-         changeEnd = '#head'
+         changeStart = 1
+         changeEnd = p4_last_change()
+         block_size = chooseBlockSize(requestedBlockSize)
      else:
          parts = changeRange.split(',')
          assert len(parts) == 2
-         changeStart = parts[0]
-         changeEnd = parts[1]
+         try:
+             (changeStart, changeEnd) = p4ParseNumericChangeRange(parts)
+             block_size = chooseBlockSize(requestedBlockSize)
+         except:
+             changeStart = parts[0][1:]
+             changeEnd = parts[1]
+             if requestedBlockSize:
+                 die("cannot use --changes-block-size with non-numeric revisions")
+             block_size = None
  
      # Accumulate change numbers in a dictionary to avoid duplicates
      changes = {}
  
      for p in depotPaths:
          # Retrieve changes a block at a time, to prevent running
-         # into a MaxScanRows error from the server.
-         start = changeStart
-         end = changeEnd
-         get_another_block = True
-         while get_another_block:
-             new_changes = []
+         # into a MaxResults/MaxScanRows error from the server.
+         while True:
              cmd = ['changes']
-             cmd += ['-m', str(block_size)]
-             cmd += ["%s...%s,%s" % (p, start, end)]
+             if block_size:
+                 end = min(changeEnd, changeStart + block_size)
+                 revisionRange = "%d,%d" % (changeStart, end)
+             else:
+                 revisionRange = "%s,%s" % (changeStart, changeEnd)
+             cmd += ["%s...@%s" % (p, revisionRange)]
              for line in p4_read_pipe_lines(cmd):
                  changeNum = int(line.split(" ")[1])
-                 new_changes.append(changeNum)
                  changes[changeNum] = True
-             if len(new_changes) == block_size:
-                 get_another_block = True
-                 end = '@' + str(min(new_changes))
-             else:
-                 get_another_block = False
+             if not block_size:
+                 break
+             if end >= changeEnd:
+                 break
+             changeStart = end + 1
  
      changelist = changes.keys()
      changelist.sort()
@@@ -1974,7 -2015,7 +2015,7 @@@ class P4Sync(Command, P4UserMap)
          self.syncWithOrigin = True
          self.importIntoRemotes = True
          self.maxChanges = ""
-         self.changes_block_size = 500
+         self.changes_block_size = None
          self.keepRepoPath = False
          self.depotPaths = None
          self.p4BranchesInGit = []
              # 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']])
 +            text = p4_read_pipe(['print', '-q', '-o', '-', "%s@%s" % (file['depotFile'], file['change']) ])
              if p4_version_string().find("/NT") >= 0:
                  text = text.replace("\r\n", "\n")
              contents = [ text ]