##// END OF EJS Templates
pytype: use "$(hg root)" instead of `hg root` to make shellcheck happier
pytype: use "$(hg root)" instead of `hg root` to make shellcheck happier

File last commit:

r52179:81224afd default
r52199:46280260 default
Show More
statichttprepo.py
271 lines | 8.0 KiB | text/x-python | PythonLexer
mpm@selenic.com
Separate out old-http support...
r1101 # statichttprepo.py - simple http repository class for mercurial
#
# This provides read-only repo access to repositories exported via static http
#
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
mpm@selenic.com
Separate out old-http support...
r1101 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
mpm@selenic.com
Separate out old-http support...
r1101
Gregory Szorc
statichttprepo: use absolute_import
r25978
import errno
from .i18n import _
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 from .node import sha1nodeconstants
Gregory Szorc
statichttprepo: use absolute_import
r25978 from . import (
Martijn Pieters
branchmap: encapsulate cache updating in the map itself...
r41764 branchmap,
Gregory Szorc
statichttprepo: use absolute_import
r25978 changelog,
error,
localrepo,
manifest,
namespaces,
Yuya Nishihara
statichttprepo: do not use platform path separator to build a URL...
r34944 pathutil,
Gregory Szorc
statichttprepo: use str to appease Python 3...
r41452 pycompat,
share-safe: add support for static-http repository...
r49514 requirements as requirementsmod,
Gregory Szorc
statichttprepo: use absolute_import
r25978 url,
util,
Pierre-Yves David
vfs: use 'vfs' module directly in 'mercurial.statichttprepo'...
r31241 vfs as vfsmod,
Gregory Szorc
statichttprepo: use absolute_import
r25978 )
urlutil: extract `url` related code from `util` into the new module...
r47669 from .utils import (
urlutil,
)
Bryan O'Sullivan
Move urllib error handling from revlog into statichttprepo, where it belongs.
r1325
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 urlerr = util.urlerr
urlreq = util.urlreq
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class httprangereader:
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274 def __init__(self, url, opener):
# we assume opener has HTTPRangeHandler
self.url = url
self.pos = 0
self.opener = opener
Nicolas Dumazet
static-http: mimic more closely localrepo (issue2164: allow clone -r )...
r11066 self.name = url
Gregory Szorc
statichttprepo: implement __enter__ and __exit__ on httprangeheader...
r27705
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274 def seek(self, pos):
self.pos = pos
Augie Fackler
formatting: blacken the codebase...
r43346
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274 def read(self, bytes=None):
Gregory Szorc
statichttprepo: use str to appease Python 3...
r41452 req = urlreq.request(pycompat.strurl(self.url))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 end = b''
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274 if bytes:
end = self.pos + bytes - 1
Alexander Boyd
statichttprepo: don't send Range header when requesting entire file...
r16882 if self.pos or end:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 req.add_header('Range', 'bytes=%d-%s' % (self.pos, end))
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274
Bryan O'Sullivan
Move urllib error handling from revlog into statichttprepo, where it belongs.
r1325 try:
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274 f = self.opener.open(req)
data = f.read()
Augie Fackler
statichttprepo: remove wrong getattr ladder...
r25196 code = f.code
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 except urlerr.httperror as inst:
Dirkjan Ochtman
make static-http work with empty repos (issue965)
r6028 num = inst.code == 404 and errno.ENOENT or None
Joerg Sonnenberger
statichttprepo: explicitly convert error message to str (issue6247)...
r46818 # Explicitly convert the exception to str as Py3 will try
# convert it to local encoding and with as the HTTPResponse
# instance doesn't support encode.
raise IOError(num, str(inst))
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 except urlerr.urlerror as inst:
Gregory Szorc
statichttprepo: use URLError.reason directly...
r41451 raise IOError(None, inst.reason)
mpm@selenic.com
Separate out old-http support...
r1101
Patrick Mezard
statichttprepo: handle remote not supporting Range headers...
r8612 if code == 200:
# HTTPRangeHandler does nothing if remote does not support
# Range headers and returns the full entity. Let's slice it.
if bytes:
Augie Fackler
formatting: blacken the codebase...
r43346 data = data[self.pos : self.pos + bytes]
Patrick Mezard
statichttprepo: handle remote not supporting Range headers...
r8612 else:
Augie Fackler
formatting: blacken the codebase...
r43346 data = data[self.pos :]
Patrick Mezard
statichttprepo: handle remote not supporting Range headers...
r8612 elif bytes:
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274 data = data[:bytes]
Patrick Mezard
statichttprepo: handle remote not supporting Range headers...
r8612 self.pos += len(data)
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274 return data
Augie Fackler
formatting: blacken the codebase...
r43346
Siddharth Agarwal
statichttprepo.httprangeheader: implement readlines...
r20055 def readlines(self):
return self.read().splitlines(True)
Augie Fackler
formatting: blacken the codebase...
r43346
Nicolas Dumazet
static-http: mimic more closely localrepo (issue2164: allow clone -r )...
r11066 def __iter__(self):
Siddharth Agarwal
statichttprepo.httprangeheader: implement readlines...
r20055 return iter(self.readlines())
Augie Fackler
formatting: blacken the codebase...
r43346
Nicolas Dumazet
static-http: mimic more closely localrepo (issue2164: allow clone -r )...
r11066 def close(self):
pass
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
statichttprepo: move HTTPRangeHandler from byterange and delete the latter...
r36443 # _RangeError and _HTTPRangeHandler were originally in byterange.py,
# which was itself extracted from urlgrabber. See the last version of
# byterange.py from history if you need more information.
class _RangeError(IOError):
"""Error raised when an unsatisfiable range is requested."""
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
statichttprepo: move HTTPRangeHandler from byterange and delete the latter...
r36443 class _HTTPRangeHandler(urlreq.basehandler):
"""Handler that enables HTTP Range headers.
This was extremely simple. The Range header is a HTTP feature to
begin with so all this class does is tell urllib2 that the
"206 Partial Content" response from the HTTP server is what we
expected.
"""
def http_error_206(self, req, fp, code, msg, hdrs):
# 206 Partial Content Response
r = urlreq.addinfourl(fp, hdrs, req.get_full_url())
r.code = code
r.msg = msg
return r
def http_error_416(self, req, fp, code, msg, hdrs):
# HTTP's Range Not Satisfiable error
Matt Harbison
statichttprepo: unbyteify several IOError messages...
r51174 raise _RangeError('Requested Range Not Satisfiable')
Augie Fackler
statichttprepo: move HTTPRangeHandler from byterange and delete the latter...
r36443
Augie Fackler
formatting: blacken the codebase...
r43346
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274 def build_opener(ui, authinfo):
# urllib cannot handle URLs with embedded user or passwd
urlopener = url.opener(ui, authinfo)
Augie Fackler
statichttprepo: move HTTPRangeHandler from byterange and delete the latter...
r36443 urlopener.add_handler(_HTTPRangeHandler())
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274
Pierre-Yves David
vfs: use 'vfs' module directly in 'mercurial.statichttprepo'...
r31241 class statichttpvfs(vfsmod.abstractvfs):
Dan Villiom Podlaski Christiansen
statichttprepo: make the opener a subclass of abstractopener
r14091 def __init__(self, base):
self.base = base
vfs: give all vfs an options attribute by default...
r43295 self.options = {}
Dan Villiom Podlaski Christiansen
statichttprepo: make the opener a subclass of abstractopener
r14091
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def __call__(self, path, mode=b'r', *args, **kw):
if mode not in (b'r', b'rb'):
Matt Harbison
statichttprepo: unbyteify several IOError messages...
r51174 raise IOError('Permission denied')
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = b"/".join((self.base, urlreq.quote(path)))
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274 return httprangereader(f, urlopener)
Matt Harbison
statichttprepo: fix the vfs.join() method to match the base class definition...
r51173 def join(self, path, *insidef):
FUJIWARA Katsunori
vfs: define "join()" in each classes derived from "abstractvfs"...
r17725 if path:
Matt Harbison
statichttprepo: fix the vfs.join() method to match the base class definition...
r51173 return pathutil.join(self.base, path, *insidef)
FUJIWARA Katsunori
vfs: define "join()" in each classes derived from "abstractvfs"...
r17725 else:
return self.base
FUJIWARA Katsunori
scmutil: rename classes from "opener" to "vfs"...
r17649 return statichttpvfs
mpm@selenic.com
Separate out old-http support...
r1101
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 class statichttppeer(localrepo.localpeer):
def local(self):
return None
Augie Fackler
formatting: blacken the codebase...
r43346
Sune Foldager
peer: introduce canpush and improve error message
r17193 def canpush(self):
return False
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Augie Fackler
formatting: blacken the codebase...
r43346
class statichttprepository(
localrepo.localrepository, localrepo.revlogfilestorage
):
FUJIWARA Katsunori
localrepo: make supported features manageable in each repositories individually...
r19778 supported = localrepo.localrepository._basesupported
mpm@selenic.com
Separate out old-http support...
r1101 def __init__(self, ui, path):
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673 self._url = path
mpm@selenic.com
Separate out old-http support...
r1101 self.ui = ui
Benoit Boissinot
switch to the .hg/store layout, fix the tests
r3853
Nicolas Dumazet
static-http: mimic more closely localrepo (issue2164: allow clone -r )...
r11066 self.root = path
urlutil: extract `url` related code from `util` into the new module...
r47669 u = urlutil.url(path.rstrip(b'/') + b"/.hg")
Brodie Rao
httprepo/sshrepo: use url.url...
r13819 self.path, authinfo = u.authinfo()
Benoit Boissinot
statichttprepo: cleanups, use url.py (proxy, password support)...
r7274
Pierre-Yves David
statichttp: use 'repo.vfs' as the main attribute...
r31147 vfsclass = build_opener(ui, authinfo)
self.vfs = vfsclass(self.path)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.cachevfs = vfsclass(self.vfs.join(b'cache'))
Pierre-Yves David
phases: mechanism to allow extension to alter initial computation of phase...
r15922 self._phasedefaults = []
Dirkjan Ochtman
make static-http work with empty repos (issue965)
r6028
Ryan McElroy
namespaces: remove weakref; always pass in repo...
r23561 self.names = namespaces.namespaces()
Gregory Szorc
localrepo: move filtername to __init__...
r32730 self.filtername = None
repoview: introduce a `experimental.extra-filter-revs` config...
r42417 self._extrafilterid = None
Raphaël Gomès
sidedata-exchange: add `wanted_sidedata` and `sidedata_computers` to repos...
r47447 self._wanted_sidedata = set()
statichttp: add the missing `features` attribute...
r47999 self.features = set()
Sean Farley
namespaces: add bookmarks to the names data structure...
r23558
Benoit Boissinot
add "requires" file to the repo, specifying the requirements
r3851 try:
Gregory Szorc
statichttprepo: use new functions for requirements validation...
r39730 requirements = set(self.vfs.read(b'requires').splitlines())
Manuel Jacob
py3: catch FileNotFoundError instead of checking errno == ENOENT
r50201 except FileNotFoundError:
Adrian Buehlmann
introduce new function scmutil.readrequires...
r14482 requirements = set()
Thomas Arendsen Hein
Fix Debian bug #494889 (fetching from static-http://... broken)...
r7178 # check if it is a non-empty old-style repository
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fp = self.vfs(b"00changelog.i")
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 fp.read(1)
fp.close()
Manuel Jacob
py3: catch FileNotFoundError instead of checking errno == ENOENT
r50201 except FileNotFoundError:
Thomas Arendsen Hein
Fix Debian bug #494889 (fetching from static-http://... broken)...
r7178 # we do not care about empty old-style repositories here
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b"'%s' does not appear to be an hg repository") % path
Matt Mackall
error: move repo errors...
r7637 raise error.RepoError(msg)
share-safe: add support for static-http repository...
r49514 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
storevfs = vfsclass(self.vfs.join(b'store'))
requirements |= set(storevfs.read(b'requires').splitlines())
Benoit Boissinot
add "requires" file to the repo, specifying the requirements
r3851
Gregory Szorc
statichttprepo: use new functions for requirements validation...
r39730 supportedrequirements = localrepo.gathersupportedrequirements(ui)
Augie Fackler
formatting: blacken the codebase...
r43346 localrepo.ensurerequirementsrecognized(
requirements, supportedrequirements
)
Gregory Szorc
localrepo: move requirements reasonability testing to own function...
r39731 localrepo.ensurerequirementscompatible(ui, requirements)
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 self.nodeconstants = sha1nodeconstants
self.nullid = self.nodeconstants.nullid
Gregory Szorc
statichttprepo: use new functions for requirements validation...
r39730
Benoit Boissinot
add "requires" file to the repo, specifying the requirements
r3851 # setup store
Gregory Szorc
localrepo: move store() from store module...
r39734 self.store = localrepo.makestore(requirements, self.path, vfsclass)
Matt Mackall
statichttp: use store class...
r6897 self.spath = self.store.path
Angel Ezquerra
localrepo: remove all external users of localrepo.sopener...
r23878 self.svfs = self.store.opener
Matt Mackall
statichttp: use store class...
r6897 self.sjoin = self.store.join
Idan Kamara
scmutil: update cached copy when filecached attribute is assigned (issue3263)...
r16115 self._filecache = {}
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 self.requirements = requirements
Benoit Boissinot
add "requires" file to the repo, specifying the requirements
r3851
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 rootmanifest = manifest.manifestrevlog(self.nodeconstants, self.svfs)
Augie Fackler
formatting: blacken the codebase...
r43346 self.manifestlog = manifest.manifestlog(
self.svfs, self, rootmanifest, self.narrowmatch()
)
Angel Ezquerra
localrepo: remove all external users of localrepo.sopener...
r23878 self.changelog = changelog.changelog(self.svfs)
Greg Ward
localrepo: rename in-memory tag cache instance attributes (issue548)....
r9146 self._tags = None
mpm@selenic.com
Separate out old-http support...
r1101 self.nodetagscache = None
Martijn Pieters
branchmap: encapsulate cache updating in the map itself...
r41764 self._branchcaches = branchmap.BranchMapCache()
Durham Goode
revbranchcache: move out of branchmap onto localrepo...
r24373 self._revbranchcache = None
Benoit Boissinot
cleanup of revlog.group when repository is local...
r1598 self.encodepats = None
self.decodepats = None
Durham Goode
revbranchcache: move cache writing to the transaction finalizer...
r24377 self._transref = None
dirstate: only reload the dirstate when it may have changed...
r51023 self._dirstate = None
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
def _restrictcapabilities(self, caps):
Pierre-Yves David
statichttp: respect localrepo _restrictcapabilities...
r20962 caps = super(statichttprepository, self)._restrictcapabilities(caps)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return caps.difference([b"pushkey"])
mpm@selenic.com
Separate out old-http support...
r1101
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673 def url(self):
Matt Mackall
Autodetect static-http
r7211 return self._url
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673
mpm@selenic.com
Separate out old-http support...
r1101 def local(self):
return False
Vadim Gelfer
clean up hg.py: move repo constructor code into each repo module
r2740
Manuel Jacob
pull: add --remote-hidden option and pass it through peer creation...
r51309 def peer(self, path=None, remotehidden=False):
return statichttppeer(self, path=path, remotehidden=remotehidden)
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Gregory Szorc
statichttprepo: implement wlock() (issue5613)...
r33605 def wlock(self, wait=True):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.LockUnavailable(
0,
lock: properly convert error to bytes...
r52179 pycompat.sysstr(_(b'lock not available')),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'lock',
_(b'cannot lock static-http repository'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
statichttprepo: implement wlock() (issue5613)...
r33605
Martin Geisler
do not pretend to lock static-http repositories (issue994)
r7005 def lock(self, wait=True):
Pulkit Goyal
statichttprepo: use LockUnavailable() instead of Abort() for lock (API)...
r46004 raise error.LockUnavailable(
0,
lock: properly convert error to bytes...
r52179 pycompat.sysstr(_(b'lock not available')),
Pulkit Goyal
statichttprepo: use LockUnavailable() instead of Abort() for lock (API)...
r46004 b'lock',
_(b'cannot lock static-http repository'),
)
Martin Geisler
do not pretend to lock static-http repositories (issue994)
r7005
Pierre-Yves David
statichttprepo: do not try to write caches...
r29738 def _writecaches(self):
Augie Fackler
formatting: blacken the codebase...
r43346 pass # statichttprepository are read only
Pierre-Yves David
statichttprepo: do not try to write caches...
r29738
Manuel Jacob
pull: add --remote-hidden option and pass it through peer creation...
r51309 def make_peer(
ui, path, create, intents=None, createopts=None, remotehidden=False
):
Vadim Gelfer
clean up hg.py: move repo constructor code into each repo module
r2740 if create:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'cannot create new static-http repository'))
peer: pass the `path` to the statichttp peer...
r50657 url = path.loc[7:]
Manuel Jacob
pull: add --remote-hidden option and pass it through peer creation...
r51309 return statichttprepository(ui, url).peer(
path=path, remotehidden=remotehidden
)