[PATCH 2 of 3] progress: Add estimated time remaining for long tasks

Augie Fackler durin42 at gmail.com
Sat Dec 11 12:05:15 CST 2010


# HG changeset patch
# User timeless <timeless at gmail.com>
# Date 1288093318 -10800
# Node ID 02908b263aa8113b467c6934018162cc46f8f9d6
# Parent  f1bfbb584d4eed48ca9eac134b2feb1255a120f8
progress: Add estimated time remaining for long tasks

Output looks roughly like this:
updating [======================>                       ] 1547/4842 0m13s

output will either show h:m or m:s

diff --git a/hgext/progress.py b/hgext/progress.py
--- a/hgext/progress.py
+++ b/hgext/progress.py
@@ -45,6 +45,7 @@
 import sys
 import time
 
+from mercurial.i18n import _
 from mercurial import util
 
 def spacejoin(*args):
@@ -62,6 +63,8 @@
     def resetstate(self):
         self.topics = []
         self.topicstates = {}
+        self.starttimes = {}
+        self.startvals = {}
         self.printed = False
         self.lastprint = time.time() + float(self.ui.config(
             'progress', 'delay', default=3))
@@ -72,7 +75,7 @@
             'progress', 'format',
             default=['topic', 'bar', 'number'])
 
-    def show(self, topic, pos, item, unit, total):
+    def show(self, now, topic, pos, item, unit, total):
         if not shouldprint(self.ui):
             return
         termwidth = self.width()
@@ -121,6 +124,26 @@
                 used += len(tail) + 1
             progwidth = termwidth - used - 3
             if total and pos <= total:
+                initial = self.startvals[topic]
+                target = total - initial
+                delta = pos - initial
+                if delta > 0:
+                    elapsed = now - self.starttimes[topic]
+                    if elapsed > float(
+                        self.ui.config('progress', 'estimate', default=2)):
+                        seconds = (elapsed * (target - delta)) // delta + 1
+                        minutes = seconds // 60
+                        if minutes < 10:
+                            seconds -= minutes * 60
+                            remaining = _("%dm%02ds") % (minutes, seconds)
+                        else:
+                            # we're going to ignore seconds in this case
+                            minutes += 1
+                            hours = minutes // 60
+                            minutes -= hours * 60
+                            remaining = _("%dh%02dm") % (hours, minutes)
+                        progwidth -= len(remaining) + 1
+                        tail = spacejoin(tail, remaining)
                 amt = pos * progwidth // total
                 bar = '=' * (amt - 1)
                 if amt > 0:
@@ -161,7 +184,10 @@
         return min(int(self.ui.config('progress', 'width', default=tw)), tw)
 
     def progress(self, topic, pos, item='', unit='', total=None):
+        now = time.time()
         if pos is None:
+            self.starttimes.pop(topic, None)
+            self.startvals.pop(topic, None)
             self.topicstates.pop(topic, None)
             # reset the progress bar if this is the outermost topic
             if self.topics and self.topics[0] == topic and self.printed:
@@ -173,13 +199,14 @@
               self.topics = self.topics[:self.topics.index(topic)]
         else:
             if topic not in self.topics:
+                self.starttimes[topic] = now
+                self.startvals[topic] = pos
                 self.topics.append(topic)
-            now = time.time()
             self.topicstates[topic] = pos, item, unit, total
             if now - self.lastprint >= self.refresh and self.topics:
                 self.lastprint = now
                 current = self.topics[-1]
-                self.show(current, *self.topicstates[current])
+                self.show(now, topic, *self.topicstates[topic])
 
 def uisetup(ui):
     class progressui(ui.__class__):


More information about the Mercurial-devel mailing list