##// END OF EJS Templates
progress: add a changedelay to prevent parallel topics from flapping (issue2698)...
Augie Fackler -
r14838:5d261fd0 default
parent child Browse files
Show More
@@ -1,289 +1,302 b''
1 # progress.py show progress bars for some actions
1 # progress.py show progress bars for some actions
2 #
2 #
3 # Copyright (C) 2010 Augie Fackler <durin42@gmail.com>
3 # Copyright (C) 2010 Augie Fackler <durin42@gmail.com>
4 #
4 #
5 # This program is free software; you can redistribute it and/or modify it
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the
6 # under the terms of the GNU General Public License as published by the
7 # Free Software Foundation; either version 2 of the License, or (at your
7 # Free Software Foundation; either version 2 of the License, or (at your
8 # option) any later version.
8 # option) any later version.
9 #
9 #
10 # This program is distributed in the hope that it will be useful, but
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 # Public License for more details.
13 # Public License for more details.
14 #
14 #
15 # You should have received a copy of the GNU General Public License along
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
18
19 """show progress bars for some actions
19 """show progress bars for some actions
20
20
21 This extension uses the progress information logged by hg commands
21 This extension uses the progress information logged by hg commands
22 to draw progress bars that are as informative as possible. Some progress
22 to draw progress bars that are as informative as possible. Some progress
23 bars only offer indeterminate information, while others have a definite
23 bars only offer indeterminate information, while others have a definite
24 end point.
24 end point.
25
25
26 The following settings are available::
26 The following settings are available::
27
27
28 [progress]
28 [progress]
29 delay = 3 # number of seconds (float) before showing the progress bar
29 delay = 3 # number of seconds (float) before showing the progress bar
30 changedelay = 1 # changedelay: minimum delay before showing a new topic.
31 # If set to less than 3 * refresh, that value will
32 # be used instead.
30 refresh = 0.1 # time in seconds between refreshes of the progress bar
33 refresh = 0.1 # time in seconds between refreshes of the progress bar
31 format = topic bar number estimate # format of the progress bar
34 format = topic bar number estimate # format of the progress bar
32 width = <none> # if set, the maximum width of the progress information
35 width = <none> # if set, the maximum width of the progress information
33 # (that is, min(width, term width) will be used)
36 # (that is, min(width, term width) will be used)
34 clear-complete = True # clear the progress bar after it's done
37 clear-complete = True # clear the progress bar after it's done
35 disable = False # if true, don't show a progress bar
38 disable = False # if true, don't show a progress bar
36 assume-tty = False # if true, ALWAYS show a progress bar, unless
39 assume-tty = False # if true, ALWAYS show a progress bar, unless
37 # disable is given
40 # disable is given
38
41
39 Valid entries for the format field are topic, bar, number, unit,
42 Valid entries for the format field are topic, bar, number, unit,
40 estimate, speed, and item. item defaults to the last 20 characters of
43 estimate, speed, and item. item defaults to the last 20 characters of
41 the item, but this can be changed by adding either ``-<num>`` which
44 the item, but this can be changed by adding either ``-<num>`` which
42 would take the last num characters, or ``+<num>`` for the first num
45 would take the last num characters, or ``+<num>`` for the first num
43 characters.
46 characters.
44 """
47 """
45
48
46 import sys
49 import sys
47 import time
50 import time
48
51
49 from mercurial import util
52 from mercurial import util
50 from mercurial.i18n import _
53 from mercurial.i18n import _
51
54
52 def spacejoin(*args):
55 def spacejoin(*args):
53 return ' '.join(s for s in args if s)
56 return ' '.join(s for s in args if s)
54
57
55 def shouldprint(ui):
58 def shouldprint(ui):
56 return util.isatty(sys.stderr) or ui.configbool('progress', 'assume-tty')
59 return util.isatty(sys.stderr) or ui.configbool('progress', 'assume-tty')
57
60
58 def fmtremaining(seconds):
61 def fmtremaining(seconds):
59 if seconds < 60:
62 if seconds < 60:
60 # i18n: format XX seconds as "XXs"
63 # i18n: format XX seconds as "XXs"
61 return _("%02ds") % (seconds)
64 return _("%02ds") % (seconds)
62 minutes = seconds // 60
65 minutes = seconds // 60
63 if minutes < 60:
66 if minutes < 60:
64 seconds -= minutes * 60
67 seconds -= minutes * 60
65 # i18n: format X minutes and YY seconds as "XmYYs"
68 # i18n: format X minutes and YY seconds as "XmYYs"
66 return _("%dm%02ds") % (minutes, seconds)
69 return _("%dm%02ds") % (minutes, seconds)
67 # we're going to ignore seconds in this case
70 # we're going to ignore seconds in this case
68 minutes += 1
71 minutes += 1
69 hours = minutes // 60
72 hours = minutes // 60
70 minutes -= hours * 60
73 minutes -= hours * 60
71 if hours < 30:
74 if hours < 30:
72 # i18n: format X hours and YY minutes as "XhYYm"
75 # i18n: format X hours and YY minutes as "XhYYm"
73 return _("%dh%02dm") % (hours, minutes)
76 return _("%dh%02dm") % (hours, minutes)
74 # we're going to ignore minutes in this case
77 # we're going to ignore minutes in this case
75 hours += 1
78 hours += 1
76 days = hours // 24
79 days = hours // 24
77 hours -= days * 24
80 hours -= days * 24
78 if days < 15:
81 if days < 15:
79 # i18n: format X days and YY hours as "XdYYh"
82 # i18n: format X days and YY hours as "XdYYh"
80 return _("%dd%02dh") % (days, hours)
83 return _("%dd%02dh") % (days, hours)
81 # we're going to ignore hours in this case
84 # we're going to ignore hours in this case
82 days += 1
85 days += 1
83 weeks = days // 7
86 weeks = days // 7
84 days -= weeks * 7
87 days -= weeks * 7
85 if weeks < 55:
88 if weeks < 55:
86 # i18n: format X weeks and YY days as "XwYYd"
89 # i18n: format X weeks and YY days as "XwYYd"
87 return _("%dw%02dd") % (weeks, days)
90 return _("%dw%02dd") % (weeks, days)
88 # we're going to ignore days and treat a year as 52 weeks
91 # we're going to ignore days and treat a year as 52 weeks
89 weeks += 1
92 weeks += 1
90 years = weeks // 52
93 years = weeks // 52
91 weeks -= years * 52
94 weeks -= years * 52
92 # i18n: format X years and YY weeks as "XyYYw"
95 # i18n: format X years and YY weeks as "XyYYw"
93 return _("%dy%02dw") % (years, weeks)
96 return _("%dy%02dw") % (years, weeks)
94
97
95 class progbar(object):
98 class progbar(object):
96 def __init__(self, ui):
99 def __init__(self, ui):
97 self.ui = ui
100 self.ui = ui
98 self.resetstate()
101 self.resetstate()
99
102
100 def resetstate(self):
103 def resetstate(self):
101 self.topics = []
104 self.topics = []
102 self.topicstates = {}
105 self.topicstates = {}
103 self.starttimes = {}
106 self.starttimes = {}
104 self.startvals = {}
107 self.startvals = {}
105 self.printed = False
108 self.printed = False
106 self.lastprint = time.time() + float(self.ui.config(
109 self.lastprint = time.time() + float(self.ui.config(
107 'progress', 'delay', default=3))
110 'progress', 'delay', default=3))
111 self.lasttopic = None
108 self.indetcount = 0
112 self.indetcount = 0
109 self.refresh = float(self.ui.config(
113 self.refresh = float(self.ui.config(
110 'progress', 'refresh', default=0.1))
114 'progress', 'refresh', default=0.1))
115 self.changedelay = max(3 * self.refresh,
116 float(self.ui.config(
117 'progress', 'changedelay', default=1)))
111 self.order = self.ui.configlist(
118 self.order = self.ui.configlist(
112 'progress', 'format',
119 'progress', 'format',
113 default=['topic', 'bar', 'number', 'estimate'])
120 default=['topic', 'bar', 'number', 'estimate'])
114
121
115 def show(self, now, topic, pos, item, unit, total):
122 def show(self, now, topic, pos, item, unit, total):
116 if not shouldprint(self.ui):
123 if not shouldprint(self.ui):
117 return
124 return
118 termwidth = self.width()
125 termwidth = self.width()
119 self.printed = True
126 self.printed = True
120 head = ''
127 head = ''
121 needprogress = False
128 needprogress = False
122 tail = ''
129 tail = ''
123 for indicator in self.order:
130 for indicator in self.order:
124 add = ''
131 add = ''
125 if indicator == 'topic':
132 if indicator == 'topic':
126 add = topic
133 add = topic
127 elif indicator == 'number':
134 elif indicator == 'number':
128 if total:
135 if total:
129 add = ('% ' + str(len(str(total))) +
136 add = ('% ' + str(len(str(total))) +
130 's/%s') % (pos, total)
137 's/%s') % (pos, total)
131 else:
138 else:
132 add = str(pos)
139 add = str(pos)
133 elif indicator.startswith('item') and item:
140 elif indicator.startswith('item') and item:
134 slice = 'end'
141 slice = 'end'
135 if '-' in indicator:
142 if '-' in indicator:
136 wid = int(indicator.split('-')[1])
143 wid = int(indicator.split('-')[1])
137 elif '+' in indicator:
144 elif '+' in indicator:
138 slice = 'beginning'
145 slice = 'beginning'
139 wid = int(indicator.split('+')[1])
146 wid = int(indicator.split('+')[1])
140 else:
147 else:
141 wid = 20
148 wid = 20
142 if slice == 'end':
149 if slice == 'end':
143 add = item[-wid:]
150 add = item[-wid:]
144 else:
151 else:
145 add = item[:wid]
152 add = item[:wid]
146 add += (wid - len(add)) * ' '
153 add += (wid - len(add)) * ' '
147 elif indicator == 'bar':
154 elif indicator == 'bar':
148 add = ''
155 add = ''
149 needprogress = True
156 needprogress = True
150 elif indicator == 'unit' and unit:
157 elif indicator == 'unit' and unit:
151 add = unit
158 add = unit
152 elif indicator == 'estimate':
159 elif indicator == 'estimate':
153 add = self.estimate(topic, pos, total, now)
160 add = self.estimate(topic, pos, total, now)
154 elif indicator == 'speed':
161 elif indicator == 'speed':
155 add = self.speed(topic, pos, unit, now)
162 add = self.speed(topic, pos, unit, now)
156 if not needprogress:
163 if not needprogress:
157 head = spacejoin(head, add)
164 head = spacejoin(head, add)
158 else:
165 else:
159 tail = spacejoin(tail, add)
166 tail = spacejoin(tail, add)
160 if needprogress:
167 if needprogress:
161 used = 0
168 used = 0
162 if head:
169 if head:
163 used += len(head) + 1
170 used += len(head) + 1
164 if tail:
171 if tail:
165 used += len(tail) + 1
172 used += len(tail) + 1
166 progwidth = termwidth - used - 3
173 progwidth = termwidth - used - 3
167 if total and pos <= total:
174 if total and pos <= total:
168 amt = pos * progwidth // total
175 amt = pos * progwidth // total
169 bar = '=' * (amt - 1)
176 bar = '=' * (amt - 1)
170 if amt > 0:
177 if amt > 0:
171 bar += '>'
178 bar += '>'
172 bar += ' ' * (progwidth - amt)
179 bar += ' ' * (progwidth - amt)
173 else:
180 else:
174 progwidth -= 3
181 progwidth -= 3
175 self.indetcount += 1
182 self.indetcount += 1
176 # mod the count by twice the width so we can make the
183 # mod the count by twice the width so we can make the
177 # cursor bounce between the right and left sides
184 # cursor bounce between the right and left sides
178 amt = self.indetcount % (2 * progwidth)
185 amt = self.indetcount % (2 * progwidth)
179 amt -= progwidth
186 amt -= progwidth
180 bar = (' ' * int(progwidth - abs(amt)) + '<=>' +
187 bar = (' ' * int(progwidth - abs(amt)) + '<=>' +
181 ' ' * int(abs(amt)))
188 ' ' * int(abs(amt)))
182 prog = ''.join(('[', bar , ']'))
189 prog = ''.join(('[', bar , ']'))
183 out = spacejoin(head, prog, tail)
190 out = spacejoin(head, prog, tail)
184 else:
191 else:
185 out = spacejoin(head, tail)
192 out = spacejoin(head, tail)
186 sys.stderr.write('\r' + out[:termwidth])
193 sys.stderr.write('\r' + out[:termwidth])
194 self.lasttopic = topic
187 sys.stderr.flush()
195 sys.stderr.flush()
188
196
189 def clear(self):
197 def clear(self):
190 if not shouldprint(self.ui):
198 if not shouldprint(self.ui):
191 return
199 return
192 sys.stderr.write('\r%s\r' % (' ' * self.width()))
200 sys.stderr.write('\r%s\r' % (' ' * self.width()))
193
201
194 def complete(self):
202 def complete(self):
195 if not shouldprint(self.ui):
203 if not shouldprint(self.ui):
196 return
204 return
197 if self.ui.configbool('progress', 'clear-complete', default=True):
205 if self.ui.configbool('progress', 'clear-complete', default=True):
198 self.clear()
206 self.clear()
199 else:
207 else:
200 sys.stderr.write('\n')
208 sys.stderr.write('\n')
201 sys.stderr.flush()
209 sys.stderr.flush()
202
210
203 def width(self):
211 def width(self):
204 tw = self.ui.termwidth()
212 tw = self.ui.termwidth()
205 return min(int(self.ui.config('progress', 'width', default=tw)), tw)
213 return min(int(self.ui.config('progress', 'width', default=tw)), tw)
206
214
207 def estimate(self, topic, pos, total, now):
215 def estimate(self, topic, pos, total, now):
208 if total is None:
216 if total is None:
209 return ''
217 return ''
210 initialpos = self.startvals[topic]
218 initialpos = self.startvals[topic]
211 target = total - initialpos
219 target = total - initialpos
212 delta = pos - initialpos
220 delta = pos - initialpos
213 if delta > 0:
221 if delta > 0:
214 elapsed = now - self.starttimes[topic]
222 elapsed = now - self.starttimes[topic]
215 if elapsed > float(
223 if elapsed > float(
216 self.ui.config('progress', 'estimate', default=2)):
224 self.ui.config('progress', 'estimate', default=2)):
217 seconds = (elapsed * (target - delta)) // delta + 1
225 seconds = (elapsed * (target - delta)) // delta + 1
218 return fmtremaining(seconds)
226 return fmtremaining(seconds)
219 return ''
227 return ''
220
228
221 def speed(self, topic, pos, unit, now):
229 def speed(self, topic, pos, unit, now):
222 initialpos = self.startvals[topic]
230 initialpos = self.startvals[topic]
223 delta = pos - initialpos
231 delta = pos - initialpos
224 elapsed = now - self.starttimes[topic]
232 elapsed = now - self.starttimes[topic]
225 if elapsed > float(
233 if elapsed > float(
226 self.ui.config('progress', 'estimate', default=2)):
234 self.ui.config('progress', 'estimate', default=2)):
227 return _('%d %s/sec') % (delta / elapsed, unit)
235 return _('%d %s/sec') % (delta / elapsed, unit)
228 return ''
236 return ''
229
237
230 def progress(self, topic, pos, item='', unit='', total=None):
238 def progress(self, topic, pos, item='', unit='', total=None):
231 now = time.time()
239 now = time.time()
232 if pos is None:
240 if pos is None:
233 self.starttimes.pop(topic, None)
241 self.starttimes.pop(topic, None)
234 self.startvals.pop(topic, None)
242 self.startvals.pop(topic, None)
235 self.topicstates.pop(topic, None)
243 self.topicstates.pop(topic, None)
236 # reset the progress bar if this is the outermost topic
244 # reset the progress bar if this is the outermost topic
237 if self.topics and self.topics[0] == topic and self.printed:
245 if self.topics and self.topics[0] == topic and self.printed:
238 self.complete()
246 self.complete()
239 self.resetstate()
247 self.resetstate()
240 # truncate the list of topics assuming all topics within
248 # truncate the list of topics assuming all topics within
241 # this one are also closed
249 # this one are also closed
242 if topic in self.topics:
250 if topic in self.topics:
243 self.topics = self.topics[:self.topics.index(topic)]
251 self.topics = self.topics[:self.topics.index(topic)]
244 else:
252 else:
245 if topic not in self.topics:
253 if topic not in self.topics:
246 self.starttimes[topic] = now
254 self.starttimes[topic] = now
247 self.startvals[topic] = pos
255 self.startvals[topic] = pos
248 self.topics.append(topic)
256 self.topics.append(topic)
249 self.topicstates[topic] = pos, item, unit, total
257 self.topicstates[topic] = pos, item, unit, total
250 if now - self.lastprint >= self.refresh and self.topics:
258 if now - self.lastprint >= self.refresh and self.topics:
251 self.lastprint = now
259 if (self.lasttopic is None # first time we printed
252 self.show(now, topic, *self.topicstates[topic])
260 # not a topic change
261 or topic == self.lasttopic
262 # it's been long enough we should print anyway
263 or now - self.lastprint >= self.changedelay):
264 self.lastprint = now
265 self.show(now, topic, *self.topicstates[topic])
253
266
254 _singleton = None
267 _singleton = None
255
268
256 def uisetup(ui):
269 def uisetup(ui):
257 global _singleton
270 global _singleton
258 class progressui(ui.__class__):
271 class progressui(ui.__class__):
259 _progbar = None
272 _progbar = None
260
273
261 def progress(self, *args, **opts):
274 def progress(self, *args, **opts):
262 self._progbar.progress(*args, **opts)
275 self._progbar.progress(*args, **opts)
263 return super(progressui, self).progress(*args, **opts)
276 return super(progressui, self).progress(*args, **opts)
264
277
265 def write(self, *args, **opts):
278 def write(self, *args, **opts):
266 if self._progbar.printed:
279 if self._progbar.printed:
267 self._progbar.clear()
280 self._progbar.clear()
268 return super(progressui, self).write(*args, **opts)
281 return super(progressui, self).write(*args, **opts)
269
282
270 def write_err(self, *args, **opts):
283 def write_err(self, *args, **opts):
271 if self._progbar.printed:
284 if self._progbar.printed:
272 self._progbar.clear()
285 self._progbar.clear()
273 return super(progressui, self).write_err(*args, **opts)
286 return super(progressui, self).write_err(*args, **opts)
274
287
275 # Apps that derive a class from ui.ui() can use
288 # Apps that derive a class from ui.ui() can use
276 # setconfig('progress', 'disable', 'True') to disable this extension
289 # setconfig('progress', 'disable', 'True') to disable this extension
277 if ui.configbool('progress', 'disable'):
290 if ui.configbool('progress', 'disable'):
278 return
291 return
279 if shouldprint(ui) and not ui.debugflag and not ui.quiet:
292 if shouldprint(ui) and not ui.debugflag and not ui.quiet:
280 ui.__class__ = progressui
293 ui.__class__ = progressui
281 # we instantiate one globally shared progress bar to avoid
294 # we instantiate one globally shared progress bar to avoid
282 # competing progress bars when multiple UI objects get created
295 # competing progress bars when multiple UI objects get created
283 if not progressui._progbar:
296 if not progressui._progbar:
284 if _singleton is None:
297 if _singleton is None:
285 _singleton = progbar(ui)
298 _singleton = progbar(ui)
286 progressui._progbar = _singleton
299 progressui._progbar = _singleton
287
300
288 def reposetup(ui, repo):
301 def reposetup(ui, repo):
289 uisetup(repo.ui)
302 uisetup(repo.ui)
@@ -1,248 +1,249 b''
1
1
2 $ "$TESTDIR/hghave" svn svn-bindings || exit 80
2 $ "$TESTDIR/hghave" svn svn-bindings || exit 80
3
3
4 $ fixpath()
4 $ fixpath()
5 > {
5 > {
6 > tr '\\' /
6 > tr '\\' /
7 > }
7 > }
8 $ cat >> $HGRCPATH <<EOF
8 $ cat >> $HGRCPATH <<EOF
9 > [extensions]
9 > [extensions]
10 > convert =
10 > convert =
11 > graphlog =
11 > graphlog =
12 > EOF
12 > EOF
13
13
14 $ svnadmin create svn-repo
14 $ svnadmin create svn-repo
15 $ svnadmin load -q svn-repo < "$TESTDIR/svn/move.svndump"
15 $ svnadmin load -q svn-repo < "$TESTDIR/svn/move.svndump"
16 $ svnpath=`pwd | fixpath`
16 $ svnpath=`pwd | fixpath`
17
17
18 SVN wants all paths to start with a slash. Unfortunately,
18 SVN wants all paths to start with a slash. Unfortunately,
19 Windows ones don't. Handle that.
19 Windows ones don't. Handle that.
20
20
21 $ expr "$svnpath" : "\/" > /dev/null
21 $ expr "$svnpath" : "\/" > /dev/null
22 > if [ $? -ne 0 ]; then
22 > if [ $? -ne 0 ]; then
23 > svnpath="/$svnpath"
23 > svnpath="/$svnpath"
24 > fi
24 > fi
25 > svnurl="file://$svnpath/svn-repo"
25 > svnurl="file://$svnpath/svn-repo"
26
26
27 Convert trunk and branches
27 Convert trunk and branches
28
28
29 $ hg convert --datesort "$svnurl"/subproject A-hg
29 $ hg convert --datesort "$svnurl"/subproject A-hg
30 initializing destination A-hg repository
30 initializing destination A-hg repository
31 scanning source...
31 scanning source...
32 sorting...
32 sorting...
33 converting...
33 converting...
34 13 createtrunk
34 13 createtrunk
35 12 moved1
35 12 moved1
36 11 moved1
36 11 moved1
37 10 moved2
37 10 moved2
38 9 changeb and rm d2
38 9 changeb and rm d2
39 8 changeb and rm d2
39 8 changeb and rm d2
40 7 moved1again
40 7 moved1again
41 6 moved1again
41 6 moved1again
42 5 copyfilefrompast
42 5 copyfilefrompast
43 4 copydirfrompast
43 4 copydirfrompast
44 3 add d3
44 3 add d3
45 2 copy dir and remove subdir
45 2 copy dir and remove subdir
46 1 add d4old
46 1 add d4old
47 0 rename d4old into d4new
47 0 rename d4old into d4new
48
48
49 $ cd A-hg
49 $ cd A-hg
50 $ hg glog --template '{rev} {desc|firstline} files: {files}\n'
50 $ hg glog --template '{rev} {desc|firstline} files: {files}\n'
51 o 13 rename d4old into d4new files: d4new/g d4old/g
51 o 13 rename d4old into d4new files: d4new/g d4old/g
52 |
52 |
53 o 12 add d4old files: d4old/g
53 o 12 add d4old files: d4old/g
54 |
54 |
55 o 11 copy dir and remove subdir files: d3/d31/e d4/d31/e d4/f
55 o 11 copy dir and remove subdir files: d3/d31/e d4/d31/e d4/f
56 |
56 |
57 o 10 add d3 files: d3/d31/e d3/f
57 o 10 add d3 files: d3/d31/e d3/f
58 |
58 |
59 o 9 copydirfrompast files: d2/d
59 o 9 copydirfrompast files: d2/d
60 |
60 |
61 o 8 copyfilefrompast files: d
61 o 8 copyfilefrompast files: d
62 |
62 |
63 o 7 moved1again files: d1/b d1/c
63 o 7 moved1again files: d1/b d1/c
64 |
64 |
65 | o 6 moved1again files:
65 | o 6 moved1again files:
66 | |
66 | |
67 o | 5 changeb and rm d2 files: d1/b d2/d
67 o | 5 changeb and rm d2 files: d1/b d2/d
68 | |
68 | |
69 | o 4 changeb and rm d2 files: b
69 | o 4 changeb and rm d2 files: b
70 | |
70 | |
71 o | 3 moved2 files: d2/d
71 o | 3 moved2 files: d2/d
72 | |
72 | |
73 o | 2 moved1 files: d1/b d1/c
73 o | 2 moved1 files: d1/b d1/c
74 | |
74 | |
75 | o 1 moved1 files: b c
75 | o 1 moved1 files: b c
76 |
76 |
77 o 0 createtrunk files:
77 o 0 createtrunk files:
78
78
79
79
80 Check move copy records
80 Check move copy records
81
81
82 $ hg st --rev 12:13 --copies
82 $ hg st --rev 12:13 --copies
83 A d4new/g
83 A d4new/g
84 d4old/g
84 d4old/g
85 R d4old/g
85 R d4old/g
86
86
87 Check branches
87 Check branches
88
88
89 $ hg branches
89 $ hg branches
90 default 13:* (glob)
90 default 13:* (glob)
91 d1 6:* (glob)
91 d1 6:* (glob)
92 $ cd ..
92 $ cd ..
93
93
94 $ mkdir test-replace
94 $ mkdir test-replace
95 $ cd test-replace
95 $ cd test-replace
96 $ svnadmin create svn-repo
96 $ svnadmin create svn-repo
97 $ svnadmin load -q svn-repo < "$TESTDIR/svn/replace.svndump"
97 $ svnadmin load -q svn-repo < "$TESTDIR/svn/replace.svndump"
98
98
99 Convert files being replaced by directories
99 Convert files being replaced by directories
100
100
101 $ hg convert svn-repo hg-repo
101 $ hg convert svn-repo hg-repo
102 initializing destination hg-repo repository
102 initializing destination hg-repo repository
103 scanning source...
103 scanning source...
104 sorting...
104 sorting...
105 converting...
105 converting...
106 6 initial
106 6 initial
107 5 clobber symlink
107 5 clobber symlink
108 4 clobber1
108 4 clobber1
109 3 clobber2
109 3 clobber2
110 2 adddb
110 2 adddb
111 1 branch
111 1 branch
112 0 clobberdir
112 0 clobberdir
113
113
114 $ cd hg-repo
114 $ cd hg-repo
115
115
116 Manifest before
116 Manifest before
117
117
118 $ hg -v manifest -r 1
118 $ hg -v manifest -r 1
119 644 a
119 644 a
120 644 d/b
120 644 d/b
121 644 d2/a
121 644 d2/a
122 644 @ dlink
122 644 @ dlink
123 644 @ dlink2
123 644 @ dlink2
124 644 dlink3
124 644 dlink3
125
125
126 Manifest after clobber1
126 Manifest after clobber1
127
127
128 $ hg -v manifest -r 2
128 $ hg -v manifest -r 2
129 644 a/b
129 644 a/b
130 644 d/b
130 644 d/b
131 644 d2/a
131 644 d2/a
132 644 dlink/b
132 644 dlink/b
133 644 @ dlink2
133 644 @ dlink2
134 644 dlink3
134 644 dlink3
135
135
136 Manifest after clobber2
136 Manifest after clobber2
137
137
138 $ hg -v manifest -r 3
138 $ hg -v manifest -r 3
139 644 a/b
139 644 a/b
140 644 d/b
140 644 d/b
141 644 d2/a
141 644 d2/a
142 644 dlink/b
142 644 dlink/b
143 644 @ dlink2
143 644 @ dlink2
144 644 @ dlink3
144 644 @ dlink3
145
145
146 Manifest after clobberdir
146 Manifest after clobberdir
147
147
148 $ hg -v manifest -r 6
148 $ hg -v manifest -r 6
149 644 a/b
149 644 a/b
150 644 d/b
150 644 d/b
151 644 d2/a
151 644 d2/a
152 644 d2/c
152 644 d2/c
153 644 dlink/b
153 644 dlink/b
154 644 @ dlink2
154 644 @ dlink2
155 644 @ dlink3
155 644 @ dlink3
156
156
157 Try updating
157 Try updating
158
158
159 $ hg up -qC default
159 $ hg up -qC default
160 $ cd ..
160 $ cd ..
161
161
162 Test convert progress bar'
162 Test convert progress bar'
163
163
164 $ cat >> $HGRCPATH <<EOF
164 $ cat >> $HGRCPATH <<EOF
165 > [extensions]
165 > [extensions]
166 > progress =
166 > progress =
167 > [progress]
167 > [progress]
168 > assume-tty = 1
168 > assume-tty = 1
169 > delay = 0
169 > delay = 0
170 > changedelay = 0
170 > format = topic bar number
171 > format = topic bar number
171 > refresh = 0
172 > refresh = 0
172 > width = 60
173 > width = 60
173 > EOF
174 > EOF
174
175
175 $ hg convert svn-repo hg-progress 2>&1 | $TESTDIR/filtercr.py
176 $ hg convert svn-repo hg-progress 2>&1 | $TESTDIR/filtercr.py
176
177
177 scanning [ <=> ] 1
178 scanning [ <=> ] 1
178 scanning [ <=> ] 2
179 scanning [ <=> ] 2
179 scanning [ <=> ] 3
180 scanning [ <=> ] 3
180 scanning [ <=> ] 4
181 scanning [ <=> ] 4
181 scanning [ <=> ] 5
182 scanning [ <=> ] 5
182 scanning [ <=> ] 6
183 scanning [ <=> ] 6
183 scanning [ <=> ] 7
184 scanning [ <=> ] 7
184
185
185 converting [ ] 0/7
186 converting [ ] 0/7
186 getting files [=====> ] 1/6
187 getting files [=====> ] 1/6
187 getting files [============> ] 2/6
188 getting files [============> ] 2/6
188 getting files [==================> ] 3/6
189 getting files [==================> ] 3/6
189 getting files [=========================> ] 4/6
190 getting files [=========================> ] 4/6
190 getting files [===============================> ] 5/6
191 getting files [===============================> ] 5/6
191 getting files [======================================>] 6/6
192 getting files [======================================>] 6/6
192
193
193 converting [=====> ] 1/7
194 converting [=====> ] 1/7
194 scanning paths [ ] 0/1
195 scanning paths [ ] 0/1
195 getting files [======================================>] 1/1
196 getting files [======================================>] 1/1
196
197
197 converting [===========> ] 2/7
198 converting [===========> ] 2/7
198 scanning paths [ ] 0/2
199 scanning paths [ ] 0/2
199 scanning paths [==================> ] 1/2
200 scanning paths [==================> ] 1/2
200 getting files [========> ] 1/4
201 getting files [========> ] 1/4
201 getting files [==================> ] 2/4
202 getting files [==================> ] 2/4
202 getting files [============================> ] 3/4
203 getting files [============================> ] 3/4
203 getting files [======================================>] 4/4
204 getting files [======================================>] 4/4
204
205
205 converting [=================> ] 3/7
206 converting [=================> ] 3/7
206 scanning paths [ ] 0/1
207 scanning paths [ ] 0/1
207 getting files [======================================>] 1/1
208 getting files [======================================>] 1/1
208
209
209 converting [=======================> ] 4/7
210 converting [=======================> ] 4/7
210 scanning paths [ ] 0/1
211 scanning paths [ ] 0/1
211 getting files [======================================>] 1/1
212 getting files [======================================>] 1/1
212
213
213 converting [=============================> ] 5/7
214 converting [=============================> ] 5/7
214 scanning paths [ ] 0/3
215 scanning paths [ ] 0/3
215 scanning paths [===========> ] 1/3
216 scanning paths [===========> ] 1/3
216 scanning paths [========================> ] 2/3
217 scanning paths [========================> ] 2/3
217 getting files [===> ] 1/8
218 getting files [===> ] 1/8
218 getting files [========> ] 2/8
219 getting files [========> ] 2/8
219 getting files [=============> ] 3/8
220 getting files [=============> ] 3/8
220 getting files [==================> ] 4/8
221 getting files [==================> ] 4/8
221 getting files [=======================> ] 5/8
222 getting files [=======================> ] 5/8
222 getting files [============================> ] 6/8
223 getting files [============================> ] 6/8
223 getting files [=================================> ] 7/8
224 getting files [=================================> ] 7/8
224 getting files [======================================>] 8/8
225 getting files [======================================>] 8/8
225
226
226 converting [===================================> ] 6/7
227 converting [===================================> ] 6/7
227 scanning paths [ ] 0/1
228 scanning paths [ ] 0/1
228 getting files [===> ] 1/8
229 getting files [===> ] 1/8
229 getting files [========> ] 2/8
230 getting files [========> ] 2/8
230 getting files [=============> ] 3/8
231 getting files [=============> ] 3/8
231 getting files [==================> ] 4/8
232 getting files [==================> ] 4/8
232 getting files [=======================> ] 5/8
233 getting files [=======================> ] 5/8
233 getting files [============================> ] 6/8
234 getting files [============================> ] 6/8
234 getting files [=================================> ] 7/8
235 getting files [=================================> ] 7/8
235 getting files [======================================>] 8/8
236 getting files [======================================>] 8/8
236
237
237 initializing destination hg-progress repository
238 initializing destination hg-progress repository
238 scanning source...
239 scanning source...
239 sorting...
240 sorting...
240 converting...
241 converting...
241 6 initial
242 6 initial
242 5 clobber symlink
243 5 clobber symlink
243 4 clobber1
244 4 clobber1
244 3 clobber2
245 3 clobber2
245 2 adddb
246 2 adddb
246 1 branch
247 1 branch
247 0 clobberdir
248 0 clobberdir
248
249
@@ -1,166 +1,214 b''
1
1
2 $ cat > loop.py <<EOF
2 $ cat > loop.py <<EOF
3 > from mercurial import commands
3 > from mercurial import commands
4 >
4 >
5 > def loop(ui, loops, **opts):
5 > def loop(ui, loops, **opts):
6 > loops = int(loops)
6 > loops = int(loops)
7 > total = None
7 > total = None
8 > if loops >= 0:
8 > if loops >= 0:
9 > total = loops
9 > total = loops
10 > if opts.get('total', None):
10 > if opts.get('total', None):
11 > total = int(opts.get('total'))
11 > total = int(opts.get('total'))
12 > nested = False
13 > if opts.get('nested', None):
14 > nested = True
12 > loops = abs(loops)
15 > loops = abs(loops)
13 >
16 >
14 > for i in range(loops):
17 > for i in range(loops):
15 > ui.progress('loop', i, 'loop.%d' % i, 'loopnum', total)
18 > ui.progress('loop', i, 'loop.%d' % i, 'loopnum', total)
19 > if opts.get('parallel'):
20 > ui.progress('other', i, 'other.%d' % i, 'othernum', total)
21 > if nested:
22 > for j in range(2):
23 > ui.progress('nested', j, 'nested.%d' % j, 'nestnum', 2)
24 > ui.progress('nested', None, 'nested.done', 'nestnum', 2)
16 > ui.progress('loop', None, 'loop.done', 'loopnum', total)
25 > ui.progress('loop', None, 'loop.done', 'loopnum', total)
17 >
26 >
18 > commands.norepo += " loop"
27 > commands.norepo += " loop"
19 >
28 >
20 > cmdtable = {
29 > cmdtable = {
21 > "loop": (loop, [('', 'total', '', 'override for total')],
30 > "loop": (loop, [('', 'total', '', 'override for total'),
31 > ('', 'nested', False, 'show nested results'),
32 > ('', 'parallel', False, 'show parallel sets of results'),
33 > ],
22 > 'hg loop LOOPS'),
34 > 'hg loop LOOPS'),
23 > }
35 > }
24 > EOF
36 > EOF
25
37
26 $ echo "[extensions]" >> $HGRCPATH
38 $ echo "[extensions]" >> $HGRCPATH
27 $ echo "progress=" >> $HGRCPATH
39 $ echo "progress=" >> $HGRCPATH
28 $ echo "loop=`pwd`/loop.py" >> $HGRCPATH
40 $ echo "loop=`pwd`/loop.py" >> $HGRCPATH
29 $ echo "[progress]" >> $HGRCPATH
41 $ echo "[progress]" >> $HGRCPATH
30 $ echo "format = topic bar number" >> $HGRCPATH
42 $ echo "format = topic bar number" >> $HGRCPATH
31 $ echo "assume-tty=1" >> $HGRCPATH
43 $ echo "assume-tty=1" >> $HGRCPATH
32 $ echo "width=60" >> $HGRCPATH
44 $ echo "width=60" >> $HGRCPATH
33
45
34 test default params, display nothing because of delay
46 test default params, display nothing because of delay
35
47
36 $ hg -y loop 3 2>&1 | $TESTDIR/filtercr.py
48 $ hg -y loop 3 2>&1 | $TESTDIR/filtercr.py
37
49
38 $ echo "delay=0" >> $HGRCPATH
50 $ echo "delay=0" >> $HGRCPATH
39 $ echo "refresh=0" >> $HGRCPATH
51 $ echo "refresh=0" >> $HGRCPATH
40
52
41 test with delay=0, refresh=0
53 test with delay=0, refresh=0
42
54
43 $ hg -y loop 3 2>&1 | $TESTDIR/filtercr.py
55 $ hg -y loop 3 2>&1 | $TESTDIR/filtercr.py
44
56
45 loop [ ] 0/3
57 loop [ ] 0/3
46 loop [===============> ] 1/3
58 loop [===============> ] 1/3
47 loop [===============================> ] 2/3
59 loop [===============================> ] 2/3
48 \r (esc)
60 \r (esc)
49
61
62
63 test nested short-lived topics (which shouldn't display with nestdelay):
64
65 $ hg -y loop 3 --nested 2>&1 | \
66 > python $TESTDIR/filtercr.py
67
68 loop [ ] 0/3
69 loop [===============> ] 1/3
70 loop [===============================> ] 2/3
71 \r (esc)
72
73
74 $ hg --config progress.changedelay=0 -y loop 3 --nested 2>&1 | \
75 > python $TESTDIR/filtercr.py
76
77 loop [ ] 0/3
78 nested [ ] 0/2
79 nested [======================> ] 1/2
80 loop [===============> ] 1/3
81 nested [ ] 0/2
82 nested [======================> ] 1/2
83 loop [===============================> ] 2/3
84 nested [ ] 0/2
85 nested [======================> ] 1/2
86 \r (esc)
87
88
89 test two topics being printed in parallel (as when we're doing a local
90 --pull clone, where you get the unbundle and bundle progress at the
91 same time):
92 $ hg loop 3 --parallel 2>&1 | python $TESTDIR/filtercr.py
93
94 loop [ ] 0/3
95 loop [===============> ] 1/3
96 loop [===============================> ] 2/3
97 \r (esc)
50 test refresh is taken in account
98 test refresh is taken in account
51
99
52 $ hg -y --config progress.refresh=100 loop 3 2>&1 | $TESTDIR/filtercr.py
100 $ hg -y --config progress.refresh=100 loop 3 2>&1 | $TESTDIR/filtercr.py
53
101
54
102
55 test format options 1
103 test format options 1
56
104
57 $ hg -y --config 'progress.format=number topic item+2' loop 2 2>&1 \
105 $ hg -y --config 'progress.format=number topic item+2' loop 2 2>&1 \
58 > | $TESTDIR/filtercr.py
106 > | $TESTDIR/filtercr.py
59
107
60 0/2 loop lo
108 0/2 loop lo
61 1/2 loop lo
109 1/2 loop lo
62 \r (esc)
110 \r (esc)
63
111
64 test format options 2
112 test format options 2
65
113
66 $ hg -y --config 'progress.format=number item-3 bar' loop 2 2>&1 \
114 $ hg -y --config 'progress.format=number item-3 bar' loop 2 2>&1 \
67 > | $TESTDIR/filtercr.py
115 > | $TESTDIR/filtercr.py
68
116
69 0/2 p.0 [ ]
117 0/2 p.0 [ ]
70 1/2 p.1 [=======================> ]
118 1/2 p.1 [=======================> ]
71 \r (esc)
119 \r (esc)
72
120
73 test format options and indeterminate progress
121 test format options and indeterminate progress
74
122
75 $ hg -y --config 'progress.format=number item bar' loop -- -2 2>&1 \
123 $ hg -y --config 'progress.format=number item bar' loop -- -2 2>&1 \
76 > | $TESTDIR/filtercr.py
124 > | $TESTDIR/filtercr.py
77
125
78 0 loop.0 [ <=> ]
126 0 loop.0 [ <=> ]
79 1 loop.1 [ <=> ]
127 1 loop.1 [ <=> ]
80 \r (esc)
128 \r (esc)
81
129
82 make sure things don't fall over if count > total
130 make sure things don't fall over if count > total
83
131
84 $ hg -y loop --total 4 6 2>&1 | $TESTDIR/filtercr.py
132 $ hg -y loop --total 4 6 2>&1 | $TESTDIR/filtercr.py
85
133
86 loop [ ] 0/4
134 loop [ ] 0/4
87 loop [===========> ] 1/4
135 loop [===========> ] 1/4
88 loop [=======================> ] 2/4
136 loop [=======================> ] 2/4
89 loop [===================================> ] 3/4
137 loop [===================================> ] 3/4
90 loop [===============================================>] 4/4
138 loop [===============================================>] 4/4
91 loop [ <=> ] 5/4
139 loop [ <=> ] 5/4
92 \r (esc)
140 \r (esc)
93
141
94 test immediate progress completion
142 test immediate progress completion
95
143
96 $ hg -y loop 0 2>&1 | $TESTDIR/filtercr.py
144 $ hg -y loop 0 2>&1 | $TESTDIR/filtercr.py
97
145
98
146
99 test delay time estimates
147 test delay time estimates
100
148
101 $ cat > mocktime.py <<EOF
149 $ cat > mocktime.py <<EOF
102 > import os
150 > import os
103 > import time
151 > import time
104 >
152 >
105 > class mocktime(object):
153 > class mocktime(object):
106 > def __init__(self, increment):
154 > def __init__(self, increment):
107 > self.time = 0
155 > self.time = 0
108 > self.increment = increment
156 > self.increment = increment
109 > def __call__(self):
157 > def __call__(self):
110 > self.time += self.increment
158 > self.time += self.increment
111 > return self.time
159 > return self.time
112 >
160 >
113 > def uisetup(ui):
161 > def uisetup(ui):
114 > time.time = mocktime(int(os.environ.get('MOCKTIME', '11')))
162 > time.time = mocktime(int(os.environ.get('MOCKTIME', '11')))
115 > EOF
163 > EOF
116
164
117 $ echo "[extensions]" > $HGRCPATH
165 $ echo "[extensions]" > $HGRCPATH
118 $ echo "mocktime=`pwd`/mocktime.py" >> $HGRCPATH
166 $ echo "mocktime=`pwd`/mocktime.py" >> $HGRCPATH
119 $ echo "progress=" >> $HGRCPATH
167 $ echo "progress=" >> $HGRCPATH
120 $ echo "loop=`pwd`/loop.py" >> $HGRCPATH
168 $ echo "loop=`pwd`/loop.py" >> $HGRCPATH
121 $ echo "[progress]" >> $HGRCPATH
169 $ echo "[progress]" >> $HGRCPATH
122 $ echo "assume-tty=1" >> $HGRCPATH
170 $ echo "assume-tty=1" >> $HGRCPATH
123 $ echo "delay=25" >> $HGRCPATH
171 $ echo "delay=25" >> $HGRCPATH
124 $ echo "width=60" >> $HGRCPATH
172 $ echo "width=60" >> $HGRCPATH
125
173
126 $ hg -y loop 8 2>&1 | python $TESTDIR/filtercr.py
174 $ hg -y loop 8 2>&1 | python $TESTDIR/filtercr.py
127
175
128 loop [=========> ] 2/8 1m07s
176 loop [=========> ] 2/8 1m07s
129 loop [===============> ] 3/8 56s
177 loop [===============> ] 3/8 56s
130 loop [=====================> ] 4/8 45s
178 loop [=====================> ] 4/8 45s
131 loop [==========================> ] 5/8 34s
179 loop [==========================> ] 5/8 34s
132 loop [================================> ] 6/8 23s
180 loop [================================> ] 6/8 23s
133 loop [=====================================> ] 7/8 12s
181 loop [=====================================> ] 7/8 12s
134 \r (esc)
182 \r (esc)
135
183
136 $ MOCKTIME=10000 hg -y loop 4 2>&1 | python $TESTDIR/filtercr.py
184 $ MOCKTIME=10000 hg -y loop 4 2>&1 | python $TESTDIR/filtercr.py
137
185
138 loop [ ] 0/4
186 loop [ ] 0/4
139 loop [=========> ] 1/4 8h21m
187 loop [=========> ] 1/4 8h21m
140 loop [====================> ] 2/4 5h34m
188 loop [====================> ] 2/4 5h34m
141 loop [==============================> ] 3/4 2h47m
189 loop [==============================> ] 3/4 2h47m
142 \r (esc)
190 \r (esc)
143
191
144 $ MOCKTIME=1000000 hg -y loop 4 2>&1 | python $TESTDIR/filtercr.py
192 $ MOCKTIME=1000000 hg -y loop 4 2>&1 | python $TESTDIR/filtercr.py
145
193
146 loop [ ] 0/4
194 loop [ ] 0/4
147 loop [=========> ] 1/4 5w00d
195 loop [=========> ] 1/4 5w00d
148 loop [====================> ] 2/4 3w03d
196 loop [====================> ] 2/4 3w03d
149 loop [=============================> ] 3/4 11d14h
197 loop [=============================> ] 3/4 11d14h
150 \r (esc)
198 \r (esc)
151
199
152
200
153 $ MOCKTIME=14000000 hg -y loop 4 2>&1 | python $TESTDIR/filtercr.py
201 $ MOCKTIME=14000000 hg -y loop 4 2>&1 | python $TESTDIR/filtercr.py
154
202
155 loop [ ] 0/4
203 loop [ ] 0/4
156 loop [=========> ] 1/4 1y18w
204 loop [=========> ] 1/4 1y18w
157 loop [===================> ] 2/4 46w03d
205 loop [===================> ] 2/4 46w03d
158 loop [=============================> ] 3/4 23w02d
206 loop [=============================> ] 3/4 23w02d
159 \r (esc)
207 \r (esc)
160
208
161 Time estimates should not fail when there's no end point:
209 Time estimates should not fail when there's no end point:
162 $ hg -y loop -- -4 2>&1 | python $TESTDIR/filtercr.py
210 $ hg -y loop -- -4 2>&1 | python $TESTDIR/filtercr.py
163
211
164 loop [ <=> ] 2
212 loop [ <=> ] 2
165 loop [ <=> ] 3
213 loop [ <=> ] 3
166 \r (esc)
214 \r (esc)
General Comments 0
You need to be logged in to leave comments. Login now