PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/test_externals.py

https://bitbucket.org/durin42/hgsubversion/
Python | 395 lines | 388 code | 6 blank | 1 comment | 2 complexity | 51baf13c53c2d1e3990ffb55fff49219 MD5 | raw file
Possible License(s): GPL-2.0
  1. import test_util
  2. import os, unittest, sys
  3. from mercurial import commands
  4. from mercurial import util as hgutil
  5. try:
  6. from mercurial import subrepo
  7. # require svnsubrepo and hg >= 1.7.1
  8. subrepo.svnsubrepo
  9. hgutil.checknlink
  10. except (ImportError, AttributeError), e:
  11. print >> sys.stderr, 'test_externals: skipping .hgsub tests'
  12. subrepo = None
  13. from hgsubversion import svnexternals
  14. class TestFetchExternals(test_util.TestBase):
  15. stupid_mode_tests = True
  16. def test_externalsfile(self):
  17. f = svnexternals.externalsfile()
  18. f['t1'] = 'dir1 -r10 svn://foobar'
  19. f['t 2'] = 'dir2 -r10 svn://foobar'
  20. f['t3'] = ['dir31 -r10 svn://foobar', 'dir32 -r10 svn://foobar']
  21. refext = """[t 2]
  22. dir2 -r10 svn://foobar
  23. [t1]
  24. dir1 -r10 svn://foobar
  25. [t3]
  26. dir31 -r10 svn://foobar
  27. dir32 -r10 svn://foobar
  28. """
  29. value = f.write()
  30. self.assertEqual(refext, value)
  31. f2 = svnexternals.externalsfile()
  32. f2.read(value)
  33. self.assertEqual(sorted(f), sorted(f2))
  34. for t in f:
  35. self.assertEqual(f[t], f2[t])
  36. def test_parsedefinitions(self):
  37. # Taken from svn book
  38. samples = [
  39. ('third-party/sounds http://svn.example.com/repos/sounds',
  40. ('third-party/sounds', None, 'http://svn.example.com/repos/sounds', None,
  41. 'third-party/sounds http://svn.example.com/repos/sounds')),
  42. ('third-party/skins -r148 http://svn.example.com/skinproj',
  43. ('third-party/skins', '148', 'http://svn.example.com/skinproj', None,
  44. 'third-party/skins -r{REV} http://svn.example.com/skinproj')),
  45. ('third-party/skins -r 148 http://svn.example.com/skinproj',
  46. ('third-party/skins', '148', 'http://svn.example.com/skinproj', None,
  47. 'third-party/skins -r {REV} http://svn.example.com/skinproj')),
  48. ('http://svn.example.com/repos/sounds third-party/sounds',
  49. ('third-party/sounds', None, 'http://svn.example.com/repos/sounds', None,
  50. 'http://svn.example.com/repos/sounds third-party/sounds')),
  51. ('-r148 http://svn.example.com/skinproj third-party/skins',
  52. ('third-party/skins', '148', 'http://svn.example.com/skinproj', None,
  53. '-r{REV} http://svn.example.com/skinproj third-party/skins')),
  54. ('-r 148 http://svn.example.com/skinproj third-party/skins',
  55. ('third-party/skins', '148', 'http://svn.example.com/skinproj', None,
  56. '-r {REV} http://svn.example.com/skinproj third-party/skins')),
  57. ('http://svn.example.com/skin-maker@21 third-party/skins/toolkit',
  58. ('third-party/skins/toolkit', None, 'http://svn.example.com/skin-maker', '21',
  59. 'http://svn.example.com/skin-maker@21 third-party/skins/toolkit')),
  60. ]
  61. for line, expected in samples:
  62. self.assertEqual(expected, svnexternals.parsedefinition(line))
  63. def test_externals(self):
  64. repo = self._load_fixture_and_fetch('externals.svndump')
  65. ref0 = """[.]
  66. ^/externals/project1 deps/project1
  67. """
  68. self.assertMultiLineEqual(ref0, repo[0]['.hgsvnexternals'].data())
  69. ref1 = """\
  70. [.]
  71. # A comment, then an empty line, then a blank line
  72. ^/externals/project1 deps/project1
  73. -r2 ^/externals/project2@2 deps/project2
  74. """
  75. self.assertMultiLineEqual(ref1, repo[1]['.hgsvnexternals'].data())
  76. ref2 = """[.]
  77. -r2 ^/externals/project2@2 deps/project2
  78. [subdir]
  79. ^/externals/project1 deps/project1
  80. [subdir2]
  81. ^/externals/project1 deps/project1
  82. """
  83. actual = repo[2]['.hgsvnexternals'].data()
  84. self.assertEqual(ref2, actual)
  85. ref3 = """[.]
  86. -r2 ^/externals/project2@2 deps/project2
  87. [subdir]
  88. ^/externals/project1 deps/project1
  89. """
  90. self.assertEqual(ref3, repo[3]['.hgsvnexternals'].data())
  91. ref4 = """[subdir]
  92. ^/externals/project1 deps/project1
  93. """
  94. self.assertEqual(ref4, repo[4]['.hgsvnexternals'].data())
  95. ref5 = """[.]
  96. -r2 ^/externals/project2@2 deps/project2
  97. [subdir2]
  98. ^/externals/project1 deps/project1
  99. """
  100. self.assertEqual(ref5, repo[5]['.hgsvnexternals'].data())
  101. ref6 = """[.]
  102. -r2 ^/externals/project2@2 deps/project2
  103. """
  104. self.assertEqual(ref6, repo[6]['.hgsvnexternals'].data())
  105. def test_updateexternals(self):
  106. def checkdeps(deps, nodeps, repo, rev=None):
  107. svnexternals.updateexternals(ui, [rev], repo)
  108. for d in deps:
  109. p = os.path.join(repo.root, d)
  110. self.assertTrue(os.path.isdir(p),
  111. 'missing: %s@%r' % (d, rev))
  112. for d in nodeps:
  113. p = os.path.join(repo.root, d)
  114. self.assertTrue(not os.path.isdir(p),
  115. 'unexpected: %s@%r' % (d, rev))
  116. ui = self.ui()
  117. repo = self._load_fixture_and_fetch('externals.svndump')
  118. commands.update(ui, repo)
  119. checkdeps(['deps/project1'], [], repo, 0)
  120. checkdeps(['deps/project1', 'deps/project2'], [], repo, 1)
  121. checkdeps(['subdir/deps/project1', 'subdir2/deps/project1',
  122. 'deps/project2'],
  123. ['deps/project1'], repo, 2)
  124. checkdeps(['subdir/deps/project1', 'deps/project2'],
  125. ['subdir2/deps/project1'], repo, 3)
  126. checkdeps(['subdir/deps/project1'], ['deps/project2'], repo, 4)
  127. def test_hgsub(self):
  128. if subrepo is None:
  129. return
  130. repo = self._load_fixture_and_fetch('externals.svndump',
  131. externals='subrepos')
  132. self.assertEqual("""\
  133. deps/project1 = [hgsubversion] :^/externals/project1 deps/project1
  134. """, repo[0]['.hgsub'].data())
  135. self.assertEqual("""\
  136. HEAD deps/project1
  137. """, repo[0]['.hgsubstate'].data())
  138. self.assertEqual("""\
  139. deps/project1 = [hgsubversion] :^/externals/project1 deps/project1
  140. deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
  141. """, repo[1]['.hgsub'].data())
  142. self.assertEqual("""\
  143. HEAD deps/project1
  144. 2 deps/project2
  145. """, repo[1]['.hgsubstate'].data())
  146. self.assertEqual("""\
  147. deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
  148. subdir/deps/project1 = [hgsubversion] subdir:^/externals/project1 deps/project1
  149. subdir2/deps/project1 = [hgsubversion] subdir2:^/externals/project1 deps/project1
  150. """, repo[2]['.hgsub'].data())
  151. self.assertEqual("""\
  152. 2 deps/project2
  153. HEAD subdir/deps/project1
  154. HEAD subdir2/deps/project1
  155. """, repo[2]['.hgsubstate'].data())
  156. self.assertMultiLineEqual("""\
  157. deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
  158. subdir/deps/project1 = [hgsubversion] subdir:^/externals/project1 deps/project1
  159. """, repo[3]['.hgsub'].data())
  160. self.assertEqual("""\
  161. 2 deps/project2
  162. HEAD subdir/deps/project1
  163. """, repo[3]['.hgsubstate'].data())
  164. self.assertEqual("""\
  165. subdir/deps/project1 = [hgsubversion] subdir:^/externals/project1 deps/project1
  166. """, repo[4]['.hgsub'].data())
  167. self.assertEqual("""\
  168. HEAD subdir/deps/project1
  169. """, repo[4]['.hgsubstate'].data())
  170. self.assertEqual("""\
  171. deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
  172. subdir2/deps/project1 = [hgsubversion] subdir2:^/externals/project1 deps/project1
  173. """, repo[5]['.hgsub'].data())
  174. self.assertEqual("""\
  175. 2 deps/project2
  176. HEAD subdir2/deps/project1
  177. """, repo[5]['.hgsubstate'].data())
  178. self.assertEqual("""\
  179. deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
  180. """, repo[6]['.hgsub'].data())
  181. self.assertEqual("""\
  182. 2 deps/project2
  183. """, repo[6]['.hgsubstate'].data())
  184. def test_ignore(self):
  185. repo = self._load_fixture_and_fetch('externals.svndump',
  186. externals='ignore')
  187. for rev in repo:
  188. ctx = repo[rev]
  189. self.assertTrue('.hgsvnexternals' not in ctx)
  190. self.assertTrue('.hgsub' not in ctx)
  191. self.assertTrue('.hgsubstate' not in ctx)
  192. def test_updatehgsub(self):
  193. def checkdeps(ui, repo, rev, deps, nodeps):
  194. commands.update(ui, repo, node=str(rev))
  195. for d in deps:
  196. p = os.path.join(repo.root, d)
  197. self.assertTrue(os.path.isdir(p),
  198. 'missing: %s@%r' % (d, repo[None].rev()))
  199. for d in nodeps:
  200. p = os.path.join(repo.root, d)
  201. self.assertTrue(not os.path.isdir(p),
  202. 'unexpected: %s@%r' % (d, repo[None].rev()))
  203. if subrepo is None:
  204. return
  205. ui = self.ui()
  206. repo = self._load_fixture_and_fetch('externals.svndump',
  207. externals='subrepos')
  208. checkdeps(ui, repo, 0, ['deps/project1'], [])
  209. checkdeps(ui, repo, 1, ['deps/project1', 'deps/project2'], [])
  210. checkdeps(ui, repo, 2, ['subdir/deps/project1', 'subdir2/deps/project1',
  211. 'deps/project2'],
  212. ['deps/project1'])
  213. checkdeps(ui, repo, 3, ['subdir/deps/project1', 'deps/project2'],
  214. ['subdir2/deps/project1'])
  215. checkdeps(ui, repo, 4, ['subdir/deps/project1'], ['deps/project2'])
  216. # Test update --clean, used to crash
  217. repo.wwrite('subdir/deps/project1/a', 'foobar', '')
  218. commands.update(ui, repo, node='4', clean=True)
  219. def test_mergeexternals(self):
  220. if subrepo is None:
  221. return
  222. repo = self._load_fixture_and_fetch('mergeexternals.svndump',
  223. externals='subrepos')
  224. # Check merged directories externals are fine
  225. self.assertEqual("""\
  226. d1/ext = [hgsubversion] d1:^/trunk/common/ext ext
  227. d2/ext = [hgsubversion] d2:^/trunk/common/ext ext
  228. d3/ext3 = [hgsubversion] d3:^/trunk/common/ext ext3
  229. """, repo['tip']['.hgsub'].data())
  230. class TestPushExternals(test_util.TestBase):
  231. stupid_mode_tests = True
  232. obsolete_mode_tests = True
  233. def test_push_externals(self):
  234. repo = self._load_fixture_and_fetch('pushexternals.svndump')
  235. # Add a new reference on an existing and non-existing directory
  236. changes = [
  237. ('.hgsvnexternals', '.hgsvnexternals',
  238. """[dir]
  239. ../externals/project2 deps/project2
  240. [subdir1]
  241. ../externals/project1 deps/project1
  242. [subdir2]
  243. ../externals/project2 deps/project2
  244. """),
  245. ('subdir1/a', 'subdir1/a', 'a'),
  246. ('subdir2/a', 'subdir2/a', 'a'),
  247. ]
  248. self.commitchanges(changes)
  249. self.pushrevisions()
  250. self.assertchanges(changes, self.repo['tip'])
  251. # Remove all references from one directory, add a new one
  252. # to the other (test multiline entries)
  253. changes = [
  254. ('.hgsvnexternals', '.hgsvnexternals',
  255. """[subdir1]
  256. ../externals/project1 deps/project1
  257. ../externals/project2 deps/project2
  258. """),
  259. # This removal used to trigger the parent directory removal
  260. ('subdir1/a', None, None),
  261. ]
  262. self.commitchanges(changes)
  263. self.pushrevisions()
  264. self.assertchanges(changes, self.repo['tip'])
  265. # Check subdir2/a is still there even if the externals were removed
  266. self.assertTrue('subdir2/a' in self.repo['tip'])
  267. self.assertTrue('subdir1/a' not in self.repo['tip'])
  268. # Test externals removal
  269. changes = [
  270. ('.hgsvnexternals', None, None),
  271. ]
  272. self.commitchanges(changes)
  273. self.pushrevisions()
  274. self.assertchanges(changes, self.repo['tip'])
  275. def test_push_hgsub(self):
  276. if subrepo is None:
  277. return
  278. repo, repo_path = self.load_and_fetch('pushexternals.svndump',
  279. externals='subrepos')
  280. # Add a new reference on an existing and non-existing directory
  281. changes = [
  282. ('.hgsub', '.hgsub', """\
  283. dir/deps/project2 = [hgsubversion] dir:^/externals/project2 deps/project2
  284. subdir1/deps/project1 = [hgsubversion] subdir1:^/externals/project1 deps/project1
  285. subdir2/deps/project2 = [hgsubversion] subdir2:^/externals/project2 deps/project2
  286. """),
  287. ('.hgsubstate', '.hgsubstate', """\
  288. HEAD dir/deps/project2
  289. HEAD subdir1/deps/project1
  290. HEAD subdir2/deps/project2
  291. """),
  292. ('subdir1/a', 'subdir1/a', 'a'),
  293. ('subdir2/a', 'subdir2/a', 'a'),
  294. ]
  295. self.svnco(repo_path, 'externals/project2', '2', 'dir/deps/project2')
  296. self.svnco(repo_path, 'externals/project1', '2', 'subdir1/deps/project1')
  297. self.svnco(repo_path, 'externals/project2', '2', 'subdir2/deps/project2')
  298. self.commitchanges(changes)
  299. self.pushrevisions()
  300. self.assertchanges(changes, self.repo['tip'])
  301. # Check .hgsub and .hgsubstate were not pushed
  302. self.assertEqual(['dir', 'subdir1', 'subdir1/a', 'subdir2',
  303. 'subdir2/a'], test_util.svnls(repo_path, 'trunk'))
  304. # Remove all references from one directory, add a new one
  305. # to the other (test multiline entries)
  306. changes = [
  307. ('.hgsub', '.hgsub', """\
  308. subdir1/deps/project1 = [hgsubversion] subdir1:^/externals/project1 deps/project1
  309. subdir1/deps/project2 = [hgsubversion] subdir1:^/externals/project2 deps/project2
  310. """),
  311. ('.hgsubstate', '.hgsubstate', """\
  312. HEAD subdir1/deps/project1
  313. HEAD subdir1/deps/project2
  314. """),
  315. # This removal used to trigger the parent directory removal
  316. ('subdir1/a', None, None),
  317. ]
  318. self.svnco(repo_path, 'externals/project1', '2', 'subdir1/deps/project1')
  319. self.svnco(repo_path, 'externals/project2', '2', 'subdir1/deps/project2')
  320. self.commitchanges(changes)
  321. self.pushrevisions()
  322. self.assertchanges(changes, self.repo['tip'])
  323. # Check subdir2/a is still there even if the externals were removed
  324. self.assertTrue('subdir2/a' in self.repo['tip'])
  325. self.assertTrue('subdir1/a' not in self.repo['tip'])
  326. # Move the externals so they are defined on the base directory,
  327. # this used to cause full branch removal when deleting the .hgsub
  328. changes = [
  329. ('.hgsub', '.hgsub', """\
  330. subdir1/deps/project1 = [hgsubversion] :^/externals/project1 subdir1/deps/project1
  331. """),
  332. ('.hgsubstate', '.hgsubstate', """\
  333. HEAD subdir1/deps/project1
  334. """),
  335. ]
  336. self.commitchanges(changes)
  337. self.pushrevisions()
  338. self.assertchanges(changes, self.repo['tip'])
  339. # Test externals removal
  340. changes = [
  341. ('.hgsub', None, None),
  342. ('.hgsubstate', None, None),
  343. ]
  344. self.commitchanges(changes)
  345. self.pushrevisions()
  346. self.assertchanges(changes, self.repo['tip'])