comparison hgext/transplant.py @ 28480:db171c6a1697

transplant: switch to using nodemod for hex+short
author timeless <timeless@mozdev.org>
date Fri, 11 Mar 2016 16:07:22 +0000
parents dcb4209bd30d
children ec75c94262a5
comparison
equal deleted inserted replaced
28479:d62b00318c19 28480:db171c6a1697
14 map from a changeset hash to its hash in the source repository. 14 map from a changeset hash to its hash in the source repository.
15 ''' 15 '''
16 16
17 from mercurial.i18n import _ 17 from mercurial.i18n import _
18 import os, tempfile 18 import os, tempfile
19 from mercurial.node import short 19 from mercurial import node as nodemod
20 from mercurial import bundlerepo, hg, merge, match 20 from mercurial import bundlerepo, hg, merge, match
21 from mercurial import patch, revlog, scmutil, util, error, cmdutil 21 from mercurial import patch, revlog, scmutil, util, error, cmdutil
22 from mercurial import registrar, revset, templatekw, exchange 22 from mercurial import registrar, revset, templatekw, exchange
23 23
24 class TransplantError(error.Abort): 24 class TransplantError(error.Abort):
62 if not os.path.isdir(self.path): 62 if not os.path.isdir(self.path):
63 os.mkdir(self.path) 63 os.mkdir(self.path)
64 fp = self.opener(self.transplantfile, 'w') 64 fp = self.opener(self.transplantfile, 'w')
65 for list in self.transplants.itervalues(): 65 for list in self.transplants.itervalues():
66 for t in list: 66 for t in list:
67 l, r = map(revlog.hex, (t.lnode, t.rnode)) 67 l, r = map(nodemod.hex, (t.lnode, t.rnode))
68 fp.write(l + ':' + r + '\n') 68 fp.write(l + ':' + r + '\n')
69 fp.close() 69 fp.close()
70 self.dirty = False 70 self.dirty = False
71 71
72 def get(self, rnode): 72 def get(self, rnode):
131 try: 131 try:
132 lock = repo.lock() 132 lock = repo.lock()
133 tr = repo.transaction('transplant') 133 tr = repo.transaction('transplant')
134 for rev in revs: 134 for rev in revs:
135 node = revmap[rev] 135 node = revmap[rev]
136 revstr = '%s:%s' % (rev, short(node)) 136 revstr = '%s:%s' % (rev, nodemod.short(node))
137 137
138 if self.applied(repo, node, p1): 138 if self.applied(repo, node, p1):
139 self.ui.warn(_('skipping already applied revision %s\n') % 139 self.ui.warn(_('skipping already applied revision %s\n') %
140 revstr) 140 revstr)
141 continue 141 continue
166 166
167 skipmerge = False 167 skipmerge = False
168 if parents[1] != revlog.nullid: 168 if parents[1] != revlog.nullid:
169 if not opts.get('parent'): 169 if not opts.get('parent'):
170 self.ui.note(_('skipping merge changeset %s:%s\n') 170 self.ui.note(_('skipping merge changeset %s:%s\n')
171 % (rev, short(node))) 171 % (rev, nodemod.short(node)))
172 skipmerge = True 172 skipmerge = True
173 else: 173 else:
174 parent = source.lookup(opts['parent']) 174 parent = source.lookup(opts['parent'])
175 if parent not in parents: 175 if parent not in parents:
176 raise error.Abort(_('%s is not a parent of %s') % 176 raise error.Abort(_('%s is not a parent of %s') %
177 (short(parent), short(node))) 177 (nodemod.short(parent),
178 nodemod.short(node)))
178 else: 179 else:
179 parent = parents[0] 180 parent = parents[0]
180 181
181 if skipmerge: 182 if skipmerge:
182 patchfile = None 183 patchfile = None
202 # fix the merge or cancel everything 203 # fix the merge or cancel everything
203 tr.close() 204 tr.close()
204 raise 205 raise
205 if n and domerge: 206 if n and domerge:
206 self.ui.status(_('%s merged at %s\n') % (revstr, 207 self.ui.status(_('%s merged at %s\n') % (revstr,
207 short(n))) 208 nodemod.short(n)))
208 elif n: 209 elif n:
209 self.ui.status(_('%s transplanted to %s\n') 210 self.ui.status(_('%s transplanted to %s\n')
210 % (short(node), 211 % (nodemod.short(node),
211 short(n))) 212 nodemod.short(n)))
212 finally: 213 finally:
213 if patchfile: 214 if patchfile:
214 os.unlink(patchfile) 215 os.unlink(patchfile)
215 tr.close() 216 tr.close()
216 if pulls: 217 if pulls:
239 240
240 try: 241 try:
241 self.ui.system('%s %s %s' % (filter, util.shellquote(headerfile), 242 self.ui.system('%s %s %s' % (filter, util.shellquote(headerfile),
242 util.shellquote(patchfile)), 243 util.shellquote(patchfile)),
243 environ={'HGUSER': changelog[1], 244 environ={'HGUSER': changelog[1],
244 'HGREVISION': revlog.hex(node), 245 'HGREVISION': nodemod.hex(node),
245 }, 246 },
246 onerr=error.Abort, errprefix=_('filter failed')) 247 onerr=error.Abort, errprefix=_('filter failed'))
247 user, date, msg = self.parselog(file(headerfile))[1:4] 248 user, date, msg = self.parselog(file(headerfile))[1:4]
248 finally: 249 finally:
249 os.unlink(headerfile) 250 os.unlink(headerfile)
259 if filter: 260 if filter:
260 (user, date, message) = self.filter(filter, node, cl, patchfile) 261 (user, date, message) = self.filter(filter, node, cl, patchfile)
261 262
262 if log: 263 if log:
263 # we don't translate messages inserted into commits 264 # we don't translate messages inserted into commits
264 message += '\n(transplanted from %s)' % revlog.hex(node) 265 message += '\n(transplanted from %s)' % nodemod.hex(node)
265 266
266 self.ui.status(_('applying %s\n') % short(node)) 267 self.ui.status(_('applying %s\n') % nodemod.short(node))
267 self.ui.note('%s %s\n%s\n' % (user, date, message)) 268 self.ui.note('%s %s\n%s\n' % (user, date, message))
268 269
269 if not patchfile and not merge: 270 if not patchfile and not merge:
270 raise error.Abort(_('can only omit patchfile if merging')) 271 raise error.Abort(_('can only omit patchfile if merging'))
271 if patchfile: 272 if patchfile:
293 m = match.exact(repo.root, '', files) 294 m = match.exact(repo.root, '', files)
294 295
295 n = repo.commit(message, user, date, extra=extra, match=m, 296 n = repo.commit(message, user, date, extra=extra, match=m,
296 editor=self.getcommiteditor()) 297 editor=self.getcommiteditor())
297 if not n: 298 if not n:
298 self.ui.warn(_('skipping emptied changeset %s\n') % short(node)) 299 self.ui.warn(_('skipping emptied changeset %s\n') %
300 nodemod.short(node))
299 return None 301 return None
300 if not merge: 302 if not merge:
301 self.transplants.set(n, node) 303 self.transplants.set(n, node)
302 304
303 return n 305 return n
308 def resume(self, repo, source, opts): 310 def resume(self, repo, source, opts):
309 '''recover last transaction and apply remaining changesets''' 311 '''recover last transaction and apply remaining changesets'''
310 if os.path.exists(os.path.join(self.path, 'journal')): 312 if os.path.exists(os.path.join(self.path, 'journal')):
311 n, node = self.recover(repo, source, opts) 313 n, node = self.recover(repo, source, opts)
312 if n: 314 if n:
313 self.ui.status(_('%s transplanted as %s\n') % (short(node), 315 self.ui.status(_('%s transplanted as %s\n') %
314 short(n))) 316 (nodemod.short(node),
317 nodemod.short(n)))
315 else: 318 else:
316 self.ui.status(_('%s skipped due to empty diff\n') 319 self.ui.status(_('%s skipped due to empty diff\n')
317 % (short(node),)) 320 % (nodemod.short(node),))
318 seriespath = os.path.join(self.path, 'series') 321 seriespath = os.path.join(self.path, 'series')
319 if not os.path.exists(seriespath): 322 if not os.path.exists(seriespath):
320 self.transplants.write() 323 self.transplants.write()
321 return 324 return
322 nodes, merges = self.readseries() 325 nodes, merges = self.readseries()
339 if len(parents) > 1: 342 if len(parents) > 1:
340 if opts.get('parent'): 343 if opts.get('parent'):
341 parent = source.lookup(opts['parent']) 344 parent = source.lookup(opts['parent'])
342 if parent not in parents: 345 if parent not in parents:
343 raise error.Abort(_('%s is not a parent of %s') % 346 raise error.Abort(_('%s is not a parent of %s') %
344 (short(parent), short(node))) 347 (nodemod.short(parent),
348 nodemod.short(node)))
345 else: 349 else:
346 merge = True 350 merge = True
347 351
348 extra = {'transplant_source': node} 352 extra = {'transplant_source': node}
349 try: 353 try:
350 p1, p2 = repo.dirstate.parents() 354 p1, p2 = repo.dirstate.parents()
351 if p1 != parent: 355 if p1 != parent:
352 raise error.Abort(_('working directory not at transplant ' 356 raise error.Abort(_('working directory not at transplant '
353 'parent %s') % revlog.hex(parent)) 357 'parent %s') % nodemod.hex(parent))
354 if merge: 358 if merge:
355 repo.setparents(p1, parents[1]) 359 repo.setparents(p1, parents[1])
356 modified, added, removed, deleted = repo.status()[:4] 360 modified, added, removed, deleted = repo.status()[:4]
357 if merge or modified or added or removed or deleted: 361 if merge or modified or added or removed or deleted:
358 n = repo.commit(message, user, date, extra=extra, 362 n = repo.commit(message, user, date, extra=extra,
389 393
390 if not os.path.isdir(self.path): 394 if not os.path.isdir(self.path):
391 os.mkdir(self.path) 395 os.mkdir(self.path)
392 series = self.opener('series', 'w') 396 series = self.opener('series', 'w')
393 for rev in sorted(revmap): 397 for rev in sorted(revmap):
394 series.write(revlog.hex(revmap[rev]) + '\n') 398 series.write(nodemod.hex(revmap[rev]) + '\n')
395 if merges: 399 if merges:
396 series.write('# Merges\n') 400 series.write('# Merges\n')
397 for m in merges: 401 for m in merges:
398 series.write(revlog.hex(m) + '\n') 402 series.write(nodemod.hex(m) + '\n')
399 series.close() 403 series.close()
400 404
401 def parselog(self, fp): 405 def parselog(self, fp):
402 parents = [] 406 parents = []
403 message = [] 407 message = []
429 if not os.path.isdir(self.path): 433 if not os.path.isdir(self.path):
430 os.mkdir(self.path) 434 os.mkdir(self.path)
431 fp = self.opener('journal', 'w') 435 fp = self.opener('journal', 'w')
432 fp.write('# User %s\n' % user) 436 fp.write('# User %s\n' % user)
433 fp.write('# Date %s\n' % date) 437 fp.write('# Date %s\n' % date)
434 fp.write('# Node ID %s\n' % revlog.hex(p2)) 438 fp.write('# Node ID %s\n' % nodemod.hex(p2))
435 fp.write('# Parent ' + revlog.hex(p1) + '\n') 439 fp.write('# Parent ' + nodemod.hex(p1) + '\n')
436 if merge: 440 if merge:
437 fp.write('# Parent ' + revlog.hex(p2) + '\n') 441 fp.write('# Parent ' + nodemod.hex(p2) + '\n')
438 fp.write(message.rstrip() + '\n') 442 fp.write(message.rstrip() + '\n')
439 fp.close() 443 fp.close()
440 444
441 def readlog(self): 445 def readlog(self):
442 return self.parselog(self.opener('journal')) 446 return self.parselog(self.opener('journal'))
709 713
710 def kwtransplanted(repo, ctx, **args): 714 def kwtransplanted(repo, ctx, **args):
711 """:transplanted: String. The node identifier of the transplanted 715 """:transplanted: String. The node identifier of the transplanted
712 changeset if any.""" 716 changeset if any."""
713 n = ctx.extra().get('transplant_source') 717 n = ctx.extra().get('transplant_source')
714 return n and revlog.hex(n) or '' 718 return n and nodemod.hex(n) or ''
715 719
716 def extsetup(ui): 720 def extsetup(ui):
717 templatekw.keywords['transplanted'] = kwtransplanted 721 templatekw.keywords['transplanted'] = kwtransplanted
718 cmdutil.unfinishedstates.append( 722 cmdutil.unfinishedstates.append(
719 ['transplant/journal', True, False, _('transplant in progress'), 723 ['transplant/journal', True, False, _('transplant in progress'),