statichttprepo.py
117 lines
| 3.7 KiB
| text/x-python
|
PythonLexer
/ mercurial / statichttprepo.py
mpm@selenic.com
|
r1101 | # statichttprepo.py - simple http repository class for mercurial | ||
# | ||||
# This provides read-only repo access to repositories exported via static http | ||||
# | ||||
Thomas Arendsen Hein
|
r4635 | # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> | ||
mpm@selenic.com
|
r1101 | # | ||
# This software may be used and distributed according to the terms | ||||
# of the GNU General Public License, incorporated herein by reference. | ||||
Matt Mackall
|
r3891 | from i18n import _ | ||
Benoit Boissinot
|
r7274 | import changelog, byterange, url | ||
Adrian Buehlmann
|
r6839 | import repo, localrepo, manifest, util, store | ||
Dirkjan Ochtman
|
r6028 | import urllib, urllib2, errno | ||
Bryan O'Sullivan
|
r1325 | |||
Benoit Boissinot
|
r7274 | class httprangereader(object): | ||
def __init__(self, url, opener): | ||||
# we assume opener has HTTPRangeHandler | ||||
self.url = url | ||||
self.pos = 0 | ||||
self.opener = opener | ||||
def seek(self, pos): | ||||
self.pos = pos | ||||
def read(self, bytes=None): | ||||
req = urllib2.Request(self.url) | ||||
end = '' | ||||
if bytes: | ||||
end = self.pos + bytes - 1 | ||||
req.add_header('Range', 'bytes=%d-%s' % (self.pos, end)) | ||||
Bryan O'Sullivan
|
r1325 | try: | ||
Benoit Boissinot
|
r7274 | f = self.opener.open(req) | ||
data = f.read() | ||||
Thomas Arendsen Hein
|
r1821 | except urllib2.HTTPError, inst: | ||
Dirkjan Ochtman
|
r6028 | num = inst.code == 404 and errno.ENOENT or None | ||
raise IOError(num, inst) | ||||
Bryan O'Sullivan
|
r1325 | except urllib2.URLError, inst: | ||
Thomas Arendsen Hein
|
r1821 | raise IOError(None, inst.reason[1]) | ||
mpm@selenic.com
|
r1101 | |||
Benoit Boissinot
|
r7274 | if bytes: | ||
data = data[:bytes] | ||||
return data | ||||
def build_opener(ui, authinfo): | ||||
# urllib cannot handle URLs with embedded user or passwd | ||||
urlopener = url.opener(ui, authinfo) | ||||
urlopener.add_handler(byterange.HTTPRangeHandler()) | ||||
def opener(base): | ||||
"""return a function that opens files over http""" | ||||
p = base | ||||
def o(path, mode="r"): | ||||
f = "/".join((p, urllib.quote(path))) | ||||
return httprangereader(f, urlopener) | ||||
return o | ||||
return opener | ||||
mpm@selenic.com
|
r1101 | |||
class statichttprepository(localrepo.localrepository): | ||||
def __init__(self, ui, path): | ||||
Vadim Gelfer
|
r2673 | self._url = path | ||
mpm@selenic.com
|
r1101 | self.ui = ui | ||
Benoit Boissinot
|
r3853 | |||
Benoit Boissinot
|
r7274 | self.path, authinfo = url.getauthinfo(path.rstrip('/') + "/.hg") | ||
opener = build_opener(ui, authinfo) | ||||
mpm@selenic.com
|
r1101 | self.opener = opener(self.path) | ||
Dirkjan Ochtman
|
r6028 | |||
Benoit Boissinot
|
r3851 | # find requirements | ||
try: | ||||
requirements = self.opener("requires").read().splitlines() | ||||
Dirkjan Ochtman
|
r6028 | except IOError, inst: | ||
Thomas Arendsen Hein
|
r7178 | if inst.errno != errno.ENOENT: | ||
raise | ||||
# check if it is a non-empty old-style repository | ||||
try: | ||||
self.opener("00changelog.i").read(1) | ||||
except IOError, inst: | ||||
if inst.errno != errno.ENOENT: | ||||
raise | ||||
# we do not care about empty old-style repositories here | ||||
Dirkjan Ochtman
|
r6028 | msg = _("'%s' does not appear to be an hg repository") % path | ||
raise repo.RepoError(msg) | ||||
Thomas Arendsen Hein
|
r7178 | requirements = [] | ||
Dirkjan Ochtman
|
r6028 | |||
Benoit Boissinot
|
r3851 | # check them | ||
for r in requirements: | ||||
if r not in self.supported: | ||||
raise repo.RepoError(_("requirement '%s' not supported") % r) | ||||
# setup store | ||||
Adrian Buehlmann
|
r6988 | def pjoin(a, b): | ||
return a + '/' + b | ||||
self.store = store.store(requirements, self.path, opener, pjoin) | ||||
Matt Mackall
|
r6897 | self.spath = self.store.path | ||
self.sopener = self.store.opener | ||||
self.sjoin = self.store.join | ||||
Benoit Boissinot
|
r3851 | |||
Benoit Boissinot
|
r3791 | self.manifest = manifest.manifest(self.sopener) | ||
self.changelog = changelog.changelog(self.sopener) | ||||
mpm@selenic.com
|
r1101 | self.tagscache = None | ||
self.nodetagscache = None | ||||
Benoit Boissinot
|
r1598 | self.encodepats = None | ||
self.decodepats = None | ||||
mpm@selenic.com
|
r1101 | |||
Vadim Gelfer
|
r2673 | def url(self): | ||
Matt Mackall
|
r7211 | return self._url | ||
Vadim Gelfer
|
r2673 | |||
mpm@selenic.com
|
r1101 | def local(self): | ||
return False | ||||
Vadim Gelfer
|
r2740 | |||
Martin Geisler
|
r7005 | def lock(self, wait=True): | ||
raise util.Abort(_('cannot lock static-http repository')) | ||||
Vadim Gelfer
|
r2740 | def instance(ui, path, create): | ||
if create: | ||||
raise util.Abort(_('cannot create new static-http repository')) | ||||
Thomas Arendsen Hein
|
r4853 | return statichttprepository(ui, path[7:]) | ||