Mercurial > hg > hgforest
changeset 48:d8e40f82bb3d
Cloning a forest is now possible over SSH.
author | Simon Law <simon@akoha.org> |
---|---|
date | Mon, 09 Jul 2007 17:46:20 -0400 |
parents | 7ed36c52acd0 |
children | 728167aff824 |
files | forest.py |
diffstat | 1 files changed, 99 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/forest.py Wed Jun 13 12:36:37 2007 +0200 +++ b/forest.py Mon Jul 09 17:46:20 2007 -0400 @@ -49,6 +49,7 @@ import re from mercurial import commands, hg, node, util +from mercurial import localrepo, httprepo, sshrepo, sshserver if not hasattr(commands, "findcmd"): from mercurial.cmdutil import findcmd else: @@ -84,13 +85,22 @@ Return a list of roots in filesystem representation. """ + return top.forests(walkhg) + +def _localrepo_forests(self, walkhg): + """Shim this function into mercurial.localrepo.localrepository so + that it gives you the list of subforests. + + Return a list of roots in filesystem representation relative to + the self repository. + """ def errhandler(err): - if err.filename == top: + if err.filename == self.root: raise err res = [] - paths = [top] + paths = [self.root] while paths: path = paths.pop() for root, dirs, files in os.walk(path, onerror=errhandler): @@ -111,8 +121,72 @@ if os.path.isdir(os.path.join(path, '.hg')): res.append(path) res.sort() + # Turn things into relative paths + pfx = len(self.root) + 1 + res = [r[pfx:] or "." for r in res] return res +localrepo.localrepository.forests = _localrepo_forests + + +def _sshrepo_forests(self, walkhg): + """Shim this function into mercurial.sshrepo.sshrepository so + that it gives you the list of subforests. + + Return a list of roots as ssh:// URLs. + """ + if 'forests' not in self.capabilities: + raise util.Abort(_("Remote forests cannot be cloned because the other repository doesn't support the forest extension.")) + data = self.call("forests", walkhg=("", "True")[walkhg]) + print data + return data.splitlines() + +sshrepo.sshrepository.forests = _sshrepo_forests + + +def _sshserver_do_hello(self): + '''the hello command returns a set of lines describing various + interesting things about the server, in an RFC822-like format. + Currently the only one defined is "capabilities", which + consists of a line in the form: + + capabilities: space separated list of tokens + ''' + + caps = ['unbundle', 'lookup', 'changegroupsubset', 'forests'] + if self.ui.configbool('server', 'uncompressed'): + caps.append('stream=%d' % self.repo.revlogversion) + self.respond("capabilities: %s\n" % (' '.join(caps),)) + +sshserver.sshserver.do_hello = _sshserver_do_hello + + +def _sshserver_do_forests(self): + key, walkhg = self.getarg() + f = self.repo.forests(bool(walkhg)) + self.respond("\n".join(f)) + +sshserver.sshserver.do_forests = _sshserver_do_forests + + + +def _httprepo_forests(self, walkhg): + """Shim this function into mercurial.httprepo.httprepository so + that it gives you the list of subforests. + + Return a list of roots as http:// URLs. + """ + if 'forests' not in self.capabilities: + raise util.Abort(_("Remote forests cannot be cloned because the other repository doesn't support the forest extension.")) + d = self.do_read("forests", walkhg=("", "True")[walkhg]) + success, data = d[:-1].split(" ", 1) + if int(success): + return data.splitlines() + else: + self.raise_(hg.RepoError(data)) + +httprepo.httprepository.forests = _httprepo_forests + tree_section_re = re.compile(r"^tree(\w+)$") @@ -138,6 +212,10 @@ def mq_patches_applied(rpath): + if rpath.startswith("file:"): + rpath = rpath[len("file:"):] + else: + raise util.Abort(_("'%s' does not start with file:") % rpath) rpath = os.path.join(rpath, ".hg") entries = os.listdir(rpath) for e in entries: @@ -203,7 +281,7 @@ """ repo = None - pfx = toprepo.root + pfx = toprepo.url() for t in self.trees: root, rev, path = t.info(pathalias) ui.write("[%s]\n" % root) @@ -221,7 +299,7 @@ ui.write(_("skipped, no valid repo found\n\n")) continue func(repo, root, path, rev, - mq_check and mq_patches_applied(repo.root)) + mq_check and mq_patches_applied(repo.url())) ui.write("\n") @@ -237,26 +315,27 @@ rootmap = {} self.trees = [] - pfxlen = len(repo.root + os.sep) - for rpath in enumerate_repos(ui, repo.root, walkhg): - root = util.pconvert(rpath[pfxlen:]) - if root == '': - root = '.' - else: - repo = hg.repository(ui, rpath) - if mq_fatal and mq_patches_applied(rpath): - raise util.Abort(_("'%s' has mq patches applied") % root) + top = repo.url() + for f in repo.forests(walkhg): + relpath = util.pconvert(f) + if f == ".": + f = "" + abspath = os.sep.join((top, f)) + if relpath != '.': + repo = hg.repository(ui, abspath) + if mq_fatal and mq_patches_applied(abspath): + raise util.Abort(_("'%s' has mq patches applied") % abspath) if tip: rev = 'tip' else: rev = node.hex(repo.dirstate.parents()[0]) paths = dict(repo.ui.configitems('paths')) - if self.rootmap.has_key(root): - tree = self.rootmap[root] + if self.rootmap.has_key(relpath): + tree = self.rootmap[relpath] tree.update(rev, paths) else: - tree = ForestSnapshot.Tree(root, rev, paths) - rootmap[root] = tree + tree = ForestSnapshot.Tree(relpath, rev, paths) + rootmap[relpath] = tree self.trees.append(tree) self.rootmap = rootmap @@ -271,7 +350,7 @@ def clone(ui, source, dest, walkhg, **opts): - """Clone a local forest.""" + """Clone a forest.""" dest = os.path.normpath(dest) def doit(repo, root, path, rev, *unused): @@ -283,11 +362,11 @@ if not os.path.exists(destpfx): os.makedirs(destpfx) opts['rev'] = [rev] - commands.clone(ui, repo.root, destpath, **opts) + commands.clone(ui, repo.url(), destpath, **opts) snapshot = ForestSnapshot() repo = hg.repository(ui, source) - snapshot.update(ui, repo, True, walkhgenabled(ui, walkhg)) + snapshot.update(ui, repo, False, walkhgenabled(ui, walkhg), True) snapshot(ui, repo, doit, mq_check=False)