##// END OF EJS Templates
configitems: register the 'progress.estimate' config
marmoute -
r33247:bbc57a7e default
parent child Browse files
Show More
@@ -1,207 +1,210 b''
1 # configitems.py - centralized declaration of configuration option
1 # configitems.py - centralized declaration of configuration option
2 #
2 #
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import functools
10 import functools
11
11
12 from . import (
12 from . import (
13 error,
13 error,
14 )
14 )
15
15
16 def loadconfigtable(ui, extname, configtable):
16 def loadconfigtable(ui, extname, configtable):
17 """update config item known to the ui with the extension ones"""
17 """update config item known to the ui with the extension ones"""
18 for section, items in configtable.items():
18 for section, items in configtable.items():
19 knownitems = ui._knownconfig.setdefault(section, {})
19 knownitems = ui._knownconfig.setdefault(section, {})
20 knownkeys = set(knownitems)
20 knownkeys = set(knownitems)
21 newkeys = set(items)
21 newkeys = set(items)
22 for key in sorted(knownkeys & newkeys):
22 for key in sorted(knownkeys & newkeys):
23 msg = "extension '%s' overwrite config item '%s.%s'"
23 msg = "extension '%s' overwrite config item '%s.%s'"
24 msg %= (extname, section, key)
24 msg %= (extname, section, key)
25 ui.develwarn(msg, config='warn-config')
25 ui.develwarn(msg, config='warn-config')
26
26
27 knownitems.update(items)
27 knownitems.update(items)
28
28
29 class configitem(object):
29 class configitem(object):
30 """represent a known config item
30 """represent a known config item
31
31
32 :section: the official config section where to find this item,
32 :section: the official config section where to find this item,
33 :name: the official name within the section,
33 :name: the official name within the section,
34 :default: default value for this item,
34 :default: default value for this item,
35 """
35 """
36
36
37 def __init__(self, section, name, default=None):
37 def __init__(self, section, name, default=None):
38 self.section = section
38 self.section = section
39 self.name = name
39 self.name = name
40 self.default = default
40 self.default = default
41
41
42 coreitems = {}
42 coreitems = {}
43
43
44 def _register(configtable, *args, **kwargs):
44 def _register(configtable, *args, **kwargs):
45 item = configitem(*args, **kwargs)
45 item = configitem(*args, **kwargs)
46 section = configtable.setdefault(item.section, {})
46 section = configtable.setdefault(item.section, {})
47 if item.name in section:
47 if item.name in section:
48 msg = "duplicated config item registration for '%s.%s'"
48 msg = "duplicated config item registration for '%s.%s'"
49 raise error.ProgrammingError(msg % (item.section, item.name))
49 raise error.ProgrammingError(msg % (item.section, item.name))
50 section[item.name] = item
50 section[item.name] = item
51
51
52 # Registering actual config items
52 # Registering actual config items
53
53
54 def getitemregister(configtable):
54 def getitemregister(configtable):
55 return functools.partial(_register, configtable)
55 return functools.partial(_register, configtable)
56
56
57 coreconfigitem = getitemregister(coreitems)
57 coreconfigitem = getitemregister(coreitems)
58
58
59 coreconfigitem('auth', 'cookiefile',
59 coreconfigitem('auth', 'cookiefile',
60 default=None,
60 default=None,
61 )
61 )
62 # bookmarks.pushing: internal hack for discovery
62 # bookmarks.pushing: internal hack for discovery
63 coreconfigitem('bookmarks', 'pushing',
63 coreconfigitem('bookmarks', 'pushing',
64 default=list,
64 default=list,
65 )
65 )
66 # bundle.mainreporoot: internal hack for bundlerepo
66 # bundle.mainreporoot: internal hack for bundlerepo
67 coreconfigitem('bundle', 'mainreporoot',
67 coreconfigitem('bundle', 'mainreporoot',
68 default='',
68 default='',
69 )
69 )
70 # bundle.reorder: experimental config
70 # bundle.reorder: experimental config
71 coreconfigitem('bundle', 'reorder',
71 coreconfigitem('bundle', 'reorder',
72 default='auto',
72 default='auto',
73 )
73 )
74 coreconfigitem('color', 'mode',
74 coreconfigitem('color', 'mode',
75 default='auto',
75 default='auto',
76 )
76 )
77 coreconfigitem('devel', 'all-warnings',
77 coreconfigitem('devel', 'all-warnings',
78 default=False,
78 default=False,
79 )
79 )
80 coreconfigitem('devel', 'bundle2.debug',
80 coreconfigitem('devel', 'bundle2.debug',
81 default=False,
81 default=False,
82 )
82 )
83 coreconfigitem('devel', 'check-locks',
83 coreconfigitem('devel', 'check-locks',
84 default=False,
84 default=False,
85 )
85 )
86 coreconfigitem('devel', 'check-relroot',
86 coreconfigitem('devel', 'check-relroot',
87 default=False,
87 default=False,
88 )
88 )
89 coreconfigitem('devel', 'disableloaddefaultcerts',
89 coreconfigitem('devel', 'disableloaddefaultcerts',
90 default=False,
90 default=False,
91 )
91 )
92 coreconfigitem('devel', 'legacy.exchange',
92 coreconfigitem('devel', 'legacy.exchange',
93 default=list,
93 default=list,
94 )
94 )
95 coreconfigitem('devel', 'servercafile',
95 coreconfigitem('devel', 'servercafile',
96 default='',
96 default='',
97 )
97 )
98 coreconfigitem('devel', 'serverexactprotocol',
98 coreconfigitem('devel', 'serverexactprotocol',
99 default='',
99 default='',
100 )
100 )
101 coreconfigitem('devel', 'serverrequirecert',
101 coreconfigitem('devel', 'serverrequirecert',
102 default=False,
102 default=False,
103 )
103 )
104 coreconfigitem('devel', 'strip-obsmarkers',
104 coreconfigitem('devel', 'strip-obsmarkers',
105 default=True,
105 default=True,
106 )
106 )
107 coreconfigitem('format', 'aggressivemergedeltas',
107 coreconfigitem('format', 'aggressivemergedeltas',
108 default=False,
108 default=False,
109 )
109 )
110 coreconfigitem('format', 'chunkcachesize',
110 coreconfigitem('format', 'chunkcachesize',
111 default=None,
111 default=None,
112 )
112 )
113 coreconfigitem('format', 'dotencode',
113 coreconfigitem('format', 'dotencode',
114 default=True,
114 default=True,
115 )
115 )
116 coreconfigitem('format', 'generaldelta',
116 coreconfigitem('format', 'generaldelta',
117 default=False,
117 default=False,
118 )
118 )
119 coreconfigitem('format', 'manifestcachesize',
119 coreconfigitem('format', 'manifestcachesize',
120 default=None,
120 default=None,
121 )
121 )
122 coreconfigitem('format', 'maxchainlen',
122 coreconfigitem('format', 'maxchainlen',
123 default=None,
123 default=None,
124 )
124 )
125 coreconfigitem('format', 'obsstore-version',
125 coreconfigitem('format', 'obsstore-version',
126 default=None,
126 default=None,
127 )
127 )
128 coreconfigitem('format', 'usefncache',
128 coreconfigitem('format', 'usefncache',
129 default=True,
129 default=True,
130 )
130 )
131 coreconfigitem('format', 'usegeneraldelta',
131 coreconfigitem('format', 'usegeneraldelta',
132 default=True,
132 default=True,
133 )
133 )
134 coreconfigitem('format', 'usestore',
134 coreconfigitem('format', 'usestore',
135 default=True,
135 default=True,
136 )
136 )
137 coreconfigitem('hostsecurity', 'ciphers',
137 coreconfigitem('hostsecurity', 'ciphers',
138 default=None,
138 default=None,
139 )
139 )
140 coreconfigitem('hostsecurity', 'disabletls10warning',
140 coreconfigitem('hostsecurity', 'disabletls10warning',
141 default=False,
141 default=False,
142 )
142 )
143 coreconfigitem('patch', 'eol',
143 coreconfigitem('patch', 'eol',
144 default='strict',
144 default='strict',
145 )
145 )
146 coreconfigitem('patch', 'fuzz',
146 coreconfigitem('patch', 'fuzz',
147 default=2,
147 default=2,
148 )
148 )
149 coreconfigitem('progress', 'assume-tty',
149 coreconfigitem('progress', 'assume-tty',
150 default=False,
150 default=False,
151 )
151 )
152 coreconfigitem('progress', 'clear-complete',
152 coreconfigitem('progress', 'clear-complete',
153 default=True,
153 default=True,
154 )
154 )
155 coreconfigitem('progress', 'estimate',
156 default=2,
157 )
155 coreconfigitem('server', 'bundle1',
158 coreconfigitem('server', 'bundle1',
156 default=True,
159 default=True,
157 )
160 )
158 coreconfigitem('server', 'bundle1gd',
161 coreconfigitem('server', 'bundle1gd',
159 default=None,
162 default=None,
160 )
163 )
161 coreconfigitem('server', 'compressionengines',
164 coreconfigitem('server', 'compressionengines',
162 default=list,
165 default=list,
163 )
166 )
164 coreconfigitem('server', 'concurrent-push-mode',
167 coreconfigitem('server', 'concurrent-push-mode',
165 default='strict',
168 default='strict',
166 )
169 )
167 coreconfigitem('server', 'disablefullbundle',
170 coreconfigitem('server', 'disablefullbundle',
168 default=False,
171 default=False,
169 )
172 )
170 coreconfigitem('server', 'maxhttpheaderlen',
173 coreconfigitem('server', 'maxhttpheaderlen',
171 default=1024,
174 default=1024,
172 )
175 )
173 coreconfigitem('server', 'preferuncompressed',
176 coreconfigitem('server', 'preferuncompressed',
174 default=False,
177 default=False,
175 )
178 )
176 coreconfigitem('server', 'uncompressedallowsecret',
179 coreconfigitem('server', 'uncompressedallowsecret',
177 default=False,
180 default=False,
178 )
181 )
179 coreconfigitem('server', 'validate',
182 coreconfigitem('server', 'validate',
180 default=False,
183 default=False,
181 )
184 )
182 coreconfigitem('server', 'zliblevel',
185 coreconfigitem('server', 'zliblevel',
183 default=-1,
186 default=-1,
184 )
187 )
185 coreconfigitem('ui', 'clonebundleprefers',
188 coreconfigitem('ui', 'clonebundleprefers',
186 default=list,
189 default=list,
187 )
190 )
188 coreconfigitem('ui', 'interactive',
191 coreconfigitem('ui', 'interactive',
189 default=None,
192 default=None,
190 )
193 )
191 coreconfigitem('ui', 'quiet',
194 coreconfigitem('ui', 'quiet',
192 default=False,
195 default=False,
193 )
196 )
194 # Windows defaults to a limit of 512 open files. A buffer of 128
197 # Windows defaults to a limit of 512 open files. A buffer of 128
195 # should give us enough headway.
198 # should give us enough headway.
196 coreconfigitem('worker', 'backgroundclosemaxqueue',
199 coreconfigitem('worker', 'backgroundclosemaxqueue',
197 default=384,
200 default=384,
198 )
201 )
199 coreconfigitem('worker', 'backgroundcloseminfilecount',
202 coreconfigitem('worker', 'backgroundcloseminfilecount',
200 default=2048,
203 default=2048,
201 )
204 )
202 coreconfigitem('worker', 'backgroundclosethreadcount',
205 coreconfigitem('worker', 'backgroundclosethreadcount',
203 default=4,
206 default=4,
204 )
207 )
205 coreconfigitem('worker', 'numcpus',
208 coreconfigitem('worker', 'numcpus',
206 default=None,
209 default=None,
207 )
210 )
@@ -1,280 +1,280 b''
1 # progress.py progress bars related code
1 # progress.py progress bars related code
2 #
2 #
3 # Copyright (C) 2010 Augie Fackler <durin42@gmail.com>
3 # Copyright (C) 2010 Augie Fackler <durin42@gmail.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import threading
11 import threading
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 def spacejoin(*args):
17 def spacejoin(*args):
18 return ' '.join(s for s in args if s)
18 return ' '.join(s for s in args if s)
19
19
20 def shouldprint(ui):
20 def shouldprint(ui):
21 return not (ui.quiet or ui.plain('progress')) and (
21 return not (ui.quiet or ui.plain('progress')) and (
22 ui._isatty(ui.ferr) or ui.configbool('progress', 'assume-tty'))
22 ui._isatty(ui.ferr) or ui.configbool('progress', 'assume-tty'))
23
23
24 def fmtremaining(seconds):
24 def fmtremaining(seconds):
25 """format a number of remaining seconds in human readable way
25 """format a number of remaining seconds in human readable way
26
26
27 This will properly display seconds, minutes, hours, days if needed"""
27 This will properly display seconds, minutes, hours, days if needed"""
28 if seconds < 60:
28 if seconds < 60:
29 # i18n: format XX seconds as "XXs"
29 # i18n: format XX seconds as "XXs"
30 return _("%02ds") % (seconds)
30 return _("%02ds") % (seconds)
31 minutes = seconds // 60
31 minutes = seconds // 60
32 if minutes < 60:
32 if minutes < 60:
33 seconds -= minutes * 60
33 seconds -= minutes * 60
34 # i18n: format X minutes and YY seconds as "XmYYs"
34 # i18n: format X minutes and YY seconds as "XmYYs"
35 return _("%dm%02ds") % (minutes, seconds)
35 return _("%dm%02ds") % (minutes, seconds)
36 # we're going to ignore seconds in this case
36 # we're going to ignore seconds in this case
37 minutes += 1
37 minutes += 1
38 hours = minutes // 60
38 hours = minutes // 60
39 minutes -= hours * 60
39 minutes -= hours * 60
40 if hours < 30:
40 if hours < 30:
41 # i18n: format X hours and YY minutes as "XhYYm"
41 # i18n: format X hours and YY minutes as "XhYYm"
42 return _("%dh%02dm") % (hours, minutes)
42 return _("%dh%02dm") % (hours, minutes)
43 # we're going to ignore minutes in this case
43 # we're going to ignore minutes in this case
44 hours += 1
44 hours += 1
45 days = hours // 24
45 days = hours // 24
46 hours -= days * 24
46 hours -= days * 24
47 if days < 15:
47 if days < 15:
48 # i18n: format X days and YY hours as "XdYYh"
48 # i18n: format X days and YY hours as "XdYYh"
49 return _("%dd%02dh") % (days, hours)
49 return _("%dd%02dh") % (days, hours)
50 # we're going to ignore hours in this case
50 # we're going to ignore hours in this case
51 days += 1
51 days += 1
52 weeks = days // 7
52 weeks = days // 7
53 days -= weeks * 7
53 days -= weeks * 7
54 if weeks < 55:
54 if weeks < 55:
55 # i18n: format X weeks and YY days as "XwYYd"
55 # i18n: format X weeks and YY days as "XwYYd"
56 return _("%dw%02dd") % (weeks, days)
56 return _("%dw%02dd") % (weeks, days)
57 # we're going to ignore days and treat a year as 52 weeks
57 # we're going to ignore days and treat a year as 52 weeks
58 weeks += 1
58 weeks += 1
59 years = weeks // 52
59 years = weeks // 52
60 weeks -= years * 52
60 weeks -= years * 52
61 # i18n: format X years and YY weeks as "XyYYw"
61 # i18n: format X years and YY weeks as "XyYYw"
62 return _("%dy%02dw") % (years, weeks)
62 return _("%dy%02dw") % (years, weeks)
63
63
64 # file_write() and file_flush() of Python 2 do not restart on EINTR if
64 # 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
65 # 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(),
66 # 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
67 # 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
68 # single write() syscall, so we can just retry file_write() with the whole
69 # text. (issue5532)
69 # text. (issue5532)
70 #
70 #
71 # This should be a short-term workaround. We'll need to fix every occurrence
71 # This should be a short-term workaround. We'll need to fix every occurrence
72 # of write() to a terminal or pipe.
72 # of write() to a terminal or pipe.
73 def _eintrretry(func, *args):
73 def _eintrretry(func, *args):
74 while True:
74 while True:
75 try:
75 try:
76 return func(*args)
76 return func(*args)
77 except IOError as err:
77 except IOError as err:
78 if err.errno == errno.EINTR:
78 if err.errno == errno.EINTR:
79 continue
79 continue
80 raise
80 raise
81
81
82 class progbar(object):
82 class progbar(object):
83 def __init__(self, ui):
83 def __init__(self, ui):
84 self.ui = ui
84 self.ui = ui
85 self._refreshlock = threading.Lock()
85 self._refreshlock = threading.Lock()
86 self.resetstate()
86 self.resetstate()
87
87
88 def resetstate(self):
88 def resetstate(self):
89 self.topics = []
89 self.topics = []
90 self.topicstates = {}
90 self.topicstates = {}
91 self.starttimes = {}
91 self.starttimes = {}
92 self.startvals = {}
92 self.startvals = {}
93 self.printed = False
93 self.printed = False
94 self.lastprint = time.time() + float(self.ui.config(
94 self.lastprint = time.time() + float(self.ui.config(
95 'progress', 'delay', default=3))
95 'progress', 'delay', default=3))
96 self.curtopic = None
96 self.curtopic = None
97 self.lasttopic = None
97 self.lasttopic = None
98 self.indetcount = 0
98 self.indetcount = 0
99 self.refresh = float(self.ui.config(
99 self.refresh = float(self.ui.config(
100 'progress', 'refresh', default=0.1))
100 'progress', 'refresh', default=0.1))
101 self.changedelay = max(3 * self.refresh,
101 self.changedelay = max(3 * self.refresh,
102 float(self.ui.config(
102 float(self.ui.config(
103 'progress', 'changedelay', default=1)))
103 'progress', 'changedelay', default=1)))
104 self.order = self.ui.configlist(
104 self.order = self.ui.configlist(
105 'progress', 'format',
105 'progress', 'format',
106 default=['topic', 'bar', 'number', 'estimate'])
106 default=['topic', 'bar', 'number', 'estimate'])
107
107
108 def show(self, now, topic, pos, item, unit, total):
108 def show(self, now, topic, pos, item, unit, total):
109 if not shouldprint(self.ui):
109 if not shouldprint(self.ui):
110 return
110 return
111 termwidth = self.width()
111 termwidth = self.width()
112 self.printed = True
112 self.printed = True
113 head = ''
113 head = ''
114 needprogress = False
114 needprogress = False
115 tail = ''
115 tail = ''
116 for indicator in self.order:
116 for indicator in self.order:
117 add = ''
117 add = ''
118 if indicator == 'topic':
118 if indicator == 'topic':
119 add = topic
119 add = topic
120 elif indicator == 'number':
120 elif indicator == 'number':
121 if total:
121 if total:
122 add = ('% ' + str(len(str(total))) +
122 add = ('% ' + str(len(str(total))) +
123 's/%s') % (pos, total)
123 's/%s') % (pos, total)
124 else:
124 else:
125 add = str(pos)
125 add = str(pos)
126 elif indicator.startswith('item') and item:
126 elif indicator.startswith('item') and item:
127 slice = 'end'
127 slice = 'end'
128 if '-' in indicator:
128 if '-' in indicator:
129 wid = int(indicator.split('-')[1])
129 wid = int(indicator.split('-')[1])
130 elif '+' in indicator:
130 elif '+' in indicator:
131 slice = 'beginning'
131 slice = 'beginning'
132 wid = int(indicator.split('+')[1])
132 wid = int(indicator.split('+')[1])
133 else:
133 else:
134 wid = 20
134 wid = 20
135 if slice == 'end':
135 if slice == 'end':
136 add = encoding.trim(item, wid, leftside=True)
136 add = encoding.trim(item, wid, leftside=True)
137 else:
137 else:
138 add = encoding.trim(item, wid)
138 add = encoding.trim(item, wid)
139 add += (wid - encoding.colwidth(add)) * ' '
139 add += (wid - encoding.colwidth(add)) * ' '
140 elif indicator == 'bar':
140 elif indicator == 'bar':
141 add = ''
141 add = ''
142 needprogress = True
142 needprogress = True
143 elif indicator == 'unit' and unit:
143 elif indicator == 'unit' and unit:
144 add = unit
144 add = unit
145 elif indicator == 'estimate':
145 elif indicator == 'estimate':
146 add = self.estimate(topic, pos, total, now)
146 add = self.estimate(topic, pos, total, now)
147 elif indicator == 'speed':
147 elif indicator == 'speed':
148 add = self.speed(topic, pos, unit, now)
148 add = self.speed(topic, pos, unit, now)
149 if not needprogress:
149 if not needprogress:
150 head = spacejoin(head, add)
150 head = spacejoin(head, add)
151 else:
151 else:
152 tail = spacejoin(tail, add)
152 tail = spacejoin(tail, add)
153 if needprogress:
153 if needprogress:
154 used = 0
154 used = 0
155 if head:
155 if head:
156 used += encoding.colwidth(head) + 1
156 used += encoding.colwidth(head) + 1
157 if tail:
157 if tail:
158 used += encoding.colwidth(tail) + 1
158 used += encoding.colwidth(tail) + 1
159 progwidth = termwidth - used - 3
159 progwidth = termwidth - used - 3
160 if total and pos <= total:
160 if total and pos <= total:
161 amt = pos * progwidth // total
161 amt = pos * progwidth // total
162 bar = '=' * (amt - 1)
162 bar = '=' * (amt - 1)
163 if amt > 0:
163 if amt > 0:
164 bar += '>'
164 bar += '>'
165 bar += ' ' * (progwidth - amt)
165 bar += ' ' * (progwidth - amt)
166 else:
166 else:
167 progwidth -= 3
167 progwidth -= 3
168 self.indetcount += 1
168 self.indetcount += 1
169 # mod the count by twice the width so we can make the
169 # mod the count by twice the width so we can make the
170 # cursor bounce between the right and left sides
170 # cursor bounce between the right and left sides
171 amt = self.indetcount % (2 * progwidth)
171 amt = self.indetcount % (2 * progwidth)
172 amt -= progwidth
172 amt -= progwidth
173 bar = (' ' * int(progwidth - abs(amt)) + '<=>' +
173 bar = (' ' * int(progwidth - abs(amt)) + '<=>' +
174 ' ' * int(abs(amt)))
174 ' ' * int(abs(amt)))
175 prog = ''.join(('[', bar , ']'))
175 prog = ''.join(('[', bar , ']'))
176 out = spacejoin(head, prog, tail)
176 out = spacejoin(head, prog, tail)
177 else:
177 else:
178 out = spacejoin(head, tail)
178 out = spacejoin(head, tail)
179 self._writeerr('\r' + encoding.trim(out, termwidth))
179 self._writeerr('\r' + encoding.trim(out, termwidth))
180 self.lasttopic = topic
180 self.lasttopic = topic
181 self._flusherr()
181 self._flusherr()
182
182
183 def clear(self):
183 def clear(self):
184 if not self.printed or not self.lastprint or not shouldprint(self.ui):
184 if not self.printed or not self.lastprint or not shouldprint(self.ui):
185 return
185 return
186 self._writeerr('\r%s\r' % (' ' * self.width()))
186 self._writeerr('\r%s\r' % (' ' * self.width()))
187 if self.printed:
187 if self.printed:
188 # force immediate re-paint of progress bar
188 # force immediate re-paint of progress bar
189 self.lastprint = 0
189 self.lastprint = 0
190
190
191 def complete(self):
191 def complete(self):
192 if not shouldprint(self.ui):
192 if not shouldprint(self.ui):
193 return
193 return
194 if self.ui.configbool('progress', 'clear-complete'):
194 if self.ui.configbool('progress', 'clear-complete'):
195 self.clear()
195 self.clear()
196 else:
196 else:
197 self._writeerr('\n')
197 self._writeerr('\n')
198 self._flusherr()
198 self._flusherr()
199
199
200 def _flusherr(self):
200 def _flusherr(self):
201 _eintrretry(self.ui.ferr.flush)
201 _eintrretry(self.ui.ferr.flush)
202
202
203 def _writeerr(self, msg):
203 def _writeerr(self, msg):
204 _eintrretry(self.ui.ferr.write, msg)
204 _eintrretry(self.ui.ferr.write, msg)
205
205
206 def width(self):
206 def width(self):
207 tw = self.ui.termwidth()
207 tw = self.ui.termwidth()
208 return min(int(self.ui.config('progress', 'width', default=tw)), tw)
208 return min(int(self.ui.config('progress', 'width', default=tw)), tw)
209
209
210 def estimate(self, topic, pos, total, now):
210 def estimate(self, topic, pos, total, now):
211 if total is None:
211 if total is None:
212 return ''
212 return ''
213 initialpos = self.startvals[topic]
213 initialpos = self.startvals[topic]
214 target = total - initialpos
214 target = total - initialpos
215 delta = pos - initialpos
215 delta = pos - initialpos
216 if delta > 0:
216 if delta > 0:
217 elapsed = now - self.starttimes[topic]
217 elapsed = now - self.starttimes[topic]
218 # experimental config: progress.estimate
218 # experimental config: progress.estimate
219 if elapsed > float(
219 if elapsed > float(
220 self.ui.config('progress', 'estimate', default=2)):
220 self.ui.config('progress', 'estimate')):
221 seconds = (elapsed * (target - delta)) // delta + 1
221 seconds = (elapsed * (target - delta)) // delta + 1
222 return fmtremaining(seconds)
222 return fmtremaining(seconds)
223 return ''
223 return ''
224
224
225 def speed(self, topic, pos, unit, now):
225 def speed(self, topic, pos, unit, now):
226 initialpos = self.startvals[topic]
226 initialpos = self.startvals[topic]
227 delta = pos - initialpos
227 delta = pos - initialpos
228 elapsed = now - self.starttimes[topic]
228 elapsed = now - self.starttimes[topic]
229 if elapsed > float(
229 if elapsed > float(
230 self.ui.config('progress', 'estimate', default=2)):
230 self.ui.config('progress', 'estimate')):
231 return _('%d %s/sec') % (delta / elapsed, unit)
231 return _('%d %s/sec') % (delta / elapsed, unit)
232 return ''
232 return ''
233
233
234 def _oktoprint(self, now):
234 def _oktoprint(self, now):
235 '''Check if conditions are met to print - e.g. changedelay elapsed'''
235 '''Check if conditions are met to print - e.g. changedelay elapsed'''
236 if (self.lasttopic is None # first time we printed
236 if (self.lasttopic is None # first time we printed
237 # not a topic change
237 # not a topic change
238 or self.curtopic == self.lasttopic
238 or self.curtopic == self.lasttopic
239 # it's been long enough we should print anyway
239 # it's been long enough we should print anyway
240 or now - self.lastprint >= self.changedelay):
240 or now - self.lastprint >= self.changedelay):
241 return True
241 return True
242 else:
242 else:
243 return False
243 return False
244
244
245 def progress(self, topic, pos, item='', unit='', total=None):
245 def progress(self, topic, pos, item='', unit='', total=None):
246 now = time.time()
246 now = time.time()
247 self._refreshlock.acquire()
247 self._refreshlock.acquire()
248 try:
248 try:
249 if pos is None:
249 if pos is None:
250 self.starttimes.pop(topic, None)
250 self.starttimes.pop(topic, None)
251 self.startvals.pop(topic, None)
251 self.startvals.pop(topic, None)
252 self.topicstates.pop(topic, None)
252 self.topicstates.pop(topic, None)
253 # reset the progress bar if this is the outermost topic
253 # reset the progress bar if this is the outermost topic
254 if self.topics and self.topics[0] == topic and self.printed:
254 if self.topics and self.topics[0] == topic and self.printed:
255 self.complete()
255 self.complete()
256 self.resetstate()
256 self.resetstate()
257 # truncate the list of topics assuming all topics within
257 # truncate the list of topics assuming all topics within
258 # this one are also closed
258 # this one are also closed
259 if topic in self.topics:
259 if topic in self.topics:
260 self.topics = self.topics[:self.topics.index(topic)]
260 self.topics = self.topics[:self.topics.index(topic)]
261 # reset the last topic to the one we just unwound to,
261 # reset the last topic to the one we just unwound to,
262 # so that higher-level topics will be stickier than
262 # so that higher-level topics will be stickier than
263 # lower-level topics
263 # lower-level topics
264 if self.topics:
264 if self.topics:
265 self.lasttopic = self.topics[-1]
265 self.lasttopic = self.topics[-1]
266 else:
266 else:
267 self.lasttopic = None
267 self.lasttopic = None
268 else:
268 else:
269 if topic not in self.topics:
269 if topic not in self.topics:
270 self.starttimes[topic] = now
270 self.starttimes[topic] = now
271 self.startvals[topic] = pos
271 self.startvals[topic] = pos
272 self.topics.append(topic)
272 self.topics.append(topic)
273 self.topicstates[topic] = pos, item, unit, total
273 self.topicstates[topic] = pos, item, unit, total
274 self.curtopic = topic
274 self.curtopic = topic
275 if now - self.lastprint >= self.refresh and self.topics:
275 if now - self.lastprint >= self.refresh and self.topics:
276 if self._oktoprint(now):
276 if self._oktoprint(now):
277 self.lastprint = now
277 self.lastprint = now
278 self.show(now, topic, *self.topicstates[topic])
278 self.show(now, topic, *self.topicstates[topic])
279 finally:
279 finally:
280 self._refreshlock.release()
280 self._refreshlock.release()
General Comments 0
You need to be logged in to leave comments. Login now