diff options
author | Tristan Seligmann <mithrandi@debian.org> | 2017-08-11 09:51:59 +0000 |
---|---|---|
committer | Tristan Seligmann <mithrandi@debian.org> | 2017-08-11 09:51:59 +0000 |
commit | a234ef0228929919399bc8adad6f8d8bb8dee7bc (patch) | |
tree | 4f9185baa7e0e6d37529ae2072e1c970244f6e14 /tests | |
parent | b7339d75dcc99eeba499b376700e9e5ff545baff (diff) | |
parent | f505a84d33c238a892064774ca31854d3b5b1df2 (diff) |
New upstream version (hg snapshot).
Diffstat (limited to 'tests')
-rw-r--r-- | tests/comprehensive/test_obsstore_on.py | 40 | ||||
-rw-r--r-- | tests/comprehensive/test_rebuildmeta.py | 17 | ||||
-rw-r--r-- | tests/comprehensive/test_sqlite_revmap.py | 77 | ||||
-rw-r--r-- | tests/comprehensive/test_verify_and_startrev.py | 1 | ||||
-rw-r--r-- | tests/fixtures/dir_removal.svndump | 103 | ||||
-rw-r--r-- | tests/fixtures/rename-closed-branch-dir.sh | 69 | ||||
-rw-r--r-- | tests/fixtures/rename-closed-branch-dir.svndump | 296 | ||||
-rwxr-xr-x | tests/run.py | 82 | ||||
-rw-r--r-- | tests/test_fetch_branches.py | 3 | ||||
-rw-r--r-- | tests/test_fetch_command.py | 2 | ||||
-rw-r--r-- | tests/test_fetch_dir_removal.py | 17 | ||||
-rw-r--r-- | tests/test_fetch_mappings.py | 51 | ||||
-rw-r--r-- | tests/test_fetch_renames.py | 33 | ||||
-rw-r--r-- | tests/test_helpers.py | 1 | ||||
-rw-r--r-- | tests/test_hooks.py | 2 | ||||
-rw-r--r-- | tests/test_pull.py | 16 | ||||
-rw-r--r-- | tests/test_pull_fallback.py | 4 | ||||
-rw-r--r-- | tests/test_push_command.py | 30 | ||||
-rw-r--r-- | tests/test_revmap_migrate.py | 72 | ||||
-rw-r--r-- | tests/test_svnwrap.py | 14 | ||||
-rw-r--r-- | tests/test_tags.py | 13 | ||||
-rw-r--r-- | tests/test_urls.py | 55 | ||||
-rw-r--r-- | tests/test_util.py | 62 | ||||
-rw-r--r-- | tests/test_utility_commands.py | 6 |
24 files changed, 911 insertions, 155 deletions
diff --git a/tests/comprehensive/test_obsstore_on.py b/tests/comprehensive/test_obsstore_on.py new file mode 100644 index 0000000..7fd4a25 --- /dev/null +++ b/tests/comprehensive/test_obsstore_on.py @@ -0,0 +1,40 @@ +import os +import sys + +# wrapped in a try/except because of weirdness in how +# run.py works as compared to nose. +try: + import test_util +except ImportError: + sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) + import test_util + +import test_push_command + + +class ObsstoreOnMixIn(object): + # do not double the test size by being wrapped again + obsolete_mode_tests = False + stupid_mode_tests = False + + def setUp(self): + super(ObsstoreOnMixIn, self).setUp() + hgrcpath = os.environ.get('HGRCPATH') + assert hgrcpath + with open(hgrcpath, 'a') as f: + f.write('\n[experimental]\nevolution=createmarkers\n') + + def shortDescription(self): + text = super(ObsstoreOnMixIn, self).shortDescription() + if text: + text += ' (obsstore on)' + return text + + +def buildtestclass(cls): + name = 'ObsstoreOn%s' % cls.__name__ + newcls = type(name, (ObsstoreOnMixIn, cls,), {}) + globals()[name] = newcls + + +buildtestclass(test_push_command.PushTests) diff --git a/tests/comprehensive/test_rebuildmeta.py b/tests/comprehensive/test_rebuildmeta.py index e4e486b..e05f712 100644 --- a/tests/comprehensive/test_rebuildmeta.py +++ b/tests/comprehensive/test_rebuildmeta.py @@ -129,10 +129,14 @@ def _run_assertions(self, name, single, src, dest, u): old, new = util.load(stf, resave=False), util.load(dtf, resave=False) if tf == 'lastpulled' and (name, self.stupid, single) in expect_youngest_skew: - self.assertNotEqual(old, new, - 'rebuildmeta unexpected match on youngest rev!') + self.assertNotEqual( + old, new, + 'rebuildmeta unexpected match on lastpulled: ' + 'old %d new %d, case %r %r %r' % ( + old, new, name, self.stupid, single)) continue - self.assertEqual(old, new, tf + ' differs') + self.assertEqual( + old, new, '%s differs old: %r new %r'% (tf, old, new)) try: self.assertEqual(src.branchmap(), dest.branchmap()) except AttributeError: @@ -141,7 +145,12 @@ def _run_assertions(self, name, single, src, dest, u): srcbi = util.load(os.path.join(src.path, 'svn', 'branch_info')) destbi = util.load(os.path.join(dest.path, 'svn', 'branch_info')) self.assertEqual(sorted(srcbi.keys()), sorted(destbi.keys())) - revkeys = svnmeta.SVNMeta(dest).revmap.keys() + revmap = svnmeta.SVNMeta(dest).revmap + # revmap disables __iter__ intentionally to avoid possible slow code + # (not using database index in SqliteRevMap) + # we need to fetch all keys so enable it by setting _allowiter + revmap._allowiter = True + revkeys = revmap.keys() for branch in destbi: srcinfo = srcbi[branch] destinfo = destbi[branch] diff --git a/tests/comprehensive/test_sqlite_revmap.py b/tests/comprehensive/test_sqlite_revmap.py new file mode 100644 index 0000000..0c0f2ec --- /dev/null +++ b/tests/comprehensive/test_sqlite_revmap.py @@ -0,0 +1,77 @@ +import os +import unittest +import sys + +# wrapped in a try/except because of weirdness in how +# run.py works as compared to nose. +try: + import test_util +except ImportError: + sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) + import test_util + +# interesting and fast tests +import test_fetch_mappings +import test_fetch_renames +import test_pull +import test_template_keywords +import test_utility_commands + +# comprehensive tests +try: + import test_custom_layout +except ImportError: + sys.path.insert(0, os.path.dirname(__file__)) + import test_custom_layout + +import test_rebuildmeta +import test_updatemeta + +from hgsubversion import svnmeta, maps + + +class SqliteRevMapMixIn(object): + # do not double the test size by being wrapped again + obsolete_mode_tests = False + stupid_mode_tests = False + + def setUp(self): + assert svnmeta.SVNMeta._defaultrevmapclass is maps.RevMap + svnmeta.SVNMeta._defaultrevmapclass = maps.SqliteRevMap + super(SqliteRevMapMixIn, self).setUp() + + def tearDown(self): + assert svnmeta.SVNMeta._defaultrevmapclass is maps.SqliteRevMap + svnmeta.SVNMeta._defaultrevmapclass = maps.RevMap + super(SqliteRevMapMixIn, self).tearDown() + + def shortDescription(self): + text = super(SqliteRevMapMixIn, self).shortDescription() + if text: + text += ' (sqlite revmap)' + return text + +def buildtestclass(cls, selector=None): + name = 'SqliteRevMap%s' % cls.__name__ + newcls = type(name, (SqliteRevMapMixIn, cls,), {}) + + # remove test cases not selected by selector + if selector: + for name in dir(newcls): + if name.startswith('test_') and not selector(name[5:]): + setattr(newcls, name, None) + + globals()[name] = newcls + +def svndumpselector(name): + return name in ['branch_rename_to_trunk', + 'tag_name_same_as_branch'] + +buildtestclass(test_fetch_mappings.MapTests) +buildtestclass(test_fetch_renames.TestFetchRenames) +buildtestclass(test_pull.TestPull) +buildtestclass(test_template_keywords.TestLogKeywords) +buildtestclass(test_utility_commands.UtilityTests) + +buildtestclass(test_rebuildmeta.RebuildMetaTests, svndumpselector) +buildtestclass(test_updatemeta.UpdateMetaTests, svndumpselector) diff --git a/tests/comprehensive/test_verify_and_startrev.py b/tests/comprehensive/test_verify_and_startrev.py index 7581df0..8ad22c2 100644 --- a/tests/comprehensive/test_verify_and_startrev.py +++ b/tests/comprehensive/test_verify_and_startrev.py @@ -34,6 +34,7 @@ _skipstandard = set([ 'correct.svndump', 'corrupt.svndump', 'emptyrepo2.svndump', + 'dir_removal.svndump', ]) def _do_case(self, name, layout): diff --git a/tests/fixtures/dir_removal.svndump b/tests/fixtures/dir_removal.svndump new file mode 100644 index 0000000..a278802 --- /dev/null +++ b/tests/fixtures/dir_removal.svndump @@ -0,0 +1,103 @@ +SVN-fs-dump-format-version: 2 + +UUID: 5554378f-55cc-437f-9045-6148f657307d + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2017-05-23T11:48:49.399395Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 103 +Content-length: 103 + +K 10 +svn:author +V 8 +testuser +K 8 +svn:date +V 27 +2017-05-23T11:49:53.974692Z +K 7 +svn:log +V 1 +1 +PROPS-END + +Node-path: dir1 +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: dir1/1.txt +Node-kind: file +Node-action: add +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709 +Prop-content-length: 10 +Text-content-length: 0 +Content-length: 10 + +PROPS-END + + +Node-path: dir2 +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: dir2/2.txt +Node-kind: file +Node-action: add +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709 +Prop-content-length: 10 +Text-content-length: 0 +Content-length: 10 + +PROPS-END + + +Revision-number: 2 +Prop-content-length: 103 +Content-length: 103 + +K 10 +svn:author +V 8 +testuser +K 8 +svn:date +V 27 +2017-05-23T11:50:14.852941Z +K 7 +svn:log +V 1 +2 +PROPS-END + +Node-path: dir1/dir2 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: dir2 + + +Node-path: dir2 +Node-action: delete + + diff --git a/tests/fixtures/rename-closed-branch-dir.sh b/tests/fixtures/rename-closed-branch-dir.sh new file mode 100644 index 0000000..d0ae264 --- /dev/null +++ b/tests/fixtures/rename-closed-branch-dir.sh @@ -0,0 +1,69 @@ +#!/bin/sh +# +# Generate rename-closed-branch-dir.svndump +# + +mkdir temp +cd temp + +mkdir project +cd project +mkdir trunk +mkdir branches +mkdir tags +cd .. + +svnadmin create testrepo +CURRENT_DIR=`pwd` +svnurl=file://"$CURRENT_DIR"/testrepo +#svn import project-orig $svnurl -m "init project" + +svn co $svnurl project +cd project +svn add * +svn ci -m "init project" + +cd trunk +echo a > a.txt +svn add a.txt +svn ci -m "add a.txt in trunk" + +# Create a branch +svn up +cd ../branches +svn copy ../trunk async-db +svn ci -m "add branch async-db" +svn up + +# Implement feature +cd async-db +echo b > b.txt +svn add b.txt +svn ci -m "Async functionality" + +# Merge feature branch +cd ../../trunk +svn merge $svnurl/branches/async-db +svn ci -m "Merged branch async-db" +cd .. +svn up + +# Create branch folder for unnecessary branches +svn mkdir $svnurl/branches/dead -m "Create branch folder for unnecessary branches" +svn up + +# We don't need the 'async-db' branch, anymore. +svn copy $svnurl/branches/async-db $svnurl/branches/dead -m "We don't need the 'async-db' branch, anymore." +svn up + +# Rename 'dead' folder to 'closed' +svn move $svnurl/branches/dead $svnurl/branches/closed -m "Renamed 'dead' folder to 'closed'" +svn up + +# Move 'branches/closed' to 'tags/closed' +svn move $svnurl/branches/closed $svnurl/tags/closed -m "Moved 'branches/closed' to 'tags/closed'." +svn up + +# Dump repository +cd .. +svnadmin dump testrepo > ../rename-closed-branch-dir.svndump diff --git a/tests/fixtures/rename-closed-branch-dir.svndump b/tests/fixtures/rename-closed-branch-dir.svndump new file mode 100644 index 0000000..aa327fe --- /dev/null +++ b/tests/fixtures/rename-closed-branch-dir.svndump @@ -0,0 +1,296 @@ +SVN-fs-dump-format-version: 2 + +UUID: 2efdcfe9-9dfd-40a7-a9cc-bf5b70806ff3 + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2016-01-27T15:35:29.673334Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 112 +Content-length: 112 + +K 10 +svn:author +V 5 +augie +K 8 +svn:date +V 27 +2016-01-27T15:35:30.079847Z +K 7 +svn:log +V 12 +init project +PROPS-END + +Node-path: branches +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: tags +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: trunk +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Revision-number: 2 +Prop-content-length: 118 +Content-length: 118 + +K 10 +svn:author +V 5 +augie +K 8 +svn:date +V 27 +2016-01-27T15:35:31.065912Z +K 7 +svn:log +V 18 +add a.txt in trunk +PROPS-END + +Node-path: trunk/a.txt +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 2 +Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3 +Text-content-sha1: 3f786850e387550fdab836ed7e6dc881de23001b +Content-length: 12 + +PROPS-END +a + + +Revision-number: 3 +Prop-content-length: 119 +Content-length: 119 + +K 10 +svn:author +V 5 +augie +K 8 +svn:date +V 27 +2016-01-27T15:35:34.051261Z +K 7 +svn:log +V 19 +add branch async-db +PROPS-END + +Node-path: branches/async-db +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 2 +Node-copyfrom-path: trunk + + +Revision-number: 4 +Prop-content-length: 119 +Content-length: 119 + +K 10 +svn:author +V 5 +augie +K 8 +svn:date +V 27 +2016-01-27T15:35:36.101507Z +K 7 +svn:log +V 19 +Async functionality +PROPS-END + +Node-path: branches/async-db/b.txt +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 2 +Text-content-md5: 3b5d5c3712955042212316173ccf37be +Text-content-sha1: 89e6c98d92887913cadf06b2adb97f26cde4849b +Content-length: 12 + +PROPS-END +b + + +Revision-number: 5 +Prop-content-length: 122 +Content-length: 122 + +K 10 +svn:author +V 5 +augie +K 8 +svn:date +V 27 +2016-01-27T15:35:38.055736Z +K 7 +svn:log +V 22 +Merged branch async-db +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 57 +Content-length: 57 + +K 13 +svn:mergeinfo +V 22 +/branches/async-db:3-4 +PROPS-END + + +Node-path: trunk/b.txt +Node-kind: file +Node-action: add +Node-copyfrom-rev: 4 +Node-copyfrom-path: branches/async-db/b.txt +Text-copy-source-md5: 3b5d5c3712955042212316173ccf37be +Text-copy-source-sha1: 89e6c98d92887913cadf06b2adb97f26cde4849b + + +Revision-number: 6 +Prop-content-length: 145 +Content-length: 145 + +K 10 +svn:author +V 5 +augie +K 8 +svn:date +V 27 +2016-01-27T15:35:40.046670Z +K 7 +svn:log +V 45 +Create branch folder for unnecessary branches +PROPS-END + +Node-path: branches/dead +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Revision-number: 7 +Prop-content-length: 145 +Content-length: 145 + +K 10 +svn:author +V 5 +augie +K 8 +svn:date +V 27 +2016-01-27T15:35:41.048576Z +K 7 +svn:log +V 45 +We don't need the 'async-db' branch, anymore. +PROPS-END + +Node-path: branches/dead/async-db +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 6 +Node-copyfrom-path: branches/async-db + + +Revision-number: 8 +Prop-content-length: 133 +Content-length: 133 + +K 10 +svn:author +V 5 +augie +K 8 +svn:date +V 27 +2016-01-27T15:35:42.046536Z +K 7 +svn:log +V 33 +Renamed 'dead' folder to 'closed' +PROPS-END + +Node-path: branches/closed +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 7 +Node-copyfrom-path: branches/dead + + +Node-path: branches/dead +Node-action: delete + + +Revision-number: 9 +Prop-content-length: 141 +Content-length: 141 + +K 10 +svn:author +V 5 +augie +K 8 +svn:date +V 27 +2016-01-27T15:35:43.048056Z +K 7 +svn:log +V 41 +Moved 'branches/closed' to 'tags/closed'. +PROPS-END + +Node-path: branches/closed +Node-action: delete + + +Node-path: tags/closed +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 8 +Node-copyfrom-path: branches/closed + + diff --git a/tests/run.py b/tests/run.py index aef61f9..497f4f2 100755 --- a/tests/run.py +++ b/tests/run.py @@ -5,53 +5,6 @@ import os import sys import unittest -import test_util -test_util.SkipTest = None - -def tests(): - import test_binaryfiles - import test_diff - import test_externals - import test_fetch_branches - import test_fetch_command - import test_fetch_command_regexes - import test_fetch_exec - import test_fetch_mappings - import test_fetch_renames - import test_fetch_symlinks - import test_fetch_truncated - import test_hooks - import test_svn_pre_commit_hooks - import test_pull - import test_pull_fallback - import test_push_command - import test_push_renames - import test_push_dirs - import test_push_eol - import test_push_autoprops - import test_single_dir_clone - import test_single_dir_push - import test_svnwrap - import test_tags - import test_template_keywords - import test_utility_commands - import test_unaffected_core - import test_urls - - sys.path.append(os.path.dirname(__file__)) - sys.path.append(os.path.join(os.path.dirname(__file__), 'comprehensive')) - - import test_rebuildmeta - import test_stupid_pull - import test_updatemeta - import test_verify_and_startrev - - return locals() - -def comprehensive(mod): - dir = os.path.basename(os.path.dirname(mod.__file__)) - return dir == 'comprehensive' - if __name__ == '__main__': description = ("This script runs the hgsubversion tests. If no tests are " "specified, all known tests are implied.") @@ -100,26 +53,33 @@ if __name__ == '__main__': import tempfile sys.stdout = tempfile.TemporaryFile() - all_tests = tests() - - args = [i.split('.py')[0].replace('-', '_') for i in args] + args = [os.path.basename(os.path.splitext(arg)[0]).replace('-', '_') + for arg in args] loader = unittest.TestLoader() suite = unittest.TestSuite() + if sys.version_info[:2] < (2, 7): + import glob + def discover(start_dir, pattern='test*.py', top_level_dir=None): + tests = [] + sys.path.append(start_dir) + for path in glob.glob(os.path.join(start_dir, pattern)): + name = os.path.splitext(os.path.basename(path))[0] + tests.append(loader.loadTestsFromModule(__import__(name))) + return tests + loader.discover = discover + if not args: - check = lambda x: options.comprehensive or not comprehensive(x) - suite.addTests(loader.loadTestsFromModule(m) - for (n, m) in sorted(all_tests.iteritems()) - if check(m)) + suite.addTests(loader.discover('.')) + + if options.comprehensive: + suite.addTests(loader.discover('comprehensive', + top_level_dir='comprehensive')) else: - for arg in args: - if arg == 'test_util': - continue - elif arg not in all_tests: - print >> sys.stderr, 'test module %s not available' % arg - else: - suite.addTest(loader.loadTestsFromModule(all_tests[arg])) + sys.path.append(os.path.join(os.path.dirname(__file__), 'comprehensive')) + + suite.addTests(loader.loadTestsFromNames(args)) runner = unittest.TextTestRunner(**testargs) result = runner.run(suite) diff --git a/tests/test_fetch_branches.py b/tests/test_fetch_branches.py index 45991ae..781f023 100644 --- a/tests/test_fetch_branches.py +++ b/tests/test_fetch_branches.py @@ -41,7 +41,8 @@ class TestFetchBranches(test_util.TestBase): heads = dict([(ctx.branch(), ctx) for ctx in heads]) # Let these tests disabled yet as the fix is not obvious self.assertEqual(heads['branch1'].manifest().keys(), ['b']) - self.assertEqual(heads['branch2'].manifest().keys(), ['a', 'b']) + self.assertEqual(sorted(heads['branch2'].manifest().keys()), + ['a', 'b']) def test_unorderedbranch(self): repo = self._load_fixture_and_fetch('unorderedbranch.svndump') diff --git a/tests/test_fetch_command.py b/tests/test_fetch_command.py index 4649555..745a4a4 100644 --- a/tests/test_fetch_command.py +++ b/tests/test_fetch_command.py @@ -93,7 +93,7 @@ class TestBasicRepoLayout(test_util.TestBase): 'test_files_copied_from_outside_btt.svndump') self.assertEqual(node.hex(repo['tip'].node()), '3c78170e30ddd35f2c32faa0d8646ab75bba4f73') - self.assertEqual(test_util.repolen(repo.changelog), 2) + self.assertEqual(test_util.repolen(repo), 2) def test_file_renamed_in_from_outside_btt(self): repo = self._load_fixture_and_fetch( diff --git a/tests/test_fetch_dir_removal.py b/tests/test_fetch_dir_removal.py new file mode 100644 index 0000000..24a795d --- /dev/null +++ b/tests/test_fetch_dir_removal.py @@ -0,0 +1,17 @@ +import test_util + +import sys +import unittest + +class TestFetchDirectoryRemoval(test_util.TestBase): + stupid_mode_tests = True + + def test_removal(self): + repo = self._load_fixture_and_fetch('dir_removal.svndump', + layout='single', + subdir='dir1') + self.assertEqual(sorted(repo['tip'].manifest().keys()), + ['1.txt', 'dir2/2.txt']) + extra = repo['tip'].extra().copy() + extra.pop('convert_revision', None) + self.assertEqual(extra, {'branch': 'default'}) diff --git a/tests/test_fetch_mappings.py b/tests/test_fetch_mappings.py index f022c6f..f4e373c 100644 --- a/tests/test_fetch_mappings.py +++ b/tests/test_fetch_mappings.py @@ -92,7 +92,10 @@ class MapTests(test_util.TestBase): new = open(os.path.join(repopath, 'authors'), 'w') new.write(open(orig).read()) new.close() - test = maps.AuthorMap(self.repo.svnmeta(skiperrorcheck=True)) + meta = self.repo.svnmeta(skiperrorcheck=True) + test = maps.AuthorMap( + meta.ui, meta.authormap_file, meta.defaulthost, + meta.caseignoreauthors, meta.mapauthorscmd, meta.defaultauthors) fromself = set(test) test.load(orig) all_tests = set(test) @@ -114,6 +117,15 @@ class MapTests(test_util.TestBase): self.assertEqual(self.repo['tip'].user(), 'evil@5b65bade-98f3-4993-a01f-b7a6710da339') + def test_author_map_mapauthorscmd(self): + repo_path = self.load_svndump('replace_trunk_with_branch.svndump') + ui = self.ui() + ui.setconfig('hgsubversion', 'mapauthorscmd', 'echo "svn: %s"') + commands.clone(ui, test_util.fileurl(repo_path), + self.wc_path) + self.assertEqual(self.repo[0].user(), 'svn: Augie') + self.assertEqual(self.repo['tip'].user(), 'svn: evil') + def _loadwithfilemap(self, svndump, filemapcontent, failonmissing=True): repo_path = self.load_svndump(svndump) @@ -149,9 +161,9 @@ class MapTests(test_util.TestBase): # The exclusion of alpha is overridden by the later rule to # include all of '.', whereas gamma should remain excluded # because it's excluded after the root directory. - self.assertEqual(self.repo[0].manifest().keys(), + self.assertEqual(sorted(self.repo[0].manifest().keys()), ['alpha', 'beta']) - self.assertEqual(self.repo['default'].manifest().keys(), + self.assertEqual(sorted(self.repo['default'].manifest().keys()), ['alpha', 'beta']) @test_util.requiresreplay @@ -200,6 +212,22 @@ class MapTests(test_util.TestBase): self.assert_('good-name' in branches) self.assertEquals(self.repo[2].branch(), 'default') + def test_branchmap_regex_and_glob(self): + repo_path = self.load_svndump('branchmap.svndump') + branchmap = open(self.branchmap, 'w') + branchmap.write("syntax:re\n") + branchmap.write("bad(.*) = good-\\1 # stuffy\n") + branchmap.write("glob:feat* = default\n") + branchmap.close() + ui = self.ui() + ui.setconfig('hgsubversion', 'branchmap', self.branchmap) + commands.clone(ui, test_util.fileurl(repo_path), + self.wc_path, branchmap=self.branchmap) + branches = set(self.repo[i].branch() for i in self.repo) + self.assert_('badname' not in branches) + self.assert_('good-name' in branches) + self.assertEquals(self.repo[2].branch(), 'default') + def test_branchmap_tagging(self): '''test tagging a renamed branch, which used to raise an exception''' repo_path = self.load_svndump('commit-to-tag.svndump') @@ -290,6 +318,23 @@ class MapTests(test_util.TestBase): for r in repo: self.assertEquals(verify.verify(ui, repo, rev=r), 0) + def test_branchmap_no_replacement(self): + '''test that empty mappings are accepted + + Empty mappings are lines like 'this ='. We check that such branches are + not converted. + ''' + repo_path = self.load_svndump('branchmap.svndump') + branchmap = open(self.branchmap, 'w') + branchmap.write("badname =\n") + branchmap.close() + ui = self.ui() + ui.setconfig('hgsubversion', 'branchmap', self.branchmap) + commands.clone(ui, test_util.fileurl(repo_path), + self.wc_path, branchmap=self.branchmap) + branches = set(self.repo[i].branch() for i in self.repo) + self.assertEquals(sorted(branches), ['default', 'feature']) + def test_tagmap(self): repo_path = self.load_svndump('basic_tag_tests.svndump') tagmap = open(self.tagmap, 'w') diff --git a/tests/test_fetch_renames.py b/tests/test_fetch_renames.py index fad681d..caeeeea 100644 --- a/tests/test_fetch_renames.py +++ b/tests/test_fetch_renames.py @@ -34,12 +34,16 @@ class TestFetchRenames(test_util.TestBase): repo = self._load_fixture_and_fetch('renames_with_prefix.svndump', subdir='prefix', config=config) - self._run_assertions(repo) + self._run_assertions(repo, prefix=True) - def _run_assertions(self, repo): + def _run_assertions(self, repo, prefix=False): # Map revnum to mappings of dest name to (source name, dest content) + if prefix: + prefixlen = len('svn:ae30a990-0fd3-493e-b5d7-883bdd606745/prefix') + else: + prefixlen = len('svn:ae30a990-0fd3-493e-b5d7-883bdd606745') copies = { - 4: { + '/trunk@6': { 'a1': ('a', 'a\n'), 'linka1': ('linka', 'a'), 'a2': ('a', 'a\n'), @@ -55,32 +59,35 @@ class TestFetchRenames(test_util.TestBase): 'da2/db/dbf': ('da/db/dbf', 'd\n'), 'da2/db/dblink': ('da/db/dblink', '../daf'), }, - 5: { + '/branches/branch1@6': { 'c1': ('c', 'c\nc\n'), 'linkc1': ('linkc', 'cc'), }, - 9: { + '/trunk@10': { 'unchanged2': ('unchanged', 'unchanged\n'), 'unchangedlink2': ('unchangedlink', 'unchanged'), 'unchangeddir2/f': ('unchangeddir/f', 'unchanged2\n'), 'unchangeddir2/link': ('unchangeddir/link', 'f'), }, - 10: { + '/trunk@11': { 'groupdir2/b': ('groupdir/b', 'b\n'), 'groupdir2/linkb': ('groupdir/linkb', 'b'), }, } for rev in repo: ctx = repo[rev] - copymap = copies.get(rev, {}) + copymap = copies.get(ctx.extra()['convert_revision'][prefixlen:], + {}) for f in ctx.manifest(): cp = ctx[f].renamed() - self.assertEqual(bool(cp), bool(copymap.get(f)), - 'copy records differ for %s in %d' % (f, rev)) - if not cp: - continue - self.assertEqual(cp[0], copymap[f][0]) - self.assertEqual(ctx[f].data(), copymap[f][1]) + want = copymap.get(f) + self.assertEqual( + bool(cp), bool(want), + 'copy records differ for %s in %d (want %r, got %r)' % ( + f, rev, want, cp)) + if cp: + self.assertEqual(cp[0], want[0]) + self.assertEqual(ctx[f].data(), want[1]) self.assertEqual(repo['tip']['changed3'].data(), 'changed\nchanged3\n') diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 219db36..527faea 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -30,3 +30,4 @@ class TestHelpers(unittest.TestCase): fs.popfile('bb') self.assertEqual([], os.listdir(fs._tempdir)) self.assertRaises(editor.EditingError, lambda: fs.getfile('bb')) + fs.close() diff --git a/tests/test_hooks.py b/tests/test_hooks.py index ffd3edc..66197df 100644 --- a/tests/test_hooks.py +++ b/tests/test_hooks.py @@ -17,7 +17,7 @@ class TestHooks(test_util.TestBase): def test_updatemetahook(self): repo, repo_path = self._loadupdate('single_rev.svndump') - state = repo.parents() + state = repo[None].parents() self.add_svn_rev(repo_path, {'trunk/alpha': 'Changed'}) commands.pull(self.repo.ui, self.repo) diff --git a/tests/test_pull.py b/tests/test_pull.py index 3a1a217..d038094 100644 --- a/tests/test_pull.py +++ b/tests/test_pull.py @@ -20,37 +20,37 @@ class TestPull(test_util.TestBase): def test_nochanges(self): self._loadupdate('single_rev.svndump') - state = self.repo.parents() + state = self.repo[None].parents() commands.pull(self.repo.ui, self.repo) - self.assertEqual(state, self.repo.parents()) + self.assertEqual(state, self.repo[None].parents()) def test_onerevision_noupdate(self): repo, repo_path = self._loadupdate('single_rev.svndump') - state = repo.parents() + state = repo[None].parents() self.add_svn_rev(repo_path, {'trunk/alpha': 'Changed'}) commands.pull(self.repo.ui, repo) - self.assertEqual(state, repo.parents()) + self.assertEqual(state, repo[None].parents()) self.assertTrue('tip' not in repo['.'].tags()) def test_onerevision_doupdate(self): repo, repo_path = self._loadupdate('single_rev.svndump') - state = repo.parents() + state = repo[None].parents() self.add_svn_rev(repo_path, {'trunk/alpha': 'Changed'}) commands.pull(self.repo.ui, repo, update=True) - self.failIfEqual(state, repo.parents()) + self.failIfEqual(state, repo[None].parents()) self.assertTrue('tip' in repo['.'].tags()) def test_onerevision_divergent(self): repo, repo_path = self._loadupdate('single_rev.svndump') self.commitchanges((('alpha', 'alpha', 'Changed another way'),)) - state = repo.parents() + state = repo[None].parents() self.add_svn_rev(repo_path, {'trunk/alpha': 'Changed one way'}) try: commands.pull(self.repo.ui, repo, update=True) except hgutil.Abort: # hg < 1.9 raised when crossing branches pass - self.assertEqual(state, repo.parents()) + self.assertEqual(state, repo[None].parents()) self.assertTrue('tip' not in repo['.'].tags()) self.assertEqual(len(repo.heads()), 2) diff --git a/tests/test_pull_fallback.py b/tests/test_pull_fallback.py index a2979ff..5d94b16 100644 --- a/tests/test_pull_fallback.py +++ b/tests/test_pull_fallback.py @@ -37,14 +37,14 @@ class TestPullFallback(test_util.TestBase): # Passing stupid=True doesn't seem to be working - force it repo.ui.setconfig('hgsubversion', 'stupid', "true") - state = repo.parents() + state = repo[None].parents() calls, replaced = _monkey_patch(to_patch) try: self.add_svn_rev(repo_path, {'trunk/alpha': 'Changed'}) commands.pull(self.repo.ui, repo, update=True) - self.failIfEqual(state, repo.parents()) + self.failIfEqual(state, repo[None].parents()) self.assertTrue('tip' in repo[None].tags()) self.assertEqual(expected_calls, calls) diff --git a/tests/test_push_command.py b/tests/test_push_command.py index a62f3ce..6debbb2 100644 --- a/tests/test_push_command.py +++ b/tests/test_push_command.py @@ -138,7 +138,33 @@ class PushTests(test_util.TestBase): open(os.path.join(repo_path, 'conf', 'svnserve.conf'), 'w').write('[general]\nanon-access=write\n[sasl]\n') self.port = random.randint(socket.IPPORT_USERRESERVED, 65535) - self.host = 'localhost' + self.host = socket.gethostname() + + # The `svnserve` binary appears to use the obsolete `gethostbyname(3)` + # function, which always returns an IPv4 address, even on hosts that + # support and expect IPv6. As a workaround, resolve the hostname + # within the test harness with `getaddrinfo(3)` to ensure that the + # client and server both use the same IPv4 or IPv6 address. + addrinfo = socket.getaddrinfo(self.host, self.port) + # On macOS svn seems to have issues with IPv6 at least some of + # the time, so try and bias towards IPv4. This works because + # AF_INET is less than AF_INET6 on all platforms I've + # checked. Hopefully any platform where that's not true will + # be fine with IPv6 all the time. :) + selected = sorted(addrinfo)[0] + self.host = selected[4][0] + + # If we're connecting via IPv6 the need to put brackets around the + # hostname in the URL. + ipv6 = selected[0] == socket.AF_INET6 + + # Ditch any interface information since that's not helpful in + # a URL + if ipv6 and ':' in self.host and '%' in self.host: + self.host = self.host.rsplit('%', 1)[0] + + urlfmt = 'svn://[%s]:%d/%s' if ipv6 else 'svn://%s:%d/%s' + args = ['svnserve', '--daemon', '--foreground', '--listen-port=%d' % self.port, '--listen-host=%s' % self.host, @@ -152,7 +178,7 @@ class PushTests(test_util.TestBase): import shutil shutil.rmtree(self.wc_path) commands.clone(self.ui(), - 'svn://%s:%d/%s' % (self.host, self.port, subdir), + urlfmt % (self.host, self.port, subdir), self.wc_path, noupdate=True) repo = self.repo diff --git a/tests/test_revmap_migrate.py b/tests/test_revmap_migrate.py new file mode 100644 index 0000000..4d92b22 --- /dev/null +++ b/tests/test_revmap_migrate.py @@ -0,0 +1,72 @@ +import test_util + +from mercurial import util as hgutil +from hgsubversion import svnmeta, maps +from mercurial.node import hex + +class TestRevMapMigrate(test_util.TestBase): + + def tearDown(self): + # revert changes to defaultrevmapclass + svnmeta.SVNMeta._defaultrevmapclass = maps.RevMap + + def _test_revmap_migrate(self, fromclass, toclass): + # revmap interfaces to test + getters = [ + lambda x: x.branchedits('the_branch', 3), + lambda x: x.branchedits('the_branch', 4), + lambda x: x.branchedits('the_branch', 5), + lambda x: x.branchedits('the_branch', 6), + lambda x: x.branchedits(None, 5), + lambda x: x.branchedits('non_existed', 10), + lambda x: x.branchmaxrevnum('the_branch', 3), + lambda x: x.branchmaxrevnum('the_branch', 4), + lambda x: x.branchmaxrevnum('the_branch', 5), + lambda x: x.branchmaxrevnum('the_branch', 6), + lambda x: x.branchmaxrevnum(None, 5), + lambda x: x.branchmaxrevnum('non_existed', 10), + lambda x: list(x.revhashes(3)), + lambda x: list(x.revhashes(4)), + lambda x: list(x.revhashes(42)), + lambda x: list(x.revhashes(105)), + lambda x: x.firstpulled, + lambda x: x.lastpulled, + lambda x: x.lasthash, + ] + + svnmeta.SVNMeta._defaultrevmapclass = fromclass + repo = self._load_fixture_and_fetch('two_heads.svndump') + meta = svnmeta.SVNMeta(repo) + self.assertEqual(meta.revmap.__class__, fromclass) + origrevmap = meta.revmap + + # insert fake special (duplicated, with '\0') data + origrevmap[103, None] = b'\0' * 20 + origrevmap[104, None] = b'\0' * 18 + b'cd' + origrevmap[105, None] = b'ab\0cdefghijklmnopqrs' + origrevmap[104, None] = b'\0' * 18 + b'\xff\0' + origrevmap[105, 'ab'] = origrevmap[105, None] + + origvalues = [f(meta.revmap) for f in getters] + + # migrate to another format (transparently) + svnmeta.SVNMeta._defaultrevmapclass = toclass + meta = svnmeta.SVNMeta(repo) + self.assertEqual(meta.revmap.__class__, toclass) + + # enable iteration otherwise we cannot use iteritems + origrevmap._allowiter = True + for k, v in origrevmap.iteritems(): + newv = meta.revmap[k] + self.assertEqual(newv, v) + self.assertEqual(len(newv), 20) + self.assertEqual(meta.revmap[meta.revmap.hashes()[v]], v) + + newvalues = [f(meta.revmap) for f in getters] + self.assertEqual(origvalues, newvalues) + + def test_revmap_migrate_up(self): + self._test_revmap_migrate(maps.RevMap, maps.SqliteRevMap) + + def test_revmap_migrate_down(self): + self._test_revmap_migrate(maps.SqliteRevMap, maps.RevMap) diff --git a/tests/test_svnwrap.py b/tests/test_svnwrap.py index d71c9e4..4db069f 100644 --- a/tests/test_svnwrap.py +++ b/tests/test_svnwrap.py @@ -11,15 +11,11 @@ class TestBasicRepoLayout(unittest.TestCase): def setUp(self): self.tmpdir = tempfile.mkdtemp('svnwrap_test') self.repo_path = '%s/testrepo' % self.tmpdir - subprocess.call(['svnadmin', 'create', self.repo_path, ]) - inp = open(os.path.join(os.path.dirname(__file__), 'fixtures', - 'project_root_at_repo_root.svndump')) - proc = subprocess.call(['svnadmin', 'load', self.repo_path, ], - stdin=inp, - close_fds=test_util.canCloseFds, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - assert proc == 0 + + with open(os.path.join(test_util.FIXTURES, + 'project_root_at_repo_root.svndump')) as fp: + svnwrap.create_and_load(self.repo_path, fp) + self.repo = svnwrap.SubversionRepo(test_util.fileurl(self.repo_path)) def tearDown(self): diff --git a/tests/test_tags.py b/tests/test_tags.py index cfd2659..2a0f06b 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -4,6 +4,7 @@ import os, sys, cStringIO, difflib import unittest from mercurial import commands +from mercurial import error from mercurial import hg from mercurial import node from mercurial import ui @@ -128,10 +129,8 @@ rename a tag 'branch': 'magic', 'convert_revision': 'svn:af82cc90-c2d2-43cd-b1aa-c8a78449440a/tags/will-edit@19'}) self.assertEqual(willedit, repo.tags()['will-edit']) - self.assertEqual(repo['will-edit'].manifest().keys(), ['alpha', - 'beta', - 'gamma', - ]) + self.assertEqual(sorted(repo['will-edit'].manifest().keys()), + ['alpha', 'beta', 'gamma']) self.assertEqual( repo[alsoedit].extra(), {'close': '1', @@ -164,14 +163,12 @@ rename a tag 'magic2': '\xa3\xa2D\x86aM\xc0v\xb9\xb0\x18\x14\xad\xacwBUi}\xe2', }) - def test_old_tag_map_rebuilds(self): + def test_old_tag_map_aborts(self): repo = self._load_fixture_and_fetch('tag_name_same_as_branch.svndump') tm = os.path.join(repo.path, 'svn', 'tagmap') open(tm, 'w').write('1\n') # force tags to load since it is lazily loaded when needed - repo.svnmeta().tags - commands.pull(repo.ui, repo) - self.assertEqual(open(tm).read().splitlines()[0], '2') + self.assertRaises(error.Abort, lambda: repo.svnmeta().tags) def _debug_print_tags(self, repo, ctx, fp): def formatnode(ctx): diff --git a/tests/test_urls.py b/tests/test_urls.py index 591ac22..a790f16 100644 --- a/tests/test_urls.py +++ b/tests/test_urls.py @@ -8,58 +8,61 @@ from hgsubversion import svnrepo class TestSubversionUrls(test_util.TestBase): def test_standard_url(self): - self.assertEqual((None, None, 'file:///var/svn/repo'), - parse_url('file:///var/svn/repo')) + self.check_parse_url((None, None, 'file:///var/svn/repo'), + ('file:///var/svn/repo', )) def test_user_url(self): - self.assertEqual( + self.check_parse_url( ('joe', None, 'https://svn.testurl.com/repo'), - parse_url('https://joe@svn.testurl.com/repo')) - self.assertEqual( + ('https://joe@svn.testurl.com/repo', )) + self.check_parse_url( ('bob', None, 'https://svn.testurl.com/repo'), - parse_url('https://joe@svn.testurl.com/repo', 'bob')) + ('https://joe@svn.testurl.com/repo', 'bob', )) def test_password_url(self): - self.assertEqual( + self.check_parse_url( (None, 't3stpw', 'svn+ssh://svn.testurl.com/repo'), - parse_url('svn+ssh://:t3stpw@svn.testurl.com/repo')) - self.assertEqual( + ('svn+ssh://:t3stpw@svn.testurl.com/repo', )) + self.check_parse_url( (None, '123abc', 'svn+ssh://svn.testurl.com/repo'), - parse_url('svn+ssh://:t3stpw@svn.testurl.com/repo', None, '123abc')) + ('svn+ssh://:t3stpw@svn.testurl.com/repo', None, '123abc', )) def test_svnssh_preserve_user(self): - self.assertEqual( + self.check_parse_url( ('user', 't3stpw', 'svn+ssh://user@svn.testurl.com/repo',), - parse_url('svn+ssh://user:t3stpw@svn.testurl.com/repo')) - self.assertEqual( + ('svn+ssh://user:t3stpw@svn.testurl.com/repo', )) + self.check_parse_url( ('bob', '123abc', 'svn+ssh://bob@svn.testurl.com/repo',), - parse_url('svn+ssh://user:t3stpw@svn.testurl.com/repo', 'bob', '123abc')) - self.assertEqual( + ('svn+ssh://user:t3stpw@svn.testurl.com/repo', 'bob', '123abc', )) + self.check_parse_url( ('user2', None, 'svn+ssh://user2@svn.testurl.com/repo',), - parse_url('svn+ssh://user2@svn.testurl.com/repo')) - self.assertEqual( + ('svn+ssh://user2@svn.testurl.com/repo', )) + self.check_parse_url( ('bob', None, 'svn+ssh://bob@svn.testurl.com/repo',), - parse_url('svn+ssh://user2@svn.testurl.com/repo', 'bob')) + ('svn+ssh://user2@svn.testurl.com/repo', 'bob', )) def test_user_password_url(self): - self.assertEqual( + self.check_parse_url( ('joe', 't3stpw', 'https://svn.testurl.com/repo'), - parse_url('https://joe:t3stpw@svn.testurl.com/repo')) - self.assertEqual( + ('https://joe:t3stpw@svn.testurl.com/repo', )) + self.check_parse_url( ('bob', '123abc', 'https://svn.testurl.com/repo'), - parse_url('https://joe:t3stpw@svn.testurl.com/repo', 'bob', '123abc')) + ('https://joe:t3stpw@svn.testurl.com/repo', 'bob', '123abc', )) def test_url_rewriting(self): ui = test_util.ui.ui() ui.setconfig('hgsubversion', 'username', 'bob') repo = svnrepo.svnremoterepo(ui, 'svn+ssh://joe@foo/bar') self.assertEqual('svn+ssh://bob@foo/bar', repo.svnauth[0]) + self.assertEqual('svn+ssh://bob@foo/bar', repo.svnurl) repo = svnrepo.svnremoterepo(ui, 'svn+http://joe@foo/bar') self.assertEqual(('http://foo/bar', 'bob', None), repo.svnauth) + self.assertEqual('http://foo/bar', repo.svnurl) repo = svnrepo.svnremoterepo(ui, 'svn+https://joe@foo/bar') self.assertEqual(('https://foo/bar', 'bob', None), repo.svnauth) + self.assertEqual('https://foo/bar', repo.svnurl) def test_quoting(self): ui = self.ui() @@ -72,3 +75,11 @@ class TestSubversionUrls(test_util.TestBase): repo1 = svnrepo.svnremoterepo(ui, repo_url + subdir) repo2 = svnrepo.svnremoterepo(ui, repo_url + quoted_subdir) self.assertEqual(repo1.svnurl, repo2.svnurl) + + def check_parse_url(self, expected, args): + self.assertEqual(expected, parse_url(*args)) + if len(args) == 1: + repo = svnrepo.svnremoterepo(self.ui(), path=args[0]) + self.assertEqual(expected[2], repo.svnauth[0]) + self.assertEqual(expected[2], repo.svnurl) + diff --git a/tests/test_util.py b/tests/test_util.py index b24c35a..7c78c51 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -28,6 +28,7 @@ from mercurial import util as hgutil from mercurial import extensions from hgsubversion import compathacks +from hgsubversion import svnrepo from hgsubversion import svnwrap try: @@ -39,14 +40,12 @@ except ImportError: try: SkipTest = unittest.SkipTest except AttributeError: - try: - from unittest2 import SkipTest - except ImportError: - try: - from nose import SkipTest - except ImportError: - SkipTest = None + if 'nose' in sys.modules: + SkipTest = sys.modules['nose'].SkipTest + else: + SkipTest = None +from hgsubversion import svnwrap from hgsubversion import util from hgsubversion import svnwrap @@ -210,15 +209,25 @@ def getlocalpeer(repo): localrepo = repo return localrepo -def repolen(repo): +def repolen(repo, svnonly=False): """Naively calculate the amount of available revisions in a repository. this is usually equal to len(repo) -- except in the face of obsolete revisions. + + if svnonly is true, only count revisions converted from Subversion. """ # kind of nasty way of calculating the length, but fortunately, # our test repositories tend to be rather small - return len([r for r in repo]) + revs = set(repo) + + if obsolete: + revs -= obsolete.getrevs(repo, 'obsolete') + + if svnonly: + revs = set(r for r in revs if util.getsvnrev(repo[r])) + + return len(revs) def _makeskip(name, message): if SkipTest: @@ -284,10 +293,12 @@ def testui(stupid=False, layout='auto', startrev=0): u = ui.ui() bools = {True: 'true', False: 'false'} u.setconfig('ui', 'quiet', bools[True]) + u.setconfig('ui', 'username', 'automated tests') u.setconfig('extensions', 'hgsubversion', '') u.setconfig('hgsubversion', 'stupid', bools[stupid]) u.setconfig('hgsubversion', 'layout', layout) u.setconfig('hgsubversion', 'startrev', startrev) + u.setconfig('devel', 'all-warnings', True) return u def dispatch(cmd): @@ -534,12 +545,8 @@ class TestBase(unittest.TestCase): ''' path = self._makerepopath() assert not os.path.exists(path) - subprocess.call(['svnadmin', 'create', path,], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - inp = open(os.path.join(FIXTURES, fixture_name)) - proc = subprocess.Popen(['svnadmin', 'load', path,], stdin=inp, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - proc.communicate() + with open(os.path.join(FIXTURES, fixture_name)) as inp: + svnwrap.create_and_load(path, inp) return path def load_repo_tarball(self, fixture_name): @@ -596,7 +603,7 @@ class TestBase(unittest.TestCase): return hg.repository(testui(), self.wc_path) - def load_and_fetch(self, fixture_name, *args, **opts): + def load(self, fixture_name): if fixture_name.endswith('.svndump'): repo_path = self.load_svndump(fixture_name) elif fixture_name.endswith('tar.gz'): @@ -604,6 +611,10 @@ class TestBase(unittest.TestCase): else: assert False, 'Unknown fixture type' + return repo_path + + def load_and_fetch(self, fixture_name, *args, **opts): + repo_path = self.load(fixture_name) return self.fetch(repo_path, *args, **opts), repo_path def _load_fixture_and_fetch(self, *args, **kwargs): @@ -704,7 +715,8 @@ class TestBase(unittest.TestCase): changed + removed, filectxfn, 'an_author', - '2008-10-07 20:59:48 -0500') + '2008-10-07 20:59:48 -0500', + {'branch': parentctx.branch()}) nodeid = repo.commitctx(ctx) repo = self.repo hg.clean(repo, nodeid) @@ -773,5 +785,21 @@ files: {files} commands.log(_ui, repo, rev=None, template=templ, graph=True) return _ui.popbuffer() + def svnlog(self, repo=None): + '''log of the remote Subversion repository corresponding to repo + + In order to make the format suitable for direct comparison in + tests, we exclude dates and convert the path operations into + a tuple. + ''' + + if repo is None: + repo = self.repo + + return [(r.revnum, r.message, + dict((p, (op.action, op.copyfrom_path, int(op.copyfrom_rev))) + for (p, op) in r.paths.items())) + for r in svnrepo.svnremoterepo(repo.ui).svn.revisions()] + def draw(self, repo): sys.stdout.write(self.getgraph(repo)) diff --git a/tests/test_utility_commands.py b/tests/test_utility_commands.py index 5b03901..481c64b 100644 --- a/tests/test_utility_commands.py +++ b/tests/test_utility_commands.py @@ -128,10 +128,10 @@ class UtilityTests(test_util.TestBase): def test_missing_metadata(self): self._load_fixture_and_fetch('two_heads.svndump') - os.remove(self.repo.join('svn/branch_info')) + os.remove(self.repo.vfs.join('svn/branch_info')) svncommands.updatemeta(self.ui(), self.repo, []) - test_util.rmtree(self.repo.join('svn')) + test_util.rmtree(self.repo.vfs.join('svn')) self.assertRaises(hgutil.Abort, self.repo.svnmeta) self.assertRaises(hgutil.Abort, @@ -141,7 +141,7 @@ class UtilityTests(test_util.TestBase): svncommands.genignore, self.ui(), repo=self.repo, args=[]) - os.remove(self.repo.join('hgrc')) + os.remove(self.repo.vfs.join('hgrc')) self.assertRaises(hgutil.Abort, self.repo.svnmeta) self.assertRaises(hgutil.Abort, |