Mercurial > hg > hgforest
changeset 54:ccfac5e72669
Cloning a forest is now possible over static HTTP.
author | Simon Law <simon@akoha.org> |
---|---|
date | Mon, 16 Jul 2007 11:44:42 -0400 |
parents | 5f46981d6b9c |
children | 146cb75364c0 |
files | forest.py test-forest.out |
diffstat | 2 files changed, 89 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/forest.py Tue Jul 10 16:21:50 2007 -0400 +++ b/forest.py Mon Jul 16 11:44:42 2007 -0400 @@ -49,7 +49,7 @@ import re from mercurial import commands, hg, node, util -from mercurial import localrepo, sshrepo, sshserver, httprepo +from mercurial import localrepo, sshrepo, sshserver, httprepo, statichttprepo from mercurial.hgweb import hgweb_mod if not hasattr(commands, "findcmd"): from mercurial.cmdutil import findcmd @@ -220,6 +220,88 @@ hgweb_mod.hgweb.do_forests = _httpserver_do_forests +def _statichttprepo_forests(self, walkhg): + """Shim this function into + mercurial.statichttprepo.statichttprepository so that it gives you + the list of subforests. + + It depends on the fact that most directory indices have directory + names followed by a slash. There is no reliable way of telling + whether a link leads into a subdirectory. + + Return a list of roots in filesystem representation relative to + the self repository. This list is lexigraphically sorted. + """ + + import HTMLParser + import string + import urllib + import urllib2 + import urlparse + + class HtmlIndexParser(HTMLParser.HTMLParser): + def __init__(self, ui, paths, walkhg): + self._paths = paths + self._ui = ui + self._walkhg = walkhg + self.current = None + def handle_starttag(self, tag, attrs): + if string.lower(tag) == "a": + for attr in attrs: + if (string.lower(attr[0]) == "href" and + attr[1].endswith('/')): + link = urlparse.urlsplit(attr[1]) + if (not self._walkhg and + link[2].rstrip('/').split('/')[-1] == '.hg'): + break + if not link[0] and not link[2].startswith('/'): + self._ui.debug(_("matched on '%s'") % attr[1]) + self._paths.append(urlparse.urljoin(self.current, + attr[1])) + + if self._url.endswith('/'): + url = self._url + else: + url = self._url + '/' + + res = [] + paths = [url] + seen = {} + + parser = HtmlIndexParser(self.ui, paths, walkhg) + while paths: + path = paths.pop() + if not seen.has_key(path): + seen[path] = True + parser.current = path + index = None + try: + self.ui.debug(_("retrieving '%s'\n") % path) + index = urllib2.urlopen(path) + parser.reset() + parser.feed(index.read()) + parser.close() + hg_path = urlparse.urljoin(path, '.hg') + self.ui.debug(_("retrieving '%s'\n") % hg_path) + hg = urllib2.urlopen(hg_path) + res.append(path) + except urllib2.HTTPError, inst: + pass + #raise IOError(None, inst) + except urllib2.URLError, inst: + pass + #raise IOError(None, inst.reason[1]) + + res.sort() + # Turn things into relative paths + result = [] + for root in res: + result.append(root[len(url):].rstrip('/') or ".") + return result + +statichttprepo.statichttprepository.forests = _statichttprepo_forests + + tree_section_re = re.compile(r"^tree(\w+)$") def tree_sections(cfg, withtop=True): @@ -362,7 +444,7 @@ if mq_fatal and mq_patches_applied(abspath): raise util.Abort(_("'%s' has mq patches applied") % relpath) if tip: - rev = 'tip' + rev = None else: rev = node.hex(repo.dirstate.parents()[0]) paths = dict(repo.ui.configitems('paths')) @@ -397,7 +479,10 @@ destpfx = os.path.dirname(destpath) if not os.path.exists(destpfx): os.makedirs(destpfx) - opts['rev'] = [rev] + if rev: + opts['rev'] = [rev] + else: + opts['rev'] = [] url = repo.url() if hasattr(repo, "root"): url = repo.root @@ -405,7 +490,7 @@ snapshot = ForestSnapshot() repo = hg.repository(ui, source) - snapshot.update(ui, repo, isinstance(repo, localrepo.localrepository), + snapshot.update(ui, repo, hasattr(repo, "root"), walkhgenabled(ui, walkhg), True) snapshot(ui, repo, doit, mq_check=False)
--- a/test-forest.out Tue Jul 10 16:21:50 2007 -0400 +++ b/test-forest.out Mon Jul 16 11:44:42 2007 -0400 @@ -37,43 +37,18 @@ # fclone [.] -requesting all changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 3 changes to 3 files 3 files updated, 0 files merged, 0 files removed, 0 files unresolved [d/d/t] -requesting all changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files 1 files updated, 0 files merged, 0 files removed, 0 files unresolved [e/d] -requesting all changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files 1 files updated, 0 files merged, 0 files removed, 0 files unresolved [t] -requesting all changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files 1 files updated, 0 files merged, 0 files removed, 0 files unresolved [t/t] -requesting all changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files 1 files updated, 0 files merged, 0 files removed, 0 files unresolved # fsnap