##// END OF EJS Templates
shelve: stop passing list of files to revert...
shelve: stop passing list of files to revert It seems to work just fine to not specify any files here. I suspect it looked the way it did for historical reasons. It apparently used to use merge instead of rebase until 1d7a36ff2615 (shelve: use rebase instead of merge (issue4068), 2013-10-23) and it makes sense to want to restrict the set of files then. I noticed this because of the files.extend(shelvectx.p1().files()). If the working copy was clean before, then shelvectx.p1() will be the working copy parent and that ended up adding all the files in that set. In our Google-internal Mercurial setup (including a FUSE) that was very noticeably slow when the working copy parent happened to have many files in large directories. This patch doesn't yet remove the call to shelvectx.p1().files(). We also use that set for deciding what to back up. I'm pretty sure it's safe to back up only the set of files we already back even if we no longer restrict the set of files to revert, so this patch should be safe on its own. Regardless, the next patch will delegate the backing-up to cmdutil.revert(). Incidentally, this also gets rid of a repo.pathto() that I had earlier wanted to get rid of. Differential Revision: https://phab.mercurial-scm.org/D6173

File last commit:

r39851:c31ce080 default
r42204:46065855 default
Show More
factotum.py
151 lines | 4.8 KiB | text/x-python | PythonLexer
# factotum.py - Plan 9 factotum integration for Mercurial
#
# Copyright (C) 2012 Steven Stallion <sstallion@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.
'''http authentication with factotum
This extension allows the factotum(4) facility on Plan 9 from Bell Labs
platforms to provide authentication information for HTTP access. Configuration
entries specified in the auth section as well as authentication information
provided in the repository URL are fully supported. If no prefix is specified,
a value of "*" will be assumed.
By default, keys are specified as::
proto=pass service=hg prefix=<prefix> user=<username> !password=<password>
If the factotum extension is unable to read the required key, one will be
requested interactively.
A configuration section is available to customize runtime behavior. By
default, these entries are::
[factotum]
executable = /bin/auth/factotum
mountpoint = /mnt/factotum
service = hg
The executable entry defines the full path to the factotum binary. The
mountpoint entry defines the path to the factotum file service. Lastly, the
service entry controls the service name used when reading keys.
'''
from __future__ import absolute_import
import os
from mercurial.i18n import _
from mercurial.utils import (
procutil,
)
from mercurial import (
error,
httpconnection,
registrar,
url,
util,
)
urlreq = util.urlreq
passwordmgr = url.passwordmgr
ERRMAX = 128
_executable = _mountpoint = _service = None
configtable = {}
configitem = registrar.configitem(configtable)
configitem('factotum', 'executable',
default='/bin/auth/factotum',
)
configitem('factotum', 'mountpoint',
default='/mnt/factotum',
)
configitem('factotum', 'service',
default='hg',
)
def auth_getkey(self, params):
if not self.ui.interactive():
raise error.Abort(_('factotum not interactive'))
if 'user=' not in params:
params = '%s user?' % params
params = '%s !password?' % params
os.system(procutil.tonativestr("%s -g '%s'" % (_executable, params)))
def auth_getuserpasswd(self, getkey, params):
params = 'proto=pass %s' % params
while True:
fd = os.open('%s/rpc' % _mountpoint, os.O_RDWR)
try:
os.write(fd, 'start %s' % params)
l = os.read(fd, ERRMAX).split()
if l[0] == 'ok':
os.write(fd, 'read')
status, user, passwd = os.read(fd, ERRMAX).split(None, 2)
if status == 'ok':
if passwd.startswith("'"):
if passwd.endswith("'"):
passwd = passwd[1:-1].replace("''", "'")
else:
raise error.Abort(_('malformed password string'))
return (user, passwd)
except (OSError, IOError):
raise error.Abort(_('factotum not responding'))
finally:
os.close(fd)
getkey(self, params)
def monkeypatch_method(cls):
def decorator(func):
setattr(cls, func.__name__, func)
return func
return decorator
@monkeypatch_method(passwordmgr)
def find_user_password(self, realm, authuri):
user, passwd = self.passwddb.find_user_password(realm, authuri)
if user and passwd:
self._writedebug(user, passwd)
return (user, passwd)
prefix = ''
res = httpconnection.readauthforuri(self.ui, authuri, user)
if res:
_, auth = res
prefix = auth.get('prefix')
user, passwd = auth.get('username'), auth.get('password')
if not user or not passwd:
if not prefix:
prefix = realm.split(' ')[0].lower()
params = 'service=%s prefix=%s' % (_service, prefix)
if user:
params = '%s user=%s' % (params, user)
user, passwd = auth_getuserpasswd(self, auth_getkey, params)
self.add_password(realm, authuri, user, passwd)
self._writedebug(user, passwd)
return (user, passwd)
def uisetup(ui):
global _executable
_executable = ui.config('factotum', 'executable')
global _mountpoint
_mountpoint = ui.config('factotum', 'mountpoint')
global _service
_service = ui.config('factotum', 'service')