# HG changeset patch # User Patrick Mezard # Date 1247967873 18000 # Node ID 0f7095f53ca381c620e99696ca3c93358cc8e44e # Parent c82d5a9acecf60f67a5ca4c897da0501bf0023ab Extend svnrepos with SubversionRepo and SVNMeta SubversionRepo and SVNMeta are now hidden behind svnremoterepo and svnlocalrepo. It unifies the way svn credentials are read from the command line and configuration file, at the cost of import cycle between svnrepo and wrappers. It is currently not a big deal thanks to demandimport. diff --git a/hgsubversion/svncommands.py b/hgsubversion/svncommands.py --- a/hgsubversion/svncommands.py +++ b/hgsubversion/svncommands.py @@ -7,7 +7,7 @@ from mercurial import util as hgutil import maps import svnwrap -import svnmeta +import svnrepo import util import utility_commands import svnexternals @@ -16,12 +16,6 @@ import svnexternals def verify(ui, repo, *args, **opts): '''verify current revision against Subversion repository ''' - - if not args: - url = repo.ui.expandpath('default') - else: - url = args[0] - ctx = repo[opts.get('rev', '.')] if 'close' in ctx.extra(): ui.write('cannot verify closed branch') @@ -33,9 +27,11 @@ def verify(ui, repo, *args, **opts): srev = int(srev.split('@')[1]) ui.write('verifying %s against r%i\n' % (ctx, srev)) - url = util.normalize_url(url.rstrip('/')) - user, passwd = util.getuserpass(ui) - svn = svnwrap.SubversionRepo(url, user, passwd) + + url = repo.ui.expandpath('default') + if args: + url = args[0] + svn = svnrepo.svnremoterepo(ui, url).svn btypes = {'default': 'trunk'} branchpath = btypes.get(ctx.branch(), 'branches/%s' % ctx.branch()) @@ -72,11 +68,9 @@ def rebuildmeta(ui, repo, hg_repo_path, dest = args[0] elif len(args) > 1: raise hgutil.Abort('rebuildmeta takes 1 or no arguments') - url = repo.ui.expandpath(dest or 'default-push', dest or 'default') uuid = None - url = util.normalize_url(url.rstrip('/')) - user, passwd = util.getuserpass(ui) - svn = svnwrap.SubversionRepo(url, user, passwd) + url = repo.ui.expandpath(dest or 'default-push', dest or 'default') + svn = svnrepo.svnremoterepo(ui, url).svn subdir = svn.subdir svnmetadir = os.path.join(repo.path, 'svn') if not os.path.exists(svnmetadir): @@ -224,7 +218,7 @@ def update(ui, args, repo, clean=False, assert len(args) == 1 rev = int(args[0]) - meta = svnmeta.SVNMeta(repo) + meta = repo.svnmeta() answers = [] for k, v in meta.revmap.iteritems(): diff --git a/hgsubversion/svnrepo.py b/hgsubversion/svnrepo.py --- a/hgsubversion/svnrepo.py +++ b/hgsubversion/svnrepo.py @@ -21,6 +21,10 @@ import mercurial.repo import util import wrappers +import svnwrap +import svnmeta + +propertycache = hgutil.propertycache def generate_repo_class(ui, repo): """ This function generates the local repository wrapper. """ @@ -56,20 +60,39 @@ def generate_repo_class(ui, repo): def findoutgoing(self, remote, base=None, heads=None, force=False): return wrappers.outgoing(repo, remote, heads, force) + def svnmeta(self, uuid=None, subdir=''): + return svnmeta.SVNMeta(self, uuid, subdir) + repo.__class__ = svnlocalrepo class svnremoterepo(mercurial.repo.repository): """ the dumb wrapper for actual Subversion repositories """ - def __init__(self, ui, path): + def __init__(self, ui, path=None): self.ui = ui + if path is None: + path = self.ui.config('paths', 'default') self.path = path self.capabilities = set(['lookup', 'subversion']) - @property + @propertycache def svnurl(self): return util.normalize_url(self.path) + @propertycache + def svn(self): + # DO NOT default the user to hg's getuser(). If you provide + # *any* default username to Subversion, it won't use any remembered + # username for the desired realm, breaking OS X Keychain support, + # GNOME keyring support, and all similar tools. + user = self.ui.config('hgsubversion', 'username') + passwd = self.ui.config('hgsubversion', 'password') + return svnwrap.SubversionRepo(self.svnurl, user, passwd) + + @property + def svnuuid(self): + return self.svn.uuid + def url(self): return self.path diff --git a/hgsubversion/util.py b/hgsubversion/util.py --- a/hgsubversion/util.py +++ b/hgsubversion/util.py @@ -60,15 +60,6 @@ def islocalrepo(url): return False -def getuserpass(ui): - # DO NOT default the user to hg's getuser(). If you provide - # *any* default username to Subversion, it won't use any remembered - # username for the desired realm, breaking OS X Keychain support, - # GNOME keyring support, and all similar tools. - return (ui.config('hgsubversion', 'username'), - ui.config('hgsubversion', 'password')) - - def version(ui): """Guess the version of hgsubversion. """ diff --git a/hgsubversion/utility_commands.py b/hgsubversion/utility_commands.py --- a/hgsubversion/utility_commands.py +++ b/hgsubversion/utility_commands.py @@ -2,8 +2,8 @@ import os from mercurial import util as hgutil -import svnmeta import svnwrap +import svnrepo import util def genignore(ui, repo, force=False, **opts): @@ -12,16 +12,15 @@ def genignore(ui, repo, force=False, **o ignpath = repo.wjoin('.hgignore') if not force and os.path.exists(ignpath): raise hgutil.Abort('not overwriting existing .hgignore, try --force?') - url = util.normalize_url(repo.ui.config('paths', 'default')) - user, passwd = util.getuserpass(ui) - svn = svnwrap.SubversionRepo(url, user, passwd) - meta = svnmeta.SVNMeta(repo, svn.uuid) + svn = svnrepo.svnremoterepo(repo.ui).svn + meta = repo.svnmeta() hashes = meta.revmap.hashes() parent = util.parentrev(ui, repo, meta, hashes) r, br = hashes[parent.node()] branchpath = br and ('branches/%s' % br) or 'trunk' ignorelines = ['.hgignore', 'syntax:glob'] - dirs = [''] + [d[0] for d in svn.list_files(branchpath, r) if d[1] == 'd'] + dirs = [''] + [d[0] for d in svn.list_files(branchpath, r) + if d[1] == 'd'] for dir in dirs: props = svn.list_props('%s/%s/' % (branchpath, dir), r) if 'svn:ignore' not in props: @@ -35,10 +34,7 @@ def genignore(ui, repo, force=False, **o def info(ui, repo, hg_repo_path, **opts): """show Subversion details similar to `svn info' """ - url = util.normalize_url(repo.ui.config('paths', 'default')) - user, passwd = util.getuserpass(ui) - svn = svnwrap.SubversionRepo(url, user, passwd) - meta = svnmeta.SVNMeta(repo, svn.uuid) + meta = repo.svnmeta() hashes = meta.revmap.hashes() parent = util.parentrev(ui, repo, meta, hashes) pn = parent.node() @@ -54,10 +50,8 @@ def info(ui, repo, hg_repo_path, **opts) subdir = subdir.replace('branches/../', '') else: branchpath = '/branches/%s' % br - url = util.normalize_url(repo.ui.config('paths', 'default')) - if url[-1] == '/': - url = url[:-1] - url = '%s%s' % (url, branchpath) + remoterepo = svnrepo.svnremoterepo(repo.ui) + url = '%s%s' % (remoterepo.svnurl, branchpath) author = meta.authors.reverselookup(parent.user()) # cleverly figure out repo root w/o actually contacting the server reporoot = url[:len(url)-len(subdir)] @@ -86,7 +80,7 @@ def listauthors(ui, args, authors=None, if not len(args): ui.status('No repository specified.\n') return - svn = svnwrap.SubversionRepo(util.normalize_url(args[0])) + svn = svnrepo.svnremoterepo(ui, args[0]).svn author_set = set() for rev in svn.revisions(): author_set.add(str(rev.author)) # So None becomes 'None' diff --git a/hgsubversion/wrappers.py b/hgsubversion/wrappers.py --- a/hgsubversion/wrappers.py +++ b/hgsubversion/wrappers.py @@ -10,11 +10,11 @@ from mercurial import i18n from svn import core from svn import delta -import svnmeta import replay import pushmod import stupid as stupidmod import svnwrap +import svnrepo import util pullfuns = { @@ -34,7 +34,7 @@ def parents(orig, ui, repo, *args, **opt """ if not opts.get('svn', False): return orig(ui, repo, *args, **opts) - meta = svnmeta.SVNMeta(repo) + meta = repo.svnmeta() hashes = meta.revmap.hashes() ha = util.parentrev(ui, repo, meta, hashes) if ha.node() == node.nullid: @@ -53,12 +53,10 @@ def incoming(orig, ui, repo, source='def if 'subversion' not in other.capabilities: return orig(ui, repo, source, **opts) - user, passwd = util.getuserpass(ui) - svn = svnwrap.SubversionRepo(other.svnurl, user, passwd) - meta = svnmeta.SVNMeta(repo) + meta = repo.svnmeta() ui.status('incoming changes from %s\n' % other.svnurl) - for r in svn.revisions(start=meta.revmap.seen): + for r in other.svn.revisions(start=meta.revmap.seen): ui.status('\n') for label, attr in revmeta: l1 = label + ':' @@ -75,7 +73,7 @@ def outgoing(repo, dest=None, heads=None # split off #rev; TODO implement --revision/#rev support svnurl, revs, checkout = hg.parseurl(dest.svnurl, heads) - meta = svnmeta.SVNMeta(repo) + meta = repo.svnmeta() parent = repo.parents()[0].node() hashes = meta.revmap.hashes() return util.outgoing_revisions(repo, hashes, parent) @@ -86,7 +84,7 @@ def diff(orig, ui, repo, *args, **opts): """ if not opts.get('svn', False) or opts.get('change', None): return orig(ui, repo, *args, **opts) - meta = svnmeta.SVNMeta(repo) + meta = repo.svnmeta() hashes = meta.revmap.hashes() if not opts.get('rev', None): parent = repo.parents()[0] @@ -119,9 +117,8 @@ def push(repo, dest, force, revs): # split of #rev; TODO: implement --rev/#rev support svnurl, revs, checkout = hg.parseurl(svnurl, revs) # TODO: do credentials specified in the URL still work? - user, passwd = util.getuserpass(ui) - svn = svnwrap.SubversionRepo(svnurl, user, passwd) - meta = svnmeta.SVNMeta(repo, svn.uuid) + svn = svnrepo.svnremoterepo(repo.ui, svnurl).svn + meta = repo.svnmeta(svn.uuid) # Strategy: # 1. Find all outgoing commits from this head @@ -156,7 +153,7 @@ def push(repo, dest, force, revs): base_revision = hashes[base_n][0] try: pushmod.commit(ui, repo, old_ctx, meta, svnurl, - base_revision, user, passwd) + base_revision, svn.username, svn.password) except pushmod.NoFilesException: ui.warn("Could not push revision %s because it had no changes in svn.\n" % old_ctx) @@ -194,7 +191,7 @@ def push(repo, dest, force, revs): child = children[0] rebasesrc = node.bin(child.extra().get('rebase_source', node.hex(node.nullid))) # TODO: stop constantly creating the SVNMeta instances. - meta = svnmeta.SVNMeta(meta.repo, svn.uuid) + meta = repo.svnmeta(svn.uuid) hashes = meta.revmap.hashes() util.swap_out_encoding(old_encoding) return 0 @@ -230,9 +227,8 @@ def pull(repo, source, heads=[], force=F repo.ui.note('fetching stupidly...\n') # TODO: do credentials specified in the URL still work? - user, passwd = util.getuserpass(repo.ui) - svn = svnwrap.SubversionRepo(svn_url, user, passwd) - meta = svnmeta.SVNMeta(repo, svn.uuid, svn.subdir) + svn = svnrepo.svnremoterepo(repo.ui, svn_url).svn + meta = repo.svnmeta(svn.uuid, svn.subdir) start = max(meta.revmap.seen, skipto_rev) initializing_repo = meta.revmap.seen <= 0 @@ -320,7 +316,7 @@ def rebase(orig, ui, repo, **opts): extra['branch'] = ctx.branch() extrafn = opts.get('svnextrafn', extrafn2) sourcerev = opts.get('svnsourcerev', repo.parents()[0].node()) - meta = svnmeta.SVNMeta(repo) + meta = repo.svnmeta() hashes = meta.revmap.hashes() o_r = util.outgoing_revisions(repo, hashes, sourcerev=sourcerev) if not o_r: