From: Junio C Hamano Date: Wed, 24 Jun 2015 19:21:56 +0000 (-0700) Subject: Merge branch 'ld/p4-changes-block-size' X-Git-Tag: v2.5.0-rc0~9 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/b79bbed185403abfe9ae1b8fc14bb94ae3b1f8cb?hp=-c Merge branch 'ld/p4-changes-block-size' 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 --- b79bbed185403abfe9ae1b8fc14bb94ae3b1f8cb diff --combined git-p4.py index 26ad4bcf77,73f05f0a88..073f87bbfd --- a/git-p4.py +++ 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 = [] @@@ -2145,7 -2186,7 +2186,7 @@@ # 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 ]