comparison hgext/transplant.py @ 46113:59fa3890d40a

node: import symbols explicitly There is no point in lazy importing mercurial.node, it is used all over the place anyway. So consistently import the used symbols directly. Fix one file using symbols indirectly via mercurial.revlog. Differential Revision: https://phab.mercurial-scm.org/D9480
author Joerg Sonnenberger <joerg@bec.de>
date Tue, 01 Dec 2020 21:54:46 +0100
parents 89a2afe31e82
children 0428e555acb7
comparison
equal deleted inserted replaced
46112:d6afa9c149c3 46113:59fa3890d40a
17 17
18 import os 18 import os
19 19
20 from mercurial.i18n import _ 20 from mercurial.i18n import _
21 from mercurial.pycompat import open 21 from mercurial.pycompat import open
22 from mercurial.node import (
23 bin,
24 hex,
25 nullid,
26 short,
27 )
22 from mercurial import ( 28 from mercurial import (
23 bundlerepo, 29 bundlerepo,
24 cmdutil, 30 cmdutil,
25 error, 31 error,
26 exchange, 32 exchange,
27 hg, 33 hg,
28 logcmdutil, 34 logcmdutil,
29 match, 35 match,
30 merge, 36 merge,
31 node as nodemod,
32 patch, 37 patch,
33 pycompat, 38 pycompat,
34 registrar, 39 registrar,
35 revlog,
36 revset, 40 revset,
37 scmutil, 41 scmutil,
38 smartset, 42 smartset,
39 state as statemod, 43 state as statemod,
40 util, 44 util,
93 97
94 def read(self): 98 def read(self):
95 abspath = os.path.join(self.path, self.transplantfile) 99 abspath = os.path.join(self.path, self.transplantfile)
96 if self.transplantfile and os.path.exists(abspath): 100 if self.transplantfile and os.path.exists(abspath):
97 for line in self.opener.read(self.transplantfile).splitlines(): 101 for line in self.opener.read(self.transplantfile).splitlines():
98 lnode, rnode = map(revlog.bin, line.split(b':')) 102 lnode, rnode = map(bin, line.split(b':'))
99 list = self.transplants.setdefault(rnode, []) 103 list = self.transplants.setdefault(rnode, [])
100 list.append(transplantentry(lnode, rnode)) 104 list.append(transplantentry(lnode, rnode))
101 105
102 def write(self): 106 def write(self):
103 if self.dirty and self.transplantfile: 107 if self.dirty and self.transplantfile:
104 if not os.path.isdir(self.path): 108 if not os.path.isdir(self.path):
105 os.mkdir(self.path) 109 os.mkdir(self.path)
106 fp = self.opener(self.transplantfile, b'w') 110 fp = self.opener(self.transplantfile, b'w')
107 for list in pycompat.itervalues(self.transplants): 111 for list in pycompat.itervalues(self.transplants):
108 for t in list: 112 for t in list:
109 l, r = map(nodemod.hex, (t.lnode, t.rnode)) 113 l, r = map(hex, (t.lnode, t.rnode))
110 fp.write(l + b':' + r + b'\n') 114 fp.write(l + b':' + r + b'\n')
111 fp.close() 115 fp.close()
112 self.dirty = False 116 self.dirty = False
113 117
114 def get(self, rnode): 118 def get(self, rnode):
181 try: 185 try:
182 lock = repo.lock() 186 lock = repo.lock()
183 tr = repo.transaction(b'transplant') 187 tr = repo.transaction(b'transplant')
184 for rev in revs: 188 for rev in revs:
185 node = revmap[rev] 189 node = revmap[rev]
186 revstr = b'%d:%s' % (rev, nodemod.short(node)) 190 revstr = b'%d:%s' % (rev, short(node))
187 191
188 if self.applied(repo, node, p1): 192 if self.applied(repo, node, p1):
189 self.ui.warn( 193 self.ui.warn(
190 _(b'skipping already applied revision %s\n') % revstr 194 _(b'skipping already applied revision %s\n') % revstr
191 ) 195 )
214 domerge = True 218 domerge = True
215 if not hasnode(repo, node): 219 if not hasnode(repo, node):
216 exchange.pull(repo, source.peer(), heads=[node]) 220 exchange.pull(repo, source.peer(), heads=[node])
217 221
218 skipmerge = False 222 skipmerge = False
219 if parents[1] != revlog.nullid: 223 if parents[1] != nullid:
220 if not opts.get(b'parent'): 224 if not opts.get(b'parent'):
221 self.ui.note( 225 self.ui.note(
222 _(b'skipping merge changeset %d:%s\n') 226 _(b'skipping merge changeset %d:%s\n')
223 % (rev, nodemod.short(node)) 227 % (rev, short(node))
224 ) 228 )
225 skipmerge = True 229 skipmerge = True
226 else: 230 else:
227 parent = source.lookup(opts[b'parent']) 231 parent = source.lookup(opts[b'parent'])
228 if parent not in parents: 232 if parent not in parents:
229 raise error.Abort( 233 raise error.Abort(
230 _(b'%s is not a parent of %s') 234 _(b'%s is not a parent of %s')
231 % (nodemod.short(parent), nodemod.short(node)) 235 % (short(parent), short(node))
232 ) 236 )
233 else: 237 else:
234 parent = parents[0] 238 parent = parents[0]
235 239
236 if skipmerge: 240 if skipmerge:
261 # fix the merge or cancel everything 265 # fix the merge or cancel everything
262 tr.close() 266 tr.close()
263 raise 267 raise
264 if n and domerge: 268 if n and domerge:
265 self.ui.status( 269 self.ui.status(
266 _(b'%s merged at %s\n') 270 _(b'%s merged at %s\n') % (revstr, short(n))
267 % (revstr, nodemod.short(n))
268 ) 271 )
269 elif n: 272 elif n:
270 self.ui.status( 273 self.ui.status(
271 _(b'%s transplanted to %s\n') 274 _(b'%s transplanted to %s\n')
272 % (nodemod.short(node), nodemod.short(n)) 275 % (short(node), short(n))
273 ) 276 )
274 finally: 277 finally:
275 if patchfile: 278 if patchfile:
276 os.unlink(patchfile) 279 os.unlink(patchfile)
277 tr.close() 280 tr.close()
307 procutil.shellquote(headerfile), 310 procutil.shellquote(headerfile),
308 procutil.shellquote(patchfile), 311 procutil.shellquote(patchfile),
309 ), 312 ),
310 environ={ 313 environ={
311 b'HGUSER': changelog[1], 314 b'HGUSER': changelog[1],
312 b'HGREVISION': nodemod.hex(node), 315 b'HGREVISION': hex(node),
313 }, 316 },
314 onerr=error.Abort, 317 onerr=error.Abort,
315 errprefix=_(b'filter failed'), 318 errprefix=_(b'filter failed'),
316 blockedtag=b'transplant_filter', 319 blockedtag=b'transplant_filter',
317 ) 320 )
331 if filter: 334 if filter:
332 (user, date, message) = self.filter(filter, node, cl, patchfile) 335 (user, date, message) = self.filter(filter, node, cl, patchfile)
333 336
334 if log: 337 if log:
335 # we don't translate messages inserted into commits 338 # we don't translate messages inserted into commits
336 message += b'\n(transplanted from %s)' % nodemod.hex(node) 339 message += b'\n(transplanted from %s)' % hex(node)
337 340
338 self.ui.status(_(b'applying %s\n') % nodemod.short(node)) 341 self.ui.status(_(b'applying %s\n') % short(node))
339 self.ui.note(b'%s %s\n%s\n' % (user, date, message)) 342 self.ui.note(b'%s %s\n%s\n' % (user, date, message))
340 343
341 if not patchfile and not merge: 344 if not patchfile and not merge:
342 raise error.Abort(_(b'can only omit patchfile if merging')) 345 raise error.Abort(_(b'can only omit patchfile if merging'))
343 if patchfile: 346 if patchfile:
375 extra=extra, 378 extra=extra,
376 match=m, 379 match=m,
377 editor=self.getcommiteditor(), 380 editor=self.getcommiteditor(),
378 ) 381 )
379 if not n: 382 if not n:
380 self.ui.warn( 383 self.ui.warn(_(b'skipping emptied changeset %s\n') % short(node))
381 _(b'skipping emptied changeset %s\n') % nodemod.short(node)
382 )
383 return None 384 return None
384 if not merge: 385 if not merge:
385 self.transplants.set(n, node) 386 self.transplants.set(n, node)
386 387
387 return n 388 return n
393 '''recover last transaction and apply remaining changesets''' 394 '''recover last transaction and apply remaining changesets'''
394 if os.path.exists(os.path.join(self.path, b'journal')): 395 if os.path.exists(os.path.join(self.path, b'journal')):
395 n, node = self.recover(repo, source, opts) 396 n, node = self.recover(repo, source, opts)
396 if n: 397 if n:
397 self.ui.status( 398 self.ui.status(
398 _(b'%s transplanted as %s\n') 399 _(b'%s transplanted as %s\n') % (short(node), short(n))
399 % (nodemod.short(node), nodemod.short(n))
400 ) 400 )
401 else: 401 else:
402 self.ui.status( 402 self.ui.status(
403 _(b'%s skipped due to empty diff\n') 403 _(b'%s skipped due to empty diff\n') % (short(node),)
404 % (nodemod.short(node),)
405 ) 404 )
406 seriespath = os.path.join(self.path, b'series') 405 seriespath = os.path.join(self.path, b'series')
407 if not os.path.exists(seriespath): 406 if not os.path.exists(seriespath):
408 self.transplants.write() 407 self.transplants.write()
409 return 408 return
428 if opts.get(b'parent'): 427 if opts.get(b'parent'):
429 parent = source.lookup(opts[b'parent']) 428 parent = source.lookup(opts[b'parent'])
430 if parent not in parents: 429 if parent not in parents:
431 raise error.Abort( 430 raise error.Abort(
432 _(b'%s is not a parent of %s') 431 _(b'%s is not a parent of %s')
433 % (nodemod.short(parent), nodemod.short(node)) 432 % (short(parent), short(node))
434 ) 433 )
435 else: 434 else:
436 merge = True 435 merge = True
437 436
438 extra = {b'transplant_source': node} 437 extra = {b'transplant_source': node}
439 try: 438 try:
440 p1 = repo.dirstate.p1() 439 p1 = repo.dirstate.p1()
441 if p1 != parent: 440 if p1 != parent:
442 raise error.Abort( 441 raise error.Abort(
443 _(b'working directory not at transplant parent %s') 442 _(b'working directory not at transplant parent %s')
444 % nodemod.hex(parent) 443 % hex(parent)
445 ) 444 )
446 if merge: 445 if merge:
447 repo.setparents(p1, parents[1]) 446 repo.setparents(p1, parents[1])
448 st = repo.status() 447 st = repo.status()
449 modified, added, removed, deleted = ( 448 modified, added, removed, deleted = (
492 cur = nodes 491 cur = nodes
493 for line in self.opener.read(b'series').splitlines(): 492 for line in self.opener.read(b'series').splitlines():
494 if line.startswith(b'# Merges'): 493 if line.startswith(b'# Merges'):
495 cur = merges 494 cur = merges
496 continue 495 continue
497 cur.append(revlog.bin(line)) 496 cur.append(bin(line))
498 497
499 return (nodes, merges) 498 return (nodes, merges)
500 499
501 def saveseries(self, revmap, merges): 500 def saveseries(self, revmap, merges):
502 if not revmap: 501 if not revmap:
504 503
505 if not os.path.isdir(self.path): 504 if not os.path.isdir(self.path):
506 os.mkdir(self.path) 505 os.mkdir(self.path)
507 series = self.opener(b'series', b'w') 506 series = self.opener(b'series', b'w')
508 for rev in sorted(revmap): 507 for rev in sorted(revmap):
509 series.write(nodemod.hex(revmap[rev]) + b'\n') 508 series.write(hex(revmap[rev]) + b'\n')
510 if merges: 509 if merges:
511 series.write(b'# Merges\n') 510 series.write(b'# Merges\n')
512 for m in merges: 511 for m in merges:
513 series.write(nodemod.hex(m) + b'\n') 512 series.write(hex(m) + b'\n')
514 series.close() 513 series.close()
515 514
516 def parselog(self, fp): 515 def parselog(self, fp):
517 parents = [] 516 parents = []
518 message = [] 517 message = []
519 node = revlog.nullid 518 node = nullid
520 inmsg = False 519 inmsg = False
521 user = None 520 user = None
522 date = None 521 date = None
523 for line in fp.read().splitlines(): 522 for line in fp.read().splitlines():
524 if inmsg: 523 if inmsg:
526 elif line.startswith(b'# User '): 525 elif line.startswith(b'# User '):
527 user = line[7:] 526 user = line[7:]
528 elif line.startswith(b'# Date '): 527 elif line.startswith(b'# Date '):
529 date = line[7:] 528 date = line[7:]
530 elif line.startswith(b'# Node ID '): 529 elif line.startswith(b'# Node ID '):
531 node = revlog.bin(line[10:]) 530 node = bin(line[10:])
532 elif line.startswith(b'# Parent '): 531 elif line.startswith(b'# Parent '):
533 parents.append(revlog.bin(line[9:])) 532 parents.append(bin(line[9:]))
534 elif not line.startswith(b'# '): 533 elif not line.startswith(b'# '):
535 inmsg = True 534 inmsg = True
536 message.append(line) 535 message.append(line)
537 if None in (user, date): 536 if None in (user, date):
538 raise error.Abort( 537 raise error.Abort(
546 if not os.path.isdir(self.path): 545 if not os.path.isdir(self.path):
547 os.mkdir(self.path) 546 os.mkdir(self.path)
548 fp = self.opener(b'journal', b'w') 547 fp = self.opener(b'journal', b'w')
549 fp.write(b'# User %s\n' % user) 548 fp.write(b'# User %s\n' % user)
550 fp.write(b'# Date %s\n' % date) 549 fp.write(b'# Date %s\n' % date)
551 fp.write(b'# Node ID %s\n' % nodemod.hex(p2)) 550 fp.write(b'# Node ID %s\n' % hex(p2))
552 fp.write(b'# Parent ' + nodemod.hex(p1) + b'\n') 551 fp.write(b'# Parent ' + hex(p1) + b'\n')
553 if merge: 552 if merge:
554 fp.write(b'# Parent ' + nodemod.hex(p2) + b'\n') 553 fp.write(b'# Parent ' + hex(p2) + b'\n')
555 fp.write(message.rstrip() + b'\n') 554 fp.write(message.rstrip() + b'\n')
556 fp.close() 555 fp.close()
557 556
558 def readlog(self): 557 def readlog(self):
559 return self.parselog(self.opener(b'journal')) 558 return self.parselog(self.opener(b'journal'))
566 565
567 def transplantfilter(self, repo, source, root): 566 def transplantfilter(self, repo, source, root):
568 def matchfn(node): 567 def matchfn(node):
569 if self.applied(repo, node, root): 568 if self.applied(repo, node, root):
570 return False 569 return False
571 if source.changelog.parents(node)[1] != revlog.nullid: 570 if source.changelog.parents(node)[1] != nullid:
572 return False 571 return False
573 extra = source.changelog.read(node)[5] 572 extra = source.changelog.read(node)[5]
574 cnode = extra.get(b'transplant_source') 573 cnode = extra.get(b'transplant_source')
575 if cnode and self.applied(repo, cnode, root): 574 if cnode and self.applied(repo, cnode, root):
576 return False 575 return False
802 opts[b'filter'] = ui.config(b'transplant', b'filter') 801 opts[b'filter'] = ui.config(b'transplant', b'filter')
803 802
804 tp = transplanter(ui, repo, opts) 803 tp = transplanter(ui, repo, opts)
805 804
806 p1 = repo.dirstate.p1() 805 p1 = repo.dirstate.p1()
807 if len(repo) > 0 and p1 == revlog.nullid: 806 if len(repo) > 0 and p1 == nullid:
808 raise error.Abort(_(b'no revision checked out')) 807 raise error.Abort(_(b'no revision checked out'))
809 if opts.get(b'continue'): 808 if opts.get(b'continue'):
810 if not tp.canresume(): 809 if not tp.canresume():
811 raise error.StateError(_(b'no transplant to continue')) 810 raise error.StateError(_(b'no transplant to continue'))
812 elif opts.get(b'stop'): 811 elif opts.get(b'stop'):
907 def kwtransplanted(context, mapping): 906 def kwtransplanted(context, mapping):
908 """String. The node identifier of the transplanted 907 """String. The node identifier of the transplanted
909 changeset if any.""" 908 changeset if any."""
910 ctx = context.resource(mapping, b'ctx') 909 ctx = context.resource(mapping, b'ctx')
911 n = ctx.extra().get(b'transplant_source') 910 n = ctx.extra().get(b'transplant_source')
912 return n and nodemod.hex(n) or b'' 911 return n and hex(n) or b''
913 912
914 913
915 def extsetup(ui): 914 def extsetup(ui):
916 statemod.addunfinished( 915 statemod.addunfinished(
917 b'transplant', 916 b'transplant',