diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -197,17 +197,21 @@ return oldwrite def filterchunks(ui, originalhunks, usecurses, testfile, operation=None): - if usecurses: - if testfile: - recordfn = crecordmod.testdecorator(testfile, - crecordmod.testchunkselector) - else: - recordfn = crecordmod.chunkselector - - return crecordmod.filterpatch(ui, originalhunks, recordfn, operation) - - else: - return patch.filterpatch(ui, originalhunks, operation) + try: + if usecurses: + if testfile: + recordfn = crecordmod.testdecorator( + testfile, crecordmod.testchunkselector) + else: + recordfn = crecordmod.chunkselector + + return crecordmod.filterpatch(ui, originalhunks, recordfn, + operation) + except crecordmod.fallbackerror as e: + ui.warn('%s\n' % e.message) + ui.warn(_('falling back to text mode\n')) + + return patch.filterpatch(ui, originalhunks, operation) def recordfilter(ui, originalhunks, operation=None): """ Prompts the user to filter the originalhunks and return a list of diff --git a/mercurial/crecord.py b/mercurial/crecord.py --- a/mercurial/crecord.py +++ b/mercurial/crecord.py @@ -65,6 +65,11 @@ # compiled with curses curses = False +class fallbackerror(error.Abort): + """Error that indicates the client should try to fallback to text mode.""" + # Inherits from error.Abort so that existing behavior is preserved if the + # calling code does not know how to fallback. + def checkcurses(ui): """Return True if the user wants to use curses @@ -529,8 +534,8 @@ origsigtstp = signal.getsignal(signal.SIGTSTP) try: curses.wrapper(chunkselector.main) - if chunkselector.initerr is not None: - raise error.Abort(chunkselector.initerr) + if chunkselector.initexc is not None: + raise chunkselector.initexc # ncurses does not restore signal handler for SIGTSTP finally: if origsigtstp is not sentinel: @@ -1718,7 +1723,7 @@ self.stdscr = stdscr # error during initialization, cannot be printed in the curses # interface, it should be printed by the calling code - self.initerr = None + self.initexc = None self.yscreensize, self.xscreensize = self.stdscr.getmaxyx() curses.start_color() @@ -1751,7 +1756,8 @@ try: self.chunkpad = curses.newpad(self.numpadlines, self.xscreensize) except curses.error: - self.initerr = _('this diff is too large to be displayed') + self.initexc = fallbackerror( + _('this diff is too large to be displayed')) return # initialize selecteditemendline (initial start-line is 0) self.selecteditemendline = self.getnumlinesdisplayed(