From e7f0d0d9b9dc99a3f748ed686625cc9f87d9a267 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 22 Mar 2007 09:13:01 +0100 Subject: Removed the .py extension from git-p4 as it's annoying to type every time. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 945 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 945 insertions(+) create mode 100755 contrib/fast-import/git-p4 (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 new file mode 100755 index 0000000000..06858844e5 --- /dev/null +++ b/contrib/fast-import/git-p4 @@ -0,0 +1,945 @@ +#!/usr/bin/env python +# +# git-p4.py -- A tool for bidirectional operation between a Perforce depot and git. +# +# Author: Simon Hausmann +# Copyright: 2007 Simon Hausmann +# 2007 Trolltech ASA +# License: MIT +# + +import optparse, sys, os, marshal, popen2, shelve +import tempfile, getopt, sha, os.path, time +from sets import Set; + +gitdir = os.environ.get("GIT_DIR", "") + +def p4CmdList(cmd): + cmd = "p4 -G %s" % cmd + pipe = os.popen(cmd, "rb") + + result = [] + try: + while True: + entry = marshal.load(pipe) + result.append(entry) + except EOFError: + pass + pipe.close() + + return result + +def p4Cmd(cmd): + list = p4CmdList(cmd) + result = {} + for entry in list: + result.update(entry) + return result; + +def die(msg): + sys.stderr.write(msg + "\n") + sys.exit(1) + +def currentGitBranch(): + return os.popen("git-name-rev HEAD").read().split(" ")[1][:-1] + +def isValidGitDir(path): + if os.path.exists(path + "/HEAD") and os.path.exists(path + "/refs") and os.path.exists(path + "/objects"): + return True; + return False + +def system(cmd): + if os.system(cmd) != 0: + die("command failed: %s" % cmd) + +class Command: + def __init__(self): + self.usage = "usage: %prog [options]" + +class P4Debug(Command): + def __init__(self): + self.options = [ + ] + self.description = "A tool to debug the output of p4 -G." + + def run(self, args): + for output in p4CmdList(" ".join(args)): + print output + return True + +class P4CleanTags(Command): + def __init__(self): + Command.__init__(self) + self.options = [ +# optparse.make_option("--branch", dest="branch", default="refs/heads/master") + ] + self.description = "A tool to remove stale unused tags from incremental perforce imports." + def run(self, args): + branch = currentGitBranch() + print "Cleaning out stale p4 import tags..." + sout, sin, serr = popen2.popen3("git-name-rev --tags `git-rev-parse %s`" % branch) + output = sout.read() + try: + tagIdx = output.index(" tags/p4/") + except: + print "Cannot find any p4/* tag. Nothing to do." + sys.exit(0) + + try: + caretIdx = output.index("^") + except: + caretIdx = len(output) - 1 + rev = int(output[tagIdx + 9 : caretIdx]) + + allTags = os.popen("git tag -l p4/").readlines() + for i in range(len(allTags)): + allTags[i] = int(allTags[i][3:-1]) + + allTags.sort() + + allTags.remove(rev) + + for rev in allTags: + print os.popen("git tag -d p4/%s" % rev).read() + + print "%s tags removed." % len(allTags) + return True + +class P4Sync(Command): + def __init__(self): + Command.__init__(self) + self.options = [ + optparse.make_option("--continue", action="store_false", dest="firstTime"), + optparse.make_option("--origin", dest="origin"), + optparse.make_option("--reset", action="store_true", dest="reset"), + optparse.make_option("--master", dest="master"), + optparse.make_option("--log-substitutions", dest="substFile"), + optparse.make_option("--noninteractive", action="store_false"), + optparse.make_option("--dry-run", action="store_true"), + optparse.make_option("--apply-as-patch", action="store_true", dest="applyAsPatch") + ] + self.description = "Submit changes from git to the perforce depot." + self.firstTime = True + self.reset = False + self.interactive = True + self.dryRun = False + self.substFile = "" + self.firstTime = True + self.origin = "origin" + self.master = "" + self.applyAsPatch = True + + self.logSubstitutions = {} + self.logSubstitutions[""] = "%log%" + self.logSubstitutions["\tDetails:"] = "\tDetails: %log%" + + def check(self): + if len(p4CmdList("opened ...")) > 0: + die("You have files opened with perforce! Close them before starting the sync.") + + def start(self): + if len(self.config) > 0 and not self.reset: + die("Cannot start sync. Previous sync config found at %s" % self.configFile) + + commits = [] + for line in os.popen("git-rev-list --no-merges %s..%s" % (self.origin, self.master)).readlines(): + commits.append(line[:-1]) + commits.reverse() + + self.config["commits"] = commits + + if not self.applyAsPatch: + print "Creating temporary p4-sync branch from %s ..." % self.origin + system("git checkout -f -b p4-sync %s" % self.origin) + + def prepareLogMessage(self, template, message): + result = "" + + for line in template.split("\n"): + if line.startswith("#"): + result += line + "\n" + continue + + substituted = False + for key in self.logSubstitutions.keys(): + if line.find(key) != -1: + value = self.logSubstitutions[key] + value = value.replace("%log%", message) + if value != "@remove@": + result += line.replace(key, value) + "\n" + substituted = True + break + + if not substituted: + result += line + "\n" + + return result + + def apply(self, id): + print "Applying %s" % (os.popen("git-log --max-count=1 --pretty=oneline %s" % id).read()) + diff = os.popen("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)).readlines() + filesToAdd = set() + filesToDelete = set() + for line in diff: + modifier = line[0] + path = line[1:].strip() + if modifier == "M": + system("p4 edit %s" % path) + elif modifier == "A": + filesToAdd.add(path) + if path in filesToDelete: + filesToDelete.remove(path) + elif modifier == "D": + filesToDelete.add(path) + if path in filesToAdd: + filesToAdd.remove(path) + else: + die("unknown modifier %s for %s" % (modifier, path)) + + if self.applyAsPatch: + system("git-diff-tree -p --diff-filter=ACMRTUXB \"%s^\" \"%s\" | patch -p1" % (id, id)) + else: + system("git-diff-files --name-only -z | git-update-index --remove -z --stdin") + system("git cherry-pick --no-commit \"%s\"" % id) + + for f in filesToAdd: + system("p4 add %s" % f) + for f in filesToDelete: + system("p4 revert %s" % f) + system("p4 delete %s" % f) + + logMessage = "" + foundTitle = False + for log in os.popen("git-cat-file commit %s" % id).readlines(): + if not foundTitle: + if len(log) == 1: + foundTitle = 1 + continue + + if len(logMessage) > 0: + logMessage += "\t" + logMessage += log + + template = os.popen("p4 change -o").read() + + if self.interactive: + submitTemplate = self.prepareLogMessage(template, logMessage) + diff = os.popen("p4 diff -du ...").read() + + for newFile in filesToAdd: + diff += "==== new file ====\n" + diff += "--- /dev/null\n" + diff += "+++ %s\n" % newFile + f = open(newFile, "r") + for line in f.readlines(): + diff += "+" + line + f.close() + + separatorLine = "######## everything below this line is just the diff #######\n" + + response = "e" + firstIteration = True + while response == "e": + if not firstIteration: + response = raw_input("Do you want to submit this change (y/e/n)? ") + firstIteration = False + if response == "e": + [handle, fileName] = tempfile.mkstemp() + tmpFile = os.fdopen(handle, "w+") + tmpFile.write(submitTemplate + separatorLine + diff) + tmpFile.close() + editor = os.environ.get("EDITOR", "vi") + system(editor + " " + fileName) + tmpFile = open(fileName, "r") + message = tmpFile.read() + tmpFile.close() + os.remove(fileName) + submitTemplate = message[:message.index(separatorLine)] + + if response == "y" or response == "yes": + if self.dryRun: + print submitTemplate + raw_input("Press return to continue...") + else: + pipe = os.popen("p4 submit -i", "w") + pipe.write(submitTemplate) + pipe.close() + else: + print "Not submitting!" + self.interactive = False + else: + fileName = "submit.txt" + file = open(fileName, "w+") + file.write(self.prepareLogMessage(template, logMessage)) + file.close() + print "Perforce submit template written as %s. Please review/edit and then use p4 submit -i < %s to submit directly!" % (fileName, fileName) + + def run(self, args): + if self.reset: + self.firstTime = True + + if len(self.substFile) > 0: + for line in open(self.substFile, "r").readlines(): + tokens = line[:-1].split("=") + self.logSubstitutions[tokens[0]] = tokens[1] + + if len(self.master) == 0: + self.master = currentGitBranch() + if len(self.master) == 0 or not os.path.exists("%s/refs/heads/%s" % (gitdir, self.master)): + die("Detecting current git branch failed!") + + self.check() + self.configFile = gitdir + "/p4-git-sync.cfg" + self.config = shelve.open(self.configFile, writeback=True) + + if self.firstTime: + self.start() + + commits = self.config.get("commits", []) + + while len(commits) > 0: + self.firstTime = False + commit = commits[0] + commits = commits[1:] + self.config["commits"] = commits + self.apply(commit) + if not self.interactive: + break + + self.config.close() + + if len(commits) == 0: + if self.firstTime: + print "No changes found to apply between %s and current HEAD" % self.origin + else: + print "All changes applied!" + if not self.applyAsPatch: + print "Deleting temporary p4-sync branch and going back to %s" % self.master + system("git checkout %s" % self.master) + system("git branch -D p4-sync") + print "Cleaning out your perforce checkout by doing p4 edit ... ; p4 revert ..." + system("p4 edit ... >/dev/null") + system("p4 revert ... >/dev/null") + os.remove(self.configFile) + + return True + +class GitSync(Command): + def __init__(self): + Command.__init__(self) + self.options = [ + optparse.make_option("--branch", dest="branch"), + optparse.make_option("--detect-branches", dest="detectBranches", action="store_true"), + optparse.make_option("--changesfile", dest="changesFile"), + optparse.make_option("--silent", dest="silent", action="store_true"), + optparse.make_option("--known-branches", dest="knownBranches"), + optparse.make_option("--cache", dest="doCache", action="store_true"), + optparse.make_option("--command-cache", dest="commandCache", action="store_true") + ] + self.description = """Imports from Perforce into a git repository.\n + example: + //depot/my/project/ -- to import the current head + //depot/my/project/@all -- to import everything + //depot/my/project/@1,6 -- to import only from revision 1 to 6 + + (a ... is not needed in the path p4 specification, it's added implicitly)""" + + self.usage += " //depot/path[@revRange]" + + self.dataCache = False + self.commandCache = False + self.silent = False + self.knownBranches = Set() + self.createdBranches = Set() + self.committedChanges = Set() + self.branch = "master" + self.detectBranches = False + self.changesFile = "" + + def p4File(self, depotPath): + return os.popen("p4 print -q \"%s\"" % depotPath, "rb").read() + + def extractFilesFromCommit(self, commit): + files = [] + fnum = 0 + while commit.has_key("depotFile%s" % fnum): + path = commit["depotFile%s" % fnum] + if not path.startswith(self.globalPrefix): + # if not self.silent: + # print "\nchanged files: ignoring path %s outside of %s in change %s" % (path, self.globalPrefix, change) + fnum = fnum + 1 + continue + + file = {} + file["path"] = path + file["rev"] = commit["rev%s" % fnum] + file["action"] = commit["action%s" % fnum] + file["type"] = commit["type%s" % fnum] + files.append(file) + fnum = fnum + 1 + return files + + def isSubPathOf(self, first, second): + if not first.startswith(second): + return False + if first == second: + return True + return first[len(second)] == "/" + + def branchesForCommit(self, files): + branches = Set() + + for file in files: + relativePath = file["path"][len(self.globalPrefix):] + # strip off the filename + relativePath = relativePath[0:relativePath.rfind("/")] + + # if len(branches) == 0: + # branches.add(relativePath) + # knownBranches.add(relativePath) + # continue + + ###### this needs more testing :) + knownBranch = False + for branch in branches: + if relativePath == branch: + knownBranch = True + break + # if relativePath.startswith(branch): + if self.isSubPathOf(relativePath, branch): + knownBranch = True + break + # if branch.startswith(relativePath): + if self.isSubPathOf(branch, relativePath): + branches.remove(branch) + break + + if knownBranch: + continue + + for branch in knownBranches: + #if relativePath.startswith(branch): + if self.isSubPathOf(relativePath, branch): + if len(branches) == 0: + relativePath = branch + else: + knownBranch = True + break + + if knownBranch: + continue + + branches.add(relativePath) + self.knownBranches.add(relativePath) + + return branches + + def findBranchParent(self, branchPrefix, files): + for file in files: + path = file["path"] + if not path.startswith(branchPrefix): + continue + action = file["action"] + if action != "integrate" and action != "branch": + continue + rev = file["rev"] + depotPath = path + "#" + rev + + log = p4CmdList("filelog \"%s\"" % depotPath) + if len(log) != 1: + print "eek! I got confused by the filelog of %s" % depotPath + sys.exit(1); + + log = log[0] + if log["action0"] != action: + print "eek! wrong action in filelog for %s : found %s, expected %s" % (depotPath, log["action0"], action) + sys.exit(1); + + branchAction = log["how0,0"] + # if branchAction == "branch into" or branchAction == "ignored": + # continue # ignore for branching + + if not branchAction.endswith(" from"): + continue # ignore for branching + # print "eek! file %s was not branched from but instead: %s" % (depotPath, branchAction) + # sys.exit(1); + + source = log["file0,0"] + if source.startswith(branchPrefix): + continue + + lastSourceRev = log["erev0,0"] + + sourceLog = p4CmdList("filelog -m 1 \"%s%s\"" % (source, lastSourceRev)) + if len(sourceLog) != 1: + print "eek! I got confused by the source filelog of %s%s" % (source, lastSourceRev) + sys.exit(1); + sourceLog = sourceLog[0] + + relPath = source[len(self.globalPrefix):] + # strip off the filename + relPath = relPath[0:relPath.rfind("/")] + + for branch in self.knownBranches: + if self.isSubPathOf(relPath, branch): + # print "determined parent branch branch %s due to change in file %s" % (branch, source) + return branch + # else: + # print "%s is not a subpath of branch %s" % (relPath, branch) + + return "" + + def commit(self, details, files, branch, branchPrefix, parent = "", merged = ""): + epoch = details["time"] + author = details["user"] + + self.gitStream.write("commit %s\n" % branch) + # gitStream.write("mark :%s\n" % details["change"]) + self.committedChanges.add(int(details["change"])) + committer = "" + if author in self.users: + committer = "%s %s %s" % (self.users[author], epoch, self.tz) + else: + committer = "%s %s %s" % (author, epoch, self.tz) + + self.gitStream.write("committer %s\n" % committer) + + self.gitStream.write("data < 0: + self.gitStream.write("from %s\n" % parent) + + if len(merged) > 0: + self.gitStream.write("merge %s\n" % merged) + + for file in files: + path = file["path"] + if not path.startswith(branchPrefix): + # if not silent: + # print "\nchanged files: ignoring path %s outside of branch prefix %s in change %s" % (path, branchPrefix, details["change"]) + continue + rev = file["rev"] + depotPath = path + "#" + rev + relPath = path[len(branchPrefix):] + action = file["action"] + + if file["type"] == "apple": + print "\nfile %s is a strange apple file that forks. Ignoring!" % path + continue + + if action == "delete": + self.gitStream.write("D %s\n" % relPath) + else: + mode = 644 + if file["type"].startswith("x"): + mode = 755 + + data = self.p4File(depotPath) + + self.gitStream.write("M %s inline %s\n" % (mode, relPath)) + self.gitStream.write("data %s\n" % len(data)) + self.gitStream.write(data) + self.gitStream.write("\n") + + self.gitStream.write("\n") + + self.lastChange = int(details["change"]) + + def extractFilesInCommitToBranch(self, files, branchPrefix): + newFiles = [] + + for file in files: + path = file["path"] + if path.startswith(branchPrefix): + newFiles.append(file) + + return newFiles + + def findBranchSourceHeuristic(self, files, branch, branchPrefix): + for file in files: + action = file["action"] + if action != "integrate" and action != "branch": + continue + path = file["path"] + rev = file["rev"] + depotPath = path + "#" + rev + + log = p4CmdList("filelog \"%s\"" % depotPath) + if len(log) != 1: + print "eek! I got confused by the filelog of %s" % depotPath + sys.exit(1); + + log = log[0] + if log["action0"] != action: + print "eek! wrong action in filelog for %s : found %s, expected %s" % (depotPath, log["action0"], action) + sys.exit(1); + + branchAction = log["how0,0"] + + if not branchAction.endswith(" from"): + continue # ignore for branching + # print "eek! file %s was not branched from but instead: %s" % (depotPath, branchAction) + # sys.exit(1); + + source = log["file0,0"] + if source.startswith(branchPrefix): + continue + + lastSourceRev = log["erev0,0"] + + sourceLog = p4CmdList("filelog -m 1 \"%s%s\"" % (source, lastSourceRev)) + if len(sourceLog) != 1: + print "eek! I got confused by the source filelog of %s%s" % (source, lastSourceRev) + sys.exit(1); + sourceLog = sourceLog[0] + + relPath = source[len(self.globalPrefix):] + # strip off the filename + relPath = relPath[0:relPath.rfind("/")] + + for candidate in self.knownBranches: + if self.isSubPathOf(relPath, candidate) and candidate != branch: + return candidate + + return "" + + def changeIsBranchMerge(self, sourceBranch, destinationBranch, change): + sourceFiles = {} + for file in p4CmdList("files %s...@%s" % (self.globalPrefix + sourceBranch + "/", change)): + if file["action"] == "delete": + continue + sourceFiles[file["depotFile"]] = file + + destinationFiles = {} + for file in p4CmdList("files %s...@%s" % (self.globalPrefix + destinationBranch + "/", change)): + destinationFiles[file["depotFile"]] = file + + for fileName in sourceFiles.keys(): + integrations = [] + deleted = False + integrationCount = 0 + for integration in p4CmdList("integrated \"%s\"" % fileName): + toFile = integration["fromFile"] # yes, it's true, it's fromFile + if not toFile in destinationFiles: + continue + destFile = destinationFiles[toFile] + if destFile["action"] == "delete": + # print "file %s has been deleted in %s" % (fileName, toFile) + deleted = True + break + integrationCount += 1 + if integration["how"] == "branch from": + continue + + if int(integration["change"]) == change: + integrations.append(integration) + continue + if int(integration["change"]) > change: + continue + + destRev = int(destFile["rev"]) + + startRev = integration["startFromRev"][1:] + if startRev == "none": + startRev = 0 + else: + startRev = int(startRev) + + endRev = integration["endFromRev"][1:] + if endRev == "none": + endRev = 0 + else: + endRev = int(endRev) + + initialBranch = (destRev == 1 and integration["how"] != "branch into") + inRange = (destRev >= startRev and destRev <= endRev) + newer = (destRev > startRev and destRev > endRev) + + if initialBranch or inRange or newer: + integrations.append(integration) + + if deleted: + continue + + if len(integrations) == 0 and integrationCount > 1: + print "file %s was not integrated from %s into %s" % (fileName, sourceBranch, destinationBranch) + return False + + return True + + def getUserMap(self): + self.users = {} + + for output in p4CmdList("users"): + if not output.has_key("User"): + continue + self.users[output["User"]] = output["FullName"] + " <" + output["Email"] + ">" + + def run(self, args): + self.branch = "refs/heads/" + self.branch + self.globalPrefix = self.previousDepotPath = os.popen("git-repo-config --get p4.depotpath").read() + if len(self.globalPrefix) != 0: + self.globalPrefix = self.globalPrefix[:-1] + + if len(args) == 0 and len(self.globalPrefix) != 0: + if not self.silent: + print "[using previously specified depot path %s]" % self.globalPrefix + elif len(args) != 1: + return False + else: + if len(self.globalPrefix) != 0 and self.globalPrefix != args[0]: + print "previous import used depot path %s and now %s was specified. this doesn't work!" % (self.globalPrefix, args[0]) + sys.exit(1) + self.globalPrefix = args[0] + + self.changeRange = "" + self.revision = "" + self.users = {} + self.initialParent = "" + self.lastChange = 0 + self.initialTag = "" + + if self.globalPrefix.find("@") != -1: + atIdx = self.globalPrefix.index("@") + self.changeRange = self.globalPrefix[atIdx:] + if self.changeRange == "@all": + self.changeRange = "" + elif self.changeRange.find(",") == -1: + self.revision = self.changeRange + self.changeRange = "" + self.globalPrefix = self.globalPrefix[0:atIdx] + elif self.globalPrefix.find("#") != -1: + hashIdx = self.globalPrefix.index("#") + self.revision = self.globalPrefix[hashIdx:] + self.globalPrefix = self.globalPrefix[0:hashIdx] + elif len(self.previousDepotPath) == 0: + self.revision = "#head" + + if self.globalPrefix.endswith("..."): + self.globalPrefix = self.globalPrefix[:-3] + + if not self.globalPrefix.endswith("/"): + self.globalPrefix += "/" + + self.getUserMap() + + if len(self.changeRange) == 0: + try: + sout, sin, serr = popen2.popen3("git-name-rev --tags `git-rev-parse %s`" % self.branch) + output = sout.read() + if output.endswith("\n"): + output = output[:-1] + tagIdx = output.index(" tags/p4/") + caretIdx = output.find("^") + endPos = len(output) + if caretIdx != -1: + endPos = caretIdx + self.rev = int(output[tagIdx + 9 : endPos]) + 1 + self.changeRange = "@%s,#head" % self.rev + self.initialParent = os.popen("git-rev-parse %s" % self.branch).read()[:-1] + self.initialTag = "p4/%s" % (int(self.rev) - 1) + except: + pass + + self.tz = - time.timezone / 36 + tzsign = ("%s" % self.tz)[0] + if tzsign != '+' and tzsign != '-': + self.tz = "+" + ("%s" % self.tz) + + self.gitOutput, self.gitStream, self.gitError = popen2.popen3("git-fast-import") + + if len(self.revision) > 0: + print "Doing initial import of %s from revision %s" % (self.globalPrefix, 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.globalPrefix, self.revision) + details["change"] = self.revision + newestRevision = 0 + + fileCnt = 0 + for info in p4CmdList("files %s...%s" % (self.globalPrefix, self.revision)): + change = int(info["change"]) + if change > newestRevision: + newestRevision = change + + if info["action"] == "delete": + fileCnt = fileCnt + 1 + continue + + for prop in [ "depotFile", "rev", "action", "type" ]: + details["%s%s" % (prop, fileCnt)] = info[prop] + + fileCnt = fileCnt + 1 + + details["change"] = newestRevision + + try: + self.commit(details, self.extractFilesFromCommit(details), self.branch, self.globalPrefix) + except IOError: + print self.gitError.read() + + else: + changes = [] + + if len(self.changesFile) > 0: + output = open(self.changesFile).readlines() + changeSet = Set() + for line in output: + changeSet.add(int(line)) + + for change in changeSet: + changes.append(change) + + changes.sort() + else: + output = os.popen("p4 changes %s...%s" % (self.globalPrefix, self.changeRange)).readlines() + + for line in output: + changeNum = line.split(" ")[1] + changes.append(changeNum) + + changes.reverse() + + if len(changes) == 0: + if not self.silent: + print "no changes to import!" + sys.exit(1) + + cnt = 1 + for change in changes: + description = p4Cmd("describe %s" % change) + + if not self.silent: + sys.stdout.write("\rimporting revision %s (%s%%)" % (change, cnt * 100 / len(changes))) + sys.stdout.flush() + cnt = cnt + 1 + + try: + files = self.extractFilesFromCommit(description) + if self.detectBranches: + for branch in self.branchesForCommit(files): + self.knownBranches.add(branch) + branchPrefix = self.globalPrefix + branch + "/" + + filesForCommit = self.extractFilesInCommitToBranch(files, branchPrefix) + + merged = "" + parent = "" + ########### remove cnt!!! + if branch not in self.createdBranches and cnt > 2: + self.createdBranches.add(branch) + parent = self.findBranchParent(branchPrefix, files) + if parent == branch: + parent = "" + # elif len(parent) > 0: + # print "%s branched off of %s" % (branch, parent) + + if len(parent) == 0: + merged = self.findBranchSourceHeuristic(filesForCommit, branch, branchPrefix) + if len(merged) > 0: + print "change %s could be a merge from %s into %s" % (description["change"], merged, branch) + if not self.changeIsBranchMerge(merged, branch, int(description["change"])): + merged = "" + + branch = "refs/heads/" + branch + if len(parent) > 0: + parent = "refs/heads/" + parent + if len(merged) > 0: + merged = "refs/heads/" + merged + self.commit(description, files, branch, branchPrefix, parent, merged) + else: + self.commit(description, files, self.branch, self.globalPrefix, self.initialParent) + self.initialParent = "" + except IOError: + print self.gitError.read() + sys.exit(1) + + if not self.silent: + print "" + + self.gitStream.write("reset refs/tags/p4/%s\n" % self.lastChange) + self.gitStream.write("from %s\n\n" % self.branch); + + + self.gitStream.close() + self.gitOutput.close() + self.gitError.close() + + os.popen("git-repo-config p4.depotpath %s" % self.globalPrefix).read() + if len(self.initialTag) > 0: + os.popen("git tag -d %s" % self.initialTag).read() + + return True + +class HelpFormatter(optparse.IndentedHelpFormatter): + def __init__(self): + optparse.IndentedHelpFormatter.__init__(self) + + def format_description(self, description): + if description: + return description + "\n" + else: + return "" + +def printUsage(commands): + print "usage: %s [options]" % sys.argv[0] + print "" + print "valid commands: %s" % ", ".join(commands) + print "" + print "Try %s --help for command specific help." % sys.argv[0] + print "" + +commands = { + "debug" : P4Debug(), + "clean-tags" : P4CleanTags(), + "submit" : P4Sync(), + "sync" : GitSync() +} + +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 +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); + +gitdir = cmd.gitdir +if len(gitdir) == 0: + gitdir = ".git" + if not isValidGitDir(gitdir): + cdup = os.popen("git-rev-parse --show-cdup").read()[:-1] + if isValidGitDir(cdup + "/" + gitdir): + os.chdir(cdup) + +if not isValidGitDir(gitdir): + if isValidGitDir(gitdir + "/.git"): + gitdir += "/.git" + else: + die("fatal: cannot locate git repository at %s" % gitdir) + +os.environ["GIT_DIR"] = gitdir + +if not cmd.run(args): + parser.print_help() + -- cgit v1.2.3 From a559b289bd78d5a3fac0f908be7d5ff92ad09dcb Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 22 Mar 2007 20:27:41 +0100 Subject: Changed the format of the imported log message slightly, so that it's easier to parse again. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 06858844e5..a5b6d94d1a 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -506,7 +506,7 @@ class GitSync(Command): self.gitStream.write("data < 0: -- cgit v1.2.3 From f5816a5522763f46e075cc618eab12110107a917 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 22 Mar 2007 20:36:28 +0100 Subject: Changed the default branch for imports from "master" to "p4" Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index a5b6d94d1a..669cf95d74 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -352,7 +352,7 @@ class GitSync(Command): self.knownBranches = Set() self.createdBranches = Set() self.committedChanges = Set() - self.branch = "master" + self.branch = "p4" self.detectBranches = False self.changesFile = "" -- cgit v1.2.3 From 6ae8de88f53f92dd593c5d03b67d0194e7d4eefe Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 22 Mar 2007 21:10:25 +0100 Subject: Added some helper function(s) to parse the depot path and change number from the log message Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 48 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 669cf95d74..6ead1c4173 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -52,12 +52,44 @@ def system(cmd): if os.system(cmd) != 0: die("command failed: %s" % cmd) +def extractLogMessageFromGitCommit(commit): + logMessage = "" + foundTitle = False + for log in os.popen("git-cat-file commit %s" % commit).readlines(): + if not foundTitle: + if len(log) == 1: + foundTitle = 1 + continue + + logMessage += log + return logMessage + +def extractDepotPathAndChangeFromGitLog(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") + class Command: def __init__(self): self.usage = "usage: %prog [options]" class P4Debug(Command): def __init__(self): + Command.__init__(self) self.options = [ ] self.description = "A tool to debug the output of p4 -G." @@ -208,17 +240,9 @@ class P4Sync(Command): system("p4 revert %s" % f) system("p4 delete %s" % f) - logMessage = "" - foundTitle = False - for log in os.popen("git-cat-file commit %s" % id).readlines(): - if not foundTitle: - if len(log) == 1: - foundTitle = 1 - continue - - if len(logMessage) > 0: - logMessage += "\t" - logMessage += log + logMessage = extractLogMessageFromGitCommit(id) + logMessage = logMessage.replace("\n", "\n\t") + logMessage = logMessage[:-1] template = os.popen("p4 change -o").read() @@ -506,7 +530,7 @@ class GitSync(Command): self.gitStream.write("data < 0: -- cgit v1.2.3 From 8136a6399c886dec8d1b806a7d8728324e906729 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 22 Mar 2007 21:27:14 +0100 Subject: Helper function to check the existance of a revision Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 3 +++ 1 file changed, 3 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6ead1c4173..b21dee3199 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -83,6 +83,9 @@ def extractDepotPathAndChangeFromGitLog(log): return values.get("depot-path"), values.get("change") +def gitBranchExists(branch): + return os.system("git-rev-parse %s 2>/dev/null >/dev/null") == 0 + class Command: def __init__(self): self.usage = "usage: %prog [options]" -- cgit v1.2.3 From 569d1bd4092aacd44a826852e087d0f0e9928ce8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 22 Mar 2007 21:34:16 +0100 Subject: Set the default branch in run, not in the constructor Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index b21dee3199..e6a34f4f47 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -379,7 +379,7 @@ class GitSync(Command): self.knownBranches = Set() self.createdBranches = Set() self.committedChanges = Set() - self.branch = "p4" + self.branch = "" self.detectBranches = False self.changesFile = "" @@ -706,6 +706,9 @@ class GitSync(Command): self.users[output["User"]] = output["FullName"] + " <" + output["Email"] + ">" def run(self, args): + if len(self.branch) == 0: + self.branch = "p4" + self.branch = "refs/heads/" + self.branch self.globalPrefix = self.previousDepotPath = os.popen("git-repo-config --get p4.depotpath").read() if len(self.globalPrefix) != 0: -- cgit v1.2.3 From 179caebff4a917dc35c8166ec183bc5c76df53e1 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 22 Mar 2007 22:17:42 +0100 Subject: Brand new smart incremental import that doesn't need tags or git repo-config :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e6a34f4f47..8684e4b20f 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -84,7 +84,9 @@ def extractDepotPathAndChangeFromGitLog(log): return values.get("depot-path"), values.get("change") def gitBranchExists(branch): - return os.system("git-rev-parse %s 2>/dev/null >/dev/null") == 0 + if os.system("git-rev-parse %s 2>/dev/null >/dev/null" % branch) == 0: + return True + return False class Command: def __init__(self): @@ -706,17 +708,40 @@ class GitSync(Command): self.users[output["User"]] = output["FullName"] + " <" + output["Email"] + ">" def run(self, args): + self.globalPrefix = "" + self.changeRange = "" + self.initialParent = "" + self.tagLastChange = True + if len(self.branch) == 0: self.branch = "p4" + if len(args) == 0: + if not gitBranchExists(self.branch) and gitBranchExists("origin"): + if not self.silent: + print "Creating %s branch in git repository based on origin" % self.branch + system("git branch %s origin" % self.branch) + + [self.previousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(self.branch)) + if len(self.previousDepotPath) > 0 and len(p4Change) > 0: + p4Change = int(p4Change) + 1 + self.globalPrefix = self.previousDepotPath + self.changeRange = "@%s,#head" % p4Change + self.initialParent = self.branch + self.tagLastChange = False + if not self.silent: + print "Performing incremental import into %s git branch" % self.branch self.branch = "refs/heads/" + self.branch - self.globalPrefix = self.previousDepotPath = os.popen("git-repo-config --get p4.depotpath").read() + + if len(self.globalPrefix) == 0: + self.globalPrefix = self.previousDepotPath = os.popen("git-repo-config --get p4.depotpath").read() + if len(self.globalPrefix) != 0: self.globalPrefix = self.globalPrefix[:-1] if len(args) == 0 and len(self.globalPrefix) != 0: if not self.silent: - print "[using previously specified depot path %s]" % self.globalPrefix + print "Depot path: %s" % self.globalPrefix elif len(args) != 1: return False else: @@ -725,10 +750,8 @@ class GitSync(Command): sys.exit(1) self.globalPrefix = args[0] - self.changeRange = "" self.revision = "" self.users = {} - self.initialParent = "" self.lastChange = 0 self.initialTag = "" @@ -890,8 +913,9 @@ class GitSync(Command): if not self.silent: print "" - self.gitStream.write("reset refs/tags/p4/%s\n" % self.lastChange) - self.gitStream.write("from %s\n\n" % self.branch); + if self.tagLastChange: + self.gitStream.write("reset refs/tags/p4/%s\n" % self.lastChange) + self.gitStream.write("from %s\n\n" % self.branch); self.gitStream.close() -- cgit v1.2.3 From 9512497bcf574a2f70e43be0bcb58e35fb6aaba8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 23 Mar 2007 09:16:07 +0100 Subject: Make it possible to run git-p4 submit from within the git repository Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 8684e4b20f..a8f7cce25d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -162,7 +162,7 @@ class P4Sync(Command): self.dryRun = False self.substFile = "" self.firstTime = True - self.origin = "origin" + self.origin = "" self.master = "" self.applyAsPatch = True @@ -304,6 +304,42 @@ class P4Sync(Command): print "Perforce submit template written as %s. Please review/edit and then use p4 submit -i < %s to submit directly!" % (fileName, fileName) def run(self, args): + global gitdir + # make gitdir absolute so we can cd out into the perforce checkout + gitdir = os.path.abspath(gitdir) + os.environ["GIT_DIR"] = gitdir + depotPath = "" + if gitBranchExists("p4"): + [depotPath, dummy] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("p4")) + if len(depotPath) == 0 and gitBranchExists("origin"): + [depotPath, dummy] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("origin")) + + if len(depotPath) == 0: + print "Internal error: cannot locate perforce depot path from existing branches" + sys.exit(128) + + if not depotPath.endswith("/"): + depotPath += "/" + clientPath = p4Cmd("where %s..." % depotPath).get("path") + if clientPath.endswith("..."): + clientPath = clientPath[:-3] + + if len(clientPath) == 0: + print "Error: Cannot locate perforce checkout of %s in client view" % depotPath + sys.exit(128) + + print "Perforce checkout for depot path %s located at %s" % (depotPath, clientPath) + os.chdir(clientPath) + response = raw_input("Do you want to sync %s with p4 sync? (y/n)" % clientPath) + if response == "y" or response == "yes": + system("p4 sync ...") + + if len(self.origin) == 0: + if gitBranchExists("p4"): + self.origin = "p4" + else: + self.origin = "origin" + if self.reset: self.firstTime = True -- cgit v1.2.3 From 967f72e21b9f38725d64a7520bca99bbef9e8ab3 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 23 Mar 2007 09:30:41 +0100 Subject: Use the new incremental import style by default Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index a8f7cce25d..61978c3da6 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -751,21 +751,22 @@ class GitSync(Command): if len(self.branch) == 0: self.branch = "p4" - if len(args) == 0: - if not gitBranchExists(self.branch) and gitBranchExists("origin"): - if not self.silent: - print "Creating %s branch in git repository based on origin" % self.branch - system("git branch %s origin" % self.branch) - - [self.previousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(self.branch)) - if len(self.previousDepotPath) > 0 and len(p4Change) > 0: - p4Change = int(p4Change) + 1 - self.globalPrefix = self.previousDepotPath - self.changeRange = "@%s,#head" % p4Change - self.initialParent = self.branch - self.tagLastChange = False - if not self.silent: - print "Performing incremental import into %s git branch" % self.branch + + if len(args) == 0: + if not gitBranchExists(self.branch) and gitBranchExists("origin"): + if not self.silent: + print "Creating %s branch in git repository based on origin" % self.branch + system("git branch %s origin" % self.branch) + + [self.previousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(self.branch)) + if len(self.previousDepotPath) > 0 and len(p4Change) > 0: + p4Change = int(p4Change) + 1 + self.globalPrefix = self.previousDepotPath + self.changeRange = "@%s,#head" % p4Change + self.initialParent = self.branch + self.tagLastChange = False + if not self.silent: + print "Performing incremental import into %s git branch" % self.branch self.branch = "refs/heads/" + self.branch -- cgit v1.2.3 From cb2c9db507cda6804f85ebbacb58a7458ab127a6 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 24 Mar 2007 09:15:11 +0100 Subject: Different versions of p4 have different output for the where command ;( Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 61978c3da6..9503786207 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -36,6 +36,22 @@ def p4Cmd(cmd): result.update(entry) return result; +def p4Where(depotPath): + if not depotPath.endswith("/"): + depotPath += "/" + output = p4Cmd("where %s..." % depotPath) + clientPath = "" + if "path" in output: + clientPath = output.get("path") + elif "data" in output: + data = output.get("data") + lastSpace = data.rfind(" ") + clientPath = data[lastSpace + 1:] + + if clientPath.endswith("..."): + clientPath = clientPath[:-3] + return clientPath + def die(msg): sys.stderr.write(msg + "\n") sys.exit(1) @@ -318,11 +334,7 @@ class P4Sync(Command): print "Internal error: cannot locate perforce depot path from existing branches" sys.exit(128) - if not depotPath.endswith("/"): - depotPath += "/" - clientPath = p4Cmd("where %s..." % depotPath).get("path") - if clientPath.endswith("..."): - clientPath = clientPath[:-3] + clientPath = p4Where(depotPath) if len(clientPath) == 0: print "Error: Cannot locate perforce checkout of %s in client view" % depotPath -- cgit v1.2.3 From 274917a3d65109cfdf225615177fe27624d8461a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 24 Mar 2007 09:18:20 +0100 Subject: Minor cosmetic fixlet for the git-p4 submit sync question. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 9503786207..aaa5d5ee5f 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -342,7 +342,7 @@ class P4Sync(Command): print "Perforce checkout for depot path %s located at %s" % (depotPath, clientPath) os.chdir(clientPath) - response = raw_input("Do you want to sync %s with p4 sync? (y/n)" % clientPath) + response = raw_input("Do you want to sync %s with p4 sync? (y/n) " % clientPath) if response == "y" or response == "yes": system("p4 sync ...") -- cgit v1.2.3 From 9863f4055e1219904f6d26c2803a72fc6c8ce561 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 24 Mar 2007 16:35:05 +0100 Subject: Prefer git command over git-command. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index aaa5d5ee5f..09990be373 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -57,7 +57,7 @@ def die(msg): sys.exit(1) def currentGitBranch(): - return os.popen("git-name-rev HEAD").read().split(" ")[1][:-1] + return os.popen("git name-rev HEAD").read().split(" ")[1][:-1] def isValidGitDir(path): if os.path.exists(path + "/HEAD") and os.path.exists(path + "/refs") and os.path.exists(path + "/objects"): @@ -71,7 +71,7 @@ def system(cmd): def extractLogMessageFromGitCommit(commit): logMessage = "" foundTitle = False - for log in os.popen("git-cat-file commit %s" % commit).readlines(): + for log in os.popen("git cat-file commit %s" % commit).readlines(): if not foundTitle: if len(log) == 1: foundTitle = 1 @@ -100,7 +100,7 @@ def extractDepotPathAndChangeFromGitLog(log): return values.get("depot-path"), values.get("change") def gitBranchExists(branch): - if os.system("git-rev-parse %s 2>/dev/null >/dev/null" % branch) == 0: + if os.system("git rev-parse %s 2>/dev/null >/dev/null" % branch) == 0: return True return False @@ -130,7 +130,7 @@ class P4CleanTags(Command): def run(self, args): branch = currentGitBranch() print "Cleaning out stale p4 import tags..." - sout, sin, serr = popen2.popen3("git-name-rev --tags `git-rev-parse %s`" % branch) + sout, sin, serr = popen2.popen3("git name-rev --tags `git rev-parse %s`" % branch) output = sout.read() try: tagIdx = output.index(" tags/p4/") @@ -195,7 +195,7 @@ class P4Sync(Command): die("Cannot start sync. Previous sync config found at %s" % self.configFile) commits = [] - for line in os.popen("git-rev-list --no-merges %s..%s" % (self.origin, self.master)).readlines(): + for line in os.popen("git rev-list --no-merges %s..%s" % (self.origin, self.master)).readlines(): commits.append(line[:-1]) commits.reverse() @@ -229,7 +229,7 @@ class P4Sync(Command): return result def apply(self, id): - print "Applying %s" % (os.popen("git-log --max-count=1 --pretty=oneline %s" % id).read()) + print "Applying %s" % (os.popen("git log --max-count=1 --pretty=oneline %s" % id).read()) diff = os.popen("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)).readlines() filesToAdd = set() filesToDelete = set() @@ -250,9 +250,9 @@ class P4Sync(Command): die("unknown modifier %s for %s" % (modifier, path)) if self.applyAsPatch: - system("git-diff-tree -p --diff-filter=ACMRTUXB \"%s^\" \"%s\" | patch -p1" % (id, id)) + system("git diff-tree -p --diff-filter=ACMRTUXB \"%s^\" \"%s\" | patch -p1" % (id, id)) else: - system("git-diff-files --name-only -z | git-update-index --remove -z --stdin") + system("git diff-files --name-only -z | git update-index --remove -z --stdin") system("git cherry-pick --no-commit \"%s\"" % id) for f in filesToAdd: @@ -783,7 +783,7 @@ class GitSync(Command): self.branch = "refs/heads/" + self.branch if len(self.globalPrefix) == 0: - self.globalPrefix = self.previousDepotPath = os.popen("git-repo-config --get p4.depotpath").read() + self.globalPrefix = self.previousDepotPath = os.popen("git repo-config --get p4.depotpath").read() if len(self.globalPrefix) != 0: self.globalPrefix = self.globalPrefix[:-1] @@ -830,7 +830,7 @@ class GitSync(Command): if len(self.changeRange) == 0: try: - sout, sin, serr = popen2.popen3("git-name-rev --tags `git-rev-parse %s`" % self.branch) + sout, sin, serr = popen2.popen3("git name-rev --tags `git rev-parse %s`" % self.branch) output = sout.read() if output.endswith("\n"): output = output[:-1] @@ -841,7 +841,7 @@ class GitSync(Command): endPos = caretIdx self.rev = int(output[tagIdx + 9 : endPos]) + 1 self.changeRange = "@%s,#head" % self.rev - self.initialParent = os.popen("git-rev-parse %s" % self.branch).read()[:-1] + self.initialParent = os.popen("git rev-parse %s" % self.branch).read()[:-1] self.initialTag = "p4/%s" % (int(self.rev) - 1) except: pass @@ -851,7 +851,7 @@ class GitSync(Command): if tzsign != '+' and tzsign != '-': self.tz = "+" + ("%s" % self.tz) - self.gitOutput, self.gitStream, self.gitError = popen2.popen3("git-fast-import") + self.gitOutput, self.gitStream, self.gitError = popen2.popen3("git fast-import") if len(self.revision) > 0: print "Doing initial import of %s from revision %s" % (self.globalPrefix, self.revision) @@ -971,7 +971,7 @@ class GitSync(Command): self.gitOutput.close() self.gitError.close() - os.popen("git-repo-config p4.depotpath %s" % self.globalPrefix).read() + os.popen("git repo-config p4.depotpath %s" % self.globalPrefix).read() if len(self.initialTag) > 0: os.popen("git tag -d %s" % self.initialTag).read() @@ -1031,7 +1031,7 @@ gitdir = cmd.gitdir if len(gitdir) == 0: gitdir = ".git" if not isValidGitDir(gitdir): - cdup = os.popen("git-rev-parse --show-cdup").read()[:-1] + cdup = os.popen("git rev-parse --show-cdup").read()[:-1] if isValidGitDir(cdup + "/" + gitdir): os.chdir(cdup) -- cgit v1.2.3 From e20a9e530a02fefaec31b484bd224784b8814554 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 26 Mar 2007 00:13:51 +0200 Subject: Don't try to parse any options with git-p4 debug but pass it straight on to p4 Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 09990be373..5b023b1b7a 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1018,14 +1018,18 @@ except KeyError: options = cmd.options cmd.gitdir = gitdir -options.append(optparse.make_option("--git-dir", dest="gitdir")) -parser = optparse.OptionParser(cmd.usage.replace("%prog", "%prog " + cmdName), - options, - description = cmd.description, - formatter = HelpFormatter()) +args = sys.argv[2:] -(cmd, args) = parser.parse_args(sys.argv[2:], cmd); +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); gitdir = cmd.gitdir if len(gitdir) == 0: -- cgit v1.2.3 From 8910ac0e888daeefdbe6f7391bece150b12b1ad0 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 26 Mar 2007 08:18:55 +0200 Subject: git-p4 debug doesn't need a git repository Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 5b023b1b7a..eb5b40aa98 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -107,6 +107,7 @@ def gitBranchExists(branch): class Command: def __init__(self): self.usage = "usage: %prog [options]" + self.needsGit = True class P4Debug(Command): def __init__(self): @@ -114,6 +115,7 @@ class P4Debug(Command): self.options = [ ] self.description = "A tool to debug the output of p4 -G." + self.needsGit = False def run(self, args): for output in p4CmdList(" ".join(args)): @@ -1031,21 +1033,22 @@ if len(options) > 0: (cmd, args) = parser.parse_args(sys.argv[2:], cmd); -gitdir = cmd.gitdir -if len(gitdir) == 0: - gitdir = ".git" - if not isValidGitDir(gitdir): - cdup = os.popen("git rev-parse --show-cdup").read()[:-1] - if isValidGitDir(cdup + "/" + gitdir): - os.chdir(cdup) +if cmd.needsGit: + gitdir = cmd.gitdir + if len(gitdir) == 0: + gitdir = ".git" + if not isValidGitDir(gitdir): + cdup = os.popen("git rev-parse --show-cdup").read()[:-1] + if isValidGitDir(cdup + "/" + gitdir): + 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 isValidGitDir(gitdir): + if isValidGitDir(gitdir + "/.git"): + gitdir += "/.git" + else: + die("fatal: cannot locate git repository at %s" % gitdir) -os.environ["GIT_DIR"] = gitdir + os.environ["GIT_DIR"] = gitdir if not cmd.run(args): parser.print_help() -- cgit v1.2.3 From 1f4ba1cbfc1d08a9c120012c9199caaec3dc5f58 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 26 Mar 2007 22:34:34 +0200 Subject: Added support for mapping p4 labels to git tags Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 58 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index eb5b40aa98..eab5990548 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -625,7 +625,47 @@ class GitSync(Command): self.gitStream.write("\n") - self.lastChange = int(details["change"]) + change = int(details["change"]) + + self.lastChange = change + + if change in self.labels: + label = self.labels[change] + labelDetails = label[0] + labelRevisions = label[1] + + files = p4CmdList("files %s...@%s" % (branchPrefix, change)) + + if len(files) == len(labelRevisions): + + cleanedFiles = {} + for info in files: + if info["action"] == "delete": + continue + cleanedFiles[info["depotFile"]] = info["rev"] + + if cleanedFiles == labelRevisions: + self.gitStream.write("tag tag_%s\n" % labelDetails["label"]) + self.gitStream.write("from %s\n" % branch) + + owner = labelDetails["Owner"] + tagger = "" + if author in self.users: + tagger = "%s %s %s" % (self.users[owner], epoch, self.tz) + else: + tagger = "%s %s %s" % (owner, epoch, self.tz) + self.gitStream.write("tagger %s\n" % tagger) + self.gitStream.write("data <" + def getLabels(self): + self.labels = {} + + for output in p4CmdList("labels %s..." % self.globalPrefix): + label = output["label"] + revisions = {} + newestChange = 0 + for file in p4CmdList("files //...@%s" % label): + revisions[file["depotFile"]] = file["rev"] + change = int(file["change"]) + if change > newestChange: + newestChange = change + + self.labels[newestChange] = [output, revisions] + def run(self, args): self.globalPrefix = "" self.changeRange = "" @@ -829,6 +884,7 @@ class GitSync(Command): self.globalPrefix += "/" self.getUserMap() + self.getLabels(); if len(self.changeRange) == 0: try: -- cgit v1.2.3 From a46668faf7f02c3fb55bf877e16c7ffdf8c9a129 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 28 Mar 2007 17:05:38 +0200 Subject: Fix variable usage in tag import Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index eab5990548..60c4b3dc6c 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -660,11 +660,11 @@ class GitSync(Command): self.gitStream.write("EOT\n\n") else: - if not silent: + if not self.silent: print "Tag %s does not match with change %s: files do not match." % (labelDetails["label"], change) else: - if not silent: + if not self.silent: print "Tag %s does not match with change %s: file count is different." % (labelDetails["label"], change) def extractFilesInCommitToBranch(self, files, branchPrefix): -- cgit v1.2.3 From c9b50e6307aa9931e18b6cd4d00de817b8e4a4c2 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 29 Mar 2007 19:15:24 +0200 Subject: Fix the docs for git-p4 submit and turn git-p4 submit --master=foo into simply git-p4 submit mytopicbranch. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 60c4b3dc6c..59c3edae19 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -167,13 +167,13 @@ class P4Sync(Command): optparse.make_option("--continue", action="store_false", dest="firstTime"), optparse.make_option("--origin", dest="origin"), optparse.make_option("--reset", action="store_true", dest="reset"), - optparse.make_option("--master", dest="master"), optparse.make_option("--log-substitutions", dest="substFile"), optparse.make_option("--noninteractive", action="store_false"), optparse.make_option("--dry-run", action="store_true"), optparse.make_option("--apply-as-patch", action="store_true", dest="applyAsPatch") ] self.description = "Submit changes from git to the perforce depot." + self.usage += " [name of git branch to submit into perforce depot]" self.firstTime = True self.reset = False self.interactive = True @@ -181,7 +181,6 @@ class P4Sync(Command): self.substFile = "" self.firstTime = True self.origin = "" - self.master = "" self.applyAsPatch = True self.logSubstitutions = {} @@ -326,6 +325,16 @@ class P4Sync(Command): # make gitdir absolute so we can cd out into the perforce checkout gitdir = os.path.abspath(gitdir) os.environ["GIT_DIR"] = gitdir + + if len(args) == 0: + self.master = currentGitBranch() + if len(self.master) == 0 or not os.path.exists("%s/refs/heads/%s" % (gitdir, self.master)): + die("Detecting current git branch failed!") + elif len(args) == 1: + self.master = args[0] + else: + return False + depotPath = "" if gitBranchExists("p4"): [depotPath, dummy] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("p4")) @@ -362,11 +371,6 @@ class P4Sync(Command): tokens = line[:-1].split("=") self.logSubstitutions[tokens[0]] = tokens[1] - if len(self.master) == 0: - self.master = currentGitBranch() - if len(self.master) == 0 or not os.path.exists("%s/refs/heads/%s" % (gitdir, self.master)): - die("Detecting current git branch failed!") - self.check() self.configFile = gitdir + "/p4-git-sync.cfg" self.config = shelve.open(self.configFile, writeback=True) -- cgit v1.2.3 From 2a9489c0249c8aef6c6ead501bae25771e710e12 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 1 Apr 2007 13:39:39 +0200 Subject: Fix "compilation" :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 59c3edae19..0443337359 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -416,7 +416,7 @@ class GitSync(Command): optparse.make_option("--changesfile", dest="changesFile"), optparse.make_option("--silent", dest="silent", action="store_true"), optparse.make_option("--known-branches", dest="knownBranches"), - optparse.make_option("--cache", dest="doCache", action="store_true"), + optparse.make_option("--data-cache", dest="dataCache", action="store_true"), optparse.make_option("--command-cache", dest="commandCache", action="store_true") ] self.description = """Imports from Perforce into a git repository.\n @@ -500,7 +500,7 @@ class GitSync(Command): if knownBranch: continue - for branch in knownBranches: + for branch in self.knownBranches: #if relativePath.startswith(branch): if self.isSubPathOf(relativePath, branch): if len(branches) == 0: -- cgit v1.2.3 From 711544b00c22b1c2559333e8925e449812f9e5cf Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 1 Apr 2007 15:40:46 +0200 Subject: Clean up python class names. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 0443337359..24c8e66e87 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -160,7 +160,7 @@ class P4CleanTags(Command): print "%s tags removed." % len(allTags) return True -class P4Sync(Command): +class P4Submit(Command): def __init__(self): Command.__init__(self) self.options = [ @@ -407,7 +407,7 @@ class P4Sync(Command): return True -class GitSync(Command): +class P4Sync(Command): def __init__(self): Command.__init__(self) self.options = [ @@ -1060,8 +1060,8 @@ def printUsage(commands): commands = { "debug" : P4Debug(), "clean-tags" : P4CleanTags(), - "submit" : P4Sync(), - "sync" : GitSync() + "submit" : P4Submit(), + "sync" : P4Sync() } if len(sys.argv[1:]) == 0: -- cgit v1.2.3 From 01ce1fe9676e3f714f3a2d068bf8cfe021f4073c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 7 Apr 2007 23:46:50 +0200 Subject: Added git-p4 rebase convenience Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 24c8e66e87..aa85800d69 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -804,7 +804,11 @@ class P4Sync(Command): def getLabels(self): self.labels = {} - for output in p4CmdList("labels %s..." % self.globalPrefix): + l = p4CmdList("labels %s..." % self.globalPrefix) + if len(l) > 0: + print "Finding files belonging to labels in %s" % self.globalPrefix + + for output in l: label = output["label"] revisions = {} newestChange = 0 @@ -1039,6 +1043,19 @@ class P4Sync(Command): return True +class P4Rebase(Command): + def __init__(self): + Command.__init__(self) + self.options = [ ] + self.description = "Fetches the latest revision from perforce and rebases the current work (branch) against it" + + def run(self, args): + sync = P4Sync() + sync.run([]) + print "Rebasing the current branch" + system("git rebase p4") + return True + class HelpFormatter(optparse.IndentedHelpFormatter): def __init__(self): optparse.IndentedHelpFormatter.__init__(self) @@ -1061,7 +1078,8 @@ commands = { "debug" : P4Debug(), "clean-tags" : P4CleanTags(), "submit" : P4Submit(), - "sync" : P4Sync() + "sync" : P4Sync(), + "rebase" : P4Rebase() } if len(sys.argv[1:]) == 0: -- cgit v1.2.3 From 1f52af6c732bc17415474c426dc009f9e6a36a83 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 8 Apr 2007 00:07:02 +0200 Subject: Provide a tree summary after git-p4 rebase Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index aa85800d69..170af90abc 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -974,7 +974,7 @@ class P4Sync(Command): if len(changes) == 0: if not self.silent: print "no changes to import!" - sys.exit(1) + return True cnt = 1 for change in changes: @@ -1053,7 +1053,9 @@ class P4Rebase(Command): sync = P4Sync() sync.run([]) print "Rebasing the current branch" + oldHead = os.popen("git rev-parse HEAD").read()[:-1] system("git rebase p4") + system("git diff-tree --stat --summary -M %s HEAD" % oldHead) return True class HelpFormatter(optparse.IndentedHelpFormatter): -- cgit v1.2.3 From cb53e1f8e9a78ab3f980250d2388a62ae2a42d77 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 8 Apr 2007 00:12:02 +0200 Subject: Turn off potentially slow label detection by default Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 170af90abc..fcdfe22a45 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -417,7 +417,8 @@ class P4Sync(Command): optparse.make_option("--silent", dest="silent", action="store_true"), optparse.make_option("--known-branches", dest="knownBranches"), optparse.make_option("--data-cache", dest="dataCache", action="store_true"), - optparse.make_option("--command-cache", dest="commandCache", action="store_true") + optparse.make_option("--command-cache", dest="commandCache", action="store_true"), + optparse.make_option("--detect-labels", dest="detectLabels", action="store_true") ] self.description = """Imports from Perforce into a git repository.\n example: @@ -437,6 +438,7 @@ class P4Sync(Command): self.committedChanges = Set() self.branch = "" self.detectBranches = False + self.detectLabels = False self.changesFile = "" def p4File(self, depotPath): @@ -892,7 +894,9 @@ class P4Sync(Command): self.globalPrefix += "/" self.getUserMap() - self.getLabels(); + self.labels = {} + if self.detectLabels: + self.getLabels(); if len(self.changeRange) == 0: try: -- cgit v1.2.3 From 68ed351ab51c8b5731665fe6a8a7cc9651edf6c9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 8 Apr 2007 09:00:55 +0200 Subject: Honor --silent for labels Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index fcdfe22a45..65660e1351 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -807,7 +807,7 @@ class P4Sync(Command): self.labels = {} l = p4CmdList("labels %s..." % self.globalPrefix) - if len(l) > 0: + if len(l) > 0 and not silent: print "Finding files belonging to labels in %s" % self.globalPrefix for output in l: -- cgit v1.2.3 From f9a3a4f796461276bbbcfef965984086e8e00b46 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 8 Apr 2007 10:08:26 +0200 Subject: Added git-p4 clone convenience command Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 57 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 65660e1351..0a22d9a2e4 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -440,6 +440,7 @@ class P4Sync(Command): self.detectBranches = False self.detectLabels = False self.changesFile = "" + self.tagLastChange = True def p4File(self, depotPath): return os.popen("p4 print -q \"%s\"" % depotPath, "rb").read() @@ -826,7 +827,6 @@ class P4Sync(Command): self.globalPrefix = "" self.changeRange = "" self.initialParent = "" - self.tagLastChange = True if len(self.branch) == 0: self.branch = "p4" @@ -1062,6 +1062,58 @@ class P4Rebase(Command): system("git diff-tree --stat --summary -M %s HEAD" % oldHead) return True +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.needsGit = False + self.tagLastChange = False + + def run(self, args): + if len(args) < 1: + return False + depotPath = args[0] + dir = "" + if len(args) == 2: + dir = args[1] + elif len(args) > 2: + return False + + if not depotPath.startswith("//"): + return False + + if len(dir) == 0: + dir = depotPath + atPos = dir.rfind("@") + if atPos != -1: + dir = dir[0:atPos] + hashPos = dir.rfind("#") + if hashPos != -1: + dir = dir[0:hashPos] + + if dir.endswith("..."): + dir = dir[:-3] + + if dir.endswith("/"): + dir = dir[:-1] + + slashPos = dir.rfind("/") + if slashPos != -1: + dir = dir[slashPos + 1:] + + print "Importing from %s into %s" % (depotPath, dir) + os.makedirs(dir) + os.chdir(dir) + system("git init") + if not P4Sync.run(self, [depotPath]): + return False + os.wait() + if self.branch != "master": + system("git branch master p4") + system("git checkout -f") + return True + class HelpFormatter(optparse.IndentedHelpFormatter): def __init__(self): optparse.IndentedHelpFormatter.__init__(self) @@ -1085,7 +1137,8 @@ commands = { "clean-tags" : P4CleanTags(), "submit" : P4Submit(), "sync" : P4Sync(), - "rebase" : P4Rebase() + "rebase" : P4Rebase(), + "clone" : P4Clone() } if len(sys.argv[1:]) == 0: -- cgit v1.2.3 From c45b1cfe1eda2cc67c4f07a0cd6986911d7c2fd8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 8 Apr 2007 10:13:32 +0200 Subject: Fix file determination for #head imports Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 0a22d9a2e4..28b088544b 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -938,7 +938,8 @@ class P4Sync(Command): newestRevision = change if info["action"] == "delete": - fileCnt = fileCnt + 1 + # don't increase the file cnt, otherwise details["depotFile123"] will have gaps! + #fileCnt = fileCnt + 1 continue for prop in [ "depotFile", "rev", "action", "type" ]: -- cgit v1.2.3 From 10c3211b81a2f67c3853900e462333933f910696 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 8 Apr 2007 10:15:47 +0200 Subject: fix variable usage (oops) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 28b088544b..72fa48af04 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -808,7 +808,7 @@ class P4Sync(Command): self.labels = {} l = p4CmdList("labels %s..." % self.globalPrefix) - if len(l) > 0 and not silent: + if len(l) > 0 and not self.silent: print "Finding files belonging to labels in %s" % self.globalPrefix for output in l: -- cgit v1.2.3 From 80b5910fac79b22ccc8eabb2262562c913d5603c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 9 Apr 2007 12:43:40 +0200 Subject: Allow for convenient rebasing after git-p4 submit Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 72fa48af04..4fbfaf11b6 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -352,6 +352,7 @@ class P4Submit(Command): sys.exit(128) print "Perforce checkout for depot path %s located at %s" % (depotPath, clientPath) + oldWorkingDirectory = os.getcwd() os.chdir(clientPath) response = raw_input("Do you want to sync %s with p4 sync? (y/n) " % clientPath) if response == "y" or response == "yes": @@ -403,6 +404,11 @@ class P4Submit(Command): print "Cleaning out your perforce checkout by doing p4 edit ... ; p4 revert ..." system("p4 edit ... >/dev/null") system("p4 revert ... >/dev/null") + response = raw_input("Do you want to sync from Perforce now using git-p4 rebase (y/n)? ") + if response == "y" or response == "yes": + os.chdir(oldWorkingDirectory) + rebase = P4Rebase() + rebase.run([]) os.remove(self.configFile) return True -- cgit v1.2.3 From fd4ca86a0b920ddde464e787ef2350126f083d75 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 13 Apr 2007 22:21:10 +0200 Subject: Print an error message of some sort if git fast-import fails. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 1 + 1 file changed, 1 insertion(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 4fbfaf11b6..6db757ae43 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -958,6 +958,7 @@ class P4Sync(Command): try: self.commit(details, self.extractFilesFromCommit(details), self.branch, self.globalPrefix) except IOError: + print "IO error with git fast-import. Is your git version recent enough?" print self.gitError.read() else: -- cgit v1.2.3 From f291b4e3d47fb03a65c0dfcfbd28f8fabb6187c1 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 14 Apr 2007 11:21:50 +0200 Subject: Fix the timezone formatting. Now qgit also displays (parses) it correctly. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6db757ae43..44a07c27ce 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -922,10 +922,7 @@ class P4Sync(Command): except: pass - self.tz = - time.timezone / 36 - tzsign = ("%s" % self.tz)[0] - if tzsign != '+' and tzsign != '-': - self.tz = "+" + ("%s" % self.tz) + self.tz = "%+03d%02d" % (- time.timezone / 3600, ((- time.timezone % 3600) / 60)) self.gitOutput, self.gitStream, self.gitError = popen2.popen3("git fast-import") -- cgit v1.2.3 From 8b72ca0f76213eb375840e6b9069b260d97f8286 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 14 Apr 2007 16:05:54 +0200 Subject: Removed the old patch apply code from git-p4 submit. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 44a07c27ce..3202a819ca 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -170,7 +170,6 @@ class P4Submit(Command): optparse.make_option("--log-substitutions", dest="substFile"), optparse.make_option("--noninteractive", action="store_false"), optparse.make_option("--dry-run", action="store_true"), - optparse.make_option("--apply-as-patch", action="store_true", dest="applyAsPatch") ] self.description = "Submit changes from git to the perforce depot." self.usage += " [name of git branch to submit into perforce depot]" @@ -181,7 +180,6 @@ class P4Submit(Command): self.substFile = "" self.firstTime = True self.origin = "" - self.applyAsPatch = True self.logSubstitutions = {} self.logSubstitutions[""] = "%log%" @@ -202,10 +200,6 @@ class P4Submit(Command): self.config["commits"] = commits - if not self.applyAsPatch: - print "Creating temporary p4-sync branch from %s ..." % self.origin - system("git checkout -f -b p4-sync %s" % self.origin) - def prepareLogMessage(self, template, message): result = "" @@ -250,11 +244,7 @@ class P4Submit(Command): else: die("unknown modifier %s for %s" % (modifier, path)) - if self.applyAsPatch: - system("git diff-tree -p --diff-filter=ACMRTUXB \"%s^\" \"%s\" | patch -p1" % (id, id)) - else: - system("git diff-files --name-only -z | git update-index --remove -z --stdin") - system("git cherry-pick --no-commit \"%s\"" % id) + system("git diff-tree -p --diff-filter=ACMRTUXB \"%s^\" \"%s\" | patch -p1" % (id, id)) for f in filesToAdd: system("p4 add %s" % f) @@ -397,13 +387,6 @@ class P4Submit(Command): print "No changes found to apply between %s and current HEAD" % self.origin else: print "All changes applied!" - if not self.applyAsPatch: - print "Deleting temporary p4-sync branch and going back to %s" % self.master - system("git checkout %s" % self.master) - system("git branch -D p4-sync") - print "Cleaning out your perforce checkout by doing p4 edit ... ; p4 revert ..." - system("p4 edit ... >/dev/null") - system("p4 revert ... >/dev/null") response = raw_input("Do you want to sync from Perforce now using git-p4 rebase (y/n)? ") if response == "y" or response == "yes": os.chdir(oldWorkingDirectory) -- cgit v1.2.3 From 5e80dd4d7e34fdd507997615d7fdefc2411571eb Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 14 Apr 2007 16:09:43 +0200 Subject: Slightly improved formatting of the raw_input questions. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3202a819ca..9c9852c75f 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -277,7 +277,7 @@ class P4Submit(Command): firstIteration = True while response == "e": if not firstIteration: - response = raw_input("Do you want to submit this change (y/e/n)? ") + response = raw_input("Do you want to submit this change? [y]es/[e]dit/[n]o ") firstIteration = False if response == "e": [handle, fileName] = tempfile.mkstemp() @@ -344,7 +344,7 @@ class P4Submit(Command): print "Perforce checkout for depot path %s located at %s" % (depotPath, clientPath) oldWorkingDirectory = os.getcwd() os.chdir(clientPath) - response = raw_input("Do you want to sync %s with p4 sync? (y/n) " % clientPath) + response = raw_input("Do you want to sync %s with p4 sync? [y]es/[n]o " % clientPath) if response == "y" or response == "yes": system("p4 sync ...") @@ -387,7 +387,7 @@ class P4Submit(Command): print "No changes found to apply between %s and current HEAD" % self.origin else: print "All changes applied!" - response = raw_input("Do you want to sync from Perforce now using git-p4 rebase (y/n)? ") + response = raw_input("Do you want to sync from Perforce now using git-p4 rebase? [y]es/[n]o ") if response == "y" or response == "yes": os.chdir(oldWorkingDirectory) rebase = P4Rebase() -- cgit v1.2.3 From 90865adc01213520980459ddc261a019f673cce8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 15 Apr 2007 09:34:15 +0200 Subject: A new attempt at fixing the child-fast-import-process-not-finished race condition in the clone command Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 9c9852c75f..b77cb20e3f 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -907,7 +907,10 @@ class P4Sync(Command): self.tz = "%+03d%02d" % (- time.timezone / 3600, ((- time.timezone % 3600) / 60)) - self.gitOutput, self.gitStream, self.gitError = popen2.popen3("git fast-import") + importProcess = popen2.Popen3("git fast-import", capturestderr = True) + self.gitOutput = importProcess.fromchild + self.gitStream = importProcess.tochild + self.gitError = importProcess.childerr if len(self.revision) > 0: print "Doing initial import of %s from revision %s" % (self.globalPrefix, self.revision) @@ -1028,6 +1031,7 @@ class P4Sync(Command): self.gitStream.close() self.gitOutput.close() self.gitError.close() + importProcess.wait() os.popen("git repo-config p4.depotpath %s" % self.globalPrefix).read() if len(self.initialTag) > 0: @@ -1096,7 +1100,6 @@ class P4Clone(P4Sync): system("git init") if not P4Sync.run(self, [depotPath]): return False - os.wait() if self.branch != "master": system("git branch master p4") system("git checkout -f") -- cgit v1.2.3 From 51a2640afdd12475642728dc3576966abe0dba6d Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 15 Apr 2007 09:59:56 +0200 Subject: Handle patch errors in git-p4 submit better. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index b77cb20e3f..fb13469ce2 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -244,7 +244,33 @@ class P4Submit(Command): else: die("unknown modifier %s for %s" % (modifier, path)) - system("git diff-tree -p --diff-filter=ACMRTUXB \"%s^\" \"%s\" | patch -p1" % (id, id)) + diffcmd = "git diff-tree -p --diff-filter=ACMRTUXB \"%s^\" \"%s\"" % (id, id) + patchcmd = diffcmd + " | patch -p1" + + if os.system(patchcmd + " --dry-run --silent") != 0: + print "Unfortunately applying the change failed!" + print "What do you want to do?" + response = "x" + while response != "s" and response != "a" and response != "w": + response = raw_input("[s]kip this patch / [a]pply the patch forcibly and with .rej files / [w]rite the patch to a file (patch.txt) ") + if response == "s": + print "Skipping! Good luck with the next patches..." + return + elif response == "a": + os.system(patchcmd) + if len(filesToAdd) > 0: + print "You may also want to call p4 add on the following files:" + print " ".join(filesToAdd) + if len(filesToDelete): + print "The following files should be scheduled for deletion with p4 delete:" + print " ".join(filesToDelete) + die("Please resolve and submit the conflict manually and continue afterwards with git-p4 submit --continue") + elif response == "w": + system(diffcmd + " > patch.txt") + print "Patch saved to patch.txt in %s !" % self.clientPath + die("Please resolve and submit the conflict manually and continue afterwards with git-p4 submit --continue") + + system(patchcmd) for f in filesToAdd: system("p4 add %s" % f) @@ -335,16 +361,16 @@ class P4Submit(Command): print "Internal error: cannot locate perforce depot path from existing branches" sys.exit(128) - clientPath = p4Where(depotPath) + self.clientPath = p4Where(depotPath) - if len(clientPath) == 0: + if len(self.clientPath) == 0: print "Error: Cannot locate perforce checkout of %s in client view" % depotPath sys.exit(128) - print "Perforce checkout for depot path %s located at %s" % (depotPath, clientPath) + print "Perforce checkout for depot path %s located at %s" % (depotPath, self.clientPath) oldWorkingDirectory = os.getcwd() - os.chdir(clientPath) - response = raw_input("Do you want to sync %s with p4 sync? [y]es/[n]o " % clientPath) + os.chdir(self.clientPath) + response = raw_input("Do you want to sync %s with p4 sync? [y]es/[n]o " % self.clientPath) if response == "y" or response == "yes": system("p4 sync ...") -- cgit v1.2.3 From 1c094184da5c7bf572c907633279890bd15d1952 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 1 May 2007 23:15:48 +0200 Subject: Micro cleanup Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index fb13469ce2..9adc66a05d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -74,7 +74,7 @@ def extractLogMessageFromGitCommit(commit): for log in os.popen("git cat-file commit %s" % commit).readlines(): if not foundTitle: if len(log) == 1: - foundTitle = 1 + foundTitle = True continue logMessage += log -- cgit v1.2.3 From 8f8725314dbed75dc1e603646ea6a2c630025f6e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 1 May 2007 23:23:00 +0200 Subject: cleanup, renamed self.globalPrefix to self.depotPath Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 80 +++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 9adc66a05d..6b74feeb64 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -465,9 +465,9 @@ class P4Sync(Command): fnum = 0 while commit.has_key("depotFile%s" % fnum): path = commit["depotFile%s" % fnum] - if not path.startswith(self.globalPrefix): + if not path.startswith(self.depotPath): # if not self.silent: - # print "\nchanged files: ignoring path %s outside of %s in change %s" % (path, self.globalPrefix, change) + # print "\nchanged files: ignoring path %s outside of %s in change %s" % (path, self.depotPath, change) fnum = fnum + 1 continue @@ -491,7 +491,7 @@ class P4Sync(Command): branches = Set() for file in files: - relativePath = file["path"][len(self.globalPrefix):] + relativePath = file["path"][len(self.depotPath):] # strip off the filename relativePath = relativePath[0:relativePath.rfind("/")] @@ -577,7 +577,7 @@ class P4Sync(Command): sys.exit(1); sourceLog = sourceLog[0] - relPath = source[len(self.globalPrefix):] + relPath = source[len(self.depotPath):] # strip off the filename relPath = relPath[0:relPath.rfind("/")] @@ -737,7 +737,7 @@ class P4Sync(Command): sys.exit(1); sourceLog = sourceLog[0] - relPath = source[len(self.globalPrefix):] + relPath = source[len(self.depotPath):] # strip off the filename relPath = relPath[0:relPath.rfind("/")] @@ -749,13 +749,13 @@ class P4Sync(Command): def changeIsBranchMerge(self, sourceBranch, destinationBranch, change): sourceFiles = {} - for file in p4CmdList("files %s...@%s" % (self.globalPrefix + sourceBranch + "/", change)): + for file in p4CmdList("files %s...@%s" % (self.depotPath + sourceBranch + "/", change)): if file["action"] == "delete": continue sourceFiles[file["depotFile"]] = file destinationFiles = {} - for file in p4CmdList("files %s...@%s" % (self.globalPrefix + destinationBranch + "/", change)): + for file in p4CmdList("files %s...@%s" % (self.depotPath + destinationBranch + "/", change)): destinationFiles[file["depotFile"]] = file for fileName in sourceFiles.keys(): @@ -822,9 +822,9 @@ class P4Sync(Command): def getLabels(self): self.labels = {} - l = p4CmdList("labels %s..." % self.globalPrefix) + l = p4CmdList("labels %s..." % self.depotPath) if len(l) > 0 and not self.silent: - print "Finding files belonging to labels in %s" % self.globalPrefix + print "Finding files belonging to labels in %s" % self.depotPath for output in l: label = output["label"] @@ -839,7 +839,7 @@ class P4Sync(Command): self.labels[newestChange] = [output, revisions] def run(self, args): - self.globalPrefix = "" + self.depotPath = "" self.changeRange = "" self.initialParent = "" @@ -855,7 +855,7 @@ class P4Sync(Command): [self.previousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(self.branch)) if len(self.previousDepotPath) > 0 and len(p4Change) > 0: p4Change = int(p4Change) + 1 - self.globalPrefix = self.previousDepotPath + self.depotPath = self.previousDepotPath self.changeRange = "@%s,#head" % p4Change self.initialParent = self.branch self.tagLastChange = False @@ -864,49 +864,49 @@ class P4Sync(Command): self.branch = "refs/heads/" + self.branch - if len(self.globalPrefix) == 0: - self.globalPrefix = self.previousDepotPath = os.popen("git repo-config --get p4.depotpath").read() + if len(self.depotPath) == 0: + self.depotPath = self.previousDepotPath = os.popen("git repo-config --get p4.depotpath").read() - if len(self.globalPrefix) != 0: - self.globalPrefix = self.globalPrefix[:-1] + if len(self.depotPath) != 0: + self.depotPath = self.depotPath[:-1] - if len(args) == 0 and len(self.globalPrefix) != 0: + if len(args) == 0 and len(self.depotPath) != 0: if not self.silent: - print "Depot path: %s" % self.globalPrefix + print "Depot path: %s" % self.depotPath elif len(args) != 1: return False else: - if len(self.globalPrefix) != 0 and self.globalPrefix != args[0]: - print "previous import used depot path %s and now %s was specified. this doesn't work!" % (self.globalPrefix, args[0]) + if len(self.depotPath) != 0 and self.depotPath != args[0]: + print "previous import used depot path %s and now %s was specified. this doesn't work!" % (self.depotPath, args[0]) sys.exit(1) - self.globalPrefix = args[0] + self.depotPath = args[0] self.revision = "" self.users = {} self.lastChange = 0 self.initialTag = "" - if self.globalPrefix.find("@") != -1: - atIdx = self.globalPrefix.index("@") - self.changeRange = self.globalPrefix[atIdx:] + 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.globalPrefix = self.globalPrefix[0:atIdx] - elif self.globalPrefix.find("#") != -1: - hashIdx = self.globalPrefix.index("#") - self.revision = self.globalPrefix[hashIdx:] - self.globalPrefix = self.globalPrefix[0:hashIdx] + 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" - if self.globalPrefix.endswith("..."): - self.globalPrefix = self.globalPrefix[:-3] + if self.depotPath.endswith("..."): + self.depotPath = self.depotPath[:-3] - if not self.globalPrefix.endswith("/"): - self.globalPrefix += "/" + if not self.depotPath.endswith("/"): + self.depotPath += "/" self.getUserMap() self.labels = {} @@ -939,15 +939,15 @@ class P4Sync(Command): self.gitError = importProcess.childerr if len(self.revision) > 0: - print "Doing initial import of %s from revision %s" % (self.globalPrefix, self.revision) + print "Doing initial import of %s from revision %s" % (self.depotPath, 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.globalPrefix, self.revision) + details["desc"] = "Initial import of %s from the state at revision %s" % (self.depotPath, self.revision) details["change"] = self.revision newestRevision = 0 fileCnt = 0 - for info in p4CmdList("files %s...%s" % (self.globalPrefix, self.revision)): + for info in p4CmdList("files %s...%s" % (self.depotPath, self.revision)): change = int(info["change"]) if change > newestRevision: newestRevision = change @@ -965,7 +965,7 @@ class P4Sync(Command): details["change"] = newestRevision try: - self.commit(details, self.extractFilesFromCommit(details), self.branch, self.globalPrefix) + self.commit(details, self.extractFilesFromCommit(details), self.branch, self.depotPath) except IOError: print "IO error with git fast-import. Is your git version recent enough?" print self.gitError.read() @@ -984,7 +984,7 @@ class P4Sync(Command): changes.sort() else: - output = os.popen("p4 changes %s...%s" % (self.globalPrefix, self.changeRange)).readlines() + output = os.popen("p4 changes %s...%s" % (self.depotPath, self.changeRange)).readlines() for line in output: changeNum = line.split(" ")[1] @@ -1011,7 +1011,7 @@ class P4Sync(Command): if self.detectBranches: for branch in self.branchesForCommit(files): self.knownBranches.add(branch) - branchPrefix = self.globalPrefix + branch + "/" + branchPrefix = self.depotPath + branch + "/" filesForCommit = self.extractFilesInCommitToBranch(files, branchPrefix) @@ -1040,7 +1040,7 @@ class P4Sync(Command): merged = "refs/heads/" + merged self.commit(description, files, branch, branchPrefix, parent, merged) else: - self.commit(description, files, self.branch, self.globalPrefix, self.initialParent) + self.commit(description, files, self.branch, self.depotPath, self.initialParent) self.initialParent = "" except IOError: print self.gitError.read() @@ -1059,7 +1059,7 @@ class P4Sync(Command): self.gitError.close() importProcess.wait() - os.popen("git repo-config p4.depotpath %s" % self.globalPrefix).read() + os.popen("git repo-config p4.depotpath %s" % self.depotPath).read() if len(self.initialTag) > 0: os.popen("git tag -d %s" % self.initialTag).read() -- cgit v1.2.3 From 28359251395c1647bf40adcdabbe4d85d7b085af Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 1 May 2007 23:26:19 +0200 Subject: Cleanup, removed the old tagging code Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6b74feeb64..9927fa142e 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -455,7 +455,6 @@ class P4Sync(Command): self.detectBranches = False self.detectLabels = False self.changesFile = "" - self.tagLastChange = True def p4File(self, depotPath): return os.popen("p4 print -q \"%s\"" % depotPath, "rb").read() @@ -858,15 +857,11 @@ class P4Sync(Command): self.depotPath = self.previousDepotPath self.changeRange = "@%s,#head" % p4Change self.initialParent = self.branch - self.tagLastChange = False if not self.silent: print "Performing incremental import into %s git branch" % self.branch self.branch = "refs/heads/" + self.branch - if len(self.depotPath) == 0: - self.depotPath = self.previousDepotPath = os.popen("git repo-config --get p4.depotpath").read() - if len(self.depotPath) != 0: self.depotPath = self.depotPath[:-1] @@ -884,7 +879,6 @@ class P4Sync(Command): self.revision = "" self.users = {} self.lastChange = 0 - self.initialTag = "" if self.depotPath.find("@") != -1: atIdx = self.depotPath.index("@") @@ -927,7 +921,6 @@ class P4Sync(Command): self.rev = int(output[tagIdx + 9 : endPos]) + 1 self.changeRange = "@%s,#head" % self.rev self.initialParent = os.popen("git rev-parse %s" % self.branch).read()[:-1] - self.initialTag = "p4/%s" % (int(self.rev) - 1) except: pass @@ -1049,20 +1042,12 @@ class P4Sync(Command): if not self.silent: print "" - if self.tagLastChange: - self.gitStream.write("reset refs/tags/p4/%s\n" % self.lastChange) - self.gitStream.write("from %s\n\n" % self.branch); - self.gitStream.close() self.gitOutput.close() self.gitError.close() importProcess.wait() - os.popen("git repo-config p4.depotpath %s" % self.depotPath).read() - if len(self.initialTag) > 0: - os.popen("git tag -d %s" % self.initialTag).read() - return True class P4Rebase(Command): @@ -1086,7 +1071,6 @@ class P4Clone(P4Sync): self.description = "Creates a new git repository and imports from Perforce into it" self.usage = "usage: %prog [options] //depot/path[@revRange] [directory]" self.needsGit = False - self.tagLastChange = False def run(self, args): if len(args) < 1: -- cgit v1.2.3 From 084835805565726c825f0853626a33a0263066bf Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 15 May 2007 14:31:06 +0200 Subject: Use the subprocess module instead of popen2 to make it work on Windows. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 9927fa142e..a2f582f8c9 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -8,7 +8,7 @@ # License: MIT # -import optparse, sys, os, marshal, popen2, shelve +import optparse, sys, os, marshal, popen2, subprocess, shelve import tempfile, getopt, sha, os.path, time from sets import Set; @@ -926,10 +926,10 @@ class P4Sync(Command): self.tz = "%+03d%02d" % (- time.timezone / 3600, ((- time.timezone % 3600) / 60)) - importProcess = popen2.Popen3("git fast-import", capturestderr = True) - self.gitOutput = importProcess.fromchild - self.gitStream = importProcess.tochild - self.gitError = importProcess.childerr + importProcess = subprocess.Popen(["git", "fast-import"], 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) -- cgit v1.2.3 From caace111129545559bf798d83ac8cfd596d36f66 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 15 May 2007 14:57:57 +0200 Subject: Make sure all popen calls use binary mode (for Windows) and also make gitBranchExists work on Windows. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index a2f582f8c9..d83ce1ae95 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -14,6 +14,9 @@ from sets import Set; gitdir = os.environ.get("GIT_DIR", "") +def mypopen(command): + return os.popen(command, "rb"); + def p4CmdList(cmd): cmd = "p4 -G %s" % cmd pipe = os.popen(cmd, "rb") @@ -57,7 +60,7 @@ def die(msg): sys.exit(1) def currentGitBranch(): - return os.popen("git name-rev HEAD").read().split(" ")[1][:-1] + return mypopen("git name-rev HEAD").read().split(" ")[1][:-1] def isValidGitDir(path): if os.path.exists(path + "/HEAD") and os.path.exists(path + "/refs") and os.path.exists(path + "/objects"): @@ -71,7 +74,7 @@ def system(cmd): def extractLogMessageFromGitCommit(commit): logMessage = "" foundTitle = False - for log in os.popen("git cat-file commit %s" % commit).readlines(): + for log in mypopen("git cat-file commit %s" % commit).readlines(): if not foundTitle: if len(log) == 1: foundTitle = True @@ -100,9 +103,8 @@ def extractDepotPathAndChangeFromGitLog(log): return values.get("depot-path"), values.get("change") def gitBranchExists(branch): - if os.system("git rev-parse %s 2>/dev/null >/dev/null" % branch) == 0: - return True - return False + proc = subprocess.Popen(["git", "rev-parse", branch], stderr=subprocess.PIPE, stdout=subprocess.PIPE); + return proc.wait() == 0; class Command: def __init__(self): @@ -146,7 +148,7 @@ class P4CleanTags(Command): caretIdx = len(output) - 1 rev = int(output[tagIdx + 9 : caretIdx]) - allTags = os.popen("git tag -l p4/").readlines() + allTags = mypopen("git tag -l p4/").readlines() for i in range(len(allTags)): allTags[i] = int(allTags[i][3:-1]) @@ -155,7 +157,7 @@ class P4CleanTags(Command): allTags.remove(rev) for rev in allTags: - print os.popen("git tag -d p4/%s" % rev).read() + print mypopen("git tag -d p4/%s" % rev).read() print "%s tags removed." % len(allTags) return True @@ -194,7 +196,7 @@ class P4Submit(Command): die("Cannot start sync. Previous sync config found at %s" % self.configFile) commits = [] - for line in os.popen("git rev-list --no-merges %s..%s" % (self.origin, self.master)).readlines(): + for line in mypopen("git rev-list --no-merges %s..%s" % (self.origin, self.master)).readlines(): commits.append(line[:-1]) commits.reverse() @@ -224,8 +226,8 @@ class P4Submit(Command): return result def apply(self, id): - print "Applying %s" % (os.popen("git log --max-count=1 --pretty=oneline %s" % id).read()) - diff = os.popen("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)).readlines() + print "Applying %s" % (mypopen("git log --max-count=1 --pretty=oneline %s" % id).read()) + diff = mypopen("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)).readlines() filesToAdd = set() filesToDelete = set() for line in diff: @@ -282,11 +284,11 @@ class P4Submit(Command): logMessage = logMessage.replace("\n", "\n\t") logMessage = logMessage[:-1] - template = os.popen("p4 change -o").read() + template = mypopen("p4 change -o").read() if self.interactive: submitTemplate = self.prepareLogMessage(template, logMessage) - diff = os.popen("p4 diff -du ...").read() + diff = mypopen("p4 diff -du ...").read() for newFile in filesToAdd: diff += "==== new file ====\n" @@ -323,7 +325,7 @@ class P4Submit(Command): print submitTemplate raw_input("Press return to continue...") else: - pipe = os.popen("p4 submit -i", "w") + pipe = mypopen("p4 submit -i", "w") pipe.write(submitTemplate) pipe.close() else: @@ -920,7 +922,7 @@ class P4Sync(Command): endPos = caretIdx self.rev = int(output[tagIdx + 9 : endPos]) + 1 self.changeRange = "@%s,#head" % self.rev - self.initialParent = os.popen("git rev-parse %s" % self.branch).read()[:-1] + self.initialParent = mypopen("git rev-parse %s" % self.branch).read()[:-1] except: pass @@ -977,7 +979,7 @@ class P4Sync(Command): changes.sort() else: - output = os.popen("p4 changes %s...%s" % (self.depotPath, self.changeRange)).readlines() + output = mypopen("p4 changes %s...%s" % (self.depotPath, self.changeRange)).readlines() for line in output: changeNum = line.split(" ")[1] @@ -1060,7 +1062,7 @@ class P4Rebase(Command): sync = P4Sync() sync.run([]) print "Rebasing the current branch" - oldHead = os.popen("git rev-parse HEAD").read()[:-1] + oldHead = mypopen("git rev-parse HEAD").read()[:-1] system("git rebase p4") system("git diff-tree --stat --summary -M %s HEAD" % oldHead) return True @@ -1176,7 +1178,7 @@ if cmd.needsGit: if len(gitdir) == 0: gitdir = ".git" if not isValidGitDir(gitdir): - cdup = os.popen("git rev-parse --show-cdup").read()[:-1] + cdup = mypopen("git rev-parse --show-cdup").read()[:-1] if isValidGitDir(cdup + "/" + gitdir): os.chdir(cdup) -- cgit v1.2.3 From 25df95cce470d74cdc5e8905a298bbc36c7ec6d0 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 15 May 2007 15:15:39 +0200 Subject: Make submitting work on Windows. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d83ce1ae95..d134a28189 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -9,7 +9,7 @@ # import optparse, sys, os, marshal, popen2, subprocess, shelve -import tempfile, getopt, sha, os.path, time +import tempfile, getopt, sha, os.path, time, platform from sets import Set; gitdir = os.environ.get("GIT_DIR", "") @@ -299,7 +299,10 @@ class P4Submit(Command): diff += "+" + line f.close() - separatorLine = "######## everything below this line is just the diff #######\n" + separatorLine = "######## everything below this line is just the diff #######" + if platform.system() == "Windows": + separatorLine += "\r" + separatorLine += "\n" response = "e" firstIteration = True @@ -312,9 +315,12 @@ class P4Submit(Command): tmpFile = os.fdopen(handle, "w+") tmpFile.write(submitTemplate + separatorLine + diff) tmpFile.close() - editor = os.environ.get("EDITOR", "vi") + defaultEditor = "vi" + if platform.system() == "Windows": + defaultEditor = "notepad" + editor = os.environ.get("EDITOR", defaultEditor); system(editor + " " + fileName) - tmpFile = open(fileName, "r") + tmpFile = open(fileName, "rb") message = tmpFile.read() tmpFile.close() os.remove(fileName) @@ -325,7 +331,7 @@ class P4Submit(Command): print submitTemplate raw_input("Press return to continue...") else: - pipe = mypopen("p4 submit -i", "w") + pipe = os.popen("p4 submit -i", "wb") pipe.write(submitTemplate) pipe.close() else: -- cgit v1.2.3 From cd6cc0d31845576082fabc7f246a99988aca6d26 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 15 May 2007 16:15:26 +0200 Subject: Fix git-p4 clone //depot/project (head import) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 1 + 1 file changed, 1 insertion(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d134a28189..2633f29942 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -849,6 +849,7 @@ class P4Sync(Command): self.depotPath = "" self.changeRange = "" self.initialParent = "" + self.previousDepotPath = "" if len(self.branch) == 0: self.branch = "p4" -- cgit v1.2.3 From 81f2373f89895a47ed0251ac0856798514cfb618 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 15 May 2007 23:06:43 +0200 Subject: Make git-p4 work with bare repositories. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 2633f29942..84cdca1aa2 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1185,9 +1185,7 @@ if cmd.needsGit: if len(gitdir) == 0: gitdir = ".git" if not isValidGitDir(gitdir): - cdup = mypopen("git rev-parse --show-cdup").read()[:-1] - if isValidGitDir(cdup + "/" + gitdir): - os.chdir(cdup) + gitdir = mypopen("git rev-parse --git-dir").read()[:-1] if not isValidGitDir(gitdir): if isValidGitDir(gitdir + "/.git"): -- cgit v1.2.3 From d336c15835c924ba8d153edbfceca88d5c748582 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 16 May 2007 09:41:26 +0200 Subject: Added the possibility of skipping patches during git-p4 submit Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 84cdca1aa2..eba7a67c68 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -230,11 +230,13 @@ class P4Submit(Command): diff = mypopen("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)).readlines() filesToAdd = set() filesToDelete = set() + editedFiles = set() for line in diff: modifier = line[0] path = line[1:].strip() if modifier == "M": - system("p4 edit %s" % path) + system("p4 edit \"%s\"" % path) + editedFiles.add(path) elif modifier == "A": filesToAdd.add(path) if path in filesToDelete: @@ -308,7 +310,7 @@ class P4Submit(Command): firstIteration = True while response == "e": if not firstIteration: - response = raw_input("Do you want to submit this change? [y]es/[e]dit/[n]o ") + response = raw_input("Do you want to submit this change? [y]es/[e]dit/[n]o/[s]kip ") firstIteration = False if response == "e": [handle, fileName] = tempfile.mkstemp() @@ -334,6 +336,15 @@ class P4Submit(Command): pipe = os.popen("p4 submit -i", "wb") pipe.write(submitTemplate) pipe.close() + elif response == "s": + for f in editedFiles: + system("p4 revert \"%s\"" % f); + for f in filesToAdd: + system("p4 revert \"%s\"" % f); + system("rm %s" %f) + for f in filesToDelete: + system("p4 delete \"%s\"" % f); + return else: print "Not submitting!" self.interactive = False -- cgit v1.2.3 From c3c46244518178bac49caf21d6ba3a782292bb10 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 16 May 2007 09:43:13 +0200 Subject: Give a better hint if git-p4 submit fails Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index eba7a67c68..c48b257577 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -193,7 +193,7 @@ class P4Submit(Command): def start(self): if len(self.config) > 0 and not self.reset: - die("Cannot start sync. Previous sync config found at %s" % self.configFile) + die("Cannot start sync. Previous sync config found at %s\nIf you want to start submitting again from scratch maybe you want to call git-p4 submit --reset" % self.configFile) commits = [] for line in mypopen("git rev-list --no-merges %s..%s" % (self.origin, self.master)).readlines(): -- cgit v1.2.3 From dc1a93b6dce1d38e6e0ddd8980d8ccd64937fcb1 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 16 May 2007 12:12:39 +0200 Subject: Fix calling git-p4 rebase from within a subdirectory (git rebase wants to be in toplevel) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 ++ 1 file changed, 2 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index c48b257577..ca6c623809 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1197,6 +1197,8 @@ if cmd.needsGit: gitdir = ".git" if not isValidGitDir(gitdir): gitdir = mypopen("git rev-parse --git-dir").read()[:-1] + if os.path.exists(gitdir): + os.chdir(mypopen("git rev-parse --show-cdup").read()[:-1]); if not isValidGitDir(gitdir): if isValidGitDir(gitdir + "/.git"): -- cgit v1.2.3 From ca0affe7bbc0ef507e2ec01c75e4f54d309dfad7 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 16 May 2007 13:15:34 +0200 Subject: A little todo note before I forget it :), based on a suggestion from Lars. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 ++ 1 file changed, 2 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index ca6c623809..70366ff8c0 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -7,6 +7,8 @@ # 2007 Trolltech ASA # License: MIT # +# TODO: Add an option to sync/rebase to fetch and rebase from origin first. +# import optparse, sys, os, marshal, popen2, subprocess, shelve import tempfile, getopt, sha, os.path, time, platform -- cgit v1.2.3 From 5c4153e4880a90c05612521e9ee575a308d207db Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 17 May 2007 07:42:38 +0200 Subject: Fixing syncing (gitdir discovery / cd) for bare repositories Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 70366ff8c0..239304857d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1200,7 +1200,9 @@ if cmd.needsGit: if not isValidGitDir(gitdir): gitdir = mypopen("git rev-parse --git-dir").read()[:-1] if os.path.exists(gitdir): - os.chdir(mypopen("git rev-parse --show-cdup").read()[:-1]); + cdup = mypopen("git rev-parse --show-cdup").read()[:-1]; + if len(cdup) > 0: + os.chdir(cdup); if not isValidGitDir(gitdir): if isValidGitDir(gitdir + "/.git"): -- cgit v1.2.3 From f9162f6a4cc9f4af3e527412b364a8eda4502920 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 17 May 2007 09:02:45 +0200 Subject: Always pass a sha1 for the initial parent so that git-fast-import doesn't think it's creating a new branch from itself. It's a sensible error in general but in the case of incremental imports we have to apply force :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 239304857d..1f549b5c62 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -865,7 +865,7 @@ class P4Sync(Command): self.previousDepotPath = "" if len(self.branch) == 0: - self.branch = "p4" + self.branch = "refs/remotes/p4" if len(args) == 0: if not gitBranchExists(self.branch) and gitBranchExists("origin"): @@ -878,11 +878,12 @@ class P4Sync(Command): p4Change = int(p4Change) + 1 self.depotPath = self.previousDepotPath self.changeRange = "@%s,#head" % p4Change - self.initialParent = self.branch + self.initialParent = mypopen("git rev-parse %s" % self.branch).read()[:-1] if not self.silent: print "Performing incremental import into %s git branch" % self.branch - self.branch = "refs/heads/" + self.branch + if not self.branch.startswith("refs/"): + self.branch = "refs/heads/" + self.branch if len(self.depotPath) != 0: self.depotPath = self.depotPath[:-1] -- cgit v1.2.3 From 463e8af65577b1df4495cb08640840234ac80c86 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 17 May 2007 09:13:54 +0200 Subject: Clean up code duplication for revision parsing and fix previous commit to not import into remotes/p4 (yet!). Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 1f549b5c62..e18f3cb8ab 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -69,6 +69,9 @@ def isValidGitDir(path): return True; return False +def parseRevision(ref): + return mypopen("git rev-parse %s" % ref).read()[:-1] + def system(cmd): if os.system(cmd) != 0: die("command failed: %s" % cmd) @@ -865,7 +868,7 @@ class P4Sync(Command): self.previousDepotPath = "" if len(self.branch) == 0: - self.branch = "refs/remotes/p4" + self.branch = "p4" if len(args) == 0: if not gitBranchExists(self.branch) and gitBranchExists("origin"): @@ -878,7 +881,7 @@ class P4Sync(Command): p4Change = int(p4Change) + 1 self.depotPath = self.previousDepotPath self.changeRange = "@%s,#head" % p4Change - self.initialParent = mypopen("git rev-parse %s" % self.branch).read()[:-1] + self.initialParent = parseRevision(self.branch) if not self.silent: print "Performing incremental import into %s git branch" % self.branch @@ -943,7 +946,7 @@ class P4Sync(Command): endPos = caretIdx self.rev = int(output[tagIdx + 9 : endPos]) + 1 self.changeRange = "@%s,#head" % self.rev - self.initialParent = mypopen("git rev-parse %s" % self.branch).read()[:-1] + self.initialParent = parseRevision(self.branch) except: pass -- cgit v1.2.3 From 8a2820def44f163ec8909863aefa5e8f98a236ea Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 17 May 2007 19:44:50 +0200 Subject: Removed cleantags command. It doesn't have any meaning anymore. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 39 --------------------------------------- 1 file changed, 39 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e18f3cb8ab..910c69b534 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -129,44 +129,6 @@ class P4Debug(Command): print output return True -class P4CleanTags(Command): - def __init__(self): - Command.__init__(self) - self.options = [ -# optparse.make_option("--branch", dest="branch", default="refs/heads/master") - ] - self.description = "A tool to remove stale unused tags from incremental perforce imports." - def run(self, args): - branch = currentGitBranch() - print "Cleaning out stale p4 import tags..." - sout, sin, serr = popen2.popen3("git name-rev --tags `git rev-parse %s`" % branch) - output = sout.read() - try: - tagIdx = output.index(" tags/p4/") - except: - print "Cannot find any p4/* tag. Nothing to do." - sys.exit(0) - - try: - caretIdx = output.index("^") - except: - caretIdx = len(output) - 1 - rev = int(output[tagIdx + 9 : caretIdx]) - - allTags = mypopen("git tag -l p4/").readlines() - for i in range(len(allTags)): - allTags[i] = int(allTags[i][3:-1]) - - allTags.sort() - - allTags.remove(rev) - - for rev in allTags: - print mypopen("git tag -d p4/%s" % rev).read() - - print "%s tags removed." % len(allTags) - return True - class P4Submit(Command): def __init__(self): Command.__init__(self) @@ -1161,7 +1123,6 @@ def printUsage(commands): commands = { "debug" : P4Debug(), - "clean-tags" : P4CleanTags(), "submit" : P4Submit(), "sync" : P4Sync(), "rebase" : P4Rebase(), -- cgit v1.2.3 From 1c9d393d30797decad703b642fa87b67a5236af4 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 17 May 2007 20:15:47 +0200 Subject: Removed ancient and unused code to find the last imported revision from previous imports to use for the current import by looking at the p4 tags. The current approach of using the log message works better. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 910c69b534..a19ba47481 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -895,23 +895,6 @@ class P4Sync(Command): if self.detectLabels: self.getLabels(); - if len(self.changeRange) == 0: - try: - sout, sin, serr = popen2.popen3("git name-rev --tags `git rev-parse %s`" % self.branch) - output = sout.read() - if output.endswith("\n"): - output = output[:-1] - tagIdx = output.index(" tags/p4/") - caretIdx = output.find("^") - endPos = len(output) - if caretIdx != -1: - endPos = caretIdx - self.rev = int(output[tagIdx + 9 : endPos]) + 1 - self.changeRange = "@%s,#head" % self.rev - self.initialParent = parseRevision(self.branch) - except: - pass - 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); -- cgit v1.2.3 From 8ead4fda3fbaba93aae46931285e9613a058c08b Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 17 May 2007 20:26:58 +0200 Subject: Create the origin based import branch using git update-ref instead of git branch so that it's possible to have the import branch in refs/remotes. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index a19ba47481..4cd486eb3a 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -836,7 +836,10 @@ class P4Sync(Command): if not gitBranchExists(self.branch) and gitBranchExists("origin"): if not self.silent: print "Creating %s branch in git repository based on origin" % self.branch - system("git branch %s origin" % self.branch) + branch = self.branch + if not branch.startswith("refs"): + branch = "refs/heads/" + branch + system("git update-ref %s origin" % branch) [self.previousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(self.branch)) if len(self.previousDepotPath) > 0 and len(p4Change) > 0: -- cgit v1.2.3 From c6d44cb1a1a9bca58d91ef414b9dbaa393d2de3a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 17 May 2007 20:57:05 +0200 Subject: Changed the default p4 import branch to be refs/remotes/p4/{HEAD,master} instead of refs/heads/p4. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 4cd486eb3a..3cc6481378 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -828,9 +828,15 @@ class P4Sync(Command): self.changeRange = "" self.initialParent = "" self.previousDepotPath = "" + # importing into default remotes/p4/* layout? + defaultImport = False if len(self.branch) == 0: - self.branch = "p4" + if gitBranchExists("refs/heads/p4"): + self.branch = "p4" + else: + self.branch = "refs/remotes/p4/master" + defaultImport = True if len(args) == 0: if not gitBranchExists(self.branch) and gitBranchExists("origin"): @@ -840,6 +846,8 @@ class P4Sync(Command): if not branch.startswith("refs"): branch = "refs/heads/" + branch system("git update-ref %s origin" % branch) + if defaultImport: + system("git symbolic-ref refs/remotes/p4/HEAD %s" % branch) [self.previousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(self.branch)) if len(self.previousDepotPath) > 0 and len(p4Change) > 0: -- cgit v1.2.3 From 48df6fd850b2d9dc52a8a89a9e6deecd2cf1d351 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 17 May 2007 21:18:53 +0200 Subject: Bite the bullet and automatically convert old style refs/heads/p4 repositories to the new style refs/remotes/p4 branching. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3cc6481378..cb9961a571 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -832,10 +832,12 @@ class P4Sync(Command): defaultImport = False if len(self.branch) == 0: + self.branch = "refs/remotes/p4/master" if gitBranchExists("refs/heads/p4"): - self.branch = "p4" + system("git update-ref %s refs/heads/p4" % self.branch) + system("git symbolic-ref refs/remotes/p4/HEAD refs/remotes/p4/master") + system("git branch -D p4"); else: - self.branch = "refs/remotes/p4/master" defaultImport = True if len(args) == 0: -- cgit v1.2.3 From ef48f9093ced75ca20295f42b993bd390873573d Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 17 May 2007 22:17:49 +0200 Subject: Added support for git-p4 sync/rebase --with-origin. See git-p4.txt for details :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index cb9961a571..e653e8cd37 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -419,7 +419,8 @@ class P4Sync(Command): optparse.make_option("--known-branches", dest="knownBranches"), optparse.make_option("--data-cache", dest="dataCache", action="store_true"), optparse.make_option("--command-cache", dest="commandCache", action="store_true"), - optparse.make_option("--detect-labels", dest="detectLabels", action="store_true") + optparse.make_option("--detect-labels", dest="detectLabels", action="store_true"), + optparse.make_option("--with-origin", dest="syncWithOrigin", action="store_true") ] self.description = """Imports from Perforce into a git repository.\n example: @@ -441,6 +442,7 @@ class P4Sync(Command): self.detectBranches = False self.detectLabels = False self.changesFile = "" + self.syncWithOrigin = False def p4File(self, depotPath): return os.popen("p4 print -q \"%s\"" % depotPath, "rb").read() @@ -831,6 +833,21 @@ class P4Sync(Command): # importing into default remotes/p4/* layout? defaultImport = False + if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists("refs/remotes/p4/master"): + print "Syncing with origin first as requested by calling git fetch origin" + system("git fetch origin") + [originPreviousDepotPath, originP4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("origin")) + [p4PreviousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("p4")) + if len(originPreviousDepotPath) > 0 and len(originP4Change) > 0 and len(p4Change) > 0: + if originPreviousDepotPath == p4PreviousDepotPath: + originP4Change = int(originP4Change) + p4Change = int(p4Change) + if originP4Change > p4Change: + print "origin (%s) is newer than p4 (%s). Updating p4 branch from origin." % (originP4Change, p4Change) + system("git update-ref refs/remotes/p4/master origin"); + else: + print "Cannot sync with origin. It was imported from %s while remotes/p4 was imported from %s" % (originPreviousDepotPath, p4PreviousDepotPath) + if len(self.branch) == 0: self.branch = "refs/remotes/p4/master" if gitBranchExists("refs/heads/p4"): @@ -1037,11 +1054,13 @@ class P4Sync(Command): class P4Rebase(Command): def __init__(self): Command.__init__(self) - self.options = [ ] + self.options = [ optparse.make_option("--with-origin", dest="syncWithOrigin", action="store_true") ] self.description = "Fetches the latest revision from perforce and rebases the current work (branch) against it" + self.syncWithOrigin = False def run(self, args): sync = P4Sync() + sync.syncWithOrigin = self.syncWithOrigin sync.run([]) print "Rebasing the current branch" oldHead = mypopen("git rev-parse HEAD").read()[:-1] -- cgit v1.2.3 From 71bd9bacec6a18c2db582e1f32b1902c82359376 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 17 May 2007 22:22:26 +0200 Subject: Removed todo item that is implemented :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 -- 1 file changed, 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e653e8cd37..a21d902ea9 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -7,8 +7,6 @@ # 2007 Trolltech ASA # License: MIT # -# TODO: Add an option to sync/rebase to fetch and rebase from origin first. -# import optparse, sys, os, marshal, popen2, subprocess, shelve import tempfile, getopt, sha, os.path, time, platform -- cgit v1.2.3 From 05094f987c2f141ec9b873ad6d6303b0aca173a4 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 18 May 2007 20:32:35 +0200 Subject: Fix branch setup after initial clone. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index a21d902ea9..2f3615bd72 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -828,8 +828,6 @@ class P4Sync(Command): self.changeRange = "" self.initialParent = "" self.previousDepotPath = "" - # importing into default remotes/p4/* layout? - defaultImport = False if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists("refs/remotes/p4/master"): print "Syncing with origin first as requested by calling git fetch origin" @@ -850,10 +848,9 @@ class P4Sync(Command): self.branch = "refs/remotes/p4/master" if gitBranchExists("refs/heads/p4"): system("git update-ref %s refs/heads/p4" % self.branch) - system("git symbolic-ref refs/remotes/p4/HEAD refs/remotes/p4/master") system("git branch -D p4"); - else: - defaultImport = True + if not gitBranchExists("refs/remotes/p4/HEAD"): + system("git symbolic-ref refs/remotes/p4/HEAD %s" % self.branch) if len(args) == 0: if not gitBranchExists(self.branch) and gitBranchExists("origin"): @@ -863,8 +860,6 @@ class P4Sync(Command): if not branch.startswith("refs"): branch = "refs/heads/" + branch system("git update-ref %s origin" % branch) - if defaultImport: - system("git symbolic-ref refs/remotes/p4/HEAD %s" % branch) [self.previousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(self.branch)) if len(self.previousDepotPath) > 0 and len(p4Change) > 0: -- cgit v1.2.3 From 66c6a9b559a883460b1aeed7dadec713be17588c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 18 May 2007 20:39:38 +0200 Subject: Removed unused cache variables. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ---- 1 file changed, 4 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 2f3615bd72..e164edef55 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -415,8 +415,6 @@ class P4Sync(Command): optparse.make_option("--changesfile", dest="changesFile"), optparse.make_option("--silent", dest="silent", action="store_true"), optparse.make_option("--known-branches", dest="knownBranches"), - optparse.make_option("--data-cache", dest="dataCache", action="store_true"), - optparse.make_option("--command-cache", dest="commandCache", action="store_true"), optparse.make_option("--detect-labels", dest="detectLabels", action="store_true"), optparse.make_option("--with-origin", dest="syncWithOrigin", action="store_true") ] @@ -430,8 +428,6 @@ class P4Sync(Command): self.usage += " //depot/path[@revRange]" - self.dataCache = False - self.commandCache = False self.silent = False self.knownBranches = Set() self.createdBranches = Set() -- cgit v1.2.3 From 4b97ffb1e462c2334b38047fbf2b7e8b24c36aed Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 18 May 2007 21:45:23 +0200 Subject: Started rewriting the branch detection, based on "p4 branches" and "p4 branch -o foo". Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 287 +++++++-------------------------------------- 1 file changed, 45 insertions(+), 242 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e164edef55..e993d3f693 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -414,9 +414,9 @@ class P4Sync(Command): optparse.make_option("--detect-branches", dest="detectBranches", action="store_true"), optparse.make_option("--changesfile", dest="changesFile"), optparse.make_option("--silent", dest="silent", action="store_true"), - optparse.make_option("--known-branches", dest="knownBranches"), optparse.make_option("--detect-labels", dest="detectLabels", action="store_true"), - optparse.make_option("--with-origin", dest="syncWithOrigin", action="store_true") + optparse.make_option("--with-origin", dest="syncWithOrigin", action="store_true"), + optparse.make_option("--verbose", dest="verbose", action="store_true") ] self.description = """Imports from Perforce into a git repository.\n example: @@ -429,7 +429,6 @@ class P4Sync(Command): self.usage += " //depot/path[@revRange]" self.silent = False - self.knownBranches = Set() self.createdBranches = Set() self.committedChanges = Set() self.branch = "" @@ -437,6 +436,7 @@ class P4Sync(Command): self.detectLabels = False self.changesFile = "" self.syncWithOrigin = False + self.verbose = False def p4File(self, depotPath): return os.popen("p4 print -q \"%s\"" % depotPath, "rb").read() @@ -461,120 +461,25 @@ class P4Sync(Command): fnum = fnum + 1 return files - def isSubPathOf(self, first, second): - if not first.startswith(second): - return False - if first == second: - return True - return first[len(second)] == "/" - def branchesForCommit(self, files): branches = Set() for file in files: - relativePath = file["path"][len(self.depotPath):] - # strip off the filename - relativePath = relativePath[0:relativePath.rfind("/")] - - # if len(branches) == 0: - # branches.add(relativePath) - # knownBranches.add(relativePath) - # continue - - ###### this needs more testing :) - knownBranch = False - for branch in branches: - if relativePath == branch: - knownBranch = True - break - # if relativePath.startswith(branch): - if self.isSubPathOf(relativePath, branch): - knownBranch = True - break - # if branch.startswith(relativePath): - if self.isSubPathOf(branch, relativePath): - branches.remove(branch) - break - - if knownBranch: - continue - - for branch in self.knownBranches: - #if relativePath.startswith(branch): - if self.isSubPathOf(relativePath, branch): - if len(branches) == 0: - relativePath = branch - else: - knownBranch = True - break + path = file["path"][len(self.depotPath):] - if knownBranch: - continue - - branches.add(relativePath) - self.knownBranches.add(relativePath) + for branch in self.knownBranches.keys(): + if path.startswith(branch): + branches.add(branch) return branches - def findBranchParent(self, branchPrefix, files): - for file in files: - path = file["path"] - if not path.startswith(branchPrefix): - continue - action = file["action"] - if action != "integrate" and action != "branch": - continue - rev = file["rev"] - depotPath = path + "#" + rev - - log = p4CmdList("filelog \"%s\"" % depotPath) - if len(log) != 1: - print "eek! I got confused by the filelog of %s" % depotPath - sys.exit(1); - - log = log[0] - if log["action0"] != action: - print "eek! wrong action in filelog for %s : found %s, expected %s" % (depotPath, log["action0"], action) - sys.exit(1); - - branchAction = log["how0,0"] - # if branchAction == "branch into" or branchAction == "ignored": - # continue # ignore for branching - - if not branchAction.endswith(" from"): - continue # ignore for branching - # print "eek! file %s was not branched from but instead: %s" % (depotPath, branchAction) - # sys.exit(1); - - source = log["file0,0"] - if source.startswith(branchPrefix): - continue - - lastSourceRev = log["erev0,0"] - - sourceLog = p4CmdList("filelog -m 1 \"%s%s\"" % (source, lastSourceRev)) - if len(sourceLog) != 1: - print "eek! I got confused by the source filelog of %s%s" % (source, lastSourceRev) - sys.exit(1); - sourceLog = sourceLog[0] - - relPath = source[len(self.depotPath):] - # strip off the filename - relPath = relPath[0:relPath.rfind("/")] - - for branch in self.knownBranches: - if self.isSubPathOf(relPath, branch): - # print "determined parent branch branch %s due to change in file %s" % (branch, source) - return branch - # else: - # print "%s is not a subpath of branch %s" % (relPath, branch) - - return "" - - def commit(self, details, files, branch, branchPrefix, parent = "", merged = ""): + def commit(self, details, files, branch, branchPrefix, parent = ""): epoch = details["time"] author = details["user"] + if self.verbose: + print "commit into %s" % branch + self.gitStream.write("commit %s\n" % branch) # gitStream.write("mark :%s\n" % details["change"]) self.committedChanges.add(int(details["change"])) @@ -592,11 +497,10 @@ class P4Sync(Command): self.gitStream.write("EOT\n\n") if len(parent) > 0: + if self.verbose: + print "parent %s" % parent self.gitStream.write("from %s\n" % parent) - if len(merged) > 0: - self.gitStream.write("merge %s\n" % merged) - for file in files: path = file["path"] if not path.startswith(branchPrefix): @@ -680,118 +584,6 @@ class P4Sync(Command): return newFiles - def findBranchSourceHeuristic(self, files, branch, branchPrefix): - for file in files: - action = file["action"] - if action != "integrate" and action != "branch": - continue - path = file["path"] - rev = file["rev"] - depotPath = path + "#" + rev - - log = p4CmdList("filelog \"%s\"" % depotPath) - if len(log) != 1: - print "eek! I got confused by the filelog of %s" % depotPath - sys.exit(1); - - log = log[0] - if log["action0"] != action: - print "eek! wrong action in filelog for %s : found %s, expected %s" % (depotPath, log["action0"], action) - sys.exit(1); - - branchAction = log["how0,0"] - - if not branchAction.endswith(" from"): - continue # ignore for branching - # print "eek! file %s was not branched from but instead: %s" % (depotPath, branchAction) - # sys.exit(1); - - source = log["file0,0"] - if source.startswith(branchPrefix): - continue - - lastSourceRev = log["erev0,0"] - - sourceLog = p4CmdList("filelog -m 1 \"%s%s\"" % (source, lastSourceRev)) - if len(sourceLog) != 1: - print "eek! I got confused by the source filelog of %s%s" % (source, lastSourceRev) - sys.exit(1); - sourceLog = sourceLog[0] - - relPath = source[len(self.depotPath):] - # strip off the filename - relPath = relPath[0:relPath.rfind("/")] - - for candidate in self.knownBranches: - if self.isSubPathOf(relPath, candidate) and candidate != branch: - return candidate - - return "" - - def changeIsBranchMerge(self, sourceBranch, destinationBranch, change): - sourceFiles = {} - for file in p4CmdList("files %s...@%s" % (self.depotPath + sourceBranch + "/", change)): - if file["action"] == "delete": - continue - sourceFiles[file["depotFile"]] = file - - destinationFiles = {} - for file in p4CmdList("files %s...@%s" % (self.depotPath + destinationBranch + "/", change)): - destinationFiles[file["depotFile"]] = file - - for fileName in sourceFiles.keys(): - integrations = [] - deleted = False - integrationCount = 0 - for integration in p4CmdList("integrated \"%s\"" % fileName): - toFile = integration["fromFile"] # yes, it's true, it's fromFile - if not toFile in destinationFiles: - continue - destFile = destinationFiles[toFile] - if destFile["action"] == "delete": - # print "file %s has been deleted in %s" % (fileName, toFile) - deleted = True - break - integrationCount += 1 - if integration["how"] == "branch from": - continue - - if int(integration["change"]) == change: - integrations.append(integration) - continue - if int(integration["change"]) > change: - continue - - destRev = int(destFile["rev"]) - - startRev = integration["startFromRev"][1:] - if startRev == "none": - startRev = 0 - else: - startRev = int(startRev) - - endRev = integration["endFromRev"][1:] - if endRev == "none": - endRev = 0 - else: - endRev = int(endRev) - - initialBranch = (destRev == 1 and integration["how"] != "branch into") - inRange = (destRev >= startRev and destRev <= endRev) - newer = (destRev > startRev and destRev > endRev) - - if initialBranch or inRange or newer: - integrations.append(integration) - - if deleted: - continue - - if len(integrations) == 0 and integrationCount > 1: - print "file %s was not integrated from %s into %s" % (fileName, sourceBranch, destinationBranch) - return False - - return True - def getUserMap(self): self.users = {} @@ -819,6 +611,27 @@ class P4Sync(Command): self.labels[newestChange] = [output, revisions] + def getBranchMapping(self): + # map from branch depot path to parent branch + self.knownBranches = {} + + for info in p4CmdList("branches"): + details = p4Cmd("branch -o %s" % info["branch"]) + viewIdx = 0 + while details.has_key("View%s" % viewIdx): + paths = details["View%s" % viewIdx].split(" ") + viewIdx = viewIdx + 1 + # require standard //depot/foo/... //depot/bar/... mapping + if len(paths) != 2 or not paths[0].endswith("/...") or not paths[1].endswith("/..."): + continue + source = paths[0] + destination = paths[1] + if source.startswith(self.depotPath) and destination.startswith(self.depotPath): + source = source[len(self.depotPath):-4] + destination = destination[len(self.depotPath):-4] + self.knownBranches[destination] = source + self.knownBranches[source] = source + def run(self, args): self.depotPath = "" self.changeRange = "" @@ -914,6 +727,9 @@ class P4Sync(Command): if self.detectLabels: self.getLabels(); + if self.detectBranches: + self.getBranchMapping(); + 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); @@ -993,35 +809,22 @@ class P4Sync(Command): files = self.extractFilesFromCommit(description) if self.detectBranches: for branch in self.branchesForCommit(files): - self.knownBranches.add(branch) branchPrefix = self.depotPath + branch + "/" - filesForCommit = self.extractFilesInCommitToBranch(files, branchPrefix) - - merged = "" parent = "" - ########### remove cnt!!! - if branch not in self.createdBranches and cnt > 2: + + filesForCommit = self.extractFilesInCommitToBranch(files, branch) + + if branch not in self.createdBranches : self.createdBranches.add(branch) - parent = self.findBranchParent(branchPrefix, files) + parent = self.knownBranches[branch] if parent == branch: parent = "" - # elif len(parent) > 0: - # print "%s branched off of %s" % (branch, parent) - - if len(parent) == 0: - merged = self.findBranchSourceHeuristic(filesForCommit, branch, branchPrefix) - if len(merged) > 0: - print "change %s could be a merge from %s into %s" % (description["change"], merged, branch) - if not self.changeIsBranchMerge(merged, branch, int(description["change"])): - merged = "" - branch = "refs/heads/" + branch + branch = "refs/remotes/p4/" + branch if len(parent) > 0: - parent = "refs/heads/" + parent - if len(merged) > 0: - merged = "refs/heads/" + merged - self.commit(description, files, branch, branchPrefix, parent, merged) + parent = "refs/remotes/p4/" + parent + self.commit(description, files, branch, branchPrefix, parent) else: self.commit(description, files, self.branch, self.depotPath, self.initialParent) self.initialParent = "" -- cgit v1.2.3 From 8f9b2e082b54787676bdad793ca013ba4fb4e407 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 18 May 2007 22:13:26 +0200 Subject: Give branches a nice project prefix and don't bail out on clone if we failed to detect the master branch. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e993d3f693..7d42739637 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -729,6 +729,7 @@ class P4Sync(Command): if self.detectBranches: self.getBranchMapping(); + self.branchPrefix = self.depotPath[self.depotPath[:-1].rfind("/") + 1:] self.tz = "%+03d%02d" % (- time.timezone / 3600, ((- time.timezone % 3600) / 60)) @@ -815,12 +816,23 @@ class P4Sync(Command): filesForCommit = self.extractFilesInCommitToBranch(files, branch) - if branch not in self.createdBranches : + if branch not in self.createdBranches: self.createdBranches.add(branch) parent = self.knownBranches[branch] if parent == branch: parent = "" + # main branch? use master + if branch == "main": + branch = "master" + else: + branch = self.branchPrefix + branch + + if parent == "main": + parent = "master" + elif len(parent) > 0: + parent = self.branchPrefix + parent + branch = "refs/remotes/p4/" + branch if len(parent) > 0: parent = "refs/remotes/p4/" + parent @@ -906,8 +918,11 @@ class P4Clone(P4Sync): if not P4Sync.run(self, [depotPath]): return False if self.branch != "master": - system("git branch master p4") - system("git checkout -f") + if gitBranchExists("refs/remotes/p4/master"): + system("git branch master refs/remotes/p4/master") + system("git checkout -f") + else: + print "Could not detect main branch. No checkout/master branch created." return True class HelpFormatter(optparse.IndentedHelpFormatter): -- cgit v1.2.3 From 29bdbac1cd5fc4126b62c9a030403d56ae43c204 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 19 May 2007 10:23:12 +0200 Subject: More work on the incremental importing of multiple branches. Improved error detection by checking the exit code of git-fast-import. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 90 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 14 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 7d42739637..2c1dc9e2b3 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -612,8 +612,7 @@ class P4Sync(Command): self.labels[newestChange] = [output, revisions] def getBranchMapping(self): - # map from branch depot path to parent branch - self.knownBranches = {} + self.projectName = self.depotPath[self.depotPath[:-1].rfind("/") + 1:] for info in p4CmdList("branches"): details = p4Cmd("branch -o %s" % info["branch"]) @@ -629,16 +628,34 @@ class P4Sync(Command): if source.startswith(self.depotPath) and destination.startswith(self.depotPath): source = source[len(self.depotPath):-4] destination = destination[len(self.depotPath):-4] - self.knownBranches[destination] = source - self.knownBranches[source] = source + if destination not in self.knownBranches: + self.knownBranches[destination] = source + if source not in self.knownBranches: + self.knownBranches[source] = source + + def listExistingP4GitBranches(self): + self.p4BranchesInGit = [] + + for line in mypopen("git rev-parse --symbolic --remotes").readlines(): + if line.startswith("p4/") and line != "p4/HEAD\n": + branch = line[3:-1] + self.p4BranchesInGit.append(branch) + self.initialParents["refs/remotes/p4/" + branch] = parseRevision(line[:-1]) def run(self, args): self.depotPath = "" self.changeRange = "" self.initialParent = "" self.previousDepotPath = "" + # map from branch depot path to parent branch + self.knownBranches = {} + self.initialParents = {} + + self.listExistingP4GitBranches() + + if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists("refs/remotes/p4/master") and not self.detectBranches: + ### needs to be ported to multi branch import - if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists("refs/remotes/p4/master"): print "Syncing with origin first as requested by calling git fetch origin" system("git fetch origin") [originPreviousDepotPath, originP4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("origin")) @@ -662,7 +679,8 @@ class P4Sync(Command): system("git symbolic-ref refs/remotes/p4/HEAD %s" % self.branch) if len(args) == 0: - if not gitBranchExists(self.branch) and gitBranchExists("origin"): + if not gitBranchExists(self.branch) and gitBranchExists("origin") and not self.detectBranches: + ### needs to be ported to multi branch import if not self.silent: print "Creating %s branch in git repository based on origin" % self.branch branch = self.branch @@ -670,11 +688,33 @@ class P4Sync(Command): branch = "refs/heads/" + branch system("git update-ref %s origin" % branch) - [self.previousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(self.branch)) - if len(self.previousDepotPath) > 0 and len(p4Change) > 0: - p4Change = int(p4Change) + 1 + if self.verbose: + print "branches: %s" % self.p4BranchesInGit + + p4Change = 0 + for branch in self.p4BranchesInGit: + depotPath, change = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("refs/remotes/p4/" + branch)) + + if self.verbose: + print "path %s change %s" % (depotPath, change) + + if len(depotPath) > 0 and len(change) > 0: + change = int(change) + 1 + p4Change = max(p4Change, change) + + if len(self.previousDepotPath) == 0: + self.previousDepotPath = depotPath + 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] + + if p4Change > 0: self.depotPath = self.previousDepotPath - self.changeRange = "@%s,#head" % p4Change + #self.changeRange = "@%s,#head" % p4Change + self.changeRange = "@%s,%s" % (p4Change, p4Change + 10) self.initialParent = parseRevision(self.branch) if not self.silent: print "Performing incremental import into %s git branch" % self.branch @@ -729,7 +769,13 @@ class P4Sync(Command): if self.detectBranches: self.getBranchMapping(); - self.branchPrefix = self.depotPath[self.depotPath[:-1].rfind("/") + 1:] + if self.verbose: + print "p4-git branches: %s" % self.p4BranchesInGit + print "initial parents: %s" % self.initialParents + for b in self.p4BranchesInGit: + if b != "master": + b = b[len(self.projectName):] + self.createdBranches.add(b) self.tz = "%+03d%02d" % (- time.timezone / 3600, ((- time.timezone % 3600) / 60)) @@ -784,6 +830,8 @@ class P4Sync(Command): changes.sort() else: + if self.verbose: + print "Getting p4 changes for %s...%s" % (self.depotPath, self.changeRange) output = mypopen("p4 changes %s...%s" % (self.depotPath, self.changeRange)).readlines() for line in output: @@ -816,26 +864,39 @@ class P4Sync(Command): filesForCommit = self.extractFilesInCommitToBranch(files, branch) + if self.verbose: + print "branch is %s" % branch + if branch not in self.createdBranches: self.createdBranches.add(branch) parent = self.knownBranches[branch] if parent == branch: parent = "" + elif self.verbose: + print "parent determined through known branches: %s" % parent # main branch? use master if branch == "main": branch = "master" else: - branch = self.branchPrefix + branch + branch = self.projectName + branch if parent == "main": parent = "master" elif len(parent) > 0: - parent = self.branchPrefix + parent + parent = self.projectName + parent branch = "refs/remotes/p4/" + branch if len(parent) > 0: parent = "refs/remotes/p4/" + parent + + if self.verbose: + print "looking for initial parent for %s; current parent is %s" % (branch, parent) + + if len(parent) == 0 and branch in self.initialParents: + parent = self.initialParents[branch] + del self.initialParents[branch] + self.commit(description, files, branch, branchPrefix, parent) else: self.commit(description, files, self.branch, self.depotPath, self.initialParent) @@ -849,9 +910,10 @@ class P4Sync(Command): self.gitStream.close() + if importProcess.wait() != 0: + die("fast-import failed: %s" % self.gitError.read()) self.gitOutput.close() self.gitError.close() - importProcess.wait() return True -- cgit v1.2.3 From d5904674d1a52620a702b4f5efa1afe21f8a5947 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 19 May 2007 11:07:32 +0200 Subject: Cleanup/speed up the branch<> file split and removed change range limitation that I added for debugging (oops). Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 2c1dc9e2b3..35c5f9c696 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -461,15 +461,17 @@ class P4Sync(Command): fnum = fnum + 1 return files - def branchesForCommit(self, files): - branches = Set() + def splitFilesIntoBranches(self, files): + branches = {} for file in files: path = file["path"][len(self.depotPath):] for branch in self.knownBranches.keys(): if path.startswith(branch): - branches.add(branch) + if branch not in branches: + branches[branch] = [] + branches[branch].append(file["path"]) return branches @@ -574,16 +576,6 @@ class P4Sync(Command): if not self.silent: print "Tag %s does not match with change %s: file count is different." % (labelDetails["label"], change) - def extractFilesInCommitToBranch(self, files, branchPrefix): - newFiles = [] - - for file in files: - path = file["path"] - if path.startswith(branchPrefix): - newFiles.append(file) - - return newFiles - def getUserMap(self): self.users = {} @@ -713,8 +705,7 @@ class P4Sync(Command): if p4Change > 0: self.depotPath = self.previousDepotPath - #self.changeRange = "@%s,#head" % p4Change - self.changeRange = "@%s,%s" % (p4Change, p4Change + 10) + self.changeRange = "@%s,#head" % p4Change self.initialParent = parseRevision(self.branch) if not self.silent: print "Performing incremental import into %s git branch" % self.branch @@ -857,12 +848,13 @@ class P4Sync(Command): try: files = self.extractFilesFromCommit(description) if self.detectBranches: - for branch in self.branchesForCommit(files): + branches = self.splitFilesIntoBranches(files) + for branch in branches.keys(): branchPrefix = self.depotPath + branch + "/" parent = "" - filesForCommit = self.extractFilesInCommitToBranch(files, branch) + filesForCommit = branches[branch] if self.verbose: print "branch is %s" % branch -- cgit v1.2.3 From 71b112d4a4e070170af7b5a50647f7dac9b48e56 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 19 May 2007 11:54:11 +0200 Subject: More cleanups and speedups for labels and branches Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 35c5f9c696..49114d2c6f 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -461,17 +461,32 @@ class P4Sync(Command): fnum = fnum + 1 return files - def splitFilesIntoBranches(self, files): + def splitFilesIntoBranches(self, commit): branches = {} - for file in files: - path = file["path"][len(self.depotPath):] + 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) + fnum = fnum + 1 + continue + + file = {} + file["path"] = path + file["rev"] = commit["rev%s" % fnum] + file["action"] = commit["action%s" % fnum] + file["type"] = commit["type%s" % fnum] + fnum = fnum + 1 + + relPath = path[len(self.depotPath):] for branch in self.knownBranches.keys(): - if path.startswith(branch): + if relPath.startswith(branch): if branch not in branches: branches[branch] = [] - branches[branch].append(file["path"]) + branches[branch].append(file) return branches @@ -542,6 +557,8 @@ class P4Sync(Command): label = self.labels[change] labelDetails = label[0] labelRevisions = label[1] + if self.verbose: + print "Change %s is labelled %s" % (change, labelDetails) files = p4CmdList("files %s...@%s" % (branchPrefix, change)) @@ -595,13 +612,15 @@ class P4Sync(Command): label = output["label"] revisions = {} newestChange = 0 - for file in p4CmdList("files //...@%s" % label): + if self.verbose: + print "Querying files for label %s" % label + for file in p4CmdList("files %s...@%s" % (self.depotPath, label)): revisions[file["depotFile"]] = file["rev"] change = int(file["change"]) if change > newestChange: newestChange = change - self.labels[newestChange] = [output, revisions] + self.labels[int(newestChange)] = [output, revisions] def getBranchMapping(self): self.projectName = self.depotPath[self.depotPath[:-1].rfind("/") + 1:] @@ -846,9 +865,8 @@ class P4Sync(Command): cnt = cnt + 1 try: - files = self.extractFilesFromCommit(description) if self.detectBranches: - branches = self.splitFilesIntoBranches(files) + branches = self.splitFilesIntoBranches(description) for branch in branches.keys(): branchPrefix = self.depotPath + branch + "/" @@ -889,8 +907,9 @@ class P4Sync(Command): parent = self.initialParents[branch] del self.initialParents[branch] - self.commit(description, files, branch, branchPrefix, parent) + self.commit(description, filesForCommit, branch, branchPrefix, parent) else: + files = self.extractFilesFromCommit(description) self.commit(description, files, self.branch, self.depotPath, self.initialParent) self.initialParent = "" except IOError: -- cgit v1.2.3 From 9bda3a8556681c90309ec34e2ee5ae50306b61a6 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 19 May 2007 12:05:40 +0200 Subject: Removed unused variable, more cleanups Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 49114d2c6f..f76d198d64 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -551,9 +551,7 @@ class P4Sync(Command): change = int(details["change"]) - self.lastChange = change - - if change in self.labels: + if self.labels.has_key(change): label = self.labels[change] labelDetails = label[0] labelRevisions = label[1] @@ -620,7 +618,10 @@ class P4Sync(Command): if change > newestChange: newestChange = change - self.labels[int(newestChange)] = [output, revisions] + self.labels[newestChange] = [output, revisions] + + if self.verbose: + print "Label changes: %s" % self.labels.keys() def getBranchMapping(self): self.projectName = self.depotPath[self.depotPath[:-1].rfind("/") + 1:] @@ -748,7 +749,6 @@ class P4Sync(Command): self.revision = "" self.users = {} - self.lastChange = 0 if self.depotPath.find("@") != -1: atIdx = self.depotPath.index("@") -- cgit v1.2.3 From b607e71efdd23cd676645b5d7bf49d985834fab8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 20 May 2007 10:55:54 +0200 Subject: Cache the output of "p4 users" for faster syncs on high latency links. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index f76d198d64..e5e7c6be12 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -501,6 +501,8 @@ class P4Sync(Command): # gitStream.write("mark :%s\n" % details["change"]) self.committedChanges.add(int(details["change"])) committer = "" + if author not in self.users: + self.getUserMapFromPerforceServer() if author in self.users: committer = "%s %s %s" % (self.users[author], epoch, self.tz) else: @@ -591,7 +593,7 @@ class P4Sync(Command): if not self.silent: print "Tag %s does not match with change %s: file count is different." % (labelDetails["label"], change) - def getUserMap(self): + def getUserMapFromPerforceServer(self): self.users = {} for output in p4CmdList("users"): @@ -599,6 +601,23 @@ class P4Sync(Command): continue self.users[output["User"]] = output["FullName"] + " <" + output["Email"] + ">" + cache = open(gitdir + "/p4-usercache.txt", "wb") + for user in self.users.keys(): + cache.write("%s\t%s\n" % (user, self.users[user])) + cache.close(); + + def loadUserMapFromCache(self): + self.users = {} + try: + cache = open(gitdir + "/p4-usercache.txt", "rb") + lines = cache.readlines() + cache.close() + for line in lines: + entry = line[:-1].split("\t") + self.users[entry[0]] = entry[1] + except IOError: + self.getUserMapFromPerforceServer() + def getLabels(self): self.labels = {} @@ -772,7 +791,7 @@ class P4Sync(Command): if not self.depotPath.endswith("/"): self.depotPath += "/" - self.getUserMap() + self.loadUserMapFromCache() self.labels = {} if self.detectLabels: self.getLabels(); -- cgit v1.2.3 From 59fa4171090ae8dcc7087ac617dca40e66f9b33a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 20 May 2007 15:15:34 +0200 Subject: Fix gitdir not being set when cloning. Needed for writing the p4 users cache. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 3 +++ 1 file changed, 3 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e5e7c6be12..14be55bcfc 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -972,6 +972,8 @@ class P4Clone(P4Sync): self.needsGit = False def run(self, args): + global gitdir + if len(args) < 1: return False depotPath = args[0] @@ -1007,6 +1009,7 @@ class P4Clone(P4Sync): os.makedirs(dir) os.chdir(dir) system("git init") + gitdir = os.getcwd() if not P4Sync.run(self, [depotPath]): return False if self.branch != "master": -- cgit v1.2.3 From 64ffb06a9c940e57a215d313cd58f702d695e919 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 20 May 2007 15:24:01 +0200 Subject: Oops, not only /set/ gitdir on clone, also set it /correctly/ :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 14be55bcfc..80d966fb30 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1009,7 +1009,7 @@ class P4Clone(P4Sync): os.makedirs(dir) os.chdir(dir) system("git init") - gitdir = os.getcwd() + gitdir = os.getcwd() + "/.git" if not P4Sync.run(self, [depotPath]): return False if self.branch != "master": -- cgit v1.2.3 From 47a130b7bf74b8f61d9fee01f5dbb745d8f44b29 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 20 May 2007 16:33:21 +0200 Subject: Use git format-patch and git apply --apply when extracting patches from git and applying them to a Perforce checkout. This should make it possible to apply git commits with binary files that cannot be handled by path. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 80d966fb30..0b1df09cb8 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -213,10 +213,13 @@ class P4Submit(Command): else: die("unknown modifier %s for %s" % (modifier, path)) - diffcmd = "git diff-tree -p --diff-filter=ACMRTUXB \"%s^\" \"%s\"" % (id, id) - patchcmd = diffcmd + " | patch -p1" + diffcmd = "git format-patch -k --stdout \"%s^\"..\"%s\"" % (id, id) + patchcmd = diffcmd + " | git apply " + tryPatchCmd = diffcmd + "--check -" + applyPatchCmd = diffcmd + "--check --apply -" + print mypopen(diffcmd).read() - if os.system(patchcmd + " --dry-run --silent") != 0: + if os.system(tryPatchCmd) != 0: print "Unfortunately applying the change failed!" print "What do you want to do?" response = "x" @@ -226,7 +229,7 @@ class P4Submit(Command): print "Skipping! Good luck with the next patches..." return elif response == "a": - os.system(patchcmd) + os.system(applyPatchCmd) if len(filesToAdd) > 0: print "You may also want to call p4 add on the following files:" print " ".join(filesToAdd) @@ -239,7 +242,7 @@ class P4Submit(Command): print "Patch saved to patch.txt in %s !" % self.clientPath die("Please resolve and submit the conflict manually and continue afterwards with git-p4 submit --continue") - system(patchcmd) + system(applyPatchCmd) for f in filesToAdd: system("p4 add %s" % f) -- cgit v1.2.3 From c1b296b9f19a62aa9e444cc454b3d62ffaa98da4 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 20 May 2007 16:55:05 +0200 Subject: Added support for git-p4 submit --direct (experimental) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 61 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 14 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 0b1df09cb8..bcea4cf3de 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -137,6 +137,7 @@ class P4Submit(Command): optparse.make_option("--log-substitutions", dest="substFile"), optparse.make_option("--noninteractive", action="store_false"), optparse.make_option("--dry-run", action="store_true"), + optparse.make_option("--direct", dest="directSubmit", action="store_true"), ] self.description = "Submit changes from git to the perforce depot." self.usage += " [name of git branch to submit into perforce depot]" @@ -147,6 +148,7 @@ class P4Submit(Command): self.substFile = "" self.firstTime = True self.origin = "" + self.directSubmit = False self.logSubstitutions = {} self.logSubstitutions[""] = "%log%" @@ -161,9 +163,12 @@ class P4Submit(Command): die("Cannot start sync. Previous sync config found at %s\nIf you want to start submitting again from scratch maybe you want to call git-p4 submit --reset" % self.configFile) commits = [] - for line in mypopen("git rev-list --no-merges %s..%s" % (self.origin, self.master)).readlines(): - commits.append(line[:-1]) - commits.reverse() + if self.directSubmit: + commits.append("0") + else: + for line in mypopen("git rev-list --no-merges %s..%s" % (self.origin, self.master)).readlines(): + commits.append(line[:-1]) + commits.reverse() self.config["commits"] = commits @@ -191,8 +196,12 @@ class P4Submit(Command): return result def apply(self, id): - print "Applying %s" % (mypopen("git log --max-count=1 --pretty=oneline %s" % id).read()) - diff = mypopen("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)).readlines() + if self.directSubmit: + print "Applying local change in working directory/index" + diff = self.diffStatus + else: + print "Applying %s" % (mypopen("git log --max-count=1 --pretty=oneline %s" % id).read()) + diff = mypopen("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)).readlines() filesToAdd = set() filesToDelete = set() editedFiles = set() @@ -213,11 +222,13 @@ class P4Submit(Command): else: die("unknown modifier %s for %s" % (modifier, path)) - diffcmd = "git format-patch -k --stdout \"%s^\"..\"%s\"" % (id, id) + if self.directSubmit: + diffcmd = "cat \"%s\"" % self.diffFile + else: + diffcmd = "git format-patch -k --stdout \"%s^\"..\"%s\"" % (id, id) patchcmd = diffcmd + " | git apply " - tryPatchCmd = diffcmd + "--check -" - applyPatchCmd = diffcmd + "--check --apply -" - print mypopen(diffcmd).read() + tryPatchCmd = patchcmd + "--check -" + applyPatchCmd = patchcmd + "--check --apply -" if os.system(tryPatchCmd) != 0: print "Unfortunately applying the change failed!" @@ -250,9 +261,11 @@ class P4Submit(Command): system("p4 revert %s" % f) system("p4 delete %s" % f) - logMessage = extractLogMessageFromGitCommit(id) - logMessage = logMessage.replace("\n", "\n\t") - logMessage = logMessage[:-1] + logMessage = "" + if not self.directSubmit: + logMessage = extractLogMessageFromGitCommit(id) + logMessage = logMessage.replace("\n", "\n\t") + logMessage = logMessage[:-1] template = mypopen("p4 change -o").read() @@ -356,6 +369,15 @@ class P4Submit(Command): print "Perforce checkout for depot path %s located at %s" % (depotPath, self.clientPath) oldWorkingDirectory = os.getcwd() + + if self.directSubmit: + self.diffStatus = mypopen("git diff -r --name-status HEAD").readlines() + patch = mypopen("git diff -p --binary --diff-filter=ACMRTUXB HEAD").read() + self.diffFile = gitdir + "/p4-git-diff" + f = open(self.diffFile, "wb") + f.write(patch) + f.close(); + os.chdir(self.clientPath) response = raw_input("Do you want to sync %s with p4 sync? [y]es/[n]o " % self.clientPath) if response == "y" or response == "yes": @@ -395,14 +417,25 @@ class P4Submit(Command): self.config.close() + if self.directSubmit: + os.remove(self.diffFile) + if len(commits) == 0: if self.firstTime: print "No changes found to apply between %s and current HEAD" % self.origin else: print "All changes applied!" - response = raw_input("Do you want to sync from Perforce now using git-p4 rebase? [y]es/[n]o ") + response = "" + os.chdir(oldWorkingDirectory) + + if self.directSubmit: + response = raw_input("Do you want to DISCARD your git WORKING DIRECTORY CHANGES and sync from Perforce now using git-p4 rebase? [y]es/[n]o ") + if response == "y" or response == "yes": + system("git reset --hard") + + if len(response) == 0: + response = raw_input("Do you want to sync from Perforce now using git-p4 rebase? [y]es/[n]o ") if response == "y" or response == "yes": - os.chdir(oldWorkingDirectory) rebase = P4Rebase() rebase.run([]) os.remove(self.configFile) -- cgit v1.2.3 From 8a5fc95b43ab25e7ce0ca14cf733669e5708b448 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 20 May 2007 23:39:40 +0200 Subject: Specifying --detect-branches is now only needed for the initial clone/sync. Afterwards it's turned on implicitly if more p4 branches than remotes/p4/master are found. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 3 +++ 1 file changed, 3 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index bcea4cf3de..d4bf67333f 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -719,6 +719,9 @@ class P4Sync(Command): self.initialParents = {} self.listExistingP4GitBranches() + if len(self.p4BranchesInGit) > 1: + print "Importing from/into multiple branches" + self.detectBranches = True if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists("refs/remotes/p4/master") and not self.detectBranches: ### needs to be ported to multi branch import -- cgit v1.2.3 From 24f7b53fdd0bcc76453fc087932ca2cdecf47f9d Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 20 May 2007 23:42:22 +0200 Subject: Had an idea for debugging, record it :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d4bf67333f..92522417cd 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -7,6 +7,10 @@ # 2007 Trolltech ASA # License: MIT # +# TODO: * implement git-p4 rollback for debugging +# to roll back all p4 remote branches to a commit older or equal to +# the specified change. +# import optparse, sys, os, marshal, popen2, subprocess, shelve import tempfile, getopt, sha, os.path, time, platform -- cgit v1.2.3 From b1561ee25628c074b3afac738ead387181d3b311 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 20 May 2007 23:52:51 +0200 Subject: Another (potentially life-saving) idea for submit --direct Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 92522417cd..5055f32140 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -10,6 +10,12 @@ # TODO: * implement git-p4 rollback for debugging # to roll back all p4 remote branches to a commit older or equal to # the specified change. +# * for git-p4 submit --direct it would be nice to still create a +# git commit without updating HEAD before submitting to perforce. +# With the commit sha1 printed (or recoded in a .git/foo file?) +# it's possible to recover if anything goes wrong instead of potentially +# loosing a change entirely because it was never comitted to git and +# the p4 submit failed (or resulted in lots of conflicts, etc.) # import optparse, sys, os, marshal, popen2, subprocess, shelve -- cgit v1.2.3 From 341dc1c1793455875086373a865db4d0a132ef6e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 21 May 2007 00:39:16 +0200 Subject: Improved output for multi branch imports and noted another little todo item Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 5055f32140..beb6529b44 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -16,6 +16,8 @@ # it's possible to recover if anything goes wrong instead of potentially # loosing a change entirely because it was never comitted to git and # the p4 submit failed (or resulted in lots of conflicts, etc.) +# * Consider making --with-origin the default, assuming that the git +# protocol is always more efficient. (needs manual testing first :) # import optparse, sys, os, marshal, popen2, subprocess, shelve @@ -729,7 +731,7 @@ class P4Sync(Command): self.initialParents = {} self.listExistingP4GitBranches() - if len(self.p4BranchesInGit) > 1: + if len(self.p4BranchesInGit) > 1 and not self.silent: print "Importing from/into multiple branches" self.detectBranches = True @@ -795,7 +797,7 @@ class P4Sync(Command): self.depotPath = self.previousDepotPath self.changeRange = "@%s,#head" % p4Change self.initialParent = parseRevision(self.branch) - if not self.silent: + if not self.silent and not self.detectBranches: print "Performing incremental import into %s git branch" % self.branch if not self.branch.startswith("refs/"): @@ -920,15 +922,17 @@ class P4Sync(Command): if len(changes) == 0: if not self.silent: - print "no changes to import!" + print "No changes to import!" return True + self.updatedBranches = set() + cnt = 1 for change in changes: description = p4Cmd("describe %s" % change) if not self.silent: - sys.stdout.write("\rimporting revision %s (%s%%)" % (change, cnt * 100 / len(changes))) + sys.stdout.write("\rImporting revision %s (%s%%)" % (change, cnt * 100 / len(changes))) sys.stdout.flush() cnt = cnt + 1 @@ -945,6 +949,8 @@ class P4Sync(Command): if self.verbose: print "branch is %s" % branch + self.updatedBranches.add(branch) + if branch not in self.createdBranches: self.createdBranches.add(branch) parent = self.knownBranches[branch] @@ -984,8 +990,13 @@ class P4Sync(Command): print self.gitError.read() sys.exit(1) - if not self.silent: - print "" + if not self.silent: + print "" + if len(self.updatedBranches) > 0: + sys.stdout.write("Updated branches: ") + for b in self.updatedBranches: + sys.stdout.write("%s " % b) + sys.stdout.write("\n") self.gitStream.close() -- cgit v1.2.3 From 33be3e6550c7051c3ac4bc624c7dacfad6974b4f Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 21 May 2007 08:44:16 +0200 Subject: Fix conversion from old style heads/p4 to remotes/p4/master Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index beb6529b44..7489c91081 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -730,11 +730,6 @@ class P4Sync(Command): self.knownBranches = {} self.initialParents = {} - self.listExistingP4GitBranches() - if len(self.p4BranchesInGit) > 1 and not self.silent: - print "Importing from/into multiple branches" - self.detectBranches = True - if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists("refs/remotes/p4/master") and not self.detectBranches: ### needs to be ported to multi branch import @@ -760,6 +755,12 @@ class P4Sync(Command): if not gitBranchExists("refs/remotes/p4/HEAD"): system("git symbolic-ref refs/remotes/p4/HEAD %s" % self.branch) + # this needs to be called after the conversion from heads/p4 to remotes/p4/master + self.listExistingP4GitBranches() + if len(self.p4BranchesInGit) > 1 and not self.silent: + print "Importing from/into multiple branches" + self.detectBranches = True + if len(args) == 0: if not gitBranchExists(self.branch) and gitBranchExists("origin") and not self.detectBranches: ### needs to be ported to multi branch import -- cgit v1.2.3 From dc5240369610a6f72eab9b59447889dfd69b31c5 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 21 May 2007 09:34:56 +0200 Subject: Fix error detection with git-p4 submit when the requested depot path is not in the client view. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 ++ 1 file changed, 2 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 7489c91081..73da5d2b27 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -55,6 +55,8 @@ def p4Where(depotPath): if not depotPath.endswith("/"): depotPath += "/" output = p4Cmd("where %s..." % depotPath) + if output["code"] == "error": + return "" clientPath = "" if "path" in output: clientPath = output.get("path") -- cgit v1.2.3 From faf1bd202640263b06c99c335269971aa9d9ead1 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 21 May 2007 10:05:30 +0200 Subject: Fix git symbolic-ref warning on initial clone Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 73da5d2b27..35a513fcb8 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -732,6 +732,8 @@ class P4Sync(Command): self.knownBranches = {} self.initialParents = {} + createP4HeadRef = False; + if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists("refs/remotes/p4/master") and not self.detectBranches: ### needs to be ported to multi branch import @@ -754,8 +756,9 @@ class P4Sync(Command): if gitBranchExists("refs/heads/p4"): system("git update-ref %s refs/heads/p4" % self.branch) system("git branch -D p4"); + # create it /after/ importing, when master exists if not gitBranchExists("refs/remotes/p4/HEAD"): - system("git symbolic-ref refs/remotes/p4/HEAD %s" % self.branch) + createP4HeadRef = True # this needs to be called after the conversion from heads/p4 to remotes/p4/master self.listExistingP4GitBranches() @@ -1008,6 +1011,9 @@ class P4Sync(Command): self.gitOutput.close() self.gitError.close() + if createP4HeadRef: + system("git symbolic-ref refs/remotes/p4/HEAD %s" % self.branch) + return True class P4Rebase(Command): -- cgit v1.2.3 From cbf5efa61a30d6454f5739cee3498f98a01210da Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 21 May 2007 10:08:11 +0200 Subject: Detect with git-p4 submit --direct when there are no changes in the working directory Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 3 +++ 1 file changed, 3 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 35a513fcb8..f08ee6da44 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -386,6 +386,9 @@ class P4Submit(Command): if self.directSubmit: self.diffStatus = mypopen("git diff -r --name-status HEAD").readlines() + if len(self.diffStatus) == 0: + print "No changes in working directory to submit." + return True patch = mypopen("git diff -p --binary --diff-filter=ACMRTUXB HEAD").read() self.diffFile = gitdir + "/p4-git-diff" f = open(self.diffFile, "wb") -- cgit v1.2.3 From 7944f1425c0665eef6a5b9f5cc92e15cddb42984 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 21 May 2007 11:04:26 +0200 Subject: Make git-p4 submit --direct safer by also creating a git commit Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index f08ee6da44..b32d8dbfd3 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -10,12 +10,6 @@ # TODO: * implement git-p4 rollback for debugging # to roll back all p4 remote branches to a commit older or equal to # the specified change. -# * for git-p4 submit --direct it would be nice to still create a -# git commit without updating HEAD before submitting to perforce. -# With the commit sha1 printed (or recoded in a .git/foo file?) -# it's possible to recover if anything goes wrong instead of potentially -# loosing a change entirely because it was never comitted to git and -# the p4 submit failed (or resulted in lots of conflicts, etc.) # * Consider making --with-origin the default, assuming that the git # protocol is always more efficient. (needs manual testing first :) # @@ -328,9 +322,17 @@ class P4Submit(Command): print submitTemplate raw_input("Press return to continue...") else: - pipe = os.popen("p4 submit -i", "wb") - pipe.write(submitTemplate) - pipe.close() + if self.directSubmit: + print "Submitting to git first" + os.chdir(self.oldWorkingDirectory) + pipe = os.popen("git commit -a -F -", "wb") + pipe.write(submitTemplate) + pipe.close() + os.chdir(self.clientPath) + + pipe = os.popen("p4 submit -i", "wb") + pipe.write(submitTemplate) + pipe.close() elif response == "s": for f in editedFiles: system("p4 revert \"%s\"" % f); @@ -382,7 +384,7 @@ class P4Submit(Command): sys.exit(128) print "Perforce checkout for depot path %s located at %s" % (depotPath, self.clientPath) - oldWorkingDirectory = os.getcwd() + self.oldWorkingDirectory = os.getcwd() if self.directSubmit: self.diffStatus = mypopen("git diff -r --name-status HEAD").readlines() @@ -442,16 +444,8 @@ class P4Submit(Command): print "No changes found to apply between %s and current HEAD" % self.origin else: print "All changes applied!" - response = "" - os.chdir(oldWorkingDirectory) - - if self.directSubmit: - response = raw_input("Do you want to DISCARD your git WORKING DIRECTORY CHANGES and sync from Perforce now using git-p4 rebase? [y]es/[n]o ") - if response == "y" or response == "yes": - system("git reset --hard") - - if len(response) == 0: - response = raw_input("Do you want to sync from Perforce now using git-p4 rebase? [y]es/[n]o ") + os.chdir(self.oldWorkingDirectory) + response = raw_input("Do you want to sync from Perforce now using git-p4 rebase? [y]es/[n]o ") if response == "y" or response == "yes": rebase = P4Rebase() rebase.run([]) -- cgit v1.2.3 From 5834684d51ee6e0c21cce8d1b5df06a34a36a4f9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 21 May 2007 22:57:06 +0200 Subject: Added a rollback command for debugging. It sets back the heads of the p4 branches to the specified p4 change number or earlier. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index b32d8dbfd3..40264cdc18 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -7,10 +7,7 @@ # 2007 Trolltech ASA # License: MIT # -# TODO: * implement git-p4 rollback for debugging -# to roll back all p4 remote branches to a commit older or equal to -# the specified change. -# * Consider making --with-origin the default, assuming that the git +# TODO: * Consider making --with-origin the default, assuming that the git # protocol is always more efficient. (needs manual testing first :) # @@ -135,6 +132,35 @@ class P4Debug(Command): print output return True +class P4RollBack(Command): + def __init__(self): + Command.__init__(self) + self.options = [ + ] + self.description = "A tool to debug the multi-branch import. Don't use :)" + + def run(self, args): + if len(args) != 1: + return False + maxChange = int(args[0]) + for line in mypopen("git rev-parse --symbolic --remotes").readlines(): + if line.startswith("p4/") and line != "p4/HEAD\n": + ref = "refs/remotes/" + line[:-1] + log = extractLogMessageFromGitCommit(ref) + depotPath, change = extractDepotPathAndChangeFromGitLog(log) + changed = False + while len(change) > 0 and int(change) > maxChange: + changed = True + 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) + + if changed: + print "%s is at %s" % (ref, change) + + return True + class P4Submit(Command): def __init__(self): Command.__init__(self) @@ -1109,7 +1135,8 @@ commands = { "submit" : P4Submit(), "sync" : P4Sync(), "rebase" : P4Rebase(), - "clone" : P4Clone() + "clone" : P4Clone(), + "rollback" : P4RollBack() } if len(sys.argv[1:]) == 0: -- cgit v1.2.3 From af8da89cb7225c7938a836de0812467c059ca52d Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 21 May 2007 23:25:51 +0200 Subject: Fix branch detection in multi-branch imports Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 40264cdc18..515f7a906f 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -556,7 +556,7 @@ class P4Sync(Command): relPath = path[len(self.depotPath):] for branch in self.knownBranches.keys(): - if relPath.startswith(branch): + if relPath.startswith(branch + "/"): # add a trailing slash so that a commit into qt/4.2foo doesn't end up in qt/4.2 if branch not in branches: branches[branch] = [] branches[branch].append(file) -- cgit v1.2.3 From 52102d4784a5f16fd84eaf98b61f714460b68693 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 21 May 2007 23:44:24 +0200 Subject: Fixes for rollback, delete branches that did not exist at the specified p4 change Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 515f7a906f..1457396abd 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -136,8 +136,10 @@ class P4RollBack(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 multi-branch import. Don't use :)" + self.verbose = False def run(self, args): if len(args) != 1: @@ -149,15 +151,22 @@ class P4RollBack(Command): log = extractLogMessageFromGitCommit(ref) depotPath, change = extractDepotPathAndChangeFromGitLog(log) changed = False + + if len(p4Cmd("changes -m 1 %s...@%s" % (depotPath, maxChange))) == 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: changed = True - print "%s is at %s ; rewinding towards %s" % (ref, change, maxChange) + 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) if changed: - print "%s is at %s" % (ref, change) + print "%s rewound to %s" % (ref, change) return True -- cgit v1.2.3 From a028a98e9ae83231f0657fdb112f7d9c0cf0b98c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 May 2007 00:03:08 +0200 Subject: Added support for importing multiple branches into refs/heads instead of just refs/remotes using --import-local. Needs some further microfix but seems to work otherwise. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 1457396abd..969c1fe45b 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -498,7 +498,8 @@ class P4Sync(Command): optparse.make_option("--silent", dest="silent", action="store_true"), optparse.make_option("--detect-labels", dest="detectLabels", action="store_true"), optparse.make_option("--with-origin", dest="syncWithOrigin", action="store_true"), - optparse.make_option("--verbose", dest="verbose", action="store_true") + optparse.make_option("--verbose", dest="verbose", action="store_true"), + optparse.make_option("--import-local", dest="importIntoRemotes", action="store_false") ] self.description = """Imports from Perforce into a git repository.\n example: @@ -519,6 +520,7 @@ class P4Sync(Command): self.changesFile = "" self.syncWithOrigin = False self.verbose = False + self.importIntoRemotes = True def p4File(self, depotPath): return os.popen("p4 print -q \"%s\"" % depotPath, "rb").read() @@ -749,11 +751,17 @@ class P4Sync(Command): def listExistingP4GitBranches(self): self.p4BranchesInGit = [] - for line in mypopen("git rev-parse --symbolic --remotes").readlines(): + cmdline = "git rev-parse --symbolic " + if self.importIntoRemotes: + cmdline += " --remotes" + else: + cmdline += " --branches" + + for line in mypopen(cmdline).readlines(): if line.startswith("p4/") and line != "p4/HEAD\n": branch = line[3:-1] self.p4BranchesInGit.append(branch) - self.initialParents["refs/remotes/p4/" + branch] = parseRevision(line[:-1]) + self.initialParents[self.refPrefix + branch] = parseRevision(line[:-1]) def run(self, args): self.depotPath = "" @@ -764,9 +772,14 @@ class P4Sync(Command): self.knownBranches = {} self.initialParents = {} + if self.importIntoRemotes: + self.refPrefix = "refs/remotes/p4/" + else: + self.refPrefix = "refs/heads/p4/" + createP4HeadRef = False; - if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists("refs/remotes/p4/master") and not self.detectBranches: + if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists(self.refPrefix + "master") and not self.detectBranches: ### needs to be ported to multi branch import print "Syncing with origin first as requested by calling git fetch origin" @@ -779,17 +792,17 @@ class P4Sync(Command): p4Change = int(p4Change) if originP4Change > p4Change: print "origin (%s) is newer than p4 (%s). Updating p4 branch from origin." % (originP4Change, p4Change) - system("git update-ref refs/remotes/p4/master origin"); + system("git update-ref " + self.refPrefix + "master origin"); else: print "Cannot sync with origin. It was imported from %s while remotes/p4 was imported from %s" % (originPreviousDepotPath, p4PreviousDepotPath) if len(self.branch) == 0: - self.branch = "refs/remotes/p4/master" - if gitBranchExists("refs/heads/p4"): + self.branch = self.refPrefix + "master" + if gitBranchExists("refs/heads/p4") and self.importIntoRemotes: system("git update-ref %s refs/heads/p4" % self.branch) system("git branch -D p4"); # create it /after/ importing, when master exists - if not gitBranchExists("refs/remotes/p4/HEAD"): + if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes: createP4HeadRef = True # this needs to be called after the conversion from heads/p4 to remotes/p4/master @@ -813,7 +826,7 @@ class P4Sync(Command): p4Change = 0 for branch in self.p4BranchesInGit: - depotPath, change = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("refs/remotes/p4/" + branch)) + depotPath, change = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(self.refPrefix + branch)) if self.verbose: print "path %s change %s" % (depotPath, change) @@ -1008,9 +1021,9 @@ class P4Sync(Command): elif len(parent) > 0: parent = self.projectName + parent - branch = "refs/remotes/p4/" + branch + branch = self.refPrefix + branch if len(parent) > 0: - parent = "refs/remotes/p4/" + parent + parent = self.refPrefix + parent if self.verbose: print "looking for initial parent for %s; current parent is %s" % (branch, parent) @@ -1044,7 +1057,7 @@ class P4Sync(Command): self.gitError.close() if createP4HeadRef: - system("git symbolic-ref refs/remotes/p4/HEAD %s" % self.branch) + system("git symbolic-ref %s/HEAD %s" % (self.refPrefix, self.branch)) return True -- cgit v1.2.3 From 01a9c9c5a80c6a1e82298870ca8e5bc73b2a828d Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 May 2007 00:07:35 +0200 Subject: Added support for --max-changes= to ease import debugging Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 969c1fe45b..3d97ce1a24 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -499,7 +499,8 @@ class P4Sync(Command): optparse.make_option("--detect-labels", dest="detectLabels", action="store_true"), optparse.make_option("--with-origin", dest="syncWithOrigin", action="store_true"), optparse.make_option("--verbose", dest="verbose", action="store_true"), - optparse.make_option("--import-local", dest="importIntoRemotes", action="store_false") + optparse.make_option("--import-local", dest="importIntoRemotes", action="store_false"), + optparse.make_option("--max-changes", dest="maxChanges") ] self.description = """Imports from Perforce into a git repository.\n example: @@ -521,6 +522,7 @@ class P4Sync(Command): self.syncWithOrigin = False self.verbose = False self.importIntoRemotes = True + self.maxChanges = "" def p4File(self, depotPath): return os.popen("p4 print -q \"%s\"" % depotPath, "rb").read() @@ -971,6 +973,9 @@ class P4Sync(Command): changes.reverse() + if len(self.maxChanges) > 0: + changes = changes[0:min(int(self.maxChanges), len(changes))] + if len(changes) == 0: if not self.silent: print "No changes to import!" -- cgit v1.2.3 From 57284050a8123a4c2d22d435a8c6daf1b53011e8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 May 2007 00:15:50 +0200 Subject: Use refs/heads/* instead of refs/heads/p4/* for local imports Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3d97ce1a24..152c3c1ca5 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -760,10 +760,15 @@ class P4Sync(Command): cmdline += " --branches" for line in mypopen(cmdline).readlines(): - if line.startswith("p4/") and line != "p4/HEAD\n": + if self.importIntoRemotes and ((not line.startswith("p4/")) or line == "p4/HEAD\n"): + continue + if self.importIntoRemotes: + # strip off p4 branch = line[3:-1] - self.p4BranchesInGit.append(branch) - self.initialParents[self.refPrefix + branch] = parseRevision(line[:-1]) + else: + branch = line[:-1] + self.p4BranchesInGit.append(branch) + self.initialParents[self.refPrefix + branch] = parseRevision(line[:-1]) def run(self, args): self.depotPath = "" @@ -777,11 +782,11 @@ class P4Sync(Command): if self.importIntoRemotes: self.refPrefix = "refs/remotes/p4/" else: - self.refPrefix = "refs/heads/p4/" + self.refPrefix = "refs/heads/" createP4HeadRef = False; - if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists(self.refPrefix + "master") and not self.detectBranches: + if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists(self.refPrefix + "master") and not self.detectBranches and self.importIntoRemotes: ### needs to be ported to multi branch import print "Syncing with origin first as requested by calling git fetch origin" -- cgit v1.2.3 From 65d2ade95e6ef5a15a30d5115073477dfe03fb85 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 May 2007 16:41:46 +0200 Subject: Avoid calling git symbolic-ref refs/heads/p4//HEAD (double slash) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 152c3c1ca5..5cea6cf9ac 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1067,7 +1067,7 @@ class P4Sync(Command): self.gitError.close() if createP4HeadRef: - system("git symbolic-ref %s/HEAD %s" % (self.refPrefix, self.branch)) + system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch)) return True -- cgit v1.2.3 From 0c66a783936d5cd7b1f28400c6b192c37690304a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 May 2007 20:07:57 +0200 Subject: Make rollback work with locally imported branches Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 5cea6cf9ac..f12ad8baff 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -136,18 +136,28 @@ class P4RollBack(Command): def __init__(self): Command.__init__(self) self.options = [ - optparse.make_option("--verbose", dest="verbose", action="store_true") + optparse.make_option("--verbose", dest="verbose", action="store_true"), + optparse.make_option("--local", dest="rollbackLocalBranches", action="store_true") ] self.description = "A tool to debug the multi-branch import. Don't use :)" self.verbose = False + self.rollbackLocalBranches = False def run(self, args): if len(args) != 1: return False maxChange = int(args[0]) - for line in mypopen("git rev-parse --symbolic --remotes").readlines(): - if line.startswith("p4/") and line != "p4/HEAD\n": - ref = "refs/remotes/" + line[:-1] + + if self.rollbackLocalBranches: + refPrefix = "refs/heads/" + lines = mypopen("git rev-parse --symbolic --branches").readlines() + else: + refPrefix = "refs/remotes/" + lines = mypopen("git rev-parse --symbolic --remotes").readlines() + + for line in lines: + if self.rollbackLocalBranches or (line.startswith("p4/") and line != "p4/HEAD\n"): + ref = refPrefix + line[:-1] log = extractLogMessageFromGitCommit(ref) depotPath, change = extractDepotPathAndChangeFromGitLog(log) changed = False -- cgit v1.2.3 From a6d5da36af9a7087cf14e717b72c66ef2c34eb3b Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 May 2007 23:27:31 +0200 Subject: Don't make len(p4Cmd("p4 changes -m 1 //foo/...")) == 0 succeed when the p4 command itself failed. When the p4 command failed write out the exit code in the returned dict. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index f12ad8baff..89a85ebb19 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -31,7 +31,9 @@ def p4CmdList(cmd): result.append(entry) except EOFError: pass - pipe.close() + exitCode = pipe.close() + if exitCode != None: + result["p4ExitCode"] = exitCode return result -- cgit v1.2.3 From ac3e0d79eef4535bb61d79315688fb1d225dea3b Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 May 2007 23:32:32 +0200 Subject: Oops, fill the /list/ correct with the p4 exit code. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 89a85ebb19..6ae3bc6e5d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -33,7 +33,9 @@ def p4CmdList(cmd): pass exitCode = pipe.close() if exitCode != None: - result["p4ExitCode"] = exitCode + entry = {} + entry["p4ExitCode"] = exitCode + result.append(entry) return result -- cgit v1.2.3 From 66a2f523958129e9b697d30ed44a5174010cb42a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 May 2007 23:40:48 +0200 Subject: Catch p4 errors in rollback early enough (before deleting refs!) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 3 +++ 1 file changed, 3 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6ae3bc6e5d..6d016b83d4 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -152,6 +152,9 @@ class P4RollBack(Command): return False maxChange = int(args[0]) + if "p4ExitCode" in p4Cmd("p4 changes -m 1"): + die("Problems executing p4"); + if self.rollbackLocalBranches: refPrefix = "refs/heads/" lines = mypopen("git rev-parse --symbolic --branches").readlines() -- cgit v1.2.3 From ad192f2888816454df14b8a35945fb418bcb9e13 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 May 2007 23:44:19 +0200 Subject: Fix p4 execution in git-p4 rollback. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6d016b83d4..b2341b7ec4 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -152,7 +152,7 @@ class P4RollBack(Command): return False maxChange = int(args[0]) - if "p4ExitCode" in p4Cmd("p4 changes -m 1"): + if "p4ExitCode" in p4Cmd("changes -m 1"): die("Problems executing p4"); if self.rollbackLocalBranches: -- cgit v1.2.3 From b3fd1b28083cded86fd141c812cfd6d215ef4d5b Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 May 2007 23:53:14 +0200 Subject: Fix multi-branch import with --silent. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index b2341b7ec4..d8b7080b4b 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -831,8 +831,9 @@ class P4Sync(Command): # this needs to be called after the conversion from heads/p4 to remotes/p4/master self.listExistingP4GitBranches() - if len(self.p4BranchesInGit) > 1 and not self.silent: - print "Importing from/into multiple branches" + if len(self.p4BranchesInGit) > 1: + if not self.silent: + print "Importing from/into multiple branches" self.detectBranches = True if len(args) == 0: -- cgit v1.2.3 From ebd8116870247fbc9fb27656d28f1b8a43aae766 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 24 May 2007 00:24:52 +0200 Subject: Load the user map from p4 only once at run-time. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d8b7080b4b..9e9d623a3c 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -697,6 +697,8 @@ class P4Sync(Command): print "Tag %s does not match with change %s: file count is different." % (labelDetails["label"], change) def getUserMapFromPerforceServer(self): + if self.userMapFromPerforceServer: + return self.users = {} for output in p4CmdList("users"): @@ -708,9 +710,11 @@ class P4Sync(Command): for user in self.users.keys(): cache.write("%s\t%s\n" % (user, self.users[user])) cache.close(); + self.userMapFromPerforceServer = True def loadUserMapFromCache(self): self.users = {} + self.userMapFromPerforceServer = False try: cache = open(gitdir + "/p4-usercache.txt", "rb") lines = cache.readlines() -- cgit v1.2.3 From c1f9197f372a5378c3dbb36adeedf37ae175ecf1 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Thu, 24 May 2007 14:07:55 +0200 Subject: Replace \r\n with \n when importing from p4 on Windows Signed-off-by: Marius Storm-Olsen --- contrib/fast-import/git-p4 | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 9e9d623a3c..09b3cb5573 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -540,6 +540,7 @@ class P4Sync(Command): self.verbose = False self.importIntoRemotes = True self.maxChanges = "" + self.isWindows = (platform.system() == "Windows") def p4File(self, depotPath): return os.popen("p4 print -q \"%s\"" % depotPath, "rb").read() @@ -647,6 +648,9 @@ class P4Sync(Command): data = self.p4File(depotPath) + if self.isWindows and file["type"].endswith("text"): + data = data.replace("\r\n", "\n") + self.gitStream.write("M %s inline %s\n" % (mode, relPath)) self.gitStream.write("data %s\n" % len(data)) self.gitStream.write(data) -- cgit v1.2.3 From d1874ed33bc346dca8b86891757703c908634aad Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 24 May 2007 21:23:04 +0200 Subject: Fix creating the remotes/p4 branches based on origin/* for the multi-branch import Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 09b3cb5573..b587e79b48 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -795,6 +795,20 @@ class P4Sync(Command): self.p4BranchesInGit.append(branch) self.initialParents[self.refPrefix + branch] = parseRevision(line[:-1]) + def createBranchesFromOrigin(self): + if not self.silent: + print "Creating branch(es) in %s based on origin branch(es)" % self.refPrefix + + for line in mypopen("git rev-parse --symbolic --remotes"): + if (not line.startswith("origin/")) or line.endswith("HEAD\n"): + continue + headName = line[len("origin/"):-1] + remoteHead = self.refPrefix + headName + if not os.path.exists(gitdir + "/" + remoteHead): + if self.verbose: + print "creating %s" % remoteHead + system("git update-ref %s origin/%s" % (remoteHead, headName)) + def run(self, args): self.depotPath = "" self.changeRange = "" @@ -841,18 +855,14 @@ class P4Sync(Command): self.listExistingP4GitBranches() if len(self.p4BranchesInGit) > 1: if not self.silent: - print "Importing from/into multiple branches" + print "Importing from/into multiple branches" self.detectBranches = True if len(args) == 0: - if not gitBranchExists(self.branch) and gitBranchExists("origin") and not self.detectBranches: - ### needs to be ported to multi branch import - if not self.silent: - print "Creating %s branch in git repository based on origin" % self.branch - branch = self.branch - if not branch.startswith("refs"): - branch = "refs/heads/" + branch - system("git update-ref %s origin" % branch) + if len(self.p4BranchesInGit) == 0: + self.createBranchesFromOrigin() + self.listExistingP4GitBranches() + return True if self.verbose: print "branches: %s" % self.p4BranchesInGit -- cgit v1.2.3 From 2cc58fd99ae5bc5845792393f232853da1ff6082 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 24 May 2007 22:10:40 +0200 Subject: Forgot to remove this return statement from debugging Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 1 - 1 file changed, 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index b587e79b48..bfd950d53d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -862,7 +862,6 @@ class P4Sync(Command): if len(self.p4BranchesInGit) == 0: self.createBranchesFromOrigin() self.listExistingP4GitBranches() - return True if self.verbose: print "branches: %s" % self.p4BranchesInGit -- cgit v1.2.3 From abcd790fe9bc168041dcc2a0e678d22a135d33c8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 24 May 2007 22:25:36 +0200 Subject: Added support for --with-origin with multi-branch imports Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 58 ++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 30 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index bfd950d53d..0597daa849 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -795,19 +795,37 @@ class P4Sync(Command): self.p4BranchesInGit.append(branch) self.initialParents[self.refPrefix + branch] = parseRevision(line[:-1]) - def createBranchesFromOrigin(self): + def createOrUpdateBranchesFromOrigin(self): if not self.silent: - print "Creating branch(es) in %s based on origin branch(es)" % self.refPrefix + print "Creating/updating branch(es) in %s based on origin branch(es)" % self.refPrefix for line in mypopen("git rev-parse --symbolic --remotes"): if (not line.startswith("origin/")) or line.endswith("HEAD\n"): continue headName = line[len("origin/"):-1] remoteHead = self.refPrefix + headName + originHead = "origin/" + headName + + update = False if not os.path.exists(gitdir + "/" + remoteHead): if self.verbose: print "creating %s" % remoteHead - system("git update-ref %s origin/%s" % (remoteHead, headName)) + update = True + else: + [originPreviousDepotPath, originP4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(originHead)) + [p4PreviousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(remoteHead)) + if len(originPreviousDepotPath) > 0 and len(originP4Change) > 0 and len(p4Change) > 0: + if originPreviousDepotPath == p4PreviousDepotPath: + originP4Change = int(originP4Change) + p4Change = int(p4Change) + if originP4Change > 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) + + if update: + system("git update-ref %s %s" % (remoteHead, originHead)) def run(self, args): self.depotPath = "" @@ -825,23 +843,6 @@ class P4Sync(Command): createP4HeadRef = False; - if self.syncWithOrigin and gitBranchExists("origin") and gitBranchExists(self.refPrefix + "master") and not self.detectBranches and self.importIntoRemotes: - ### needs to be ported to multi branch import - - print "Syncing with origin first as requested by calling git fetch origin" - system("git fetch origin") - [originPreviousDepotPath, originP4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("origin")) - [p4PreviousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("p4")) - if len(originPreviousDepotPath) > 0 and len(originP4Change) > 0 and len(p4Change) > 0: - if originPreviousDepotPath == p4PreviousDepotPath: - originP4Change = int(originP4Change) - p4Change = int(p4Change) - if originP4Change > p4Change: - print "origin (%s) is newer than p4 (%s). Updating p4 branch from origin." % (originP4Change, p4Change) - system("git update-ref " + self.refPrefix + "master origin"); - else: - print "Cannot sync with origin. It was imported from %s while remotes/p4 was imported from %s" % (originPreviousDepotPath, p4PreviousDepotPath) - if len(self.branch) == 0: self.branch = self.refPrefix + "master" if gitBranchExists("refs/heads/p4") and self.importIntoRemotes: @@ -851,17 +852,14 @@ class P4Sync(Command): if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes: createP4HeadRef = True - # this needs to be called after the conversion from heads/p4 to remotes/p4/master - self.listExistingP4GitBranches() - if len(self.p4BranchesInGit) > 1: - if not self.silent: - print "Importing from/into multiple branches" - self.detectBranches = True - if len(args) == 0: - if len(self.p4BranchesInGit) == 0: - self.createBranchesFromOrigin() - self.listExistingP4GitBranches() + self.createOrUpdateBranchesFromOrigin() + self.listExistingP4GitBranches() + + if len(self.p4BranchesInGit) > 1: + if not self.silent: + print "Importing from/into multiple branches" + self.detectBranches = True if self.verbose: print "branches: %s" % self.p4BranchesInGit -- cgit v1.2.3 From 10f880f8d4e2c6390928a0bcc8b43161b5f845b2 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 24 May 2007 22:28:28 +0200 Subject: Oops, fix --with-origin to /really/ also call git fetch :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 0597daa849..08af23f9fd 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -841,6 +841,10 @@ class P4Sync(Command): else: self.refPrefix = "refs/heads/" + if self.syncWithOrigin: + print "Syncing with origin first as requested by calling git fetch origin" + system("git fetch origin") + createP4HeadRef = False; if len(self.branch) == 0: -- cgit v1.2.3 From 65c5f3e3f2dfb470c16628032235222a492e3239 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 25 May 2007 08:44:41 +0200 Subject: Avoid creating non-p4 branches in remotes/p4 off of remotes/origin Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 08af23f9fd..1cce38a6f7 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -802,19 +802,23 @@ class P4Sync(Command): for line in mypopen("git rev-parse --symbolic --remotes"): if (not line.startswith("origin/")) or line.endswith("HEAD\n"): continue + headName = line[len("origin/"):-1] remoteHead = self.refPrefix + headName originHead = "origin/" + headName + [originPreviousDepotPath, originP4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(originHead)) + if len(originPreviousDepotPath) == 0 or len(originP4Change) == 0: + continue + update = False if not os.path.exists(gitdir + "/" + remoteHead): if self.verbose: print "creating %s" % remoteHead update = True else: - [originPreviousDepotPath, originP4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(originHead)) [p4PreviousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(remoteHead)) - if len(originPreviousDepotPath) > 0 and len(originP4Change) > 0 and len(p4Change) > 0: + if len(p4Change) > 0: if originPreviousDepotPath == p4PreviousDepotPath: originP4Change = int(originP4Change) p4Change = int(p4Change) -- cgit v1.2.3 From 4280e5333354c6dddcd994bdacd3c6a11ac2da5e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 25 May 2007 08:49:18 +0200 Subject: Make git-p4 work with packed refs (don't use os.path.exists to check for the existance of a ref) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 1cce38a6f7..e8a5c1fa31 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -412,7 +412,7 @@ class P4Submit(Command): if len(args) == 0: self.master = currentGitBranch() - if len(self.master) == 0 or not os.path.exists("%s/refs/heads/%s" % (gitdir, self.master)): + if len(self.master) == 0 or not gitBranchExists("refs/heads/%s" % self.master): die("Detecting current git branch failed!") elif len(args) == 1: self.master = args[0] @@ -812,7 +812,7 @@ class P4Sync(Command): continue update = False - if not os.path.exists(gitdir + "/" + remoteHead): + if not gitBranchExists(remoteHead): if self.verbose: print "creating %s" % remoteHead update = True -- cgit v1.2.3 From 417a7a6fc8c3d77e3e9a3bb0e11cb2eea978e20b Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 25 May 2007 10:28:46 +0200 Subject: Make --with-origin also work without origin :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e8a5c1fa31..30ee68c609 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -846,8 +846,9 @@ class P4Sync(Command): self.refPrefix = "refs/heads/" if self.syncWithOrigin: - print "Syncing with origin first as requested by calling git fetch origin" - system("git fetch origin") + if gitBranchExists("origin"): + print "Syncing with origin first as requested by calling git fetch origin" + system("git fetch origin") createP4HeadRef = False; -- cgit v1.2.3 From 01265103fe3966abd720ebb0bba1882a5701f327 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 25 May 2007 10:36:10 +0200 Subject: Make --with-origin the default for syncing. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 30ee68c609..ed5a5c593c 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -118,6 +118,9 @@ def gitBranchExists(branch): proc = subprocess.Popen(["git", "rev-parse", branch], stderr=subprocess.PIPE, stdout=subprocess.PIPE); return proc.wait() == 0; +def gitConfig(key): + return mypopen("git config %s" % key).read()[:-1] + class Command: def __init__(self): self.usage = "usage: %prog [options]" @@ -514,7 +517,6 @@ class P4Sync(Command): optparse.make_option("--changesfile", dest="changesFile"), optparse.make_option("--silent", dest="silent", action="store_true"), optparse.make_option("--detect-labels", dest="detectLabels", action="store_true"), - optparse.make_option("--with-origin", dest="syncWithOrigin", action="store_true"), 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") @@ -536,12 +538,15 @@ class P4Sync(Command): self.detectBranches = False self.detectLabels = False self.changesFile = "" - self.syncWithOrigin = False + self.syncWithOrigin = True self.verbose = False self.importIntoRemotes = True self.maxChanges = "" self.isWindows = (platform.system() == "Windows") + if gitConfig("git-p4.syncFromOrigin") == "false": + self.syncWithOrigin = False + def p4File(self, depotPath): return os.popen("p4 print -q \"%s\"" % depotPath, "rb").read() @@ -847,7 +852,8 @@ class P4Sync(Command): if self.syncWithOrigin: if gitBranchExists("origin"): - print "Syncing with origin first as requested by calling git fetch origin" + if not self.silent: + print "Syncing with origin first by calling git fetch origin" system("git fetch origin") createP4HeadRef = False; @@ -1116,13 +1122,11 @@ class P4Sync(Command): class P4Rebase(Command): def __init__(self): Command.__init__(self) - self.options = [ optparse.make_option("--with-origin", dest="syncWithOrigin", action="store_true") ] + self.options = [ ] self.description = "Fetches the latest revision from perforce and rebases the current work (branch) against it" - self.syncWithOrigin = False def run(self, args): sync = P4Sync() - sync.syncWithOrigin = self.syncWithOrigin sync.run([]) print "Rebasing the current branch" oldHead = mypopen("git rev-parse HEAD").read()[:-1] -- cgit v1.2.3 From d414c74afd8610c8c22dadf62b5ba8c6efa59e75 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 25 May 2007 11:36:42 +0200 Subject: Shortcut the case where we have no origin branch Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index ed5a5c593c..d99237c632 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -844,6 +844,7 @@ class P4Sync(Command): # map from branch depot path to parent branch self.knownBranches = {} self.initialParents = {} + self.hasOrigin = gitBranchExists("origin") if self.importIntoRemotes: self.refPrefix = "refs/remotes/p4/" @@ -851,7 +852,7 @@ class P4Sync(Command): self.refPrefix = "refs/heads/" if self.syncWithOrigin: - if gitBranchExists("origin"): + if self.hasOrigin: if not self.silent: print "Syncing with origin first by calling git fetch origin" system("git fetch origin") @@ -868,7 +869,8 @@ class P4Sync(Command): createP4HeadRef = True if len(args) == 0: - self.createOrUpdateBranchesFromOrigin() + if self.hasOrigin: + self.createOrUpdateBranchesFromOrigin() self.listExistingP4GitBranches() if len(self.p4BranchesInGit) > 1: -- cgit v1.2.3 From 877db584aae9816671147da45c30c31748ef287f Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 25 May 2007 19:43:38 +0200 Subject: Forgot to remove this TODO item when I made --with-origin the default :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 3 --- 1 file changed, 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d99237c632..0946965043 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -7,9 +7,6 @@ # 2007 Trolltech ASA # License: MIT # -# TODO: * Consider making --with-origin the default, assuming that the git -# protocol is always more efficient. (needs manual testing first :) -# import optparse, sys, os, marshal, popen2, subprocess, shelve import tempfile, getopt, sha, os.path, time, platform -- cgit v1.2.3 From cb4f1280dd5691890abea4521bff0a3d6e3facfd Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 25 May 2007 22:34:30 +0200 Subject: Added git-p4 submit --trust-me-like-a-fool for the adventurous users :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 0946965043..dbd5b3bcf1 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -195,9 +195,9 @@ class P4Submit(Command): optparse.make_option("--origin", dest="origin"), optparse.make_option("--reset", action="store_true", dest="reset"), optparse.make_option("--log-substitutions", dest="substFile"), - optparse.make_option("--noninteractive", action="store_false"), optparse.make_option("--dry-run", action="store_true"), optparse.make_option("--direct", dest="directSubmit", action="store_true"), + optparse.make_option("--trust-me-like-a-fool", dest="trustMeLikeAFool", action="store_true"), ] self.description = "Submit changes from git to the perforce depot." self.usage += " [name of git branch to submit into perforce depot]" @@ -209,6 +209,7 @@ class P4Submit(Command): self.firstTime = True self.origin = "" self.directSubmit = False + self.trustMeLikeAFool = False self.logSubstitutions = {} self.logSubstitutions[""] = "%log%" @@ -348,6 +349,9 @@ class P4Submit(Command): separatorLine += "\n" response = "e" + if self.trustMeLikeAFool: + response = "y" + firstIteration = True while response == "e": if not firstIteration: -- cgit v1.2.3 From a3c55c09ecae2a9c852c8c10e668c901639e845b Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 27 May 2007 15:48:01 +0200 Subject: Fix creation of refs/remotes/p4/HEAD symbolic ref Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index dbd5b3bcf1..aeefadcd66 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -858,8 +858,6 @@ class P4Sync(Command): print "Syncing with origin first by calling git fetch origin" system("git fetch origin") - createP4HeadRef = False; - if len(self.branch) == 0: self.branch = self.refPrefix + "master" if gitBranchExists("refs/heads/p4") and self.importIntoRemotes: @@ -867,7 +865,7 @@ class P4Sync(Command): system("git branch -D p4"); # create it /after/ importing, when master exists if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes: - createP4HeadRef = True + system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch)) if len(args) == 0: if self.hasOrigin: @@ -1117,9 +1115,6 @@ class P4Sync(Command): self.gitOutput.close() self.gitError.close() - if createP4HeadRef: - system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch)) - return True class P4Rebase(Command): -- cgit v1.2.3 From ce6f33c83537a04a3fb7557d7a74fe81ebccd7e4 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 16:46:29 -0300 Subject: Cleanups - don't use dir (python builtin) - use re for munging depotPath into destination Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index aeefadcd66..910e4ff3cd 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -10,6 +10,7 @@ import optparse, sys, os, marshal, popen2, subprocess, shelve import tempfile, getopt, sha, os.path, time, platform +import re from sets import Set; gitdir = os.environ.get("GIT_DIR", "") @@ -842,6 +843,7 @@ class P4Sync(Command): self.changeRange = "" self.initialParent = "" self.previousDepotPath = "" + # map from branch depot path to parent branch self.knownBranches = {} self.initialParents = {} @@ -1145,37 +1147,26 @@ class P4Clone(P4Sync): if len(args) < 1: return False depotPath = args[0] - dir = "" + destination = "" if len(args) == 2: - dir = args[1] + destination = args[1] elif len(args) > 2: return False if not depotPath.startswith("//"): return False - if len(dir) == 0: - dir = depotPath - atPos = dir.rfind("@") - if atPos != -1: - dir = dir[0:atPos] - hashPos = dir.rfind("#") - if hashPos != -1: - dir = dir[0:hashPos] - - if dir.endswith("..."): - dir = dir[:-3] - - if dir.endswith("/"): - dir = dir[:-1] + depotDir = re.sub("(@[^@]*)$", "", depotPath) + depotDir = re.sub("(#[^#]*)$", "", depotDir) + depotDir = re.sub(r"\.\.\.$,", "", depotDir) + depotDir = re.sub(r"/$", "", depotDir) - slashPos = dir.rfind("/") - if slashPos != -1: - dir = dir[slashPos + 1:] + if not destination: + destination = os.path.split(depotDir)[-1] - print "Importing from %s into %s" % (depotPath, dir) - os.makedirs(dir) - os.chdir(dir) + print "Importing from %s into %s" % (depotPath, destination) + os.makedirs(destination) + os.chdir(destination) system("git init") gitdir = os.getcwd() + "/.git" if not P4Sync.run(self, [depotPath]): -- cgit v1.2.3 From cebdf5af319ce638862fe2e2cd2797840962ddbb Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 16:53:11 -0300 Subject: reformatting: break long lines. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 48 +++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 910e4ff3cd..aba4752d4e 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -222,7 +222,9 @@ class P4Submit(Command): def start(self): if len(self.config) > 0 and not self.reset: - die("Cannot start sync. Previous sync config found at %s\nIf you want to start submitting again from scratch maybe you want to call git-p4 submit --reset" % self.configFile) + die("Cannot start sync. Previous sync config found at %s\n" + "If you want to start submitting again from scratch " + "maybe you want to call git-p4 submit --reset" % self.configFile) commits = [] if self.directSubmit: @@ -297,7 +299,8 @@ class P4Submit(Command): print "What do you want to do?" response = "x" while response != "s" and response != "a" and response != "w": - response = raw_input("[s]kip this patch / [a]pply the patch forcibly and with .rej files / [w]rite the patch to a file (patch.txt) ") + response = raw_input("[s]kip this patch / [a]pply the patch forcibly " + "and with .rej files / [w]rite the patch to a file (patch.txt) ") if response == "s": print "Skipping! Good luck with the next patches..." return @@ -309,11 +312,13 @@ class P4Submit(Command): if len(filesToDelete): print "The following files should be scheduled for deletion with p4 delete:" print " ".join(filesToDelete) - die("Please resolve and submit the conflict manually and continue afterwards with git-p4 submit --continue") + die("Please resolve and submit the conflict manually and " + + "continue afterwards with git-p4 submit --continue") elif response == "w": system(diffcmd + " > patch.txt") print "Patch saved to patch.txt in %s !" % self.clientPath - die("Please resolve and submit the conflict manually and continue afterwards with git-p4 submit --continue") + die("Please resolve and submit the conflict manually and " + "continue afterwards with git-p4 submit --continue") system(applyPatchCmd) @@ -407,7 +412,9 @@ class P4Submit(Command): file = open(fileName, "w+") file.write(self.prepareLogMessage(template, logMessage)) file.close() - print "Perforce submit template written as %s. Please review/edit and then use p4 submit -i < %s to submit directly!" % (fileName, fileName) + print ("Perforce submit template written as %s. " + + "Please review/edit and then use p4 submit -i < %s to submit directly!" + % (fileName, fileName)) def run(self, args): global gitdir @@ -634,7 +641,6 @@ class P4Sync(Command): for file in files: path = file["path"] if not path.startswith(branchPrefix): - # if not silent: # print "\nchanged files: ignoring path %s outside of branch prefix %s in change %s" % (path, branchPrefix, details["change"]) continue rev = file["rev"] @@ -701,11 +707,13 @@ class P4Sync(Command): else: if not self.silent: - print "Tag %s does not match with change %s: files do not match." % (labelDetails["label"], change) + print ("Tag %s does not match with change %s: files do not match." + % (labelDetails["label"], change)) else: if not self.silent: - print "Tag %s does not match with change %s: file count is different." % (labelDetails["label"], change) + print ("Tag %s does not match with change %s: file count is different." + % (labelDetails["label"], change)) def getUserMapFromPerforceServer(self): if self.userMapFromPerforceServer: @@ -854,11 +862,10 @@ class P4Sync(Command): else: self.refPrefix = "refs/heads/" - if self.syncWithOrigin: - if self.hasOrigin: - if not self.silent: - print "Syncing with origin first by calling git fetch origin" - system("git fetch origin") + if self.syncWithOrigin and self.hasOrigin: + if not self.silent: + print "Syncing with origin first by calling git fetch origin" + system("git fetch origin") if len(self.branch) == 0: self.branch = self.refPrefix + "master" @@ -884,7 +891,8 @@ class P4Sync(Command): p4Change = 0 for branch in self.p4BranchesInGit: - depotPath, change = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(self.refPrefix + branch)) + logMsg = extractLogMessageFromGitCommit(self.refPrefix + branch) + (depotPath, change) = extractDepotPathAndChangeFromGitLog(logMsg) if self.verbose: print "path %s change %s" % (depotPath, change) @@ -922,7 +930,8 @@ class P4Sync(Command): return False else: if len(self.depotPath) != 0 and self.depotPath != args[0]: - print "previous import used depot path %s and now %s was specified. this doesn't work!" % (self.depotPath, args[0]) + print ("previous import used depot path %s and now %s was specified. " + "This doesn't work!" % (self.depotPath, args[0])) sys.exit(1) self.depotPath = args[0] @@ -968,7 +977,8 @@ class P4Sync(Command): 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); + importProcess = subprocess.Popen(["git", "fast-import"], + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE); self.gitOutput = importProcess.stdout self.gitStream = importProcess.stdin self.gitError = importProcess.stderr @@ -977,7 +987,8 @@ class P4Sync(Command): print "Doing initial import of %s from revision %s" % (self.depotPath, 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) + details["desc"] = ("Initial import of %s from the state at revision %s" + % (self.depotPath, self.revision)) details["change"] = self.revision newestRevision = 0 @@ -1123,7 +1134,8 @@ class P4Rebase(Command): def __init__(self): Command.__init__(self) self.options = [ ] - self.description = "Fetches the latest revision from perforce and rebases the current work (branch) against it" + self.description = ("Fetches the latest revision from perforce and " + + "rebases the current work (branch) against it") def run(self, args): sync = P4Sync() -- cgit v1.2.3 From 7cb5cbefd2c8b4c24bc87c6e30906907f94726ad Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 16:55:48 -0300 Subject: rename apply() to applyCommit(); apply is a python builtin Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index aba4752d4e..bd0ea54929 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -259,7 +259,7 @@ class P4Submit(Command): return result - def apply(self, id): + def applyCommit(self, id): if self.directSubmit: print "Applying local change in working directory/index" diff = self.diffStatus @@ -494,7 +494,7 @@ class P4Submit(Command): commit = commits[0] commits = commits[1:] self.config["commits"] = commits - self.apply(commit) + self.applyCommit(commit) if not self.interactive: break -- cgit v1.2.3 From c8cbbee980ac3961d5cdae164f2cb0a6b88075e0 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 28 May 2007 14:43:25 +0200 Subject: Fix my email address, this isn't really KDE related :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index bd0ea54929..400edce459 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -2,8 +2,8 @@ # # git-p4.py -- A tool for bidirectional operation between a Perforce depot and git. # -# Author: Simon Hausmann -# Copyright: 2007 Simon Hausmann +# Author: Simon Hausmann +# Copyright: 2007 Simon Hausmann # 2007 Trolltech ASA # License: MIT # -- cgit v1.2.3 From b016d39756f7d82e51c35e281673ed30b95cc586 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 17:10:46 -0300 Subject: Robustness fixes for pipes - add read_pipe(), read_pipe_lines(), write_pipe(), which check pipe.close() - use throughout Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 85 +++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 27 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 400edce459..05b308f5be 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -14,9 +14,43 @@ import re from sets import Set; gitdir = os.environ.get("GIT_DIR", "") +silent = False -def mypopen(command): - return os.popen(command, "rb"); +def write_pipe (c, str): + if not silent: + sys.stderr.write ('writing pipe: %s\n' % c) + + ## todo: check return status + pipe = os.popen (c, 'w') + val = pipe.write(str) + if pipe.close (): + sys.stderr.write ('Command failed') + sys.exit (1) + + return val + +def read_pipe (c): + sys.stderr.write ('reading pipe: %s\n' % c) + ## todo: check return status + pipe = os.popen (c, 'rb') + val = pipe.read() + if pipe.close (): + sys.stderr.write ('Command failed') + sys.exit (1) + + return val + + +def read_pipe_lines (c): + 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 failed') + sys.exit (1) + + return val def p4CmdList(cmd): cmd = "p4 -G %s" % cmd @@ -67,7 +101,7 @@ def die(msg): sys.exit(1) def currentGitBranch(): - return mypopen("git name-rev HEAD").read().split(" ")[1][:-1] + return read_pipe("git name-rev HEAD").split(" ")[1][:-1] def isValidGitDir(path): if os.path.exists(path + "/HEAD") and os.path.exists(path + "/refs") and os.path.exists(path + "/objects"): @@ -75,7 +109,7 @@ def isValidGitDir(path): return False def parseRevision(ref): - return mypopen("git rev-parse %s" % ref).read()[:-1] + return read_pipe("git rev-parse %s" % ref)[:-1] def system(cmd): if os.system(cmd) != 0: @@ -83,8 +117,10 @@ def system(cmd): def extractLogMessageFromGitCommit(commit): logMessage = "" + + ## fixme: title is first line of commit, not 1st paragraph. foundTitle = False - for log in mypopen("git cat-file commit %s" % commit).readlines(): + for log in read_pipe_lines("git cat-file commit %s" % commit): if not foundTitle: if len(log) == 1: foundTitle = True @@ -158,10 +194,10 @@ class P4RollBack(Command): if self.rollbackLocalBranches: refPrefix = "refs/heads/" - lines = mypopen("git rev-parse --symbolic --branches").readlines() + lines = read_pipe_lines("git rev-parse --symbolic --branches") else: refPrefix = "refs/remotes/" - lines = mypopen("git rev-parse --symbolic --remotes").readlines() + lines = read_pipe_lines("git rev-parse --symbolic --remotes") for line in lines: if self.rollbackLocalBranches or (line.startswith("p4/") and line != "p4/HEAD\n"): @@ -230,7 +266,7 @@ class P4Submit(Command): if self.directSubmit: commits.append("0") else: - for line in mypopen("git rev-list --no-merges %s..%s" % (self.origin, self.master)).readlines(): + for line in read_pipe_lines("git rev-list --no-merges %s..%s" % (self.origin, self.master)): commits.append(line[:-1]) commits.reverse() @@ -264,8 +300,8 @@ class P4Submit(Command): print "Applying local change in working directory/index" diff = self.diffStatus else: - print "Applying %s" % (mypopen("git log --max-count=1 --pretty=oneline %s" % id).read()) - diff = mypopen("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)).readlines() + print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id)) + diff = read_pipe_lines("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)) filesToAdd = set() filesToDelete = set() editedFiles = set() @@ -334,11 +370,11 @@ class P4Submit(Command): logMessage = logMessage.replace("\n", "\n\t") logMessage = logMessage[:-1] - template = mypopen("p4 change -o").read() + template = read_pipe("p4 change -o") if self.interactive: submitTemplate = self.prepareLogMessage(template, logMessage) - diff = mypopen("p4 diff -du ...").read() + diff = read_pipe("p4 diff -du ...") for newFile in filesToAdd: diff += "==== new file ====\n" @@ -387,14 +423,10 @@ class P4Submit(Command): if self.directSubmit: print "Submitting to git first" os.chdir(self.oldWorkingDirectory) - pipe = os.popen("git commit -a -F -", "wb") - pipe.write(submitTemplate) - pipe.close() + write_pipe("git commit -a -F -", submitTemplate) os.chdir(self.clientPath) - pipe = os.popen("p4 submit -i", "wb") - pipe.write(submitTemplate) - pipe.close() + write_pipe("p4 submit -i", submitTemplate) elif response == "s": for f in editedFiles: system("p4 revert \"%s\"" % f); @@ -451,11 +483,11 @@ class P4Submit(Command): self.oldWorkingDirectory = os.getcwd() if self.directSubmit: - self.diffStatus = mypopen("git diff -r --name-status HEAD").readlines() + self.diffStatus = read_pipe_lines("git diff -r --name-status HEAD") if len(self.diffStatus) == 0: print "No changes in working directory to submit." return True - patch = mypopen("git diff -p --binary --diff-filter=ACMRTUXB HEAD").read() + patch = read_pipe("git diff -p --binary --diff-filter=ACMRTUXB HEAD") self.diffFile = gitdir + "/p4-git-diff" f = open(self.diffFile, "wb") f.write(patch) @@ -557,7 +589,7 @@ class P4Sync(Command): self.syncWithOrigin = False def p4File(self, depotPath): - return os.popen("p4 print -q \"%s\"" % depotPath, "rb").read() + return read_pipe("p4 print -q \"%s\"" % depotPath) def extractFilesFromCommit(self, commit): files = [] @@ -799,7 +831,7 @@ class P4Sync(Command): else: cmdline += " --branches" - for line in mypopen(cmdline).readlines(): + for line in read_pipe_lines(cmdline): if self.importIntoRemotes and ((not line.startswith("p4/")) or line == "p4/HEAD\n"): continue if self.importIntoRemotes: @@ -1032,7 +1064,7 @@ class P4Sync(Command): else: if self.verbose: print "Getting p4 changes for %s...%s" % (self.depotPath, self.changeRange) - output = mypopen("p4 changes %s...%s" % (self.depotPath, self.changeRange)).readlines() + output = read_pipe_lines("p4 changes %s...%s" % (self.depotPath, self.changeRange)) for line in output: changeNum = line.split(" ")[1] @@ -1141,7 +1173,7 @@ class P4Rebase(Command): sync = P4Sync() sync.run([]) print "Rebasing the current branch" - oldHead = mypopen("git rev-parse HEAD").read()[:-1] + oldHead = read_pipe("git rev-parse HEAD")[:-1] system("git rebase p4") system("git diff-tree --stat --summary -M %s HEAD" % oldHead) return True @@ -1252,9 +1284,9 @@ if cmd.needsGit: if len(gitdir) == 0: gitdir = ".git" if not isValidGitDir(gitdir): - gitdir = mypopen("git rev-parse --git-dir").read()[:-1] + gitdir = read_pipe("git rev-parse --git-dir")[:-1] if os.path.exists(gitdir): - cdup = mypopen("git rev-parse --show-cdup").read()[:-1]; + cdup = read_pipe("git rev-parse --show-cdup")[:-1]; if len(cdup) > 0: os.chdir(cdup); @@ -1268,4 +1300,3 @@ if cmd.needsGit: if not cmd.run(args): parser.print_help() - -- cgit v1.2.3 From bce4c5fc0b6aa9e599fc181c5350b461dafecee2 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 17:14:33 -0300 Subject: cleanup - use re.sub() iso. if for stripping ... - spacing nits Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 05b308f5be..8d649dd762 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -16,39 +16,39 @@ from sets import Set; gitdir = os.environ.get("GIT_DIR", "") silent = False -def write_pipe (c, str): +def write_pipe(c, str): if not silent: - sys.stderr.write ('writing pipe: %s\n' % c) + sys.stderr.write('writing pipe: %s\n' % c) ## todo: check return status - pipe = os.popen (c, 'w') + pipe = os.popen(c, 'w') val = pipe.write(str) - if pipe.close (): - sys.stderr.write ('Command failed') - sys.exit (1) + if pipe.close(): + sys.stderr.write('Command failed') + sys.exit(1) return val -def read_pipe (c): - sys.stderr.write ('reading pipe: %s\n' % c) +def read_pipe(c): + sys.stderr.write('reading pipe: %s\n' % c) ## todo: check return status - pipe = os.popen (c, 'rb') + pipe = os.popen(c, 'rb') val = pipe.read() - if pipe.close (): - sys.stderr.write ('Command failed') - sys.exit (1) + if pipe.close(): + sys.stderr.write('Command failed') + sys.exit(1) return val -def read_pipe_lines (c): - sys.stderr.write ('reading pipe: %s\n' % c) +def read_pipe_lines(c): + sys.stderr.write('reading pipe: %s\n' % c) ## todo: check return status - pipe = os.popen (c, 'rb') + pipe = os.popen(c, 'rb') val = pipe.readlines() - if pipe.close (): - sys.stderr.write ('Command failed') - sys.exit (1) + if pipe.close(): + sys.stderr.write('Command failed') + sys.exit(1) return val @@ -986,9 +986,7 @@ class P4Sync(Command): elif len(self.previousDepotPath) == 0: self.revision = "#head" - if self.depotPath.endswith("..."): - self.depotPath = self.depotPath[:-3] - + self.depotPath = re.sub ("\.\.\.$", "", self.depotPath) if not self.depotPath.endswith("/"): self.depotPath += "/" -- cgit v1.2.3 From 6754a299d8d977326e396d641106cc5db4d29db1 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 17:41:50 -0300 Subject: minor cleanups Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 8d649dd762..93c9d6417c 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -30,7 +30,8 @@ def write_pipe(c, str): return val def read_pipe(c): - sys.stderr.write('reading pipe: %s\n' % c) + if not silent: + sys.stderr.write('reading pipe: %s\n' % c) ## todo: check return status pipe = os.popen(c, 'rb') val = pipe.read() @@ -42,7 +43,8 @@ def read_pipe(c): def read_pipe_lines(c): - sys.stderr.write('reading pipe: %s\n' % c) + if not silent: + sys.stderr.write('reading pipe: %s\n' % c) ## todo: check return status pipe = os.popen(c, 'rb') val = pipe.readlines() @@ -52,6 +54,14 @@ def read_pipe_lines(c): return val +def system(cmd): + if not silent: + sys.stderr.write("executing %s" % cmd) + if os.system(cmd) != 0: + die("command failed: %s" % cmd) + + + def p4CmdList(cmd): cmd = "p4 -G %s" % cmd pipe = os.popen(cmd, "rb") @@ -111,10 +121,6 @@ def isValidGitDir(path): def parseRevision(ref): return read_pipe("git rev-parse %s" % ref)[:-1] -def system(cmd): - if os.system(cmd) != 0: - die("command failed: %s" % cmd) - def extractLogMessageFromGitCommit(commit): logMessage = "" @@ -571,7 +577,6 @@ class P4Sync(Command): (a ... is not needed in the path p4 specification, it's added implicitly)""" self.usage += " //depot/path[@revRange]" - self.silent = False self.createdBranches = Set() self.committedChanges = Set() @@ -584,6 +589,7 @@ class P4Sync(Command): self.importIntoRemotes = True self.maxChanges = "" self.isWindows = (platform.system() == "Windows") + self.depotPath = None if gitConfig("git-p4.syncFromOrigin") == "false": self.syncWithOrigin = False @@ -611,9 +617,11 @@ class P4Sync(Command): fnum = fnum + 1 return files + def stripRepoPath(self, path): + return path[len(self.depotPath):] + def splitFilesIntoBranches(self, commit): branches = {} - fnum = 0 while commit.has_key("depotFile%s" % fnum): path = commit["depotFile%s" % fnum] @@ -630,10 +638,12 @@ class P4Sync(Command): file["type"] = commit["type%s" % fnum] fnum = fnum + 1 - relPath = path[len(self.depotPath):] + relPath = self.stripRepoPath(path) for branch in self.knownBranches.keys(): - if relPath.startswith(branch + "/"): # add a trailing slash so that a commit into qt/4.2foo doesn't end up in qt/4.2 + + # add a trailing slash so that a commit into qt/4.2foo doesn't end up in qt/4.2 + if relPath.startswith(branch + "/"): if branch not in branches: branches[branch] = [] branches[branch].append(file) -- cgit v1.2.3 From 8b41a97f8a3e2778ce733cd3d7e181bc28cc43a0 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:20:53 -0300 Subject: clone and sync --keep-path to keep perforce path to module. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 93c9d6417c..51d117b789 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -11,6 +11,7 @@ import optparse, sys, os, marshal, popen2, subprocess, shelve import tempfile, getopt, sha, os.path, time, platform import re + from sets import Set; gitdir = os.environ.get("GIT_DIR", "") @@ -20,7 +21,6 @@ def write_pipe(c, str): if not silent: sys.stderr.write('writing pipe: %s\n' % c) - ## todo: check return status pipe = os.popen(c, 'w') val = pipe.write(str) if pipe.close(): @@ -32,7 +32,7 @@ def write_pipe(c, str): def read_pipe(c): if not silent: sys.stderr.write('reading pipe: %s\n' % c) - ## todo: check return status + pipe = os.popen(c, 'rb') val = pipe.read() if pipe.close(): @@ -60,8 +60,6 @@ def system(cmd): if os.system(cmd) != 0: die("command failed: %s" % cmd) - - def p4CmdList(cmd): cmd = "p4 -G %s" % cmd pipe = os.popen(cmd, "rb") @@ -566,7 +564,8 @@ class P4Sync(Command): optparse.make_option("--detect-labels", dest="detectLabels", action="store_true"), 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("--max-changes", dest="maxChanges"), + optparse.make_option("--keep-path", dest="keepRepoPath") ] self.description = """Imports from Perforce into a git repository.\n example: @@ -590,6 +589,7 @@ class P4Sync(Command): self.maxChanges = "" self.isWindows = (platform.system() == "Windows") self.depotPath = None + self.keepRepoPath = False if gitConfig("git-p4.syncFromOrigin") == "false": self.syncWithOrigin = False @@ -617,8 +617,11 @@ class P4Sync(Command): fnum = fnum + 1 return files - def stripRepoPath(self, path): - return path[len(self.depotPath):] + def stripRepoPath(self, path, prefix): + if self.keepRepoPath: + prefix = re.sub("^(//[^/]+/).*", r'\1', prefix) + + return path[len(prefix):] def splitFilesIntoBranches(self, commit): branches = {} @@ -638,7 +641,7 @@ class P4Sync(Command): file["type"] = commit["type%s" % fnum] fnum = fnum + 1 - relPath = self.stripRepoPath(path) + relPath = self.stripRepoPath(path, self.depotPath) for branch in self.knownBranches.keys(): @@ -687,7 +690,7 @@ class P4Sync(Command): continue rev = file["rev"] depotPath = path + "#" + rev - relPath = path[len(branchPrefix):] + relPath = self.stripRepoPath(path, branchPrefix) action = file["action"] if file["type"] == "apple": -- cgit v1.2.3 From b76f0565bfcfedba9e8920aa5120fc97796b642f Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:29:34 -0300 Subject: use string.strip() iso. slicing. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 51d117b789..ac446a8dc4 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -845,15 +845,15 @@ class P4Sync(Command): 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"): continue if self.importIntoRemotes: # strip off p4 - branch = line[3:-1] - else: - branch = line[:-1] + branch = re.sub ("^p4/", "", line) + self.p4BranchesInGit.append(branch) - self.initialParents[self.refPrefix + branch] = parseRevision(line[:-1]) + self.initialParents[self.refPrefix + branch] = parseRevision(line) def createOrUpdateBranchesFromOrigin(self): if not self.silent: -- cgit v1.2.3 From b25b20656dceff6145a1286f10618ab25d717537 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: use strip() iso. slicing for removing \n Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index ac446a8dc4..efa2fce29e 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -15,7 +15,7 @@ import re from sets import Set; gitdir = os.environ.get("GIT_DIR", "") -silent = False +silent = True def write_pipe(c, str): if not silent: @@ -109,7 +109,7 @@ def die(msg): sys.exit(1) def currentGitBranch(): - return read_pipe("git name-rev HEAD").split(" ")[1][:-1] + 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"): @@ -117,7 +117,7 @@ def isValidGitDir(path): return False def parseRevision(ref): - return read_pipe("git rev-parse %s" % ref)[:-1] + return read_pipe("git rev-parse %s" % ref).strip() def extractLogMessageFromGitCommit(commit): logMessage = "" @@ -205,7 +205,8 @@ class P4RollBack(Command): for line in lines: if self.rollbackLocalBranches or (line.startswith("p4/") and line != "p4/HEAD\n"): - ref = refPrefix + line[:-1] + line = line.strip() + ref = refPrefix + line log = extractLogMessageFromGitCommit(ref) depotPath, change = extractDepotPathAndChangeFromGitLog(log) changed = False @@ -271,7 +272,7 @@ class P4Submit(Command): commits.append("0") else: for line in read_pipe_lines("git rev-list --no-merges %s..%s" % (self.origin, self.master)): - commits.append(line[:-1]) + commits.append(line.strip()) commits.reverse() self.config["commits"] = commits @@ -372,7 +373,7 @@ class P4Submit(Command): if not self.directSubmit: logMessage = extractLogMessageFromGitCommit(id) logMessage = logMessage.replace("\n", "\n\t") - logMessage = logMessage[:-1] + logMessage = logMessage.strip() template = read_pipe("p4 change -o") @@ -513,7 +514,7 @@ class P4Submit(Command): if len(self.substFile) > 0: for line in open(self.substFile, "r").readlines(): - tokens = line[:-1].split("=") + tokens = line.strip().split("=") self.logSubstitutions[tokens[0]] = tokens[1] self.check() @@ -784,7 +785,7 @@ class P4Sync(Command): lines = cache.readlines() cache.close() for line in lines: - entry = line[:-1].split("\t") + entry = line.strip().split("\t") self.users[entry[0]] = entry[1] except IOError: self.getUserMapFromPerforceServer() @@ -814,7 +815,7 @@ class P4Sync(Command): print "Label changes: %s" % self.labels.keys() def getBranchMapping(self): - self.projectName = self.depotPath[self.depotPath[:-1].rfind("/") + 1:] + self.projectName = self.depotPath[self.depotPath.strip().rfind("/") + 1:] for info in p4CmdList("branches"): details = p4Cmd("branch -o %s" % info["branch"]) @@ -848,6 +849,7 @@ class P4Sync(Command): lie = line.strip() if self.importIntoRemotes and ((not line.startswith("p4/")) or line == "p4/HEAD\n"): continue + if self.importIntoRemotes: # strip off p4 branch = re.sub ("^p4/", "", line) @@ -966,7 +968,7 @@ class P4Sync(Command): self.branch = "refs/heads/" + self.branch if len(self.depotPath) != 0: - self.depotPath = self.depotPath[:-1] + self.depotPath = self.depotPath.strip() if len(args) == 0 and len(self.depotPath) != 0: if not self.silent: @@ -1184,7 +1186,7 @@ class P4Rebase(Command): sync = P4Sync() sync.run([]) print "Rebasing the current branch" - oldHead = read_pipe("git rev-parse HEAD")[:-1] + oldHead = read_pipe("git rev-parse HEAD").strip() system("git rebase p4") system("git diff-tree --stat --summary -M %s HEAD" % oldHead) return True @@ -1217,7 +1219,7 @@ class P4Clone(P4Sync): depotDir = re.sub(r"/$", "", depotDir) if not destination: - destination = os.path.split(depotDir)[-1] + destination = os.path.split(depotDir)[1] print "Importing from %s into %s" % (depotPath, destination) os.makedirs(destination) @@ -1295,9 +1297,9 @@ if cmd.needsGit: if len(gitdir) == 0: gitdir = ".git" if not isValidGitDir(gitdir): - gitdir = read_pipe("git rev-parse --git-dir")[:-1] + gitdir = read_pipe("git rev-parse --git-dir").strip() if os.path.exists(gitdir): - cdup = read_pipe("git rev-parse --show-cdup")[:-1]; + cdup = read_pipe("git rev-parse --show-cdup").strip() if len(cdup) > 0: os.chdir(cdup); -- cgit v1.2.3 From 4addad229169ece62f36c6c17cc15bdf532a60bc Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: add --verbose to all commands. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index efa2fce29e..cf9db73da6 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -15,47 +15,47 @@ import re 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 failed') + sys.stderr.write('Command %s failed\n' % 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') + if pipe.close() and not ignore_error: + sys.stderr.write('Command %s failed\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 failed') + sys.stderr.write('Command %s failed\n' % c) sys.exit(1) return val def system(cmd): - if not silent: + if verbose: sys.stderr.write("executing %s" % cmd) if os.system(cmd) != 0: die("command failed: %s" % cmd) @@ -157,7 +157,7 @@ def gitBranchExists(branch): return proc.wait() == 0; def gitConfig(key): - return mypopen("git config %s" % key).read()[:-1] + return read_pipe("git config %s" % key, ignore_error=True).strip() class Command: def __init__(self): @@ -168,7 +168,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 @@ -234,6 +235,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"), @@ -861,11 +863,12 @@ class P4Sync(Command): if not self.silent: print "Creating/updating branch(es) in %s based on origin branch(es)" % self.refPrefix - for line in mypopen("git rev-parse --symbolic --remotes"): + 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 @@ -1292,6 +1295,7 @@ if len(options) > 0: (cmd, args) = parser.parse_args(sys.argv[2:], cmd); +verbose = cmd.verbose if cmd.needsGit: gitdir = cmd.gitdir if len(gitdir) == 0: -- cgit v1.2.3 From 6326aa58662932212678a25c6f482a8da4195ac9 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: Extract multiple paths concurrently. This enables importing just the interesting bits of large repositories. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 262 ++++++++++++++++++++++++++------------------- 1 file changed, 153 insertions(+), 109 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index cf9db73da6..ad145e8595 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -133,24 +133,26 @@ def extractLogMessageFromGitCommit(commit): logMessage += log return logMessage -def extractDepotPathAndChangeFromGitLog(log): +def extractDepotPathsAndChangeFromGitLog(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 + + paths = values.get("depot-path").split(',') + return paths, values.get("change") def gitBranchExists(branch): proc = subprocess.Popen(["git", "rev-parse", branch], stderr=subprocess.PIPE, stdout=subprocess.PIPE); @@ -209,10 +211,11 @@ class P4RollBack(Command): line = line.strip() ref = refPrefix + line log = extractLogMessageFromGitCommit(ref) - depotPath, change = extractDepotPathAndChangeFromGitLog(log) + depotPaths, change = extractDepotPathsAndChangeFromGitLog(log) 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 @@ -223,7 +226,7 @@ class P4RollBack(Command): 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) + depotPaths, change = extractDepotPathsAndChangeFromGitLog(log) if changed: print "%s rewound to %s" % (ref, change) @@ -472,9 +475,9 @@ class P4Submit(Command): depotPath = "" if gitBranchExists("p4"): - [depotPath, dummy] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("p4")) + [depotPaths, dummy] = extractDepotPathsAndChangeFromGitLog(extractLogMessageFromGitCommit("p4")) if len(depotPath) == 0 and gitBranchExists("origin"): - [depotPath, dummy] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit("origin")) + [depotPaths, dummy] = extractDepotPathsAndChangeFromGitLog(extractLogMessageFromGitCommit("origin")) if len(depotPath) == 0: print "Internal error: cannot locate perforce depot path from existing branches" @@ -568,7 +571,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: @@ -591,8 +594,8 @@ class P4Sync(Command): 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 @@ -605,9 +608,10 @@ class P4Sync(Command): 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 @@ -620,20 +624,24 @@ class P4Sync(Command): 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 @@ -644,7 +652,7 @@ class P4Sync(Command): 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(): @@ -656,7 +664,7 @@ class P4Sync(Command): return branches - def commit(self, details, files, branch, branchPrefix, parent = ""): + def commit(self, details, files, branch, branchPrefixes, parent = ""): epoch = details["time"] author = details["user"] @@ -678,7 +686,8 @@ class P4Sync(Command): self.gitStream.write("data < 0: @@ -688,12 +697,13 @@ class P4Sync(Command): 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": @@ -728,7 +738,8 @@ class P4Sync(Command): 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): @@ -795,9 +806,9 @@ class P4Sync(Command): 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"] @@ -805,7 +816,9 @@ class P4Sync(Command): 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: @@ -817,6 +830,8 @@ class P4Sync(Command): 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"): @@ -872,8 +887,8 @@ class P4Sync(Command): remoteHead = self.refPrefix + headName originHead = "origin/" + headName - [originPreviousDepotPath, originP4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(originHead)) - if len(originPreviousDepotPath) == 0 or len(originP4Change) == 0: + [originPreviousDepotPaths, originP4Change] = extractDepotPathsAndChangeFromGitLog(extractLogMessageFromGitCommit(originHead)) + if len(originPreviousDepotPaths) == 0 or len(originP4Change) == 0: continue update = False @@ -882,25 +897,26 @@ class P4Sync(Command): print "creating %s" % remoteHead update = True else: - [p4PreviousDepotPath, p4Change] = extractDepotPathAndChangeFromGitLog(extractLogMessageFromGitCommit(remoteHead)) + [p4PreviousDepotPaths, p4Change] = extractDepotPathsAndChangeFromGitLog(extractLogMessageFromGitCommit(remoteHead)) if len(p4Change) > 0: - if originPreviousDepotPath == p4PreviousDepotPath: + if originPreviousDepotPaths == p4PreviousDepotPaths: originP4Change = int(originP4Change) p4Change = int(p4Change) if originP4Change > 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, originPreviousDepotPaths, remoteHead, p4PreviousDepotPaths) if update: system("git update-ref %s %s" % (remoteHead, originHead)) + 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 = {} @@ -926,7 +942,7 @@ class P4Sync(Command): if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes: system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch)) - if len(args) == 0: + if args == []: if self.hasOrigin: self.createOrUpdateBranchesFromOrigin() self.listExistingP4GitBranches() @@ -942,26 +958,31 @@ class P4Sync(Command): p4Change = 0 for branch in self.p4BranchesInGit: logMsg = extractLogMessageFromGitCommit(self.refPrefix + branch) - (depotPath, change) = extractDepotPathAndChangeFromGitLog(logMsg) + (depotPaths, change) = extractDepotPathsAndChangeFromGitLog(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: + if len(depotPaths) > 0 and len(change) > 0: change = int(change) + 1 p4Change = max(p4Change, change) - if len(self.previousDepotPath) == 0: - self.previousDepotPath = depotPath + if len(self.previousDepotPaths) == 0: + 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] + ## FIXME + 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 = self.previousDepotPaths self.changeRange = "@%s,#head" % p4Change self.initialParent = parseRevision(self.branch) if not self.silent and not self.detectBranches: @@ -970,43 +991,47 @@ class P4Sync(Command): 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 = 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 = {} @@ -1020,28 +1045,34 @@ class P4Sync(Command): 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 @@ -1059,7 +1090,7 @@ class P4Sync(Command): details["change"] = newestRevision 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() @@ -1079,8 +1110,11 @@ class P4Sync(Command): 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] @@ -1111,7 +1145,8 @@ class P4Sync(Command): if self.detectBranches: branches = self.splitFilesIntoBranches(description) for branch in branches.keys(): - branchPrefix = self.depotPath + branch + "/" + ## HACK --hwn + branchPrefix = self.depotPaths[0] + branch + "/" parent = "" @@ -1134,11 +1169,14 @@ class P4Sync(Command): 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 @@ -1155,7 +1193,8 @@ class P4Sync(Command): 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() @@ -1206,30 +1245,35 @@ class P4Clone(P4Sync): if len(args) < 1: return False - depotPath = args[0] destination = "" - if len(args) == 2: + if self.keepRepoPath: + destination = args[-1] + args = args[:-1] + elif len(args) == 2: destination = args[1] elif len(args) > 2: return False - if not depotPath.startswith("//"): - return False - - depotDir = re.sub("(@[^@]*)$", "", depotPath) - depotDir = re.sub("(#[^#]*)$", "", depotDir) - depotDir = re.sub(r"\.\.\.$,", "", depotDir) - depotDir = re.sub(r"/$", "", depotDir) + depotPaths = args + for p in depotPaths: + if not p.startswith("//"): + return False if not destination: + depotPath = args[0] + depotDir = re.sub("(@[^@]*)$", "", depotPath) + depotDir = re.sub("(#[^#]*)$", "", depotDir) + depotDir = re.sub(r"\.\.\.$,", "", depotDir) + depotDir = re.sub(r"/$", "", depotDir) + destination = os.path.split(depotDir)[1] - print "Importing from %s into %s" % (depotPath, destination) + print "Importing from %s into %s" % (`depotPaths`, destination) os.makedirs(destination) os.chdir(destination) 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"): -- cgit v1.2.3 From 9226c03c3279d66e2dea21a7a3e9f187e5ee9b9a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 28 May 2007 19:23:19 +0200 Subject: In *_pipe print the command that failed if it fails. Fixed old calls to mypopen. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index efa2fce29e..0f1285b39b 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -24,7 +24,7 @@ def write_pipe(c, str): pipe = os.popen(c, 'w') val = pipe.write(str) if pipe.close(): - sys.stderr.write('Command failed') + sys.stderr.write('Command failed: %s' % c) sys.exit(1) return val @@ -36,7 +36,7 @@ def read_pipe(c): pipe = os.popen(c, 'rb') val = pipe.read() if pipe.close(): - sys.stderr.write('Command failed') + sys.stderr.write('Command failed: %s' % c) sys.exit(1) return val @@ -49,7 +49,7 @@ def read_pipe_lines(c): pipe = os.popen(c, 'rb') val = pipe.readlines() if pipe.close(): - sys.stderr.write('Command failed') + sys.stderr.write('Command failed: %s' % c) sys.exit(1) return val @@ -157,7 +157,7 @@ def gitBranchExists(branch): return proc.wait() == 0; def gitConfig(key): - return mypopen("git config %s" % key).read()[:-1] + return os.popen("git config %s" % key, "rb").read()[:-1] class Command: def __init__(self): @@ -861,7 +861,7 @@ class P4Sync(Command): if not self.silent: print "Creating/updating branch(es) in %s based on origin branch(es)" % self.refPrefix - for line in mypopen("git rev-parse --symbolic --remotes"): + for line in read_pipe_lines("git rev-parse --symbolic --remotes"): if (not line.startswith("origin/")) or line.endswith("HEAD\n"): continue -- cgit v1.2.3 From cfeb59be256bf9cd2853ed04d4af056b2f0eff31 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 28 May 2007 19:24:57 +0200 Subject: Fix typo in listExistingP4Branches that broke sync. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 0f1285b39b..794286ee8e 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -846,8 +846,8 @@ class P4Sync(Command): 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: -- cgit v1.2.3 From bb6e09b27afeaae780dabfda7a07d59fc7efc4cf Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: Diverse cleanups - print commands with \n - extractDepotPathsAndChangeFromGitLog -> extractSettings, returning dict. - store keepRepoPath in [git-p4: ] line - create a main() function, so git-p4 can be pychecked - use --destination for clone destination. This simplifies logic for --keep-path Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 224 +++++++++++++++++++++++++++------------------ 1 file changed, 134 insertions(+), 90 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index ad145e8595..b280e97742 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -56,7 +56,7 @@ def read_pipe_lines(c): def system(cmd): if verbose: - sys.stderr.write("executing %s" % cmd) + sys.stderr.write("executing %s\n" % cmd) if os.system(cmd) != 0: die("command failed: %s" % cmd) @@ -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 @@ -133,7 +134,7 @@ def extractLogMessageFromGitCommit(commit): logMessage += log return logMessage -def extractDepotPathsAndChangeFromGitLog(log): +def extractSettingsGitLog(log): values = {} for line in log.split("\n"): line = line.strip() @@ -151,11 +152,12 @@ def extractDepotPathsAndChangeFromGitLog(log): values[key] = val - paths = values.get("depot-path").split(',') - return paths, values.get("change") + 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): @@ -211,7 +213,11 @@ class P4RollBack(Command): line = line.strip() ref = refPrefix + line log = extractLogMessageFromGitCommit(ref) - depotPaths, change = extractDepotPathsAndChangeFromGitLog(log) + settings = extractSettingsGitLog(log) + + depotPaths = settings['depot-paths'] + change = settings['change'] + changed = False if len(p4Cmd("changes -m 1 " + ' '.join (['%s...@%s' % (p, maxChange) @@ -220,13 +226,17 @@ class P4RollBack(Command): 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) - depotPaths, change = extractDepotPathsAndChangeFromGitLog(log) + settings = extractSettingsGitLog(log) + + + depotPaths = settings['depot-paths'] + change = settings['change'] if changed: print "%s rewound to %s" % (ref, change) @@ -474,10 +484,12 @@ class P4Submit(Command): return False depotPath = "" + settings = None if gitBranchExists("p4"): - [depotPaths, dummy] = extractDepotPathsAndChangeFromGitLog(extractLogMessageFromGitCommit("p4")) + settings = extractSettingsGitLog(extractLogMessageFromGitCommit("p4")) if len(depotPath) == 0 and gitBranchExists("origin"): - [depotPaths, dummy] = extractDepotPathsAndChangeFromGitLog(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" @@ -686,8 +698,11 @@ class P4Sync(Command): self.gitStream.write("data < 0: @@ -883,12 +898,13 @@ class P4Sync(Command): if (not line.startswith("origin/")) or line.endswith("HEAD\n"): continue - headName = line[len("origin/")] + headName = line[len("origin/"):] remoteHead = self.refPrefix + headName originHead = "origin/" + headName - [originPreviousDepotPaths, originP4Change] = extractDepotPathsAndChangeFromGitLog(extractLogMessageFromGitCommit(originHead)) - if len(originPreviousDepotPaths) == 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 @@ -897,20 +913,36 @@ class P4Sync(Command): print "creating %s" % remoteHead update = True else: - [p4PreviousDepotPaths, p4Change] = extractDepotPathsAndChangeFromGitLog(extractLogMessageFromGitCommit(remoteHead)) - if len(p4Change) > 0: - if originPreviousDepotPaths == p4PreviousDepotPaths: - 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, originPreviousDepotPaths, remoteHead, p4PreviousDepotPaths) + 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.depotPaths = [] @@ -942,7 +974,8 @@ class P4Sync(Command): if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes: system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch)) - if args == []: + ### FIXME + if 1: if self.hasOrigin: self.createOrUpdateBranchesFromOrigin() self.listExistingP4GitBranches() @@ -958,19 +991,22 @@ class P4Sync(Command): p4Change = 0 for branch in self.p4BranchesInGit: logMsg = extractLogMessageFromGitCommit(self.refPrefix + branch) - (depotPaths, change) = extractDepotPathsAndChangeFromGitLog(logMsg) + + settings = extractSettingsGitLog(logMsg) if self.verbose: print "path %s change %s" % (','.join(depotPaths), change) - if len(depotPaths) > 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.previousDepotPaths) == 0: + depotPaths = sorted(settings['depot-paths']) + if self.previousDepotPaths == []: self.previousDepotPaths = depotPaths else: - ## FIXME paths = [] for (prev, cur) in zip(self.previousDepotPaths, depotPaths): for i in range(0, max(len(cur), len(prev))): @@ -982,7 +1018,7 @@ class P4Sync(Command): self.previousDepotPaths = paths if p4Change > 0: - self.depotPaths = self.previousDepotPaths + self.depotPaths = sorted(self.previousDepotPaths) self.changeRange = "@%s,#head" % p4Change self.initialParent = parseRevision(self.branch) if not self.silent and not self.detectBranches: @@ -1001,7 +1037,7 @@ class P4Sync(Command): ' '.join (args))) sys.exit(1) - self.depotPaths = args + self.depotPaths = sorted(args) self.revision = "" self.users = {} @@ -1088,7 +1124,7 @@ class P4Sync(Command): fileCnt = fileCnt + 1 details["change"] = newestRevision - + self.updateOptionDict(details) try: self.commit(details, self.extractFilesFromCommit(details), self.branch, self.depotPaths) except IOError: @@ -1135,6 +1171,7 @@ class P4Sync(Command): 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))) @@ -1237,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): @@ -1245,32 +1287,28 @@ class P4Clone(P4Sync): if len(args) < 1: return False - destination = "" - if self.keepRepoPath: - destination = args[-1] - args = args[:-1] - elif len(args) == 2: - destination = args[1] - elif len(args) > 2: - 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 - if not destination: + 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) - destination = os.path.split(depotDir)[1] + self.cloneDestination = os.path.split(depotDir)[1] - print "Importing from %s into %s" % (`depotPaths`, 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, depotPaths): @@ -1310,54 +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 +def main(): + if len(sys.argv[1:]) == 0: + printUsage(commands.keys()) + sys.exit(2) -args = sys.argv[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 -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); - - 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() -- cgit v1.2.3 From b86f73782eafd1c61bb706ec5ca3d1ec548d82f5 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: remove global .gitdir Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 53 +++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 28ea53dea4..6501387657 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -14,7 +14,6 @@ import re from sets import Set; -gitdir = os.environ.get("GIT_DIR", "") verbose = False def write_pipe(c, str): @@ -469,9 +468,7 @@ class P4Submit(Command): % (fileName, fileName)) def run(self, args): - global gitdir # make gitdir absolute so we can cd out into the perforce checkout - gitdir = os.path.abspath(gitdir) os.environ["GIT_DIR"] = gitdir if len(args) == 0: @@ -510,7 +507,7 @@ class P4Submit(Command): print "No changes in working directory to submit." return True patch = read_pipe("git diff -p --binary --diff-filter=ACMRTUXB HEAD") - self.diffFile = gitdir + "/p4-git-diff" + self.diffFile = self.gitdir + "/p4-git-diff" f = open(self.diffFile, "wb") f.write(patch) f.close(); @@ -535,7 +532,7 @@ class P4Submit(Command): self.logSubstitutions[tokens[0]] = tokens[1] self.check() - self.configFile = gitdir + "/p4-git-sync.cfg" + self.configFile = self.gitdir + "/p4-git-sync.cfg" self.config = shelve.open(self.configFile, writeback=True) if self.firstTime: @@ -799,7 +796,7 @@ class P4Sync(Command): continue self.users[output["User"]] = output["FullName"] + " <" + output["Email"] + ">" - cache = open(gitdir + "/p4-usercache.txt", "wb") + cache = open(self.gitdir + "/p4-usercache.txt", "wb") for user in self.users.keys(): cache.write("%s\t%s\n" % (user, self.users[user])) cache.close(); @@ -809,7 +806,7 @@ class P4Sync(Command): self.users = {} self.userMapFromPerforceServer = False try: - cache = open(gitdir + "/p4-usercache.txt", "rb") + cache = open(self.gitdir + "/p4-usercache.txt", "rb") lines = cache.readlines() cache.close() for line in lines: @@ -1283,8 +1280,6 @@ class P4Clone(P4Sync): self.needsGit = False def run(self, args): - global gitdir - if len(args) < 1: return False @@ -1310,7 +1305,7 @@ class P4Clone(P4Sync): os.makedirs(self.cloneDestination) os.chdir(self.cloneDestination) system("git init") - gitdir = os.getcwd() + "/.git" + self.gitdir = os.getcwd() + "/.git" if not P4Sync.run(self, depotPaths): return False if self.branch != "master": @@ -1340,12 +1335,12 @@ def printUsage(commands): print "" commands = { - "debug" : P4Debug(), - "submit" : P4Submit(), - "sync" : P4Sync(), - "rebase" : P4Rebase(), - "clone" : P4Clone(), - "rollback" : P4RollBack() + "debug" : P4Debug, + "submit" : P4Submit, + "sync" : P4Sync, + "rebase" : P4Rebase, + "clone" : P4Clone, + "rollback" : P4RollBack } @@ -1357,7 +1352,8 @@ def main(): cmd = "" cmdName = sys.argv[1] try: - cmd = commands[cmdName] + klass = commands[cmdName] + cmd = klass() except KeyError: print "unknown command %s" % cmdName print "" @@ -1365,7 +1361,7 @@ def main(): sys.exit(2) options = cmd.options - cmd.gitdir = gitdir + cmd.gitdir = os.environ.get("GIT_DIR", None) args = sys.argv[2:] @@ -1381,23 +1377,22 @@ def main(): 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): + if cmd.gitdir == None: + cmd.gitdir = os.path.abspath(".git") + if not isValidGitDir(cmd.gitdir): + cmd.gitdir = read_pipe("git rev-parse --git-dir").strip() + if os.path.exists(cmd.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" + if not isValidGitDir(cmd.gitdir): + if isValidGitDir(cmd.gitdir + "/.git"): + cmd.gitdir += "/.git" else: - die("fatal: cannot locate git repository at %s" % gitdir) + die("fatal: cannot locate git repository at %s" % cmd.gitdir) - os.environ["GIT_DIR"] = gitdir + os.environ["GIT_DIR"] = cmd.gitdir if not cmd.run(args): parser.print_help() -- cgit v1.2.3 From 6a49f8e2e04317175060576d85a5d2062ebb43a4 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: Read p4 files in one batch. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 89 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 26 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6501387657..8a3c53eb8c 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -61,6 +61,8 @@ def system(cmd): def p4CmdList(cmd): cmd = "p4 -G %s" % cmd + if verbose: + sys.stderr.write("Opening pipe: %s\n" % cmd) pipe = os.popen(cmd, "rb") result = [] @@ -609,9 +611,6 @@ class P4Sync(Command): if gitConfig("git-p4.syncFromOrigin") == "false": self.syncWithOrigin = False - def p4File(self, depotPath): - return read_pipe("p4 print -q \"%s\"" % depotPath) - def extractFilesFromCommit(self, commit): files = [] fnum = 0 @@ -673,6 +672,39 @@ class P4Sync(Command): return branches + ## Should move this out, doesn't use SELF. + def readP4Files(self, files): + specs = [(f['path'] + "#" + f['rev'], f) for f in files] + + data = read_pipe('p4 print %s' % ' '.join(['"%s"' % spec + for (spec, info) in specs])) + + idx = 0 + for j in range(0, len(specs)): + filespec, info = specs[j] + + assert idx < len(data) + if data[idx:idx + len(filespec)] != filespec: + assert False + idx = data.find ('\n', idx) + assert idx > 0 + idx += 1 + + start = idx + + end = -1 + if j < len(specs)-1: + next_spec, next_info = specs[j+1] + end = data.find(next_spec, start) + + assert end >= 0 + else: + end = len(specs) + + + info['data'] = data[start:end] + idx = end + def commit(self, details, files, branch, branchPrefixes, parent = ""): epoch = details["time"] author = details["user"] @@ -681,7 +713,7 @@ class P4Sync(Command): print "commit into %s" % branch self.gitStream.write("commit %s\n" % branch) - # gitStream.write("mark :%s\n" % details["change"]) +# gitStream.write("mark :%s\n" % details["change"]) self.committedChanges.add(int(details["change"])) committer = "" if author not in self.users: @@ -707,29 +739,30 @@ class P4Sync(Command): print "parent %s" % parent self.gitStream.write("from %s\n" % parent) - for file in files: - path = file["path"] + new_files = [] + for f in files: + if [p for p in branchPrefixes if f['path'].startswith(p)]: + new_files.append (f) + else: + sys.stderr.write("Ignoring file outside of prefix: %s\n" % path) + files = new_files - if not [p for p in branchPrefixes if path.startswith(p)]: - continue - rev = file["rev"] - depotPath = path + "#" + rev - relPath = self.stripRepoPath(path, branchPrefixes) - action = file["action"] - + self.readP4Files(files) + for file in files: if file["type"] == "apple": - print "\nfile %s is a strange apple file that forks. Ignoring!" % path + print "\nfile %s is a strange apple file that forks. Ignoring!" % file['path'] continue - if action == "delete": + relPath = self.stripRepoPath(file['path'], branchPrefixes) + if file["action"] == "delete": self.gitStream.write("D %s\n" % relPath) else: mode = 644 if file["type"].startswith("x"): mode = 755 - data = self.p4File(depotPath) + data = file['data'] if self.isWindows and file["type"].endswith("text"): data = data.replace("\r\n", "\n") @@ -971,8 +1004,9 @@ class P4Sync(Command): if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes: system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch)) - ### FIXME - if 1: + # TODO: should always look at previous commits, + # merge with previous imports, if possible. + if args == []: if self.hasOrigin: self.createOrUpdateBranchesFromOrigin() self.listExistingP4GitBranches() @@ -1046,7 +1080,7 @@ class P4Sync(Command): self.changeRange = p[atIdx:] if self.changeRange == "@all": self.changeRange = "" - elif self.changeRange.find(",") == -1: + elif ',' not in self.changeRange: self.revision = self.changeRange self.changeRange = "" p = p[0:atIdx] @@ -1279,6 +1313,15 @@ class P4Clone(P4Sync): self.cloneDestination = None self.needsGit = False + def defaultDestination(self, args): + ## TODO: use common prefix of args? + depotPath = args[0] + depotDir = re.sub("(@[^@]*)$", "", depotPath) + depotDir = re.sub("(#[^#]*)$", "", depotDir) + depotDir = re.sub(r"\.\.\.$,", "", depotDir) + depotDir = re.sub(r"/$", "", depotDir) + return os.path.split(depotDir)[1] + def run(self, args): if len(args) < 1: return False @@ -1293,13 +1336,7 @@ class P4Clone(P4Sync): return False 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) - - self.cloneDestination = os.path.split(depotDir)[1] + self.cloneDestination = self.defaultDestination() print "Importing from %s into %s" % (`depotPaths`, self.cloneDestination) os.makedirs(self.cloneDestination) -- cgit v1.2.3 From 9320da8dd492c13f1d32b7fde8c9e60bdbd10217 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: Thinko, fix buglet. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 8a3c53eb8c..f1f562fae4 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -699,11 +699,11 @@ class P4Sync(Command): assert end >= 0 else: - end = len(specs) - + end = len(data) info['data'] = data[start:end] idx = end + assert idx == len(data) def commit(self, details, files, branch, branchPrefixes, parent = ""): epoch = details["time"] -- cgit v1.2.3 From 183b8ef89be041cd50803427cfc46fe1afed17bb Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: store p4 user cache in home directory. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index f1f562fae4..bd1afb2964 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -819,6 +819,9 @@ class P4Sync(Command): print ("Tag %s does not match with change %s: file count is different." % (labelDetails["label"], change)) + def getUserCacheFilename(self): + return os.environ["HOME"] + "/.gitp4-usercache.txt") + def getUserMapFromPerforceServer(self): if self.userMapFromPerforceServer: return @@ -829,17 +832,19 @@ class P4Sync(Command): continue self.users[output["User"]] = output["FullName"] + " <" + output["Email"] + ">" - cache = open(self.gitdir + "/p4-usercache.txt", "wb") - for user in self.users.keys(): - cache.write("%s\t%s\n" % (user, self.users[user])) - cache.close(); + + s = '' + for (key, val) in self.users.items(): + s += "%s\t%s\n" % (key, val) + + open(self.getUserCacheFilename(), "wb").write(s) self.userMapFromPerforceServer = True def loadUserMapFromCache(self): self.users = {} self.userMapFromPerforceServer = False try: - cache = open(self.gitdir + "/p4-usercache.txt", "rb") + cache = open(self.getUserCacheFilename(), "rb") lines = cache.readlines() cache.close() for line in lines: -- cgit v1.2.3 From a3287be5bc40c1aa036eb5422db5a6a087d1736e Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: thinko. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index bd1afb2964..01efd92809 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -820,7 +820,7 @@ class P4Sync(Command): % (labelDetails["label"], change)) def getUserCacheFilename(self): - return os.environ["HOME"] + "/.gitp4-usercache.txt") + return os.environ["HOME"] + "/.gitp4-usercache.txt" def getUserMapFromPerforceServer(self): if self.userMapFromPerforceServer: -- cgit v1.2.3 From 96e07dd23c570fe5e65e619c0f1e3c87be2a8352 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: read files before creating the commit. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 01efd92809..d1989e6134 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -697,6 +697,9 @@ class P4Sync(Command): next_spec, next_info = specs[j+1] end = data.find(next_spec, start) + if end < 0: + print spec, next_spec + assert end >= 0 else: end = len(data) @@ -712,6 +715,20 @@ class P4Sync(Command): if self.verbose: print "commit into %s" % branch + # start with reading files; if that fails, we should not + # create a commit. + new_files = [] + for f in files: + if [p for p in branchPrefixes if f['path'].startswith(p)]: + new_files.append (f) + else: + sys.stderr.write("Ignoring file outside of prefix: %s\n" % path) + files = new_files + self.readP4Files(files) + + + + self.gitStream.write("commit %s\n" % branch) # gitStream.write("mark :%s\n" % details["change"]) self.committedChanges.add(int(details["change"])) @@ -739,16 +756,6 @@ class P4Sync(Command): print "parent %s" % parent self.gitStream.write("from %s\n" % parent) - - new_files = [] - for f in files: - if [p for p in branchPrefixes if f['path'].startswith(p)]: - new_files.append (f) - else: - sys.stderr.write("Ignoring file outside of prefix: %s\n" % path) - files = new_files - - self.readP4Files(files) for file in files: if file["type"] == "apple": print "\nfile %s is a strange apple file that forks. Ignoring!" % file['path'] @@ -1030,9 +1037,6 @@ class P4Sync(Command): settings = extractSettingsGitLog(logMsg) - if self.verbose: - print "path %s change %s" % (','.join(depotPaths), change) - self.readOptions(settings) if (settings.has_key('depot-paths') and settings.has_key ('change')): @@ -1145,6 +1149,9 @@ class P4Sync(Command): + ' '.join(["%s...%s" % (p, self.revision) for p in self.depotPaths])): + + if not info.has_key("change"): + print info change = int(info["change"]) if change > newestRevision: newestRevision = change @@ -1154,7 +1161,7 @@ class P4Sync(Command): #fileCnt = fileCnt + 1 continue - for prop in [ "depotFile", "rev", "action", "type" ]: + for prop in ["depotFile", "rev", "action", "type" ]: details["%s%s" % (prop, fileCnt)] = info[prop] fileCnt = fileCnt + 1 -- cgit v1.2.3 From 982bb8a30376d0024a1794426e6e2291a7a21294 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: don't p4 print deleted files. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d1989e6134..63d7a4c995 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -674,17 +674,18 @@ class P4Sync(Command): ## Should move this out, doesn't use SELF. def readP4Files(self, files): - specs = [(f['path'] + "#" + f['rev'], f) for f in files] + specs = [(f['path'] + "#" + f['rev'], f) for f in files + if f['action'] != 'delete'] - data = read_pipe('p4 print %s' % ' '.join(['"%s"' % spec - for (spec, info) in specs])) + data = read_pipe('p4 print %s' % ' '.join(['"%s"' % path + for (path, info) in specs])) idx = 0 for j in range(0, len(specs)): - filespec, info = specs[j] + (pathrev, info) = specs[j] assert idx < len(data) - if data[idx:idx + len(filespec)] != filespec: + if data[idx:idx + len(pathrev)] != pathrev: assert False idx = data.find ('\n', idx) assert idx > 0 @@ -694,11 +695,15 @@ class P4Sync(Command): end = -1 if j < len(specs)-1: - next_spec, next_info = specs[j+1] - end = data.find(next_spec, start) + (next_pathrev, next_info) = specs[j+1] + end = data.find(next_pathrev, start) if end < 0: - print spec, next_spec + print 'j' + print 'PATHREV', pathrev, specs[j] + print 'nextpathrev', next_pathrev, specs[j+1] + print 'start', start, len(data) + print 'end', end assert end >= 0 else: -- cgit v1.2.3 From f2eda79f6967363f9377ef3b137a35d0c86aca2c Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: only run p4 print if necessary Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 3 +++ 1 file changed, 3 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 63d7a4c995..76bbe3fdbf 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -677,6 +677,9 @@ class P4Sync(Command): specs = [(f['path'] + "#" + f['rev'], f) for f in files if f['action'] != 'delete'] + if not specs: + return + data = read_pipe('p4 print %s' % ' '.join(['"%s"' % path for (path, info) in specs])) -- cgit v1.2.3 From d2c6dd30eff648aef30d003ef327ab9415f86db0 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: use p4CmdList() to get file contents in Python dicts. This is more robust. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 56 +++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 35 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 76bbe3fdbf..1d799708f6 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -580,7 +580,8 @@ class P4Sync(Command): optparse.make_option("--silent", dest="silent", action="store_true"), optparse.make_option("--detect-labels", dest="detectLabels", action="store_true"), optparse.make_option("--verbose", dest="verbose", action="store_true"), - optparse.make_option("--import-local", dest="importIntoRemotes", action="store_false"), + 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("--keep-path", dest="keepRepoPath", action='store_true') ] @@ -680,41 +681,22 @@ class P4Sync(Command): if not specs: return - data = read_pipe('p4 print %s' % ' '.join(['"%s"' % path - for (path, info) in specs])) + filedata = p4CmdList('print %s' % ' '.join(['"%s"' % path + for (path, info) in specs])) - idx = 0 - for j in range(0, len(specs)): - (pathrev, info) = specs[j] + j = 0; + contents = {} + while filedata[j:]: + stat = filedata[j] + text = filedata[j+1] + j += 2 - assert idx < len(data) - if data[idx:idx + len(pathrev)] != pathrev: - assert False - idx = data.find ('\n', idx) - assert idx > 0 - idx += 1 + assert stat['code'] == 'stat' and text['code'] == 'text' + contents[stat['depotFile']] = text['data'] - start = idx - - end = -1 - if j < len(specs)-1: - (next_pathrev, next_info) = specs[j+1] - end = data.find(next_pathrev, start) - - if end < 0: - print 'j' - print 'PATHREV', pathrev, specs[j] - print 'nextpathrev', next_pathrev, specs[j+1] - print 'start', start, len(data) - print 'end', end - - assert end >= 0 - else: - end = len(data) - - info['data'] = data[start:end] - idx = end - assert idx == len(data) + for f in files: + assert not f.has_key('data') + f['data'] = contents[f['path']] def commit(self, details, files, branch, branchPrefixes, parent = ""): epoch = details["time"] @@ -1158,8 +1140,12 @@ class P4Sync(Command): % (p, self.revision) for p in self.depotPaths])): - if not info.has_key("change"): - print info + if info['code'] == 'error': + sys.stderr.write("p4 returned an error: %s\n" + % info['data']) + sys.exit(1) + + change = int(info["change"]) if change > newestRevision: newestRevision = change -- cgit v1.2.3 From 86dff6b6762149d5f3d4b44bb57f58a8399a33ee Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: Cleanups & import into p4/master for local import - import into master/local if --import-local is set - use Die() for exiting - if --verbose is set, raise Exception() - use joined strings iso. `list` for progress printing Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 54 +++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 1d799708f6..cc0b7013da 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -16,40 +16,44 @@ from sets import Set; verbose = False +def die(msg): + if verbose: + raise Exception(msg) + else: + sys.stderr.write(msg + "\n") + sys.exit(1) + def write_pipe(c, str): if verbose: - sys.stderr.write('writing pipe: %s\n' % c) + sys.stderr.write('Writing pipe: %s\n' % c) pipe = os.popen(c, 'w') val = pipe.write(str) if pipe.close(): - sys.stderr.write('Command failed: %s' % c) - sys.exit(1) + die('Command failed: %s' % c) return val def read_pipe(c, ignore_error=False): if verbose: - sys.stderr.write('reading pipe: %s\n' % c) + sys.stderr.write('Reading pipe: %s\n' % c) pipe = os.popen(c, 'rb') val = pipe.read() if pipe.close() and not ignore_error: - sys.stderr.write('Command failed: %s\n' % c) - sys.exit(1) + die('Command failed: %s' % c) return val def read_pipe_lines(c): if verbose: - sys.stderr.write('reading pipe: %s\n' % c) + 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 failed: %s\n' % c) - sys.exit(1) + die('Command failed: %s' % c) return val @@ -105,10 +109,6 @@ def p4Where(depotPath): clientPath = clientPath[:-3] return clientPath -def die(msg): - sys.stderr.write(msg + "\n") - sys.exit(1) - def currentGitBranch(): return read_pipe("git name-rev HEAD").split(" ")[1].strip() @@ -583,7 +583,8 @@ class P4Sync(Command): 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("--keep-path", dest="keepRepoPath", action='store_true') + optparse.make_option("--keep-path", dest="keepRepoPath", action='store_true', + help="Keep entire BRANCH/DIR/SUBDIR prefix during import") ] self.description = """Imports from Perforce into a git repository.\n example: @@ -876,10 +877,14 @@ class P4Sync(Command): if self.verbose: print "Label changes: %s" % self.labels.keys() + def guessProjectName(self): + for p in self.depotPaths: + return p [p.strip().rfind("/") + 1:] + def getBranchMapping(self): ## FIXME - what's a P4 projectName ? - self.projectName = self.depotPath[self.depotPath.strip().rfind("/") + 1:] + self.projectName = self.guessProjectName() for info in p4CmdList("branches"): details = p4Cmd("branch -o %s" % info["branch"]) @@ -911,9 +916,11 @@ class P4Sync(Command): for line in read_pipe_lines(cmdline): line = line.strip() - if self.importIntoRemotes and ((not line.startswith("p4/")) or line == "p4/HEAD"): - continue + ## only import to p4/ + if not line.startswith('p4/'): + continue + branch = line if self.importIntoRemotes: # strip off p4 branch = re.sub ("^p4/", "", line) @@ -923,7 +930,8 @@ class P4Sync(Command): def createOrUpdateBranchesFromOrigin(self): if not self.silent: - print "Creating/updating branch(es) in %s based on origin branch(es)" % self.refPrefix + 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() @@ -998,7 +1006,7 @@ class P4Sync(Command): system("git fetch origin") if len(self.branch) == 0: - self.branch = self.refPrefix + "master" + self.branch = self.refPrefix + "p4/master" if gitBranchExists("refs/heads/p4") and self.importIntoRemotes: system("git update-ref %s refs/heads/p4" % self.branch) system("git branch -D p4"); @@ -1023,6 +1031,7 @@ class P4Sync(Command): p4Change = 0 for branch in self.p4BranchesInGit: + print self.p4BranchesInGit logMsg = extractLogMessageFromGitCommit(self.refPrefix + branch) settings = extractSettingsGitLog(logMsg) @@ -1125,7 +1134,7 @@ class P4Sync(Command): self.gitStream = importProcess.stdin self.gitError = importProcess.stderr - if len(self.revision) > 0: + if 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()) } @@ -1183,7 +1192,7 @@ class P4Sync(Command): changes.sort() else: if self.verbose: - print "Getting p4 changes for %s...%s" % (`self.depotPaths`, + print "Getting p4 changes for %s...%s" % (', '.join(self.depotPaths), self.changeRange) assert self.depotPaths output = read_pipe_lines("p4 changes " + ' '.join (["%s...%s" % (p, self.changeRange) @@ -1344,7 +1353,7 @@ class P4Clone(P4Sync): if not self.cloneDestination: self.cloneDestination = self.defaultDestination() - print "Importing from %s into %s" % (`depotPaths`, self.cloneDestination) + print "Importing from %s into %s" % (', '.join(depotPaths), self.cloneDestination) os.makedirs(self.cloneDestination) os.chdir(self.cloneDestination) system("git init") @@ -1357,6 +1366,7 @@ class P4Clone(P4Sync): system("git checkout -f") else: print "Could not detect main branch. No checkout/master branch created." + return True class HelpFormatter(optparse.IndentedHelpFormatter): -- cgit v1.2.3 From b17f88b5445210c2223b0642917c43581c767761 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: remove debug print Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 1 - 1 file changed, 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index cc0b7013da..5dae1f19ae 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1031,7 +1031,6 @@ class P4Sync(Command): p4Change = 0 for branch in self.p4BranchesInGit: - print self.p4BranchesInGit logMsg = extractLogMessageFromGitCommit(self.refPrefix + branch) settings = extractSettingsGitLog(logMsg) -- cgit v1.2.3 From b1ce94472684957cd5aba759f495a889f154a9a2 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: thinko: really ignore deleted files. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 5dae1f19ae..294c2ecfca 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -173,13 +173,18 @@ class P4Debug(Command): def __init__(self): Command.__init__(self) self.options = [ - optparse.make_option("--verbose", dest="verbose", action="store_true"), + optparse.make_option("--verbose", dest="verbose", action="store_true", + default=False), ] self.description = "A tool to debug the output of p4 -G." self.needsGit = False + self.verbose = False def run(self, args): + j = 0 for output in p4CmdList(" ".join(args)): + print 'Element: %d' % j + j += 1 print output return True @@ -676,24 +681,27 @@ class P4Sync(Command): ## Should move this out, doesn't use SELF. def readP4Files(self, files): - specs = [(f['path'] + "#" + f['rev'], f) for f in files + files = [f for f in files if f['action'] != 'delete'] - if not specs: + if not files: return - filedata = p4CmdList('print %s' % ' '.join(['"%s"' % path - for (path, info) in specs])) + filedata = p4CmdList('print %s' % ' '.join(['"%s#%s"' % (f['path'], + f['rev']) + for f in files])) j = 0; contents = {} - while filedata[j:]: + while j < len(filedata): stat = filedata[j] - text = filedata[j+1] - j += 2 + j += 1 + text = '' + while j < len(filedata) and filedata[j]['code'] == 'text': + text += filedata[j]['data'] + j += 1 - assert stat['code'] == 'stat' and text['code'] == 'text' - contents[stat['depotFile']] = text['data'] + contents[stat['depotFile']] = text for f in files: assert not f.has_key('data') -- cgit v1.2.3 From 7530a40ce2006082580865f4db6d32b956ca8dc0 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: look for 'text' and 'binary' files. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 294c2ecfca..e955ad4f44 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -697,7 +697,8 @@ class P4Sync(Command): stat = filedata[j] j += 1 text = '' - while j < len(filedata) and filedata[j]['code'] == 'text': + while j < len(filedata) and filedata[j]['code'] in ('text', + 'binary'): text += filedata[j]['data'] j += 1 @@ -773,7 +774,7 @@ class P4Sync(Command): if self.isWindows and file["type"].endswith("text"): data = data.replace("\r\n", "\n") - self.gitStream.write("M %s inline %s\n" % (mode, relPath)) + self.gitStream.write("M %d inline %s\n" % (mode, relPath)) self.gitStream.write("data %s\n" % len(data)) self.gitStream.write(data) self.gitStream.write("\n") -- cgit v1.2.3 From 845b42cb6c1c1e80c4283234ea2162cae809bd50 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 7 Jun 2007 09:19:34 +0200 Subject: Fix support for "depot-path" in older git-p4 imports Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e955ad4f44..e576f2dd9e 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -153,7 +153,10 @@ def extractSettingsGitLog(log): values[key] = val - values['depot-paths'] = values.get("depot-paths").split(',') + paths = values.get("depot-paths") + if not paths: + paths = values.get("depot-path") + values['depot-paths'] = paths.split(',') return values def gitBranchExists(branch): -- cgit v1.2.3 From 583e170706f5d69770d0de220286f8f0f73667f3 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 7 Jun 2007 09:37:13 +0200 Subject: Fix common path "calculation" from logs of multiple branches. Need to use min instead of max for prev/cur to avoid out-of-bounds string access. Also treat "i" as index of the last match instead of a length because in case of a complete match of the two strings i was off by one. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e576f2dd9e..ba34f0a61f 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1059,11 +1059,12 @@ class P4Sync(Command): else: paths = [] for (prev, cur) in zip(self.previousDepotPaths, depotPaths): - for i in range(0, max(len(cur), len(prev))): + for i in range(0, min(len(cur), len(prev))): if cur[i] <> prev[i]: + i = i - 1 break - paths.append (cur[:i]) + paths.append (cur[:i + 1]) self.previousDepotPaths = paths -- cgit v1.2.3 From 330f53b8d679ece8363a73ed6f6e211d99cd5fdf Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 7 Jun 2007 09:39:51 +0200 Subject: Don't attempt to set the initialParent on multi-branch imports (useless). At some point the code paths should be unified, but for now I need a working git-p4 :) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index ba34f0a61f..ff737d762c 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1071,7 +1071,8 @@ class P4Sync(Command): if p4Change > 0: self.depotPaths = sorted(self.previousDepotPaths) self.changeRange = "@%s,#head" % p4Change - self.initialParent = parseRevision(self.branch) + if not self.detectBranches: + self.initialParent = parseRevision(self.branch) if not self.silent and not self.detectBranches: print "Performing incremental import into %s git branch" % self.branch -- cgit v1.2.3 From 6509e19cd1f6b5620d339a2be35b8a160ab30794 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 7 Jun 2007 09:41:53 +0200 Subject: Hack to make the multi-branch import work again with self.depotPaths now that self.depotPath is gone Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index ff737d762c..ececc44518 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -909,9 +909,10 @@ class P4Sync(Command): continue source = paths[0] destination = paths[1] - if source.startswith(self.depotPath) and destination.startswith(self.depotPath): - source = source[len(self.depotPath):-4] - destination = destination[len(self.depotPath):-4] + ## HACK + if source.startswith(self.depotPaths[0]) and destination.startswith(self.depotPaths[0]): + source = source[len(self.depotPaths[0]):-4] + destination = destination[len(self.depotPaths[0]):-4] if destination not in self.knownBranches: self.knownBranches[destination] = source if source not in self.knownBranches: -- cgit v1.2.3 From 68c42153060cab9ea6c16256febcf736a2a710d9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 7 Jun 2007 12:51:03 +0200 Subject: Fix git-p4 rebase Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 1 + 1 file changed, 1 insertion(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index ececc44518..50d92c0f42 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1320,6 +1320,7 @@ class P4Rebase(Command): self.options = [ ] self.description = ("Fetches the latest revision from perforce and " + "rebases the current work (branch) against it") + self.verbose = False def run(self, args): sync = P4Sync() -- cgit v1.2.3 From b0d10df77a1130bdf3b4f59fdc18312432b90823 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 7 Jun 2007 13:09:14 +0200 Subject: Fix git-p4 submit Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 50d92c0f42..8be0afe828 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -276,6 +276,7 @@ class P4Submit(Command): self.origin = "" self.directSubmit = False self.trustMeLikeAFool = False + self.verbose = False self.logSubstitutions = {} self.logSubstitutions[""] = "%log%" @@ -478,9 +479,6 @@ class P4Submit(Command): % (fileName, fileName)) def run(self, args): - # make gitdir absolute so we can cd out into the perforce checkout - os.environ["GIT_DIR"] = gitdir - if len(args) == 0: self.master = currentGitBranch() if len(self.master) == 0 or not gitBranchExists("refs/heads/%s" % self.master): -- cgit v1.2.3 From a52d5c7bc027248fca472a402882586a9eaf59bf Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 7 Jun 2007 13:10:20 +0200 Subject: Fix depot-path determination for git-p4 submit Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 8be0afe828..8b00e350ec 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -494,7 +494,7 @@ class P4Submit(Command): settings = extractSettingsGitLog(extractLogMessageFromGitCommit("p4")) if len(depotPath) == 0 and gitBranchExists("origin"): settings = extractSettingsGitLog(extractLogMessageFromGitCommit("origin")) - depotPaths = settings['depot-paths'] + depotPath = settings['depot-paths'][0] if len(depotPath) == 0: print "Internal error: cannot locate perforce depot path from existing branches" -- cgit v1.2.3 From f7baba8b092bdbc31196de1095c7779b633e28b1 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Thu, 7 Jun 2007 14:07:01 +0200 Subject: Ensure that the commit message is Windows formated (CRLF) before invoking the editor. (The default editor on Windows (Notepad) doesn't handle Unix line endings) Signed-off-by: Marius Storm-Olsen --- contrib/fast-import/git-p4 | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 8b00e350ec..fc4e7d26f0 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -277,6 +277,7 @@ class P4Submit(Command): self.directSubmit = False self.trustMeLikeAFool = False self.verbose = False + self.isWindows = (platform.system() == "Windows") self.logSubstitutions = {} self.logSubstitutions[""] = "%log%" @@ -398,6 +399,8 @@ class P4Submit(Command): if not self.directSubmit: logMessage = extractLogMessageFromGitCommit(id) logMessage = logMessage.replace("\n", "\n\t") + if self.isWindows: + logMessage = logMessage.replace("\n", "\r\n") logMessage = logMessage.strip() template = read_pipe("p4 change -o") @@ -444,6 +447,8 @@ class P4Submit(Command): tmpFile.close() os.remove(fileName) submitTemplate = message[:message.index(separatorLine)] + if self.isWindows: + submitTemplate = submitTemplate.replace("\r\n", "\n") if response == "y" or response == "yes": if self.dryRun: -- cgit v1.2.3 From 98ad4faf95c1e98d6f1aaccda6d96a00a3cddeed Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Thu, 7 Jun 2007 15:08:33 +0200 Subject: Fix git-p4 clone (defaultDestination) Signed-off-by: Marius Storm-Olsen --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index fc4e7d26f0..89581eacaa 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1369,7 +1369,7 @@ class P4Clone(P4Sync): return False if not self.cloneDestination: - self.cloneDestination = self.defaultDestination() + self.cloneDestination = self.defaultDestination(args) print "Importing from %s into %s" % (', '.join(depotPaths), self.cloneDestination) os.makedirs(self.cloneDestination) -- cgit v1.2.3 From db775559c2d866de895cc36532ddff6b1ebbeda9 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Thu, 7 Jun 2007 15:13:59 +0200 Subject: Fix single branch import into remotes Signed-off-by: Marius Storm-Olsen --- contrib/fast-import/git-p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 89581eacaa..ad023f203c 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1014,7 +1014,7 @@ class P4Sync(Command): if self.importIntoRemotes: self.refPrefix = "refs/remotes/p4/" else: - self.refPrefix = "refs/heads/" + self.refPrefix = "refs/heads/p4/" if self.syncWithOrigin and self.hasOrigin: if not self.silent: @@ -1022,7 +1022,7 @@ class P4Sync(Command): system("git fetch origin") if len(self.branch) == 0: - self.branch = self.refPrefix + "p4/master" + self.branch = self.refPrefix + "master" if gitBranchExists("refs/heads/p4") and self.importIntoRemotes: system("git update-ref %s refs/heads/p4" % self.branch) system("git branch -D p4"); -- cgit v1.2.3 From c4b33253c221d928f3edde71123a44765495b31a Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Thu, 7 Jun 2007 15:28:04 +0200 Subject: Exclude the HEAD symbolic ref from the list of known branches Signed-off-by: Marius Storm-Olsen --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index ad023f203c..965b391cda 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -934,7 +934,7 @@ class P4Sync(Command): line = line.strip() ## only import to p4/ - if not line.startswith('p4/'): + if not line.startswith('p4/') or line == "p4/HEAD": continue branch = line if self.importIntoRemotes: -- cgit v1.2.3 From 5e100b5cd7210f8054fd3464872c0366abc3c1dc Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 7 Jun 2007 21:12:25 +0200 Subject: Make clone behave like git clone by default again. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 965b391cda..3fe7ae77a8 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1364,6 +1364,11 @@ class P4Clone(P4Sync): sys.exit(1) depotPaths = args + + if not self.cloneDestination and len(depotPaths) > 1: + self.cloneDestination = depotPaths[-1] + depotPaths = depotPaths[:-1] + for p in depotPaths: if not p.startswith("//"): return False -- cgit v1.2.3 From a3fdd57901bfe1014c4a48e13815d80f1f0e8577 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 7 Jun 2007 22:54:32 +0200 Subject: Make git-p4 submit detect the correct reference (origin) branch when working with multi-branch imports. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3fe7ae77a8..efec0be32c 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -156,7 +156,8 @@ def extractSettingsGitLog(log): paths = values.get("depot-paths") if not paths: paths = values.get("depot-path") - values['depot-paths'] = paths.split(',') + if paths: + values['depot-paths'] = paths.split(',') return values def gitBranchExists(branch): @@ -494,12 +495,27 @@ class P4Submit(Command): return False depotPath = "" - settings = None - if gitBranchExists("p4"): - settings = extractSettingsGitLog(extractLogMessageFromGitCommit("p4")) - if len(depotPath) == 0 and gitBranchExists("origin"): - settings = extractSettingsGitLog(extractLogMessageFromGitCommit("origin")) - depotPath = settings['depot-paths'][0] + 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 + + if self.verbose: + print "Origin branch is " + self.origin if len(depotPath) == 0: print "Internal error: cannot locate perforce depot path from existing branches" @@ -530,12 +546,6 @@ class P4Submit(Command): if response == "y" or response == "yes": system("p4 sync ...") - if len(self.origin) == 0: - if gitBranchExists("p4"): - self.origin = "p4" - else: - self.origin = "origin" - if self.reset: self.firstTime = True @@ -969,7 +979,7 @@ class P4Sync(Command): print "creating %s" % remoteHead update = True else: - settings = extractSettingsGitLog(extractLogMessageFromGitCommit(remoteHead)) + settings = extractSettingsGitLog(extractLogMessageFromGitCommit(remoteHead)) if settings.has_key('change') > 0: if settings['depot-paths'] == original['depot-paths']: originP4Change = int(original['change']) -- cgit v1.2.3 From df450923a2a08c50976f2d241a1c4992cf03b3a7 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 8 Jun 2007 08:49:22 +0200 Subject: Only get the expensive branch mapping from the p4 server when not syncing with the help of an origin remote (which we instead then use to get new branches from). Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index efec0be32c..36fe69a795 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -907,10 +907,6 @@ class P4Sync(Command): return p [p.strip().rfind("/") + 1:] 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 @@ -1141,7 +1137,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 -- cgit v1.2.3 From 1b9a46849a45f2b0f58d6286957316f720a301b6 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: print error message when p4 print fails (eg. due to permission problems) Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e955ad4f44..35c24c93e3 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -702,6 +702,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: -- cgit v1.2.3 From 5265bfcb06f420841e6304b278b552a4654a4ba0 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 23 May 2007 18:49:35 -0300 Subject: also strip p4/ from local imports. Signed-off-by: Han-Wen Nienhuys --- contrib/fast-import/git-p4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 28e37fa6ab..88ea12cb37 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -948,9 +948,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) -- cgit v1.2.3 From 7aded26ce870ba2998e276604fc3c18dad6133bd Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 10 Jun 2007 00:22:30 +0200 Subject: Fixed the check to make sure to exclude the HEAD symbolic refs when updating the remotes/p4 branches from origin. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 88ea12cb37..d03ba0b6ad 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -962,7 +962,7 @@ class P4Sync(Command): 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("origin/")) or line.endswith("HEAD"): continue headName = line[len("origin/"):] -- cgit v1.2.3 From cae7b732d859b06a4f560271099891f15c5700f6 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 10 Jun 2007 10:57:40 +0200 Subject: Fix updating/creating remotes/p4/* heads from origin/p4/* Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d03ba0b6ad..9d52eada42 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -960,14 +960,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"): + 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') @@ -1020,7 +1022,7 @@ 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 self.importIntoRemotes: self.refPrefix = "refs/remotes/p4/" -- cgit v1.2.3 From 6e5295c4d3e4e79838d1dd7ab4a8b4965e1c7f96 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 11 Jun 2007 08:50:57 +0200 Subject: Fix project name guessing Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 9d52eada42..551573afc5 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -909,7 +909,12 @@ 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): for info in p4CmdList("branches"): -- cgit v1.2.3 From 86fda6a327ce9355ae9eab69fc7a3ec33fb5d7d1 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 11 Jun 2007 08:54:45 +0200 Subject: Fix depot-paths encoding for multi-path imports (don't split up //depot/path/foo) Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 551573afc5..815d8bbb5d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1312,7 +1312,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, -- cgit v1.2.3 From a43ff00c7c2981426d06b3621bbf62476aa5ec0d Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 11 Jun 2007 09:59:27 +0200 Subject: Fix support for explicit disabling of syncing with the origin Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 ++ 1 file changed, 2 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 815d8bbb5d..ff56181310 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1028,6 +1028,8 @@ class P4Sync(Command): self.knownBranches = {} self.initialParents = {} 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/" -- cgit v1.2.3 From 6581de096e8323385b8ec7d467e91927a80ce3b9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 11 Jun 2007 10:01:58 +0200 Subject: Write out the options tag in the log message of imports only if we actually have options Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index ff56181310..e380c149b4 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -765,12 +765,11 @@ class P4Sync(Command): self.gitStream.write("data < 0: + self.gitStream.write(": options = %s" % details['options']) + self.gitStream.write("]\nEOT\n\n") if len(parent) > 0: if self.verbose: -- cgit v1.2.3 From c3bf3f1301319faab7344e2d8b5ab10a3d648856 Mon Sep 17 00:00:00 2001 From: Kevin Green Date: Mon, 11 Jun 2007 16:48:07 -0400 Subject: git-p4: check for existence of repo dir before trying to create When using git-p4 in this manner: git-p4 clone //depot/path/project myproject If "myproject" already exists as a dir, but not a valid git repo, it fails to create the directory. Signed-off-by: Kevin Green --- contrib/fast-import/git-p4 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e380c149b4..cababc7fc8 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1400,7 +1400,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" -- cgit v1.2.3 From a9d1a27af1f1c997eeef67aed54136ae83355bb9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 11 Jun 2007 23:28:03 +0200 Subject: Provide some information for single branch imports where the commits go Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index cababc7fc8..6c199296d3 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1175,7 +1175,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" @@ -1252,6 +1252,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 -- cgit v1.2.3 From e6b711f00e4578eb4b2127af12f73a5fa438f948 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 11 Jun 2007 23:40:25 +0200 Subject: git-p4 submit: Fix missing quotes around p4 commands to make them work with spaces in filenames Noticed by Alex Riesen Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6c199296d3..21f9ba7e07 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -391,10 +391,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: -- cgit v1.2.3 From 27d2d8119bf985a0b59152737316f04f871e03f7 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 12 Jun 2007 14:31:59 +0200 Subject: Moved the code from git-p4 submit to figure out the upstream branch point into a separate helper method. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 21f9ba7e07..1c7db11529 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -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]" @@ -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 -- cgit v1.2.3 From d7e3868cdfdc73c3de15296ecf32138a8308c07e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 12 Jun 2007 14:34:46 +0200 Subject: Fix git-p4 rebase to detect the correct upstream branch instead of unconditionally always rebasing on top of remotes/p4/master Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 1c7db11529..1168704be4 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1361,9 +1361,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 -- cgit v1.2.3 From cbae7080a7fe0586255e85e1d14f1011260e8eee Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Tue, 12 Jun 2007 15:27:52 +0200 Subject: Only use double quotes on Windows Signed-off-by: Marius Storm-Olsen --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 1168704be4..b3f27fe90f 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -180,7 +180,7 @@ def findUpstreamBranchPoint(): parent = parent + 1 continue - names = read_pipe_lines("git name-rev '--refs=refs/remotes/p4/*' '%s'" % commit) + names = read_pipe_lines("git name-rev \"--refs=refs/remotes/p4/*\" \"%s\"" % commit) if len(names) <= 0: continue -- cgit v1.2.3 From 3c699645f589612065b048ecde45a4ea293dc75f Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 16 Jun 2007 13:09:21 +0200 Subject: Fix initial multi-branch import. The list of existing p4 branches in git wasn't initialized. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 1 + 1 file changed, 1 insertion(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index b3f27fe90f..e527734be5 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -637,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 -- cgit v1.2.3 From da4a660161cfe9d04c0849d77fa460c6ffc6503c Mon Sep 17 00:00:00 2001 From: Benjamin Sergeant Date: Fri, 8 Jun 2007 11:13:55 -0700 Subject: git-p4 fails when cloning a p4 depo. A perforce command with all the files in the repo is generated to get all the file content. Here is a patch to break it into multiple successive perforce command who uses 4K of parameter max, and collect the output for later. It works, but not for big depos, because the whole perforce depo content is stored in memory in P4Sync.run(), and it looks like mine is bigger than 2 Gigs, so I had to kill the process. [Simon: I added the bit about using SC_ARG_MAX, as suggested by Han-Wen] Signed-off-by: Benjamin Sergeant Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e527734be5..d1f8d3b78d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -711,9 +711,23 @@ class P4Sync(Command): if not files: return - filedata = p4CmdList('print %s' % ' '.join(['"%s#%s"' % (f['path'], - f['rev']) - for f in files])) + # We cannot put all the files on the command line + # OS have limitations on the max lenght of arguments + # POSIX says it's 4096 bytes, default for Linux seems to be 130 K. + # and all OS from the table below seems to be higher than POSIX. + # See http://www.in-ulm.de/~mascheck/various/argmax/ + argmax = min(4000, os.sysconf('SC_ARG_MAX')) + chunk = '' + filedata = [] + for i in xrange(len(files)): + f = files[i] + chunk += '"%s#%s" ' % (f['path'], f['rev']) + if len(chunk) > argmax or i == len(files)-1: + data = p4CmdList('print %s' % chunk) + if "p4ExitCode" in data[0]: + die("Problems executing p4. Error: [%d]." % (data[0]['p4ExitCode'])); + filedata.extend(data) + chunk = '' j = 0; contents = {} -- cgit v1.2.3 From 6555b2ccfe63913b3e5c8b02e117f0f476307ca2 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 17 Jun 2007 11:25:34 +0200 Subject: Fix the branch mapping detection to be independent from the order of the "p4 branches" output. Collect "unknown" source branches separately and register them at the end. Also added a minor speed up to splitFilesIntoBranches by breaking out of the loop through all branches when it's safe. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d1f8d3b78d..3b6d8a09d1 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -700,6 +700,7 @@ class P4Sync(Command): if branch not in branches: branches[branch] = [] branches[branch].append(file) + break return branches @@ -938,6 +939,8 @@ class P4Sync(Command): return p def getBranchMapping(self): + lostAndFoundBranches = set() + for info in p4CmdList("branches"): details = p4Cmd("branch -o %s" % info["branch"]) viewIdx = 0 @@ -953,10 +956,17 @@ class P4Sync(Command): if source.startswith(self.depotPaths[0]) and destination.startswith(self.depotPaths[0]): source = source[len(self.depotPaths[0]):-4] destination = destination[len(self.depotPaths[0]):-4] - if destination not in self.knownBranches: - self.knownBranches[destination] = source + + self.knownBranches[destination] = source + + lostAndFoundBranches.discard(destination) + if source not in self.knownBranches: - self.knownBranches[source] = source + lostAndFoundBranches.add(source) + + + for branch in lostAndFoundBranches: + self.knownBranches[branch] = branch def listExistingP4GitBranches(self): self.p4BranchesInGit = [] -- cgit v1.2.3 From 1a2edf4e8dff05fea66daf82c675cfab673c1242 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 17 Jun 2007 15:10:24 +0200 Subject: Warn about conflicting p4 branch mappings and use the first one found. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3b6d8a09d1..2040591383 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -957,6 +957,12 @@ class P4Sync(Command): source = source[len(self.depotPaths[0]):-4] destination = destination[len(self.depotPaths[0]):-4] + if destination in self.knownBranches: + if not self.silent: + print "p4 branch %s defines a mapping from %s to %s" % (info["branch"], source, destination) + print "but there exists another mapping from %s to %s already!" % (self.knownBranches[destination], destination) + continue + self.knownBranches[destination] = source lostAndFoundBranches.discard(destination) -- cgit v1.2.3 From 09d89de2e31ed4d62b6ff344e9ad9ef29550121b Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 20 Jun 2007 23:10:28 +0200 Subject: Added git-p4 branches command that shows the mapping of perforce depot paths to imported git branches. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 2040591383..16de15c4ea 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1465,6 +1465,31 @@ class P4Clone(P4Sync): return True +class P4Branches(Command): + def __init__(self): + Command.__init__(self) + self.options = [ ] + self.description = ("Shows the git branches that hold imports and their " + + "corresponding perforce depot paths") + self.verbose = False + + def run(self, args): + cmdline = "git rev-parse --symbolic " + cmdline += " --remotes" + + for line in read_pipe_lines(cmdline): + line = line.strip() + + if not line.startswith('p4/') or line == "p4/HEAD": + continue + branch = line + + log = extractLogMessageFromGitCommit("refs/remotes/%s" % branch) + settings = extractSettingsGitLog(log) + + print "%s <= %s (%s)" % (branch, ",".join(settings["depot-paths"]), settings["change"]) + return True + class HelpFormatter(optparse.IndentedHelpFormatter): def __init__(self): optparse.IndentedHelpFormatter.__init__(self) @@ -1489,7 +1514,8 @@ commands = { "sync" : P4Sync, "rebase" : P4Rebase, "clone" : P4Clone, - "rollback" : P4RollBack + "rollback" : P4RollBack, + "branches" : P4Branches } -- cgit v1.2.3 From 9ceab36375dfd4088b265033e1de9225b3527cab Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 22 Jun 2007 00:01:57 +0200 Subject: Make it possible to specify the HEAD for the internal findUpstreamBranchPoint function. This isn't used right now in git-p4 but I use it in an external script that loads git-p4 as module. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 16de15c4ea..54a05eb99c 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -168,12 +168,12 @@ def gitBranchExists(branch): def gitConfig(key): return read_pipe("git config %s" % key, ignore_error=True).strip() -def findUpstreamBranchPoint(): +def findUpstreamBranchPoint(head = "HEAD"): settings = None branchPoint = "" parent = 0 while parent < 65535: - commit = "HEAD~%s" % parent + commit = head + "~%s" % parent log = extractLogMessageFromGitCommit(commit) settings = extractSettingsGitLog(log) if not settings.has_key("depot-paths"): -- cgit v1.2.3 From 48b4c3d5ab1610c6dc0198fe94334d78e8a82e16 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Fri, 13 Jul 2007 14:39:05 +0200 Subject: Fix git-p4 on Windows to not use the Posix sysconf function. Add condition for Windows, since it doesn't support the os.sysconf module. We hardcode the commandline limit to 2K, as that should work on most Windows platforms. Signed-off-by: Marius Storm-Olsen Acked-by: Simon Hausmann Signed-off-by: Shawn O. Pearce --- contrib/fast-import/git-p4 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 54a05eb99c..d877150f41 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -717,7 +717,11 @@ class P4Sync(Command): # POSIX says it's 4096 bytes, default for Linux seems to be 130 K. # and all OS from the table below seems to be higher than POSIX. # See http://www.in-ulm.de/~mascheck/various/argmax/ - argmax = min(4000, os.sysconf('SC_ARG_MAX')) + if (self.isWindows): + argmax = 2000 + else: + argmax = min(4000, os.sysconf('SC_ARG_MAX')) + chunk = '' filedata = [] for i in xrange(len(files)): -- cgit v1.2.3 From 9f90c7335e223c26d19f3c01a6d89e6c0cd8b827 Mon Sep 17 00:00:00 2001 From: Scott Lamb Date: Sun, 15 Jul 2007 20:58:10 -0700 Subject: git-p4: use subprocess in p4CmdList This allows bidirectional piping - useful for "-x -" to avoid commandline arguments - and is a step toward bypassing the shell. Signed-off-by: Scott Lamb Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d877150f41..d93e656155 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -63,21 +63,34 @@ def system(cmd): if os.system(cmd) != 0: die("command failed: %s" % cmd) -def p4CmdList(cmd): +def p4CmdList(cmd, stdin=None, stdin_mode='w+b'): cmd = "p4 -G %s" % cmd if verbose: sys.stderr.write("Opening pipe: %s\n" % cmd) - pipe = os.popen(cmd, "rb") + + # Use a temporary file to avoid deadlocks without + # subprocess.communicate(), which would put another copy + # of stdout into memory. + stdin_file = None + if stdin is not None: + stdin_file = tempfile.TemporaryFile(prefix='p4-stdin', mode=stdin_mode) + stdin_file.write(stdin) + stdin_file.flush() + stdin_file.seek(0) + + p4 = subprocess.Popen(cmd, shell=True, + stdin=stdin_file, + stdout=subprocess.PIPE) result = [] try: while True: - entry = marshal.load(pipe) + entry = marshal.load(p4.stdout) result.append(entry) except EOFError: pass - exitCode = pipe.close() - if exitCode != None: + exitCode = p4.wait() + if exitCode != 0: entry = {} entry["p4ExitCode"] = exitCode result.append(entry) -- cgit v1.2.3 From 788001908c8960daa162c32baf3dc0f9ad1c16f8 Mon Sep 17 00:00:00 2001 From: Scott Lamb Date: Sun, 15 Jul 2007 20:58:11 -0700 Subject: git-p4: input to "p4 files" by stdin instead of arguments This approach, suggested by Alex Riesen, bypasses the need for xargs-style argument list handling. The handling in question looks broken in a corner case with SC_ARG_MAX=4096 and final argument over 96 characters. Signed-off-by: Scott Lamb Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d93e656155..54053e3f3d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -725,27 +725,13 @@ class P4Sync(Command): if not files: return - # We cannot put all the files on the command line - # OS have limitations on the max lenght of arguments - # POSIX says it's 4096 bytes, default for Linux seems to be 130 K. - # and all OS from the table below seems to be higher than POSIX. - # See http://www.in-ulm.de/~mascheck/various/argmax/ - if (self.isWindows): - argmax = 2000 - else: - argmax = min(4000, os.sysconf('SC_ARG_MAX')) - - chunk = '' - filedata = [] - for i in xrange(len(files)): - f = files[i] - chunk += '"%s#%s" ' % (f['path'], f['rev']) - if len(chunk) > argmax or i == len(files)-1: - data = p4CmdList('print %s' % chunk) - if "p4ExitCode" in data[0]: - die("Problems executing p4. Error: [%d]." % (data[0]['p4ExitCode'])); - filedata.extend(data) - chunk = '' + filedata = p4CmdList('-x - print', + stdin='\n'.join(['%s#%s' % (f['path'], f['rev']) + for f in files]), + stdin_mode='w+') + if "p4ExitCode" in filedata[0]: + die("Problems executing p4. Error: [%d]." + % (filedata[0]['p4ExitCode'])); j = 0; contents = {} -- cgit v1.2.3 From 062410bb9d6553e6bc4f8fa7f0cab1ed63b75628 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 18 Jul 2007 10:56:31 +0200 Subject: git-p4: Cleanup, make listExistingP4Branches a global function for later use. Signed-off-by: Simon Hausmann Signed-off-by: Marius Storm-Olsen --- contrib/fast-import/git-p4 | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 54053e3f3d..d4a2f14311 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -181,6 +181,29 @@ def gitBranchExists(branch): def gitConfig(key): return read_pipe("git config %s" % key, ignore_error=True).strip() +def p4BranchesInGit(branchesAreInRemotes = True): + branches = {} + + cmdline = "git rev-parse --symbolic " + if branchesAreInRemotes: + cmdline += " --remotes" + else: + cmdline += " --branches" + + for line in read_pipe_lines(cmdline): + line = line.strip() + + ## only import to p4/ + if not line.startswith('p4/') or line == "p4/HEAD": + continue + branch = line + + # strip off p4 + branch = re.sub ("^p4/", "", line) + + branches[branch] = parseRevision(line) + return branches + def findUpstreamBranchPoint(head = "HEAD"): settings = None branchPoint = "" -- cgit v1.2.3 From 86506fe54c8e9e5f75a73956840497e3e5744f86 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 18 Jul 2007 12:40:12 +0200 Subject: git-p4: Fix upstream branch detection for submit/rebase with multiple branches. Don't use git name-rev to locate the upstream git-p4 branch for rebase and submit but instead locate the branch by comparing the depot paths. name-rev may produce results like wrongbranch~12 as it uses the first match. Signed-off-by: Simon Hausmann Signed-off-by: Marius Storm-Olsen --- contrib/fast-import/git-p4 | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d4a2f14311..a65f53a47b 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -205,26 +205,31 @@ def p4BranchesInGit(branchesAreInRemotes = True): return branches def findUpstreamBranchPoint(head = "HEAD"): + branches = p4BranchesInGit() + # map from depot-path to branch name + branchByDepotPath = {} + for branch in branches.keys(): + tip = branches[branch] + log = extractLogMessageFromGitCommit(tip) + settings = extractSettingsGitLog(log) + if settings.has_key("depot-paths"): + paths = ",".join(settings["depot-paths"]) + branchByDepotPath[paths] = "remotes/p4/" + branch + 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 + if settings.has_key("depot-paths"): + paths = ",".join(settings["depot-paths"]) + if branchByDepotPath.has_key(paths): + return [branchByDepotPath[paths], settings] - # strip away the beginning of 'HEAD~42 refs/remotes/p4/foo' - branchPoint = names[0].strip()[len(commit) + 1:] - break + parent = parent + 1 - return [branchPoint, settings] + return ["", settings] class Command: def __init__(self): -- cgit v1.2.3 From 144ff46b196e49fd52b2ecf0aaa1db4c190393b9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 18 Jul 2007 17:27:50 +0200 Subject: git-p4: Cleanup, used common function for listing imported p4 branches Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index a65f53a47b..e3404ca853 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1006,27 +1006,11 @@ class P4Sync(Command): self.knownBranches[branch] = branch def listExistingP4GitBranches(self): - self.p4BranchesInGit = [] - - cmdline = "git rev-parse --symbolic " - if self.importIntoRemotes: - cmdline += " --remotes" - else: - cmdline += " --branches" - - for line in read_pipe_lines(cmdline): - line = line.strip() - - ## only import to p4/ - if not line.startswith('p4/') or line == "p4/HEAD": - continue - branch = line - - # strip off p4 - branch = re.sub ("^p4/", "", line) - - self.p4BranchesInGit.append(branch) - self.initialParents[self.refPrefix + branch] = parseRevision(line) + # branches holds mapping from name to commit + branches = p4BranchesInGit(self.importIntoRemotes) + self.p4BranchesInGit = branches.keys() + for branch in branches.keys(): + self.initialParents[self.refPrefix + branch] = branches[branch] def createOrUpdateBranchesFromOrigin(self): if not self.silent: -- cgit v1.2.3 From b2d2d16af7ff686fb96d344daaf49653fd67366a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 25 Jul 2007 09:31:38 +0200 Subject: git-p4: Fix p4 user cache population on Windows. Fall back to USERPROFILE if HOME isn't set. Signed-off-by: Simon Hausmann Signed-off-by: Marius Storm-Olsen Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e3404ca853..1f5a56ee7f 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -901,7 +901,8 @@ class P4Sync(Command): % (labelDetails["label"], change)) def getUserCacheFilename(self): - return os.environ["HOME"] + "/.gitp4-usercache.txt" + home = os.environ.get("HOME", os.environ.get("USERPROFILE")) + return home + "/.gitp4-usercache.txt" def getUserMapFromPerforceServer(self): if self.userMapFromPerforceServer: -- cgit v1.2.3 From a4eba020f96e1b85f856a992782b8bb2bab6a719 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Mon, 23 Jul 2007 15:51:49 -0700 Subject: Sort output of "p4 change" in incremental import before further processing P4 change outputs the changes sorted for each directory separately. We want the global ordering on the changes, hence we sort. Signed-off-by: Han-Wen Nienhuys Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 1f5a56ee7f..f00c691a7b 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1296,7 +1296,7 @@ class P4Sync(Command): changeNum = line.split(" ")[1] changes.append(changeNum) - changes.reverse() + changes.sort() if len(self.maxChanges) > 0: changes = changes[0:min(int(self.maxChanges), len(changes))] -- cgit v1.2.3 From 7fcff9def564fae7de5d2a34a095229a999b80b0 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Mon, 23 Jul 2007 15:56:37 -0700 Subject: Fix style nit in Python slicing. Python slices start at 0 by default. Signed-off-by: Han-Wen Nienhuys Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index f00c691a7b..41e86e76cb 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1181,11 +1181,11 @@ class P4Sync(Command): elif ',' not in self.changeRange: self.revision = self.changeRange self.changeRange = "" - p = p[0:atIdx] + p = p[:atIdx] elif p.find("#") != -1: hashIdx = p.index("#") self.revision = p[hashIdx:] - p = p[0:hashIdx] + p = p[:hashIdx] elif self.previousDepotPaths == []: self.revision = "#head" @@ -1299,7 +1299,7 @@ class P4Sync(Command): changes.sort() if len(self.maxChanges) > 0: - changes = changes[0:min(int(self.maxChanges), len(changes))] + changes = changes[:min(int(self.maxChanges), len(changes))] if len(changes) == 0: if not self.silent: -- cgit v1.2.3 From 74276ec6f2d2123714066cee24b26a629930e7a8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 7 Aug 2007 12:28:00 +0200 Subject: git-p4: Fix support for symlinks. Detect symlinks as file type, set the git file mode accordingly and strip off the trailing newline in the p4 print output. Make the mode handling a bit more readable at the same time. Signed-off-by: Simon Hausmann Acked-by: Brian Swetland Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 41e86e76cb..3cbb2da221 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -839,16 +839,20 @@ class P4Sync(Command): if file["action"] == "delete": self.gitStream.write("D %s\n" % relPath) else: - mode = 644 - if file["type"].startswith("x"): - mode = 755 - data = file['data'] + mode = "644" + if file["type"].startswith("x"): + mode = "755" + elif file["type"] == "symlink": + mode = "120000" + # p4 print on a symlink contains "target\n", so strip it off + data = data[:-1] + if self.isWindows and file["type"].endswith("text"): data = data.replace("\r\n", "\n") - self.gitStream.write("M %d inline %s\n" % (mode, relPath)) + self.gitStream.write("M %s inline %s\n" % (mode, relPath)) self.gitStream.write("data %s\n" % len(data)) self.gitStream.write(data) self.gitStream.write("\n") -- cgit v1.2.3 From ea99c3ae0e2cecaa0950532385319d60c59e97e0 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 8 Aug 2007 17:06:55 +0200 Subject: git-p4: Fix git-p4 submit to include only changed files in the perforce submit template. Parse the files section in the "p4 change -o" output and remove lines with file changes in unrelated depot paths. Signed-off-by: Simon Hausmann Signed-off-by: Marius Storm-Olsen Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3cbb2da221..805d632a68 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -390,6 +390,30 @@ class P4Submit(Command): return result + def prepareSubmitTemplate(self): + # remove lines in the Files section that show changes to files outside the depot path we're committing into + template = "" + inFilesSection = False + for line in read_pipe_lines("p4 change -o"): + if inFilesSection: + if line.startswith("\t"): + # path starts and ends with a tab + path = line[1:] + lastTab = path.rfind("\t") + if lastTab != -1: + path = path[:lastTab] + if not path.startswith(self.depotPath): + continue + else: + inFilesSection = False + else: + if line.startswith("Files:"): + inFilesSection = True + + template += line + + return template + def applyCommit(self, id): if self.directSubmit: print "Applying local change in working directory/index" @@ -467,7 +491,7 @@ class P4Submit(Command): logMessage = logMessage.replace("\n", "\r\n") logMessage = logMessage.strip() - template = read_pipe("p4 change -o") + template = self.prepareSubmitTemplate() if self.interactive: submitTemplate = self.prepareLogMessage(template, logMessage) @@ -558,24 +582,24 @@ class P4Submit(Command): return False [upstream, settings] = findUpstreamBranchPoint() - depotPath = settings['depot-paths'][0] + self.depotPath = settings['depot-paths'][0] if len(self.origin) == 0: self.origin = upstream if self.verbose: print "Origin branch is " + self.origin - if len(depotPath) == 0: + if len(self.depotPath) == 0: print "Internal error: cannot locate perforce depot path from existing branches" sys.exit(128) - self.clientPath = p4Where(depotPath) + self.clientPath = p4Where(self.depotPath) if len(self.clientPath) == 0: - print "Error: Cannot locate perforce checkout of %s in client view" % depotPath + print "Error: Cannot locate perforce checkout of %s in client view" % self.depotPath sys.exit(128) - print "Perforce checkout for depot path %s located at %s" % (depotPath, self.clientPath) + print "Perforce checkout for depot path %s located at %s" % (self.depotPath, self.clientPath) self.oldWorkingDirectory = os.getcwd() if self.directSubmit: -- cgit v1.2.3 From 7da660f4372f4113184f782634c0fafb2cf46cef Mon Sep 17 00:00:00 2001 From: "Reece H. Dunn" Date: Mon, 13 Aug 2007 19:40:50 +0100 Subject: git-p4: Fix the sorting of changelists when cloning a Perforce repository. When performing a git-p4 clone operation on a Perforce repository, where the changelists change in order of magnitude (e.g. 100 to 1000), the set of changes to import from is not sorted properly. This is because the data in the list is strings not integers. The other place where this is done already converts the value to an integer, so it is not affected. Acked-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 805d632a68..6d0106237a 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1322,7 +1322,7 @@ class P4Sync(Command): for line in output: changeNum = line.split(" ")[1] - changes.append(changeNum) + changes.append(int(changeNum)) changes.sort() -- cgit v1.2.3 From 5ca4461728adadf22b5b8833693702ab09e556db Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 24 Aug 2007 17:44:16 +0200 Subject: git-p4: Make 'git-p4 branches' work after an initial clone with git clone from an origin-updated repository. After a clone with "git clone" of a repository the p4 branches are only in remotes/origin/p4/* and not in remotes/p4/*. Separate the code for detection and creation out of the P4Sync command class into standalone methods and use them from the P4Branches command. Signed-off-by: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 104 ++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 49 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6d0106237a..b571e30473 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -231,6 +231,56 @@ def findUpstreamBranchPoint(head = "HEAD"): return ["", settings] +def createOrUpdateBranchesFromOrigin(localRefPrefix = "refs/remotes/p4/", silent=True): + if not silent: + print ("Creating/updating branch(es) in %s based on origin branch(es)" + % localRefPrefix) + + originPrefix = "origin/p4/" + + for line in read_pipe_lines("git rev-parse --symbolic --remotes"): + line = line.strip() + if (not line.startswith(originPrefix)) or line.endswith("HEAD"): + continue + + headName = line[len(originPrefix):] + remoteHead = localRefPrefix + headName + originHead = line + + original = extractSettingsGitLog(extractLogMessageFromGitCommit(originHead)) + if (not original.has_key('depot-paths') + or not original.has_key('change')): + continue + + update = False + if not gitBranchExists(remoteHead): + if verbose: + print "creating %s" % remoteHead + update = True + else: + 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)) + update = True + else: + 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 originP4BranchesExist(): + return gitBranchExists("origin") or gitBranchExists("origin/p4") or gitBranchExists("origin/p4/master") + class Command: def __init__(self): self.usage = "usage: %prog [options]" @@ -1041,53 +1091,6 @@ class P4Sync(Command): for branch in branches.keys(): self.initialParents[self.refPrefix + branch] = branches[branch] - def createOrUpdateBranchesFromOrigin(self): - if not self.silent: - 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(originPrefix)) or line.endswith("HEAD"): - continue - - headName = line[len(originPrefix):] - remoteHead = self.refPrefix + headName - originHead = line - - original = extractSettingsGitLog(extractLogMessageFromGitCommit(originHead)) - if (not original.has_key('depot-paths') - or not original.has_key('change')): - continue - - update = False - if not gitBranchExists(remoteHead): - if self.verbose: - print "creating %s" % remoteHead - update = True - else: - 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)) - update = True - else: - 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: @@ -1108,7 +1111,7 @@ class P4Sync(Command): # map from branch depot path to parent branch self.knownBranches = {} self.initialParents = {} - self.hasOrigin = gitBranchExists("origin") or gitBranchExists("origin/p4") or gitBranchExists("origin/p4/master") + self.hasOrigin = originP4BranchesExist() if not self.syncWithOrigin: self.hasOrigin = False @@ -1135,7 +1138,7 @@ class P4Sync(Command): # merge with previous imports, if possible. if args == []: if self.hasOrigin: - self.createOrUpdateBranchesFromOrigin() + createOrUpdateBranchesFromOrigin(self.refPrefix, self.silent) self.listExistingP4GitBranches() if len(self.p4BranchesInGit) > 1: @@ -1518,6 +1521,9 @@ class P4Branches(Command): self.verbose = False def run(self, args): + if originP4BranchesExist(): + createOrUpdateBranchesFromOrigin() + cmdline = "git rev-parse --symbolic " cmdline += " --remotes" -- cgit v1.2.3 From 0058a33a8eb5a8bfcfc5f5e769a2517cff4b73f1 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 24 Aug 2007 17:46:16 +0200 Subject: git-p4: Fix warnings about non-existant refs/remotes/p4/HEAD ref when running git-p4 sync the first time after a git clone. Don't create the p4/HEAD symbolic ref if p4/master doesn't exist yet. Signed-off-by: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index b571e30473..55778c5775 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1131,7 +1131,7 @@ class P4Sync(Command): system("git update-ref %s refs/heads/p4" % self.branch) system("git branch -D p4"); # create it /after/ importing, when master exists - if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes: + if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes and gitBranchExists(self.branch): system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch)) # TODO: should always look at previous commits, -- cgit v1.2.3 From 31f9ec129ef37e50b5cacf26a2ebcb5420fcdc5e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 21 Aug 2007 11:53:02 +0200 Subject: git-p4: Always call 'p4 sync ...' before submitting to Perforce. Acked-by: Marius Storm-Olsen Acked-by: Thiago Macieira --- contrib/fast-import/git-p4 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 55778c5775..3728cbf9aa 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -664,9 +664,8 @@ class P4Submit(Command): f.close(); os.chdir(self.clientPath) - response = raw_input("Do you want to sync %s with p4 sync? [y]es/[n]o " % self.clientPath) - if response == "y" or response == "yes": - system("p4 sync ...") + print "Syncronizing p4 checkout..." + system("p4 sync ...") if self.reset: self.firstTime = True -- cgit v1.2.3 From 14594f4b5747e51b051f647f6430089e6664e77d Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 22 Aug 2007 09:07:15 +0200 Subject: git-p4: After submission to p4 always synchronize from p4 again (into refs/remotes). Whether to rebase HEAD or not is still left as question to the end-user. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3728cbf9aa..16e0a7bc81 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -704,10 +704,14 @@ class P4Submit(Command): else: print "All changes applied!" os.chdir(self.oldWorkingDirectory) - response = raw_input("Do you want to sync from Perforce now using git-p4 rebase? [y]es/[n]o ") + + sync = P4Sync() + sync.run([]) + + response = raw_input("Do you want to rebase current HEAD from Perforce now using git-p4 rebase? [y]es/[n]o ") if response == "y" or response == "yes": rebase = P4Rebase() - rebase.run([]) + rebase.rebase() os.remove(self.configFile) return True @@ -1439,6 +1443,9 @@ class P4Rebase(Command): sync = P4Sync() sync.run([]) + return self.rebase() + + def rebase(self): [upstream, settings] = findUpstreamBranchPoint() if len(upstream) == 0: die("Cannot find upstream branchpoint for rebase") -- cgit v1.2.3 From 4f6432d8cc6ebdcdc366cf67ab39e8125c449d80 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 26 Aug 2007 15:56:36 +0200 Subject: git-p4: Cleanup; moved the code for getting a sorted list of p4 changes for a list of given depot paths into a standalone method. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 16e0a7bc81..e9feb7498c 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -281,6 +281,19 @@ 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): + assert depotPaths + output = read_pipe_lines("p4 changes " + ' '.join (["%s...%s" % (p, changeRange) + for p in depotPaths])) + + changes = [] + for line in output: + changeNum = line.split(" ")[1] + changes.append(int(changeNum)) + + changes.sort() + return changes + class Command: def __init__(self): self.usage = "usage: %prog [options]" @@ -1322,15 +1335,7 @@ class P4Sync(Command): if self.verbose: print "Getting p4 changes for %s...%s" % (', '.join(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] - changes.append(int(changeNum)) - - changes.sort() + changes = p4ChangesForPaths(self.depotPaths, self.changeRange) if len(self.maxChanges) > 0: changes = changes[:min(int(self.maxChanges), len(changes))] -- cgit v1.2.3 From e87f37ae42dad89b39620c234fc29c94529a4d07 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 26 Aug 2007 16:00:52 +0200 Subject: git-p4: Cleanup; moved the code to import a list of p4 changes using fast-import into a separate member function of P4Sync. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 140 +++++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 69 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e9feb7498c..c00702c895 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1118,6 +1118,76 @@ class P4Sync(Command): self.keepRepoPath = (d.has_key('options') and ('keepRepoPath' in d['options'])) + def importChanges(self, changes): + 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))) + sys.stdout.flush() + cnt = cnt + 1 + + try: + if self.detectBranches: + branches = self.splitFilesIntoBranches(description) + for branch in branches.keys(): + ## HACK --hwn + branchPrefix = self.depotPaths[0] + branch + "/" + + parent = "" + + filesForCommit = branches[branch] + + if self.verbose: + print "branch is %s" % branch + + self.updatedBranches.add(branch) + + if branch not in self.createdBranches: + self.createdBranches.add(branch) + parent = self.knownBranches[branch] + if parent == branch: + parent = "" + elif self.verbose: + print "parent determined through known branches: %s" % parent + + # main branch? use master + 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 + if len(parent) > 0: + parent = self.refPrefix + parent + + if self.verbose: + print "looking for initial parent for %s; current parent is %s" % (branch, parent) + + if len(parent) == 0 and branch in self.initialParents: + parent = self.initialParents[branch] + del self.initialParents[branch] + + self.commit(description, filesForCommit, branch, [branchPrefix], parent) + else: + files = self.extractFilesFromCommit(description) + self.commit(description, files, self.branch, self.depotPaths, + self.initialParent) + self.initialParent = "" + except IOError: + print self.gitError.read() + sys.exit(1) + def run(self, args): self.depotPaths = [] self.changeRange = "" @@ -1350,74 +1420,7 @@ class P4Sync(Command): self.updatedBranches = set() - 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))) - sys.stdout.flush() - cnt = cnt + 1 - - try: - if self.detectBranches: - branches = self.splitFilesIntoBranches(description) - for branch in branches.keys(): - ## HACK --hwn - branchPrefix = self.depotPaths[0] + branch + "/" - - parent = "" - - filesForCommit = branches[branch] - - if self.verbose: - print "branch is %s" % branch - - self.updatedBranches.add(branch) - - if branch not in self.createdBranches: - self.createdBranches.add(branch) - parent = self.knownBranches[branch] - if parent == branch: - parent = "" - elif self.verbose: - print "parent determined through known branches: %s" % parent - - # main branch? use master - 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 - if len(parent) > 0: - parent = self.refPrefix + parent - - if self.verbose: - print "looking for initial parent for %s; current parent is %s" % (branch, parent) - - if len(parent) == 0 and branch in self.initialParents: - parent = self.initialParents[branch] - del self.initialParents[branch] - - self.commit(description, filesForCommit, branch, [branchPrefix], parent) - else: - files = self.extractFilesFromCommit(description) - self.commit(description, files, self.branch, self.depotPaths, - self.initialParent) - self.initialParent = "" - except IOError: - print self.gitError.read() - sys.exit(1) + self.importChanges(changes) if not self.silent: print "" @@ -1427,7 +1430,6 @@ class P4Sync(Command): sys.stdout.write("%s " % b) sys.stdout.write("\n") - self.gitStream.close() if importProcess.wait() != 0: die("fast-import failed: %s" % self.gitError.read()) -- cgit v1.2.3 From 1c49fc197bd05a4c2ed602efcdbe277ef798813a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 26 Aug 2007 16:04:34 +0200 Subject: git-p4: Cleanup; Turn self.revision into a function local variable (it's not used anywhere outside the function). Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index c00702c895..d7c5becc0e 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1285,7 +1285,7 @@ class P4Sync(Command): self.depotPaths = sorted(args) - self.revision = "" + revision = "" self.users = {} newPaths = [] @@ -1296,15 +1296,15 @@ class P4Sync(Command): if self.changeRange == "@all": self.changeRange = "" elif ',' not in self.changeRange: - self.revision = self.changeRange + revision = self.changeRange self.changeRange = "" p = p[:atIdx] elif p.find("#") != -1: hashIdx = p.index("#") - self.revision = p[hashIdx:] + revision = p[hashIdx:] p = p[:hashIdx] elif self.previousDepotPaths == []: - self.revision = "#head" + revision = "#head" p = re.sub ("\.\.\.$", "", p) if not p.endswith("/"): @@ -1345,19 +1345,19 @@ class P4Sync(Command): self.gitStream = importProcess.stdin self.gitError = importProcess.stderr - if self.revision: - print "Doing initial import of %s from revision %s into %s" % (' '.join(self.depotPaths), self.revision, self.branch) + if revision: + print "Doing initial import of %s from revision %s into %s" % (' '.join(self.depotPaths), 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" - % (' '.join(self.depotPaths), self.revision)) - details["change"] = self.revision + % (' '.join(self.depotPaths), revision)) + details["change"] = revision newestRevision = 0 fileCnt = 0 for info in p4CmdList("files " + ' '.join(["%s...%s" - % (p, self.revision) + % (p, revision) for p in self.depotPaths])): if info['code'] == 'error': -- cgit v1.2.3 From c208a24310582d9cf337b66f41a0d7a9fe106bb4 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 26 Aug 2007 16:07:18 +0200 Subject: git-p4: Cleanup; moved the code for the initial #head or revision import into a separate function, out of P4Sync.run. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 87 ++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 42 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d7c5becc0e..2c67190ffc 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1188,6 +1188,50 @@ class P4Sync(Command): print self.gitError.read() sys.exit(1) + def importHeadRevision(self, revision): + print "Doing initial import of %s from revision %s into %s" % (' '.join(self.depotPaths), 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" + % (' '.join(self.depotPaths), revision)) + details["change"] = revision + newestRevision = 0 + + fileCnt = 0 + for info in p4CmdList("files " + + ' '.join(["%s...%s" + % (p, revision) + for p in self.depotPaths])): + + if info['code'] == 'error': + sys.stderr.write("p4 returned an error: %s\n" + % info['data']) + sys.exit(1) + + + change = int(info["change"]) + if change > newestRevision: + newestRevision = change + + if info["action"] == "delete": + # don't increase the file cnt, otherwise details["depotFile123"] will have gaps! + #fileCnt = fileCnt + 1 + continue + + for prop in ["depotFile", "rev", "action", "type" ]: + details["%s%s" % (prop, fileCnt)] = info[prop] + + fileCnt = fileCnt + 1 + + details["change"] = newestRevision + self.updateOptionDict(details) + try: + 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() + + def run(self, args): self.depotPaths = [] self.changeRange = "" @@ -1346,48 +1390,7 @@ class P4Sync(Command): self.gitError = importProcess.stderr if revision: - print "Doing initial import of %s from revision %s into %s" % (' '.join(self.depotPaths), 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" - % (' '.join(self.depotPaths), revision)) - details["change"] = revision - newestRevision = 0 - - fileCnt = 0 - for info in p4CmdList("files " - + ' '.join(["%s...%s" - % (p, revision) - for p in self.depotPaths])): - - if info['code'] == 'error': - sys.stderr.write("p4 returned an error: %s\n" - % info['data']) - sys.exit(1) - - - change = int(info["change"]) - if change > newestRevision: - newestRevision = change - - if info["action"] == "delete": - # don't increase the file cnt, otherwise details["depotFile123"] will have gaps! - #fileCnt = fileCnt + 1 - continue - - for prop in ["depotFile", "rev", "action", "type" ]: - details["%s%s" % (prop, fileCnt)] = info[prop] - - fileCnt = fileCnt + 1 - - details["change"] = newestRevision - self.updateOptionDict(details) - try: - 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() - + self.importHeadRevision(revision) else: changes = [] -- cgit v1.2.3 From 8134f69c21ff47283d8b3ea3cc5b306727cde256 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 26 Aug 2007 16:44:55 +0200 Subject: git-p4: Cleanup; moved the (duplicated) code for turning a branch into a git ref (for example foo -> refs/remotes/p4//foo) into a separate method. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 2c67190ffc..406bec1a29 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1118,6 +1118,15 @@ class P4Sync(Command): self.keepRepoPath = (d.has_key('options') and ('keepRepoPath' in d['options'])) + def gitRefForBranch(self, branch): + if branch == "main": + return self.refPrefix + "master" + + if len(branch) <= 0: + return branch + + return self.refPrefix + self.projectName + branch + def importChanges(self, changes): cnt = 1 for change in changes: @@ -1153,23 +1162,8 @@ class P4Sync(Command): elif self.verbose: print "parent determined through known branches: %s" % parent - # main branch? use master - 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 - if len(parent) > 0: - parent = self.refPrefix + parent + branch = self.gitRefForBranch(branch) + parent = self.gitRefForBranch(parent) if self.verbose: print "looking for initial parent for %s; current parent is %s" % (branch, parent) -- cgit v1.2.3 From 1ca3d71069620f1438d9f89165a3e69e8d47d302 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 26 Aug 2007 17:36:55 +0200 Subject: git-p4: Added support for automatically importing newly appearing perforce branches. If a change in a p4 "branch" appears that hasn't seen any previous commit and that has a known branch mapping we now try to import it properly. First we find the p4 change of the source branch that the new p4 branch is based on. Then we using git rev-list --bisect to locate the corresponding git commit to that change. Finally we import all changes in the new p4 branch up to the current change and resume with the regular import. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 76 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 406bec1a29..adaaae6633 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1127,6 +1127,67 @@ class P4Sync(Command): return self.refPrefix + self.projectName + branch + def gitCommitByP4Change(self, ref, change): + if self.verbose: + print "looking in ref " + ref + " for change %s using bisect..." % change + + earliestCommit = "" + latestCommit = parseRevision(ref) + + while True: + if self.verbose: + print "trying: earliest %s latest %s" % (earliestCommit, latestCommit) + next = read_pipe("git rev-list --bisect %s %s" % (latestCommit, earliestCommit)).strip() + if len(next) == 0: + if self.verbose: + print "argh" + return "" + log = extractLogMessageFromGitCommit(next) + settings = extractSettingsGitLog(log) + currentChange = int(settings['change']) + if self.verbose: + print "current change %s" % currentChange + + if currentChange == change: + if self.verbose: + print "found %s" % next + return next + + if currentChange < change: + earliestCommit = "^%s" % next + else: + latestCommit = "%s" % next + + return "" + + def importNewBranch(self, branch, maxChange): + # make fast-import flush all changes to disk and update the refs using the checkpoint + # command so that we can try to find the branch parent in the git history + self.gitStream.write("checkpoint\n\n"); + self.gitStream.flush(); + branchPrefix = self.depotPaths[0] + branch + "/" + range = "@1,%s" % maxChange + #print "prefix" + branchPrefix + changes = p4ChangesForPaths([branchPrefix], range) + if len(changes) <= 0: + return False + firstChange = changes[0] + #print "first change in branch: %s" % firstChange + sourceBranch = self.knownBranches[branch] + sourceDepotPath = self.depotPaths[0] + sourceBranch + sourceRef = self.gitRefForBranch(sourceBranch) + #print "source " + sourceBranch + + branchParentChange = int(p4Cmd("changes -m 1 %s...@1,%s" % (sourceDepotPath, firstChange))["change"]) + #print "branch parent: %s" % branchParentChange + gitParent = self.gitCommitByP4Change(sourceRef, branchParentChange) + if len(gitParent) > 0: + self.initialParents[self.gitRefForBranch(branch)] = gitParent + #print "parent git commit: %s" % gitParent + + self.importChanges(changes) + return True + def importChanges(self, changes): cnt = 1 for change in changes: @@ -1159,8 +1220,19 @@ class P4Sync(Command): parent = self.knownBranches[branch] if parent == branch: parent = "" - elif self.verbose: - print "parent determined through known branches: %s" % parent + else: + fullBranch = self.projectName + branch + if fullBranch not in self.p4BranchesInGit: + if not self.silent: + print("\n Importing new branch %s" % fullBranch); + if self.importNewBranch(branch, change - 1): + parent = "" + self.p4BranchesInGit.append(fullBranch) + if not self.silent: + print("\n Resuming with change %s" % change); + + if self.verbose: + print "parent determined through known branches: %s" % parent branch = self.gitRefForBranch(branch) parent = self.gitRefForBranch(parent) -- cgit v1.2.3 From b9fc6ea9efdc988d851666d45d80076839d9c225 Mon Sep 17 00:00:00 2001 From: David Brown Date: Wed, 19 Sep 2007 13:12:48 -0700 Subject: Detect exec bit in more cases. git-p4 was missing the execute bit setting if the file had other attribute bits set. Acked-By: Simon Hausmann --- contrib/fast-import/git-p4 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 55778c5775..65c57ac4d8 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -63,6 +63,14 @@ def system(cmd): if os.system(cmd) != 0: die("command failed: %s" % cmd) +def isP4Exec(kind): + """Determine if a Perforce 'kind' should have execute permission + + 'p4 help filetypes' gives a list of the types. If it starts with 'x', + or x follows one of a few letters. Otherwise, if there is an 'x' after + a plus sign, it is also executable""" + return (re.search(r"(^[cku]?x)|\+.*x", kind) != None) + def p4CmdList(cmd, stdin=None, stdin_mode='w+b'): cmd = "p4 -G %s" % cmd if verbose: @@ -916,7 +924,7 @@ class P4Sync(Command): data = file['data'] mode = "644" - if file["type"].startswith("x"): + if isP4Exec(file["type"]): mode = "755" elif file["type"] == "symlink": mode = "120000" -- cgit v1.2.3 From a9834f58335b81f48e137beb33afb5bb799cdae8 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Tue, 9 Oct 2007 16:16:09 +0200 Subject: Add 'git-p4 commit' as an alias for 'git-p4 submit' Given that git uses 'commit', git-p4's 'sumbit' was a bit confusing at times; often making me do 'git submit' and 'git-p4 commit' instead. Signed-off-by: Marius Storm-Olsen Acked-By: Simon Hausmann Signed-off-by: Lars Hjemli Signed-off-by: Shawn O. Pearce --- contrib/fast-import/git-p4 | 1 + 1 file changed, 1 insertion(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 557649a14a..52cd2a46ba 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1651,6 +1651,7 @@ def printUsage(commands): commands = { "debug" : P4Debug, "submit" : P4Submit, + "commit" : P4Submit, "sync" : P4Sync, "rebase" : P4Rebase, "clone" : P4Clone, -- cgit v1.2.3 From 209471493afbf30d5c1fc80feadfc4836b86dc42 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 13 Sep 2007 22:10:18 +0200 Subject: git-p4: When skipping a patch as part of "git-p4 submit" make sure we correctly revert to the previous state of the files using "p4 revert". Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 52cd2a46ba..e1dc263013 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -529,6 +529,10 @@ class P4Submit(Command): "and with .rej files / [w]rite the patch to a file (patch.txt) ") if response == "s": print "Skipping! Good luck with the next patches..." + for f in editedFiles: + system("p4 revert \"%s\"" % f); + for f in filesToAdd: + system("rm %s" %f) return elif response == "a": os.system(applyPatchCmd) -- cgit v1.2.3 From d9a5f25b67951eb68e80d872611542b58ce5aa33 Mon Sep 17 00:00:00 2001 From: Chris Pettitt Date: Mon, 15 Oct 2007 22:15:06 -0700 Subject: git-p4 support for perforce renames. The current git-p4 implementation does support file renames. However, because it does not use the "p4 integrate" command, the history for the renamed file is not linked to the new file. This changeset adds support for perforce renames with the integrate command. Currently this feature is only enabled when calling git-p4 submit with the -M option. This is intended to look and behave similar to the "detect renames" feature of other git commands. The following sequence is used for renamed files: p4 integrate -Dt x x' p4 edit x' rm x' git apply p4 delete x By default, perforce will not allow an integration with a target file that has been deleted. That is, if x' in the example above is the name of a previously deleted file then perforce will fail the integrate. The -Dt option tells perforce to allow the target of integrate to be a previously deleted file. Signed-off-by: Chris Pettitt Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e1dc263013..bf33f74b70 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -399,6 +399,7 @@ class P4Submit(Command): optparse.make_option("--dry-run", action="store_true"), optparse.make_option("--direct", dest="directSubmit", action="store_true"), optparse.make_option("--trust-me-like-a-fool", dest="trustMeLikeAFool", action="store_true"), + optparse.make_option("-M", dest="detectRename", action="store_true"), ] self.description = "Submit changes from git to the perforce depot." self.usage += " [name of git branch to submit into perforce depot]" @@ -411,6 +412,7 @@ class P4Submit(Command): self.origin = "" self.directSubmit = False self.trustMeLikeAFool = False + self.detectRename = False self.verbose = False self.isWindows = (platform.system() == "Windows") @@ -491,7 +493,8 @@ class P4Submit(Command): diff = self.diffStatus else: print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id)) - diff = read_pipe_lines("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)) + diffOpts = ("", "-M")[self.detectRename] + diff = read_pipe_lines("git diff-tree -r --name-status %s \"%s^\" \"%s\"" % (diffOpts, id, id)) filesToAdd = set() filesToDelete = set() editedFiles = set() @@ -509,6 +512,13 @@ class P4Submit(Command): filesToDelete.add(path) if path in filesToAdd: filesToAdd.remove(path) + elif modifier == "R": + src, dest = line.strip().split("\t")[1:3] + system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest)) + system("p4 edit \"%s\"" % (dest)) + os.unlink(dest) + editedFiles.add(dest) + filesToDelete.add(src) else: die("unknown modifier %s for %s" % (modifier, path)) -- cgit v1.2.3 From b43b0a3c5c313619397b2f81d5a4acad2c3cb4a9 Mon Sep 17 00:00:00 2001 From: Chris Pettitt Date: Thu, 1 Nov 2007 20:43:13 -0700 Subject: git-p4: Add a helper function to parse the full git diff-tree output. Signed-off-by: Chris Pettitt Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 49 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index bf33f74b70..c7fc564a5b 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -71,6 +71,46 @@ def isP4Exec(kind): a plus sign, it is also executable""" return (re.search(r"(^[cku]?x)|\+.*x", kind) != None) +def diffTreePattern(): + # This is a simple generator for the diff tree regex pattern. This could be + # a class variable if this and parseDiffTreeEntry were a part of a class. + pattern = re.compile(':(\d+) (\d+) (\w+) (\w+) ([A-Z])(\d+)?\t(.*?)((\t(.*))|$)') + while True: + yield pattern + +def parseDiffTreeEntry(entry): + """Parses a single diff tree entry into its component elements. + + See git-diff-tree(1) manpage for details about the format of the diff + output. This method returns a dictionary with the following elements: + + src_mode - The mode of the source file + dst_mode - The mode of the destination file + src_sha1 - The sha1 for the source file + dst_sha1 - The sha1 fr the destination file + status - The one letter status of the diff (i.e. 'A', 'M', 'D', etc) + status_score - The score for the status (applicable for 'C' and 'R' + statuses). This is None if there is no score. + src - The path for the source file. + dst - The path for the destination file. This is only present for + copy or renames. If it is not present, this is None. + + If the pattern is not matched, None is returned.""" + + match = diffTreePattern().next().match(entry) + if match: + return { + 'src_mode': match.group(1), + 'dst_mode': match.group(2), + 'src_sha1': match.group(3), + 'dst_sha1': match.group(4), + 'status': match.group(5), + 'status_score': match.group(6), + 'src': match.group(7), + 'dst': match.group(10) + } + return None + def p4CmdList(cmd, stdin=None, stdin_mode='w+b'): cmd = "p4 -G %s" % cmd if verbose: @@ -494,13 +534,14 @@ class P4Submit(Command): else: print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id)) diffOpts = ("", "-M")[self.detectRename] - diff = read_pipe_lines("git diff-tree -r --name-status %s \"%s^\" \"%s\"" % (diffOpts, id, id)) + diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (diffOpts, id, id)) filesToAdd = set() filesToDelete = set() editedFiles = set() for line in diff: - modifier = line[0] - path = line[1:].strip() + diff = parseDiffTreeEntry(line) + modifier = diff['status'] + path = diff['src'] if modifier == "M": system("p4 edit \"%s\"" % path) editedFiles.add(path) @@ -513,7 +554,7 @@ class P4Submit(Command): if path in filesToAdd: filesToAdd.remove(path) elif modifier == "R": - src, dest = line.strip().split("\t")[1:3] + src, dest = diff['src'], diff['dst'] system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest)) system("p4 edit \"%s\"" % (dest)) os.unlink(dest) -- cgit v1.2.3 From c65b670e858a0fc010c8b8bb3cbf064bb22e1839 Mon Sep 17 00:00:00 2001 From: Chris Pettitt Date: Thu, 1 Nov 2007 20:43:14 -0700 Subject: git-p4: Detect changes to executable bit and include them in p4 submit. This changeset takes advantage of the new parseDiffTreeEntry(...) function to detect changes to the execute bit in the git repository. During submit, git-p4 now looks for changes to the executable bit and if it finds them it "reopens" the file in perforce, which allows it to change the file type. The logic for adding the executable bit in perforce is straightforward: the +x modifier can be used. Removing the executable bit in perforce requires that the entire filetype be redefined (there is no way to join remove the bit with a -x modifier, for example). This changeset includes logic to remove the executable bit from the full file type while preserving the base file type and other modifiers. Signed-off-by: Chris Pettitt Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index c7fc564a5b..c148b5ab7d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -71,6 +71,31 @@ def isP4Exec(kind): a plus sign, it is also executable""" return (re.search(r"(^[cku]?x)|\+.*x", kind) != None) +def setP4ExecBit(file, mode): + # Reopens an already open file and changes the execute bit to match + # the execute bit setting in the passed in mode. + + p4Type = "+x" + + if not isModeExec(mode): + p4Type = getP4OpenedType(file) + p4Type = re.sub('^([cku]?)x(.*)', '\\1\\2', p4Type) + p4Type = re.sub('(.*?\+.*?)x(.*?)', '\\1\\2', p4Type) + if p4Type[-1] == "+": + p4Type = p4Type[0:-1] + + system("p4 reopen -t %s %s" % (p4Type, file)) + +def getP4OpenedType(file): + # Returns the perforce file type for the given file. + + result = read_pipe("p4 opened %s" % file) + match = re.match(".*\((.+)\)$", result) + if match: + return match.group(1) + else: + die("Could not determine file type for %s" % file) + def diffTreePattern(): # This is a simple generator for the diff tree regex pattern. This could be # a class variable if this and parseDiffTreeEntry were a part of a class. @@ -111,6 +136,14 @@ def parseDiffTreeEntry(entry): } return None +def isModeExec(mode): + # Returns True if the given git mode represents an executable file, + # otherwise False. + return mode[-3:] == "755" + +def isModeExecChanged(src_mode, dst_mode): + return isModeExec(src_mode) != isModeExec(dst_mode) + def p4CmdList(cmd, stdin=None, stdin_mode='w+b'): cmd = "p4 -G %s" % cmd if verbose: @@ -538,15 +571,19 @@ class P4Submit(Command): filesToAdd = set() filesToDelete = set() editedFiles = set() + filesToChangeExecBit = {} for line in diff: diff = parseDiffTreeEntry(line) modifier = diff['status'] path = diff['src'] if modifier == "M": system("p4 edit \"%s\"" % path) + if isModeExecChanged(diff['src_mode'], diff['dst_mode']): + filesToChangeExecBit[path] = diff['dst_mode'] editedFiles.add(path) elif modifier == "A": filesToAdd.add(path) + filesToChangeExecBit[path] = diff['dst_mode'] if path in filesToDelete: filesToDelete.remove(path) elif modifier == "D": @@ -557,6 +594,8 @@ class P4Submit(Command): src, dest = diff['src'], diff['dst'] system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest)) system("p4 edit \"%s\"" % (dest)) + if isModeExecChanged(diff['src_mode'], diff['dst_mode']): + filesToChangeExecBit[dest] = diff['dst_mode'] os.unlink(dest) editedFiles.add(dest) filesToDelete.add(src) @@ -609,6 +648,11 @@ class P4Submit(Command): system("p4 revert \"%s\"" % f) system("p4 delete \"%s\"" % f) + # Set/clear executable bits + for f in filesToChangeExecBit.keys(): + mode = filesToChangeExecBit[f] + setP4ExecBit(f, mode) + logMessage = "" if not self.directSubmit: logMessage = extractLogMessageFromGitCommit(id) -- cgit v1.2.3 From 38f9f5ec41803558b4ccefc9db08fac5696aff8d Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 15 Nov 2007 10:38:45 +0100 Subject: git-p4: Fix direct import from perforce after fetching changes through git from origin When using an existing git repository to cache the perforce import we don't fetch the branch mapping from perforce as that is a slow operation. However the origin repository may not be fully up-to-date and therefore it may be necessary to import more changes directly from Perforce. Such a direct import needs self.knownBranches to be set up though, so initialize it from the existing p4/* git branches. Signed-off-by: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index c148b5ab7d..c869bb8864 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1207,6 +1207,15 @@ class P4Sync(Command): for branch in lostAndFoundBranches: self.knownBranches[branch] = branch + def getBranchMappingFromGitBranches(self): + branches = p4BranchesInGit(self.importIntoRemotes) + for branch in branches.keys(): + if branch == "master": + branch = "main" + else: + branch = branch[len(self.projectName):] + self.knownBranches[branch] = branch + def listExistingP4GitBranches(self): # branches holds mapping from name to commit branches = p4BranchesInGit(self.importIntoRemotes) @@ -1541,8 +1550,10 @@ class P4Sync(Command): ## FIXME - what's a P4 projectName ? self.projectName = self.guessProjectName() - if not self.hasOrigin: - self.getBranchMapping(); + if self.hasOrigin: + self.getBranchMappingFromGitBranches() + else: + self.getBranchMapping() if self.verbose: print "p4-git branches: %s" % self.p4BranchesInGit print "initial parents: %s" % self.initialParents -- cgit v1.2.3 From 183f84365de7b4b1fe0e15cebce80a95023aa1d6 Mon Sep 17 00:00:00 2001 From: Shun Kei Leung Date: Wed, 21 Nov 2007 11:01:19 +0800 Subject: git-p4: Fix typo in --detect-labels Signed-off-by: Kevin Leung Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index c869bb8864..c80a6da252 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1141,7 +1141,7 @@ class P4Sync(Command): 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.depotPaths` for output in l: label = output["label"] -- cgit v1.2.3 From f3e9512be1c7935b8ca496f3687c6850b32a06f3 Mon Sep 17 00:00:00 2001 From: Jason McMullan Date: Wed, 5 Dec 2007 12:16:56 -0500 Subject: Remove $Id: ..$ $Header: ..$ etc from +ko and +k files during import This patch removes the '$Keyword: ...$' '...' data, so that files don't have spurious megre conflicts between branches. Handles both +ko and +k styles, and leaves the '$Foo$' in the original file. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index c80a6da252..31c5501d11 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -964,9 +964,13 @@ class P4Sync(Command): stat = filedata[j] j += 1 text = '' - while j < len(filedata) and filedata[j]['code'] in ('text', - 'binary'): - text += filedata[j]['data'] + while j < len(filedata) and filedata[j]['code'] in ('text', 'unicode', 'binary'): + tmp = filedata[j]['data'] + if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'): + tmp = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', tmp) + elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'): + tmp = re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', tmp) + text += tmp j += 1 -- cgit v1.2.3 From e96e400f67b8478a99f9d2b5d82f08cd21f51a88 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 4 Jan 2008 14:27:55 +0100 Subject: git-p4: Fix submit user-interface. Don't ask any questions when submitting, behave similar to git-svn dcommit. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 85 ++++++++++++++-------------------------------- 1 file changed, 26 insertions(+), 59 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 31c5501d11..a74aabdb28 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -469,9 +469,7 @@ class P4Submit(Command): optparse.make_option("--origin", dest="origin"), optparse.make_option("--reset", action="store_true", dest="reset"), optparse.make_option("--log-substitutions", dest="substFile"), - optparse.make_option("--dry-run", action="store_true"), optparse.make_option("--direct", dest="directSubmit", action="store_true"), - optparse.make_option("--trust-me-like-a-fool", dest="trustMeLikeAFool", action="store_true"), optparse.make_option("-M", dest="detectRename", action="store_true"), ] self.description = "Submit changes from git to the perforce depot." @@ -479,12 +477,10 @@ class P4Submit(Command): self.firstTime = True self.reset = False self.interactive = True - self.dryRun = False self.substFile = "" self.firstTime = True self.origin = "" self.directSubmit = False - self.trustMeLikeAFool = False self.detectRename = False self.verbose = False self.isWindows = (platform.system() == "Windows") @@ -681,57 +677,30 @@ class P4Submit(Command): separatorLine += "\r" separatorLine += "\n" - response = "e" - if self.trustMeLikeAFool: - response = "y" - - firstIteration = True - while response == "e": - if not firstIteration: - response = raw_input("Do you want to submit this change? [y]es/[e]dit/[n]o/[s]kip ") - firstIteration = False - if response == "e": - [handle, fileName] = tempfile.mkstemp() - tmpFile = os.fdopen(handle, "w+") - tmpFile.write(submitTemplate + separatorLine + diff) - tmpFile.close() - defaultEditor = "vi" - if platform.system() == "Windows": - defaultEditor = "notepad" - editor = os.environ.get("EDITOR", defaultEditor); - system(editor + " " + fileName) - tmpFile = open(fileName, "rb") - message = tmpFile.read() - tmpFile.close() - os.remove(fileName) - submitTemplate = message[:message.index(separatorLine)] - if self.isWindows: - submitTemplate = submitTemplate.replace("\r\n", "\n") - - if response == "y" or response == "yes": - if self.dryRun: - print submitTemplate - raw_input("Press return to continue...") - else: - if self.directSubmit: - print "Submitting to git first" - os.chdir(self.oldWorkingDirectory) - write_pipe("git commit -a -F -", submitTemplate) - os.chdir(self.clientPath) - - write_pipe("p4 submit -i", submitTemplate) - elif response == "s": - for f in editedFiles: - system("p4 revert \"%s\"" % f); - for f in filesToAdd: - system("p4 revert \"%s\"" % f); - system("rm %s" %f) - for f in filesToDelete: - system("p4 delete \"%s\"" % f); - return - else: - print "Not submitting!" - self.interactive = False + [handle, fileName] = tempfile.mkstemp() + tmpFile = os.fdopen(handle, "w+") + tmpFile.write(submitTemplate + separatorLine + diff) + tmpFile.close() + defaultEditor = "vi" + if platform.system() == "Windows": + defaultEditor = "notepad" + editor = os.environ.get("EDITOR", defaultEditor); + system(editor + " " + fileName) + tmpFile = open(fileName, "rb") + message = tmpFile.read() + tmpFile.close() + os.remove(fileName) + submitTemplate = message[:message.index(separatorLine)] + if self.isWindows: + submitTemplate = submitTemplate.replace("\r\n", "\n") + + if self.directSubmit: + print "Submitting to git first" + os.chdir(self.oldWorkingDirectory) + write_pipe("git commit -a -F -", submitTemplate) + os.chdir(self.clientPath) + + write_pipe("p4 submit -i", submitTemplate) else: fileName = "submit.txt" file = open(fileName, "w+") @@ -828,10 +797,8 @@ class P4Submit(Command): sync = P4Sync() sync.run([]) - response = raw_input("Do you want to rebase current HEAD from Perforce now using git-p4 rebase? [y]es/[n]o ") - if response == "y" or response == "yes": - rebase = P4Rebase() - rebase.rebase() + rebase = P4Rebase() + rebase.rebase() os.remove(self.configFile) return True -- cgit v1.2.3 From 36ee4ee40e1851442b0b075870cd5de5df6ee2b6 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 7 Jan 2008 14:21:45 +0100 Subject: git-p4: Ensure the working directory and the index are clean before "git-p4 rebase" Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index a74aabdb28..e5fe5f6d3d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1611,6 +1611,11 @@ class P4Rebase(Command): return self.rebase() def rebase(self): + if os.system("git update-index --refresh") != 0: + die("Some files in your working directory are modified and different than what is in your index. You can use git update-index to bring the index up-to-date or stash away all your changes with git stash."); + if len(read_pipe("git diff-index HEAD --")) > 0: + die("You have uncommited changes. Please commit them before rebasing or stash them away with git stash."); + [upstream, settings] = findUpstreamBranchPoint() if len(upstream) == 0: die("Cannot find upstream branchpoint for rebase") -- cgit v1.2.3 From 147402a2e9e29efe3fe75b5409cc2dd88cef04c7 Mon Sep 17 00:00:00 2001 From: Tommy Thorn Date: Sat, 2 Feb 2008 00:11:44 -0800 Subject: git-p4: Fix an obvious typo The regexp "$," can't match anything. Clearly not intended. This was introduced in ce6f33c8 which is quite a while ago. Signed-off-by: Tommy Thorn Acked-by: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e5fe5f6d3d..c17afae94a 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1646,7 +1646,7 @@ class P4Clone(P4Sync): depotPath = args[0] depotDir = re.sub("(@[^@]*)$", "", depotPath) depotDir = re.sub("(#[^#]*)$", "", depotDir) - depotDir = re.sub(r"\.\.\.$,", "", depotDir) + depotDir = re.sub(r"\.\.\.$", "", depotDir) depotDir = re.sub(r"/$", "", depotDir) return os.path.split(depotDir)[1] -- cgit v1.2.3 From 053d9e432be246a389fb8adaa0c88e7c791f8b21 Mon Sep 17 00:00:00 2001 From: Toby Allsopp Date: Tue, 5 Feb 2008 09:41:43 +1300 Subject: git-p4: Fix indentation from tab to spaces Signed-off-by: Toby Allsopp --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index c17afae94a..781a0cbbbc 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1646,7 +1646,7 @@ class P4Clone(P4Sync): depotPath = args[0] depotDir = re.sub("(@[^@]*)$", "", depotPath) depotDir = re.sub("(#[^#]*)$", "", depotDir) - depotDir = re.sub(r"\.\.\.$", "", depotDir) + depotDir = re.sub(r"\.\.\.$", "", depotDir) depotDir = re.sub(r"/$", "", depotDir) return os.path.split(depotDir)[1] -- cgit v1.2.3 From 354081d5a0392a015731a637f026dc885a4ddb0f Mon Sep 17 00:00:00 2001 From: Tommy Thorn Date: Sun, 3 Feb 2008 10:38:51 -0800 Subject: git-p4: support exclude paths Teach git-p4 about the -/ option which adds depot paths to the exclude list, used when cloning. The option is chosen such that the natural Perforce syntax works, eg: git p4 clone //branch/path/... -//branch/path/{large,old}/... Trailing ... on exclude paths are optional. This is a generalization of a change by Dmitry Kakurin (thanks). Signed-off-by: Tommy Thorn Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 781a0cbbbc..e4238538a1 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -843,18 +843,25 @@ class P4Sync(Command): self.keepRepoPath = False self.depotPaths = None self.p4BranchesInGit = [] + self.cloneExclude = [] if gitConfig("git-p4.syncFromOrigin") == "false": self.syncWithOrigin = False def extractFilesFromCommit(self, commit): + self.cloneExclude = [re.sub(r"\.\.\.$", "", path) + for path in self.cloneExclude] files = [] fnum = 0 while commit.has_key("depotFile%s" % fnum): path = commit["depotFile%s" % fnum] - found = [p for p in self.depotPaths - if path.startswith (p)] + if [p for p in self.cloneExclude + if path.startswith (p)]: + found = False + else: + found = [p for p in self.depotPaths + if path.startswith (p)] if not found: fnum = fnum + 1 continue @@ -1634,13 +1641,23 @@ class P4Clone(P4Sync): P4Sync.__init__(self) self.description = "Creates a new git repository and imports from Perforce into it" self.usage = "usage: %prog [options] //depot/path[@revRange]" - self.options.append( + self.options += [ optparse.make_option("--destination", dest="cloneDestination", action='store', default=None, - help="where to leave result of the clone")) + help="where to leave result of the clone"), + optparse.make_option("-/", dest="cloneExclude", + action="append", type="string", + help="exclude depot path") + ] self.cloneDestination = None self.needsGit = 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] @@ -1664,6 +1681,7 @@ class P4Clone(P4Sync): self.cloneDestination = depotPaths[-1] depotPaths = depotPaths[:-1] + self.cloneExclude = ["/"+p for p in self.cloneExclude] for p in depotPaths: if not p.startswith("//"): return False -- cgit v1.2.3 From 4b61b5c963ad1fd59e858c2bc21b1b48836f04f8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 19 Feb 2008 09:12:29 +0100 Subject: git-p4: Remove --log-substitutions feature. This turns out to be rarely useful and is already covered by git's commit.template configuration variable. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 7 ------- 1 file changed, 7 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e4238538a1..f2a6059a7e 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -468,7 +468,6 @@ class P4Submit(Command): 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"), optparse.make_option("--direct", dest="directSubmit", action="store_true"), optparse.make_option("-M", dest="detectRename", action="store_true"), ] @@ -477,7 +476,6 @@ class P4Submit(Command): self.firstTime = True self.reset = False self.interactive = True - self.substFile = "" self.firstTime = True self.origin = "" self.directSubmit = False @@ -759,11 +757,6 @@ class P4Submit(Command): if self.reset: self.firstTime = True - if len(self.substFile) > 0: - for line in open(self.substFile, "r").readlines(): - tokens = line.strip().split("=") - self.logSubstitutions[tokens[0]] = tokens[1] - self.check() self.configFile = self.gitdir + "/p4-git-sync.cfg" self.config = shelve.open(self.configFile, writeback=True) -- cgit v1.2.3 From edae1e2f407d0e9c6c92333047bc31b27bfdd58f Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 19 Feb 2008 09:29:06 +0100 Subject: git-p4: Clean up git-p4 submit's log message handling. Instead of trying to substitute fields in the p4 submit template we now simply replace the description of the submit with the log message of the git commit. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index f2a6059a7e..e55a41b10e 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -483,10 +483,6 @@ class P4Submit(Command): self.verbose = False self.isWindows = (platform.system() == "Windows") - self.logSubstitutions = {} - self.logSubstitutions[""] = "%log%" - self.logSubstitutions["\tDetails:"] = "\tDetails: %log%" - def check(self): if len(p4CmdList("opened ...")) > 0: die("You have files opened with perforce! Close them before starting the sync.") @@ -507,26 +503,31 @@ class P4Submit(Command): self.config["commits"] = commits + # replaces everything between 'Description:' and the next P4 submit template field with the + # commit message def prepareLogMessage(self, template, message): result = "" + inDescriptionSection = False + for line in template.split("\n"): if line.startswith("#"): result += line + "\n" continue - substituted = False - for key in self.logSubstitutions.keys(): - if line.find(key) != -1: - value = self.logSubstitutions[key] - value = value.replace("%log%", message) - if value != "@remove@": - result += line.replace(key, value) + "\n" - substituted = True - break + if inDescriptionSection: + if line.startswith("Files:"): + inDescriptionSection = False + else: + continue + else: + if line.startswith("Description:"): + inDescriptionSection = True + line += "\n" + for messageLine in message.split("\n"): + line += "\t" + messageLine + "\n" - if not substituted: - result += line + "\n" + result += line + "\n" return result @@ -650,7 +651,6 @@ class P4Submit(Command): logMessage = "" if not self.directSubmit: logMessage = extractLogMessageFromGitCommit(id) - logMessage = logMessage.replace("\n", "\n\t") if self.isWindows: logMessage = logMessage.replace("\n", "\r\n") logMessage = logMessage.strip() -- cgit v1.2.3 From 0e36f2d726d4ce50c3f128bcc168d59ad03e804f Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 19 Feb 2008 09:33:08 +0100 Subject: git-p4: Removed git-p4 submit --direct. This feature was originally meant to allow for quicker direct submits into perforce, but it turns out that it is not actually quicker than doing a git commit and then running git-p4 submit. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 56 +++++++++------------------------------------- 1 file changed, 11 insertions(+), 45 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e55a41b10e..087f4229a0 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -468,7 +468,6 @@ class P4Submit(Command): 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("--direct", dest="directSubmit", action="store_true"), optparse.make_option("-M", dest="detectRename", action="store_true"), ] self.description = "Submit changes from git to the perforce depot." @@ -478,7 +477,6 @@ class P4Submit(Command): self.interactive = True self.firstTime = True self.origin = "" - self.directSubmit = False self.detectRename = False self.verbose = False self.isWindows = (platform.system() == "Windows") @@ -494,12 +492,9 @@ class P4Submit(Command): "maybe you want to call git-p4 submit --reset" % self.configFile) commits = [] - if self.directSubmit: - commits.append("0") - else: - for line in read_pipe_lines("git rev-list --no-merges %s..%s" % (self.origin, self.master)): - commits.append(line.strip()) - commits.reverse() + for line in read_pipe_lines("git rev-list --no-merges %s..%s" % (self.origin, self.master)): + commits.append(line.strip()) + commits.reverse() self.config["commits"] = commits @@ -556,13 +551,9 @@ class P4Submit(Command): return template def applyCommit(self, id): - if self.directSubmit: - print "Applying local change in working directory/index" - diff = self.diffStatus - else: - print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id)) - diffOpts = ("", "-M")[self.detectRename] - diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (diffOpts, id, id)) + print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id)) + diffOpts = ("", "-M")[self.detectRename] + diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (diffOpts, id, id)) filesToAdd = set() filesToDelete = set() editedFiles = set() @@ -597,10 +588,7 @@ class P4Submit(Command): else: die("unknown modifier %s for %s" % (modifier, path)) - if self.directSubmit: - diffcmd = "cat \"%s\"" % self.diffFile - else: - diffcmd = "git format-patch -k --stdout \"%s^\"..\"%s\"" % (id, id) + diffcmd = "git format-patch -k --stdout \"%s^\"..\"%s\"" % (id, id) patchcmd = diffcmd + " | git apply " tryPatchCmd = patchcmd + "--check -" applyPatchCmd = patchcmd + "--check --apply -" @@ -648,12 +636,10 @@ class P4Submit(Command): mode = filesToChangeExecBit[f] setP4ExecBit(f, mode) - logMessage = "" - if not self.directSubmit: - logMessage = extractLogMessageFromGitCommit(id) - if self.isWindows: - logMessage = logMessage.replace("\n", "\r\n") - logMessage = logMessage.strip() + logMessage = extractLogMessageFromGitCommit(id) + if self.isWindows: + logMessage = logMessage.replace("\n", "\r\n") + logMessage = logMessage.strip() template = self.prepareSubmitTemplate() @@ -692,12 +678,6 @@ class P4Submit(Command): if self.isWindows: submitTemplate = submitTemplate.replace("\r\n", "\n") - if self.directSubmit: - print "Submitting to git first" - os.chdir(self.oldWorkingDirectory) - write_pipe("git commit -a -F -", submitTemplate) - os.chdir(self.clientPath) - write_pipe("p4 submit -i", submitTemplate) else: fileName = "submit.txt" @@ -739,17 +719,6 @@ class P4Submit(Command): print "Perforce checkout for depot path %s located at %s" % (self.depotPath, self.clientPath) self.oldWorkingDirectory = os.getcwd() - if self.directSubmit: - self.diffStatus = read_pipe_lines("git diff -r --name-status HEAD") - if len(self.diffStatus) == 0: - print "No changes in working directory to submit." - return True - patch = read_pipe("git diff -p --binary --diff-filter=ACMRTUXB HEAD") - self.diffFile = self.gitdir + "/p4-git-diff" - f = open(self.diffFile, "wb") - f.write(patch) - f.close(); - os.chdir(self.clientPath) print "Syncronizing p4 checkout..." system("p4 sync ...") @@ -777,9 +746,6 @@ class P4Submit(Command): self.config.close() - if self.directSubmit: - os.remove(self.diffFile) - if len(commits) == 0: if self.firstTime: print "No changes found to apply between %s and current HEAD" % self.origin -- cgit v1.2.3 From 4c750c0d8bfd7e75b86d660def012bff17d2bf8e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 19 Feb 2008 09:37:16 +0100 Subject: git-p4: git-p4 submit cleanups. Removed storing the list of commits in a configuration file. We only need the list of commits at run-time. Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 51 +++++++++------------------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 087f4229a0..d59ed945de 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -464,18 +464,13 @@ class P4Submit(Command): def __init__(self): 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("-M", dest="detectRename", action="store_true"), ] self.description = "Submit changes from git to the perforce depot." self.usage += " [name of git branch to submit into perforce depot]" - self.firstTime = True - self.reset = False self.interactive = True - self.firstTime = True self.origin = "" self.detectRename = False self.verbose = False @@ -485,19 +480,6 @@ class P4Submit(Command): if len(p4CmdList("opened ...")) > 0: die("You have files opened with perforce! Close them before starting the sync.") - def start(self): - if len(self.config) > 0 and not self.reset: - die("Cannot start sync. Previous sync config found at %s\n" - "If you want to start submitting again from scratch " - "maybe you want to call git-p4 submit --reset" % self.configFile) - - commits = [] - for line in read_pipe_lines("git rev-list --no-merges %s..%s" % (self.origin, self.master)): - commits.append(line.strip()) - commits.reverse() - - self.config["commits"] = commits - # replaces everything between 'Description:' and the next P4 submit template field with the # commit message def prepareLogMessage(self, template, message): @@ -723,42 +705,29 @@ class P4Submit(Command): print "Syncronizing p4 checkout..." system("p4 sync ...") - if self.reset: - self.firstTime = True - self.check() - self.configFile = self.gitdir + "/p4-git-sync.cfg" - self.config = shelve.open(self.configFile, writeback=True) - if self.firstTime: - self.start() - - commits = self.config.get("commits", []) + commits = [] + for line in read_pipe_lines("git rev-list --no-merges %s..%s" % (self.origin, self.master)): + commits.append(line.strip()) + commits.reverse() while len(commits) > 0: - self.firstTime = False commit = commits[0] commits = commits[1:] - self.config["commits"] = commits self.applyCommit(commit) if not self.interactive: break - self.config.close() - if len(commits) == 0: - if self.firstTime: - print "No changes found to apply between %s and current HEAD" % self.origin - else: - print "All changes applied!" - os.chdir(self.oldWorkingDirectory) + print "All changes applied!" + os.chdir(self.oldWorkingDirectory) - sync = P4Sync() - sync.run([]) + sync = P4Sync() + sync.run([]) - rebase = P4Rebase() - rebase.rebase() - os.remove(self.configFile) + rebase = P4Rebase() + rebase.rebase() return True -- cgit v1.2.3 From 3a70cdfa42199e16d2d047c286431c4274d65b1a Mon Sep 17 00:00:00 2001 From: Tor Arvid Lund Date: Mon, 18 Feb 2008 15:22:08 +0100 Subject: git-p4: Support usage of perforce client spec When syncing, git-p4 will only download files that are included in the active perforce client spec. This does not change the default behaviour - it requires that the user either supplies the command line argument --use-client-spec, or sets the git config option p4.useclientspec to "true". Signed-off-by: Tor Arvid Lund Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 50 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d59ed945de..be96600753 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -745,7 +745,9 @@ class P4Sync(Command): help="Import into refs/heads/ , not refs/remotes"), optparse.make_option("--max-changes", dest="maxChanges"), optparse.make_option("--keep-path", dest="keepRepoPath", action='store_true', - help="Keep entire BRANCH/DIR/SUBDIR prefix during import") + 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") ] self.description = """Imports from Perforce into a git repository.\n example: @@ -772,6 +774,8 @@ class P4Sync(Command): self.depotPaths = None self.p4BranchesInGit = [] self.cloneExclude = [] + self.useClientSpec = False + self.clientSpecDirs = [] if gitConfig("git-p4.syncFromOrigin") == "false": self.syncWithOrigin = False @@ -846,11 +850,21 @@ class P4Sync(Command): ## Should move this out, doesn't use SELF. def readP4Files(self, files): + for f in files: + for val in self.clientSpecDirs: + if f['path'].startswith(val[0]): + if val[1] > 0: + f['include'] = True + else: + f['include'] = False + break + files = [f for f in files - if f['action'] != 'delete'] + if f['action'] != 'delete' and + (f.has_key('include') == False or f['include'] == True)] if not files: - return + return [] filedata = p4CmdList('-x - print', stdin='\n'.join(['%s#%s' % (f['path'], f['rev']) @@ -885,6 +899,7 @@ class P4Sync(Command): for f in files: assert not f.has_key('data') f['data'] = contents[f['path']] + return files def commit(self, details, files, branch, branchPrefixes, parent = ""): epoch = details["time"] @@ -901,11 +916,7 @@ class P4Sync(Command): new_files.append (f) else: sys.stderr.write("Ignoring file outside of prefix: %s\n" % path) - files = new_files - self.readP4Files(files) - - - + files = self.readP4Files(new_files) self.gitStream.write("commit %s\n" % branch) # gitStream.write("mark :%s\n" % details["change"]) @@ -1320,6 +1331,26 @@ class P4Sync(Command): print self.gitError.read() + def getClientSpec(self): + specList = p4CmdList( "client -o" ) + temp = {} + for entry in specList: + for k,v in entry.iteritems(): + if k.startswith("View"): + if v.startswith('"'): + start = 1 + else: + start = 0 + index = v.find("...") + v = v[start:index] + if v.startswith("-"): + v = v[1:] + temp[v] = -len(v) + else: + temp[v] = len(v) + self.clientSpecDirs = temp.items() + self.clientSpecDirs.sort( lambda x, y: abs( y[1] ) - abs( x[1] ) ) + def run(self, args): self.depotPaths = [] self.changeRange = "" @@ -1352,6 +1383,9 @@ class P4Sync(Command): if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes and gitBranchExists(self.branch): system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch)) + if self.useClientSpec or gitConfig("p4.useclientspec") == "true": + self.getClientSpec() + # TODO: should always look at previous commits, # merge with previous imports, if possible. if args == []: -- cgit v1.2.3 From 30b5940bcd3ed7392795f6a27563013f6f806de4 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 3 Mar 2008 11:55:48 +0100 Subject: git-p4: Fix import of changesets with file deletions Commit 3a70cdfa42199e16d2d047c286431c4274d65b1a made readP4Files abort quickly when the changeset only contains files that are marked for deletion with an empty return value, which caused the commit to not do anything. This commit changes readP4Files to distinguish between files that need to be passed to p4 print and files that have no content ("deleted") and merge them in the returned list. Signed-off-by: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index be96600753..650ea34176 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -850,29 +850,32 @@ class P4Sync(Command): ## Should move this out, doesn't use SELF. def readP4Files(self, files): + filesForCommit = [] + filesToRead = [] + for f in files: + includeFile = True for val in self.clientSpecDirs: if f['path'].startswith(val[0]): - if val[1] > 0: - f['include'] = True - else: - f['include'] = False + if val[1] <= 0: + includeFile = False break - files = [f for f in files - if f['action'] != 'delete' and - (f.has_key('include') == False or f['include'] == True)] + if includeFile: + filesForCommit.append(f) + if f['action'] != 'delete': + filesToRead.append(f) - if not files: - return [] + filedata = [] + if len(filesToRead) > 0: + filedata = p4CmdList('-x - print', + stdin='\n'.join(['%s#%s' % (f['path'], f['rev']) + for f in filesToRead]), + stdin_mode='w+') - filedata = p4CmdList('-x - print', - stdin='\n'.join(['%s#%s' % (f['path'], f['rev']) - for f in files]), - stdin_mode='w+') - if "p4ExitCode" in filedata[0]: - die("Problems executing p4. Error: [%d]." - % (filedata[0]['p4ExitCode'])); + if "p4ExitCode" in filedata[0]: + die("Problems executing p4. Error: [%d]." + % (filedata[0]['p4ExitCode'])); j = 0; contents = {} @@ -896,10 +899,12 @@ class P4Sync(Command): contents[stat['depotFile']] = text - for f in files: - assert not f.has_key('data') - f['data'] = contents[f['path']] - return files + for f in filesForCommit: + path = f['path'] + if contents.has_key(path): + f['data'] = contents[path] + + return filesForCommit def commit(self, details, files, branch, branchPrefixes, parent = ""): epoch = details["time"] -- cgit v1.2.3 From 8ff45f2af5b25b7581072ee7896f4285dfc034ea Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Mon, 3 Mar 2008 13:42:47 +0100 Subject: git-p4: Optimize the fetching of data from perforce. Use shallow copies in loop, and join content at the end. Then do the substitution, if needed. Signed-off-by: Marius Storm-Olsen Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 650ea34176..539c5cda07 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -882,21 +882,21 @@ class P4Sync(Command): while j < len(filedata): stat = filedata[j] j += 1 - text = '' + text = []; while j < len(filedata) and filedata[j]['code'] in ('text', 'unicode', 'binary'): - tmp = filedata[j]['data'] - if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'): - tmp = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', tmp) - elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'): - tmp = re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', tmp) - text += tmp + text.append(filedata[j]['data']) j += 1 - + text = ''.join(text) if not stat.has_key('depotFile'): sys.stderr.write("p4 print fails with: %s\n" % repr(stat)) continue + if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'): + text = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', text) + elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'): + text = re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', text) + contents[stat['depotFile']] = text for f in filesForCommit: -- cgit v1.2.3 From 67abd417165d1e7716d947949f5e5e27318c8a29 Mon Sep 17 00:00:00 2001 From: Shawn Bohrer Date: Wed, 12 Mar 2008 19:03:23 -0500 Subject: git-p4: Unset P4DIFF environment variable when using 'p4 -du diff' A custom diffing utility can be specified for the 'p4 diff' command by setting the P4DIFF environment variable. However when using a custom diffing utility such as 'vimdiff' passing options like -du can cause unexpected behavior. Since the goal is to generate a unified diff of the changes and attach them to the bottom of the p4 submit log we should unset P4DIFF if it has been set in order to generate the diff properly. Signed-off-by: Shawn Bohrer Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 2 ++ 1 file changed, 2 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 539c5cda07..28b9c3c3cb 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -627,6 +627,8 @@ class P4Submit(Command): if self.interactive: submitTemplate = self.prepareLogMessage(template, logMessage) + if os.environ.has_key("P4DIFF"): + del(os.environ["P4DIFF"]) diff = read_pipe("p4 diff -du ...") for newFile in filesToAdd: -- cgit v1.2.3 From 82cea9ffb1c4677155e3e2996d76542502611370 Mon Sep 17 00:00:00 2001 From: Shawn Bohrer Date: Wed, 12 Mar 2008 19:03:24 -0500 Subject: git-p4: Use P4EDITOR environment variable when set Perforce allows you to set the P4EDITOR environment variable to your preferred editor for use in perforce. Since we are displaying a perforce changelog to the user we should use it when it is defined. Signed-off-by: Shawn Bohrer Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 28b9c3c3cb..3cb0330ec2 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -652,7 +652,10 @@ class P4Submit(Command): defaultEditor = "vi" if platform.system() == "Windows": defaultEditor = "notepad" - editor = os.environ.get("EDITOR", defaultEditor); + if os.environ.has_key("P4EDITOR"): + editor = os.environ.get("P4EDITOR") + else: + editor = os.environ.get("EDITOR", defaultEditor); system(editor + " " + fileName) tmpFile = open(fileName, "rb") message = tmpFile.read() -- cgit v1.2.3 From f3e5ae4f06ae968b710d286280a46b38ae3d36e8 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Fri, 28 Mar 2008 15:40:40 +0100 Subject: git-p4: Handle Windows EOLs properly after removal of p4 submit template handling. git-p4s handling of Windows style EOL was broken after the removal of the p4 submit template handling in commit f2a6059. Fix that, and make getP4OpenedType() more robust. Signed-off-by: Marius Storm-Olsen Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3cb0330ec2..d8de9f6c25 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -90,11 +90,11 @@ def getP4OpenedType(file): # Returns the perforce file type for the given file. result = read_pipe("p4 opened %s" % file) - match = re.match(".*\((.+)\)$", result) + match = re.match(".*\((.+)\)\r?$", result) if match: return match.group(1) else: - die("Could not determine file type for %s" % file) + die("Could not determine file type for %s (result: '%s')" % (file, result)) def diffTreePattern(): # This is a simple generator for the diff tree regex pattern. This could be @@ -513,6 +513,8 @@ class P4Submit(Command): template = "" inFilesSection = False for line in read_pipe_lines("p4 change -o"): + if line.endswith("\r\n"): + line = line[:-2] + "\n" if inFilesSection: if line.startswith("\t"): # path starts and ends with a tab @@ -619,8 +621,6 @@ class P4Submit(Command): setP4ExecBit(f, mode) logMessage = extractLogMessageFromGitCommit(id) - if self.isWindows: - logMessage = logMessage.replace("\n", "\r\n") logMessage = logMessage.strip() template = self.prepareSubmitTemplate() @@ -631,23 +631,25 @@ class P4Submit(Command): del(os.environ["P4DIFF"]) diff = read_pipe("p4 diff -du ...") + newdiff = "" for newFile in filesToAdd: - diff += "==== new file ====\n" - diff += "--- /dev/null\n" - diff += "+++ %s\n" % newFile + newdiff += "==== new file ====\n" + newdiff += "--- /dev/null\n" + newdiff += "+++ %s\n" % newFile f = open(newFile, "r") for line in f.readlines(): - diff += "+" + line + newdiff += "+" + line f.close() - separatorLine = "######## everything below this line is just the diff #######" - if platform.system() == "Windows": - separatorLine += "\r" - separatorLine += "\n" + separatorLine = "######## everything below this line is just the diff #######\n" [handle, fileName] = tempfile.mkstemp() tmpFile = os.fdopen(handle, "w+") - tmpFile.write(submitTemplate + separatorLine + diff) + 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.close() defaultEditor = "vi" if platform.system() == "Windows": -- cgit v1.2.3 From 4c2d5d722c4775c1efd5e63f41ba5b303ec8fb65 Mon Sep 17 00:00:00 2001 From: Jing Xue Date: Sun, 22 Jun 2008 14:12:39 -0400 Subject: Add 'git-p4.allowSubmit' to git-p4 I'm working with a perforce repo using git-p4. There are some config files which I need to change locally according to my environment. I'm using a 'local' git branch to park these changes. And I want to avoid accidentally checking them into p4 just by doing "git p4 submit" mindlessly without realizing which branch I'm actually on. This patch adds a new git config, 'git-p4.allowSubmit', which is a whitelist of branch names. "git p4 submit" will only allow submissions from local branches on the list. Useful for preventing inadvertently submitting from a strictly local branch. For backward compatibility, if this config is not set at all, submissions from all branches are allowed. Signed-off-by: Jing Xue Acked-By: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d8de9f6c25..87ca51e401 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -687,6 +687,10 @@ class P4Submit(Command): else: return False + allowSubmit = gitConfig("git-p4.allowSubmit") + if len(allowSubmit) > 0 and not self.master in allowSubmit.split(","): + die("%s is not in git-p4.allowSubmit" % self.master) + [upstream, settings] = findUpstreamBranchPoint() self.depotPath = settings['depot-paths'][0] if len(self.origin) == 0: -- cgit v1.2.3 From 2d71bde2d1a8f4e1c06cb8049a794ba4ba35d37d Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Tue, 22 Jul 2008 12:48:57 -0400 Subject: In perforce, RCS keywords are case-sensitive At least, this is true in 2007.2, according to the documentation. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 87ca51e401..6ae0429c2d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -906,7 +906,7 @@ class P4Sync(Command): if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'): text = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', text) elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'): - text = re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', text) + text = re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', text) contents[stat['depotFile']] = text -- cgit v1.2.3 From 2318121babea786390f51796bfce17088c3420ee Mon Sep 17 00:00:00 2001 From: Anand Kumria Date: Sun, 10 Aug 2008 19:26:24 +0100 Subject: Create a specific version of the read_pipe_lines command for p4 invocations This will make it easier to isolate changes to how 'p4' is invoked (whether with parameters or not, etc.). Signed-off-by: Anand Kumria Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6ae0429c2d..fc2a60dfee 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -57,6 +57,13 @@ def read_pipe_lines(c): return val +def p4_read_pipe_lines(c): + """Specifically invoke p4 on the command supplied. """ + real_cmd = "%s %s" % ("p4", c) + if verbose: + print real_cmd + return read_pipe_lines(real_cmd) + def system(cmd): if verbose: sys.stderr.write("executing %s\n" % cmd) -- cgit v1.2.3 From b340fa43017437988e233ed4fd8dc00042614071 Mon Sep 17 00:00:00 2001 From: Anand Kumria Date: Sun, 10 Aug 2008 19:26:25 +0100 Subject: Utilise the new 'p4_read_pipe_lines' command Now that we have the new command, we can utilise it and then eventually, isolate any changes required to the one place. Signed-off-by: Anand Kumria Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index fc2a60dfee..3deaa42559 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -371,7 +371,7 @@ def originP4BranchesExist(): def p4ChangesForPaths(depotPaths, changeRange): assert depotPaths - output = read_pipe_lines("p4 changes " + ' '.join (["%s...%s" % (p, changeRange) + output = p4_read_pipe_lines("changes " + ' '.join (["%s...%s" % (p, changeRange) for p in depotPaths])) changes = [] @@ -519,7 +519,7 @@ class P4Submit(Command): # remove lines in the Files section that show changes to files outside the depot path we're committing into template = "" inFilesSection = False - for line in read_pipe_lines("p4 change -o"): + for line in p4_read_pipe_lines("change -o"): if line.endswith("\r\n"): line = line[:-2] + "\n" if inFilesSection: -- cgit v1.2.3 From bf9320f1512d7ad4a17a64cfe5a593bba5037b3e Mon Sep 17 00:00:00 2001 From: Anand Kumria Date: Sun, 10 Aug 2008 19:26:26 +0100 Subject: Have a command that specifically invokes 'p4' (via system) Similiar to our 'p4_read_pipe_lines' command, we can isolate specific changes to the invocation method in the one location with this change. Signed-off-by: Anand Kumria Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3deaa42559..08acd517ba 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -70,6 +70,13 @@ def system(cmd): if os.system(cmd) != 0: die("command failed: %s" % cmd) +def p4_system(cmd): + """Specifically invoke p4 as the system command. """ + real_cmd = "%s %s" % ("p4", cmd) + if verbose: + print real_cmd + return system(real_cmd) + def isP4Exec(kind): """Determine if a Perforce 'kind' should have execute permission -- cgit v1.2.3 From 87b611d5fd518e4754e599bc2f348f83db410c56 Mon Sep 17 00:00:00 2001 From: Anand Kumria Date: Sun, 10 Aug 2008 19:26:27 +0100 Subject: Utilise the new 'p4_system' function. Signed-off-by: Anand Kumria Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 08acd517ba..2ed36ecd6b 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -98,7 +98,7 @@ def setP4ExecBit(file, mode): if p4Type[-1] == "+": p4Type = p4Type[0:-1] - system("p4 reopen -t %s %s" % (p4Type, file)) + p4_system("reopen -t %s %s" % (p4Type, file)) def getP4OpenedType(file): # Returns the perforce file type for the given file. @@ -561,7 +561,7 @@ class P4Submit(Command): modifier = diff['status'] path = diff['src'] if modifier == "M": - system("p4 edit \"%s\"" % path) + p4_system("edit \"%s\"" % path) if isModeExecChanged(diff['src_mode'], diff['dst_mode']): filesToChangeExecBit[path] = diff['dst_mode'] editedFiles.add(path) @@ -576,8 +576,8 @@ class P4Submit(Command): filesToAdd.remove(path) elif modifier == "R": src, dest = diff['src'], diff['dst'] - system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest)) - system("p4 edit \"%s\"" % (dest)) + p4_system("integrate -Dt \"%s\" \"%s\"" % (src, dest)) + p4_system("edit \"%s\"" % (dest)) if isModeExecChanged(diff['src_mode'], diff['dst_mode']): filesToChangeExecBit[dest] = diff['dst_mode'] os.unlink(dest) @@ -601,7 +601,7 @@ class P4Submit(Command): if response == "s": print "Skipping! Good luck with the next patches..." for f in editedFiles: - system("p4 revert \"%s\"" % f); + p4_system("revert \"%s\"" % f); for f in filesToAdd: system("rm %s" %f) return @@ -624,10 +624,10 @@ class P4Submit(Command): system(applyPatchCmd) for f in filesToAdd: - system("p4 add \"%s\"" % f) + p4_system("add \"%s\"" % f) for f in filesToDelete: - system("p4 revert \"%s\"" % f) - system("p4 delete \"%s\"" % f) + p4_system("revert \"%s\"" % f) + p4_system("delete \"%s\"" % f) # Set/clear executable bits for f in filesToChangeExecBit.keys(): @@ -728,7 +728,7 @@ class P4Submit(Command): os.chdir(self.clientPath) print "Syncronizing p4 checkout..." - system("p4 sync ...") + p4_system("sync ...") self.check() -- cgit v1.2.3 From 21a50753852cb51b120ec9933416daa6cea6d184 Mon Sep 17 00:00:00 2001 From: Anand Kumria Date: Sun, 10 Aug 2008 19:26:28 +0100 Subject: Add a single command that will be used to construct the 'p4' command Rather than having three locations where the 'p4' command is built up, refactor this into the one place. This will, eventually, allow us to have one place where we modify the evironment or pass extra command-line options to the 'p4' binary. Signed-off-by: Anand Kumria Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 2ed36ecd6b..b4acf7689d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -16,6 +16,17 @@ from sets import Set; verbose = False + +def p4_build_cmd(cmd): + """Build a suitable p4 command line. + + This consolidates building and returning a p4 command line into one + location. It means that hooking into the environment, or other configuration + can be done more easily. + """ + real_cmd = "%s %s" % ("p4", cmd) + return real_cmd + def die(msg): if verbose: raise Exception(msg) -- cgit v1.2.3 From ee06427aa6d975c35b63c3cd103ace43fbde062b Mon Sep 17 00:00:00 2001 From: Anand Kumria Date: Sun, 10 Aug 2008 19:26:29 +0100 Subject: If we are in verbose mode, output what we are about to run (or return) Signed-off-by: Anand Kumria Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 2 ++ 1 file changed, 2 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index b4acf7689d..d36b0c6bec 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -25,6 +25,8 @@ def p4_build_cmd(cmd): can be done more easily. """ real_cmd = "%s %s" % ("p4", cmd) + if verbose: + print real_cmd return real_cmd def die(msg): -- cgit v1.2.3 From 155af83491b26d958b147c93620816846343b019 Mon Sep 17 00:00:00 2001 From: Anand Kumria Date: Sun, 10 Aug 2008 19:26:30 +0100 Subject: Switch to using 'p4_build_cmd' Signed-off-by: Anand Kumria Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d36b0c6bec..2b6ea74d1c 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -72,9 +72,7 @@ def read_pipe_lines(c): def p4_read_pipe_lines(c): """Specifically invoke p4 on the command supplied. """ - real_cmd = "%s %s" % ("p4", c) - if verbose: - print real_cmd + real_cmd = p4_build_cmd(c) return read_pipe_lines(real_cmd) def system(cmd): @@ -85,9 +83,7 @@ def system(cmd): def p4_system(cmd): """Specifically invoke p4 as the system command. """ - real_cmd = "%s %s" % ("p4", cmd) - if verbose: - print real_cmd + real_cmd = p4_build_cmd(cmd) return system(real_cmd) def isP4Exec(kind): @@ -172,7 +168,7 @@ def isModeExecChanged(src_mode, dst_mode): return isModeExec(src_mode) != isModeExec(dst_mode) def p4CmdList(cmd, stdin=None, stdin_mode='w+b'): - cmd = "p4 -G %s" % cmd + cmd = p4_build_cmd("-G %s" % (cmd)) if verbose: sys.stderr.write("Opening pipe: %s\n" % cmd) -- cgit v1.2.3 From abcaf07360357cf2e9ce4b34e44adc09bb5587f0 Mon Sep 17 00:00:00 2001 From: Anand Kumria Date: Sun, 10 Aug 2008 19:26:31 +0100 Subject: If the user has configured various parameters, use them. Some repositories require authentication and access to certain hosts. Allow git-p4 to pull this information from the configuration Signed-off-by: Anand Kumria Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 2b6ea74d1c..a927e50b25 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -24,7 +24,29 @@ def p4_build_cmd(cmd): location. It means that hooking into the environment, or other configuration can be done more easily. """ - real_cmd = "%s %s" % ("p4", cmd) + real_cmd = "%s " % "p4" + + user = gitConfig("git-p4.user") + if len(user) > 0: + real_cmd += "-u %s " % user + + password = gitConfig("git-p4.password") + if len(password) > 0: + real_cmd += "-P %s " % password + + port = gitConfig("git-p4.port") + if len(port) > 0: + real_cmd += "-p %s " % port + + host = gitConfig("git-p4.host") + if len(host) > 0: + real_cmd += "-h %s " % host + + client = gitConfig("git-p4.client") + if len(client) > 0: + real_cmd += "-c %s " % client + + real_cmd += "%s" % (cmd) if verbose: print real_cmd return real_cmd -- cgit v1.2.3 From 3cafb7d8ce63effe6bf477182d431ecb4470eded Mon Sep 17 00:00:00 2001 From: Anand Kumria Date: Sun, 10 Aug 2008 19:26:32 +0100 Subject: Consistently use 'git-p4' for the configuration entries Signed-off-by: Anand Kumria Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index a927e50b25..6c64224b77 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1444,7 +1444,7 @@ class P4Sync(Command): if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes and gitBranchExists(self.branch): system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch)) - if self.useClientSpec or gitConfig("p4.useclientspec") == "true": + if self.useClientSpec or gitConfig("git-p4.useclientspec") == "true": self.getClientSpec() # TODO: should always look at previous commits, -- cgit v1.2.3 From d9429194f6e30e1f6f46a286217cd88972e1c83b Mon Sep 17 00:00:00 2001 From: Anand Kumria Date: Thu, 14 Aug 2008 23:40:38 +0100 Subject: Add p4 read_pipe and write_pipe wrappers Two additional wrappers to cover 3 places where we utilise p4 in piped form. Found by Tor Arvid Lund. Signed-off-by: Anand Kumria Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6c64224b77..3e9df70f29 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -69,6 +69,10 @@ def write_pipe(c, str): return val +def p4_write_pipe(c, str): + real_cmd = p4_build_cmd(c) + return write_pipe(c, str) + def read_pipe(c, ignore_error=False): if verbose: sys.stderr.write('Reading pipe: %s\n' % c) @@ -80,6 +84,9 @@ def read_pipe(c, ignore_error=False): return val +def p4_read_pipe(c, ignore_error=False): + real_cmd = p4_build_cmd(c) + return read_pipe(real_cmd, ignore_error) def read_pipe_lines(c): if verbose: -- cgit v1.2.3 From a7d3ef9d099ab00a19595bc3ca8abdc1fc6ff35d Mon Sep 17 00:00:00 2001 From: Anand Kumria Date: Thu, 14 Aug 2008 23:40:39 +0100 Subject: Utilise our new p4_read_pipe and p4_write_pipe wrappers Signed-off-by: Anand Kumria Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3e9df70f29..12fa9d3fd8 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -141,7 +141,7 @@ def setP4ExecBit(file, mode): def getP4OpenedType(file): # Returns the perforce file type for the given file. - result = read_pipe("p4 opened %s" % file) + result = p4_read_pipe("opened %s" % file) match = re.match(".*\((.+)\)\r?$", result) if match: return match.group(1) @@ -681,7 +681,7 @@ class P4Submit(Command): submitTemplate = self.prepareLogMessage(template, logMessage) if os.environ.has_key("P4DIFF"): del(os.environ["P4DIFF"]) - diff = read_pipe("p4 diff -du ...") + diff = p4_read_pipe("diff -du ...") newdiff = "" for newFile in filesToAdd: @@ -719,7 +719,7 @@ class P4Submit(Command): if self.isWindows: submitTemplate = submitTemplate.replace("\r\n", "\n") - write_pipe("p4 submit -i", submitTemplate) + p4_write_pipe("submit -i", submitTemplate) else: fileName = "submit.txt" file = open(fileName, "w+") -- cgit v1.2.3 From 053fd0c1c3da20474c4ff175c56ea4c1d6eeda11 Mon Sep 17 00:00:00 2001 From: Robert Blum Date: Fri, 1 Aug 2008 12:50:03 -0700 Subject: git-p4: chdir now properly sets PWD environment variable in msysGit P4 on Windows expects the PWD environment variable to be set to the current working dir, but os.chdir in python doesn't do so. Signed-off-by: Robert Blum Acked-by: Simon Hausmann Acked-by: Han-Wen Nienhuys Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6ae0429c2d..3f2303dcf0 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -16,6 +16,11 @@ from sets import Set; verbose = False +def chdir(dir): + if os.name == 'nt': + os.environ['PWD']=dir + os.chdir(dir) + def die(msg): if verbose: raise Exception(msg) @@ -712,7 +717,7 @@ class P4Submit(Command): print "Perforce checkout for depot path %s located at %s" % (self.depotPath, self.clientPath) self.oldWorkingDirectory = os.getcwd() - os.chdir(self.clientPath) + chdir(self.clientPath) print "Syncronizing p4 checkout..." system("p4 sync ...") @@ -732,7 +737,7 @@ class P4Submit(Command): if len(commits) == 0: print "All changes applied!" - os.chdir(self.oldWorkingDirectory) + chdir(self.oldWorkingDirectory) sync = P4Sync() sync.run([]) @@ -1670,7 +1675,7 @@ class P4Clone(P4Sync): print "Importing from %s into %s" % (', '.join(depotPaths), self.cloneDestination) if not os.path.exists(self.cloneDestination): os.makedirs(self.cloneDestination) - os.chdir(self.cloneDestination) + chdir(self.cloneDestination) system("git init") self.gitdir = os.getcwd() + "/.git" if not P4Sync.run(self, depotPaths): @@ -1782,7 +1787,7 @@ def main(): if os.path.exists(cmd.gitdir): cdup = read_pipe("git rev-parse --show-cdup").strip() if len(cdup) > 0: - os.chdir(cdup); + chdir(cdup); if not isValidGitDir(cmd.gitdir): if isValidGitDir(cmd.gitdir + "/.git"): -- cgit v1.2.3 From 893d340f2c735dc85b9360556ccd46cc0bf27fc0 Mon Sep 17 00:00:00 2001 From: Tor Arvid Lund Date: Thu, 21 Aug 2008 23:11:40 +0200 Subject: git-p4: Fix one-liner in p4_write_pipe function. The function built a p4 command string via the p4_build_cmd function, but ignored the result. Signed-off-by: Tor Arvid Lund Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index f9865b444f..46136d49bf 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -76,7 +76,7 @@ def write_pipe(c, str): def p4_write_pipe(c, str): real_cmd = p4_build_cmd(c) - return write_pipe(c, str) + return write_pipe(real_cmd, str) def read_pipe(c, ignore_error=False): if verbose: -- cgit v1.2.3 From cdc7e388da47b66fe11c92ed7698ec233ce70635 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 27 Aug 2008 09:30:29 +0200 Subject: Make it possible to abort the submission of a change to Perforce Currently it is not possible to skip the submission of a change to Perforce when running git-p4 submit. This patch compares the modification time before and after the submit editor invokation and offers a prompt for skipping if the submit template file was not saved. Signed-off-by: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 46136d49bf..c1d24b38f3 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -708,6 +708,7 @@ class P4Submit(Command): newdiff = newdiff.replace("\n", "\r\n") tmpFile.write(submitTemplate + separatorLine + diff + newdiff) tmpFile.close() + mtime = os.stat(fileName).st_mtime defaultEditor = "vi" if platform.system() == "Windows": defaultEditor = "notepad" @@ -716,15 +717,29 @@ class P4Submit(Command): else: editor = os.environ.get("EDITOR", defaultEditor); system(editor + " " + fileName) - tmpFile = open(fileName, "rb") - message = tmpFile.read() - tmpFile.close() - os.remove(fileName) - submitTemplate = message[:message.index(separatorLine)] - if self.isWindows: - submitTemplate = submitTemplate.replace("\r\n", "\n") - p4_write_pipe("submit -i", submitTemplate) + response = "y" + if os.stat(fileName).st_mtime <= mtime: + response = "x" + while response != "y" and response != "n": + response = raw_input("Submit template unchanged. Submit anyway? [y]es, [n]o (skip this patch) ") + + if response == "y": + tmpFile = open(fileName, "rb") + message = tmpFile.read() + tmpFile.close() + submitTemplate = message[:message.index(separatorLine)] + if self.isWindows: + submitTemplate = submitTemplate.replace("\r\n", "\n") + p4_write_pipe("submit -i", submitTemplate) + else: + for f in editedFiles: + p4_system("revert \"%s\"" % f); + for f in filesToAdd: + p4_system("revert \"%s\"" % f); + system("rm %s" %f) + + os.remove(fileName) else: fileName = "submit.txt" file = open(fileName, "w+") -- cgit v1.2.3 From e990501312e22cfa910d88dc7143bc4eb3632ae1 Mon Sep 17 00:00:00 2001 From: Tor Arvid Lund Date: Thu, 28 Aug 2008 00:36:12 +0200 Subject: git-p4: Fix checkout bug when using --import-local. When this option is passed to git p4 clone, the checkout at the end would previously fail. This patch fixes it by optionally creating the master branch from refs/heads/p4/master, which is the correct one for this option. Signed-off-by: Tor Arvid Lund Acked-By: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index c1d24b38f3..2216cacba7 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1748,8 +1748,12 @@ class P4Clone(P4Sync): if not P4Sync.run(self, depotPaths): return False if self.branch != "master": - if gitBranchExists("refs/remotes/p4/master"): - system("git branch master refs/remotes/p4/master") + if self.importIntoRemotes: + masterbranch = "refs/remotes/p4/master" + else: + masterbranch = "refs/heads/p4/master" + if gitBranchExists(masterbranch): + system("git branch master %s" % masterbranch) system("git checkout -f") else: print "Could not detect main branch. No checkout/master branch created." -- cgit v1.2.3 From 7f96e2e25aa008556a4ede7a65de8488eb9890e6 Mon Sep 17 00:00:00 2001 From: John Chapman Date: Sat, 8 Nov 2008 14:22:48 +1100 Subject: git-p4: Support purged files and optimize memory usage Purged files are handled as if they are merely deleted, which is not entirely optimal, but I don't know of any other way to handle them. File data is deleted from memory as early as they can, and they are more efficiently handled, at (significant) cost to CPU usage. Still need to handle p4 branches with spaces in their names. Still need to make git-p4 clone more reliable. - Perhaps with a --continue option. (Sometimes the p4 server kills the connection) Signed-off-by: John Chapman Acked-by: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 2216cacba7..38d1a17333 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -946,7 +946,7 @@ class P4Sync(Command): if includeFile: filesForCommit.append(f) - if f['action'] != 'delete': + if f['action'] not in ('delete', 'purge'): filesToRead.append(f) filedata = [] @@ -965,11 +965,11 @@ class P4Sync(Command): while j < len(filedata): stat = filedata[j] j += 1 - text = []; + text = '' while j < len(filedata) and filedata[j]['code'] in ('text', 'unicode', 'binary'): - text.append(filedata[j]['data']) + text += filedata[j]['data'] + del filedata[j]['data'] j += 1 - text = ''.join(text) if not stat.has_key('depotFile'): sys.stderr.write("p4 print fails with: %s\n" % repr(stat)) @@ -1038,7 +1038,7 @@ class P4Sync(Command): continue relPath = self.stripRepoPath(file['path'], branchPrefixes) - if file["action"] == "delete": + if file["action"] in ("delete", "purge"): self.gitStream.write("D %s\n" % relPath) else: data = file['data'] @@ -1077,7 +1077,7 @@ class P4Sync(Command): cleanedFiles = {} for info in files: - if info["action"] == "delete": + if info["action"] in ("delete", "purge"): continue cleanedFiles[info["depotFile"]] = info["rev"] @@ -1400,7 +1400,7 @@ class P4Sync(Command): if change > newestRevision: newestRevision = change - if info["action"] == "delete": + if info["action"] in ("delete", "purge"): # don't increase the file cnt, otherwise details["depotFile123"] will have gaps! #fileCnt = fileCnt + 1 continue -- cgit v1.2.3 From 36bd844658cf244ec2c6756c18673a4b7ed8ec9e Mon Sep 17 00:00:00 2001 From: John Chapman Date: Sat, 8 Nov 2008 14:22:49 +1100 Subject: git-p4: Cache git config for performance This makes git-p4 noticibly faster on Windows. Signed-off-by: John Chapman Acked-by: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 38d1a17333..9f0a5f92c1 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -316,8 +316,11 @@ def gitBranchExists(branch): stderr=subprocess.PIPE, stdout=subprocess.PIPE); return proc.wait() == 0; +_gitConfig = {} def gitConfig(key): - return read_pipe("git config %s" % key, ignore_error=True).strip() + if not _gitConfig.has_key(key): + _gitConfig[key] = read_pipe("git config %s" % key, ignore_error=True).strip() + return _gitConfig[key] def p4BranchesInGit(branchesAreInRemotes = True): branches = {} -- cgit v1.2.3 From 3d51c853df5730212f704a526340a5a059dffeda Mon Sep 17 00:00:00 2001 From: Pete Wyckoff Date: Wed, 26 Nov 2008 13:52:15 -0500 Subject: git-p4: fix keyword-expansion regex This text: my $dir = $File::Find::dir; return if ($dir !~ m,$options->{dirpat}$,); was improperly converted to: my $dir = $File$dir !~ m,$options->{dirpat}$,); by the keyword identifier expansion code. Add a \n to make sure the regex doesn't go across end-of-line boundaries. Signed-off-by: Pete Wyckoff Acked-by: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 46136d49bf..2b122d3f51 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -963,7 +963,7 @@ class P4Sync(Command): if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'): text = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', text) elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'): - text = re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', text) + text = re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$\n]*\$',r'$\1$', text) contents[stat['depotFile']] = text -- cgit v1.2.3 From 7f705dc3686c2b1c77172b6847c1406eb66a20c3 Mon Sep 17 00:00:00 2001 From: Tor Arvid Lund Date: Thu, 4 Dec 2008 14:37:33 +0100 Subject: git-p4: Fix bug in p4Where method. When running: p4 where //depot/SomePath/... The result can in some situations look like: //depot/SomePath/... //client/SomePath/... /home/user/p4root/SomePath/... -//depot/SomePath/UndesiredSubdir/... //client/SomePath/UndesiredSubdir/... /home/user/p4root/SomePath/UndesiredSubdir/... This depends on the users Client view. The current p4Where method will now return /home/user/p4root/SomePath/UndesiredSubdir/... which is not what we want. This patch loops through the results from "p4 where", and picks the one where the depotFile exactly matches the given depotPath (//depot/SomePath/... in this example). Signed-off-by: Tor Arvid Lund Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index b44fbfc9b3..ee504e90ed 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -245,7 +245,15 @@ def p4Cmd(cmd): def p4Where(depotPath): if not depotPath.endswith("/"): depotPath += "/" - output = p4Cmd("where %s..." % depotPath) + depotPath = depotPath + "..." + outputList = p4CmdList("where %s" % depotPath) + output = None + for entry in outputList: + if entry["depotFile"] == depotPath: + output = entry + break + if output == None: + return "" if output["code"] == "error": return "" clientPath = "" -- cgit v1.2.3 From 75bc9573b0e332c34bc1c3d97306077fda573083 Mon Sep 17 00:00:00 2001 From: Tor Arvid Lund Date: Tue, 9 Dec 2008 16:41:50 +0100 Subject: git-p4: Fix regression in p4Where method. Unfortunately, I introduced a bug in commit 7f705dc36 (git-p4: Fix bug in p4Where method). This happens because sometimes the result from "p4 where " doesn't contain a "depotFile" key, but instead a "data" key that needs further parsing. This commit should ensure that both of these cases are checked. Signed-off-by: Tor Arvid Lund Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index ee504e90ed..a85a7b2a58 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -249,9 +249,16 @@ def p4Where(depotPath): outputList = p4CmdList("where %s" % depotPath) output = None for entry in outputList: - if entry["depotFile"] == depotPath: - output = entry - break + if "depotFile" in entry: + if entry["depotFile"] == depotPath: + output = entry + break + elif "data" in entry: + data = entry.get("data") + space = data.find(" ") + if data[:space] == depotPath: + output = entry + break if output == None: return "" if output["code"] == "error": -- cgit v1.2.3 From b4b0ba06f8748348039d56ffa5890590dd9776ee Mon Sep 17 00:00:00 2001 From: Pete Wyckoff Date: Wed, 18 Feb 2009 13:12:14 -0500 Subject: git-p4: avoid syncing duplicate changes When a particular changeset affects multiple depot paths, it will appear multiple times in the output of "p4 changes". Filter out the duplicates to avoid the extra empty commits that this otherwise would create. Signed-off-by: Pete Wyckoff Acked-by: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index a85a7b2a58..3832f60225 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -442,13 +442,14 @@ def p4ChangesForPaths(depotPaths, changeRange): output = p4_read_pipe_lines("changes " + ' '.join (["%s...%s" % (p, changeRange) for p in depotPaths])) - changes = [] + changes = {} for line in output: - changeNum = line.split(" ")[1] - changes.append(int(changeNum)) + changeNum = int(line.split(" ")[1]) + changes[changeNum] = True - changes.sort() - return changes + changelist = changes.keys() + changelist.sort() + return changelist class Command: def __init__(self): -- cgit v1.2.3 From 3b167396b416541f7559f3141392d56b93ea049c Mon Sep 17 00:00:00 2001 From: Pete Wyckoff Date: Fri, 27 Feb 2009 10:53:59 -0800 Subject: git-p4: remove tabs from usermap file Some users have tabs in their names, oddly enough. This causes problems when loading the usercache from disk, as split separates the fields on the wrong tabs. When fast-import's parse_ident() tries to parse the committer field, it is unhappy about the unbalanced <..> angle brackets. It is easy enough to convert the tabs to single spaces. Signed-off-by: Pete Wyckoff Acked-by: Simon Hausmann Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/fast-import/git-p4') diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 3832f60225..342529db30 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -1142,7 +1142,7 @@ class P4Sync(Command): s = '' for (key, val) in self.users.items(): - s += "%s\t%s\n" % (key, val) + s += "%s\t%s\n" % (key.expandtabs(1), val.expandtabs(1)) open(self.getUserCacheFilename(), "wb").write(s) self.userMapFromPerforceServer = True -- cgit v1.2.3