Mercurial > hg
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', |