mirror of
https://github.com/facebook/sapling.git
synced 2024-10-08 07:49:11 +03:00
15ec41ce13
- unify httprangereader.py and statichttprepo.py:rangegreader() - build the opener from url.py, that allows use to puse username and password in the url, to follow the proxy settings from hgrc, etc.
118 lines
3.7 KiB
Python
118 lines
3.7 KiB
Python
# statichttprepo.py - simple http repository class for mercurial
|
|
#
|
|
# This provides read-only repo access to repositories exported via static http
|
|
#
|
|
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
|
|
#
|
|
# This software may be used and distributed according to the terms
|
|
# of the GNU General Public License, incorporated herein by reference.
|
|
|
|
from i18n import _
|
|
import changelog, byterange, url
|
|
import repo, localrepo, manifest, util, store
|
|
import urllib, urllib2, errno
|
|
|
|
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))
|
|
|
|
try:
|
|
f = self.opener.open(req)
|
|
data = f.read()
|
|
except urllib2.HTTPError, inst:
|
|
num = inst.code == 404 and errno.ENOENT or None
|
|
raise IOError(num, inst)
|
|
except urllib2.URLError, inst:
|
|
raise IOError(None, inst.reason[1])
|
|
|
|
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
|
|
|
|
class statichttprepository(localrepo.localrepository):
|
|
def __init__(self, ui, path):
|
|
self._url = path
|
|
self.ui = ui
|
|
|
|
self.path, authinfo = url.getauthinfo(path.rstrip('/') + "/.hg")
|
|
|
|
opener = build_opener(ui, authinfo)
|
|
self.opener = opener(self.path)
|
|
|
|
# find requirements
|
|
try:
|
|
requirements = self.opener("requires").read().splitlines()
|
|
except IOError, inst:
|
|
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
|
|
msg = _("'%s' does not appear to be an hg repository") % path
|
|
raise repo.RepoError(msg)
|
|
requirements = []
|
|
|
|
# check them
|
|
for r in requirements:
|
|
if r not in self.supported:
|
|
raise repo.RepoError(_("requirement '%s' not supported") % r)
|
|
|
|
# setup store
|
|
def pjoin(a, b):
|
|
return a + '/' + b
|
|
self.store = store.store(requirements, self.path, opener, pjoin)
|
|
self.spath = self.store.path
|
|
self.sopener = self.store.opener
|
|
self.sjoin = self.store.join
|
|
|
|
self.manifest = manifest.manifest(self.sopener)
|
|
self.changelog = changelog.changelog(self.sopener)
|
|
self.tagscache = None
|
|
self.nodetagscache = None
|
|
self.encodepats = None
|
|
self.decodepats = None
|
|
|
|
def url(self):
|
|
return self._url
|
|
|
|
def local(self):
|
|
return False
|
|
|
|
def lock(self, wait=True):
|
|
raise util.Abort(_('cannot lock static-http repository'))
|
|
|
|
def instance(ui, path, create):
|
|
if create:
|
|
raise util.Abort(_('cannot create new static-http repository'))
|
|
return statichttprepository(ui, path[7:])
|