12 import time |
12 import time |
13 |
13 |
14 from .i18n import _ |
14 from .i18n import _ |
15 from . import encoding |
15 from . import encoding |
16 |
16 |
|
17 |
17 def spacejoin(*args): |
18 def spacejoin(*args): |
18 return ' '.join(s for s in args if s) |
19 return ' '.join(s for s in args if s) |
19 |
20 |
|
21 |
20 def shouldprint(ui): |
22 def shouldprint(ui): |
21 return not (ui.quiet or ui.plain('progress')) and ( |
23 return not (ui.quiet or ui.plain('progress')) and ( |
22 ui._isatty(ui.ferr) or ui.configbool('progress', 'assume-tty')) |
24 ui._isatty(ui.ferr) or ui.configbool('progress', 'assume-tty') |
|
25 ) |
|
26 |
23 |
27 |
24 def fmtremaining(seconds): |
28 def fmtremaining(seconds): |
25 """format a number of remaining seconds in human readable way |
29 """format a number of remaining seconds in human readable way |
26 |
30 |
27 This will properly display seconds, minutes, hours, days if needed""" |
31 This will properly display seconds, minutes, hours, days if needed""" |
28 if seconds < 60: |
32 if seconds < 60: |
29 # i18n: format XX seconds as "XXs" |
33 # i18n: format XX seconds as "XXs" |
30 return _("%02ds") % (seconds) |
34 return _("%02ds") % seconds |
31 minutes = seconds // 60 |
35 minutes = seconds // 60 |
32 if minutes < 60: |
36 if minutes < 60: |
33 seconds -= minutes * 60 |
37 seconds -= minutes * 60 |
34 # i18n: format X minutes and YY seconds as "XmYYs" |
38 # i18n: format X minutes and YY seconds as "XmYYs" |
35 return _("%dm%02ds") % (minutes, seconds) |
39 return _("%dm%02ds") % (minutes, seconds) |
59 years = weeks // 52 |
63 years = weeks // 52 |
60 weeks -= years * 52 |
64 weeks -= years * 52 |
61 # i18n: format X years and YY weeks as "XyYYw" |
65 # i18n: format X years and YY weeks as "XyYYw" |
62 return _("%dy%02dw") % (years, weeks) |
66 return _("%dy%02dw") % (years, weeks) |
63 |
67 |
|
68 |
64 # file_write() and file_flush() of Python 2 do not restart on EINTR if |
69 # file_write() and file_flush() of Python 2 do not restart on EINTR if |
65 # the file is attached to a "slow" device (e.g. a terminal) and raise |
70 # the file is attached to a "slow" device (e.g. a terminal) and raise |
66 # IOError. We cannot know how many bytes would be written by file_write(), |
71 # IOError. We cannot know how many bytes would be written by file_write(), |
67 # but a progress text is known to be short enough to be written by a |
72 # but a progress text is known to be short enough to be written by a |
68 # single write() syscall, so we can just retry file_write() with the whole |
73 # single write() syscall, so we can just retry file_write() with the whole |
77 except IOError as err: |
82 except IOError as err: |
78 if err.errno == errno.EINTR: |
83 if err.errno == errno.EINTR: |
79 continue |
84 continue |
80 raise |
85 raise |
81 |
86 |
|
87 |
82 class progbar(object): |
88 class progbar(object): |
83 def __init__(self, ui): |
89 def __init__(self, ui): |
84 self.ui = ui |
90 self.ui = ui |
85 self._refreshlock = threading.Lock() |
91 self._refreshlock = threading.Lock() |
86 self.resetstate() |
92 self.resetstate() |
89 self.topics = [] |
95 self.topics = [] |
90 self.topicstates = {} |
96 self.topicstates = {} |
91 self.starttimes = {} |
97 self.starttimes = {} |
92 self.startvals = {} |
98 self.startvals = {} |
93 self.printed = False |
99 self.printed = False |
94 self.lastprint = time.time() + float(self.ui.config( |
100 self.lastprint = time.time() + float( |
95 'progress', 'delay')) |
101 self.ui.config('progress', 'delay') |
|
102 ) |
96 self.curtopic = None |
103 self.curtopic = None |
97 self.lasttopic = None |
104 self.lasttopic = None |
98 self.indetcount = 0 |
105 self.indetcount = 0 |
99 self.refresh = float(self.ui.config( |
106 self.refresh = float(self.ui.config('progress', 'refresh')) |
100 'progress', 'refresh')) |
107 self.changedelay = max( |
101 self.changedelay = max(3 * self.refresh, |
108 3 * self.refresh, float(self.ui.config('progress', 'changedelay')) |
102 float(self.ui.config( |
109 ) |
103 'progress', 'changedelay'))) |
|
104 self.order = self.ui.configlist('progress', 'format') |
110 self.order = self.ui.configlist('progress', 'format') |
105 self.estimateinterval = self.ui.configwith( |
111 self.estimateinterval = self.ui.configwith( |
106 float, 'progress', 'estimateinterval') |
112 float, 'progress', 'estimateinterval' |
|
113 ) |
107 |
114 |
108 def show(self, now, topic, pos, item, unit, total): |
115 def show(self, now, topic, pos, item, unit, total): |
109 if not shouldprint(self.ui): |
116 if not shouldprint(self.ui): |
110 return |
117 return |
111 termwidth = self.width() |
118 termwidth = self.width() |
167 self.indetcount += 1 |
174 self.indetcount += 1 |
168 # mod the count by twice the width so we can make the |
175 # mod the count by twice the width so we can make the |
169 # cursor bounce between the right and left sides |
176 # cursor bounce between the right and left sides |
170 amt = self.indetcount % (2 * progwidth) |
177 amt = self.indetcount % (2 * progwidth) |
171 amt -= progwidth |
178 amt -= progwidth |
172 bar = (' ' * int(progwidth - abs(amt)) + '<=>' + |
179 bar = ( |
173 ' ' * int(abs(amt))) |
180 ' ' * int(progwidth - abs(amt)) |
|
181 + '<=>' |
|
182 + ' ' * int(abs(amt)) |
|
183 ) |
174 prog = ''.join(('[', bar, ']')) |
184 prog = ''.join(('[', bar, ']')) |
175 out = spacejoin(head, prog, tail) |
185 out = spacejoin(head, prog, tail) |
176 else: |
186 else: |
177 out = spacejoin(head, tail) |
187 out = spacejoin(head, tail) |
178 self._writeerr('\r' + encoding.trim(out, termwidth)) |
188 self._writeerr('\r' + encoding.trim(out, termwidth)) |
226 return _('%d %s/sec') % (delta / elapsed, unit) |
236 return _('%d %s/sec') % (delta / elapsed, unit) |
227 return '' |
237 return '' |
228 |
238 |
229 def _oktoprint(self, now): |
239 def _oktoprint(self, now): |
230 '''Check if conditions are met to print - e.g. changedelay elapsed''' |
240 '''Check if conditions are met to print - e.g. changedelay elapsed''' |
231 if (self.lasttopic is None # first time we printed |
241 if ( |
|
242 self.lasttopic is None # first time we printed |
232 # not a topic change |
243 # not a topic change |
233 or self.curtopic == self.lasttopic |
244 or self.curtopic == self.lasttopic |
234 # it's been long enough we should print anyway |
245 # it's been long enough we should print anyway |
235 or now - self.lastprint >= self.changedelay): |
246 or now - self.lastprint >= self.changedelay |
|
247 ): |
236 return True |
248 return True |
237 else: |
249 else: |
238 return False |
250 return False |
239 |
251 |
240 def _calibrateestimate(self, topic, now, pos): |
252 def _calibrateestimate(self, topic, now, pos): |
291 self.complete() |
303 self.complete() |
292 self.resetstate() |
304 self.resetstate() |
293 # truncate the list of topics assuming all topics within |
305 # truncate the list of topics assuming all topics within |
294 # this one are also closed |
306 # this one are also closed |
295 if topic in self.topics: |
307 if topic in self.topics: |
296 self.topics = self.topics[:self.topics.index(topic)] |
308 self.topics = self.topics[: self.topics.index(topic)] |
297 # reset the last topic to the one we just unwound to, |
309 # reset the last topic to the one we just unwound to, |
298 # so that higher-level topics will be stickier than |
310 # so that higher-level topics will be stickier than |
299 # lower-level topics |
311 # lower-level topics |
300 if self.topics: |
312 if self.topics: |
301 self.lasttopic = self.topics[-1] |
313 self.lasttopic = self.topics[-1] |