comparison mercurial/crecord.py @ 30542:40fe96fc7cd2

crecord: add an "operation" field The field would provide extra information to help us to make the curses UI text less confusing.
author Jun Wu <quark@fb.com>
date Wed, 23 Nov 2016 19:22:36 +0000
parents 318a24b52eeb
children 3899c358b45a
comparison
equal deleted inserted replaced
30541:66b162fa3ffa 30542:40fe96fc7cd2
431 return getattr(self._hunk, name) 431 return getattr(self._hunk, name)
432 432
433 def __repr__(self): 433 def __repr__(self):
434 return '<hunk %r@%d>' % (self.filename(), self.fromline) 434 return '<hunk %r@%d>' % (self.filename(), self.fromline)
435 435
436 def filterpatch(ui, chunks, chunkselector): 436 def filterpatch(ui, chunks, chunkselector, operation=None):
437 """interactively filter patch chunks into applied-only chunks""" 437 """interactively filter patch chunks into applied-only chunks"""
438 chunks = list(chunks) 438 chunks = list(chunks)
439 # convert chunks list into structure suitable for displaying/modifying 439 # convert chunks list into structure suitable for displaying/modifying
440 # with curses. create a list of headers only. 440 # with curses. create a list of headers only.
441 headers = [c for c in chunks if isinstance(c, patchmod.header)] 441 headers = [c for c in chunks if isinstance(c, patchmod.header)]
444 if len(headers) == 0: 444 if len(headers) == 0:
445 return [], {} 445 return [], {}
446 uiheaders = [uiheader(h) for h in headers] 446 uiheaders = [uiheader(h) for h in headers]
447 # let user choose headers/hunks/lines, and mark their applied flags 447 # let user choose headers/hunks/lines, and mark their applied flags
448 # accordingly 448 # accordingly
449 ret = chunkselector(ui, uiheaders) 449 ret = chunkselector(ui, uiheaders, operation=operation)
450 appliedhunklist = [] 450 appliedhunklist = []
451 for hdr in uiheaders: 451 for hdr in uiheaders:
452 if (hdr.applied and 452 if (hdr.applied and
453 (hdr.special() or len([h for h in hdr.hunks if h.applied]) > 0)): 453 (hdr.special() or len([h for h in hdr.hunks if h.applied]) > 0)):
454 appliedhunklist.append(hdr) 454 appliedhunklist.append(hdr)
464 else: 464 else:
465 fixoffset += hnk.removed - hnk.added 465 fixoffset += hnk.removed - hnk.added
466 466
467 return (appliedhunklist, ret) 467 return (appliedhunklist, ret)
468 468
469 def chunkselector(ui, headerlist): 469 def chunkselector(ui, headerlist, operation=None):
470 """ 470 """
471 curses interface to get selection of chunks, and mark the applied flags 471 curses interface to get selection of chunks, and mark the applied flags
472 of the chosen chunks. 472 of the chosen chunks.
473 """ 473 """
474 ui.write(_('starting interactive selection\n')) 474 ui.write(_('starting interactive selection\n'))
475 chunkselector = curseschunkselector(headerlist, ui) 475 chunkselector = curseschunkselector(headerlist, ui, operation)
476 f = signal.getsignal(signal.SIGTSTP) 476 f = signal.getsignal(signal.SIGTSTP)
477 curses.wrapper(chunkselector.main) 477 curses.wrapper(chunkselector.main)
478 if chunkselector.initerr is not None: 478 if chunkselector.initerr is not None:
479 raise error.Abort(chunkselector.initerr) 479 raise error.Abort(chunkselector.initerr)
480 # ncurses does not restore signal handler for SIGTSTP 480 # ncurses does not restore signal handler for SIGTSTP
484 def testdecorator(testfn, f): 484 def testdecorator(testfn, f):
485 def u(*args, **kwargs): 485 def u(*args, **kwargs):
486 return f(testfn, *args, **kwargs) 486 return f(testfn, *args, **kwargs)
487 return u 487 return u
488 488
489 def testchunkselector(testfn, ui, headerlist): 489 def testchunkselector(testfn, ui, headerlist, operation=None):
490 """ 490 """
491 test interface to get selection of chunks, and mark the applied flags 491 test interface to get selection of chunks, and mark the applied flags
492 of the chosen chunks. 492 of the chosen chunks.
493 """ 493 """
494 chunkselector = curseschunkselector(headerlist, ui) 494 chunkselector = curseschunkselector(headerlist, ui, operation)
495 if testfn and os.path.exists(testfn): 495 if testfn and os.path.exists(testfn):
496 testf = open(testfn) 496 testf = open(testfn)
497 testcommands = map(lambda x: x.rstrip('\n'), testf.readlines()) 497 testcommands = map(lambda x: x.rstrip('\n'), testf.readlines())
498 testf.close() 498 testf.close()
499 while True: 499 while True:
500 if chunkselector.handlekeypressed(testcommands.pop(0), test=True): 500 if chunkselector.handlekeypressed(testcommands.pop(0), test=True):
501 break 501 break
502 return chunkselector.opts 502 return chunkselector.opts
503 503
504 class curseschunkselector(object): 504 class curseschunkselector(object):
505 def __init__(self, headerlist, ui): 505 def __init__(self, headerlist, ui, operation=None):
506 # put the headers into a patch object 506 # put the headers into a patch object
507 self.headerlist = patch(headerlist) 507 self.headerlist = patch(headerlist)
508 508
509 self.ui = ui 509 self.ui = ui
510 self.opts = {} 510 self.opts = {}
553 # stores optional text for a commit comment provided by the user 553 # stores optional text for a commit comment provided by the user
554 self.commenttext = "" 554 self.commenttext = ""
555 555
556 # if the last 'toggle all' command caused all changes to be applied 556 # if the last 'toggle all' command caused all changes to be applied
557 self.waslasttoggleallapplied = True 557 self.waslasttoggleallapplied = True
558
559 # affects some ui text
560 self.operation = operation
558 561
559 def uparrowevent(self): 562 def uparrowevent(self):
560 """ 563 """
561 try to select the previous item to the current item that has the 564 try to select the previous item to the current item that has the
562 most-indented level. for example, if a hunk is selected, try to select 565 most-indented level. for example, if a hunk is selected, try to select