First version of a new script to submit changes back to perforce from git repositories.
Signed-off-by: Simon Hausmann <hausmann@kde.org>
This commit is contained in:
parent
4fe2ca17f7
commit
0bcff6121d
208
contrib/fast-import/p4-git-sync.py
Executable file
208
contrib/fast-import/p4-git-sync.py
Executable file
@ -0,0 +1,208 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# p4-git-sync.py
|
||||
#
|
||||
# Author: Simon Hausmann <hausmann@kde.org>
|
||||
# License: MIT <http://www.opensource.org/licenses/mit-license.php>
|
||||
#
|
||||
|
||||
import os, string, shelve, stat
|
||||
import getopt, sys, marshal
|
||||
|
||||
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;
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "", [ "continue", "--git-dir=", "origin=", "reset", "master=",
|
||||
"submit-log-subst=" ])
|
||||
except getopt.GetoptError:
|
||||
print "fixme, syntax error"
|
||||
sys.exit(1)
|
||||
|
||||
logSubstitutions = {}
|
||||
logSubstitutions["<enter description here>"] = "%log%"
|
||||
logSubstitutions["\tDetails:"] = "\tDetails: %log%"
|
||||
gitdir = os.environ.get("GIT_DIR", "")
|
||||
origin = "origin"
|
||||
master = "master"
|
||||
firstTime = True
|
||||
reset = False
|
||||
|
||||
for o, a in opts:
|
||||
if o == "--git-dir":
|
||||
gitdir = a
|
||||
elif o == "--origin":
|
||||
origin = a
|
||||
elif o == "--master":
|
||||
master = a
|
||||
elif o == "--continue":
|
||||
firstTime = False
|
||||
elif o == "--reset":
|
||||
reset = True
|
||||
firstTime = True
|
||||
elif o == "--submit-log-subst":
|
||||
key = a.split("%")[0]
|
||||
value = a.split("%")[1]
|
||||
logSubstitutions[key] = value
|
||||
|
||||
if len(gitdir) == 0:
|
||||
gitdir = ".git"
|
||||
else:
|
||||
os.environ["GIT_DIR"] = gitdir
|
||||
|
||||
configFile = gitdir + "/p4-git-sync.cfg"
|
||||
|
||||
origin = "origin"
|
||||
if len(args) == 1:
|
||||
origin = args[0]
|
||||
|
||||
def die(msg):
|
||||
sys.stderr.write(msg + "\n")
|
||||
sys.exit(1)
|
||||
|
||||
def system(cmd):
|
||||
if os.system(cmd) != 0:
|
||||
die("command failed: %s" % cmd)
|
||||
|
||||
def check():
|
||||
return
|
||||
if len(p4CmdList("opened ...")) > 0:
|
||||
die("You have files opened with perforce! Close them before starting the sync.")
|
||||
|
||||
def start(config):
|
||||
if len(config) > 0 and not reset:
|
||||
die("Cannot start sync. Previous sync config found at %s" % configFile)
|
||||
|
||||
#if len(os.popen("git-update-index --refresh").read()) > 0:
|
||||
# die("Your working tree is not clean. Check with git status!")
|
||||
|
||||
commits = []
|
||||
for line in os.popen("git-rev-list --no-merges %s..%s" % (origin, master)).readlines():
|
||||
commits.append(line[:-1])
|
||||
commits.reverse()
|
||||
|
||||
config["commits"] = commits
|
||||
|
||||
# print "Cleaning index..."
|
||||
# system("git checkout -f")
|
||||
|
||||
def prepareLogMessage(template, message):
|
||||
result = ""
|
||||
|
||||
substs = logSubstitutions
|
||||
for k in substs.keys():
|
||||
substs[k] = substs[k].replace("%log%", message)
|
||||
|
||||
for line in template.split("\n"):
|
||||
if line.startswith("#"):
|
||||
result += line + "\n"
|
||||
continue
|
||||
|
||||
substituted = False
|
||||
for key in substs.keys():
|
||||
if line.find(key) != -1:
|
||||
value = substs[key]
|
||||
if value != "@remove@":
|
||||
result += line.replace(key, value) + "\n"
|
||||
substituted = True
|
||||
break
|
||||
|
||||
if not substituted:
|
||||
result += line + "\n"
|
||||
|
||||
return result
|
||||
|
||||
def apply(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))
|
||||
|
||||
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():
|
||||
log = log[:-1]
|
||||
if not foundTitle:
|
||||
if len(log) == 0:
|
||||
foundTitle = 1
|
||||
continue
|
||||
|
||||
if len(logMessage) > 0:
|
||||
logMessage += "\t"
|
||||
logMessage += log + "\n"
|
||||
|
||||
template = os.popen("p4 change -o").read()
|
||||
fileName = "submit.txt"
|
||||
file = open(fileName, "w+")
|
||||
file.write(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)
|
||||
|
||||
check()
|
||||
|
||||
config = shelve.open(configFile, writeback=True)
|
||||
|
||||
if firstTime:
|
||||
start(config)
|
||||
|
||||
commits = config.get("commits", [])
|
||||
|
||||
if len(commits) > 0:
|
||||
firstTime = False
|
||||
commit = commits[0]
|
||||
commits = commits[1:]
|
||||
config["commits"] = commits
|
||||
apply(commit)
|
||||
|
||||
config.close()
|
||||
|
||||
if len(commits) == 0:
|
||||
if firstTime:
|
||||
print "No changes found to apply between %s and current HEAD" % origin
|
||||
else:
|
||||
print "All changes applied!"
|
||||
os.remove(configFile)
|
||||
|
Loading…
Reference in New Issue
Block a user