Mercurial > hgsubversion
diff tag_repo.py @ 326:33736e2e25f0
alternate approach for supporting svn schemes for repository paths
We now intercept the operations in the local repo class, and handle
the relevant operation ourselves. This frees us from wrapping all
relevant commands and replicating their functionality.
The implementation is incomplete; only one test has been modified to
use the standard Mercurial API with the changed URLs. Once changed,
those tests will likely reveal bugs or missing features in the new
wrappers. Also, new wrappers will be needed for handling conversion
flags such as -A/--authormap.
author | Dan Villiom Podlaski Christiansen <danchr@gmail.com> |
---|---|
date | Thu, 07 May 2009 20:50:53 +0200 |
parents | 91c818377703 |
children | 98740f66a70c |
line wrap: on
line diff
--- a/tag_repo.py +++ b/tag_repo.py @@ -1,23 +1,100 @@ from mercurial import node +from mercurial import util as hgutil +import mercurial.repo import hg_delta_editor +import util +import wrappers +def generate_repo_class(ui, repo): + def localsvn(fn): + ''' + Filter for instance methods which only apply to local Subversion + repositories. + ''' + if util.is_svn_repo(repo): + return fn + else: + original = repo.__getattribute__(fn.__name__) + return original -def tags_from_tag_info(repo): - hg_editor = hg_delta_editor.HgChangeReceiver(repo=repo) - for tag, source in hg_editor.tags.iteritems(): - source_ha = hg_editor.get_parent_revision(source[1]+1, source[0]) - yield 'tag/%s'%tag, node.hex(source_ha) - + def remotesvn(fn): + ''' + Filter for instance methods which require the first argument + to be a remote Subversion repository instance. + ''' + original = repo.__getattribute__(fn.__name__) + def wrapper(self, *args, **opts): + print args + if not isinstance(args[0], svnremoterepo): + return original(*args, **opts) + else: + return fn(self, *args, **opts) + wrapper.__name__ = fn.__name__ + '_wrapper' + wrapper.__doc__ = fn.__doc__ + return wrapper -def generate_repo_class(ui, repo): + class svnlocalrepo(repo.__class__): + @remotesvn + def pull(self, remote, heads=None, force=False): + try: + lock = self.wlock() + wrappers.pull(None, self.ui, self, source=remote.path, + svn=True, rev=heads, force=force) + except KeyboardInterrupt: + pass + finally: + lock.release() - class svntagrepo(repo.__class__): + @localsvn def tags(self): - tags = dict((k, node.bin(v)) - for k,v in tags_from_tag_info(self)) - hg_tags = super(svntagrepo, self).tags() - tags.update(hg_tags) + tags = super(svnlocalrepo, self).tags() + hg_editor = hg_delta_editor.HgChangeReceiver(repo=self) + for tag, source in hg_editor.tags.iteritems(): + target = hg_editor.get_parent_revision(source[1]+1, source[0]) + tags['tag/%s' % tag] = node.hex(target) + # TODO: should we even generate these tags? + if not hasattr(self, '_nofaketags'): + for (revnum, branch), node_hash in hg_editor.revmap.iteritems(): + tags['%s@r%d' % (branch or 'trunk', revnum)] = node_hash return tags - return svntagrepo + @localsvn + def tagslist(self): + try: + self._nofaketags = True + return super(svnlocalrepo, self).tagslist() + finally: + del self._nofaketags + + repo.__class__ = svnlocalrepo + +class svnremoterepo(mercurial.repo.repository): + def __init__(self, ui, path): + self.ui = ui + self.path = path + self.capabilities = set(['lookup']) + + def url(self): + return self.path + + def lookup(self, key): + return key + + def cancopy(self): + return False + + def heads(self, *args, **opts): + """ + Whenever this function is hit, we abort. The traceback is useful for + figuring out where to intercept the functionality. + """ + raise hgutil.Abort('command unavailable for Subversion repositories') + +def instance(ui, url, create): + if create: + raise hgutil.Abort('cannot create new remote Subversion repository') + + if url.startswith('svn+') and not url.startswith('svn+ssh:'): + url = url[4:] + return svnremoterepo(ui, util.normalize_url(url))