diff options
Diffstat (limited to 'git-p4.py')
-rwxr-xr-x | git-p4.py | 144 |
1 files changed, 91 insertions, 53 deletions
@@ -368,7 +368,7 @@ def getP4OpenedType(file): # Returns the perforce file type for the given file. result = p4_read_pipe(["opened", wildcard_encode(file)]) - match = re.match(".*\((.+)\)\r?$", result) + match = re.match(".*\((.+)\)( \*exclusive\*)?\r?$", result) if match: return match.group(1) else: @@ -502,12 +502,14 @@ def p4Cmd(cmd): def p4Where(depotPath): if not depotPath.endswith("/"): depotPath += "/" - depotPath = depotPath + "..." - outputList = p4CmdList(["where", depotPath]) + depotPathLong = depotPath + "..." + outputList = p4CmdList(["where", depotPathLong]) output = None for entry in outputList: if "depotFile" in entry: - if entry["depotFile"] == depotPath: + # Search for the base client side depot path, as long as it starts with the branch's P4 path. + # The base path always ends with "/...". + if entry["depotFile"].find(depotPath) == 0 and entry["depotFile"][-4:] == "/...": output = entry break elif "data" in entry: @@ -740,17 +742,43 @@ def createOrUpdateBranchesFromOrigin(localRefPrefix = "refs/remotes/p4/", silent def originP4BranchesExist(): return gitBranchExists("origin") or gitBranchExists("origin/p4") or gitBranchExists("origin/p4/master") -def p4ChangesForPaths(depotPaths, changeRange): +def p4ChangesForPaths(depotPaths, changeRange, block_size): assert depotPaths - cmd = ['changes'] - for p in depotPaths: - cmd += ["%s...%s" % (p, changeRange)] - output = p4_read_pipe_lines(cmd) + assert block_size + + # Parse the change range into start and end + if changeRange is None or changeRange == '': + changeStart = '@1' + changeEnd = '#head' + else: + parts = changeRange.split(',') + assert len(parts) == 2 + changeStart = parts[0] + changeEnd = parts[1] + # Accumulate change numbers in a dictionary to avoid duplicates changes = {} - for line in output: - changeNum = int(line.split(" ")[1]) - changes[changeNum] = True + + 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 = [] + cmd = ['changes'] + cmd += ['-m', str(block_size)] + cmd += ["%s...%s,%s" % (p, start, end)] + 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 changelist = changes.keys() changelist.sort() @@ -1238,6 +1266,28 @@ class P4Submit(Command, P4UserMap): if response == 'n': return False + def get_diff_description(self, editedFiles, filesToAdd): + # diff + if os.environ.has_key("P4DIFF"): + del(os.environ["P4DIFF"]) + diff = "" + for editedFile in editedFiles: + diff += p4_read_pipe(['diff', '-du', + wildcard_encode(editedFile)]) + + # new file diff + newdiff = "" + for newFile in filesToAdd: + newdiff += "==== new file ====\n" + newdiff += "--- /dev/null\n" + newdiff += "+++ %s\n" % newFile + f = open(newFile, "r") + for line in f.readlines(): + newdiff += "+" + line + f.close() + + return (diff + newdiff).replace('\r\n', '\n') + def applyCommit(self, id): """Apply one commit, return True if it succeeded.""" @@ -1398,34 +1448,15 @@ class P4Submit(Command, P4UserMap): submitTemplate += "######## Variable git-p4.skipUserNameCheck hides this message.\n" separatorLine = "######## everything below this line is just the diff #######\n" + if not self.prepare_p4_only: + submitTemplate += separatorLine + submitTemplate += self.get_diff_description(editedFiles, filesToAdd) - # diff - if os.environ.has_key("P4DIFF"): - del(os.environ["P4DIFF"]) - diff = "" - for editedFile in editedFiles: - diff += p4_read_pipe(['diff', '-du', - wildcard_encode(editedFile)]) - - # new file diff - newdiff = "" - for newFile in filesToAdd: - newdiff += "==== new file ====\n" - newdiff += "--- /dev/null\n" - newdiff += "+++ %s\n" % newFile - f = open(newFile, "r") - for line in f.readlines(): - newdiff += "+" + line - f.close() - - # change description file: submitTemplate, separatorLine, diff, newdiff (handle, fileName) = tempfile.mkstemp() - tmpFile = os.fdopen(handle, "w+") + tmpFile = os.fdopen(handle, "w+b") if self.isWindows: submitTemplate = submitTemplate.replace("\n", "\r\n") - separatorLine = separatorLine.replace("\n", "\r\n") - newdiff = newdiff.replace("\n", "\r\n") - tmpFile.write(submitTemplate + separatorLine + diff + newdiff) + tmpFile.write(submitTemplate) tmpFile.close() if self.prepare_p4_only: @@ -1439,7 +1470,7 @@ class P4Submit(Command, P4UserMap): print " " + self.clientPath print print "To submit, use \"p4 submit\" to write a new description," - print "or \"p4 submit -i %s\" to use the one prepared by" \ + print "or \"p4 submit -i <%s\" to use the one prepared by" \ " \"git p4\"." % fileName print "You can delete the file \"%s\" when finished." % fileName @@ -1472,9 +1503,9 @@ class P4Submit(Command, P4UserMap): tmpFile = open(fileName, "rb") message = tmpFile.read() tmpFile.close() - submitTemplate = message[:message.index(separatorLine)] if self.isWindows: - submitTemplate = submitTemplate.replace("\r\n", "\n") + message = message.replace("\r\n", "\n") + submitTemplate = message[:message.index(separatorLine)] p4_write_pipe(['submit', '-i'], submitTemplate) if self.preserveUser: @@ -1624,7 +1655,10 @@ class P4Submit(Command, P4UserMap): if self.useClientSpec: self.clientSpecDirs = getClientSpec() - if self.useClientSpec: + # Check for the existance of P4 branches + branchesDetected = (len(p4BranchesInGit().keys()) > 1) + + if self.useClientSpec and not branchesDetected: # all files are relative to the client spec self.clientPath = getClientRoot() else: @@ -1908,11 +1942,17 @@ class P4Sync(Command, P4UserMap): optparse.make_option("--import-labels", dest="importLabels", action="store_true"), optparse.make_option("--import-local", dest="importIntoRemotes", action="store_false", help="Import into refs/heads/ , not refs/remotes"), - optparse.make_option("--max-changes", dest="maxChanges"), + optparse.make_option("--max-changes", dest="maxChanges", + help="Maximum number of changes to import"), + optparse.make_option("--changes-block-size", dest="changes_block_size", type="int", + help="Internal block size to use when iteratively calling p4 changes"), optparse.make_option("--keep-path", dest="keepRepoPath", action='store_true', help="Keep entire BRANCH/DIR/SUBDIR prefix during import"), optparse.make_option("--use-client-spec", dest="useClientSpec", action='store_true', - help="Only sync files that are included in the Perforce Client Spec") + help="Only sync files that are included in the Perforce Client Spec"), + optparse.make_option("-/", dest="cloneExclude", + action="append", type="string", + help="exclude depot path"), ] self.description = """Imports from Perforce into a git repository.\n example: @@ -1934,6 +1974,7 @@ class P4Sync(Command, P4UserMap): self.syncWithOrigin = True self.importIntoRemotes = True self.maxChanges = "" + self.changes_block_size = 500 self.keepRepoPath = False self.depotPaths = None self.p4BranchesInGit = [] @@ -1947,6 +1988,12 @@ class P4Sync(Command, P4UserMap): if gitConfig("git-p4.syncFromOrigin") == "false": self.syncWithOrigin = False + # This is required for the "append" cloneExclude action + def ensure_value(self, attr, value): + if not hasattr(self, attr) or getattr(self, attr) is None: + setattr(self, attr, value) + return getattr(self, attr) + # Force a checkpoint in fast-import and wait for it to finish def checkpoint(self): self.gitStream.write("checkpoint\n\n") @@ -2574,7 +2621,7 @@ class P4Sync(Command, P4UserMap): branchPrefix = self.depotPaths[0] + branch + "/" range = "@1,%s" % maxChange #print "prefix" + branchPrefix - changes = p4ChangesForPaths([branchPrefix], range) + changes = p4ChangesForPaths([branchPrefix], range, self.changes_block_size) if len(changes) <= 0: return False firstChange = changes[0] @@ -2990,7 +3037,7 @@ class P4Sync(Command, P4UserMap): if self.verbose: print "Getting p4 changes for %s...%s" % (', '.join(self.depotPaths), self.changeRange) - changes = p4ChangesForPaths(self.depotPaths, self.changeRange) + changes = p4ChangesForPaths(self.depotPaths, self.changeRange, self.changes_block_size) if len(self.maxChanges) > 0: changes = changes[:min(int(self.maxChanges), len(changes))] @@ -3098,9 +3145,6 @@ class P4Clone(P4Sync): optparse.make_option("--destination", dest="cloneDestination", action='store', default=None, help="where to leave result of the clone"), - optparse.make_option("-/", dest="cloneExclude", - action="append", type="string", - help="exclude depot path"), optparse.make_option("--bare", dest="cloneBare", action="store_true", default=False), ] @@ -3108,12 +3152,6 @@ class P4Clone(P4Sync): self.needsGit = False self.cloneBare = False - # This is required for the "append" cloneExclude action - def ensure_value(self, attr, value): - if not hasattr(self, attr) or getattr(self, attr) is None: - setattr(self, attr, value) - return getattr(self, attr) - def defaultDestination(self, args): ## TODO: use common prefix of args? depotPath = args[0] |