##// END OF EJS Templates
hgweb: do not ignore [auth] if url has a username (issue2822)...
hgweb: do not ignore [auth] if url has a username (issue2822) The [auth] section was ignored when handling URLs like: http://user@example.com/foo Instead, we look in [auth] for an entry matching the URL and supplied user name. Entries without username can match URL with a username. Prefix length ties are resolved in favor of entries matching the username. With: foo.prefix = http://example.org foo.username = user foo.password = password bar.prefix = http://example.org/bar and the input URL: http://user@example.org/bar the 'bar' entry will be selected because of prefix length, therefore prompting for a password. This behaviour ensure that entries selection is consistent when looking for credentials or for certificates, and that certificates can be picked even if their entries do no define usernames while the URL does. Additionally, entries without a username matched against a username are returned as if they did have requested username set to avoid prompting again for a username if the password is not set. v2: reparse the URL in readauthforuri() to handle HTTP and HTTPS similarly. v3: allow unset usernames to match URL usernames to pick certificates. Resolve prefix length ties in favor of entries with usernames.

File last commit:

r14838:5d261fd0 default
r15005:4a43e23b 1.9.1 stable
Show More
progress.py
284 lines | 10.2 KiB | text/x-python | PythonLexer
# progress.py show progress bars for some actions
#
# Copyright (C) 2010 Augie Fackler <durin42@gmail.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""show progress bars for some actions
This extension uses the progress information logged by hg commands
to draw progress bars that are as informative as possible. Some progress
bars only offer indeterminate information, while others have a definite
end point.
The following settings are available::
[progress]
delay = 3 # number of seconds (float) before showing the progress bar
refresh = 0.1 # time in seconds between refreshes of the progress bar
format = topic bar number estimate # format of the progress bar
width = <none> # if set, the maximum width of the progress information
# (that is, min(width, term width) will be used)
clear-complete = True # clear the progress bar after it's done
disable = False # if true, don't show a progress bar
assume-tty = False # if true, ALWAYS show a progress bar, unless
# disable is given
Valid entries for the format field are topic, bar, number, unit,
estimate, speed, and item. item defaults to the last 20 characters of
the item, but this can be changed by adding either ``-<num>`` which
would take the last num characters, or ``+<num>`` for the first num
characters.
"""
import sys
import time
from mercurial import util
from mercurial.i18n import _
def spacejoin(*args):
return ' '.join(s for s in args if s)
def shouldprint(ui):
return (util.isatty(sys.stderr) or ui.configbool('progress', 'assume-tty'))
def fmtremaining(seconds):
if seconds < 60:
# i18n: format XX seconds as "XXs"
return _("%02ds") % (seconds)
minutes = seconds // 60
if minutes < 60:
seconds -= minutes * 60
# i18n: format X minutes and YY seconds as "XmYYs"
return _("%dm%02ds") % (minutes, seconds)
# we're going to ignore seconds in this case
minutes += 1
hours = minutes // 60
minutes -= hours * 60
if hours < 30:
# i18n: format X hours and YY minutes as "XhYYm"
return _("%dh%02dm") % (hours, minutes)
# we're going to ignore minutes in this case
hours += 1
days = hours // 24
hours -= days * 24
if days < 15:
# i18n: format X days and YY hours as "XdYYh"
return _("%dd%02dh") % (days, hours)
# we're going to ignore hours in this case
days += 1
weeks = days // 7
days -= weeks * 7
if weeks < 55:
# i18n: format X weeks and YY days as "XwYYd"
return _("%dw%02dd") % (weeks, days)
# we're going to ignore days and treat a year as 52 weeks
weeks += 1
years = weeks // 52
weeks -= years * 52
# i18n: format X years and YY weeks as "XyYYw"
return _("%dy%02dw") % (years, weeks)
class progbar(object):
def __init__(self, ui):
self.ui = ui
self.resetstate()
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))
self.indetcount = 0
self.refresh = float(self.ui.config(
'progress', 'refresh', default=0.1))
self.order = self.ui.configlist(
'progress', 'format',
default=['topic', 'bar', 'number', 'estimate'])
def show(self, now, topic, pos, item, unit, total):
if not shouldprint(self.ui):
return
termwidth = self.width()
self.printed = True
head = ''
needprogress = False
tail = ''
for indicator in self.order:
add = ''
if indicator == 'topic':
add = topic
elif indicator == 'number':
if total:
add = ('% ' + str(len(str(total))) +
's/%s') % (pos, total)
else:
add = str(pos)
elif indicator.startswith('item') and item:
slice = 'end'
if '-' in indicator:
wid = int(indicator.split('-')[1])
elif '+' in indicator:
slice = 'beginning'
wid = int(indicator.split('+')[1])
else:
wid = 20
if slice == 'end':
add = item[-wid:]
else:
add = item[:wid]
add += (wid - len(add)) * ' '
elif indicator == 'bar':
add = ''
needprogress = True
elif indicator == 'unit' and unit:
add = unit
elif indicator == 'estimate':
add = self.estimate(topic, pos, total, now)
elif indicator == 'speed':
add = self.speed(topic, pos, unit, now)
if not needprogress:
head = spacejoin(head, add)
else:
tail = spacejoin(tail, add)
if needprogress:
used = 0
if head:
used += len(head) + 1
if tail:
used += len(tail) + 1
progwidth = termwidth - used - 3
if total and pos <= total:
amt = pos * progwidth // total
bar = '=' * (amt - 1)
if amt > 0:
bar += '>'
bar += ' ' * (progwidth - amt)
else:
progwidth -= 3
self.indetcount += 1
# mod the count by twice the width so we can make the
# cursor bounce between the right and left sides
amt = self.indetcount % (2 * progwidth)
amt -= progwidth
bar = (' ' * int(progwidth - abs(amt)) + '<=>' +
' ' * int(abs(amt)))
prog = ''.join(('[', bar , ']'))
out = spacejoin(head, prog, tail)
else:
out = spacejoin(head, tail)
sys.stderr.write('\r' + out[:termwidth])
sys.stderr.flush()
def clear(self):
if not shouldprint(self.ui):
return
sys.stderr.write('\r%s\r' % (' ' * self.width()))
def complete(self):
if not shouldprint(self.ui):
return
if self.ui.configbool('progress', 'clear-complete', default=True):
self.clear()
else:
sys.stderr.write('\n')
sys.stderr.flush()
def width(self):
tw = self.ui.termwidth()
return min(int(self.ui.config('progress', 'width', default=tw)), tw)
def estimate(self, topic, pos, total, now):
if total is None:
return ''
initialpos = self.startvals[topic]
target = total - initialpos
delta = pos - initialpos
if delta > 0:
elapsed = now - self.starttimes[topic]
if elapsed > float(
self.ui.config('progress', 'estimate', default=2)):
seconds = (elapsed * (target - delta)) // delta + 1
return fmtremaining(seconds)
return ''
def speed(self, topic, pos, unit, now):
initialpos = self.startvals[topic]
delta = pos - initialpos
elapsed = now - self.starttimes[topic]
if elapsed > float(
self.ui.config('progress', 'estimate', default=2)):
return _('%d %s/sec') % (delta / elapsed, unit)
return ''
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:
self.complete()
self.resetstate()
# truncate the list of topics assuming all topics within
# this one are also closed
if topic in self.topics:
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)
self.topicstates[topic] = pos, item, unit, total
if now - self.lastprint >= self.refresh and self.topics:
self.lastprint = now
self.show(now, topic, *self.topicstates[topic])
def uisetup(ui):
class progressui(ui.__class__):
_progbar = None
def progress(self, *args, **opts):
self._progbar.progress(*args, **opts)
return super(progressui, self).progress(*args, **opts)
def write(self, *args, **opts):
if self._progbar.printed:
self._progbar.clear()
return super(progressui, self).write(*args, **opts)
def write_err(self, *args, **opts):
if self._progbar.printed:
self._progbar.clear()
return super(progressui, self).write_err(*args, **opts)
# Apps that derive a class from ui.ui() can use
# setconfig('progress', 'disable', 'True') to disable this extension
if ui.configbool('progress', 'disable'):
return
if shouldprint(ui) and not ui.debugflag and not ui.quiet:
ui.__class__ = progressui
# we instantiate one globally shared progress bar to avoid
# competing progress bars when multiple UI objects get created
if not progressui._progbar:
progressui._progbar = progbar(ui)
def reposetup(ui, repo):
uisetup(repo.ui)