Mercurial > kallithea
comparison rhodecode/tests/vcs/test_git.py @ 2451:402a96fcfa22 beta
Added vcs testsuite for better integration tests + added fetching
of two new repos into test env for rhodecode
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Wed, 13 Jun 2012 23:27:33 +0200 |
parents | |
children | 32471bd1f4ee |
comparison
equal
deleted
inserted
replaced
2450:26193dba1f0e | 2451:402a96fcfa22 |
---|---|
1 from __future__ import with_statement | |
2 | |
3 import os | |
4 import mock | |
5 import datetime | |
6 from rhodecode.lib.vcs.backends.git import GitRepository, GitChangeset | |
7 from rhodecode.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError | |
8 from rhodecode.lib.vcs.nodes import NodeKind, FileNode, DirNode, NodeState | |
9 from rhodecode.lib.vcs.utils.compat import unittest | |
10 from rhodecode.tests.vcs.base import BackendTestMixin | |
11 from conf import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, get_new_dir | |
12 | |
13 | |
14 class GitRepositoryTest(unittest.TestCase): | |
15 | |
16 def __check_for_existing_repo(self): | |
17 if os.path.exists(TEST_GIT_REPO_CLONE): | |
18 self.fail('Cannot test git clone repo as location %s already ' | |
19 'exists. You should manually remove it first.' | |
20 % TEST_GIT_REPO_CLONE) | |
21 | |
22 def setUp(self): | |
23 self.repo = GitRepository(TEST_GIT_REPO) | |
24 | |
25 def test_wrong_repo_path(self): | |
26 wrong_repo_path = '/tmp/errorrepo' | |
27 self.assertRaises(RepositoryError, GitRepository, wrong_repo_path) | |
28 | |
29 def test_repo_clone(self): | |
30 self.__check_for_existing_repo() | |
31 repo = GitRepository(TEST_GIT_REPO) | |
32 repo_clone = GitRepository(TEST_GIT_REPO_CLONE, | |
33 src_url=TEST_GIT_REPO, create=True, update_after_clone=True) | |
34 self.assertEqual(len(repo.revisions), len(repo_clone.revisions)) | |
35 # Checking hashes of changesets should be enough | |
36 for changeset in repo.get_changesets(): | |
37 raw_id = changeset.raw_id | |
38 self.assertEqual(raw_id, repo_clone.get_changeset(raw_id).raw_id) | |
39 | |
40 def test_repo_clone_without_create(self): | |
41 self.assertRaises(RepositoryError, GitRepository, | |
42 TEST_GIT_REPO_CLONE + '_wo_create', src_url=TEST_GIT_REPO) | |
43 | |
44 def test_repo_clone_with_update(self): | |
45 repo = GitRepository(TEST_GIT_REPO) | |
46 clone_path = TEST_GIT_REPO_CLONE + '_with_update' | |
47 repo_clone = GitRepository(clone_path, | |
48 create=True, src_url=TEST_GIT_REPO, update_after_clone=True) | |
49 self.assertEqual(len(repo.revisions), len(repo_clone.revisions)) | |
50 | |
51 #check if current workdir was updated | |
52 fpath = os.path.join(clone_path, 'MANIFEST.in') | |
53 self.assertEqual(True, os.path.isfile(fpath), | |
54 'Repo was cloned and updated but file %s could not be found' | |
55 % fpath) | |
56 | |
57 def test_repo_clone_without_update(self): | |
58 repo = GitRepository(TEST_GIT_REPO) | |
59 clone_path = TEST_GIT_REPO_CLONE + '_without_update' | |
60 repo_clone = GitRepository(clone_path, | |
61 create=True, src_url=TEST_GIT_REPO, update_after_clone=False) | |
62 self.assertEqual(len(repo.revisions), len(repo_clone.revisions)) | |
63 #check if current workdir was *NOT* updated | |
64 fpath = os.path.join(clone_path, 'MANIFEST.in') | |
65 # Make sure it's not bare repo | |
66 self.assertFalse(repo_clone._repo.bare) | |
67 self.assertEqual(False, os.path.isfile(fpath), | |
68 'Repo was cloned and updated but file %s was found' | |
69 % fpath) | |
70 | |
71 def test_repo_clone_into_bare_repo(self): | |
72 repo = GitRepository(TEST_GIT_REPO) | |
73 clone_path = TEST_GIT_REPO_CLONE + '_bare.git' | |
74 repo_clone = GitRepository(clone_path, create=True, | |
75 src_url=repo.path, bare=True) | |
76 self.assertTrue(repo_clone._repo.bare) | |
77 | |
78 def test_create_repo_is_not_bare_by_default(self): | |
79 repo = GitRepository(get_new_dir('not-bare-by-default'), create=True) | |
80 self.assertFalse(repo._repo.bare) | |
81 | |
82 def test_create_bare_repo(self): | |
83 repo = GitRepository(get_new_dir('bare-repo'), create=True, bare=True) | |
84 self.assertTrue(repo._repo.bare) | |
85 | |
86 def test_revisions(self): | |
87 # there are 112 revisions (by now) | |
88 # so we can assume they would be available from now on | |
89 subset = set([ | |
90 'c1214f7e79e02fc37156ff215cd71275450cffc3', | |
91 '38b5fe81f109cb111f549bfe9bb6b267e10bc557', | |
92 'fa6600f6848800641328adbf7811fd2372c02ab2', | |
93 '102607b09cdd60e2793929c4f90478be29f85a17', | |
94 '49d3fd156b6f7db46313fac355dca1a0b94a0017', | |
95 '2d1028c054665b962fa3d307adfc923ddd528038', | |
96 'd7e0d30fbcae12c90680eb095a4f5f02505ce501', | |
97 'ff7ca51e58c505fec0dd2491de52c622bb7a806b', | |
98 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f', | |
99 '8430a588b43b5d6da365400117c89400326e7992', | |
100 'd955cd312c17b02143c04fa1099a352b04368118', | |
101 'f67b87e5c629c2ee0ba58f85197e423ff28d735b', | |
102 'add63e382e4aabc9e1afdc4bdc24506c269b7618', | |
103 'f298fe1189f1b69779a4423f40b48edf92a703fc', | |
104 'bd9b619eb41994cac43d67cf4ccc8399c1125808', | |
105 '6e125e7c890379446e98980d8ed60fba87d0f6d1', | |
106 'd4a54db9f745dfeba6933bf5b1e79e15d0af20bd', | |
107 '0b05e4ed56c802098dfc813cbe779b2f49e92500', | |
108 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e', | |
109 '45223f8f114c64bf4d6f853e3c35a369a6305520', | |
110 'ca1eb7957a54bce53b12d1a51b13452f95bc7c7e', | |
111 'f5ea29fc42ef67a2a5a7aecff10e1566699acd68', | |
112 '27d48942240f5b91dfda77accd2caac94708cc7d', | |
113 '622f0eb0bafd619d2560c26f80f09e3b0b0d78af', | |
114 'e686b958768ee96af8029fe19c6050b1a8dd3b2b']) | |
115 self.assertTrue(subset.issubset(set(self.repo.revisions))) | |
116 | |
117 | |
118 | |
119 def test_slicing(self): | |
120 #4 1 5 10 95 | |
121 for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5), | |
122 (10, 20, 10), (5, 100, 95)]: | |
123 revs = list(self.repo[sfrom:sto]) | |
124 self.assertEqual(len(revs), size) | |
125 self.assertEqual(revs[0], self.repo.get_changeset(sfrom)) | |
126 self.assertEqual(revs[-1], self.repo.get_changeset(sto - 1)) | |
127 | |
128 | |
129 def test_branches(self): | |
130 # TODO: Need more tests here | |
131 # Removed (those are 'remotes' branches for cloned repo) | |
132 #self.assertTrue('master' in self.repo.branches) | |
133 #self.assertTrue('gittree' in self.repo.branches) | |
134 #self.assertTrue('web-branch' in self.repo.branches) | |
135 for name, id in self.repo.branches.items(): | |
136 self.assertTrue(isinstance( | |
137 self.repo.get_changeset(id), GitChangeset)) | |
138 | |
139 def test_tags(self): | |
140 # TODO: Need more tests here | |
141 self.assertTrue('v0.1.1' in self.repo.tags) | |
142 self.assertTrue('v0.1.2' in self.repo.tags) | |
143 for name, id in self.repo.tags.items(): | |
144 self.assertTrue(isinstance( | |
145 self.repo.get_changeset(id), GitChangeset)) | |
146 | |
147 def _test_single_changeset_cache(self, revision): | |
148 chset = self.repo.get_changeset(revision) | |
149 self.assertTrue(revision in self.repo.changesets) | |
150 self.assertTrue(chset is self.repo.changesets[revision]) | |
151 | |
152 def test_initial_changeset(self): | |
153 id = self.repo.revisions[0] | |
154 init_chset = self.repo.get_changeset(id) | |
155 self.assertEqual(init_chset.message, 'initial import\n') | |
156 self.assertEqual(init_chset.author, | |
157 'Marcin Kuzminski <marcin@python-blog.com>') | |
158 for path in ('vcs/__init__.py', | |
159 'vcs/backends/BaseRepository.py', | |
160 'vcs/backends/__init__.py'): | |
161 self.assertTrue(isinstance(init_chset.get_node(path), FileNode)) | |
162 for path in ('', 'vcs', 'vcs/backends'): | |
163 self.assertTrue(isinstance(init_chset.get_node(path), DirNode)) | |
164 | |
165 self.assertRaises(NodeDoesNotExistError, init_chset.get_node, path='foobar') | |
166 | |
167 node = init_chset.get_node('vcs/') | |
168 self.assertTrue(hasattr(node, 'kind')) | |
169 self.assertEqual(node.kind, NodeKind.DIR) | |
170 | |
171 node = init_chset.get_node('vcs') | |
172 self.assertTrue(hasattr(node, 'kind')) | |
173 self.assertEqual(node.kind, NodeKind.DIR) | |
174 | |
175 node = init_chset.get_node('vcs/__init__.py') | |
176 self.assertTrue(hasattr(node, 'kind')) | |
177 self.assertEqual(node.kind, NodeKind.FILE) | |
178 | |
179 def test_not_existing_changeset(self): | |
180 self.assertRaises(RepositoryError, self.repo.get_changeset, | |
181 'f' * 40) | |
182 | |
183 def test_changeset10(self): | |
184 | |
185 chset10 = self.repo.get_changeset(self.repo.revisions[9]) | |
186 README = """=== | |
187 VCS | |
188 === | |
189 | |
190 Various Version Control System management abstraction layer for Python. | |
191 | |
192 Introduction | |
193 ------------ | |
194 | |
195 TODO: To be written... | |
196 | |
197 """ | |
198 node = chset10.get_node('README.rst') | |
199 self.assertEqual(node.kind, NodeKind.FILE) | |
200 self.assertEqual(node.content, README) | |
201 | |
202 | |
203 class GitChangesetTest(unittest.TestCase): | |
204 | |
205 def setUp(self): | |
206 self.repo = GitRepository(TEST_GIT_REPO) | |
207 | |
208 def test_default_changeset(self): | |
209 tip = self.repo.get_changeset() | |
210 self.assertEqual(tip, self.repo.get_changeset(None)) | |
211 self.assertEqual(tip, self.repo.get_changeset('tip')) | |
212 | |
213 def test_root_node(self): | |
214 tip = self.repo.get_changeset() | |
215 self.assertTrue(tip.root is tip.get_node('')) | |
216 | |
217 def test_lazy_fetch(self): | |
218 """ | |
219 Test if changeset's nodes expands and are cached as we walk through | |
220 the revision. This test is somewhat hard to write as order of tests | |
221 is a key here. Written by running command after command in a shell. | |
222 """ | |
223 hex = '2a13f185e4525f9d4b59882791a2d397b90d5ddc' | |
224 self.assertTrue(hex in self.repo.revisions) | |
225 chset = self.repo.get_changeset(hex) | |
226 self.assertTrue(len(chset.nodes) == 0) | |
227 root = chset.root | |
228 self.assertTrue(len(chset.nodes) == 1) | |
229 self.assertTrue(len(root.nodes) == 8) | |
230 # accessing root.nodes updates chset.nodes | |
231 self.assertTrue(len(chset.nodes) == 9) | |
232 | |
233 docs = root.get_node('docs') | |
234 # we haven't yet accessed anything new as docs dir was already cached | |
235 self.assertTrue(len(chset.nodes) == 9) | |
236 self.assertTrue(len(docs.nodes) == 8) | |
237 # accessing docs.nodes updates chset.nodes | |
238 self.assertTrue(len(chset.nodes) == 17) | |
239 | |
240 self.assertTrue(docs is chset.get_node('docs')) | |
241 self.assertTrue(docs is root.nodes[0]) | |
242 self.assertTrue(docs is root.dirs[0]) | |
243 self.assertTrue(docs is chset.get_node('docs')) | |
244 | |
245 def test_nodes_with_changeset(self): | |
246 hex = '2a13f185e4525f9d4b59882791a2d397b90d5ddc' | |
247 chset = self.repo.get_changeset(hex) | |
248 root = chset.root | |
249 docs = root.get_node('docs') | |
250 self.assertTrue(docs is chset.get_node('docs')) | |
251 api = docs.get_node('api') | |
252 self.assertTrue(api is chset.get_node('docs/api')) | |
253 index = api.get_node('index.rst') | |
254 self.assertTrue(index is chset.get_node('docs/api/index.rst')) | |
255 self.assertTrue(index is chset.get_node('docs')\ | |
256 .get_node('api')\ | |
257 .get_node('index.rst')) | |
258 | |
259 def test_branch_and_tags(self): | |
260 ''' | |
261 rev0 = self.repo.revisions[0] | |
262 chset0 = self.repo.get_changeset(rev0) | |
263 self.assertEqual(chset0.branch, 'master') | |
264 self.assertEqual(chset0.tags, []) | |
265 | |
266 rev10 = self.repo.revisions[10] | |
267 chset10 = self.repo.get_changeset(rev10) | |
268 self.assertEqual(chset10.branch, 'master') | |
269 self.assertEqual(chset10.tags, []) | |
270 | |
271 rev44 = self.repo.revisions[44] | |
272 chset44 = self.repo.get_changeset(rev44) | |
273 self.assertEqual(chset44.branch, 'web-branch') | |
274 | |
275 tip = self.repo.get_changeset('tip') | |
276 self.assertTrue('tip' in tip.tags) | |
277 ''' | |
278 # Those tests would fail - branches are now going | |
279 # to be changed at main API in order to support git backend | |
280 pass | |
281 | |
282 def _test_slices(self, limit, offset): | |
283 count = self.repo.count() | |
284 changesets = self.repo.get_changesets(limit=limit, offset=offset) | |
285 idx = 0 | |
286 for changeset in changesets: | |
287 rev = offset + idx | |
288 idx += 1 | |
289 rev_id = self.repo.revisions[rev] | |
290 if idx > limit: | |
291 self.fail("Exceeded limit already (getting revision %s, " | |
292 "there are %s total revisions, offset=%s, limit=%s)" | |
293 % (rev_id, count, offset, limit)) | |
294 self.assertEqual(changeset, self.repo.get_changeset(rev_id)) | |
295 result = list(self.repo.get_changesets(limit=limit, offset=offset)) | |
296 start = offset | |
297 end = limit and offset + limit or None | |
298 sliced = list(self.repo[start:end]) | |
299 self.failUnlessEqual(result, sliced, | |
300 msg="Comparison failed for limit=%s, offset=%s" | |
301 "(get_changeset returned: %s and sliced: %s" | |
302 % (limit, offset, result, sliced)) | |
303 | |
304 def _test_file_size(self, revision, path, size): | |
305 node = self.repo.get_changeset(revision).get_node(path) | |
306 self.assertTrue(node.is_file()) | |
307 self.assertEqual(node.size, size) | |
308 | |
309 def test_file_size(self): | |
310 to_check = ( | |
311 ('c1214f7e79e02fc37156ff215cd71275450cffc3', | |
312 'vcs/backends/BaseRepository.py', 502), | |
313 ('d7e0d30fbcae12c90680eb095a4f5f02505ce501', | |
314 'vcs/backends/hg.py', 854), | |
315 ('6e125e7c890379446e98980d8ed60fba87d0f6d1', | |
316 'setup.py', 1068), | |
317 | |
318 ('d955cd312c17b02143c04fa1099a352b04368118', | |
319 'vcs/backends/base.py', 2921), | |
320 ('ca1eb7957a54bce53b12d1a51b13452f95bc7c7e', | |
321 'vcs/backends/base.py', 3936), | |
322 ('f50f42baeed5af6518ef4b0cb2f1423f3851a941', | |
323 'vcs/backends/base.py', 6189), | |
324 ) | |
325 for revision, path, size in to_check: | |
326 self._test_file_size(revision, path, size) | |
327 | |
328 def test_file_history(self): | |
329 # we can only check if those revisions are present in the history | |
330 # as we cannot update this test every time file is changed | |
331 files = { | |
332 'setup.py': [ | |
333 '54386793436c938cff89326944d4c2702340037d', | |
334 '51d254f0ecf5df2ce50c0b115741f4cf13985dab', | |
335 '998ed409c795fec2012b1c0ca054d99888b22090', | |
336 '5e0eb4c47f56564395f76333f319d26c79e2fb09', | |
337 '0115510b70c7229dbc5dc49036b32e7d91d23acd', | |
338 '7cb3fd1b6d8c20ba89e2264f1c8baebc8a52d36e', | |
339 '2a13f185e4525f9d4b59882791a2d397b90d5ddc', | |
340 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e', | |
341 'ff7ca51e58c505fec0dd2491de52c622bb7a806b', | |
342 ], | |
343 'vcs/nodes.py': [ | |
344 '33fa3223355104431402a888fa77a4e9956feb3e', | |
345 'fa014c12c26d10ba682fadb78f2a11c24c8118e1', | |
346 'e686b958768ee96af8029fe19c6050b1a8dd3b2b', | |
347 'ab5721ca0a081f26bf43d9051e615af2cc99952f', | |
348 'c877b68d18e792a66b7f4c529ea02c8f80801542', | |
349 '4313566d2e417cb382948f8d9d7c765330356054', | |
350 '6c2303a793671e807d1cfc70134c9ca0767d98c2', | |
351 '54386793436c938cff89326944d4c2702340037d', | |
352 '54000345d2e78b03a99d561399e8e548de3f3203', | |
353 '1c6b3677b37ea064cb4b51714d8f7498f93f4b2b', | |
354 '2d03ca750a44440fb5ea8b751176d1f36f8e8f46', | |
355 '2a08b128c206db48c2f0b8f70df060e6db0ae4f8', | |
356 '30c26513ff1eb8e5ce0e1c6b477ee5dc50e2f34b', | |
357 'ac71e9503c2ca95542839af0ce7b64011b72ea7c', | |
358 '12669288fd13adba2a9b7dd5b870cc23ffab92d2', | |
359 '5a0c84f3e6fe3473e4c8427199d5a6fc71a9b382', | |
360 '12f2f5e2b38e6ff3fbdb5d722efed9aa72ecb0d5', | |
361 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378', | |
362 'f50f42baeed5af6518ef4b0cb2f1423f3851a941', | |
363 'd7e390a45f6aa96f04f5e7f583ad4f867431aa25', | |
364 'f15c21f97864b4f071cddfbf2750ec2e23859414', | |
365 'e906ef056cf539a4e4e5fc8003eaf7cf14dd8ade', | |
366 'ea2b108b48aa8f8c9c4a941f66c1a03315ca1c3b', | |
367 '84dec09632a4458f79f50ddbbd155506c460b4f9', | |
368 '0115510b70c7229dbc5dc49036b32e7d91d23acd', | |
369 '2a13f185e4525f9d4b59882791a2d397b90d5ddc', | |
370 '3bf1c5868e570e39569d094f922d33ced2fa3b2b', | |
371 'b8d04012574729d2c29886e53b1a43ef16dd00a1', | |
372 '6970b057cffe4aab0a792aa634c89f4bebf01441', | |
373 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f', | |
374 'ff7ca51e58c505fec0dd2491de52c622bb7a806b', | |
375 ], | |
376 'vcs/backends/git.py': [ | |
377 '4cf116ad5a457530381135e2f4c453e68a1b0105', | |
378 '9a751d84d8e9408e736329767387f41b36935153', | |
379 'cb681fb539c3faaedbcdf5ca71ca413425c18f01', | |
380 '428f81bb652bcba8d631bce926e8834ff49bdcc6', | |
381 '180ab15aebf26f98f714d8c68715e0f05fa6e1c7', | |
382 '2b8e07312a2e89e92b90426ab97f349f4bce2a3a', | |
383 '50e08c506174d8645a4bb517dd122ac946a0f3bf', | |
384 '54000345d2e78b03a99d561399e8e548de3f3203', | |
385 ], | |
386 } | |
387 for path, revs in files.items(): | |
388 node = self.repo.get_changeset(revs[0]).get_node(path) | |
389 node_revs = [chset.raw_id for chset in node.history] | |
390 self.assertTrue(set(revs).issubset(set(node_revs)), | |
391 "We assumed that %s is subset of revisions for which file %s " | |
392 "has been changed, and history of that node returned: %s" | |
393 % (revs, path, node_revs)) | |
394 | |
395 def test_file_annotate(self): | |
396 files = { | |
397 'vcs/backends/__init__.py': { | |
398 'c1214f7e79e02fc37156ff215cd71275450cffc3': { | |
399 'lines_no': 1, | |
400 'changesets': [ | |
401 'c1214f7e79e02fc37156ff215cd71275450cffc3', | |
402 ], | |
403 }, | |
404 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647': { | |
405 'lines_no': 21, | |
406 'changesets': [ | |
407 '49d3fd156b6f7db46313fac355dca1a0b94a0017', | |
408 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
409 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
410 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
411 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
412 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
413 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
414 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
415 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
416 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
417 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
418 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
419 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
420 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
421 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
422 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
423 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
424 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
425 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
426 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
427 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
428 ], | |
429 }, | |
430 'e29b67bd158580fc90fc5e9111240b90e6e86064': { | |
431 'lines_no': 32, | |
432 'changesets': [ | |
433 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
434 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
435 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378', | |
436 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
437 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
438 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
439 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
440 '54000345d2e78b03a99d561399e8e548de3f3203', | |
441 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
442 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
443 '78c3f0c23b7ee935ec276acb8b8212444c33c396', | |
444 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
445 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
446 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
447 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
448 '2a13f185e4525f9d4b59882791a2d397b90d5ddc', | |
449 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
450 '78c3f0c23b7ee935ec276acb8b8212444c33c396', | |
451 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
452 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
453 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
454 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
455 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
456 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
457 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
458 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
459 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
460 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
461 '992f38217b979d0b0987d0bae3cc26dac85d9b19', | |
462 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
463 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
464 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647', | |
465 ], | |
466 }, | |
467 }, | |
468 } | |
469 | |
470 for fname, revision_dict in files.items(): | |
471 for rev, data in revision_dict.items(): | |
472 cs = self.repo.get_changeset(rev) | |
473 ann = cs.get_file_annotate(fname) | |
474 | |
475 l1 = [x[1].raw_id for x in ann] | |
476 l2 = files[fname][rev]['changesets'] | |
477 self.assertTrue(l1 == l2 , "The lists of revision for %s@rev %s" | |
478 "from annotation list should match each other, " | |
479 "got \n%s \nvs \n%s " % (fname, rev, l1, l2)) | |
480 | |
481 def test_files_state(self): | |
482 """ | |
483 Tests state of FileNodes. | |
484 """ | |
485 node = self.repo\ | |
486 .get_changeset('e6ea6d16e2f26250124a1f4b4fe37a912f9d86a0')\ | |
487 .get_node('vcs/utils/diffs.py') | |
488 self.assertTrue(node.state, NodeState.ADDED) | |
489 self.assertTrue(node.added) | |
490 self.assertFalse(node.changed) | |
491 self.assertFalse(node.not_changed) | |
492 self.assertFalse(node.removed) | |
493 | |
494 node = self.repo\ | |
495 .get_changeset('33fa3223355104431402a888fa77a4e9956feb3e')\ | |
496 .get_node('.hgignore') | |
497 self.assertTrue(node.state, NodeState.CHANGED) | |
498 self.assertFalse(node.added) | |
499 self.assertTrue(node.changed) | |
500 self.assertFalse(node.not_changed) | |
501 self.assertFalse(node.removed) | |
502 | |
503 node = self.repo\ | |
504 .get_changeset('e29b67bd158580fc90fc5e9111240b90e6e86064')\ | |
505 .get_node('setup.py') | |
506 self.assertTrue(node.state, NodeState.NOT_CHANGED) | |
507 self.assertFalse(node.added) | |
508 self.assertFalse(node.changed) | |
509 self.assertTrue(node.not_changed) | |
510 self.assertFalse(node.removed) | |
511 | |
512 # If node has REMOVED state then trying to fetch it would raise | |
513 # ChangesetError exception | |
514 chset = self.repo.get_changeset( | |
515 'fa6600f6848800641328adbf7811fd2372c02ab2') | |
516 path = 'vcs/backends/BaseRepository.py' | |
517 self.assertRaises(NodeDoesNotExistError, chset.get_node, path) | |
518 # but it would be one of ``removed`` (changeset's attribute) | |
519 self.assertTrue(path in [rf.path for rf in chset.removed]) | |
520 | |
521 chset = self.repo.get_changeset( | |
522 '54386793436c938cff89326944d4c2702340037d') | |
523 changed = ['setup.py', 'tests/test_nodes.py', 'vcs/backends/hg.py', | |
524 'vcs/nodes.py'] | |
525 self.assertEqual(set(changed), set([f.path for f in chset.changed])) | |
526 | |
527 def test_commit_message_is_unicode(self): | |
528 for cs in self.repo: | |
529 self.assertEqual(type(cs.message), unicode) | |
530 | |
531 def test_changeset_author_is_unicode(self): | |
532 for cs in self.repo: | |
533 self.assertEqual(type(cs.author), unicode) | |
534 | |
535 def test_repo_files_content_is_unicode(self): | |
536 changeset = self.repo.get_changeset() | |
537 for node in changeset.get_node('/'): | |
538 if node.is_file(): | |
539 self.assertEqual(type(node.content), unicode) | |
540 | |
541 def test_wrong_path(self): | |
542 # There is 'setup.py' in the root dir but not there: | |
543 path = 'foo/bar/setup.py' | |
544 tip = self.repo.get_changeset() | |
545 self.assertRaises(VCSError, tip.get_node, path) | |
546 | |
547 def test_author_email(self): | |
548 self.assertEqual('marcin@python-blog.com', | |
549 self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3')\ | |
550 .author_email) | |
551 self.assertEqual('lukasz.balcerzak@python-center.pl', | |
552 self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b')\ | |
553 .author_email) | |
554 self.assertEqual('none@none', | |
555 self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992')\ | |
556 .author_email) | |
557 | |
558 def test_author_username(self): | |
559 self.assertEqual('Marcin Kuzminski', | |
560 self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3')\ | |
561 .author_name) | |
562 self.assertEqual('Lukasz Balcerzak', | |
563 self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b')\ | |
564 .author_name) | |
565 self.assertEqual('marcink', | |
566 self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992')\ | |
567 .author_name) | |
568 | |
569 | |
570 class GitSpecificTest(unittest.TestCase): | |
571 | |
572 def test_error_is_raised_for_added_if_diff_name_status_is_wrong(self): | |
573 repo = mock.MagicMock() | |
574 changeset = GitChangeset(repo, 'foobar') | |
575 changeset._diff_name_status = 'foobar' | |
576 with self.assertRaises(VCSError): | |
577 changeset.added | |
578 | |
579 def test_error_is_raised_for_changed_if_diff_name_status_is_wrong(self): | |
580 repo = mock.MagicMock() | |
581 changeset = GitChangeset(repo, 'foobar') | |
582 changeset._diff_name_status = 'foobar' | |
583 with self.assertRaises(VCSError): | |
584 changeset.added | |
585 | |
586 def test_error_is_raised_for_removed_if_diff_name_status_is_wrong(self): | |
587 repo = mock.MagicMock() | |
588 changeset = GitChangeset(repo, 'foobar') | |
589 changeset._diff_name_status = 'foobar' | |
590 with self.assertRaises(VCSError): | |
591 changeset.added | |
592 | |
593 | |
594 class GitSpecificWithRepoTest(BackendTestMixin, unittest.TestCase): | |
595 backend_alias = 'git' | |
596 | |
597 @classmethod | |
598 def _get_commits(cls): | |
599 return [ | |
600 { | |
601 'message': 'Initial', | |
602 'author': 'Joe Doe <joe.doe@example.com>', | |
603 'date': datetime.datetime(2010, 1, 1, 20), | |
604 'added': [ | |
605 FileNode('foobar/static/js/admin/base.js', content='base'), | |
606 FileNode('foobar/static/admin', content='admin', | |
607 mode=0120000), # this is a link | |
608 FileNode('foo', content='foo'), | |
609 ], | |
610 }, | |
611 { | |
612 'message': 'Second', | |
613 'author': 'Joe Doe <joe.doe@example.com>', | |
614 'date': datetime.datetime(2010, 1, 1, 22), | |
615 'added': [ | |
616 FileNode('foo2', content='foo2'), | |
617 ], | |
618 }, | |
619 ] | |
620 | |
621 def test_paths_slow_traversing(self): | |
622 cs = self.repo.get_changeset() | |
623 self.assertEqual(cs.get_node('foobar').get_node('static').get_node('js') | |
624 .get_node('admin').get_node('base.js').content, 'base') | |
625 | |
626 def test_paths_fast_traversing(self): | |
627 cs = self.repo.get_changeset() | |
628 self.assertEqual(cs.get_node('foobar/static/js/admin/base.js').content, | |
629 'base') | |
630 | |
631 def test_workdir_get_branch(self): | |
632 self.repo.run_git_command('checkout -b production') | |
633 # Regression test: one of following would fail if we don't check | |
634 # .git/HEAD file | |
635 self.repo.run_git_command('checkout production') | |
636 self.assertEqual(self.repo.workdir.get_branch(), 'production') | |
637 self.repo.run_git_command('checkout master') | |
638 self.assertEqual(self.repo.workdir.get_branch(), 'master') | |
639 | |
640 def test_get_diff_runs_git_command_with_hashes(self): | |
641 self.repo.run_git_command = mock.Mock(return_value=['', '']) | |
642 self.repo.get_diff(0, 1) | |
643 self.repo.run_git_command.assert_called_once_with('diff -U%s %s %s' % | |
644 (3, self.repo._get_revision(0), self.repo._get_revision(1))) | |
645 | |
646 def test_get_diff_runs_git_command_with_str_hashes(self): | |
647 self.repo.run_git_command = mock.Mock(return_value=['', '']) | |
648 self.repo.get_diff(self.repo.EMPTY_CHANGESET, 1) | |
649 self.repo.run_git_command.assert_called_once_with('show -U%s %s' % | |
650 (3, self.repo._get_revision(1))) | |
651 | |
652 def test_get_diff_runs_git_command_with_path_if_its_given(self): | |
653 self.repo.run_git_command = mock.Mock(return_value=['', '']) | |
654 self.repo.get_diff(0, 1, 'foo') | |
655 self.repo.run_git_command.assert_called_once_with('diff -U%s %s %s -- "foo"' | |
656 % (3, self.repo._get_revision(0), self.repo._get_revision(1))) | |
657 | |
658 | |
659 class GitRegressionTest(BackendTestMixin, unittest.TestCase): | |
660 backend_alias = 'git' | |
661 | |
662 @classmethod | |
663 def _get_commits(cls): | |
664 return [ | |
665 { | |
666 'message': 'Initial', | |
667 'author': 'Joe Doe <joe.doe@example.com>', | |
668 'date': datetime.datetime(2010, 1, 1, 20), | |
669 'added': [ | |
670 FileNode('bot/__init__.py', content='base'), | |
671 FileNode('bot/templates/404.html', content='base'), | |
672 FileNode('bot/templates/500.html', content='base'), | |
673 ], | |
674 }, | |
675 { | |
676 'message': 'Second', | |
677 'author': 'Joe Doe <joe.doe@example.com>', | |
678 'date': datetime.datetime(2010, 1, 1, 22), | |
679 'added': [ | |
680 FileNode('bot/build/migrations/1.py', content='foo2'), | |
681 FileNode('bot/build/migrations/2.py', content='foo2'), | |
682 FileNode('bot/build/static/templates/f.html', content='foo2'), | |
683 FileNode('bot/build/static/templates/f1.html', content='foo2'), | |
684 FileNode('bot/build/templates/err.html', content='foo2'), | |
685 FileNode('bot/build/templates/err2.html', content='foo2'), | |
686 ], | |
687 }, | |
688 ] | |
689 | |
690 def test_similar_paths(self): | |
691 cs = self.repo.get_changeset() | |
692 paths = lambda *n:[x.path for x in n] | |
693 self.assertEqual(paths(*cs.get_nodes('bot')), ['bot/build', 'bot/templates', 'bot/__init__.py']) | |
694 self.assertEqual(paths(*cs.get_nodes('bot/build')), ['bot/build/migrations', 'bot/build/static', 'bot/build/templates']) | |
695 self.assertEqual(paths(*cs.get_nodes('bot/build/static')), ['bot/build/static/templates']) | |
696 # this get_nodes below causes troubles ! | |
697 self.assertEqual(paths(*cs.get_nodes('bot/build/static/templates')), ['bot/build/static/templates/f.html', 'bot/build/static/templates/f1.html']) | |
698 self.assertEqual(paths(*cs.get_nodes('bot/build/templates')), ['bot/build/templates/err.html', 'bot/build/templates/err2.html']) | |
699 self.assertEqual(paths(*cs.get_nodes('bot/templates/')), ['bot/templates/404.html', 'bot/templates/500.html']) | |
700 | |
701 if __name__ == '__main__': | |
702 unittest.main() |