5 # Author: Simon Hausmann <hausmann@kde.org>
6 # Copyright: 2007 Simon Hausmann <hausmann@kde.org>
8 # License: MIT <http://www.opensource.org/licenses/mit-license.php>
11 import os
, string
, shelve
, stat
12 import getopt
, sys
, marshal
, tempfile
15 cmd
= "p4 -G %s" % cmd
16 pipe
= os
.popen(cmd
, "rb")
21 entry
= marshal
.load(pipe
)
37 sys
.stderr
.write(msg
+ "\n")
41 if os
.path
.exists(path
+ "/HEAD") and os
.path
.exists(path
+ "/refs") and os
.path
.exists(path
+ "/objects"):
46 opts
, args
= getopt
.getopt(sys
.argv
[1:], "", [ "continue", "git-dir=", "origin=", "reset", "master=",
47 "submit-log-subst=", "log-substitutions=", "noninteractive",
49 except getopt
.GetoptError
:
50 print "fixme, syntax error"
54 logSubstitutions
["<enter description here>"] = "%log%"
55 logSubstitutions
["\tDetails:"] = "\tDetails: %log%"
56 gitdir
= os
.environ
.get("GIT_DIR", "")
71 elif o
== "--continue":
76 elif o
== "--submit-log-subst":
78 value
= a
.split("%")[1]
79 logSubstitutions
[key
] = value
80 elif o
== "--log-substitutions":
81 for line
in open(a
, "r").readlines():
82 tokens
= line
[:-1].split("=")
83 logSubstitutions
[tokens
[0]] = tokens
[1]
84 elif o
== "--noninteractive":
86 elif o
== "--dry-run":
92 os
.environ
["GIT_DIR"] = gitdir
94 if not tryGitDir(gitdir
):
95 if tryGitDir(gitdir
+ "/.git"):
97 os
.environ
["GIT_DIR"] = gitdir
99 die("fatal: %s seems not to be a git repository." % gitdir
)
102 configFile
= gitdir
+ "/p4-git-sync.cfg"
109 sys
.stdout
.write("Auto-detecting current branch: ")
110 master
= os
.popen("git-name-rev HEAD").read().split(" ")[1][:-1]
111 if len(master
) == 0 or not os
.path
.exists("%s/refs/heads/%s" % (gitdir
, master
)):
112 die("\nFailed to detect current branch! Aborting!");
113 sys
.stdout
.write("%s\n" % master
)
116 if os
.system(cmd
) != 0:
117 die("command failed: %s" % cmd
)
120 if len(p4CmdList("opened ...")) > 0:
121 die("You have files opened with perforce! Close them before starting the sync.")
124 if len(config
) > 0 and not reset
:
125 die("Cannot start sync. Previous sync config found at %s" % configFile
)
127 #if len(os.popen("git-update-index --refresh").read()) > 0:
128 # die("Your working tree is not clean. Check with git status!")
131 for line
in os
.popen("git-rev-list --no-merges %s..%s" % (origin
, master
)).readlines():
132 commits
.append(line
[:-1])
135 config
["commits"] = commits
137 print "Creating temporary p4-sync branch from %s ..." % origin
138 system("git checkout -f -b p4-sync %s" % origin
)
140 # print "Cleaning index..."
141 # system("git checkout -f")
143 def prepareLogMessage(template
, message
):
146 for line
in template
.split("\n"):
147 if line
.startswith("#"):
148 result
+= line
+ "\n"
152 for key
in logSubstitutions
.keys():
153 if line
.find(key
) != -1:
154 value
= logSubstitutions
[key
]
155 value
= value
.replace("%log%", message
)
156 if value
!= "@remove@":
157 result
+= line
.replace(key
, value
) + "\n"
162 result
+= line
+ "\n"
168 print "Applying %s" % (os
.popen("git-log --max-count=1 --pretty=oneline %s" % id).read())
169 diff
= os
.popen("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)).readlines()
171 filesToDelete
= set()
174 path
= line
[1:].strip()
176 system("p4 edit %s" % path
)
177 elif modifier
== "A":
179 if path
in filesToDelete
:
180 filesToDelete
.remove(path
)
181 elif modifier
== "D":
182 filesToDelete
.add(path
)
183 if path
in filesToAdd
:
184 filesToAdd
.remove(path
)
186 die("unknown modifier %s for %s" % (modifier
, path
))
188 system("git-diff-files --name-only -z | git-update-index --remove -z --stdin")
189 system("git cherry-pick --no-commit \"%s\"" % id)
190 #system("git format-patch --stdout -k \"%s^\"..\"%s\" | git-am -k" % (id, id))
191 #system("git branch -D tmp")
192 #system("git checkout -f -b tmp \"%s^\"" % id)
195 system("p4 add %s" % f
)
196 for f
in filesToDelete
:
197 system("p4 revert %s" % f
)
198 system("p4 delete %s" % f
)
202 for log
in os
.popen("git-cat-file commit %s" % id).readlines():
208 if len(logMessage
) > 0:
212 template
= os
.popen("p4 change -o").read()
215 submitTemplate
= prepareLogMessage(template
, logMessage
)
216 diff
= os
.popen("p4 diff -du ...").read()
218 for newFile
in filesToAdd
:
219 diff
+= "==== new file ====\n"
220 diff
+= "--- /dev/null\n"
221 diff
+= "+++ %s\n" % newFile
222 f
= open(newFile
, "r")
223 for line
in f
.readlines():
227 pipe
= os
.popen("less", "w")
228 pipe
.write(submitTemplate
+ diff
)
232 while response
== "e":
233 response
= raw_input("Do you want to submit this change (y/e/n)? ")
235 [handle
, fileName
] = tempfile
.mkstemp()
236 tmpFile
= os
.fdopen(handle
, "w+")
237 tmpFile
.write(submitTemplate
)
239 editor
= os
.environ
.get("EDITOR", "vi")
240 system(editor
+ " " + fileName
)
241 tmpFile
= open(fileName
, "r")
242 submitTemplate
= tmpFile
.read()
246 if response
== "y" or response
== "yes":
249 raw_input("Press return to continue...")
251 pipe
= os
.popen("p4 submit -i", "w")
252 pipe
.write(submitTemplate
)
255 print "Not submitting!"
258 fileName
= "submit.txt"
259 file = open(fileName
, "w+")
260 file.write(prepareLogMessage(template
, logMessage
))
262 print "Perforce submit template written as %s. Please review/edit and then use p4 submit -i < %s to submit directly!" % (fileName
, fileName
)
266 config
= shelve
.open(configFile
, writeback
=True)
271 commits
= config
.get("commits", [])
273 while len(commits
) > 0:
276 commits
= commits
[1:]
277 config
["commits"] = commits
284 if len(commits
) == 0:
286 print "No changes found to apply between %s and current HEAD" % origin
288 print "All changes applied!"
289 print "Deleting temporary p4-sync branch and going back to %s" % master
290 system("git checkout %s" % master
)
291 system("git branch -D p4-sync")
292 print "Cleaning out your perforce checkout by doing p4 edit ... ; p4 revert ..."
293 system("p4 edit ... >/dev/null")
294 system("p4 revert ... >/dev/null")
295 os
.remove(configFile
)