mercurial/ui.py
changeset 38528 313a940d49a3
parent 38351 bec1212eceaa
child 38576 152f4822d210
--- a/mercurial/ui.py	Tue Jul 03 12:22:37 2018 -0400
+++ b/mercurial/ui.py	Wed Jun 27 10:47:14 2018 -0400
@@ -224,6 +224,7 @@
         self._colormode = None
         self._terminfoparams = {}
         self._styles = {}
+        self._uninterruptible = False
 
         if src:
             self.fout = src.fout
@@ -334,6 +335,37 @@
             self._blockedtimes[key + '_blocked'] += \
                 (util.timer() - starttime) * 1000
 
+    @contextlib.contextmanager
+    def uninterruptable(self):
+        """Mark an operation as unsafe.
+
+        Most operations on a repository are safe to interrupt, but a
+        few are risky (for example repair.strip). This context manager
+        lets you advise Mercurial that something risky is happening so
+        that control-C etc can be blocked if desired.
+        """
+        enabled = self.configbool('experimental', 'nointerrupt')
+        if (enabled and
+            self.configbool('experimental', 'nointerrupt-interactiveonly')):
+            enabled = self.interactive()
+        if self._uninterruptible or not enabled:
+            # if nointerrupt support is turned off, the process isn't
+            # interactive, or we're already in an uninterruptable
+            # block, do nothing.
+            yield
+            return
+        def warn():
+            self.warn(_("shutting down cleanly\n"))
+            self.warn(
+                _("press ^C again to terminate immediately (dangerous)\n"))
+            return True
+        with procutil.uninterruptable(warn):
+            try:
+                self._uninterruptible = True
+                yield
+            finally:
+                self._uninterruptible = False
+
     def formatter(self, topic, opts):
         return formatter.formatter(self, self, topic, opts)