diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -359,6 +359,9 @@ coreconfigitem('progress', 'estimate', default=2, ) +coreconfigitem('progress', 'estimateinterval', + default=60, +) coreconfigitem('progress', 'refresh', default=0.1, ) diff --git a/mercurial/progress.py b/mercurial/progress.py --- a/mercurial/progress.py +++ b/mercurial/progress.py @@ -104,6 +104,9 @@ self.order = self.ui.configlist( 'progress', 'format', default=['topic', 'bar', 'number', 'estimate']) + # experimental config: progress.estimateinterval, in seconds + self.estimateinterval = self.ui.configint( + 'progress', 'estimateinterval') def show(self, now, topic, pos, item, unit, total): if not shouldprint(self.ui): @@ -242,6 +245,29 @@ else: return False + def _calibrateestimate(self, topic, now, pos): + '''Adjust starttimes and startvals so ETA and speed works better + + If progress is non-linear (ex. get much slower in the last minute), + it's more friendly to reflect the slow-down to the ETA or speed. + + [======================================> ] + ^^^^^^^ + last minute (estimateinterval) progress + only use this for estimation + ''' + interval = self.estimateinterval + if not interval: + return + elapsed = now - self.starttimes[topic] + if elapsed > interval: + delta = pos - self.startvals[topic] + newdelta = 1.0 * delta * interval / elapsed + if newdelta < 0.1: # prevent too steep changes + 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() @@ -272,6 +298,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 diff --git a/tests/test-progress.t b/tests/test-progress.t --- a/tests/test-progress.t +++ b/tests/test-progress.t @@ -260,17 +260,17 @@ loop [===========> ] 6/20 4m41s\r (no-eol) (esc) loop [=============> ] 7/20 4m21s\r (no-eol) (esc) loop [===============> ] 8/20 4m01s\r (no-eol) (esc) - loop [================> ] 9/20 13m27s\r (no-eol) (esc) - loop [==================> ] 10/20 19m21s\r (no-eol) (esc) - loop [====================> ] 11/20 22m39s\r (no-eol) (esc) - loop [======================> ] 12/20 24m01s\r (no-eol) (esc) - loop [========================> ] 13/20 23m53s\r (no-eol) (esc) - loop [==========================> ] 14/20 19m09s\r (no-eol) (esc) - loop [============================> ] 15/20 15m01s\r (no-eol) (esc) - loop [==============================> ] 16/20 11m21s\r (no-eol) (esc) - loop [=================================> ] 17/20 8m04s\r (no-eol) (esc) - loop [===================================> ] 18/20 5m07s\r (no-eol) (esc) - loop [=====================================> ] 19/20 2m27s\r (no-eol) (esc) + loop [================> ] 9/20 25m40s\r (no-eol) (esc) + loop [===================> ] 10/20 1h06m\r (no-eol) (esc) + loop [=====================> ] 11/20 1h13m\r (no-eol) (esc) + loop [=======================> ] 12/20 1h07m\r (no-eol) (esc) + loop [========================> ] 13/20 58m19s\r (no-eol) (esc) + loop [===========================> ] 14/20 7m09s\r (no-eol) (esc) + loop [=============================> ] 15/20 3m38s\r (no-eol) (esc) + loop [===============================> ] 16/20 2m15s\r (no-eol) (esc) + loop [=================================> ] 17/20 1m27s\r (no-eol) (esc) + loop [====================================> ] 18/20 52s\r (no-eol) (esc) + loop [======================================> ] 19/20 25s\r (no-eol) (esc) \r (no-eol) (esc) Time estimates should not fail when there's no end point: