mercurial/progress.py
changeset 34314 a667f0ca1d5f
parent 34313 f428c347d32b
child 34486 a57c938e7ac8
--- a/mercurial/progress.py	Wed Sep 27 14:30:58 2017 -0700
+++ b/mercurial/progress.py	Wed Sep 27 15:14:59 2017 -0700
@@ -104,6 +104,8 @@
         self.order = self.ui.configlist(
             'progress', 'format',
             default=['topic', 'bar', 'number', 'estimate'])
+        self.estimateinterval = self.ui.configwith(
+            float, 'progress', 'estimateinterval')
 
     def show(self, now, topic, pos, item, unit, total):
         if not shouldprint(self.ui):
@@ -238,6 +240,32 @@
         else:
             return False
 
+    def _calibrateestimate(self, topic, now, pos):
+        '''Adjust starttimes and startvals for topic so ETA works better
+
+        If progress is non-linear (ex. get much slower in the last minute),
+        it's more friendly to only use a recent time span for ETA and speed
+        calculation.
+
+            [======================================>       ]
+                                             ^^^^^^^
+                           estimateinterval, only use this for estimation
+        '''
+        interval = self.estimateinterval
+        if interval <= 0:
+            return
+        elapsed = now - self.starttimes[topic]
+        if elapsed > interval:
+            delta = pos - self.startvals[topic]
+            newdelta = delta * interval / elapsed
+            # If a stall happens temporarily, ETA could change dramatically
+            # frequently. This is to avoid such dramatical change and make ETA
+            # smoother.
+            if newdelta < 0.1:
+                return
+            self.startvals[topic] = pos - newdelta
+            self.starttimes[topic] = now - interval
+
     def progress(self, topic, pos, item='', unit='', total=None):
         now = time.time()
         self._refreshlock.acquire()
@@ -268,6 +296,7 @@
                     self.topics.append(topic)
                 self.topicstates[topic] = pos, item, unit, total
                 self.curtopic = topic
+                self._calibrateestimate(topic, now, pos)
                 if now - self.lastprint >= self.refresh and self.topics:
                     if self._oktoprint(now):
                         self.lastprint = now