changeset 395:636e9bf5d49c

svncommands: add verify command
author Dirkjan Ochtman <dirkjan@ochtman.nl>
date Thu, 11 Jun 2009 19:14:05 +0200
parents d70c8e45cb9e
children 11c4c7242a36
files hgsubversion/svncommands.py tests/comprehensive/test_verify.py tests/run.py
diffstat 3 files changed, 96 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/hgsubversion/svncommands.py
+++ b/hgsubversion/svncommands.py
@@ -55,6 +55,57 @@ def incoming(ui, svn_url, hg_repo_path, 
                                   str(r.__getattribute__(attr)).strip(), ))
 
 
+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['.']
+    if 'close' in ctx.extra():
+        ui.write('cannot verify closed branch')
+        return 0
+    srev = ctx.extra().get('convert_revision')
+    if srev is None:
+        raise hgutil.Abort('revision %s not from SVN' % ctx)
+
+    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(opts)
+    svn = svnwrap.SubversionRepo(url, user, passwd)
+
+    btypes = {'default': 'trunk'}
+    branchpath = btypes.get(ctx.branch(), 'branches/%s' % ctx.branch())
+    svnfiles = set()
+    result = 0
+    for fn, type in svn.list_files(branchpath, srev):
+        if type != 'f':
+            continue
+        svnfiles.add(fn)
+        data, mode = svn.get_file(branchpath + '/'  + fn, srev)
+        fctx = ctx[fn]
+        dmatch = fctx.data() == data
+        mmatch = fctx.flags() == mode
+        if not (dmatch and mmatch):
+            ui.write('difference in file %s' % fn)
+            result = 1
+
+    hgfiles = set(ctx)
+    hgfiles.discard('.hgtags')
+    hgfiles.discard('.hgsvnexternals')
+    if hgfiles != svnfiles:
+        missing = set(hgfiles).symmetric_difference(svnfiles)
+        ui.write('missing files: %s' % (', '.join(missing)))
+        result = 1
+
+    return result
+
+
 def rebuildmeta(ui, repo, hg_repo_path, args, **opts):
     """rebuild hgsubversion metadata using values stored in revisions
     """
@@ -200,6 +251,7 @@ table = {
     'rebuildmeta': rebuildmeta,
     'incoming': incoming,
     'updateexternals': svnexternals.updateexternals,
+    'verify': verify,
 }
 
 table.update(utility_commands.table)
new file mode 100644
--- /dev/null
+++ b/tests/comprehensive/test_verify.py
@@ -0,0 +1,43 @@
+import os
+import pickle
+import unittest
+
+import test_util
+
+from mercurial import hg
+from mercurial import ui
+
+from hgsubversion import svncommands
+
+def _do_case(self, name, stupid):
+    subdir = test_util.subdir.get(name, '')
+    repo = self._load_fixture_and_fetch(name, subdir=subdir, stupid=stupid)
+    assert len(self.repo) > 0
+    for i in repo:
+        ctx = repo[i]
+        hg.clean(repo, ctx.node(), False)
+        self.assertEqual(svncommands.verify(repo.ui, repo), 0)
+
+def buildmethod(case, name, stupid):
+    m = lambda self: self._do_case(case, stupid)
+    m.__name__ = name
+    bits = case, stupid and 'stupid' or 'real'
+    m.__doc__ = 'Test verify on %s with %s replay.' % bits
+    return m
+
+attrs = {'_do_case': _do_case}
+fixtures = [f for f in os.listdir(test_util.FIXTURES) if f.endswith('.svndump')]
+for case in fixtures:
+    # this fixture results in an empty repository, don't use it
+    if case == 'project_root_not_repo_root.svndump':
+        continue
+    name = 'test_' + case[:-len('.svndump')]
+    attrs[name] = buildmethod(case, name, False)
+    name += '_stupid'
+    attrs[name] = buildmethod(case, name, True)
+
+VerifyTests = type('VerifyTests', (test_util.TestBase,), attrs)
+
+def suite():
+    all = [unittest.TestLoader().loadTestsFromTestCase(VerifyTests)]
+    return unittest.TestSuite(all)
--- a/tests/run.py
+++ b/tests/run.py
@@ -26,6 +26,7 @@ import test_utility_commands
 import test_urls
 
 from comprehensive import test_stupid_pull
+from comprehensive import test_verify
 
 def comprehensive(mod):
     dir = os.path.basename(os.path.dirname(mod.__file__))