Mercurial > public > mercurial-scm > hg
view mercurial/statichttprepo.py @ 7305:c21d236ca897
hgweb: descend empty directories in web view
When a manifest has a series of directories with nothing in them but a single
directory, displaying the entire chain of empty directories allows for
navigation down to the first non-empty directory with a single click.
Because Java links package hierarchy to directory hierarchy, and because Java
conventions include at least three empty directories at the top of this
hierarchy, descending down empty directories is very common in Java web tools.
author | Ry4an Brase <ry4an-hg@ry4an.org> |
---|---|
date | Mon, 03 Nov 2008 10:20:28 +0100 |
parents | 95f3694cc5a4 |
children | 1d54e2f6c0b7 |
line wrap: on
line source
# 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:])