sapling/tests/test-hgsubversion-externals.py
Jun Wu 9dc21f8d0b codemod: import from the edenscm package
Summary:
D13853115 adds `edenscm/` to `sys.path` and code still uses `import mercurial`.
That has nasty problems if both `import mercurial` and
`import edenscm.mercurial` are used, because Python would think `mercurial.foo`
and `edenscm.mercurial.foo` are different modules so code like
`try: ... except mercurial.error.Foo: ...`, or `isinstance(x, mercurial.foo.Bar)`
would fail to handle the `edenscm.mercurial` version. There are also some
module-level states (ex. `extensions._extensions`) that would cause trouble if
they have multiple versions in a single process.

Change imports to use the `edenscm` so ideally the `mercurial` is no longer
imported at all. Add checks in extensions.py to catch unexpected extensions
importing modules from the old (wrong) locations when running tests.

Reviewed By: phillco

Differential Revision: D13868981

fbshipit-source-id: f4e2513766957fd81d85407994f7521a08e4de48
2019-01-29 17:25:32 -08:00

525 lines
16 KiB
Python

# no-check-code -- see T24862348
import os
import test_hgsubversion_util
from edenscm.hgext.hgsubversion import svnexternals
from edenscm.mercurial import commands, subrepo
class TestFetchExternals(test_hgsubversion_util.TestBase):
stupid_mode_tests = True
def test_externalsfile(self):
f = svnexternals.externalsfile()
f["t1"] = "dir1 -r10 svn://foobar"
f["t 2"] = "dir2 -r10 svn://foobar"
f["t3"] = ["dir31 -r10 svn://foobar", "dir32 -r10 svn://foobar"]
refext = """[t 2]
dir2 -r10 svn://foobar
[t1]
dir1 -r10 svn://foobar
[t3]
dir31 -r10 svn://foobar
dir32 -r10 svn://foobar
"""
value = f.write()
self.assertEqual(refext, value)
f2 = svnexternals.externalsfile()
f2.read(value)
self.assertEqual(sorted(f), sorted(f2))
for t in f:
self.assertEqual(f[t], f2[t])
def test_parsedefinitions(self):
# Taken from svn book
samples = [
(
"third-party/sounds http://svn.example.com/repos/sounds",
(
"third-party/sounds",
None,
"http://svn.example.com/repos/sounds",
None,
"third-party/sounds http://svn.example.com/repos/sounds",
),
),
(
"third-party/skins -r148 http://svn.example.com/skinproj",
(
"third-party/skins",
"148",
"http://svn.example.com/skinproj",
None,
"third-party/skins -r{REV} http://svn.example.com/skinproj",
),
),
(
"third-party/skins -r 148 http://svn.example.com/skinproj",
(
"third-party/skins",
"148",
"http://svn.example.com/skinproj",
None,
"third-party/skins -r {REV} http://svn.example.com/skinproj",
),
),
(
"http://svn.example.com/repos/sounds third-party/sounds",
(
"third-party/sounds",
None,
"http://svn.example.com/repos/sounds",
None,
"http://svn.example.com/repos/sounds third-party/sounds",
),
),
(
"-r148 http://svn.example.com/skinproj third-party/skins",
(
"third-party/skins",
"148",
"http://svn.example.com/skinproj",
None,
"-r{REV} http://svn.example.com/skinproj third-party/skins",
),
),
(
"-r 148 http://svn.example.com/skinproj third-party/skins",
(
"third-party/skins",
"148",
"http://svn.example.com/skinproj",
None,
"-r {REV} http://svn.example.com/skinproj third-party/skins",
),
),
(
"http://svn.example.com/skin-maker@21 third-party/skins/toolkit",
(
"third-party/skins/toolkit",
None,
"http://svn.example.com/skin-maker",
"21",
"http://svn.example.com/skin-maker@21 third-party/skins/toolkit",
),
),
]
for line, expected in samples:
self.assertEqual(expected, svnexternals.parsedefinition(line))
def test_externals(self):
repo = self._load_fixture_and_fetch("externals.svndump")
ref0 = """[.]
^/externals/project1 deps/project1
"""
self.assertMultiLineEqual(ref0, repo[0][".hgsvnexternals"].data())
ref1 = """\
[.]
# A comment, then an empty line, then a blank line
^/externals/project1 deps/project1
-r2 ^/externals/project2@2 deps/project2
"""
self.assertMultiLineEqual(ref1, repo[1][".hgsvnexternals"].data())
ref2 = """[.]
-r2 ^/externals/project2@2 deps/project2
[subdir]
^/externals/project1 deps/project1
[subdir2]
^/externals/project1 deps/project1
"""
actual = repo[2][".hgsvnexternals"].data()
self.assertEqual(ref2, actual)
ref3 = """[.]
-r2 ^/externals/project2@2 deps/project2
[subdir]
^/externals/project1 deps/project1
"""
self.assertEqual(ref3, repo[3][".hgsvnexternals"].data())
ref4 = """[subdir]
^/externals/project1 deps/project1
"""
self.assertEqual(ref4, repo[4][".hgsvnexternals"].data())
ref5 = """[.]
-r2 ^/externals/project2@2 deps/project2
[subdir2]
^/externals/project1 deps/project1
"""
self.assertEqual(ref5, repo[5][".hgsvnexternals"].data())
ref6 = """[.]
-r2 ^/externals/project2@2 deps/project2
"""
self.assertEqual(ref6, repo[6][".hgsvnexternals"].data())
def test_updateexternals(self):
def checkdeps(deps, nodeps, repo, rev=None):
svnexternals.updateexternals(ui, [rev], repo)
for d in deps:
p = os.path.join(repo.root, d)
self.assertTrue(os.path.isdir(p), "missing: %s@%r" % (d, rev))
for d in nodeps:
p = os.path.join(repo.root, d)
self.assertTrue(not os.path.isdir(p), "unexpected: %s@%r" % (d, rev))
ui = self.ui()
repo = self._load_fixture_and_fetch("externals.svndump")
commands.update(ui, repo)
checkdeps(["deps/project1"], [], repo, 0)
checkdeps(["deps/project1", "deps/project2"], [], repo, 1)
checkdeps(
["subdir/deps/project1", "subdir2/deps/project1", "deps/project2"],
["deps/project1"],
repo,
2,
)
checkdeps(
["subdir/deps/project1", "deps/project2"],
["subdir2/deps/project1"],
repo,
3,
)
checkdeps(["subdir/deps/project1"], ["deps/project2"], repo, 4)
def test_hgsub(self):
if subrepo is None:
return
repo = self._load_fixture_and_fetch("externals.svndump", externals="subrepos")
self.assertEqual(
"""\
deps/project1 = [hgsubversion] :^/externals/project1 deps/project1
""",
repo[0][".hgsub"].data(),
)
self.assertEqual(
"""\
HEAD deps/project1
""",
repo[0][".hgsubstate"].data(),
)
self.assertEqual(
"""\
deps/project1 = [hgsubversion] :^/externals/project1 deps/project1
deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
""",
repo[1][".hgsub"].data(),
)
self.assertEqual(
"""\
HEAD deps/project1
2 deps/project2
""",
repo[1][".hgsubstate"].data(),
)
self.assertEqual(
"""\
deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
subdir/deps/project1 = [hgsubversion] subdir:^/externals/project1 deps/project1
subdir2/deps/project1 = [hgsubversion] subdir2:^/externals/project1 deps/project1
""",
repo[2][".hgsub"].data(),
)
self.assertEqual(
"""\
2 deps/project2
HEAD subdir/deps/project1
HEAD subdir2/deps/project1
""",
repo[2][".hgsubstate"].data(),
)
self.assertMultiLineEqual(
"""\
deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
subdir/deps/project1 = [hgsubversion] subdir:^/externals/project1 deps/project1
""",
repo[3][".hgsub"].data(),
)
self.assertEqual(
"""\
2 deps/project2
HEAD subdir/deps/project1
""",
repo[3][".hgsubstate"].data(),
)
self.assertEqual(
"""\
subdir/deps/project1 = [hgsubversion] subdir:^/externals/project1 deps/project1
""",
repo[4][".hgsub"].data(),
)
self.assertEqual(
"""\
HEAD subdir/deps/project1
""",
repo[4][".hgsubstate"].data(),
)
self.assertEqual(
"""\
deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
subdir2/deps/project1 = [hgsubversion] subdir2:^/externals/project1 deps/project1
""",
repo[5][".hgsub"].data(),
)
self.assertEqual(
"""\
2 deps/project2
HEAD subdir2/deps/project1
""",
repo[5][".hgsubstate"].data(),
)
self.assertEqual(
"""\
deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
""",
repo[6][".hgsub"].data(),
)
self.assertEqual(
"""\
2 deps/project2
""",
repo[6][".hgsubstate"].data(),
)
def test_ignore(self):
repo = self._load_fixture_and_fetch("externals.svndump", externals="ignore")
for rev in repo:
ctx = repo[rev]
self.assertTrue(".hgsvnexternals" not in ctx)
self.assertTrue(".hgsub" not in ctx)
self.assertTrue(".hgsubstate" not in ctx)
def test_updatehgsub(self):
def checkdeps(ui, repo, rev, deps, nodeps):
commands.update(ui, repo, node=str(rev))
for d in deps:
p = os.path.join(repo.root, d)
self.assertTrue(
os.path.isdir(p), "missing: %s@%r" % (d, repo[None].rev())
)
for d in nodeps:
p = os.path.join(repo.root, d)
self.assertTrue(
not os.path.isdir(p), "unexpected: %s@%r" % (d, repo[None].rev())
)
if subrepo is None:
return
ui = self.ui()
repo = self._load_fixture_and_fetch("externals.svndump", externals="subrepos")
checkdeps(ui, repo, 0, ["deps/project1"], [])
checkdeps(ui, repo, 1, ["deps/project1", "deps/project2"], [])
checkdeps(
ui,
repo,
2,
["subdir/deps/project1", "subdir2/deps/project1", "deps/project2"],
["deps/project1"],
)
checkdeps(
ui,
repo,
3,
["subdir/deps/project1", "deps/project2"],
["subdir2/deps/project1"],
)
checkdeps(ui, repo, 4, ["subdir/deps/project1"], ["deps/project2"])
# Test update --clean, used to crash
repo.wwrite("subdir/deps/project1/a", "foobar", "")
commands.update(ui, repo, node="4", clean=True)
def test_mergeexternals(self):
if subrepo is None:
return
repo = self._load_fixture_and_fetch(
"mergeexternals.svndump", externals="subrepos"
)
# Check merged directories externals are fine
self.assertEqual(
"""\
d1/ext = [hgsubversion] d1:^/trunk/common/ext ext
d2/ext = [hgsubversion] d2:^/trunk/common/ext ext
d3/ext3 = [hgsubversion] d3:^/trunk/common/ext ext3
""",
repo["tip"][".hgsub"].data(),
)
class TestPushExternals(test_hgsubversion_util.TestBase):
stupid_mode_tests = True
obsolete_mode_tests = True
def test_push_externals(self):
self._load_fixture_and_fetch("pushexternals.svndump")
# Add a new reference on an existing and non-existing directory
changes = [
(
".hgsvnexternals",
".hgsvnexternals",
"""[dir]
../externals/project2 deps/project2
[subdir1]
../externals/project1 deps/project1
[subdir2]
../externals/project2 deps/project2
""",
),
("subdir1/a", "subdir1/a", "a"),
("subdir2/a", "subdir2/a", "a"),
]
self.commitchanges(changes)
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
# Remove all references from one directory, add a new one
# to the other (test multiline entries)
changes = [
(
".hgsvnexternals",
".hgsvnexternals",
"""[subdir1]
../externals/project1 deps/project1
../externals/project2 deps/project2
""",
),
# This removal used to trigger the parent directory removal
("subdir1/a", None, None),
]
self.commitchanges(changes)
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
# Check subdir2/a is still there even if the externals were removed
self.assertTrue("subdir2/a" in self.repo["tip"])
self.assertTrue("subdir1/a" not in self.repo["tip"])
# Test externals removal
changes = [(".hgsvnexternals", None, None)]
self.commitchanges(changes)
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
def test_push_hgsub(self):
if subrepo is None:
return
repo, repo_path = self.load_and_fetch(
"pushexternals.svndump", externals="subrepos"
)
# Add a new reference on an existing and non-existing directory
changes = [
(
".hgsub",
".hgsub",
"""\
dir/deps/project2 = [hgsubversion] dir:^/externals/project2 deps/project2
subdir1/deps/project1 = [hgsubversion] subdir1:^/externals/project1 deps/project1
subdir2/deps/project2 = [hgsubversion] subdir2:^/externals/project2 deps/project2
""",
),
(
".hgsubstate",
".hgsubstate",
"""\
HEAD dir/deps/project2
HEAD subdir1/deps/project1
HEAD subdir2/deps/project2
""",
),
("subdir1/a", "subdir1/a", "a"),
("subdir2/a", "subdir2/a", "a"),
]
self.svnco(repo_path, "externals/project2", "2", "dir/deps/project2")
self.svnco(repo_path, "externals/project1", "2", "subdir1/deps/project1")
self.svnco(repo_path, "externals/project2", "2", "subdir2/deps/project2")
self.commitchanges(changes)
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
# Check .hgsub and .hgsubstate were not pushed
self.assertEqual(
["dir", "subdir1", "subdir1/a", "subdir2", "subdir2/a"],
test_hgsubversion_util.svnls(repo_path, "trunk"),
)
# Remove all references from one directory, add a new one
# to the other (test multiline entries)
changes = [
(
".hgsub",
".hgsub",
"""\
subdir1/deps/project1 = [hgsubversion] subdir1:^/externals/project1 deps/project1
subdir1/deps/project2 = [hgsubversion] subdir1:^/externals/project2 deps/project2
""",
),
(
".hgsubstate",
".hgsubstate",
"""\
HEAD subdir1/deps/project1
HEAD subdir1/deps/project2
""",
),
# This removal used to trigger the parent directory removal
("subdir1/a", None, None),
]
self.svnco(repo_path, "externals/project1", "2", "subdir1/deps/project1")
self.svnco(repo_path, "externals/project2", "2", "subdir1/deps/project2")
self.commitchanges(changes)
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
# Check subdir2/a is still there even if the externals were removed
self.assertTrue("subdir2/a" in self.repo["tip"])
self.assertTrue("subdir1/a" not in self.repo["tip"])
# Move the externals so they are defined on the base directory,
# this used to cause full branch removal when deleting the .hgsub
changes = [
(
".hgsub",
".hgsub",
"""\
subdir1/deps/project1 = [hgsubversion] :^/externals/project1 subdir1/deps/project1
""",
),
(
".hgsubstate",
".hgsubstate",
"""\
HEAD subdir1/deps/project1
""",
),
]
self.commitchanges(changes)
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
# Test externals removal
changes = [(".hgsub", None, None), (".hgsubstate", None, None)]
self.commitchanges(changes)
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
if __name__ == "__main__":
import silenttestrunner
silenttestrunner.main(__name__)