##// END OF EJS Templates
tests: add repository size tests
domruf -
r5770:43d23fa8 stable
parent child Browse files
Show More
@@ -1,834 +1,850 b''
1
1
2 import os
2 import os
3 import sys
3 import sys
4 import mock
4 import mock
5 import datetime
5 import datetime
6 import urllib2
6 import urllib2
7 from kallithea.lib.vcs.backends.git import GitRepository, GitChangeset
7 from kallithea.lib.vcs.backends.git import GitRepository, GitChangeset
8 from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
8 from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
9 from kallithea.lib.vcs.nodes import NodeKind, FileNode, DirNode, NodeState
9 from kallithea.lib.vcs.nodes import NodeKind, FileNode, DirNode, NodeState
10 from kallithea.lib.vcs.utils.compat import unittest
10 from kallithea.lib.vcs.utils.compat import unittest
11 from kallithea.model.scm import ScmModel
11 from kallithea.model.scm import ScmModel
12 from kallithea.tests.vcs.base import _BackendTestMixin
12 from kallithea.tests.vcs.base import _BackendTestMixin
13 from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, get_new_dir
13 from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, get_new_dir
14
14
15
15
16 class GitRepositoryTest(unittest.TestCase):
16 class GitRepositoryTest(unittest.TestCase):
17
17
18 def __check_for_existing_repo(self):
18 def __check_for_existing_repo(self):
19 if os.path.exists(TEST_GIT_REPO_CLONE):
19 if os.path.exists(TEST_GIT_REPO_CLONE):
20 self.fail('Cannot test git clone repo as location %s already '
20 self.fail('Cannot test git clone repo as location %s already '
21 'exists. You should manually remove it first.'
21 'exists. You should manually remove it first.'
22 % TEST_GIT_REPO_CLONE)
22 % TEST_GIT_REPO_CLONE)
23
23
24 def setUp(self):
24 def setUp(self):
25 self.repo = GitRepository(TEST_GIT_REPO)
25 self.repo = GitRepository(TEST_GIT_REPO)
26
26
27 def test_wrong_repo_path(self):
27 def test_wrong_repo_path(self):
28 wrong_repo_path = '/tmp/errorrepo'
28 wrong_repo_path = '/tmp/errorrepo'
29 self.assertRaises(RepositoryError, GitRepository, wrong_repo_path)
29 self.assertRaises(RepositoryError, GitRepository, wrong_repo_path)
30
30
31 def test_git_cmd_injection(self):
31 def test_git_cmd_injection(self):
32 repo_inject_path = TEST_GIT_REPO + '; echo "Cake";'
32 repo_inject_path = TEST_GIT_REPO + '; echo "Cake";'
33 with self.assertRaises(urllib2.URLError):
33 with self.assertRaises(urllib2.URLError):
34 # Should fail because URL will contain the parts after ; too
34 # Should fail because URL will contain the parts after ; too
35 urlerror_fail_repo = GitRepository(get_new_dir('injection-repo'), src_url=repo_inject_path, update_after_clone=True, create=True)
35 urlerror_fail_repo = GitRepository(get_new_dir('injection-repo'), src_url=repo_inject_path, update_after_clone=True, create=True)
36
36
37 with self.assertRaises(RepositoryError):
37 with self.assertRaises(RepositoryError):
38 # Should fail on direct clone call, which as of this writing does not happen outside of class
38 # Should fail on direct clone call, which as of this writing does not happen outside of class
39 clone_fail_repo = GitRepository(get_new_dir('injection-repo'), create=True)
39 clone_fail_repo = GitRepository(get_new_dir('injection-repo'), create=True)
40 clone_fail_repo.clone(repo_inject_path, update_after_clone=True,)
40 clone_fail_repo.clone(repo_inject_path, update_after_clone=True,)
41
41
42 # Verify correct quoting of evil characters that should work on posix file systems
42 # Verify correct quoting of evil characters that should work on posix file systems
43 if sys.platform == 'win32':
43 if sys.platform == 'win32':
44 # windows does not allow '"' in dir names
44 # windows does not allow '"' in dir names
45 tricky_path = get_new_dir("tricky-path-repo-$'`")
45 tricky_path = get_new_dir("tricky-path-repo-$'`")
46 else:
46 else:
47 tricky_path = get_new_dir("tricky-path-repo-$'\"`")
47 tricky_path = get_new_dir("tricky-path-repo-$'\"`")
48 successfully_cloned = GitRepository(tricky_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True)
48 successfully_cloned = GitRepository(tricky_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True)
49 # Repo should have been created
49 # Repo should have been created
50 self.assertFalse(successfully_cloned._repo.bare)
50 self.assertFalse(successfully_cloned._repo.bare)
51
51
52 if sys.platform == 'win32':
52 if sys.platform == 'win32':
53 # windows does not allow '"' in dir names
53 # windows does not allow '"' in dir names
54 tricky_path_2 = get_new_dir("tricky-path-2-repo-$'`")
54 tricky_path_2 = get_new_dir("tricky-path-2-repo-$'`")
55 else:
55 else:
56 tricky_path_2 = get_new_dir("tricky-path-2-repo-$'\"`")
56 tricky_path_2 = get_new_dir("tricky-path-2-repo-$'\"`")
57 successfully_cloned2 = GitRepository(tricky_path_2, src_url=tricky_path, bare=True, create=True)
57 successfully_cloned2 = GitRepository(tricky_path_2, src_url=tricky_path, bare=True, create=True)
58 # Repo should have been created and thus used correct quoting for clone
58 # Repo should have been created and thus used correct quoting for clone
59 self.assertTrue(successfully_cloned2._repo.bare)
59 self.assertTrue(successfully_cloned2._repo.bare)
60
60
61 # Should pass because URL has been properly quoted
61 # Should pass because URL has been properly quoted
62 successfully_cloned.pull(tricky_path_2)
62 successfully_cloned.pull(tricky_path_2)
63 successfully_cloned2.fetch(tricky_path)
63 successfully_cloned2.fetch(tricky_path)
64
64
65 def test_repo_create_with_spaces_in_path(self):
65 def test_repo_create_with_spaces_in_path(self):
66 repo_path = get_new_dir("path with spaces")
66 repo_path = get_new_dir("path with spaces")
67 repo = GitRepository(repo_path, src_url=None, bare=True, create=True)
67 repo = GitRepository(repo_path, src_url=None, bare=True, create=True)
68 # Repo should have been created
68 # Repo should have been created
69 self.assertTrue(repo._repo.bare)
69 self.assertTrue(repo._repo.bare)
70
70
71 def test_repo_clone(self):
71 def test_repo_clone(self):
72 self.__check_for_existing_repo()
72 self.__check_for_existing_repo()
73 repo = GitRepository(TEST_GIT_REPO)
73 repo = GitRepository(TEST_GIT_REPO)
74 repo_clone = GitRepository(TEST_GIT_REPO_CLONE,
74 repo_clone = GitRepository(TEST_GIT_REPO_CLONE,
75 src_url=TEST_GIT_REPO, create=True, update_after_clone=True)
75 src_url=TEST_GIT_REPO, create=True, update_after_clone=True)
76 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
76 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
77 # Checking hashes of changesets should be enough
77 # Checking hashes of changesets should be enough
78 for changeset in repo.get_changesets():
78 for changeset in repo.get_changesets():
79 raw_id = changeset.raw_id
79 raw_id = changeset.raw_id
80 self.assertEqual(raw_id, repo_clone.get_changeset(raw_id).raw_id)
80 self.assertEqual(raw_id, repo_clone.get_changeset(raw_id).raw_id)
81
81
82 def test_repo_clone_with_spaces_in_path(self):
82 def test_repo_clone_with_spaces_in_path(self):
83 repo_path = get_new_dir("path with spaces")
83 repo_path = get_new_dir("path with spaces")
84 successfully_cloned = GitRepository(repo_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True)
84 successfully_cloned = GitRepository(repo_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True)
85 # Repo should have been created
85 # Repo should have been created
86 self.assertFalse(successfully_cloned._repo.bare)
86 self.assertFalse(successfully_cloned._repo.bare)
87
87
88 successfully_cloned.pull(TEST_GIT_REPO)
88 successfully_cloned.pull(TEST_GIT_REPO)
89 self.repo.fetch(repo_path)
89 self.repo.fetch(repo_path)
90
90
91 def test_repo_clone_without_create(self):
91 def test_repo_clone_without_create(self):
92 self.assertRaises(RepositoryError, GitRepository,
92 self.assertRaises(RepositoryError, GitRepository,
93 TEST_GIT_REPO_CLONE + '_wo_create', src_url=TEST_GIT_REPO)
93 TEST_GIT_REPO_CLONE + '_wo_create', src_url=TEST_GIT_REPO)
94
94
95 def test_repo_clone_with_update(self):
95 def test_repo_clone_with_update(self):
96 repo = GitRepository(TEST_GIT_REPO)
96 repo = GitRepository(TEST_GIT_REPO)
97 clone_path = TEST_GIT_REPO_CLONE + '_with_update'
97 clone_path = TEST_GIT_REPO_CLONE + '_with_update'
98 repo_clone = GitRepository(clone_path,
98 repo_clone = GitRepository(clone_path,
99 create=True, src_url=TEST_GIT_REPO, update_after_clone=True)
99 create=True, src_url=TEST_GIT_REPO, update_after_clone=True)
100 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
100 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
101
101
102 #check if current workdir was updated
102 #check if current workdir was updated
103 fpath = os.path.join(clone_path, 'MANIFEST.in')
103 fpath = os.path.join(clone_path, 'MANIFEST.in')
104 self.assertEqual(True, os.path.isfile(fpath),
104 self.assertEqual(True, os.path.isfile(fpath),
105 'Repo was cloned and updated but file %s could not be found'
105 'Repo was cloned and updated but file %s could not be found'
106 % fpath)
106 % fpath)
107
107
108 def test_repo_clone_without_update(self):
108 def test_repo_clone_without_update(self):
109 repo = GitRepository(TEST_GIT_REPO)
109 repo = GitRepository(TEST_GIT_REPO)
110 clone_path = TEST_GIT_REPO_CLONE + '_without_update'
110 clone_path = TEST_GIT_REPO_CLONE + '_without_update'
111 repo_clone = GitRepository(clone_path,
111 repo_clone = GitRepository(clone_path,
112 create=True, src_url=TEST_GIT_REPO, update_after_clone=False)
112 create=True, src_url=TEST_GIT_REPO, update_after_clone=False)
113 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
113 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
114 #check if current workdir was *NOT* updated
114 #check if current workdir was *NOT* updated
115 fpath = os.path.join(clone_path, 'MANIFEST.in')
115 fpath = os.path.join(clone_path, 'MANIFEST.in')
116 # Make sure it's not bare repo
116 # Make sure it's not bare repo
117 self.assertFalse(repo_clone._repo.bare)
117 self.assertFalse(repo_clone._repo.bare)
118 self.assertEqual(False, os.path.isfile(fpath),
118 self.assertEqual(False, os.path.isfile(fpath),
119 'Repo was cloned and updated but file %s was found'
119 'Repo was cloned and updated but file %s was found'
120 % fpath)
120 % fpath)
121
121
122 def test_repo_clone_into_bare_repo(self):
122 def test_repo_clone_into_bare_repo(self):
123 repo = GitRepository(TEST_GIT_REPO)
123 repo = GitRepository(TEST_GIT_REPO)
124 clone_path = TEST_GIT_REPO_CLONE + '_bare.git'
124 clone_path = TEST_GIT_REPO_CLONE + '_bare.git'
125 repo_clone = GitRepository(clone_path, create=True,
125 repo_clone = GitRepository(clone_path, create=True,
126 src_url=repo.path, bare=True)
126 src_url=repo.path, bare=True)
127 self.assertTrue(repo_clone._repo.bare)
127 self.assertTrue(repo_clone._repo.bare)
128
128
129 def test_create_repo_is_not_bare_by_default(self):
129 def test_create_repo_is_not_bare_by_default(self):
130 repo = GitRepository(get_new_dir('not-bare-by-default'), create=True)
130 repo = GitRepository(get_new_dir('not-bare-by-default'), create=True)
131 self.assertFalse(repo._repo.bare)
131 self.assertFalse(repo._repo.bare)
132
132
133 def test_create_bare_repo(self):
133 def test_create_bare_repo(self):
134 repo = GitRepository(get_new_dir('bare-repo'), create=True, bare=True)
134 repo = GitRepository(get_new_dir('bare-repo'), create=True, bare=True)
135 self.assertTrue(repo._repo.bare)
135 self.assertTrue(repo._repo.bare)
136
136
137 def test_revisions(self):
137 def test_revisions(self):
138 # there are 112 revisions (by now)
138 # there are 112 revisions (by now)
139 # so we can assume they would be available from now on
139 # so we can assume they would be available from now on
140 subset = set([
140 subset = set([
141 'c1214f7e79e02fc37156ff215cd71275450cffc3',
141 'c1214f7e79e02fc37156ff215cd71275450cffc3',
142 '38b5fe81f109cb111f549bfe9bb6b267e10bc557',
142 '38b5fe81f109cb111f549bfe9bb6b267e10bc557',
143 'fa6600f6848800641328adbf7811fd2372c02ab2',
143 'fa6600f6848800641328adbf7811fd2372c02ab2',
144 '102607b09cdd60e2793929c4f90478be29f85a17',
144 '102607b09cdd60e2793929c4f90478be29f85a17',
145 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
145 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
146 '2d1028c054665b962fa3d307adfc923ddd528038',
146 '2d1028c054665b962fa3d307adfc923ddd528038',
147 'd7e0d30fbcae12c90680eb095a4f5f02505ce501',
147 'd7e0d30fbcae12c90680eb095a4f5f02505ce501',
148 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
148 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
149 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
149 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
150 '8430a588b43b5d6da365400117c89400326e7992',
150 '8430a588b43b5d6da365400117c89400326e7992',
151 'd955cd312c17b02143c04fa1099a352b04368118',
151 'd955cd312c17b02143c04fa1099a352b04368118',
152 'f67b87e5c629c2ee0ba58f85197e423ff28d735b',
152 'f67b87e5c629c2ee0ba58f85197e423ff28d735b',
153 'add63e382e4aabc9e1afdc4bdc24506c269b7618',
153 'add63e382e4aabc9e1afdc4bdc24506c269b7618',
154 'f298fe1189f1b69779a4423f40b48edf92a703fc',
154 'f298fe1189f1b69779a4423f40b48edf92a703fc',
155 'bd9b619eb41994cac43d67cf4ccc8399c1125808',
155 'bd9b619eb41994cac43d67cf4ccc8399c1125808',
156 '6e125e7c890379446e98980d8ed60fba87d0f6d1',
156 '6e125e7c890379446e98980d8ed60fba87d0f6d1',
157 'd4a54db9f745dfeba6933bf5b1e79e15d0af20bd',
157 'd4a54db9f745dfeba6933bf5b1e79e15d0af20bd',
158 '0b05e4ed56c802098dfc813cbe779b2f49e92500',
158 '0b05e4ed56c802098dfc813cbe779b2f49e92500',
159 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
159 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
160 '45223f8f114c64bf4d6f853e3c35a369a6305520',
160 '45223f8f114c64bf4d6f853e3c35a369a6305520',
161 'ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
161 'ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
162 'f5ea29fc42ef67a2a5a7aecff10e1566699acd68',
162 'f5ea29fc42ef67a2a5a7aecff10e1566699acd68',
163 '27d48942240f5b91dfda77accd2caac94708cc7d',
163 '27d48942240f5b91dfda77accd2caac94708cc7d',
164 '622f0eb0bafd619d2560c26f80f09e3b0b0d78af',
164 '622f0eb0bafd619d2560c26f80f09e3b0b0d78af',
165 'e686b958768ee96af8029fe19c6050b1a8dd3b2b'])
165 'e686b958768ee96af8029fe19c6050b1a8dd3b2b'])
166 self.assertTrue(subset.issubset(set(self.repo.revisions)))
166 self.assertTrue(subset.issubset(set(self.repo.revisions)))
167
167
168
168
169
169
170 def test_slicing(self):
170 def test_slicing(self):
171 #4 1 5 10 95
171 #4 1 5 10 95
172 for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5),
172 for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5),
173 (10, 20, 10), (5, 100, 95)]:
173 (10, 20, 10), (5, 100, 95)]:
174 revs = list(self.repo[sfrom:sto])
174 revs = list(self.repo[sfrom:sto])
175 self.assertEqual(len(revs), size)
175 self.assertEqual(len(revs), size)
176 self.assertEqual(revs[0], self.repo.get_changeset(sfrom))
176 self.assertEqual(revs[0], self.repo.get_changeset(sfrom))
177 self.assertEqual(revs[-1], self.repo.get_changeset(sto - 1))
177 self.assertEqual(revs[-1], self.repo.get_changeset(sto - 1))
178
178
179
179
180 def test_branches(self):
180 def test_branches(self):
181 # TODO: Need more tests here
181 # TODO: Need more tests here
182 # Removed (those are 'remotes' branches for cloned repo)
182 # Removed (those are 'remotes' branches for cloned repo)
183 #self.assertTrue('master' in self.repo.branches)
183 #self.assertTrue('master' in self.repo.branches)
184 #self.assertTrue('gittree' in self.repo.branches)
184 #self.assertTrue('gittree' in self.repo.branches)
185 #self.assertTrue('web-branch' in self.repo.branches)
185 #self.assertTrue('web-branch' in self.repo.branches)
186 for name, id in self.repo.branches.items():
186 for name, id in self.repo.branches.items():
187 self.assertTrue(isinstance(
187 self.assertTrue(isinstance(
188 self.repo.get_changeset(id), GitChangeset))
188 self.repo.get_changeset(id), GitChangeset))
189
189
190 def test_tags(self):
190 def test_tags(self):
191 # TODO: Need more tests here
191 # TODO: Need more tests here
192 self.assertTrue('v0.1.1' in self.repo.tags)
192 self.assertTrue('v0.1.1' in self.repo.tags)
193 self.assertTrue('v0.1.2' in self.repo.tags)
193 self.assertTrue('v0.1.2' in self.repo.tags)
194 for name, id in self.repo.tags.items():
194 for name, id in self.repo.tags.items():
195 self.assertTrue(isinstance(
195 self.assertTrue(isinstance(
196 self.repo.get_changeset(id), GitChangeset))
196 self.repo.get_changeset(id), GitChangeset))
197
197
198 def _test_single_changeset_cache(self, revision):
198 def _test_single_changeset_cache(self, revision):
199 chset = self.repo.get_changeset(revision)
199 chset = self.repo.get_changeset(revision)
200 self.assertTrue(revision in self.repo.changesets)
200 self.assertTrue(revision in self.repo.changesets)
201 self.assertTrue(chset is self.repo.changesets[revision])
201 self.assertTrue(chset is self.repo.changesets[revision])
202
202
203 def test_initial_changeset(self):
203 def test_initial_changeset(self):
204 id = self.repo.revisions[0]
204 id = self.repo.revisions[0]
205 init_chset = self.repo.get_changeset(id)
205 init_chset = self.repo.get_changeset(id)
206 self.assertEqual(init_chset.message, 'initial import\n')
206 self.assertEqual(init_chset.message, 'initial import\n')
207 self.assertEqual(init_chset.author,
207 self.assertEqual(init_chset.author,
208 'Marcin Kuzminski <marcin@python-blog.com>')
208 'Marcin Kuzminski <marcin@python-blog.com>')
209 for path in ('vcs/__init__.py',
209 for path in ('vcs/__init__.py',
210 'vcs/backends/BaseRepository.py',
210 'vcs/backends/BaseRepository.py',
211 'vcs/backends/__init__.py'):
211 'vcs/backends/__init__.py'):
212 self.assertTrue(isinstance(init_chset.get_node(path), FileNode))
212 self.assertTrue(isinstance(init_chset.get_node(path), FileNode))
213 for path in ('', 'vcs', 'vcs/backends'):
213 for path in ('', 'vcs', 'vcs/backends'):
214 self.assertTrue(isinstance(init_chset.get_node(path), DirNode))
214 self.assertTrue(isinstance(init_chset.get_node(path), DirNode))
215
215
216 self.assertRaises(NodeDoesNotExistError, init_chset.get_node, path='foobar')
216 self.assertRaises(NodeDoesNotExistError, init_chset.get_node, path='foobar')
217
217
218 node = init_chset.get_node('vcs/')
218 node = init_chset.get_node('vcs/')
219 self.assertTrue(hasattr(node, 'kind'))
219 self.assertTrue(hasattr(node, 'kind'))
220 self.assertEqual(node.kind, NodeKind.DIR)
220 self.assertEqual(node.kind, NodeKind.DIR)
221
221
222 node = init_chset.get_node('vcs')
222 node = init_chset.get_node('vcs')
223 self.assertTrue(hasattr(node, 'kind'))
223 self.assertTrue(hasattr(node, 'kind'))
224 self.assertEqual(node.kind, NodeKind.DIR)
224 self.assertEqual(node.kind, NodeKind.DIR)
225
225
226 node = init_chset.get_node('vcs/__init__.py')
226 node = init_chset.get_node('vcs/__init__.py')
227 self.assertTrue(hasattr(node, 'kind'))
227 self.assertTrue(hasattr(node, 'kind'))
228 self.assertEqual(node.kind, NodeKind.FILE)
228 self.assertEqual(node.kind, NodeKind.FILE)
229
229
230 def test_not_existing_changeset(self):
230 def test_not_existing_changeset(self):
231 self.assertRaises(RepositoryError, self.repo.get_changeset,
231 self.assertRaises(RepositoryError, self.repo.get_changeset,
232 'f' * 40)
232 'f' * 40)
233
233
234 def test_changeset10(self):
234 def test_changeset10(self):
235
235
236 chset10 = self.repo.get_changeset(self.repo.revisions[9])
236 chset10 = self.repo.get_changeset(self.repo.revisions[9])
237 README = """===
237 README = """===
238 VCS
238 VCS
239 ===
239 ===
240
240
241 Various Version Control System management abstraction layer for Python.
241 Various Version Control System management abstraction layer for Python.
242
242
243 Introduction
243 Introduction
244 ------------
244 ------------
245
245
246 TODO: To be written...
246 TODO: To be written...
247
247
248 """
248 """
249 node = chset10.get_node('README.rst')
249 node = chset10.get_node('README.rst')
250 self.assertEqual(node.kind, NodeKind.FILE)
250 self.assertEqual(node.kind, NodeKind.FILE)
251 self.assertEqual(node.content, README)
251 self.assertEqual(node.content, README)
252
252
253
253
254 class GitChangesetTest(unittest.TestCase):
254 class GitChangesetTest(unittest.TestCase):
255
255
256 def setUp(self):
256 def setUp(self):
257 self.repo = GitRepository(TEST_GIT_REPO)
257 self.repo = GitRepository(TEST_GIT_REPO)
258
258
259 def test_default_changeset(self):
259 def test_default_changeset(self):
260 tip = self.repo.get_changeset()
260 tip = self.repo.get_changeset()
261 self.assertEqual(tip, self.repo.get_changeset(None))
261 self.assertEqual(tip, self.repo.get_changeset(None))
262 self.assertEqual(tip, self.repo.get_changeset('tip'))
262 self.assertEqual(tip, self.repo.get_changeset('tip'))
263
263
264 def test_root_node(self):
264 def test_root_node(self):
265 tip = self.repo.get_changeset()
265 tip = self.repo.get_changeset()
266 self.assertTrue(tip.root is tip.get_node(''))
266 self.assertTrue(tip.root is tip.get_node(''))
267
267
268 def test_lazy_fetch(self):
268 def test_lazy_fetch(self):
269 """
269 """
270 Test if changeset's nodes expands and are cached as we walk through
270 Test if changeset's nodes expands and are cached as we walk through
271 the revision. This test is somewhat hard to write as order of tests
271 the revision. This test is somewhat hard to write as order of tests
272 is a key here. Written by running command after command in a shell.
272 is a key here. Written by running command after command in a shell.
273 """
273 """
274 hex = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
274 hex = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
275 self.assertTrue(hex in self.repo.revisions)
275 self.assertTrue(hex in self.repo.revisions)
276 chset = self.repo.get_changeset(hex)
276 chset = self.repo.get_changeset(hex)
277 self.assertTrue(len(chset.nodes) == 0)
277 self.assertTrue(len(chset.nodes) == 0)
278 root = chset.root
278 root = chset.root
279 self.assertTrue(len(chset.nodes) == 1)
279 self.assertTrue(len(chset.nodes) == 1)
280 self.assertTrue(len(root.nodes) == 8)
280 self.assertTrue(len(root.nodes) == 8)
281 # accessing root.nodes updates chset.nodes
281 # accessing root.nodes updates chset.nodes
282 self.assertTrue(len(chset.nodes) == 9)
282 self.assertTrue(len(chset.nodes) == 9)
283
283
284 docs = root.get_node('docs')
284 docs = root.get_node('docs')
285 # we haven't yet accessed anything new as docs dir was already cached
285 # we haven't yet accessed anything new as docs dir was already cached
286 self.assertTrue(len(chset.nodes) == 9)
286 self.assertTrue(len(chset.nodes) == 9)
287 self.assertTrue(len(docs.nodes) == 8)
287 self.assertTrue(len(docs.nodes) == 8)
288 # accessing docs.nodes updates chset.nodes
288 # accessing docs.nodes updates chset.nodes
289 self.assertTrue(len(chset.nodes) == 17)
289 self.assertTrue(len(chset.nodes) == 17)
290
290
291 self.assertTrue(docs is chset.get_node('docs'))
291 self.assertTrue(docs is chset.get_node('docs'))
292 self.assertTrue(docs is root.nodes[0])
292 self.assertTrue(docs is root.nodes[0])
293 self.assertTrue(docs is root.dirs[0])
293 self.assertTrue(docs is root.dirs[0])
294 self.assertTrue(docs is chset.get_node('docs'))
294 self.assertTrue(docs is chset.get_node('docs'))
295
295
296 def test_nodes_with_changeset(self):
296 def test_nodes_with_changeset(self):
297 hex = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
297 hex = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
298 chset = self.repo.get_changeset(hex)
298 chset = self.repo.get_changeset(hex)
299 root = chset.root
299 root = chset.root
300 docs = root.get_node('docs')
300 docs = root.get_node('docs')
301 self.assertTrue(docs is chset.get_node('docs'))
301 self.assertTrue(docs is chset.get_node('docs'))
302 api = docs.get_node('api')
302 api = docs.get_node('api')
303 self.assertTrue(api is chset.get_node('docs/api'))
303 self.assertTrue(api is chset.get_node('docs/api'))
304 index = api.get_node('index.rst')
304 index = api.get_node('index.rst')
305 self.assertTrue(index is chset.get_node('docs/api/index.rst'))
305 self.assertTrue(index is chset.get_node('docs/api/index.rst'))
306 self.assertTrue(index is chset.get_node('docs')\
306 self.assertTrue(index is chset.get_node('docs')\
307 .get_node('api')\
307 .get_node('api')\
308 .get_node('index.rst'))
308 .get_node('index.rst'))
309
309
310 def test_branch_and_tags(self):
310 def test_branch_and_tags(self):
311 """
311 """
312 rev0 = self.repo.revisions[0]
312 rev0 = self.repo.revisions[0]
313 chset0 = self.repo.get_changeset(rev0)
313 chset0 = self.repo.get_changeset(rev0)
314 self.assertEqual(chset0.branch, 'master')
314 self.assertEqual(chset0.branch, 'master')
315 self.assertEqual(chset0.tags, [])
315 self.assertEqual(chset0.tags, [])
316
316
317 rev10 = self.repo.revisions[10]
317 rev10 = self.repo.revisions[10]
318 chset10 = self.repo.get_changeset(rev10)
318 chset10 = self.repo.get_changeset(rev10)
319 self.assertEqual(chset10.branch, 'master')
319 self.assertEqual(chset10.branch, 'master')
320 self.assertEqual(chset10.tags, [])
320 self.assertEqual(chset10.tags, [])
321
321
322 rev44 = self.repo.revisions[44]
322 rev44 = self.repo.revisions[44]
323 chset44 = self.repo.get_changeset(rev44)
323 chset44 = self.repo.get_changeset(rev44)
324 self.assertEqual(chset44.branch, 'web-branch')
324 self.assertEqual(chset44.branch, 'web-branch')
325
325
326 tip = self.repo.get_changeset('tip')
326 tip = self.repo.get_changeset('tip')
327 self.assertTrue('tip' in tip.tags)
327 self.assertTrue('tip' in tip.tags)
328 """
328 """
329 # Those tests would fail - branches are now going
329 # Those tests would fail - branches are now going
330 # to be changed at main API in order to support git backend
330 # to be changed at main API in order to support git backend
331 pass
331 pass
332
332
333 def _test_slices(self, limit, offset):
333 def _test_slices(self, limit, offset):
334 count = self.repo.count()
334 count = self.repo.count()
335 changesets = self.repo.get_changesets(limit=limit, offset=offset)
335 changesets = self.repo.get_changesets(limit=limit, offset=offset)
336 idx = 0
336 idx = 0
337 for changeset in changesets:
337 for changeset in changesets:
338 rev = offset + idx
338 rev = offset + idx
339 idx += 1
339 idx += 1
340 rev_id = self.repo.revisions[rev]
340 rev_id = self.repo.revisions[rev]
341 if idx > limit:
341 if idx > limit:
342 self.fail("Exceeded limit already (getting revision %s, "
342 self.fail("Exceeded limit already (getting revision %s, "
343 "there are %s total revisions, offset=%s, limit=%s)"
343 "there are %s total revisions, offset=%s, limit=%s)"
344 % (rev_id, count, offset, limit))
344 % (rev_id, count, offset, limit))
345 self.assertEqual(changeset, self.repo.get_changeset(rev_id))
345 self.assertEqual(changeset, self.repo.get_changeset(rev_id))
346 result = list(self.repo.get_changesets(limit=limit, offset=offset))
346 result = list(self.repo.get_changesets(limit=limit, offset=offset))
347 start = offset
347 start = offset
348 end = limit and offset + limit or None
348 end = limit and offset + limit or None
349 sliced = list(self.repo[start:end])
349 sliced = list(self.repo[start:end])
350 self.failUnlessEqual(result, sliced,
350 self.failUnlessEqual(result, sliced,
351 msg="Comparison failed for limit=%s, offset=%s"
351 msg="Comparison failed for limit=%s, offset=%s"
352 "(get_changeset returned: %s and sliced: %s"
352 "(get_changeset returned: %s and sliced: %s"
353 % (limit, offset, result, sliced))
353 % (limit, offset, result, sliced))
354
354
355 def _test_file_size(self, revision, path, size):
355 def _test_file_size(self, revision, path, size):
356 node = self.repo.get_changeset(revision).get_node(path)
356 node = self.repo.get_changeset(revision).get_node(path)
357 self.assertTrue(node.is_file())
357 self.assertTrue(node.is_file())
358 self.assertEqual(node.size, size)
358 self.assertEqual(node.size, size)
359
359
360 def test_file_size(self):
360 def test_file_size(self):
361 to_check = (
361 to_check = (
362 ('c1214f7e79e02fc37156ff215cd71275450cffc3',
362 ('c1214f7e79e02fc37156ff215cd71275450cffc3',
363 'vcs/backends/BaseRepository.py', 502),
363 'vcs/backends/BaseRepository.py', 502),
364 ('d7e0d30fbcae12c90680eb095a4f5f02505ce501',
364 ('d7e0d30fbcae12c90680eb095a4f5f02505ce501',
365 'vcs/backends/hg.py', 854),
365 'vcs/backends/hg.py', 854),
366 ('6e125e7c890379446e98980d8ed60fba87d0f6d1',
366 ('6e125e7c890379446e98980d8ed60fba87d0f6d1',
367 'setup.py', 1068),
367 'setup.py', 1068),
368
368
369 ('d955cd312c17b02143c04fa1099a352b04368118',
369 ('d955cd312c17b02143c04fa1099a352b04368118',
370 'vcs/backends/base.py', 2921),
370 'vcs/backends/base.py', 2921),
371 ('ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
371 ('ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
372 'vcs/backends/base.py', 3936),
372 'vcs/backends/base.py', 3936),
373 ('f50f42baeed5af6518ef4b0cb2f1423f3851a941',
373 ('f50f42baeed5af6518ef4b0cb2f1423f3851a941',
374 'vcs/backends/base.py', 6189),
374 'vcs/backends/base.py', 6189),
375 )
375 )
376 for revision, path, size in to_check:
376 for revision, path, size in to_check:
377 self._test_file_size(revision, path, size)
377 self._test_file_size(revision, path, size)
378
378
379 def _test_dir_size(self, revision, path, size):
380 node = self.repo.get_changeset(revision).get_node(path)
381 self.assertEqual(node.size, size)
382
383 def test_dir_size(self):
384 to_check = (
385 ('5f2c6ee195929b0be80749243c18121c9864a3b3', '/', 674076),
386 ('7ab37bc680b4aa72c34d07b230c866c28e9fc204', '/', 674049),
387 ('6892503fb8f2a552cef5f4d4cc2cdbd13ae1cd2f', '/', 671830),
388 )
389 for revision, path, size in to_check:
390 self._test_dir_size(revision, path, size)
391
392 def test_repo_size(self):
393 self.assertEqual(self.repo.size, 1022026) # FIXME
394
379 def test_file_history(self):
395 def test_file_history(self):
380 # we can only check if those revisions are present in the history
396 # we can only check if those revisions are present in the history
381 # as we cannot update this test every time file is changed
397 # as we cannot update this test every time file is changed
382 files = {
398 files = {
383 'setup.py': [
399 'setup.py': [
384 '54386793436c938cff89326944d4c2702340037d',
400 '54386793436c938cff89326944d4c2702340037d',
385 '51d254f0ecf5df2ce50c0b115741f4cf13985dab',
401 '51d254f0ecf5df2ce50c0b115741f4cf13985dab',
386 '998ed409c795fec2012b1c0ca054d99888b22090',
402 '998ed409c795fec2012b1c0ca054d99888b22090',
387 '5e0eb4c47f56564395f76333f319d26c79e2fb09',
403 '5e0eb4c47f56564395f76333f319d26c79e2fb09',
388 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
404 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
389 '7cb3fd1b6d8c20ba89e2264f1c8baebc8a52d36e',
405 '7cb3fd1b6d8c20ba89e2264f1c8baebc8a52d36e',
390 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
406 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
391 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
407 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
392 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
408 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
393 ],
409 ],
394 'vcs/nodes.py': [
410 'vcs/nodes.py': [
395 '33fa3223355104431402a888fa77a4e9956feb3e',
411 '33fa3223355104431402a888fa77a4e9956feb3e',
396 'fa014c12c26d10ba682fadb78f2a11c24c8118e1',
412 'fa014c12c26d10ba682fadb78f2a11c24c8118e1',
397 'e686b958768ee96af8029fe19c6050b1a8dd3b2b',
413 'e686b958768ee96af8029fe19c6050b1a8dd3b2b',
398 'ab5721ca0a081f26bf43d9051e615af2cc99952f',
414 'ab5721ca0a081f26bf43d9051e615af2cc99952f',
399 'c877b68d18e792a66b7f4c529ea02c8f80801542',
415 'c877b68d18e792a66b7f4c529ea02c8f80801542',
400 '4313566d2e417cb382948f8d9d7c765330356054',
416 '4313566d2e417cb382948f8d9d7c765330356054',
401 '6c2303a793671e807d1cfc70134c9ca0767d98c2',
417 '6c2303a793671e807d1cfc70134c9ca0767d98c2',
402 '54386793436c938cff89326944d4c2702340037d',
418 '54386793436c938cff89326944d4c2702340037d',
403 '54000345d2e78b03a99d561399e8e548de3f3203',
419 '54000345d2e78b03a99d561399e8e548de3f3203',
404 '1c6b3677b37ea064cb4b51714d8f7498f93f4b2b',
420 '1c6b3677b37ea064cb4b51714d8f7498f93f4b2b',
405 '2d03ca750a44440fb5ea8b751176d1f36f8e8f46',
421 '2d03ca750a44440fb5ea8b751176d1f36f8e8f46',
406 '2a08b128c206db48c2f0b8f70df060e6db0ae4f8',
422 '2a08b128c206db48c2f0b8f70df060e6db0ae4f8',
407 '30c26513ff1eb8e5ce0e1c6b477ee5dc50e2f34b',
423 '30c26513ff1eb8e5ce0e1c6b477ee5dc50e2f34b',
408 'ac71e9503c2ca95542839af0ce7b64011b72ea7c',
424 'ac71e9503c2ca95542839af0ce7b64011b72ea7c',
409 '12669288fd13adba2a9b7dd5b870cc23ffab92d2',
425 '12669288fd13adba2a9b7dd5b870cc23ffab92d2',
410 '5a0c84f3e6fe3473e4c8427199d5a6fc71a9b382',
426 '5a0c84f3e6fe3473e4c8427199d5a6fc71a9b382',
411 '12f2f5e2b38e6ff3fbdb5d722efed9aa72ecb0d5',
427 '12f2f5e2b38e6ff3fbdb5d722efed9aa72ecb0d5',
412 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
428 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
413 'f50f42baeed5af6518ef4b0cb2f1423f3851a941',
429 'f50f42baeed5af6518ef4b0cb2f1423f3851a941',
414 'd7e390a45f6aa96f04f5e7f583ad4f867431aa25',
430 'd7e390a45f6aa96f04f5e7f583ad4f867431aa25',
415 'f15c21f97864b4f071cddfbf2750ec2e23859414',
431 'f15c21f97864b4f071cddfbf2750ec2e23859414',
416 'e906ef056cf539a4e4e5fc8003eaf7cf14dd8ade',
432 'e906ef056cf539a4e4e5fc8003eaf7cf14dd8ade',
417 'ea2b108b48aa8f8c9c4a941f66c1a03315ca1c3b',
433 'ea2b108b48aa8f8c9c4a941f66c1a03315ca1c3b',
418 '84dec09632a4458f79f50ddbbd155506c460b4f9',
434 '84dec09632a4458f79f50ddbbd155506c460b4f9',
419 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
435 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
420 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
436 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
421 '3bf1c5868e570e39569d094f922d33ced2fa3b2b',
437 '3bf1c5868e570e39569d094f922d33ced2fa3b2b',
422 'b8d04012574729d2c29886e53b1a43ef16dd00a1',
438 'b8d04012574729d2c29886e53b1a43ef16dd00a1',
423 '6970b057cffe4aab0a792aa634c89f4bebf01441',
439 '6970b057cffe4aab0a792aa634c89f4bebf01441',
424 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
440 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
425 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
441 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
426 ],
442 ],
427 'vcs/backends/git.py': [
443 'vcs/backends/git.py': [
428 '4cf116ad5a457530381135e2f4c453e68a1b0105',
444 '4cf116ad5a457530381135e2f4c453e68a1b0105',
429 '9a751d84d8e9408e736329767387f41b36935153',
445 '9a751d84d8e9408e736329767387f41b36935153',
430 'cb681fb539c3faaedbcdf5ca71ca413425c18f01',
446 'cb681fb539c3faaedbcdf5ca71ca413425c18f01',
431 '428f81bb652bcba8d631bce926e8834ff49bdcc6',
447 '428f81bb652bcba8d631bce926e8834ff49bdcc6',
432 '180ab15aebf26f98f714d8c68715e0f05fa6e1c7',
448 '180ab15aebf26f98f714d8c68715e0f05fa6e1c7',
433 '2b8e07312a2e89e92b90426ab97f349f4bce2a3a',
449 '2b8e07312a2e89e92b90426ab97f349f4bce2a3a',
434 '50e08c506174d8645a4bb517dd122ac946a0f3bf',
450 '50e08c506174d8645a4bb517dd122ac946a0f3bf',
435 '54000345d2e78b03a99d561399e8e548de3f3203',
451 '54000345d2e78b03a99d561399e8e548de3f3203',
436 ],
452 ],
437 }
453 }
438 for path, revs in files.items():
454 for path, revs in files.items():
439 node = self.repo.get_changeset(revs[0]).get_node(path)
455 node = self.repo.get_changeset(revs[0]).get_node(path)
440 node_revs = [chset.raw_id for chset in node.history]
456 node_revs = [chset.raw_id for chset in node.history]
441 self.assertTrue(set(revs).issubset(set(node_revs)),
457 self.assertTrue(set(revs).issubset(set(node_revs)),
442 "We assumed that %s is subset of revisions for which file %s "
458 "We assumed that %s is subset of revisions for which file %s "
443 "has been changed, and history of that node returned: %s"
459 "has been changed, and history of that node returned: %s"
444 % (revs, path, node_revs))
460 % (revs, path, node_revs))
445
461
446 def test_file_annotate(self):
462 def test_file_annotate(self):
447 files = {
463 files = {
448 'vcs/backends/__init__.py': {
464 'vcs/backends/__init__.py': {
449 'c1214f7e79e02fc37156ff215cd71275450cffc3': {
465 'c1214f7e79e02fc37156ff215cd71275450cffc3': {
450 'lines_no': 1,
466 'lines_no': 1,
451 'changesets': [
467 'changesets': [
452 'c1214f7e79e02fc37156ff215cd71275450cffc3',
468 'c1214f7e79e02fc37156ff215cd71275450cffc3',
453 ],
469 ],
454 },
470 },
455 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647': {
471 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647': {
456 'lines_no': 21,
472 'lines_no': 21,
457 'changesets': [
473 'changesets': [
458 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
474 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
459 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
475 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
460 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
476 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
461 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
477 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
462 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
478 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
463 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
479 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
464 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
480 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
465 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
481 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
466 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
482 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
467 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
483 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
468 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
484 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
469 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
485 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
470 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
486 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
471 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
487 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
472 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
488 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
473 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
489 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
474 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
490 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
475 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
491 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
476 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
492 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
477 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
493 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
478 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
494 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
479 ],
495 ],
480 },
496 },
481 'e29b67bd158580fc90fc5e9111240b90e6e86064': {
497 'e29b67bd158580fc90fc5e9111240b90e6e86064': {
482 'lines_no': 32,
498 'lines_no': 32,
483 'changesets': [
499 'changesets': [
484 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
500 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
485 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
501 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
486 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
502 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
487 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
503 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
488 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
504 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
489 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
505 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
490 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
506 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
491 '54000345d2e78b03a99d561399e8e548de3f3203',
507 '54000345d2e78b03a99d561399e8e548de3f3203',
492 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
508 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
493 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
509 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
494 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
510 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
495 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
511 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
496 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
512 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
497 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
513 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
498 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
514 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
499 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
515 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
500 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
516 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
501 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
517 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
502 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
518 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
503 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
519 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
504 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
520 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
505 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
521 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
506 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
522 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
507 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
523 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
508 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
524 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
509 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
525 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
510 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
526 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
511 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
527 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
512 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
528 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
513 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
529 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
514 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
530 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
515 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
531 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
516 ],
532 ],
517 },
533 },
518 },
534 },
519 }
535 }
520
536
521 for fname, revision_dict in files.items():
537 for fname, revision_dict in files.items():
522 for rev, data in revision_dict.items():
538 for rev, data in revision_dict.items():
523 cs = self.repo.get_changeset(rev)
539 cs = self.repo.get_changeset(rev)
524
540
525 l1_1 = [x[1] for x in cs.get_file_annotate(fname)]
541 l1_1 = [x[1] for x in cs.get_file_annotate(fname)]
526 l1_2 = [x[2]().raw_id for x in cs.get_file_annotate(fname)]
542 l1_2 = [x[2]().raw_id for x in cs.get_file_annotate(fname)]
527 self.assertEqual(l1_1, l1_2)
543 self.assertEqual(l1_1, l1_2)
528 l1 = l1_1
544 l1 = l1_1
529 l2 = files[fname][rev]['changesets']
545 l2 = files[fname][rev]['changesets']
530 self.assertTrue(l1 == l2 , "The lists of revision for %s@rev %s"
546 self.assertTrue(l1 == l2 , "The lists of revision for %s@rev %s"
531 "from annotation list should match each other, "
547 "from annotation list should match each other, "
532 "got \n%s \nvs \n%s " % (fname, rev, l1, l2))
548 "got \n%s \nvs \n%s " % (fname, rev, l1, l2))
533
549
534 def test_files_state(self):
550 def test_files_state(self):
535 """
551 """
536 Tests state of FileNodes.
552 Tests state of FileNodes.
537 """
553 """
538 node = self.repo\
554 node = self.repo\
539 .get_changeset('e6ea6d16e2f26250124a1f4b4fe37a912f9d86a0')\
555 .get_changeset('e6ea6d16e2f26250124a1f4b4fe37a912f9d86a0')\
540 .get_node('vcs/utils/diffs.py')
556 .get_node('vcs/utils/diffs.py')
541 self.assertTrue(node.state, NodeState.ADDED)
557 self.assertTrue(node.state, NodeState.ADDED)
542 self.assertTrue(node.added)
558 self.assertTrue(node.added)
543 self.assertFalse(node.changed)
559 self.assertFalse(node.changed)
544 self.assertFalse(node.not_changed)
560 self.assertFalse(node.not_changed)
545 self.assertFalse(node.removed)
561 self.assertFalse(node.removed)
546
562
547 node = self.repo\
563 node = self.repo\
548 .get_changeset('33fa3223355104431402a888fa77a4e9956feb3e')\
564 .get_changeset('33fa3223355104431402a888fa77a4e9956feb3e')\
549 .get_node('.hgignore')
565 .get_node('.hgignore')
550 self.assertTrue(node.state, NodeState.CHANGED)
566 self.assertTrue(node.state, NodeState.CHANGED)
551 self.assertFalse(node.added)
567 self.assertFalse(node.added)
552 self.assertTrue(node.changed)
568 self.assertTrue(node.changed)
553 self.assertFalse(node.not_changed)
569 self.assertFalse(node.not_changed)
554 self.assertFalse(node.removed)
570 self.assertFalse(node.removed)
555
571
556 node = self.repo\
572 node = self.repo\
557 .get_changeset('e29b67bd158580fc90fc5e9111240b90e6e86064')\
573 .get_changeset('e29b67bd158580fc90fc5e9111240b90e6e86064')\
558 .get_node('setup.py')
574 .get_node('setup.py')
559 self.assertTrue(node.state, NodeState.NOT_CHANGED)
575 self.assertTrue(node.state, NodeState.NOT_CHANGED)
560 self.assertFalse(node.added)
576 self.assertFalse(node.added)
561 self.assertFalse(node.changed)
577 self.assertFalse(node.changed)
562 self.assertTrue(node.not_changed)
578 self.assertTrue(node.not_changed)
563 self.assertFalse(node.removed)
579 self.assertFalse(node.removed)
564
580
565 # If node has REMOVED state then trying to fetch it would raise
581 # If node has REMOVED state then trying to fetch it would raise
566 # ChangesetError exception
582 # ChangesetError exception
567 chset = self.repo.get_changeset(
583 chset = self.repo.get_changeset(
568 'fa6600f6848800641328adbf7811fd2372c02ab2')
584 'fa6600f6848800641328adbf7811fd2372c02ab2')
569 path = 'vcs/backends/BaseRepository.py'
585 path = 'vcs/backends/BaseRepository.py'
570 self.assertRaises(NodeDoesNotExistError, chset.get_node, path)
586 self.assertRaises(NodeDoesNotExistError, chset.get_node, path)
571 # but it would be one of ``removed`` (changeset's attribute)
587 # but it would be one of ``removed`` (changeset's attribute)
572 self.assertTrue(path in [rf.path for rf in chset.removed])
588 self.assertTrue(path in [rf.path for rf in chset.removed])
573
589
574 chset = self.repo.get_changeset(
590 chset = self.repo.get_changeset(
575 '54386793436c938cff89326944d4c2702340037d')
591 '54386793436c938cff89326944d4c2702340037d')
576 changed = ['setup.py', 'tests/test_nodes.py', 'vcs/backends/hg.py',
592 changed = ['setup.py', 'tests/test_nodes.py', 'vcs/backends/hg.py',
577 'vcs/nodes.py']
593 'vcs/nodes.py']
578 self.assertEqual(set(changed), set([f.path for f in chset.changed]))
594 self.assertEqual(set(changed), set([f.path for f in chset.changed]))
579
595
580 def test_commit_message_is_unicode(self):
596 def test_commit_message_is_unicode(self):
581 for cs in self.repo:
597 for cs in self.repo:
582 self.assertEqual(type(cs.message), unicode)
598 self.assertEqual(type(cs.message), unicode)
583
599
584 def test_changeset_author_is_unicode(self):
600 def test_changeset_author_is_unicode(self):
585 for cs in self.repo:
601 for cs in self.repo:
586 self.assertEqual(type(cs.author), unicode)
602 self.assertEqual(type(cs.author), unicode)
587
603
588 def test_repo_files_content_is_unicode(self):
604 def test_repo_files_content_is_unicode(self):
589 changeset = self.repo.get_changeset()
605 changeset = self.repo.get_changeset()
590 for node in changeset.get_node('/'):
606 for node in changeset.get_node('/'):
591 if node.is_file():
607 if node.is_file():
592 self.assertEqual(type(node.content), unicode)
608 self.assertEqual(type(node.content), unicode)
593
609
594 def test_wrong_path(self):
610 def test_wrong_path(self):
595 # There is 'setup.py' in the root dir but not there:
611 # There is 'setup.py' in the root dir but not there:
596 path = 'foo/bar/setup.py'
612 path = 'foo/bar/setup.py'
597 tip = self.repo.get_changeset()
613 tip = self.repo.get_changeset()
598 self.assertRaises(VCSError, tip.get_node, path)
614 self.assertRaises(VCSError, tip.get_node, path)
599
615
600 def test_author_email(self):
616 def test_author_email(self):
601 self.assertEqual('marcin@python-blog.com',
617 self.assertEqual('marcin@python-blog.com',
602 self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3')\
618 self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3')\
603 .author_email)
619 .author_email)
604 self.assertEqual('lukasz.balcerzak@python-center.pl',
620 self.assertEqual('lukasz.balcerzak@python-center.pl',
605 self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b')\
621 self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b')\
606 .author_email)
622 .author_email)
607 self.assertEqual('none@none',
623 self.assertEqual('none@none',
608 self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992')\
624 self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992')\
609 .author_email)
625 .author_email)
610
626
611 def test_author_username(self):
627 def test_author_username(self):
612 self.assertEqual('Marcin Kuzminski',
628 self.assertEqual('Marcin Kuzminski',
613 self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3')\
629 self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3')\
614 .author_name)
630 .author_name)
615 self.assertEqual('Lukasz Balcerzak',
631 self.assertEqual('Lukasz Balcerzak',
616 self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b')\
632 self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b')\
617 .author_name)
633 .author_name)
618 self.assertEqual('marcink',
634 self.assertEqual('marcink',
619 self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992')\
635 self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992')\
620 .author_name)
636 .author_name)
621
637
622
638
623 class GitSpecificTest(unittest.TestCase):
639 class GitSpecificTest(unittest.TestCase):
624
640
625 def test_error_is_raised_for_added_if_diff_name_status_is_wrong(self):
641 def test_error_is_raised_for_added_if_diff_name_status_is_wrong(self):
626 repo = mock.MagicMock()
642 repo = mock.MagicMock()
627 changeset = GitChangeset(repo, 'foobar')
643 changeset = GitChangeset(repo, 'foobar')
628 changeset._diff_name_status = 'foobar'
644 changeset._diff_name_status = 'foobar'
629 with self.assertRaises(VCSError):
645 with self.assertRaises(VCSError):
630 changeset.added
646 changeset.added
631
647
632 def test_error_is_raised_for_changed_if_diff_name_status_is_wrong(self):
648 def test_error_is_raised_for_changed_if_diff_name_status_is_wrong(self):
633 repo = mock.MagicMock()
649 repo = mock.MagicMock()
634 changeset = GitChangeset(repo, 'foobar')
650 changeset = GitChangeset(repo, 'foobar')
635 changeset._diff_name_status = 'foobar'
651 changeset._diff_name_status = 'foobar'
636 with self.assertRaises(VCSError):
652 with self.assertRaises(VCSError):
637 changeset.added
653 changeset.added
638
654
639 def test_error_is_raised_for_removed_if_diff_name_status_is_wrong(self):
655 def test_error_is_raised_for_removed_if_diff_name_status_is_wrong(self):
640 repo = mock.MagicMock()
656 repo = mock.MagicMock()
641 changeset = GitChangeset(repo, 'foobar')
657 changeset = GitChangeset(repo, 'foobar')
642 changeset._diff_name_status = 'foobar'
658 changeset._diff_name_status = 'foobar'
643 with self.assertRaises(VCSError):
659 with self.assertRaises(VCSError):
644 changeset.added
660 changeset.added
645
661
646
662
647 class GitSpecificWithRepoTest(_BackendTestMixin, unittest.TestCase):
663 class GitSpecificWithRepoTest(_BackendTestMixin, unittest.TestCase):
648 backend_alias = 'git'
664 backend_alias = 'git'
649
665
650 @classmethod
666 @classmethod
651 def _get_commits(cls):
667 def _get_commits(cls):
652 return [
668 return [
653 {
669 {
654 'message': 'Initial',
670 'message': 'Initial',
655 'author': 'Joe Doe <joe.doe@example.com>',
671 'author': 'Joe Doe <joe.doe@example.com>',
656 'date': datetime.datetime(2010, 1, 1, 20),
672 'date': datetime.datetime(2010, 1, 1, 20),
657 'added': [
673 'added': [
658 FileNode('foobar/static/js/admin/base.js', content='base'),
674 FileNode('foobar/static/js/admin/base.js', content='base'),
659 FileNode('foobar/static/admin', content='admin',
675 FileNode('foobar/static/admin', content='admin',
660 mode=0120000), # this is a link
676 mode=0120000), # this is a link
661 FileNode('foo', content='foo'),
677 FileNode('foo', content='foo'),
662 ],
678 ],
663 },
679 },
664 {
680 {
665 'message': 'Second',
681 'message': 'Second',
666 'author': 'Joe Doe <joe.doe@example.com>',
682 'author': 'Joe Doe <joe.doe@example.com>',
667 'date': datetime.datetime(2010, 1, 1, 22),
683 'date': datetime.datetime(2010, 1, 1, 22),
668 'added': [
684 'added': [
669 FileNode('foo2', content='foo2'),
685 FileNode('foo2', content='foo2'),
670 ],
686 ],
671 },
687 },
672 ]
688 ]
673
689
674 def test_paths_slow_traversing(self):
690 def test_paths_slow_traversing(self):
675 cs = self.repo.get_changeset()
691 cs = self.repo.get_changeset()
676 self.assertEqual(cs.get_node('foobar').get_node('static').get_node('js')
692 self.assertEqual(cs.get_node('foobar').get_node('static').get_node('js')
677 .get_node('admin').get_node('base.js').content, 'base')
693 .get_node('admin').get_node('base.js').content, 'base')
678
694
679 def test_paths_fast_traversing(self):
695 def test_paths_fast_traversing(self):
680 cs = self.repo.get_changeset()
696 cs = self.repo.get_changeset()
681 self.assertEqual(cs.get_node('foobar/static/js/admin/base.js').content,
697 self.assertEqual(cs.get_node('foobar/static/js/admin/base.js').content,
682 'base')
698 'base')
683
699
684 def test_workdir_get_branch(self):
700 def test_workdir_get_branch(self):
685 self.repo.run_git_command(['checkout', '-b', 'production'])
701 self.repo.run_git_command(['checkout', '-b', 'production'])
686 # Regression test: one of following would fail if we don't check
702 # Regression test: one of following would fail if we don't check
687 # .git/HEAD file
703 # .git/HEAD file
688 self.repo.run_git_command(['checkout', 'production'])
704 self.repo.run_git_command(['checkout', 'production'])
689 self.assertEqual(self.repo.workdir.get_branch(), 'production')
705 self.assertEqual(self.repo.workdir.get_branch(), 'production')
690 self.repo.run_git_command(['checkout', 'master'])
706 self.repo.run_git_command(['checkout', 'master'])
691 self.assertEqual(self.repo.workdir.get_branch(), 'master')
707 self.assertEqual(self.repo.workdir.get_branch(), 'master')
692
708
693 def test_get_diff_runs_git_command_with_hashes(self):
709 def test_get_diff_runs_git_command_with_hashes(self):
694 self.repo.run_git_command = mock.Mock(return_value=['', ''])
710 self.repo.run_git_command = mock.Mock(return_value=['', ''])
695 self.repo.get_diff(0, 1)
711 self.repo.get_diff(0, 1)
696 self.repo.run_git_command.assert_called_once_with(
712 self.repo.run_git_command.assert_called_once_with(
697 ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
713 ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
698 self.repo._get_revision(0), self.repo._get_revision(1)])
714 self.repo._get_revision(0), self.repo._get_revision(1)])
699
715
700 def test_get_diff_runs_git_command_with_str_hashes(self):
716 def test_get_diff_runs_git_command_with_str_hashes(self):
701 self.repo.run_git_command = mock.Mock(return_value=['', ''])
717 self.repo.run_git_command = mock.Mock(return_value=['', ''])
702 self.repo.get_diff(self.repo.EMPTY_CHANGESET, 1)
718 self.repo.get_diff(self.repo.EMPTY_CHANGESET, 1)
703 self.repo.run_git_command.assert_called_once_with(
719 self.repo.run_git_command.assert_called_once_with(
704 ['show', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
720 ['show', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
705 self.repo._get_revision(1)])
721 self.repo._get_revision(1)])
706
722
707 def test_get_diff_runs_git_command_with_path_if_its_given(self):
723 def test_get_diff_runs_git_command_with_path_if_its_given(self):
708 self.repo.run_git_command = mock.Mock(return_value=['', ''])
724 self.repo.run_git_command = mock.Mock(return_value=['', ''])
709 self.repo.get_diff(0, 1, 'foo')
725 self.repo.get_diff(0, 1, 'foo')
710 self.repo.run_git_command.assert_called_once_with(
726 self.repo.run_git_command.assert_called_once_with(
711 ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
727 ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
712 self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'])
728 self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'])
713
729
714
730
715 class GitRegressionTest(_BackendTestMixin, unittest.TestCase):
731 class GitRegressionTest(_BackendTestMixin, unittest.TestCase):
716 backend_alias = 'git'
732 backend_alias = 'git'
717
733
718 @classmethod
734 @classmethod
719 def _get_commits(cls):
735 def _get_commits(cls):
720 return [
736 return [
721 {
737 {
722 'message': 'Initial',
738 'message': 'Initial',
723 'author': 'Joe Doe <joe.doe@example.com>',
739 'author': 'Joe Doe <joe.doe@example.com>',
724 'date': datetime.datetime(2010, 1, 1, 20),
740 'date': datetime.datetime(2010, 1, 1, 20),
725 'added': [
741 'added': [
726 FileNode('bot/__init__.py', content='base'),
742 FileNode('bot/__init__.py', content='base'),
727 FileNode('bot/templates/404.html', content='base'),
743 FileNode('bot/templates/404.html', content='base'),
728 FileNode('bot/templates/500.html', content='base'),
744 FileNode('bot/templates/500.html', content='base'),
729 ],
745 ],
730 },
746 },
731 {
747 {
732 'message': 'Second',
748 'message': 'Second',
733 'author': 'Joe Doe <joe.doe@example.com>',
749 'author': 'Joe Doe <joe.doe@example.com>',
734 'date': datetime.datetime(2010, 1, 1, 22),
750 'date': datetime.datetime(2010, 1, 1, 22),
735 'added': [
751 'added': [
736 FileNode('bot/build/migrations/1.py', content='foo2'),
752 FileNode('bot/build/migrations/1.py', content='foo2'),
737 FileNode('bot/build/migrations/2.py', content='foo2'),
753 FileNode('bot/build/migrations/2.py', content='foo2'),
738 FileNode('bot/build/static/templates/f.html', content='foo2'),
754 FileNode('bot/build/static/templates/f.html', content='foo2'),
739 FileNode('bot/build/static/templates/f1.html', content='foo2'),
755 FileNode('bot/build/static/templates/f1.html', content='foo2'),
740 FileNode('bot/build/templates/err.html', content='foo2'),
756 FileNode('bot/build/templates/err.html', content='foo2'),
741 FileNode('bot/build/templates/err2.html', content='foo2'),
757 FileNode('bot/build/templates/err2.html', content='foo2'),
742 ],
758 ],
743 },
759 },
744 ]
760 ]
745
761
746 def test_similar_paths(self):
762 def test_similar_paths(self):
747 cs = self.repo.get_changeset()
763 cs = self.repo.get_changeset()
748 paths = lambda *n:[x.path for x in n]
764 paths = lambda *n:[x.path for x in n]
749 self.assertEqual(paths(*cs.get_nodes('bot')), ['bot/build', 'bot/templates', 'bot/__init__.py'])
765 self.assertEqual(paths(*cs.get_nodes('bot')), ['bot/build', 'bot/templates', 'bot/__init__.py'])
750 self.assertEqual(paths(*cs.get_nodes('bot/build')), ['bot/build/migrations', 'bot/build/static', 'bot/build/templates'])
766 self.assertEqual(paths(*cs.get_nodes('bot/build')), ['bot/build/migrations', 'bot/build/static', 'bot/build/templates'])
751 self.assertEqual(paths(*cs.get_nodes('bot/build/static')), ['bot/build/static/templates'])
767 self.assertEqual(paths(*cs.get_nodes('bot/build/static')), ['bot/build/static/templates'])
752 # this get_nodes below causes troubles !
768 # this get_nodes below causes troubles !
753 self.assertEqual(paths(*cs.get_nodes('bot/build/static/templates')), ['bot/build/static/templates/f.html', 'bot/build/static/templates/f1.html'])
769 self.assertEqual(paths(*cs.get_nodes('bot/build/static/templates')), ['bot/build/static/templates/f.html', 'bot/build/static/templates/f1.html'])
754 self.assertEqual(paths(*cs.get_nodes('bot/build/templates')), ['bot/build/templates/err.html', 'bot/build/templates/err2.html'])
770 self.assertEqual(paths(*cs.get_nodes('bot/build/templates')), ['bot/build/templates/err.html', 'bot/build/templates/err2.html'])
755 self.assertEqual(paths(*cs.get_nodes('bot/templates/')), ['bot/templates/404.html', 'bot/templates/500.html'])
771 self.assertEqual(paths(*cs.get_nodes('bot/templates/')), ['bot/templates/404.html', 'bot/templates/500.html'])
756
772
757
773
758 class GitHooksTest(unittest.TestCase):
774 class GitHooksTest(unittest.TestCase):
759 """
775 """
760 Tests related to hook functionality of Git repositories.
776 Tests related to hook functionality of Git repositories.
761 """
777 """
762
778
763 def setUp(self):
779 def setUp(self):
764 # For each run we want a fresh repo.
780 # For each run we want a fresh repo.
765 self.repo_directory = get_new_dir("githookrepo")
781 self.repo_directory = get_new_dir("githookrepo")
766 self.repo = GitRepository(self.repo_directory, create=True)
782 self.repo = GitRepository(self.repo_directory, create=True)
767
783
768 # Create a dictionary where keys are hook names, and values are paths to
784 # Create a dictionary where keys are hook names, and values are paths to
769 # them. Deduplicates code in tests a bit.
785 # them. Deduplicates code in tests a bit.
770 self.hook_directory = self.repo.get_hook_location()
786 self.hook_directory = self.repo.get_hook_location()
771 self.kallithea_hooks = {h: os.path.join(self.hook_directory, h) for h in ("pre-receive", "post-receive")}
787 self.kallithea_hooks = {h: os.path.join(self.hook_directory, h) for h in ("pre-receive", "post-receive")}
772
788
773 def test_hooks_created_if_missing(self):
789 def test_hooks_created_if_missing(self):
774 """
790 """
775 Tests if hooks are installed in repository if they are missing.
791 Tests if hooks are installed in repository if they are missing.
776 """
792 """
777
793
778 for hook, hook_path in self.kallithea_hooks.iteritems():
794 for hook, hook_path in self.kallithea_hooks.iteritems():
779 if os.path.exists(hook_path):
795 if os.path.exists(hook_path):
780 os.remove(hook_path)
796 os.remove(hook_path)
781
797
782 ScmModel().install_git_hooks(repo=self.repo)
798 ScmModel().install_git_hooks(repo=self.repo)
783
799
784 for hook, hook_path in self.kallithea_hooks.iteritems():
800 for hook, hook_path in self.kallithea_hooks.iteritems():
785 self.assertTrue(os.path.exists(hook_path))
801 self.assertTrue(os.path.exists(hook_path))
786
802
787 def test_kallithea_hooks_updated(self):
803 def test_kallithea_hooks_updated(self):
788 """
804 """
789 Tests if hooks are updated if they are Kallithea hooks already.
805 Tests if hooks are updated if they are Kallithea hooks already.
790 """
806 """
791
807
792 for hook, hook_path in self.kallithea_hooks.iteritems():
808 for hook, hook_path in self.kallithea_hooks.iteritems():
793 with open(hook_path, "w") as f:
809 with open(hook_path, "w") as f:
794 f.write("KALLITHEA_HOOK_VER=0.0.0\nJUST_BOGUS")
810 f.write("KALLITHEA_HOOK_VER=0.0.0\nJUST_BOGUS")
795
811
796 ScmModel().install_git_hooks(repo=self.repo)
812 ScmModel().install_git_hooks(repo=self.repo)
797
813
798 for hook, hook_path in self.kallithea_hooks.iteritems():
814 for hook, hook_path in self.kallithea_hooks.iteritems():
799 with open(hook_path) as f:
815 with open(hook_path) as f:
800 self.assertNotIn("JUST_BOGUS", f.read())
816 self.assertNotIn("JUST_BOGUS", f.read())
801
817
802 def test_custom_hooks_untouched(self):
818 def test_custom_hooks_untouched(self):
803 """
819 """
804 Tests if hooks are left untouched if they are not Kallithea hooks.
820 Tests if hooks are left untouched if they are not Kallithea hooks.
805 """
821 """
806
822
807 for hook, hook_path in self.kallithea_hooks.iteritems():
823 for hook, hook_path in self.kallithea_hooks.iteritems():
808 with open(hook_path, "w") as f:
824 with open(hook_path, "w") as f:
809 f.write("#!/bin/bash\n#CUSTOM_HOOK")
825 f.write("#!/bin/bash\n#CUSTOM_HOOK")
810
826
811 ScmModel().install_git_hooks(repo=self.repo)
827 ScmModel().install_git_hooks(repo=self.repo)
812
828
813 for hook, hook_path in self.kallithea_hooks.iteritems():
829 for hook, hook_path in self.kallithea_hooks.iteritems():
814 with open(hook_path) as f:
830 with open(hook_path) as f:
815 self.assertIn("CUSTOM_HOOK", f.read())
831 self.assertIn("CUSTOM_HOOK", f.read())
816
832
817 def test_custom_hooks_forced_update(self):
833 def test_custom_hooks_forced_update(self):
818 """
834 """
819 Tests if hooks are forcefully updated even though they are custom hooks.
835 Tests if hooks are forcefully updated even though they are custom hooks.
820 """
836 """
821
837
822 for hook, hook_path in self.kallithea_hooks.iteritems():
838 for hook, hook_path in self.kallithea_hooks.iteritems():
823 with open(hook_path, "w") as f:
839 with open(hook_path, "w") as f:
824 f.write("#!/bin/bash\n#CUSTOM_HOOK")
840 f.write("#!/bin/bash\n#CUSTOM_HOOK")
825
841
826 ScmModel().install_git_hooks(repo=self.repo, force_create=True)
842 ScmModel().install_git_hooks(repo=self.repo, force_create=True)
827
843
828 for hook, hook_path in self.kallithea_hooks.iteritems():
844 for hook, hook_path in self.kallithea_hooks.iteritems():
829 with open(hook_path) as f:
845 with open(hook_path) as f:
830 self.assertIn("KALLITHEA_HOOK_VER", f.read())
846 self.assertIn("KALLITHEA_HOOK_VER", f.read())
831
847
832
848
833 if __name__ == '__main__':
849 if __name__ == '__main__':
834 unittest.main()
850 unittest.main()
@@ -1,557 +1,574 b''
1
1
2 import os
2 import os
3 from kallithea.lib.vcs.backends.hg import MercurialRepository, MercurialChangeset
3 from kallithea.lib.vcs.backends.hg import MercurialRepository, MercurialChangeset
4 from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
4 from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
5 from kallithea.lib.vcs.nodes import NodeKind, NodeState
5 from kallithea.lib.vcs.nodes import NodeKind, NodeState
6 from kallithea.tests.vcs.conf import TEST_HG_REPO, TEST_HG_REPO_CLONE, \
6 from kallithea.tests.vcs.conf import TEST_HG_REPO, TEST_HG_REPO_CLONE, \
7 TEST_HG_REPO_PULL
7 TEST_HG_REPO_PULL
8 from kallithea.lib.vcs.utils.compat import unittest
8 from kallithea.lib.vcs.utils.compat import unittest
9
9
10
10
11 # Use only clean mercurial's ui
11 # Use only clean mercurial's ui
12 from kallithea.lib.vcs.utils.hgcompat import mercurial
12 from kallithea.lib.vcs.utils.hgcompat import mercurial
13 mercurial.scmutil.rcpath()
13 mercurial.scmutil.rcpath()
14 if mercurial.scmutil._rcpath:
14 if mercurial.scmutil._rcpath:
15 mercurial.scmutil._rcpath = mercurial.scmutil._rcpath[:1]
15 mercurial.scmutil._rcpath = mercurial.scmutil._rcpath[:1]
16
16
17
17
18 class MercurialRepositoryTest(unittest.TestCase):
18 class MercurialRepositoryTest(unittest.TestCase):
19
19
20 def __check_for_existing_repo(self):
20 def __check_for_existing_repo(self):
21 if os.path.exists(TEST_HG_REPO_CLONE):
21 if os.path.exists(TEST_HG_REPO_CLONE):
22 self.fail('Cannot test mercurial clone repo as location %s already '
22 self.fail('Cannot test mercurial clone repo as location %s already '
23 'exists. You should manually remove it first.'
23 'exists. You should manually remove it first.'
24 % TEST_HG_REPO_CLONE)
24 % TEST_HG_REPO_CLONE)
25
25
26 def setUp(self):
26 def setUp(self):
27 self.repo = MercurialRepository(TEST_HG_REPO)
27 self.repo = MercurialRepository(TEST_HG_REPO)
28
28
29 def test_wrong_repo_path(self):
29 def test_wrong_repo_path(self):
30 wrong_repo_path = '/tmp/errorrepo'
30 wrong_repo_path = '/tmp/errorrepo'
31 self.assertRaises(RepositoryError, MercurialRepository, wrong_repo_path)
31 self.assertRaises(RepositoryError, MercurialRepository, wrong_repo_path)
32
32
33 def test_unicode_path_repo(self):
33 def test_unicode_path_repo(self):
34 self.assertRaises(VCSError,lambda:MercurialRepository(u'iShouldFail'))
34 self.assertRaises(VCSError,lambda:MercurialRepository(u'iShouldFail'))
35
35
36 def test_repo_clone(self):
36 def test_repo_clone(self):
37 self.__check_for_existing_repo()
37 self.__check_for_existing_repo()
38 repo = MercurialRepository(TEST_HG_REPO)
38 repo = MercurialRepository(TEST_HG_REPO)
39 repo_clone = MercurialRepository(TEST_HG_REPO_CLONE,
39 repo_clone = MercurialRepository(TEST_HG_REPO_CLONE,
40 src_url=TEST_HG_REPO, update_after_clone=True)
40 src_url=TEST_HG_REPO, update_after_clone=True)
41 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
41 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
42 # Checking hashes of changesets should be enough
42 # Checking hashes of changesets should be enough
43 for changeset in repo.get_changesets():
43 for changeset in repo.get_changesets():
44 raw_id = changeset.raw_id
44 raw_id = changeset.raw_id
45 self.assertEqual(raw_id, repo_clone.get_changeset(raw_id).raw_id)
45 self.assertEqual(raw_id, repo_clone.get_changeset(raw_id).raw_id)
46
46
47 def test_repo_clone_with_update(self):
47 def test_repo_clone_with_update(self):
48 repo = MercurialRepository(TEST_HG_REPO)
48 repo = MercurialRepository(TEST_HG_REPO)
49 repo_clone = MercurialRepository(TEST_HG_REPO_CLONE + '_w_update',
49 repo_clone = MercurialRepository(TEST_HG_REPO_CLONE + '_w_update',
50 src_url=TEST_HG_REPO, update_after_clone=True)
50 src_url=TEST_HG_REPO, update_after_clone=True)
51 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
51 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
52
52
53 #check if current workdir was updated
53 #check if current workdir was updated
54 self.assertEqual(os.path.isfile(os.path.join(TEST_HG_REPO_CLONE \
54 self.assertEqual(os.path.isfile(os.path.join(TEST_HG_REPO_CLONE \
55 + '_w_update',
55 + '_w_update',
56 'MANIFEST.in')), True,)
56 'MANIFEST.in')), True,)
57
57
58 def test_repo_clone_without_update(self):
58 def test_repo_clone_without_update(self):
59 repo = MercurialRepository(TEST_HG_REPO)
59 repo = MercurialRepository(TEST_HG_REPO)
60 repo_clone = MercurialRepository(TEST_HG_REPO_CLONE + '_wo_update',
60 repo_clone = MercurialRepository(TEST_HG_REPO_CLONE + '_wo_update',
61 src_url=TEST_HG_REPO, update_after_clone=False)
61 src_url=TEST_HG_REPO, update_after_clone=False)
62 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
62 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
63 self.assertEqual(os.path.isfile(os.path.join(TEST_HG_REPO_CLONE \
63 self.assertEqual(os.path.isfile(os.path.join(TEST_HG_REPO_CLONE \
64 + '_wo_update',
64 + '_wo_update',
65 'MANIFEST.in')), False,)
65 'MANIFEST.in')), False,)
66
66
67 def test_pull(self):
67 def test_pull(self):
68 if os.path.exists(TEST_HG_REPO_PULL):
68 if os.path.exists(TEST_HG_REPO_PULL):
69 self.fail('Cannot test mercurial pull command as location %s '
69 self.fail('Cannot test mercurial pull command as location %s '
70 'already exists. You should manually remove it first'
70 'already exists. You should manually remove it first'
71 % TEST_HG_REPO_PULL)
71 % TEST_HG_REPO_PULL)
72 repo_new = MercurialRepository(TEST_HG_REPO_PULL, create=True)
72 repo_new = MercurialRepository(TEST_HG_REPO_PULL, create=True)
73 self.assertTrue(len(self.repo.revisions) > len(repo_new.revisions))
73 self.assertTrue(len(self.repo.revisions) > len(repo_new.revisions))
74
74
75 repo_new.pull(self.repo.path)
75 repo_new.pull(self.repo.path)
76 repo_new = MercurialRepository(TEST_HG_REPO_PULL)
76 repo_new = MercurialRepository(TEST_HG_REPO_PULL)
77 self.assertTrue(len(self.repo.revisions) == len(repo_new.revisions))
77 self.assertTrue(len(self.repo.revisions) == len(repo_new.revisions))
78
78
79 def test_revisions(self):
79 def test_revisions(self):
80 # there are 21 revisions at bitbucket now
80 # there are 21 revisions at bitbucket now
81 # so we can assume they would be available from now on
81 # so we can assume they would be available from now on
82 subset = set(['b986218ba1c9b0d6a259fac9b050b1724ed8e545',
82 subset = set(['b986218ba1c9b0d6a259fac9b050b1724ed8e545',
83 '3d8f361e72ab303da48d799ff1ac40d5ac37c67e',
83 '3d8f361e72ab303da48d799ff1ac40d5ac37c67e',
84 '6cba7170863a2411822803fa77a0a264f1310b35',
84 '6cba7170863a2411822803fa77a0a264f1310b35',
85 '56349e29c2af3ac913b28bde9a2c6154436e615b',
85 '56349e29c2af3ac913b28bde9a2c6154436e615b',
86 '2dda4e345facb0ccff1a191052dd1606dba6781d',
86 '2dda4e345facb0ccff1a191052dd1606dba6781d',
87 '6fff84722075f1607a30f436523403845f84cd9e',
87 '6fff84722075f1607a30f436523403845f84cd9e',
88 '7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7',
88 '7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7',
89 '3803844fdbd3b711175fc3da9bdacfcd6d29a6fb',
89 '3803844fdbd3b711175fc3da9bdacfcd6d29a6fb',
90 'dc5d2c0661b61928834a785d3e64a3f80d3aad9c',
90 'dc5d2c0661b61928834a785d3e64a3f80d3aad9c',
91 'be90031137367893f1c406e0a8683010fd115b79',
91 'be90031137367893f1c406e0a8683010fd115b79',
92 'db8e58be770518cbb2b1cdfa69146e47cd481481',
92 'db8e58be770518cbb2b1cdfa69146e47cd481481',
93 '84478366594b424af694a6c784cb991a16b87c21',
93 '84478366594b424af694a6c784cb991a16b87c21',
94 '17f8e105dddb9f339600389c6dc7175d395a535c',
94 '17f8e105dddb9f339600389c6dc7175d395a535c',
95 '20a662e756499bde3095ffc9bc0643d1def2d0eb',
95 '20a662e756499bde3095ffc9bc0643d1def2d0eb',
96 '2e319b85e70a707bba0beff866d9f9de032aa4f9',
96 '2e319b85e70a707bba0beff866d9f9de032aa4f9',
97 '786facd2c61deb9cf91e9534735124fb8fc11842',
97 '786facd2c61deb9cf91e9534735124fb8fc11842',
98 '94593d2128d38210a2fcd1aabff6dda0d6d9edf8',
98 '94593d2128d38210a2fcd1aabff6dda0d6d9edf8',
99 'aa6a0de05b7612707db567078e130a6cd114a9a7',
99 'aa6a0de05b7612707db567078e130a6cd114a9a7',
100 'eada5a770da98ab0dd7325e29d00e0714f228d09'
100 'eada5a770da98ab0dd7325e29d00e0714f228d09'
101 ])
101 ])
102 self.assertTrue(subset.issubset(set(self.repo.revisions)))
102 self.assertTrue(subset.issubset(set(self.repo.revisions)))
103
103
104
104
105 # check if we have the proper order of revisions
105 # check if we have the proper order of revisions
106 org = ['b986218ba1c9b0d6a259fac9b050b1724ed8e545',
106 org = ['b986218ba1c9b0d6a259fac9b050b1724ed8e545',
107 '3d8f361e72ab303da48d799ff1ac40d5ac37c67e',
107 '3d8f361e72ab303da48d799ff1ac40d5ac37c67e',
108 '6cba7170863a2411822803fa77a0a264f1310b35',
108 '6cba7170863a2411822803fa77a0a264f1310b35',
109 '56349e29c2af3ac913b28bde9a2c6154436e615b',
109 '56349e29c2af3ac913b28bde9a2c6154436e615b',
110 '2dda4e345facb0ccff1a191052dd1606dba6781d',
110 '2dda4e345facb0ccff1a191052dd1606dba6781d',
111 '6fff84722075f1607a30f436523403845f84cd9e',
111 '6fff84722075f1607a30f436523403845f84cd9e',
112 '7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7',
112 '7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7',
113 '3803844fdbd3b711175fc3da9bdacfcd6d29a6fb',
113 '3803844fdbd3b711175fc3da9bdacfcd6d29a6fb',
114 'dc5d2c0661b61928834a785d3e64a3f80d3aad9c',
114 'dc5d2c0661b61928834a785d3e64a3f80d3aad9c',
115 'be90031137367893f1c406e0a8683010fd115b79',
115 'be90031137367893f1c406e0a8683010fd115b79',
116 'db8e58be770518cbb2b1cdfa69146e47cd481481',
116 'db8e58be770518cbb2b1cdfa69146e47cd481481',
117 '84478366594b424af694a6c784cb991a16b87c21',
117 '84478366594b424af694a6c784cb991a16b87c21',
118 '17f8e105dddb9f339600389c6dc7175d395a535c',
118 '17f8e105dddb9f339600389c6dc7175d395a535c',
119 '20a662e756499bde3095ffc9bc0643d1def2d0eb',
119 '20a662e756499bde3095ffc9bc0643d1def2d0eb',
120 '2e319b85e70a707bba0beff866d9f9de032aa4f9',
120 '2e319b85e70a707bba0beff866d9f9de032aa4f9',
121 '786facd2c61deb9cf91e9534735124fb8fc11842',
121 '786facd2c61deb9cf91e9534735124fb8fc11842',
122 '94593d2128d38210a2fcd1aabff6dda0d6d9edf8',
122 '94593d2128d38210a2fcd1aabff6dda0d6d9edf8',
123 'aa6a0de05b7612707db567078e130a6cd114a9a7',
123 'aa6a0de05b7612707db567078e130a6cd114a9a7',
124 'eada5a770da98ab0dd7325e29d00e0714f228d09',
124 'eada5a770da98ab0dd7325e29d00e0714f228d09',
125 '2c1885c735575ca478bf9e17b0029dca68824458',
125 '2c1885c735575ca478bf9e17b0029dca68824458',
126 'd9bcd465040bf869799b09ad732c04e0eea99fe9',
126 'd9bcd465040bf869799b09ad732c04e0eea99fe9',
127 '469e9c847fe1f6f7a697b8b25b4bc5b48780c1a7',
127 '469e9c847fe1f6f7a697b8b25b4bc5b48780c1a7',
128 '4fb8326d78e5120da2c7468dcf7098997be385da',
128 '4fb8326d78e5120da2c7468dcf7098997be385da',
129 '62b4a097164940bd66030c4db51687f3ec035eed',
129 '62b4a097164940bd66030c4db51687f3ec035eed',
130 '536c1a19428381cfea92ac44985304f6a8049569',
130 '536c1a19428381cfea92ac44985304f6a8049569',
131 '965e8ab3c44b070cdaa5bf727ddef0ada980ecc4',
131 '965e8ab3c44b070cdaa5bf727ddef0ada980ecc4',
132 '9bb326a04ae5d98d437dece54be04f830cf1edd9',
132 '9bb326a04ae5d98d437dece54be04f830cf1edd9',
133 'f8940bcb890a98c4702319fbe36db75ea309b475',
133 'f8940bcb890a98c4702319fbe36db75ea309b475',
134 'ff5ab059786ebc7411e559a2cc309dfae3625a3b',
134 'ff5ab059786ebc7411e559a2cc309dfae3625a3b',
135 '6b6ad5f82ad5bb6190037671bd254bd4e1f4bf08',
135 '6b6ad5f82ad5bb6190037671bd254bd4e1f4bf08',
136 'ee87846a61c12153b51543bf860e1026c6d3dcba', ]
136 'ee87846a61c12153b51543bf860e1026c6d3dcba', ]
137 self.assertEqual(org, self.repo.revisions[:31])
137 self.assertEqual(org, self.repo.revisions[:31])
138
138
139 def test_iter_slice(self):
139 def test_iter_slice(self):
140 sliced = list(self.repo[:10])
140 sliced = list(self.repo[:10])
141 itered = list(self.repo)[:10]
141 itered = list(self.repo)[:10]
142 self.assertEqual(sliced, itered)
142 self.assertEqual(sliced, itered)
143
143
144 def test_slicing(self):
144 def test_slicing(self):
145 #4 1 5 10 95
145 #4 1 5 10 95
146 for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5),
146 for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5),
147 (10, 20, 10), (5, 100, 95)]:
147 (10, 20, 10), (5, 100, 95)]:
148 revs = list(self.repo[sfrom:sto])
148 revs = list(self.repo[sfrom:sto])
149 self.assertEqual(len(revs), size)
149 self.assertEqual(len(revs), size)
150 self.assertEqual(revs[0], self.repo.get_changeset(sfrom))
150 self.assertEqual(revs[0], self.repo.get_changeset(sfrom))
151 self.assertEqual(revs[-1], self.repo.get_changeset(sto - 1))
151 self.assertEqual(revs[-1], self.repo.get_changeset(sto - 1))
152
152
153 def test_branches(self):
153 def test_branches(self):
154 # TODO: Need more tests here
154 # TODO: Need more tests here
155
155
156 #active branches
156 #active branches
157 self.assertTrue('default' in self.repo.branches)
157 self.assertTrue('default' in self.repo.branches)
158 self.assertTrue('stable' in self.repo.branches)
158 self.assertTrue('stable' in self.repo.branches)
159
159
160 # closed
160 # closed
161 self.assertTrue('git' in self.repo._get_branches(closed=True))
161 self.assertTrue('git' in self.repo._get_branches(closed=True))
162 self.assertTrue('web' in self.repo._get_branches(closed=True))
162 self.assertTrue('web' in self.repo._get_branches(closed=True))
163
163
164 for name, id in self.repo.branches.items():
164 for name, id in self.repo.branches.items():
165 self.assertTrue(isinstance(
165 self.assertTrue(isinstance(
166 self.repo.get_changeset(id), MercurialChangeset))
166 self.repo.get_changeset(id), MercurialChangeset))
167
167
168 def test_tip_in_tags(self):
168 def test_tip_in_tags(self):
169 # tip is always a tag
169 # tip is always a tag
170 self.assertIn('tip', self.repo.tags)
170 self.assertIn('tip', self.repo.tags)
171
171
172 def test_tip_changeset_in_tags(self):
172 def test_tip_changeset_in_tags(self):
173 tip = self.repo.get_changeset()
173 tip = self.repo.get_changeset()
174 self.assertEqual(self.repo.tags['tip'], tip.raw_id)
174 self.assertEqual(self.repo.tags['tip'], tip.raw_id)
175
175
176 def test_initial_changeset(self):
176 def test_initial_changeset(self):
177
177
178 init_chset = self.repo.get_changeset(0)
178 init_chset = self.repo.get_changeset(0)
179 self.assertEqual(init_chset.message, 'initial import')
179 self.assertEqual(init_chset.message, 'initial import')
180 self.assertEqual(init_chset.author,
180 self.assertEqual(init_chset.author,
181 'Marcin Kuzminski <marcin@python-blog.com>')
181 'Marcin Kuzminski <marcin@python-blog.com>')
182 self.assertEqual(sorted(init_chset._file_paths),
182 self.assertEqual(sorted(init_chset._file_paths),
183 sorted([
183 sorted([
184 'vcs/__init__.py',
184 'vcs/__init__.py',
185 'vcs/backends/BaseRepository.py',
185 'vcs/backends/BaseRepository.py',
186 'vcs/backends/__init__.py',
186 'vcs/backends/__init__.py',
187 ])
187 ])
188 )
188 )
189 self.assertEqual(sorted(init_chset._dir_paths),
189 self.assertEqual(sorted(init_chset._dir_paths),
190 sorted(['', 'vcs', 'vcs/backends']))
190 sorted(['', 'vcs', 'vcs/backends']))
191
191
192 self.assertRaises(NodeDoesNotExistError, init_chset.get_node, path='foobar')
192 self.assertRaises(NodeDoesNotExistError, init_chset.get_node, path='foobar')
193
193
194 node = init_chset.get_node('vcs/')
194 node = init_chset.get_node('vcs/')
195 self.assertTrue(hasattr(node, 'kind'))
195 self.assertTrue(hasattr(node, 'kind'))
196 self.assertEqual(node.kind, NodeKind.DIR)
196 self.assertEqual(node.kind, NodeKind.DIR)
197
197
198 node = init_chset.get_node('vcs')
198 node = init_chset.get_node('vcs')
199 self.assertTrue(hasattr(node, 'kind'))
199 self.assertTrue(hasattr(node, 'kind'))
200 self.assertEqual(node.kind, NodeKind.DIR)
200 self.assertEqual(node.kind, NodeKind.DIR)
201
201
202 node = init_chset.get_node('vcs/__init__.py')
202 node = init_chset.get_node('vcs/__init__.py')
203 self.assertTrue(hasattr(node, 'kind'))
203 self.assertTrue(hasattr(node, 'kind'))
204 self.assertEqual(node.kind, NodeKind.FILE)
204 self.assertEqual(node.kind, NodeKind.FILE)
205
205
206 def test_not_existing_changeset(self):
206 def test_not_existing_changeset(self):
207 #rawid
207 #rawid
208 self.assertRaises(RepositoryError, self.repo.get_changeset,
208 self.assertRaises(RepositoryError, self.repo.get_changeset,
209 'abcd' * 10)
209 'abcd' * 10)
210 #shortid
210 #shortid
211 self.assertRaises(RepositoryError, self.repo.get_changeset,
211 self.assertRaises(RepositoryError, self.repo.get_changeset,
212 'erro' * 4)
212 'erro' * 4)
213 #numeric
213 #numeric
214 self.assertRaises(RepositoryError, self.repo.get_changeset,
214 self.assertRaises(RepositoryError, self.repo.get_changeset,
215 self.repo.count() + 1)
215 self.repo.count() + 1)
216
216
217
217
218 # Small chance we ever get to this one
218 # Small chance we ever get to this one
219 revision = pow(2, 30)
219 revision = pow(2, 30)
220 self.assertRaises(RepositoryError, self.repo.get_changeset, revision)
220 self.assertRaises(RepositoryError, self.repo.get_changeset, revision)
221
221
222 def test_changeset10(self):
222 def test_changeset10(self):
223
223
224 chset10 = self.repo.get_changeset(10)
224 chset10 = self.repo.get_changeset(10)
225 README = """===
225 README = """===
226 VCS
226 VCS
227 ===
227 ===
228
228
229 Various Version Control System management abstraction layer for Python.
229 Various Version Control System management abstraction layer for Python.
230
230
231 Introduction
231 Introduction
232 ------------
232 ------------
233
233
234 TODO: To be written...
234 TODO: To be written...
235
235
236 """
236 """
237 node = chset10.get_node('README.rst')
237 node = chset10.get_node('README.rst')
238 self.assertEqual(node.kind, NodeKind.FILE)
238 self.assertEqual(node.kind, NodeKind.FILE)
239 self.assertEqual(node.content, README)
239 self.assertEqual(node.content, README)
240
240
241
241
242 class MercurialChangesetTest(unittest.TestCase):
242 class MercurialChangesetTest(unittest.TestCase):
243
243
244 def setUp(self):
244 def setUp(self):
245 self.repo = MercurialRepository(TEST_HG_REPO)
245 self.repo = MercurialRepository(TEST_HG_REPO)
246
246
247 def _test_equality(self, changeset):
247 def _test_equality(self, changeset):
248 revision = changeset.revision
248 revision = changeset.revision
249 self.assertEqual(changeset, self.repo.get_changeset(revision))
249 self.assertEqual(changeset, self.repo.get_changeset(revision))
250
250
251 def test_equality(self):
251 def test_equality(self):
252 self.setUp()
252 self.setUp()
253 revs = [0, 10, 20]
253 revs = [0, 10, 20]
254 changesets = [self.repo.get_changeset(rev) for rev in revs]
254 changesets = [self.repo.get_changeset(rev) for rev in revs]
255 for changeset in changesets:
255 for changeset in changesets:
256 self._test_equality(changeset)
256 self._test_equality(changeset)
257
257
258 def test_default_changeset(self):
258 def test_default_changeset(self):
259 tip = self.repo.get_changeset('tip')
259 tip = self.repo.get_changeset('tip')
260 self.assertEqual(tip, self.repo.get_changeset())
260 self.assertEqual(tip, self.repo.get_changeset())
261 self.assertEqual(tip, self.repo.get_changeset(revision=None))
261 self.assertEqual(tip, self.repo.get_changeset(revision=None))
262 self.assertEqual(tip, list(self.repo[-1:])[0])
262 self.assertEqual(tip, list(self.repo[-1:])[0])
263
263
264 def test_root_node(self):
264 def test_root_node(self):
265 tip = self.repo.get_changeset('tip')
265 tip = self.repo.get_changeset('tip')
266 self.assertTrue(tip.root is tip.get_node(''))
266 self.assertTrue(tip.root is tip.get_node(''))
267
267
268 def test_lazy_fetch(self):
268 def test_lazy_fetch(self):
269 """
269 """
270 Test if changeset's nodes expands and are cached as we walk through
270 Test if changeset's nodes expands and are cached as we walk through
271 the revision. This test is somewhat hard to write as order of tests
271 the revision. This test is somewhat hard to write as order of tests
272 is a key here. Written by running command after command in a shell.
272 is a key here. Written by running command after command in a shell.
273 """
273 """
274 self.setUp()
274 self.setUp()
275 chset = self.repo.get_changeset(45)
275 chset = self.repo.get_changeset(45)
276 self.assertTrue(len(chset.nodes) == 0)
276 self.assertTrue(len(chset.nodes) == 0)
277 root = chset.root
277 root = chset.root
278 self.assertTrue(len(chset.nodes) == 1)
278 self.assertTrue(len(chset.nodes) == 1)
279 self.assertTrue(len(root.nodes) == 8)
279 self.assertTrue(len(root.nodes) == 8)
280 # accessing root.nodes updates chset.nodes
280 # accessing root.nodes updates chset.nodes
281 self.assertTrue(len(chset.nodes) == 9)
281 self.assertTrue(len(chset.nodes) == 9)
282
282
283 docs = root.get_node('docs')
283 docs = root.get_node('docs')
284 # we haven't yet accessed anything new as docs dir was already cached
284 # we haven't yet accessed anything new as docs dir was already cached
285 self.assertTrue(len(chset.nodes) == 9)
285 self.assertTrue(len(chset.nodes) == 9)
286 self.assertTrue(len(docs.nodes) == 8)
286 self.assertTrue(len(docs.nodes) == 8)
287 # accessing docs.nodes updates chset.nodes
287 # accessing docs.nodes updates chset.nodes
288 self.assertTrue(len(chset.nodes) == 17)
288 self.assertTrue(len(chset.nodes) == 17)
289
289
290 self.assertTrue(docs is chset.get_node('docs'))
290 self.assertTrue(docs is chset.get_node('docs'))
291 self.assertTrue(docs is root.nodes[0])
291 self.assertTrue(docs is root.nodes[0])
292 self.assertTrue(docs is root.dirs[0])
292 self.assertTrue(docs is root.dirs[0])
293 self.assertTrue(docs is chset.get_node('docs'))
293 self.assertTrue(docs is chset.get_node('docs'))
294
294
295 def test_nodes_with_changeset(self):
295 def test_nodes_with_changeset(self):
296 self.setUp()
296 self.setUp()
297 chset = self.repo.get_changeset(45)
297 chset = self.repo.get_changeset(45)
298 root = chset.root
298 root = chset.root
299 docs = root.get_node('docs')
299 docs = root.get_node('docs')
300 self.assertTrue(docs is chset.get_node('docs'))
300 self.assertTrue(docs is chset.get_node('docs'))
301 api = docs.get_node('api')
301 api = docs.get_node('api')
302 self.assertTrue(api is chset.get_node('docs/api'))
302 self.assertTrue(api is chset.get_node('docs/api'))
303 index = api.get_node('index.rst')
303 index = api.get_node('index.rst')
304 self.assertTrue(index is chset.get_node('docs/api/index.rst'))
304 self.assertTrue(index is chset.get_node('docs/api/index.rst'))
305 self.assertTrue(index is chset.get_node('docs')\
305 self.assertTrue(index is chset.get_node('docs')\
306 .get_node('api')\
306 .get_node('api')\
307 .get_node('index.rst'))
307 .get_node('index.rst'))
308
308
309 def test_branch_and_tags(self):
309 def test_branch_and_tags(self):
310 chset0 = self.repo.get_changeset(0)
310 chset0 = self.repo.get_changeset(0)
311 self.assertEqual(chset0.branch, 'default')
311 self.assertEqual(chset0.branch, 'default')
312 self.assertEqual(chset0.tags, [])
312 self.assertEqual(chset0.tags, [])
313
313
314 chset10 = self.repo.get_changeset(10)
314 chset10 = self.repo.get_changeset(10)
315 self.assertEqual(chset10.branch, 'default')
315 self.assertEqual(chset10.branch, 'default')
316 self.assertEqual(chset10.tags, [])
316 self.assertEqual(chset10.tags, [])
317
317
318 chset44 = self.repo.get_changeset(44)
318 chset44 = self.repo.get_changeset(44)
319 self.assertEqual(chset44.branch, 'web')
319 self.assertEqual(chset44.branch, 'web')
320
320
321 tip = self.repo.get_changeset('tip')
321 tip = self.repo.get_changeset('tip')
322 self.assertTrue('tip' in tip.tags)
322 self.assertTrue('tip' in tip.tags)
323
323
324 def _test_file_size(self, revision, path, size):
324 def _test_file_size(self, revision, path, size):
325 node = self.repo.get_changeset(revision).get_node(path)
325 node = self.repo.get_changeset(revision).get_node(path)
326 self.assertTrue(node.is_file())
326 self.assertTrue(node.is_file())
327 self.assertEqual(node.size, size)
327 self.assertEqual(node.size, size)
328
328
329 def test_file_size(self):
329 def test_file_size(self):
330 to_check = (
330 to_check = (
331 (10, 'setup.py', 1068),
331 (10, 'setup.py', 1068),
332 (20, 'setup.py', 1106),
332 (20, 'setup.py', 1106),
333 (60, 'setup.py', 1074),
333 (60, 'setup.py', 1074),
334
334
335 (10, 'vcs/backends/base.py', 2921),
335 (10, 'vcs/backends/base.py', 2921),
336 (20, 'vcs/backends/base.py', 3936),
336 (20, 'vcs/backends/base.py', 3936),
337 (60, 'vcs/backends/base.py', 6189),
337 (60, 'vcs/backends/base.py', 6189),
338 )
338 )
339 for revision, path, size in to_check:
339 for revision, path, size in to_check:
340 self._test_file_size(revision, path, size)
340 self._test_file_size(revision, path, size)
341
341
342 def _test_dir_size(self, revision, path, size):
343 node = self.repo.get_changeset(revision).get_node(path)
344 self.assertFalse(node.is_file())
345 self.assertEqual(node.size, size)
346
347 def test_dir_size(self):
348 to_check = (
349 ('96507bd11ecc', '/', 682421),
350 ('a53d9201d4bc', '/', 682410),
351 ('90243de06161', '/', 682006),
352 )
353 for revision, path, size in to_check:
354 self._test_dir_size(revision, path, size)
355
356 def test_repo_size(self):
357 self.assertEqual(self.repo.size, 1042958) # FIXME
358
342 def test_file_history(self):
359 def test_file_history(self):
343 # we can only check if those revisions are present in the history
360 # we can only check if those revisions are present in the history
344 # as we cannot update this test every time file is changed
361 # as we cannot update this test every time file is changed
345 files = {
362 files = {
346 'setup.py': [7, 18, 45, 46, 47, 69, 77],
363 'setup.py': [7, 18, 45, 46, 47, 69, 77],
347 'vcs/nodes.py': [7, 8, 24, 26, 30, 45, 47, 49, 56, 57, 58, 59, 60,
364 'vcs/nodes.py': [7, 8, 24, 26, 30, 45, 47, 49, 56, 57, 58, 59, 60,
348 61, 73, 76],
365 61, 73, 76],
349 'vcs/backends/hg.py': [4, 5, 6, 11, 12, 13, 14, 15, 16, 21, 22, 23,
366 'vcs/backends/hg.py': [4, 5, 6, 11, 12, 13, 14, 15, 16, 21, 22, 23,
350 26, 27, 28, 30, 31, 33, 35, 36, 37, 38, 39, 40, 41, 44, 45, 47,
367 26, 27, 28, 30, 31, 33, 35, 36, 37, 38, 39, 40, 41, 44, 45, 47,
351 48, 49, 53, 54, 55, 58, 60, 61, 67, 68, 69, 70, 73, 77, 78, 79,
368 48, 49, 53, 54, 55, 58, 60, 61, 67, 68, 69, 70, 73, 77, 78, 79,
352 82],
369 82],
353 }
370 }
354 for path, revs in files.items():
371 for path, revs in files.items():
355 tip = self.repo.get_changeset(revs[-1])
372 tip = self.repo.get_changeset(revs[-1])
356 node = tip.get_node(path)
373 node = tip.get_node(path)
357 node_revs = [chset.revision for chset in node.history]
374 node_revs = [chset.revision for chset in node.history]
358 self.assertTrue(set(revs).issubset(set(node_revs)),
375 self.assertTrue(set(revs).issubset(set(node_revs)),
359 "We assumed that %s is subset of revisions for which file %s "
376 "We assumed that %s is subset of revisions for which file %s "
360 "has been changed, and history of that node returned: %s"
377 "has been changed, and history of that node returned: %s"
361 % (revs, path, node_revs))
378 % (revs, path, node_revs))
362
379
363 def test_file_annotate(self):
380 def test_file_annotate(self):
364 files = {
381 files = {
365 'vcs/backends/__init__.py':
382 'vcs/backends/__init__.py':
366 {89: {'lines_no': 31,
383 {89: {'lines_no': 31,
367 'changesets': [32, 32, 61, 32, 32, 37, 32, 32, 32, 44,
384 'changesets': [32, 32, 61, 32, 32, 37, 32, 32, 32, 44,
368 37, 37, 37, 37, 45, 37, 44, 37, 37, 37,
385 37, 37, 37, 37, 45, 37, 44, 37, 37, 37,
369 32, 32, 32, 32, 37, 32, 37, 37, 32,
386 32, 32, 32, 32, 37, 32, 37, 37, 32,
370 32, 32]},
387 32, 32]},
371 20: {'lines_no': 1,
388 20: {'lines_no': 1,
372 'changesets': [4]},
389 'changesets': [4]},
373 55: {'lines_no': 31,
390 55: {'lines_no': 31,
374 'changesets': [32, 32, 45, 32, 32, 37, 32, 32, 32, 44,
391 'changesets': [32, 32, 45, 32, 32, 37, 32, 32, 32, 44,
375 37, 37, 37, 37, 45, 37, 44, 37, 37, 37,
392 37, 37, 37, 37, 45, 37, 44, 37, 37, 37,
376 32, 32, 32, 32, 37, 32, 37, 37, 32,
393 32, 32, 32, 32, 37, 32, 37, 37, 32,
377 32, 32]}},
394 32, 32]}},
378 'vcs/exceptions.py':
395 'vcs/exceptions.py':
379 {89: {'lines_no': 18,
396 {89: {'lines_no': 18,
380 'changesets': [16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
397 'changesets': [16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
381 16, 16, 17, 16, 16, 18, 18, 18]},
398 16, 16, 17, 16, 16, 18, 18, 18]},
382 20: {'lines_no': 18,
399 20: {'lines_no': 18,
383 'changesets': [16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
400 'changesets': [16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
384 16, 16, 17, 16, 16, 18, 18, 18]},
401 16, 16, 17, 16, 16, 18, 18, 18]},
385 55: {'lines_no': 18, 'changesets': [16, 16, 16, 16, 16, 16,
402 55: {'lines_no': 18, 'changesets': [16, 16, 16, 16, 16, 16,
386 16, 16, 16, 16, 16, 16,
403 16, 16, 16, 16, 16, 16,
387 17, 16, 16, 18, 18, 18]}},
404 17, 16, 16, 18, 18, 18]}},
388 'MANIFEST.in': {89: {'lines_no': 5,
405 'MANIFEST.in': {89: {'lines_no': 5,
389 'changesets': [7, 7, 7, 71, 71]},
406 'changesets': [7, 7, 7, 71, 71]},
390 20: {'lines_no': 3,
407 20: {'lines_no': 3,
391 'changesets': [7, 7, 7]},
408 'changesets': [7, 7, 7]},
392 55: {'lines_no': 3,
409 55: {'lines_no': 3,
393 'changesets': [7, 7, 7]}}}
410 'changesets': [7, 7, 7]}}}
394
411
395 for fname, revision_dict in files.items():
412 for fname, revision_dict in files.items():
396 for rev, data in revision_dict.items():
413 for rev, data in revision_dict.items():
397 cs = self.repo.get_changeset(rev)
414 cs = self.repo.get_changeset(rev)
398 l1_1 = [x[1] for x in cs.get_file_annotate(fname)]
415 l1_1 = [x[1] for x in cs.get_file_annotate(fname)]
399 l1_2 = [x[2]().raw_id for x in cs.get_file_annotate(fname)]
416 l1_2 = [x[2]().raw_id for x in cs.get_file_annotate(fname)]
400 self.assertEqual(l1_1, l1_2)
417 self.assertEqual(l1_1, l1_2)
401 l1 = l1_2 = [x[2]().revision for x in cs.get_file_annotate(fname)]
418 l1 = l1_2 = [x[2]().revision for x in cs.get_file_annotate(fname)]
402 l2 = files[fname][rev]['changesets']
419 l2 = files[fname][rev]['changesets']
403 self.assertTrue(l1 == l2 , "The lists of revision for %s@rev%s"
420 self.assertTrue(l1 == l2 , "The lists of revision for %s@rev%s"
404 "from annotation list should match each other,"
421 "from annotation list should match each other,"
405 "got \n%s \nvs \n%s " % (fname, rev, l1, l2))
422 "got \n%s \nvs \n%s " % (fname, rev, l1, l2))
406
423
407 def test_changeset_state(self):
424 def test_changeset_state(self):
408 """
425 """
409 Tests which files have been added/changed/removed at particular revision
426 Tests which files have been added/changed/removed at particular revision
410 """
427 """
411
428
412 # rev 46ad32a4f974:
429 # rev 46ad32a4f974:
413 # hg st --rev 46ad32a4f974
430 # hg st --rev 46ad32a4f974
414 # changed: 13
431 # changed: 13
415 # added: 20
432 # added: 20
416 # removed: 1
433 # removed: 1
417 changed = set(['.hgignore'
434 changed = set(['.hgignore'
418 , 'README.rst' , 'docs/conf.py' , 'docs/index.rst' , 'setup.py'
435 , 'README.rst' , 'docs/conf.py' , 'docs/index.rst' , 'setup.py'
419 , 'tests/test_hg.py' , 'tests/test_nodes.py' , 'vcs/__init__.py'
436 , 'tests/test_hg.py' , 'tests/test_nodes.py' , 'vcs/__init__.py'
420 , 'vcs/backends/__init__.py' , 'vcs/backends/base.py'
437 , 'vcs/backends/__init__.py' , 'vcs/backends/base.py'
421 , 'vcs/backends/hg.py' , 'vcs/nodes.py' , 'vcs/utils/__init__.py'])
438 , 'vcs/backends/hg.py' , 'vcs/nodes.py' , 'vcs/utils/__init__.py'])
422
439
423 added = set(['docs/api/backends/hg.rst'
440 added = set(['docs/api/backends/hg.rst'
424 , 'docs/api/backends/index.rst' , 'docs/api/index.rst'
441 , 'docs/api/backends/index.rst' , 'docs/api/index.rst'
425 , 'docs/api/nodes.rst' , 'docs/api/web/index.rst'
442 , 'docs/api/nodes.rst' , 'docs/api/web/index.rst'
426 , 'docs/api/web/simplevcs.rst' , 'docs/installation.rst'
443 , 'docs/api/web/simplevcs.rst' , 'docs/installation.rst'
427 , 'docs/quickstart.rst' , 'setup.cfg' , 'vcs/utils/baseui_config.py'
444 , 'docs/quickstart.rst' , 'setup.cfg' , 'vcs/utils/baseui_config.py'
428 , 'vcs/utils/web.py' , 'vcs/web/__init__.py' , 'vcs/web/exceptions.py'
445 , 'vcs/utils/web.py' , 'vcs/web/__init__.py' , 'vcs/web/exceptions.py'
429 , 'vcs/web/simplevcs/__init__.py' , 'vcs/web/simplevcs/exceptions.py'
446 , 'vcs/web/simplevcs/__init__.py' , 'vcs/web/simplevcs/exceptions.py'
430 , 'vcs/web/simplevcs/middleware.py' , 'vcs/web/simplevcs/models.py'
447 , 'vcs/web/simplevcs/middleware.py' , 'vcs/web/simplevcs/models.py'
431 , 'vcs/web/simplevcs/settings.py' , 'vcs/web/simplevcs/utils.py'
448 , 'vcs/web/simplevcs/settings.py' , 'vcs/web/simplevcs/utils.py'
432 , 'vcs/web/simplevcs/views.py'])
449 , 'vcs/web/simplevcs/views.py'])
433
450
434 removed = set(['docs/api.rst'])
451 removed = set(['docs/api.rst'])
435
452
436 chset64 = self.repo.get_changeset('46ad32a4f974')
453 chset64 = self.repo.get_changeset('46ad32a4f974')
437 self.assertEqual(set((node.path for node in chset64.added)), added)
454 self.assertEqual(set((node.path for node in chset64.added)), added)
438 self.assertEqual(set((node.path for node in chset64.changed)), changed)
455 self.assertEqual(set((node.path for node in chset64.changed)), changed)
439 self.assertEqual(set((node.path for node in chset64.removed)), removed)
456 self.assertEqual(set((node.path for node in chset64.removed)), removed)
440
457
441 # rev b090f22d27d6:
458 # rev b090f22d27d6:
442 # hg st --rev b090f22d27d6
459 # hg st --rev b090f22d27d6
443 # changed: 13
460 # changed: 13
444 # added: 20
461 # added: 20
445 # removed: 1
462 # removed: 1
446 chset88 = self.repo.get_changeset('b090f22d27d6')
463 chset88 = self.repo.get_changeset('b090f22d27d6')
447 self.assertEqual(set((node.path for node in chset88.added)), set())
464 self.assertEqual(set((node.path for node in chset88.added)), set())
448 self.assertEqual(set((node.path for node in chset88.changed)),
465 self.assertEqual(set((node.path for node in chset88.changed)),
449 set(['.hgignore']))
466 set(['.hgignore']))
450 self.assertEqual(set((node.path for node in chset88.removed)), set())
467 self.assertEqual(set((node.path for node in chset88.removed)), set())
451 #
468 #
452 # 85:
469 # 85:
453 # added: 2 ['vcs/utils/diffs.py', 'vcs/web/simplevcs/views/diffs.py']
470 # added: 2 ['vcs/utils/diffs.py', 'vcs/web/simplevcs/views/diffs.py']
454 # changed: 4 ['vcs/web/simplevcs/models.py', ...]
471 # changed: 4 ['vcs/web/simplevcs/models.py', ...]
455 # removed: 1 ['vcs/utils/web.py']
472 # removed: 1 ['vcs/utils/web.py']
456 chset85 = self.repo.get_changeset(85)
473 chset85 = self.repo.get_changeset(85)
457 self.assertEqual(set((node.path for node in chset85.added)), set([
474 self.assertEqual(set((node.path for node in chset85.added)), set([
458 'vcs/utils/diffs.py',
475 'vcs/utils/diffs.py',
459 'vcs/web/simplevcs/views/diffs.py']))
476 'vcs/web/simplevcs/views/diffs.py']))
460 self.assertEqual(set((node.path for node in chset85.changed)), set([
477 self.assertEqual(set((node.path for node in chset85.changed)), set([
461 'vcs/web/simplevcs/models.py',
478 'vcs/web/simplevcs/models.py',
462 'vcs/web/simplevcs/utils.py',
479 'vcs/web/simplevcs/utils.py',
463 'vcs/web/simplevcs/views/__init__.py',
480 'vcs/web/simplevcs/views/__init__.py',
464 'vcs/web/simplevcs/views/repository.py',
481 'vcs/web/simplevcs/views/repository.py',
465 ]))
482 ]))
466 self.assertEqual(set((node.path for node in chset85.removed)),
483 self.assertEqual(set((node.path for node in chset85.removed)),
467 set(['vcs/utils/web.py']))
484 set(['vcs/utils/web.py']))
468
485
469
486
470 def test_files_state(self):
487 def test_files_state(self):
471 """
488 """
472 Tests state of FileNodes.
489 Tests state of FileNodes.
473 """
490 """
474 chset = self.repo.get_changeset(85)
491 chset = self.repo.get_changeset(85)
475 node = chset.get_node('vcs/utils/diffs.py')
492 node = chset.get_node('vcs/utils/diffs.py')
476 self.assertTrue(node.state, NodeState.ADDED)
493 self.assertTrue(node.state, NodeState.ADDED)
477 self.assertTrue(node.added)
494 self.assertTrue(node.added)
478 self.assertFalse(node.changed)
495 self.assertFalse(node.changed)
479 self.assertFalse(node.not_changed)
496 self.assertFalse(node.not_changed)
480 self.assertFalse(node.removed)
497 self.assertFalse(node.removed)
481
498
482 chset = self.repo.get_changeset(88)
499 chset = self.repo.get_changeset(88)
483 node = chset.get_node('.hgignore')
500 node = chset.get_node('.hgignore')
484 self.assertTrue(node.state, NodeState.CHANGED)
501 self.assertTrue(node.state, NodeState.CHANGED)
485 self.assertFalse(node.added)
502 self.assertFalse(node.added)
486 self.assertTrue(node.changed)
503 self.assertTrue(node.changed)
487 self.assertFalse(node.not_changed)
504 self.assertFalse(node.not_changed)
488 self.assertFalse(node.removed)
505 self.assertFalse(node.removed)
489
506
490 chset = self.repo.get_changeset(85)
507 chset = self.repo.get_changeset(85)
491 node = chset.get_node('setup.py')
508 node = chset.get_node('setup.py')
492 self.assertTrue(node.state, NodeState.NOT_CHANGED)
509 self.assertTrue(node.state, NodeState.NOT_CHANGED)
493 self.assertFalse(node.added)
510 self.assertFalse(node.added)
494 self.assertFalse(node.changed)
511 self.assertFalse(node.changed)
495 self.assertTrue(node.not_changed)
512 self.assertTrue(node.not_changed)
496 self.assertFalse(node.removed)
513 self.assertFalse(node.removed)
497
514
498 # If node has REMOVED state then trying to fetch it would raise
515 # If node has REMOVED state then trying to fetch it would raise
499 # ChangesetError exception
516 # ChangesetError exception
500 chset = self.repo.get_changeset(2)
517 chset = self.repo.get_changeset(2)
501 path = 'vcs/backends/BaseRepository.py'
518 path = 'vcs/backends/BaseRepository.py'
502 self.assertRaises(NodeDoesNotExistError, chset.get_node, path)
519 self.assertRaises(NodeDoesNotExistError, chset.get_node, path)
503 # but it would be one of ``removed`` (changeset's attribute)
520 # but it would be one of ``removed`` (changeset's attribute)
504 self.assertTrue(path in [rf.path for rf in chset.removed])
521 self.assertTrue(path in [rf.path for rf in chset.removed])
505
522
506 def test_commit_message_is_unicode(self):
523 def test_commit_message_is_unicode(self):
507 for cm in self.repo:
524 for cm in self.repo:
508 self.assertEqual(type(cm.message), unicode)
525 self.assertEqual(type(cm.message), unicode)
509
526
510 def test_changeset_author_is_unicode(self):
527 def test_changeset_author_is_unicode(self):
511 for cm in self.repo:
528 for cm in self.repo:
512 self.assertEqual(type(cm.author), unicode)
529 self.assertEqual(type(cm.author), unicode)
513
530
514 def test_repo_files_content_is_unicode(self):
531 def test_repo_files_content_is_unicode(self):
515 test_changeset = self.repo.get_changeset(100)
532 test_changeset = self.repo.get_changeset(100)
516 for node in test_changeset.get_node('/'):
533 for node in test_changeset.get_node('/'):
517 if node.is_file():
534 if node.is_file():
518 self.assertEqual(type(node.content), unicode)
535 self.assertEqual(type(node.content), unicode)
519
536
520 def test_wrong_path(self):
537 def test_wrong_path(self):
521 # There is 'setup.py' in the root dir but not there:
538 # There is 'setup.py' in the root dir but not there:
522 path = 'foo/bar/setup.py'
539 path = 'foo/bar/setup.py'
523 self.assertRaises(VCSError, self.repo.get_changeset().get_node, path)
540 self.assertRaises(VCSError, self.repo.get_changeset().get_node, path)
524
541
525
542
526 def test_archival_file(self):
543 def test_archival_file(self):
527 #TODO:
544 #TODO:
528 pass
545 pass
529
546
530 def test_archival_as_generator(self):
547 def test_archival_as_generator(self):
531 #TODO:
548 #TODO:
532 pass
549 pass
533
550
534 def test_archival_wrong_kind(self):
551 def test_archival_wrong_kind(self):
535 tip = self.repo.get_changeset()
552 tip = self.repo.get_changeset()
536 self.assertRaises(VCSError, tip.fill_archive, kind='error')
553 self.assertRaises(VCSError, tip.fill_archive, kind='error')
537
554
538 def test_archival_empty_prefix(self):
555 def test_archival_empty_prefix(self):
539 #TODO:
556 #TODO:
540 pass
557 pass
541
558
542
559
543 def test_author_email(self):
560 def test_author_email(self):
544 self.assertEqual('marcin@python-blog.com',
561 self.assertEqual('marcin@python-blog.com',
545 self.repo.get_changeset('b986218ba1c9').author_email)
562 self.repo.get_changeset('b986218ba1c9').author_email)
546 self.assertEqual('lukasz.balcerzak@python-center.pl',
563 self.assertEqual('lukasz.balcerzak@python-center.pl',
547 self.repo.get_changeset('3803844fdbd3').author_email)
564 self.repo.get_changeset('3803844fdbd3').author_email)
548 self.assertEqual('',
565 self.assertEqual('',
549 self.repo.get_changeset('84478366594b').author_email)
566 self.repo.get_changeset('84478366594b').author_email)
550
567
551 def test_author_username(self):
568 def test_author_username(self):
552 self.assertEqual('Marcin Kuzminski',
569 self.assertEqual('Marcin Kuzminski',
553 self.repo.get_changeset('b986218ba1c9').author_name)
570 self.repo.get_changeset('b986218ba1c9').author_name)
554 self.assertEqual('Lukasz Balcerzak',
571 self.assertEqual('Lukasz Balcerzak',
555 self.repo.get_changeset('3803844fdbd3').author_name)
572 self.repo.get_changeset('3803844fdbd3').author_name)
556 self.assertEqual('marcink',
573 self.assertEqual('marcink',
557 self.repo.get_changeset('84478366594b').author_name)
574 self.repo.get_changeset('84478366594b').author_name)
General Comments 0
You need to be logged in to leave comments. Login now