mirror of
https://github.com/facebook/sapling.git
synced 2024-10-13 02:07:31 +03:00
a9a41202ed
This improves compatibility with hg-git.
179 lines
5.8 KiB
Python
179 lines
5.8 KiB
Python
'''integration with Subversion repositories
|
|
|
|
hgsubversion is an extension for Mercurial that allows it to act as a Subversion
|
|
client, offering fast, incremental and bidirectional synchronisation.
|
|
|
|
Please note that hgsubversion should not be considered stable software. It is
|
|
not feature complete, and neither guarantees of functionality nor future
|
|
compatability can be offered. It is, however, quite useful for the cases where
|
|
it works, and a good platform for further improvements.
|
|
|
|
Before using hgsubversion, we *strongly* encourage running the
|
|
automated tests. See 'README' in the hgsubversion directory for
|
|
details.
|
|
|
|
The operation of hgsubversion can be customised with the following variables:
|
|
|
|
<list not written yet>
|
|
|
|
'''
|
|
# TODO: The docstring should be slightly more helpful, and at least mention all
|
|
# configuration settings we support
|
|
|
|
import os
|
|
import sys
|
|
import traceback
|
|
|
|
from mercurial import commands
|
|
from mercurial import extensions
|
|
from mercurial import hg
|
|
from mercurial import util as hgutil
|
|
from mercurial import demandimport
|
|
demandimport.ignore.extend([
|
|
'svn',
|
|
'svn.client',
|
|
'svn.core',
|
|
'svn.delta',
|
|
'svn.ra',
|
|
])
|
|
|
|
from svn import core
|
|
|
|
import svncommands
|
|
import util
|
|
import svnrepo
|
|
import wrappers
|
|
|
|
svnopts = [
|
|
('', 'stupid', None,
|
|
'use slower, but more compatible, protocol for Subversion'),
|
|
]
|
|
|
|
wrapcmds = { # cmd: generic, target, fixdoc, ppopts, opts
|
|
'parents': (False, None, False, False, [
|
|
('', 'svn', None, 'show parent svn revision instead'),
|
|
]),
|
|
'diff': (False, None, False, False, [
|
|
('', 'svn', None, 'show svn diffs against svn parent'),
|
|
]),
|
|
'pull': (True, 'sources', True, True, []),
|
|
'push': (True, 'destinations', True, True, []),
|
|
'incoming': (False, 'sources', True, True, []),
|
|
'clone': (False, 'sources', True, True, [
|
|
('T', 'tagpaths', '',
|
|
'list of paths to search for tags in Subversion repositories'),
|
|
('A', 'authors', '',
|
|
'file mapping Subversion usernames to Mercurial authors'),
|
|
('', 'filemap', '',
|
|
'file containing rules for remapping Subversion repository paths'),
|
|
('', 'layout', 'auto', ('import standard layout or single '
|
|
'directory? Can be standard, single, or auto.')),
|
|
]),
|
|
}
|
|
|
|
def uisetup(ui):
|
|
"""insert command wrappers for a bunch of commands"""
|
|
|
|
docvals = {'extension': 'hgsubversion'}
|
|
for cmd, (generic, target, fixdoc, ppopts, opts) in wrapcmds.iteritems():
|
|
|
|
if fixdoc and wrappers.generic.__doc__:
|
|
docvals['command'] = cmd
|
|
docvals['Command'] = cmd.capitalize()
|
|
docvals['target'] = target
|
|
doc = wrappers.generic.__doc__.strip() % docvals
|
|
fn = getattr(commands, cmd)
|
|
fn.__doc__ = fn.__doc__.rstrip() + '\n\n ' + doc
|
|
|
|
wrapped = generic and wrappers.generic or getattr(wrappers, cmd)
|
|
entry = extensions.wrapcommand(commands.table, cmd, wrapped)
|
|
if ppopts:
|
|
entry[1].extend(svnopts)
|
|
if opts:
|
|
entry[1].extend(opts)
|
|
|
|
try:
|
|
rebase = extensions.find('rebase')
|
|
if not rebase:
|
|
return
|
|
entry = extensions.wrapcommand(rebase.cmdtable, 'rebase', wrappers.rebase)
|
|
entry[1].append(('', 'svn', None, 'automatic svn rebase'))
|
|
except:
|
|
pass
|
|
|
|
|
|
def svn(ui, repo, subcommand, *args, **opts):
|
|
'''see detailed help for list of subcommands'''
|
|
|
|
# guess command if prefix
|
|
if subcommand not in svncommands.table:
|
|
candidates = []
|
|
for c in svncommands.table:
|
|
if c.startswith(subcommand):
|
|
candidates.append(c)
|
|
if len(candidates) == 1:
|
|
subcommand = candidates[0]
|
|
|
|
# override subversion credentials
|
|
for key in ('username', 'password'):
|
|
if key in opts:
|
|
ui.setconfig('hgsubversion', key, opts[key])
|
|
|
|
path = os.path.dirname(repo.path)
|
|
try:
|
|
commandfunc = svncommands.table[subcommand]
|
|
return commandfunc(ui, args=args, hg_repo_path=path, repo=repo, **opts)
|
|
except core.SubversionException, e:
|
|
if e.apr_err == core.SVN_ERR_RA_SERF_SSL_CERT_UNTRUSTED:
|
|
raise hgutil.Abort('It appears svn does not trust the ssl cert for this site.\n'
|
|
'Please try running svn ls on that url first.')
|
|
raise
|
|
except TypeError:
|
|
tb = traceback.extract_tb(sys.exc_info()[2])
|
|
if len(tb) == 1:
|
|
ui.status('Bad arguments for subcommand %s\n' % subcommand)
|
|
else:
|
|
raise
|
|
except KeyError, e:
|
|
tb = traceback.extract_tb(sys.exc_info()[2])
|
|
if len(tb) == 1:
|
|
ui.status('Unknown subcommand %s\n' % subcommand)
|
|
else:
|
|
raise
|
|
|
|
def reposetup(ui, repo):
|
|
if repo.local():
|
|
svnrepo.generate_repo_class(ui, repo)
|
|
|
|
_old_local = hg.schemes['file']
|
|
def _lookup(url):
|
|
if util.islocalrepo(url):
|
|
return svnrepo
|
|
else:
|
|
return _old_local(url)
|
|
|
|
# install scheme handlers
|
|
hg.schemes.update({ 'file': _lookup, 'http': svnrepo, 'https': svnrepo,
|
|
'svn': svnrepo, 'svn+ssh': svnrepo, 'svn+http': svnrepo,
|
|
'svn+https': svnrepo})
|
|
|
|
cmdtable = {
|
|
"svn":
|
|
(svn,
|
|
[('u', 'svn-url', '', 'path to the Subversion server.'),
|
|
('', 'stupid', False, 'be stupid and use diffy replay.'),
|
|
('A', 'authors', '', 'username mapping filename'),
|
|
('', 'filemap', '',
|
|
'remap file to exclude paths or include only certain paths'),
|
|
('', 'force', False, 'force an operation to happen'),
|
|
('', 'username', '', 'username for authentication'),
|
|
('', 'password', '', 'password for authentication'),
|
|
('r', 'rev', '', 'Mercurial revision'),
|
|
],
|
|
svncommands._helpgen(),
|
|
),
|
|
}
|
|
|
|
# only these methods are public
|
|
__all__ = ('cmdtable', 'reposetup', 'uisetup')
|