##// END OF EJS Templates
tests: update _BackendTestMixin to py.test and convert tests using it from self.assert to plain py.test style asserts
Branko Majic -
r7046:4c46ebbc default
parent child Browse files
Show More
@@ -1,108 +1,106 b''
1 """
1 """
2 Module providing backend independent mixin class. It requires that
2 Module providing backend independent mixin class. It requires that
3 InMemoryChangeset class is working properly at backend class.
3 InMemoryChangeset class is working properly at backend class.
4 """
4 """
5 import os
5 import os
6 import time
6 import time
7 import shutil
7 import shutil
8 import datetime
8 import datetime
9
9
10 from kallithea.lib import vcs
10 from kallithea.lib import vcs
11 from kallithea.lib.vcs.utils.compat import unittest
12 from kallithea.lib.vcs.nodes import FileNode
11 from kallithea.lib.vcs.nodes import FileNode
13
12
14 from kallithea.tests.vcs.conf import SCM_TESTS, get_new_dir
13 from kallithea.tests.vcs.conf import SCM_TESTS, get_new_dir
15
14
16
15
17 class _BackendTestMixin(object):
16 class _BackendTestMixin(object):
18 """
17 """
19 This is a backend independent test case class which should be created
18 This is a backend independent test case class which should be created
20 with ``type`` method.
19 with ``type`` method.
21
20
22 It is required to set following attributes at subclass:
21 It is required to set following attributes at subclass:
23
22
24 - ``backend_alias``: alias of used backend (see ``vcs.BACKENDS``)
23 - ``backend_alias``: alias of used backend (see ``vcs.BACKENDS``)
25 - ``repo_path``: path to the repository which would be created for set of
24 - ``repo_path``: path to the repository which would be created for set of
26 tests
25 tests
27 - ``recreate_repo_per_test``: If set to ``False``, repo would NOT be created
26 - ``recreate_repo_per_test``: If set to ``False``, repo would NOT be created
28 before every single test. Defaults to ``True``.
27 before every single test. Defaults to ``True``.
29 """
28 """
30 recreate_repo_per_test = True
29 recreate_repo_per_test = True
31
30
32 @classmethod
31 @classmethod
33 def get_backend(cls):
32 def get_backend(cls):
34 return vcs.get_backend(cls.backend_alias)
33 return vcs.get_backend(cls.backend_alias)
35
34
36 @classmethod
35 @classmethod
37 def _get_commits(cls):
36 def _get_commits(cls):
38 commits = [
37 commits = [
39 {
38 {
40 'message': u'Initial commit',
39 'message': u'Initial commit',
41 'author': u'Joe Doe <joe.doe@example.com>',
40 'author': u'Joe Doe <joe.doe@example.com>',
42 'date': datetime.datetime(2010, 1, 1, 20),
41 'date': datetime.datetime(2010, 1, 1, 20),
43 'added': [
42 'added': [
44 FileNode('foobar', content='Foobar'),
43 FileNode('foobar', content='Foobar'),
45 FileNode('foobar2', content='Foobar II'),
44 FileNode('foobar2', content='Foobar II'),
46 FileNode('foo/bar/baz', content='baz here!'),
45 FileNode('foo/bar/baz', content='baz here!'),
47 ],
46 ],
48 },
47 },
49 {
48 {
50 'message': u'Changes...',
49 'message': u'Changes...',
51 'author': u'Jane Doe <jane.doe@example.com>',
50 'author': u'Jane Doe <jane.doe@example.com>',
52 'date': datetime.datetime(2010, 1, 1, 21),
51 'date': datetime.datetime(2010, 1, 1, 21),
53 'added': [
52 'added': [
54 FileNode('some/new.txt', content='news...'),
53 FileNode('some/new.txt', content='news...'),
55 ],
54 ],
56 'changed': [
55 'changed': [
57 FileNode('foobar', 'Foobar I'),
56 FileNode('foobar', 'Foobar I'),
58 ],
57 ],
59 'removed': [],
58 'removed': [],
60 },
59 },
61 ]
60 ]
62 return commits
61 return commits
63
62
64 @classmethod
63 @classmethod
65 def setUpClass(cls):
64 def setup_class(cls):
66 Backend = cls.get_backend()
65 Backend = cls.get_backend()
67 cls.backend_class = Backend
66 cls.backend_class = Backend
68 cls.repo_path = get_new_dir(str(time.time()))
67 cls.repo_path = get_new_dir(str(time.time()))
69 cls.repo = Backend(cls.repo_path, create=True)
68 cls.repo = Backend(cls.repo_path, create=True)
70 cls.imc = cls.repo.in_memory_changeset
69 cls.imc = cls.repo.in_memory_changeset
71 cls.default_branch = cls.repo.DEFAULT_BRANCH_NAME
70 cls.default_branch = cls.repo.DEFAULT_BRANCH_NAME
72
71
73 for commit in cls._get_commits():
72 for commit in cls._get_commits():
74 for node in commit.get('added', []):
73 for node in commit.get('added', []):
75 cls.imc.add(FileNode(node.path, content=node.content))
74 cls.imc.add(FileNode(node.path, content=node.content))
76 for node in commit.get('changed', []):
75 for node in commit.get('changed', []):
77 cls.imc.change(FileNode(node.path, content=node.content))
76 cls.imc.change(FileNode(node.path, content=node.content))
78 for node in commit.get('removed', []):
77 for node in commit.get('removed', []):
79 cls.imc.remove(FileNode(node.path))
78 cls.imc.remove(FileNode(node.path))
80
79
81 cls.tip = cls.imc.commit(message=unicode(commit['message']),
80 cls.tip = cls.imc.commit(message=unicode(commit['message']),
82 author=unicode(commit['author']),
81 author=unicode(commit['author']),
83 date=commit['date'])
82 date=commit['date'])
84
83
85 @classmethod
84 @classmethod
86 def tearDownClass(cls):
85 def teardown_class(cls):
87 if not getattr(cls, 'recreate_repo_per_test', False) and \
86 if not getattr(cls, 'recreate_repo_per_test', False) and \
88 'VCS_REMOVE_TEST_DIRS' in os.environ:
87 'VCS_REMOVE_TEST_DIRS' in os.environ:
89 shutil.rmtree(cls.repo_path)
88 shutil.rmtree(cls.repo_path)
90
89
91 def setUp(self):
90 def setup_method(self, method):
92 if getattr(self, 'recreate_repo_per_test', False):
91 if getattr(self, 'recreate_repo_per_test', False):
93 self.__class__.setUpClass()
92 self.__class__.setup_class()
94
93
95 def tearDown(self):
94 def teardown_method(self, method):
96 if getattr(self, 'recreate_repo_per_test', False) and \
95 if getattr(self, 'recreate_repo_per_test', False) and \
97 'VCS_REMOVE_TEST_DIRS' in os.environ:
96 'VCS_REMOVE_TEST_DIRS' in os.environ:
98 shutil.rmtree(self.repo_path)
97 shutil.rmtree(self.repo_path)
99
98
100
99
101 # For each backend create test case class
100 # For each backend create test case class
102 for alias in SCM_TESTS:
101 for alias in SCM_TESTS:
103 attrs = {
102 attrs = {
104 'backend_alias': alias,
103 'backend_alias': alias,
105 }
104 }
106 cls_name = ''.join(('%s base backend test' % alias).title().split())
105 cls_name = ''.join(('%s base backend test' % alias).title().split())
107 bases = (_BackendTestMixin, unittest.TestCase)
106 globals()[cls_name] = type(cls_name, (_BackendTestMixin,), attrs)
108 globals()[cls_name] = type(cls_name, bases, attrs)
@@ -1,113 +1,106 b''
1 import os
1 import os
2 import tarfile
2 import tarfile
3 import zipfile
3 import zipfile
4 import datetime
4 import datetime
5 import tempfile
5 import tempfile
6 import StringIO
6 import StringIO
7
7
8 from kallithea.lib.vcs.utils.compat import unittest
8 import pytest
9
9
10 from kallithea.lib.vcs.exceptions import VCSError
10 from kallithea.lib.vcs.exceptions import VCSError
11 from kallithea.lib.vcs.nodes import FileNode
11 from kallithea.lib.vcs.nodes import FileNode
12
12
13 from kallithea.tests.vcs.base import _BackendTestMixin
13 from kallithea.tests.vcs.base import _BackendTestMixin
14 from kallithea.tests.vcs.conf import SCM_TESTS, TESTS_TMP_PATH
14 from kallithea.tests.vcs.conf import SCM_TESTS, TESTS_TMP_PATH
15
15
16
16
17 class ArchivesTestCaseMixin(_BackendTestMixin):
17 class ArchivesTestCaseMixin(_BackendTestMixin):
18
18
19 @classmethod
19 @classmethod
20 def _get_commits(cls):
20 def _get_commits(cls):
21 start_date = datetime.datetime(2010, 1, 1, 20)
21 start_date = datetime.datetime(2010, 1, 1, 20)
22 for x in xrange(5):
22 for x in xrange(5):
23 yield {
23 yield {
24 'message': 'Commit %d' % x,
24 'message': 'Commit %d' % x,
25 'author': 'Joe Doe <joe.doe@example.com>',
25 'author': 'Joe Doe <joe.doe@example.com>',
26 'date': start_date + datetime.timedelta(hours=12 * x),
26 'date': start_date + datetime.timedelta(hours=12 * x),
27 'added': [
27 'added': [
28 FileNode('%d/file_%d.txt' % (x, x),
28 FileNode('%d/file_%d.txt' % (x, x),
29 content='Foobar %d' % x),
29 content='Foobar %d' % x),
30 ],
30 ],
31 }
31 }
32
32
33 def test_archive_zip(self):
33 def test_archive_zip(self):
34 path = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_zip-')[1]
34 path = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_zip-')[1]
35 with open(path, 'wb') as f:
35 with open(path, 'wb') as f:
36 self.tip.fill_archive(stream=f, kind='zip', prefix='repo')
36 self.tip.fill_archive(stream=f, kind='zip', prefix='repo')
37 out = zipfile.ZipFile(path)
37 out = zipfile.ZipFile(path)
38
38
39 for x in xrange(5):
39 for x in xrange(5):
40 node_path = '%d/file_%d.txt' % (x, x)
40 node_path = '%d/file_%d.txt' % (x, x)
41 decompressed = StringIO.StringIO()
41 decompressed = StringIO.StringIO()
42 decompressed.write(out.read('repo/' + node_path))
42 decompressed.write(out.read('repo/' + node_path))
43 self.assertEqual(
43 assert decompressed.getvalue() == self.tip.get_node(node_path).content
44 decompressed.getvalue(),
45 self.tip.get_node(node_path).content)
46
44
47 def test_archive_tgz(self):
45 def test_archive_tgz(self):
48 path = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_tgz-')[1]
46 path = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_tgz-')[1]
49 with open(path, 'wb') as f:
47 with open(path, 'wb') as f:
50 self.tip.fill_archive(stream=f, kind='tgz', prefix='repo')
48 self.tip.fill_archive(stream=f, kind='tgz', prefix='repo')
51 outdir = tempfile.mkdtemp(dir=TESTS_TMP_PATH, prefix='test_archive_tgz-', suffix='-outdir')
49 outdir = tempfile.mkdtemp(dir=TESTS_TMP_PATH, prefix='test_archive_tgz-', suffix='-outdir')
52
50
53 outfile = tarfile.open(path, 'r|gz')
51 outfile = tarfile.open(path, 'r|gz')
54 outfile.extractall(outdir)
52 outfile.extractall(outdir)
55
53
56 for x in xrange(5):
54 for x in xrange(5):
57 node_path = '%d/file_%d.txt' % (x, x)
55 node_path = '%d/file_%d.txt' % (x, x)
58 self.assertEqual(
56 assert open(os.path.join(outdir, 'repo/' + node_path)).read() == self.tip.get_node(node_path).content
59 open(os.path.join(outdir, 'repo/' + node_path)).read(),
60 self.tip.get_node(node_path).content)
61
57
62 def test_archive_tbz2(self):
58 def test_archive_tbz2(self):
63 path = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_tbz2-')[1]
59 path = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_tbz2-')[1]
64 with open(path, 'w+b') as f:
60 with open(path, 'w+b') as f:
65 self.tip.fill_archive(stream=f, kind='tbz2', prefix='repo')
61 self.tip.fill_archive(stream=f, kind='tbz2', prefix='repo')
66 outdir = tempfile.mkdtemp(dir=TESTS_TMP_PATH, prefix='test_archive_tbz2-', suffix='-outdir')
62 outdir = tempfile.mkdtemp(dir=TESTS_TMP_PATH, prefix='test_archive_tbz2-', suffix='-outdir')
67
63
68 outfile = tarfile.open(path, 'r|bz2')
64 outfile = tarfile.open(path, 'r|bz2')
69 outfile.extractall(outdir)
65 outfile.extractall(outdir)
70
66
71 for x in xrange(5):
67 for x in xrange(5):
72 node_path = '%d/file_%d.txt' % (x, x)
68 node_path = '%d/file_%d.txt' % (x, x)
73 self.assertEqual(
69 assert open(os.path.join(outdir, 'repo/' + node_path)).read() == self.tip.get_node(node_path).content
74 open(os.path.join(outdir, 'repo/' + node_path)).read(),
75 self.tip.get_node(node_path).content)
76
70
77 def test_archive_default_stream(self):
71 def test_archive_default_stream(self):
78 tmppath = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_default_stream-')[1]
72 tmppath = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_default_stream-')[1]
79 with open(tmppath, 'wb') as stream:
73 with open(tmppath, 'wb') as stream:
80 self.tip.fill_archive(stream=stream)
74 self.tip.fill_archive(stream=stream)
81 mystream = StringIO.StringIO()
75 mystream = StringIO.StringIO()
82 self.tip.fill_archive(stream=mystream)
76 self.tip.fill_archive(stream=mystream)
83 mystream.seek(0)
77 mystream.seek(0)
84 with open(tmppath, 'rb') as f:
78 with open(tmppath, 'rb') as f:
85 file_content = f.read()
79 file_content = f.read()
86 stringio_content = mystream.read()
80 stringio_content = mystream.read()
87 # the gzip header contains a MTIME header
81 # the gzip header contains a MTIME header
88 # because is takes a little bit of time from one fill_archive call to the next
82 # because is takes a little bit of time from one fill_archive call to the next
89 # this part may differ so don't include that part in the comparison
83 # this part may differ so don't include that part in the comparison
90 self.assertEqual(file_content[:4], stringio_content[:4])
84 assert file_content[:4] == stringio_content[:4]
91 self.assertEqual(file_content[8:], stringio_content[8:])
85 assert file_content[8:] == stringio_content[8:]
92
86
93 def test_archive_wrong_kind(self):
87 def test_archive_wrong_kind(self):
94 with self.assertRaises(VCSError):
88 with pytest.raises(VCSError):
95 self.tip.fill_archive(kind='wrong kind')
89 self.tip.fill_archive(kind='wrong kind')
96
90
97 def test_archive_empty_prefix(self):
91 def test_archive_empty_prefix(self):
98 with self.assertRaises(VCSError):
92 with pytest.raises(VCSError):
99 self.tip.fill_archive(prefix='')
93 self.tip.fill_archive(prefix='')
100
94
101 def test_archive_prefix_with_leading_slash(self):
95 def test_archive_prefix_with_leading_slash(self):
102 with self.assertRaises(VCSError):
96 with pytest.raises(VCSError):
103 self.tip.fill_archive(prefix='/any')
97 self.tip.fill_archive(prefix='/any')
104
98
105
99
106 # For each backend create test case class
100 # For each backend create test case class
107 for alias in SCM_TESTS:
101 for alias in SCM_TESTS:
108 attrs = {
102 attrs = {
109 'backend_alias': alias,
103 'backend_alias': alias,
110 }
104 }
111 cls_name = ''.join(('%s archive test' % alias).title().split())
105 cls_name = ''.join(('test %s archive' % alias).title().split())
112 bases = (ArchivesTestCaseMixin, unittest.TestCase)
106 globals()[cls_name] = type(cls_name, (ArchivesTestCaseMixin,), attrs)
113 globals()[cls_name] = type(cls_name, bases, attrs)
@@ -1,111 +1,108 b''
1 import datetime
1 import datetime
2 from kallithea.lib import vcs
2 from kallithea.lib import vcs
3 from kallithea.lib.vcs.utils.compat import unittest
4 from kallithea.lib.vcs.nodes import FileNode
3 from kallithea.lib.vcs.nodes import FileNode
5
4
6 from kallithea.tests.vcs.base import _BackendTestMixin
5 from kallithea.tests.vcs.base import _BackendTestMixin
7 from kallithea.tests.vcs.conf import SCM_TESTS
6 from kallithea.tests.vcs.conf import SCM_TESTS
8
7
9
8
10 class BranchesTestCaseMixin(_BackendTestMixin):
9 class BranchesTestCaseMixin(_BackendTestMixin):
11
10
12 @classmethod
11 @classmethod
13 def _get_commits(cls):
12 def _get_commits(cls):
14 commits = [
13 commits = [
15 {
14 {
16 'message': 'Initial commit',
15 'message': 'Initial commit',
17 'author': 'Joe Doe <joe.doe@example.com>',
16 'author': 'Joe Doe <joe.doe@example.com>',
18 'date': datetime.datetime(2010, 1, 1, 20),
17 'date': datetime.datetime(2010, 1, 1, 20),
19 'added': [
18 'added': [
20 FileNode('foobar', content='Foobar'),
19 FileNode('foobar', content='Foobar'),
21 FileNode('foobar2', content='Foobar II'),
20 FileNode('foobar2', content='Foobar II'),
22 FileNode('foo/bar/baz', content='baz here!'),
21 FileNode('foo/bar/baz', content='baz here!'),
23 ],
22 ],
24 },
23 },
25 {
24 {
26 'message': 'Changes...',
25 'message': 'Changes...',
27 'author': 'Jane Doe <jane.doe@example.com>',
26 'author': 'Jane Doe <jane.doe@example.com>',
28 'date': datetime.datetime(2010, 1, 1, 21),
27 'date': datetime.datetime(2010, 1, 1, 21),
29 'added': [
28 'added': [
30 FileNode('some/new.txt', content='news...'),
29 FileNode('some/new.txt', content='news...'),
31 ],
30 ],
32 'changed': [
31 'changed': [
33 FileNode('foobar', 'Foobar I'),
32 FileNode('foobar', 'Foobar I'),
34 ],
33 ],
35 'removed': [],
34 'removed': [],
36 },
35 },
37 ]
36 ]
38 return commits
37 return commits
39
38
40 def test_simple(self):
39 def test_simple(self):
41 tip = self.repo.get_changeset()
40 tip = self.repo.get_changeset()
42 self.assertEqual(tip.date, datetime.datetime(2010, 1, 1, 21))
41 assert tip.date == datetime.datetime(2010, 1, 1, 21)
43
42
44 def test_new_branch(self):
43 def test_new_branch(self):
45 # This check must not be removed to ensure the 'branches' LazyProperty
44 # This check must not be removed to ensure the 'branches' LazyProperty
46 # gets hit *before* the new 'foobar' branch got created:
45 # gets hit *before* the new 'foobar' branch got created:
47 self.assertFalse('foobar' in self.repo.branches)
46 assert 'foobar' not in self.repo.branches
48 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
47 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
49 content='Documentation\n'))
48 content='Documentation\n'))
50 foobar_tip = self.imc.commit(
49 foobar_tip = self.imc.commit(
51 message=u'New branch: foobar',
50 message=u'New branch: foobar',
52 author=u'joe',
51 author=u'joe',
53 branch='foobar',
52 branch='foobar',
54 )
53 )
55 self.assertTrue('foobar' in self.repo.branches)
54 assert 'foobar' in self.repo.branches
56 self.assertEqual(foobar_tip.branch, 'foobar')
55 assert foobar_tip.branch == 'foobar'
57
56
58 def test_new_head(self):
57 def test_new_head(self):
59 tip = self.repo.get_changeset()
58 tip = self.repo.get_changeset()
60 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
59 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
61 content='Documentation\n'))
60 content='Documentation\n'))
62 foobar_tip = self.imc.commit(
61 foobar_tip = self.imc.commit(
63 message=u'New branch: foobar',
62 message=u'New branch: foobar',
64 author=u'joe',
63 author=u'joe',
65 branch='foobar',
64 branch='foobar',
66 parents=[tip],
65 parents=[tip],
67 )
66 )
68 self.imc.change(vcs.nodes.FileNode('docs/index.txt',
67 self.imc.change(vcs.nodes.FileNode('docs/index.txt',
69 content='Documentation\nand more...\n'))
68 content='Documentation\nand more...\n'))
70 newtip = self.imc.commit(
69 newtip = self.imc.commit(
71 message=u'At default branch',
70 message=u'At default branch',
72 author=u'joe',
71 author=u'joe',
73 branch=foobar_tip.branch,
72 branch=foobar_tip.branch,
74 parents=[foobar_tip],
73 parents=[foobar_tip],
75 )
74 )
76
75
77 newest_tip = self.imc.commit(
76 newest_tip = self.imc.commit(
78 message=u'Merged with %s' % foobar_tip.raw_id,
77 message=u'Merged with %s' % foobar_tip.raw_id,
79 author=u'joe',
78 author=u'joe',
80 branch=self.backend_class.DEFAULT_BRANCH_NAME,
79 branch=self.backend_class.DEFAULT_BRANCH_NAME,
81 parents=[newtip, foobar_tip],
80 parents=[newtip, foobar_tip],
82 )
81 )
83
82
84 self.assertEqual(newest_tip.branch,
83 assert newest_tip.branch == self.backend_class.DEFAULT_BRANCH_NAME
85 self.backend_class.DEFAULT_BRANCH_NAME)
86
84
87 def test_branch_with_slash_in_name(self):
85 def test_branch_with_slash_in_name(self):
88 self.imc.add(vcs.nodes.FileNode('extrafile', content='Some data\n'))
86 self.imc.add(vcs.nodes.FileNode('extrafile', content='Some data\n'))
89 self.imc.commit(u'Branch with a slash!', author=u'joe',
87 self.imc.commit(u'Branch with a slash!', author=u'joe',
90 branch='issue/123')
88 branch='issue/123')
91 self.assertTrue('issue/123' in self.repo.branches)
89 assert 'issue/123' in self.repo.branches
92
90
93 def test_branch_with_slash_in_name_and_similar_without(self):
91 def test_branch_with_slash_in_name_and_similar_without(self):
94 self.imc.add(vcs.nodes.FileNode('extrafile', content='Some data\n'))
92 self.imc.add(vcs.nodes.FileNode('extrafile', content='Some data\n'))
95 self.imc.commit(u'Branch with a slash!', author=u'joe',
93 self.imc.commit(u'Branch with a slash!', author=u'joe',
96 branch='issue/123')
94 branch='issue/123')
97 self.imc.add(vcs.nodes.FileNode('extrafile II', content='Some data\n'))
95 self.imc.add(vcs.nodes.FileNode('extrafile II', content='Some data\n'))
98 self.imc.commit(u'Branch without a slash...', author=u'joe',
96 self.imc.commit(u'Branch without a slash...', author=u'joe',
99 branch='123')
97 branch='123')
100 self.assertIn('issue/123', self.repo.branches)
98 assert 'issue/123' in self.repo.branches
101 self.assertIn('123', self.repo.branches)
99 assert '123' in self.repo.branches
102
100
103
101
104 # For each backend create test case class
102 # For each backend create test case class
105 for alias in SCM_TESTS:
103 for alias in SCM_TESTS:
106 attrs = {
104 attrs = {
107 'backend_alias': alias,
105 'backend_alias': alias,
108 }
106 }
109 cls_name = ''.join(('%s branches test' % alias).title().split())
107 cls_name = ''.join(('test %s branches' % alias).title().split())
110 bases = (BranchesTestCaseMixin, unittest.TestCase)
108 globals()[cls_name] = type(cls_name, (BranchesTestCaseMixin,), attrs)
111 globals()[cls_name] = type(cls_name, bases, attrs)
@@ -1,392 +1,390 b''
1 # encoding: utf8
1 # encoding: utf8
2
2
3 import time
3 import time
4 import datetime
4 import datetime
5
5
6 from kallithea.lib.vcs.utils.compat import unittest
6 import pytest
7
7
8 from kallithea.lib import vcs
8 from kallithea.lib import vcs
9
9
10 from kallithea.lib.vcs.backends.base import BaseChangeset
10 from kallithea.lib.vcs.backends.base import BaseChangeset
11 from kallithea.lib.vcs.nodes import (
11 from kallithea.lib.vcs.nodes import (
12 FileNode, AddedFileNodesGenerator,
12 FileNode, AddedFileNodesGenerator,
13 ChangedFileNodesGenerator, RemovedFileNodesGenerator
13 ChangedFileNodesGenerator, RemovedFileNodesGenerator
14 )
14 )
15 from kallithea.lib.vcs.exceptions import (
15 from kallithea.lib.vcs.exceptions import (
16 BranchDoesNotExistError, ChangesetDoesNotExistError,
16 BranchDoesNotExistError, ChangesetDoesNotExistError,
17 RepositoryError, EmptyRepositoryError
17 RepositoryError, EmptyRepositoryError
18 )
18 )
19
19
20 from kallithea.tests.vcs.base import _BackendTestMixin
20 from kallithea.tests.vcs.base import _BackendTestMixin
21 from kallithea.tests.vcs.conf import SCM_TESTS, get_new_dir
21 from kallithea.tests.vcs.conf import SCM_TESTS, get_new_dir
22
22
23
23
24 class TestBaseChangeset(unittest.TestCase):
24 class TestBaseChangeset(object):
25
25
26 def test_as_dict(self):
26 def test_as_dict(self):
27 changeset = BaseChangeset()
27 changeset = BaseChangeset()
28 changeset.id = 'ID'
28 changeset.id = 'ID'
29 changeset.raw_id = 'RAW_ID'
29 changeset.raw_id = 'RAW_ID'
30 changeset.short_id = 'SHORT_ID'
30 changeset.short_id = 'SHORT_ID'
31 changeset.revision = 1009
31 changeset.revision = 1009
32 changeset.date = datetime.datetime(2011, 1, 30, 1, 45)
32 changeset.date = datetime.datetime(2011, 1, 30, 1, 45)
33 changeset.message = 'Message of a commit'
33 changeset.message = 'Message of a commit'
34 changeset.author = 'Joe Doe <joe.doe@example.com>'
34 changeset.author = 'Joe Doe <joe.doe@example.com>'
35 changeset.added = [FileNode('foo/bar/baz'), FileNode(u'foobar'), FileNode(u'blΓ₯bΓ¦rgrΓΈd')]
35 changeset.added = [FileNode('foo/bar/baz'), FileNode(u'foobar'), FileNode(u'blΓ₯bΓ¦rgrΓΈd')]
36 changeset.changed = []
36 changeset.changed = []
37 changeset.removed = []
37 changeset.removed = []
38 self.assertEqual(changeset.as_dict(), {
38 assert changeset.as_dict() == {
39 'id': 'ID',
39 'id': 'ID',
40 'raw_id': 'RAW_ID',
40 'raw_id': 'RAW_ID',
41 'short_id': 'SHORT_ID',
41 'short_id': 'SHORT_ID',
42 'revision': 1009,
42 'revision': 1009,
43 'date': datetime.datetime(2011, 1, 30, 1, 45),
43 'date': datetime.datetime(2011, 1, 30, 1, 45),
44 'message': 'Message of a commit',
44 'message': 'Message of a commit',
45 'author': {
45 'author': {
46 'name': 'Joe Doe',
46 'name': 'Joe Doe',
47 'email': 'joe.doe@example.com',
47 'email': 'joe.doe@example.com',
48 },
48 },
49 'added': ['foo/bar/baz', 'foobar', u'bl\xe5b\xe6rgr\xf8d'],
49 'added': ['foo/bar/baz', 'foobar', u'bl\xe5b\xe6rgr\xf8d'],
50 'changed': [],
50 'changed': [],
51 'removed': [],
51 'removed': [],
52 })
52 }
53
53
54
54
55 class _ChangesetsWithCommitsTestCaseixin(_BackendTestMixin):
55 class _ChangesetsWithCommitsTestCaseixin(_BackendTestMixin):
56 recreate_repo_per_test = True
56 recreate_repo_per_test = True
57
57
58 @classmethod
58 @classmethod
59 def _get_commits(cls):
59 def _get_commits(cls):
60 start_date = datetime.datetime(2010, 1, 1, 20)
60 start_date = datetime.datetime(2010, 1, 1, 20)
61 for x in xrange(5):
61 for x in xrange(5):
62 yield {
62 yield {
63 'message': 'Commit %d' % x,
63 'message': 'Commit %d' % x,
64 'author': 'Joe Doe <joe.doe@example.com>',
64 'author': 'Joe Doe <joe.doe@example.com>',
65 'date': start_date + datetime.timedelta(hours=12 * x),
65 'date': start_date + datetime.timedelta(hours=12 * x),
66 'added': [
66 'added': [
67 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
67 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
68 ],
68 ],
69 }
69 }
70
70
71 def test_new_branch(self):
71 def test_new_branch(self):
72 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
72 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
73 content='Documentation\n'))
73 content='Documentation\n'))
74 foobar_tip = self.imc.commit(
74 foobar_tip = self.imc.commit(
75 message=u'New branch: foobar',
75 message=u'New branch: foobar',
76 author=u'joe',
76 author=u'joe',
77 branch='foobar',
77 branch='foobar',
78 )
78 )
79 self.assertTrue('foobar' in self.repo.branches)
79 assert 'foobar' in self.repo.branches
80 self.assertEqual(foobar_tip.branch, 'foobar')
80 assert foobar_tip.branch == 'foobar'
81 # 'foobar' should be the only branch that contains the new commit
81 # 'foobar' should be the only branch that contains the new commit
82 self.assertNotEqual(*self.repo.branches.values())
82 branches = self.repo.branches.values()
83 assert branches[0] != branches[1]
83
84
84 def test_new_head_in_default_branch(self):
85 def test_new_head_in_default_branch(self):
85 tip = self.repo.get_changeset()
86 tip = self.repo.get_changeset()
86 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
87 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
87 content='Documentation\n'))
88 content='Documentation\n'))
88 foobar_tip = self.imc.commit(
89 foobar_tip = self.imc.commit(
89 message=u'New branch: foobar',
90 message=u'New branch: foobar',
90 author=u'joe',
91 author=u'joe',
91 branch='foobar',
92 branch='foobar',
92 parents=[tip],
93 parents=[tip],
93 )
94 )
94 self.imc.change(vcs.nodes.FileNode('docs/index.txt',
95 self.imc.change(vcs.nodes.FileNode('docs/index.txt',
95 content='Documentation\nand more...\n'))
96 content='Documentation\nand more...\n'))
96 newtip = self.imc.commit(
97 newtip = self.imc.commit(
97 message=u'At default branch',
98 message=u'At default branch',
98 author=u'joe',
99 author=u'joe',
99 branch=foobar_tip.branch,
100 branch=foobar_tip.branch,
100 parents=[foobar_tip],
101 parents=[foobar_tip],
101 )
102 )
102
103
103 newest_tip = self.imc.commit(
104 newest_tip = self.imc.commit(
104 message=u'Merged with %s' % foobar_tip.raw_id,
105 message=u'Merged with %s' % foobar_tip.raw_id,
105 author=u'joe',
106 author=u'joe',
106 branch=self.backend_class.DEFAULT_BRANCH_NAME,
107 branch=self.backend_class.DEFAULT_BRANCH_NAME,
107 parents=[newtip, foobar_tip],
108 parents=[newtip, foobar_tip],
108 )
109 )
109
110
110 self.assertEqual(newest_tip.branch,
111 assert newest_tip.branch == self.backend_class.DEFAULT_BRANCH_NAME
111 self.backend_class.DEFAULT_BRANCH_NAME)
112
112
113 def test_get_changesets_respects_branch_name(self):
113 def test_get_changesets_respects_branch_name(self):
114 tip = self.repo.get_changeset()
114 tip = self.repo.get_changeset()
115 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
115 self.imc.add(vcs.nodes.FileNode('docs/index.txt',
116 content='Documentation\n'))
116 content='Documentation\n'))
117 doc_changeset = self.imc.commit(
117 doc_changeset = self.imc.commit(
118 message=u'New branch: docs',
118 message=u'New branch: docs',
119 author=u'joe',
119 author=u'joe',
120 branch='docs',
120 branch='docs',
121 )
121 )
122 self.imc.add(vcs.nodes.FileNode('newfile', content=''))
122 self.imc.add(vcs.nodes.FileNode('newfile', content=''))
123 self.imc.commit(
123 self.imc.commit(
124 message=u'Back in default branch',
124 message=u'Back in default branch',
125 author=u'joe',
125 author=u'joe',
126 parents=[tip],
126 parents=[tip],
127 )
127 )
128 default_branch_changesets = self.repo.get_changesets(
128 default_branch_changesets = self.repo.get_changesets(
129 branch_name=self.repo.DEFAULT_BRANCH_NAME)
129 branch_name=self.repo.DEFAULT_BRANCH_NAME)
130 self.assertNotIn(doc_changeset, default_branch_changesets)
130 assert doc_changeset not in default_branch_changesets
131
131
132 def test_get_changeset_by_branch(self):
132 def test_get_changeset_by_branch(self):
133 for branch, sha in self.repo.branches.iteritems():
133 for branch, sha in self.repo.branches.iteritems():
134 self.assertEqual(sha, self.repo.get_changeset(branch).raw_id)
134 assert sha == self.repo.get_changeset(branch).raw_id
135
135
136 def test_get_changeset_by_tag(self):
136 def test_get_changeset_by_tag(self):
137 for tag, sha in self.repo.tags.iteritems():
137 for tag, sha in self.repo.tags.iteritems():
138 self.assertEqual(sha, self.repo.get_changeset(tag).raw_id)
138 assert sha == self.repo.get_changeset(tag).raw_id
139
139
140 def test_get_changeset_parents(self):
140 def test_get_changeset_parents(self):
141 for test_rev in [1, 2, 3]:
141 for test_rev in [1, 2, 3]:
142 sha = self.repo.get_changeset(test_rev-1)
142 sha = self.repo.get_changeset(test_rev-1)
143 self.assertEqual([sha], self.repo.get_changeset(test_rev).parents)
143 assert [sha] == self.repo.get_changeset(test_rev).parents
144
144
145 def test_get_changeset_children(self):
145 def test_get_changeset_children(self):
146 for test_rev in [1, 2, 3]:
146 for test_rev in [1, 2, 3]:
147 sha = self.repo.get_changeset(test_rev+1)
147 sha = self.repo.get_changeset(test_rev+1)
148 self.assertEqual([sha], self.repo.get_changeset(test_rev).children)
148 assert [sha] == self.repo.get_changeset(test_rev).children
149
149
150
150
151 class _ChangesetsTestCaseMixin(_BackendTestMixin):
151 class _ChangesetsTestCaseMixin(_BackendTestMixin):
152 recreate_repo_per_test = False
152 recreate_repo_per_test = False
153
153
154 @classmethod
154 @classmethod
155 def _get_commits(cls):
155 def _get_commits(cls):
156 start_date = datetime.datetime(2010, 1, 1, 20)
156 start_date = datetime.datetime(2010, 1, 1, 20)
157 for x in xrange(5):
157 for x in xrange(5):
158 yield {
158 yield {
159 'message': u'Commit %d' % x,
159 'message': u'Commit %d' % x,
160 'author': u'Joe Doe <joe.doe@example.com>',
160 'author': u'Joe Doe <joe.doe@example.com>',
161 'date': start_date + datetime.timedelta(hours=12 * x),
161 'date': start_date + datetime.timedelta(hours=12 * x),
162 'added': [
162 'added': [
163 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
163 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
164 ],
164 ],
165 }
165 }
166
166
167 def test_simple(self):
167 def test_simple(self):
168 tip = self.repo.get_changeset()
168 tip = self.repo.get_changeset()
169 self.assertEqual(tip.date, datetime.datetime(2010, 1, 3, 20))
169 assert tip.date == datetime.datetime(2010, 1, 3, 20)
170
170
171 def test_get_changesets_is_ordered_by_date(self):
171 def test_get_changesets_is_ordered_by_date(self):
172 changesets = list(self.repo.get_changesets())
172 changesets = list(self.repo.get_changesets())
173 ordered_by_date = sorted(changesets,
173 ordered_by_date = sorted(changesets,
174 key=lambda cs: cs.date)
174 key=lambda cs: cs.date)
175 self.assertItemsEqual(changesets, ordered_by_date)
175
176 assert changesets == ordered_by_date
176
177
177 def test_get_changesets_respects_start(self):
178 def test_get_changesets_respects_start(self):
178 second_id = self.repo.revisions[1]
179 second_id = self.repo.revisions[1]
179 changesets = list(self.repo.get_changesets(start=second_id))
180 changesets = list(self.repo.get_changesets(start=second_id))
180 self.assertEqual(len(changesets), 4)
181 assert len(changesets) == 4
181
182
182 def test_get_changesets_numerical_id_respects_start(self):
183 def test_get_changesets_numerical_id_respects_start(self):
183 second_id = 1
184 second_id = 1
184 changesets = list(self.repo.get_changesets(start=second_id))
185 changesets = list(self.repo.get_changesets(start=second_id))
185 self.assertEqual(len(changesets), 4)
186 assert len(changesets) == 4
186
187
187 def test_get_changesets_includes_start_changeset(self):
188 def test_get_changesets_includes_start_changeset(self):
188 second_id = self.repo.revisions[1]
189 second_id = self.repo.revisions[1]
189 changesets = list(self.repo.get_changesets(start=second_id))
190 changesets = list(self.repo.get_changesets(start=second_id))
190 self.assertEqual(changesets[0].raw_id, second_id)
191 assert changesets[0].raw_id == second_id
191
192
192 def test_get_changesets_respects_end(self):
193 def test_get_changesets_respects_end(self):
193 second_id = self.repo.revisions[1]
194 second_id = self.repo.revisions[1]
194 changesets = list(self.repo.get_changesets(end=second_id))
195 changesets = list(self.repo.get_changesets(end=second_id))
195 self.assertEqual(changesets[-1].raw_id, second_id)
196 assert changesets[-1].raw_id == second_id
196 self.assertEqual(len(changesets), 2)
197 assert len(changesets) == 2
197
198
198 def test_get_changesets_numerical_id_respects_end(self):
199 def test_get_changesets_numerical_id_respects_end(self):
199 second_id = 1
200 second_id = 1
200 changesets = list(self.repo.get_changesets(end=second_id))
201 changesets = list(self.repo.get_changesets(end=second_id))
201 self.assertEqual(changesets.index(changesets[-1]), second_id)
202 assert changesets.index(changesets[-1]) == second_id
202 self.assertEqual(len(changesets), 2)
203 assert len(changesets) == 2
203
204
204 def test_get_changesets_respects_both_start_and_end(self):
205 def test_get_changesets_respects_both_start_and_end(self):
205 second_id = self.repo.revisions[1]
206 second_id = self.repo.revisions[1]
206 third_id = self.repo.revisions[2]
207 third_id = self.repo.revisions[2]
207 changesets = list(self.repo.get_changesets(start=second_id,
208 changesets = list(self.repo.get_changesets(start=second_id,
208 end=third_id))
209 end=third_id))
209 self.assertEqual(len(changesets), 2)
210 assert len(changesets) == 2
210
211
211 def test_get_changesets_numerical_id_respects_both_start_and_end(self):
212 def test_get_changesets_numerical_id_respects_both_start_and_end(self):
212 changesets = list(self.repo.get_changesets(start=2, end=3))
213 changesets = list(self.repo.get_changesets(start=2, end=3))
213 self.assertEqual(len(changesets), 2)
214 assert len(changesets) == 2
214
215
215 def test_get_changesets_on_empty_repo_raises_EmptyRepository_error(self):
216 def test_get_changesets_on_empty_repo_raises_EmptyRepository_error(self):
216 Backend = self.get_backend()
217 Backend = self.get_backend()
217 repo_path = get_new_dir(str(time.time()))
218 repo_path = get_new_dir(str(time.time()))
218 repo = Backend(repo_path, create=True)
219 repo = Backend(repo_path, create=True)
219
220
220 with self.assertRaises(EmptyRepositoryError):
221 with pytest.raises(EmptyRepositoryError):
221 list(repo.get_changesets(start='foobar'))
222 list(repo.get_changesets(start='foobar'))
222
223
223 def test_get_changesets_includes_end_changeset(self):
224 def test_get_changesets_includes_end_changeset(self):
224 second_id = self.repo.revisions[1]
225 second_id = self.repo.revisions[1]
225 changesets = list(self.repo.get_changesets(end=second_id))
226 changesets = list(self.repo.get_changesets(end=second_id))
226 self.assertEqual(changesets[-1].raw_id, second_id)
227 assert changesets[-1].raw_id == second_id
227
228
228 def test_get_changesets_respects_start_date(self):
229 def test_get_changesets_respects_start_date(self):
229 start_date = datetime.datetime(2010, 2, 1)
230 start_date = datetime.datetime(2010, 2, 1)
230 for cs in self.repo.get_changesets(start_date=start_date):
231 for cs in self.repo.get_changesets(start_date=start_date):
231 self.assertGreaterEqual(cs.date, start_date)
232 assert cs.date >= start_date
232
233
233 def test_get_changesets_respects_end_date(self):
234 def test_get_changesets_respects_end_date(self):
234 start_date = datetime.datetime(2010, 1, 1)
235 start_date = datetime.datetime(2010, 1, 1)
235 end_date = datetime.datetime(2010, 2, 1)
236 end_date = datetime.datetime(2010, 2, 1)
236 for cs in self.repo.get_changesets(start_date=start_date,
237 for cs in self.repo.get_changesets(start_date=start_date,
237 end_date=end_date):
238 end_date=end_date):
238 self.assertGreaterEqual(cs.date, start_date)
239 assert cs.date >= start_date
239 self.assertLessEqual(cs.date, end_date)
240 assert cs.date <= end_date
240
241
241 def test_get_changesets_respects_start_date_and_end_date(self):
242 def test_get_changesets_respects_start_date_and_end_date(self):
242 end_date = datetime.datetime(2010, 2, 1)
243 end_date = datetime.datetime(2010, 2, 1)
243 for cs in self.repo.get_changesets(end_date=end_date):
244 for cs in self.repo.get_changesets(end_date=end_date):
244 self.assertLessEqual(cs.date, end_date)
245 assert cs.date <= end_date
245
246
246 def test_get_changesets_respects_reverse(self):
247 def test_get_changesets_respects_reverse(self):
247 changesets_id_list = [cs.raw_id for cs in
248 changesets_id_list = [cs.raw_id for cs in
248 self.repo.get_changesets(reverse=True)]
249 self.repo.get_changesets(reverse=True)]
249 self.assertItemsEqual(changesets_id_list, reversed(self.repo.revisions))
250 assert changesets_id_list == list(reversed(self.repo.revisions))
250
251
251 def test_get_filenodes_generator(self):
252 def test_get_filenodes_generator(self):
252 tip = self.repo.get_changeset()
253 tip = self.repo.get_changeset()
253 filepaths = [node.path for node in tip.get_filenodes_generator()]
254 filepaths = [node.path for node in tip.get_filenodes_generator()]
254 self.assertItemsEqual(filepaths, ['file_%d.txt' % x for x in xrange(5)])
255 assert filepaths == ['file_%d.txt' % x for x in xrange(5)]
255
256
256 def test_size(self):
257 def test_size(self):
257 tip = self.repo.get_changeset()
258 tip = self.repo.get_changeset()
258 size = 5 * len('Foobar N') # Size of 5 files
259 size = 5 * len('Foobar N') # Size of 5 files
259 self.assertEqual(tip.size, size)
260 assert tip.size == size
260
261
261 def test_author(self):
262 def test_author(self):
262 tip = self.repo.get_changeset()
263 tip = self.repo.get_changeset()
263 self.assertEqual(tip.author, u'Joe Doe <joe.doe@example.com>')
264 assert tip.author == u'Joe Doe <joe.doe@example.com>'
264
265
265 def test_author_name(self):
266 def test_author_name(self):
266 tip = self.repo.get_changeset()
267 tip = self.repo.get_changeset()
267 self.assertEqual(tip.author_name, u'Joe Doe')
268 assert tip.author_name == u'Joe Doe'
268
269
269 def test_author_email(self):
270 def test_author_email(self):
270 tip = self.repo.get_changeset()
271 tip = self.repo.get_changeset()
271 self.assertEqual(tip.author_email, u'joe.doe@example.com')
272 assert tip.author_email == u'joe.doe@example.com'
272
273
273 def test_get_changesets_raise_changesetdoesnotexist_for_wrong_start(self):
274 def test_get_changesets_raise_changesetdoesnotexist_for_wrong_start(self):
274 with self.assertRaises(ChangesetDoesNotExistError):
275 with pytest.raises(ChangesetDoesNotExistError):
275 list(self.repo.get_changesets(start='foobar'))
276 list(self.repo.get_changesets(start='foobar'))
276
277
277 def test_get_changesets_raise_changesetdoesnotexist_for_wrong_end(self):
278 def test_get_changesets_raise_changesetdoesnotexist_for_wrong_end(self):
278 with self.assertRaises(ChangesetDoesNotExistError):
279 with pytest.raises(ChangesetDoesNotExistError):
279 list(self.repo.get_changesets(end='foobar'))
280 list(self.repo.get_changesets(end='foobar'))
280
281
281 def test_get_changesets_raise_branchdoesnotexist_for_wrong_branch_name(self):
282 def test_get_changesets_raise_branchdoesnotexist_for_wrong_branch_name(self):
282 with self.assertRaises(BranchDoesNotExistError):
283 with pytest.raises(BranchDoesNotExistError):
283 list(self.repo.get_changesets(branch_name='foobar'))
284 list(self.repo.get_changesets(branch_name='foobar'))
284
285
285 def test_get_changesets_raise_repositoryerror_for_wrong_start_end(self):
286 def test_get_changesets_raise_repositoryerror_for_wrong_start_end(self):
286 start = self.repo.revisions[-1]
287 start = self.repo.revisions[-1]
287 end = self.repo.revisions[0]
288 end = self.repo.revisions[0]
288 with self.assertRaises(RepositoryError):
289 with pytest.raises(RepositoryError):
289 list(self.repo.get_changesets(start=start, end=end))
290 list(self.repo.get_changesets(start=start, end=end))
290
291
291 def test_get_changesets_numerical_id_reversed(self):
292 def test_get_changesets_numerical_id_reversed(self):
292 with self.assertRaises(RepositoryError):
293 with pytest.raises(RepositoryError):
293 [x for x in self.repo.get_changesets(start=3, end=2)]
294 [x for x in self.repo.get_changesets(start=3, end=2)]
294
295
295 def test_get_changesets_numerical_id_respects_both_start_and_end_last(self):
296 def test_get_changesets_numerical_id_respects_both_start_and_end_last(self):
296 with self.assertRaises(RepositoryError):
297 with pytest.raises(RepositoryError):
297 last = len(self.repo.revisions)
298 last = len(self.repo.revisions)
298 list(self.repo.get_changesets(start=last-1, end=last-2))
299 list(self.repo.get_changesets(start=last-1, end=last-2))
299
300
300 def test_get_changesets_numerical_id_last_zero_error(self):
301 def test_get_changesets_numerical_id_last_zero_error(self):
301 with self.assertRaises(RepositoryError):
302 with pytest.raises(RepositoryError):
302 last = len(self.repo.revisions)
303 last = len(self.repo.revisions)
303 list(self.repo.get_changesets(start=last-1, end=0))
304 list(self.repo.get_changesets(start=last-1, end=0))
304
305
305
306
306 class _ChangesetsChangesTestCaseMixin(_BackendTestMixin):
307 class _ChangesetsChangesTestCaseMixin(_BackendTestMixin):
307 recreate_repo_per_test = False
308 recreate_repo_per_test = False
308
309
309 @classmethod
310 @classmethod
310 def _get_commits(cls):
311 def _get_commits(cls):
311 return [
312 return [
312 {
313 {
313 'message': u'Initial',
314 'message': u'Initial',
314 'author': u'Joe Doe <joe.doe@example.com>',
315 'author': u'Joe Doe <joe.doe@example.com>',
315 'date': datetime.datetime(2010, 1, 1, 20),
316 'date': datetime.datetime(2010, 1, 1, 20),
316 'added': [
317 'added': [
317 FileNode('foo/bar', content='foo'),
318 FileNode('foo/bar', content='foo'),
318 FileNode('foo/baΕ‚', content='foo'),
319 FileNode('foo/baΕ‚', content='foo'),
319 FileNode('foobar', content='foo'),
320 FileNode('foobar', content='foo'),
320 FileNode('qwe', content='foo'),
321 FileNode('qwe', content='foo'),
321 ],
322 ],
322 },
323 },
323 {
324 {
324 'message': u'Massive changes',
325 'message': u'Massive changes',
325 'author': u'Joe Doe <joe.doe@example.com>',
326 'author': u'Joe Doe <joe.doe@example.com>',
326 'date': datetime.datetime(2010, 1, 1, 22),
327 'date': datetime.datetime(2010, 1, 1, 22),
327 'added': [FileNode('fallout', content='War never changes')],
328 'added': [FileNode('fallout', content='War never changes')],
328 'changed': [
329 'changed': [
329 FileNode('foo/bar', content='baz'),
330 FileNode('foo/bar', content='baz'),
330 FileNode('foobar', content='baz'),
331 FileNode('foobar', content='baz'),
331 ],
332 ],
332 'removed': [FileNode('qwe')],
333 'removed': [FileNode('qwe')],
333 },
334 },
334 ]
335 ]
335
336
336 def test_initial_commit(self):
337 def test_initial_commit(self):
337 changeset = self.repo.get_changeset(0)
338 changeset = self.repo.get_changeset(0)
338 self.assertItemsEqual(changeset.added, [
339 assert sorted(list(changeset.added)) == sorted([
339 changeset.get_node('foo/bar'),
340 changeset.get_node('foo/bar'),
340 changeset.get_node('foo/baΕ‚'),
341 changeset.get_node('foo/baΕ‚'),
341 changeset.get_node('foobar'),
342 changeset.get_node('foobar'),
342 changeset.get_node('qwe'),
343 changeset.get_node('qwe'),
343 ])
344 ])
344 self.assertItemsEqual(changeset.changed, [])
345 assert list(changeset.changed) == []
345 self.assertItemsEqual(changeset.removed, [])
346 assert list(changeset.removed) == []
346 assert u'foo/ba\u0142' in changeset.as_dict()['added']
347 assert u'foo/ba\u0142' in changeset.as_dict()['added']
347 assert u'foo/ba\u0142' in changeset.__json__(with_file_list=True)['added']
348 assert u'foo/ba\u0142' in changeset.__json__(with_file_list=True)['added']
348
349
349 def test_head_added(self):
350 def test_head_added(self):
350 changeset = self.repo.get_changeset()
351 changeset = self.repo.get_changeset()
351 self.assertTrue(isinstance(changeset.added, AddedFileNodesGenerator))
352 assert isinstance(changeset.added, AddedFileNodesGenerator)
352 self.assertItemsEqual(changeset.added, [
353 assert list(changeset.added) == [
353 changeset.get_node('fallout'),
354 changeset.get_node('fallout'),
354 ])
355 ]
355 self.assertTrue(isinstance(changeset.changed, ChangedFileNodesGenerator))
356 assert isinstance(changeset.changed, ChangedFileNodesGenerator)
356 self.assertItemsEqual(changeset.changed, [
357 assert list(changeset.changed) == [
357 changeset.get_node('foo/bar'),
358 changeset.get_node('foo/bar'),
358 changeset.get_node('foobar'),
359 changeset.get_node('foobar'),
359 ])
360 ]
360 self.assertTrue(isinstance(changeset.removed, RemovedFileNodesGenerator))
361 assert isinstance(changeset.removed, RemovedFileNodesGenerator)
361 self.assertEqual(len(changeset.removed), 1)
362 assert len(changeset.removed) == 1
362 self.assertEqual(list(changeset.removed)[0].path, 'qwe')
363 assert list(changeset.removed)[0].path == 'qwe'
363
364
364 def test_get_filemode(self):
365 def test_get_filemode(self):
365 changeset = self.repo.get_changeset()
366 changeset = self.repo.get_changeset()
366 self.assertEqual(33188, changeset.get_file_mode('foo/bar'))
367 assert 33188 == changeset.get_file_mode('foo/bar')
367
368
368 def test_get_filemode_non_ascii(self):
369 def test_get_filemode_non_ascii(self):
369 changeset = self.repo.get_changeset()
370 changeset = self.repo.get_changeset()
370 self.assertEqual(33188, changeset.get_file_mode('foo/baΕ‚'))
371 assert 33188 == changeset.get_file_mode('foo/baΕ‚')
371 self.assertEqual(33188, changeset.get_file_mode(u'foo/baΕ‚'))
372 assert 33188 == changeset.get_file_mode(u'foo/baΕ‚')
372
373
373
374
374 # For each backend create test case class
375 # For each backend create test case class
375 for alias in SCM_TESTS:
376 for alias in SCM_TESTS:
376 attrs = {
377 attrs = {
377 'backend_alias': alias,
378 'backend_alias': alias,
378 }
379 }
379 # tests with additional commits
380 # tests with additional commits
380 cls_name = alias.title() + 'ChangesetsWithCommitsTest'
381 cls_name = 'Test' + alias.title() + 'ChangesetsWithCommits'
381 bases = (_ChangesetsWithCommitsTestCaseixin, unittest.TestCase)
382 globals()[cls_name] = type(cls_name, (_ChangesetsWithCommitsTestCaseixin,), attrs)
382 globals()[cls_name] = type(cls_name, bases, attrs)
383
383
384 # tests without additional commits
384 # tests without additional commits
385 cls_name = alias.title() + 'ChangesetsTest'
385 cls_name = 'Test' + alias.title() + 'Changesets'
386 bases = (_ChangesetsTestCaseMixin, unittest.TestCase)
386 globals()[cls_name] = type(cls_name, (_ChangesetsTestCaseMixin,), attrs)
387 globals()[cls_name] = type(cls_name, bases, attrs)
388
387
389 # tests changes
388 # tests changes
390 cls_name = alias.title() + 'ChangesetsChangesTest'
389 cls_name = 'Test' + alias.title() + 'ChangesetsChanges'
391 bases = (_ChangesetsChangesTestCaseMixin, unittest.TestCase)
390 globals()[cls_name] = type(cls_name, (_ChangesetsChangesTestCaseMixin,), attrs)
392 globals()[cls_name] = type(cls_name, bases, attrs)
@@ -1,43 +1,43 b''
1 # encoding: utf8
1 # encoding: utf8
2
2
3 import datetime
3 import datetime
4
4
5 from kallithea.lib.vcs.nodes import FileNode
5 from kallithea.lib.vcs.nodes import FileNode
6 from kallithea.tests.vcs.test_inmemchangesets import BackendBaseTestCase
6 from kallithea.tests.vcs.test_inmemchangesets import BackendBaseTestCase
7 from kallithea.tests.vcs.conf import SCM_TESTS
7 from kallithea.tests.vcs.conf import SCM_TESTS
8
8
9
9
10 class FileNodeUnicodePathTestsMixin(object):
10 class FileNodeUnicodePathTestsMixin(object):
11
11
12 fname = 'Δ…Ε›Γ°Δ…Δ™Ε‚Δ…Δ‡.txt'
12 fname = 'Δ…Ε›Γ°Δ…Δ™Ε‚Δ…Δ‡.txt'
13 ufname = (fname).decode('utf-8')
13 ufname = (fname).decode('utf-8')
14
14
15 def get_commits(self):
15 def get_commits(self):
16 self.nodes = [
16 self.nodes = [
17 FileNode(self.fname, content='Foobar'),
17 FileNode(self.fname, content='Foobar'),
18 ]
18 ]
19
19
20 commits = [
20 commits = [
21 {
21 {
22 'message': 'Initial commit',
22 'message': 'Initial commit',
23 'author': 'Joe Doe <joe.doe@example.com>',
23 'author': 'Joe Doe <joe.doe@example.com>',
24 'date': datetime.datetime(2010, 1, 1, 20),
24 'date': datetime.datetime(2010, 1, 1, 20),
25 'added': self.nodes,
25 'added': self.nodes,
26 },
26 },
27 ]
27 ]
28 return commits
28 return commits
29
29
30 def test_filenode_path(self):
30 def test_filenode_path(self):
31 node = self.tip.get_node(self.fname)
31 node = self.tip.get_node(self.fname)
32 unode = self.tip.get_node(self.ufname)
32 unode = self.tip.get_node(self.ufname)
33 self.assertEqual(node, unode)
33 assert node == unode
34
34
35
35
36 for alias in SCM_TESTS:
36 for alias in SCM_TESTS:
37 attrs = {
37 attrs = {
38 'backend_alias': alias,
38 'backend_alias': alias,
39 }
39 }
40 cls_name = ''.join(('%s file node unicode path test' % alias).title()
40 cls_name = ''.join(('test %s file node unicode path' % alias).title()
41 .split())
41 .split())
42 bases = (FileNodeUnicodePathTestsMixin, BackendBaseTestCase)
42 bases = (FileNodeUnicodePathTestsMixin, BackendBaseTestCase)
43 globals()[cls_name] = type(cls_name, bases, attrs)
43 globals()[cls_name] = type(cls_name, bases, attrs)
@@ -1,39 +1,37 b''
1 import datetime
1 import datetime
2
2
3 from kallithea.tests.vcs.base import _BackendTestMixin
3 from kallithea.tests.vcs.base import _BackendTestMixin
4 from kallithea.tests.vcs.conf import SCM_TESTS
4 from kallithea.tests.vcs.conf import SCM_TESTS
5 from kallithea.lib.vcs.nodes import FileNode
5 from kallithea.lib.vcs.nodes import FileNode
6 from kallithea.lib.vcs.utils.compat import unittest
7
6
8
7
9 class GetitemTestCaseMixin(_BackendTestMixin):
8 class GetitemTestCaseMixin(_BackendTestMixin):
10
9
11 @classmethod
10 @classmethod
12 def _get_commits(cls):
11 def _get_commits(cls):
13 start_date = datetime.datetime(2010, 1, 1, 20)
12 start_date = datetime.datetime(2010, 1, 1, 20)
14 for x in xrange(5):
13 for x in xrange(5):
15 yield {
14 yield {
16 'message': 'Commit %d' % x,
15 'message': 'Commit %d' % x,
17 'author': 'Joe Doe <joe.doe@example.com>',
16 'author': 'Joe Doe <joe.doe@example.com>',
18 'date': start_date + datetime.timedelta(hours=12 * x),
17 'date': start_date + datetime.timedelta(hours=12 * x),
19 'added': [
18 'added': [
20 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
19 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
21 ],
20 ],
22 }
21 }
23
22
24 def test__getitem__last_item_is_tip(self):
23 def test__getitem__last_item_is_tip(self):
25 self.assertEqual(self.repo[-1], self.repo.get_changeset())
24 assert self.repo[-1] == self.repo.get_changeset()
26
25
27 def test__getitem__returns_correct_items(self):
26 def test__getitem__returns_correct_items(self):
28 changesets = [self.repo[x] for x in xrange(len(self.repo.revisions))]
27 changesets = [self.repo[x] for x in xrange(len(self.repo.revisions))]
29 self.assertEqual(changesets, list(self.repo.get_changesets()))
28 assert changesets == list(self.repo.get_changesets())
30
29
31
30
32 # For each backend create test case class
31 # For each backend create test case class
33 for alias in SCM_TESTS:
32 for alias in SCM_TESTS:
34 attrs = {
33 attrs = {
35 'backend_alias': alias,
34 'backend_alias': alias,
36 }
35 }
37 cls_name = ''.join(('%s getitem test' % alias).title().split())
36 cls_name = ''.join(('test %s getitem' % alias).title().split())
38 bases = (GetitemTestCaseMixin, unittest.TestCase)
37 globals()[cls_name] = type(cls_name, (GetitemTestCaseMixin,), attrs)
39 globals()[cls_name] = type(cls_name, bases, attrs)
@@ -1,53 +1,46 b''
1 import datetime
1 import datetime
2
2
3 from kallithea.lib.vcs.nodes import FileNode
3 from kallithea.lib.vcs.nodes import FileNode
4
4
5 from kallithea.lib.vcs.utils.compat import unittest
6
7 from kallithea.tests.vcs.base import _BackendTestMixin
5 from kallithea.tests.vcs.base import _BackendTestMixin
8 from kallithea.tests.vcs.conf import SCM_TESTS
6 from kallithea.tests.vcs.conf import SCM_TESTS
9
7
10
8
11 class GetsliceTestCaseMixin(_BackendTestMixin):
9 class GetsliceTestCaseMixin(_BackendTestMixin):
12
10
13 @classmethod
11 @classmethod
14 def _get_commits(cls):
12 def _get_commits(cls):
15 start_date = datetime.datetime(2010, 1, 1, 20)
13 start_date = datetime.datetime(2010, 1, 1, 20)
16 for x in xrange(5):
14 for x in xrange(5):
17 yield {
15 yield {
18 'message': 'Commit %d' % x,
16 'message': 'Commit %d' % x,
19 'author': 'Joe Doe <joe.doe@example.com>',
17 'author': 'Joe Doe <joe.doe@example.com>',
20 'date': start_date + datetime.timedelta(hours=12 * x),
18 'date': start_date + datetime.timedelta(hours=12 * x),
21 'added': [
19 'added': [
22 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
20 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
23 ],
21 ],
24 }
22 }
25
23
26 def test__getslice__last_item_is_tip(self):
24 def test__getslice__last_item_is_tip(self):
27 self.assertEqual(list(self.repo[-1:])[0], self.repo.get_changeset())
25 assert list(self.repo[-1:])[0] == self.repo.get_changeset()
28
26
29 def test__getslice__respects_start_index(self):
27 def test__getslice__respects_start_index(self):
30 self.assertEqual(list(self.repo[2:]),
28 assert list(self.repo[2:]) == [self.repo.get_changeset(rev) for rev in self.repo.revisions[2:]]
31 [self.repo.get_changeset(rev) for rev in self.repo.revisions[2:]])
32
29
33 def test__getslice__respects_negative_start_index(self):
30 def test__getslice__respects_negative_start_index(self):
34 self.assertEqual(list(self.repo[-2:]),
31 assert list(self.repo[-2:]) == [self.repo.get_changeset(rev) for rev in self.repo.revisions[-2:]]
35 [self.repo.get_changeset(rev) for rev in self.repo.revisions[-2:]])
36
32
37 def test__getslice__respects_end_index(self):
33 def test__getslice__respects_end_index(self):
38 self.assertEqual(list(self.repo[:2]),
34 assert list(self.repo[:2]) == [self.repo.get_changeset(rev) for rev in self.repo.revisions[:2]]
39 [self.repo.get_changeset(rev) for rev in self.repo.revisions[:2]])
40
35
41 def test__getslice__respects_negative_end_index(self):
36 def test__getslice__respects_negative_end_index(self):
42 self.assertEqual(list(self.repo[:-2]),
37 assert list(self.repo[:-2]) == [self.repo.get_changeset(rev) for rev in self.repo.revisions[:-2]]
43 [self.repo.get_changeset(rev) for rev in self.repo.revisions[:-2]])
44
38
45
39
46 # For each backend create test case class
40 # For each backend create test case class
47 for alias in SCM_TESTS:
41 for alias in SCM_TESTS:
48 attrs = {
42 attrs = {
49 'backend_alias': alias,
43 'backend_alias': alias,
50 }
44 }
51 cls_name = ''.join(('%s getslice test' % alias).title().split())
45 cls_name = ''.join(('test %s getslice' % alias).title().split())
52 bases = (GetsliceTestCaseMixin, unittest.TestCase)
46 globals()[cls_name] = type(cls_name, (GetsliceTestCaseMixin,), attrs)
53 globals()[cls_name] = type(cls_name, bases, attrs)
@@ -1,847 +1,828 b''
1 import os
1 import os
2 import sys
2 import sys
3 import mock
3 import mock
4 import datetime
4 import datetime
5 import urllib2
5 import urllib2
6
6
7 import pytest
7 import pytest
8
8
9 from kallithea.lib.vcs.backends.git import GitRepository, GitChangeset
9 from kallithea.lib.vcs.backends.git import GitRepository, GitChangeset
10 from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
10 from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
11 from kallithea.lib.vcs.nodes import NodeKind, FileNode, DirNode, NodeState
11 from kallithea.lib.vcs.nodes import NodeKind, FileNode, DirNode, NodeState
12 from kallithea.lib.vcs.utils.compat import unittest
13 from kallithea.model.scm import ScmModel
12 from kallithea.model.scm import ScmModel
14
13
15 from kallithea.tests.vcs.base import _BackendTestMixin
14 from kallithea.tests.vcs.base import _BackendTestMixin
16 from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, TESTS_TMP_PATH, get_new_dir
15 from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, TESTS_TMP_PATH, get_new_dir
17
16
18
17
19 class GitRepositoryTest(unittest.TestCase):
18 class TestGitRepository(object):
20
19
21 def __check_for_existing_repo(self):
20 def __check_for_existing_repo(self):
22 if os.path.exists(TEST_GIT_REPO_CLONE):
21 if os.path.exists(TEST_GIT_REPO_CLONE):
23 pytest.fail('Cannot test git clone repo as location %s already '
22 pytest.fail('Cannot test git clone repo as location %s already '
24 'exists. You should manually remove it first.'
23 'exists. You should manually remove it first.'
25 % TEST_GIT_REPO_CLONE)
24 % TEST_GIT_REPO_CLONE)
26
25
27 def setUp(self):
26 def setup_method(self):
28 self.repo = GitRepository(TEST_GIT_REPO)
27 self.repo = GitRepository(TEST_GIT_REPO)
29
28
30 def test_wrong_repo_path(self):
29 def test_wrong_repo_path(self):
31 wrong_repo_path = os.path.join(TESTS_TMP_PATH, 'errorrepo')
30 wrong_repo_path = os.path.join(TESTS_TMP_PATH, 'errorrepo')
32 self.assertRaises(RepositoryError, GitRepository, wrong_repo_path)
31 with pytest.raises(RepositoryError):
32 GitRepository(wrong_repo_path)
33
33
34 def test_git_cmd_injection(self):
34 def test_git_cmd_injection(self):
35 repo_inject_path = TEST_GIT_REPO + '; echo "Cake";'
35 repo_inject_path = TEST_GIT_REPO + '; echo "Cake";'
36 with self.assertRaises(urllib2.URLError):
36 with pytest.raises(urllib2.URLError):
37 # Should fail because URL will contain the parts after ; too
37 # Should fail because URL will contain the parts after ; too
38 GitRepository(get_new_dir('injection-repo'), src_url=repo_inject_path, update_after_clone=True, create=True)
38 GitRepository(get_new_dir('injection-repo'), src_url=repo_inject_path, update_after_clone=True, create=True)
39
39
40 with self.assertRaises(RepositoryError):
40 with pytest.raises(RepositoryError):
41 # Should fail on direct clone call, which as of this writing does not happen outside of class
41 # Should fail on direct clone call, which as of this writing does not happen outside of class
42 clone_fail_repo = GitRepository(get_new_dir('injection-repo'), create=True)
42 clone_fail_repo = GitRepository(get_new_dir('injection-repo'), create=True)
43 clone_fail_repo.clone(repo_inject_path, update_after_clone=True,)
43 clone_fail_repo.clone(repo_inject_path, update_after_clone=True,)
44
44
45 # Verify correct quoting of evil characters that should work on posix file systems
45 # Verify correct quoting of evil characters that should work on posix file systems
46 if sys.platform == 'win32':
46 if sys.platform == 'win32':
47 # windows does not allow '"' in dir names
47 # windows does not allow '"' in dir names
48 # and some versions of the git client don't like ` and '
48 # and some versions of the git client don't like ` and '
49 tricky_path = get_new_dir("tricky-path-repo-$")
49 tricky_path = get_new_dir("tricky-path-repo-$")
50 else:
50 else:
51 tricky_path = get_new_dir("tricky-path-repo-$'\"`")
51 tricky_path = get_new_dir("tricky-path-repo-$'\"`")
52 successfully_cloned = GitRepository(tricky_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True)
52 successfully_cloned = GitRepository(tricky_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True)
53 # Repo should have been created
53 # Repo should have been created
54 self.assertFalse(successfully_cloned._repo.bare)
54 assert not successfully_cloned._repo.bare
55
55
56 if sys.platform == 'win32':
56 if sys.platform == 'win32':
57 # windows does not allow '"' in dir names
57 # windows does not allow '"' in dir names
58 # and some versions of the git client don't like ` and '
58 # and some versions of the git client don't like ` and '
59 tricky_path_2 = get_new_dir("tricky-path-2-repo-$")
59 tricky_path_2 = get_new_dir("tricky-path-2-repo-$")
60 else:
60 else:
61 tricky_path_2 = get_new_dir("tricky-path-2-repo-$'\"`")
61 tricky_path_2 = get_new_dir("tricky-path-2-repo-$'\"`")
62 successfully_cloned2 = GitRepository(tricky_path_2, src_url=tricky_path, bare=True, create=True)
62 successfully_cloned2 = GitRepository(tricky_path_2, src_url=tricky_path, bare=True, create=True)
63 # Repo should have been created and thus used correct quoting for clone
63 # Repo should have been created and thus used correct quoting for clone
64 self.assertTrue(successfully_cloned2._repo.bare)
64 assert successfully_cloned2._repo.bare
65
65
66 # Should pass because URL has been properly quoted
66 # Should pass because URL has been properly quoted
67 successfully_cloned.pull(tricky_path_2)
67 successfully_cloned.pull(tricky_path_2)
68 successfully_cloned2.fetch(tricky_path)
68 successfully_cloned2.fetch(tricky_path)
69
69
70 def test_repo_create_with_spaces_in_path(self):
70 def test_repo_create_with_spaces_in_path(self):
71 repo_path = get_new_dir("path with spaces")
71 repo_path = get_new_dir("path with spaces")
72 repo = GitRepository(repo_path, src_url=None, bare=True, create=True)
72 repo = GitRepository(repo_path, src_url=None, bare=True, create=True)
73 # Repo should have been created
73 # Repo should have been created
74 self.assertTrue(repo._repo.bare)
74 assert repo._repo.bare
75
75
76 def test_repo_clone(self):
76 def test_repo_clone(self):
77 self.__check_for_existing_repo()
77 self.__check_for_existing_repo()
78 repo = GitRepository(TEST_GIT_REPO)
78 repo = GitRepository(TEST_GIT_REPO)
79 repo_clone = GitRepository(TEST_GIT_REPO_CLONE,
79 repo_clone = GitRepository(TEST_GIT_REPO_CLONE,
80 src_url=TEST_GIT_REPO, create=True, update_after_clone=True)
80 src_url=TEST_GIT_REPO, create=True, update_after_clone=True)
81 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
81 assert len(repo.revisions) == len(repo_clone.revisions)
82 # Checking hashes of changesets should be enough
82 # Checking hashes of changesets should be enough
83 for changeset in repo.get_changesets():
83 for changeset in repo.get_changesets():
84 raw_id = changeset.raw_id
84 raw_id = changeset.raw_id
85 self.assertEqual(raw_id, repo_clone.get_changeset(raw_id).raw_id)
85 assert raw_id == repo_clone.get_changeset(raw_id).raw_id
86
86
87 def test_repo_clone_with_spaces_in_path(self):
87 def test_repo_clone_with_spaces_in_path(self):
88 repo_path = get_new_dir("path with spaces")
88 repo_path = get_new_dir("path with spaces")
89 successfully_cloned = GitRepository(repo_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True)
89 successfully_cloned = GitRepository(repo_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True)
90 # Repo should have been created
90 # Repo should have been created
91 self.assertFalse(successfully_cloned._repo.bare)
91 assert not successfully_cloned._repo.bare
92
92
93 successfully_cloned.pull(TEST_GIT_REPO)
93 successfully_cloned.pull(TEST_GIT_REPO)
94 self.repo.fetch(repo_path)
94 self.repo.fetch(repo_path)
95
95
96 def test_repo_clone_without_create(self):
96 def test_repo_clone_without_create(self):
97 self.assertRaises(RepositoryError, GitRepository,
97 with pytest.raises(RepositoryError):
98 TEST_GIT_REPO_CLONE + '_wo_create', src_url=TEST_GIT_REPO)
98 GitRepository(TEST_GIT_REPO_CLONE + '_wo_create', src_url=TEST_GIT_REPO)
99
99
100 def test_repo_clone_with_update(self):
100 def test_repo_clone_with_update(self):
101 repo = GitRepository(TEST_GIT_REPO)
101 repo = GitRepository(TEST_GIT_REPO)
102 clone_path = TEST_GIT_REPO_CLONE + '_with_update'
102 clone_path = TEST_GIT_REPO_CLONE + '_with_update'
103 repo_clone = GitRepository(clone_path,
103 repo_clone = GitRepository(clone_path,
104 create=True, src_url=TEST_GIT_REPO, update_after_clone=True)
104 create=True, src_url=TEST_GIT_REPO, update_after_clone=True)
105 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
105 assert len(repo.revisions) == len(repo_clone.revisions)
106
106
107 # check if current workdir was updated
107 # check if current workdir was updated
108 fpath = os.path.join(clone_path, 'MANIFEST.in')
108 fpath = os.path.join(clone_path, 'MANIFEST.in')
109 self.assertEqual(True, os.path.isfile(fpath),
109 assert os.path.isfile(fpath) == True, 'Repo was cloned and updated but file %s could not be found' % fpath
110 'Repo was cloned and updated but file %s could not be found'
111 % fpath)
112
110
113 def test_repo_clone_without_update(self):
111 def test_repo_clone_without_update(self):
114 repo = GitRepository(TEST_GIT_REPO)
112 repo = GitRepository(TEST_GIT_REPO)
115 clone_path = TEST_GIT_REPO_CLONE + '_without_update'
113 clone_path = TEST_GIT_REPO_CLONE + '_without_update'
116 repo_clone = GitRepository(clone_path,
114 repo_clone = GitRepository(clone_path,
117 create=True, src_url=TEST_GIT_REPO, update_after_clone=False)
115 create=True, src_url=TEST_GIT_REPO, update_after_clone=False)
118 self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
116 assert len(repo.revisions) == len(repo_clone.revisions)
119 # check if current workdir was *NOT* updated
117 # check if current workdir was *NOT* updated
120 fpath = os.path.join(clone_path, 'MANIFEST.in')
118 fpath = os.path.join(clone_path, 'MANIFEST.in')
121 # Make sure it's not bare repo
119 # Make sure it's not bare repo
122 self.assertFalse(repo_clone._repo.bare)
120 assert not repo_clone._repo.bare
123 self.assertEqual(False, os.path.isfile(fpath),
121 assert os.path.isfile(fpath) == False, 'Repo was cloned and updated but file %s was found' % fpath
124 'Repo was cloned and updated but file %s was found'
125 % fpath)
126
122
127 def test_repo_clone_into_bare_repo(self):
123 def test_repo_clone_into_bare_repo(self):
128 repo = GitRepository(TEST_GIT_REPO)
124 repo = GitRepository(TEST_GIT_REPO)
129 clone_path = TEST_GIT_REPO_CLONE + '_bare.git'
125 clone_path = TEST_GIT_REPO_CLONE + '_bare.git'
130 repo_clone = GitRepository(clone_path, create=True,
126 repo_clone = GitRepository(clone_path, create=True,
131 src_url=repo.path, bare=True)
127 src_url=repo.path, bare=True)
132 self.assertTrue(repo_clone._repo.bare)
128 assert repo_clone._repo.bare
133
129
134 def test_create_repo_is_not_bare_by_default(self):
130 def test_create_repo_is_not_bare_by_default(self):
135 repo = GitRepository(get_new_dir('not-bare-by-default'), create=True)
131 repo = GitRepository(get_new_dir('not-bare-by-default'), create=True)
136 self.assertFalse(repo._repo.bare)
132 assert not repo._repo.bare
137
133
138 def test_create_bare_repo(self):
134 def test_create_bare_repo(self):
139 repo = GitRepository(get_new_dir('bare-repo'), create=True, bare=True)
135 repo = GitRepository(get_new_dir('bare-repo'), create=True, bare=True)
140 self.assertTrue(repo._repo.bare)
136 assert repo._repo.bare
141
137
142 def test_revisions(self):
138 def test_revisions(self):
143 # there are 112 revisions (by now)
139 # there are 112 revisions (by now)
144 # so we can assume they would be available from now on
140 # so we can assume they would be available from now on
145 subset = set([
141 subset = set([
146 'c1214f7e79e02fc37156ff215cd71275450cffc3',
142 'c1214f7e79e02fc37156ff215cd71275450cffc3',
147 '38b5fe81f109cb111f549bfe9bb6b267e10bc557',
143 '38b5fe81f109cb111f549bfe9bb6b267e10bc557',
148 'fa6600f6848800641328adbf7811fd2372c02ab2',
144 'fa6600f6848800641328adbf7811fd2372c02ab2',
149 '102607b09cdd60e2793929c4f90478be29f85a17',
145 '102607b09cdd60e2793929c4f90478be29f85a17',
150 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
146 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
151 '2d1028c054665b962fa3d307adfc923ddd528038',
147 '2d1028c054665b962fa3d307adfc923ddd528038',
152 'd7e0d30fbcae12c90680eb095a4f5f02505ce501',
148 'd7e0d30fbcae12c90680eb095a4f5f02505ce501',
153 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
149 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
154 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
150 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
155 '8430a588b43b5d6da365400117c89400326e7992',
151 '8430a588b43b5d6da365400117c89400326e7992',
156 'd955cd312c17b02143c04fa1099a352b04368118',
152 'd955cd312c17b02143c04fa1099a352b04368118',
157 'f67b87e5c629c2ee0ba58f85197e423ff28d735b',
153 'f67b87e5c629c2ee0ba58f85197e423ff28d735b',
158 'add63e382e4aabc9e1afdc4bdc24506c269b7618',
154 'add63e382e4aabc9e1afdc4bdc24506c269b7618',
159 'f298fe1189f1b69779a4423f40b48edf92a703fc',
155 'f298fe1189f1b69779a4423f40b48edf92a703fc',
160 'bd9b619eb41994cac43d67cf4ccc8399c1125808',
156 'bd9b619eb41994cac43d67cf4ccc8399c1125808',
161 '6e125e7c890379446e98980d8ed60fba87d0f6d1',
157 '6e125e7c890379446e98980d8ed60fba87d0f6d1',
162 'd4a54db9f745dfeba6933bf5b1e79e15d0af20bd',
158 'd4a54db9f745dfeba6933bf5b1e79e15d0af20bd',
163 '0b05e4ed56c802098dfc813cbe779b2f49e92500',
159 '0b05e4ed56c802098dfc813cbe779b2f49e92500',
164 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
160 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
165 '45223f8f114c64bf4d6f853e3c35a369a6305520',
161 '45223f8f114c64bf4d6f853e3c35a369a6305520',
166 'ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
162 'ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
167 'f5ea29fc42ef67a2a5a7aecff10e1566699acd68',
163 'f5ea29fc42ef67a2a5a7aecff10e1566699acd68',
168 '27d48942240f5b91dfda77accd2caac94708cc7d',
164 '27d48942240f5b91dfda77accd2caac94708cc7d',
169 '622f0eb0bafd619d2560c26f80f09e3b0b0d78af',
165 '622f0eb0bafd619d2560c26f80f09e3b0b0d78af',
170 'e686b958768ee96af8029fe19c6050b1a8dd3b2b'])
166 'e686b958768ee96af8029fe19c6050b1a8dd3b2b'])
171 self.assertTrue(subset.issubset(set(self.repo.revisions)))
167 assert subset.issubset(set(self.repo.revisions))
172
168
173 def test_slicing(self):
169 def test_slicing(self):
174 # 4 1 5 10 95
170 # 4 1 5 10 95
175 for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5),
171 for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5),
176 (10, 20, 10), (5, 100, 95)]:
172 (10, 20, 10), (5, 100, 95)]:
177 revs = list(self.repo[sfrom:sto])
173 revs = list(self.repo[sfrom:sto])
178 self.assertEqual(len(revs), size)
174 assert len(revs) == size
179 self.assertEqual(revs[0], self.repo.get_changeset(sfrom))
175 assert revs[0] == self.repo.get_changeset(sfrom)
180 self.assertEqual(revs[-1], self.repo.get_changeset(sto - 1))
176 assert revs[-1] == self.repo.get_changeset(sto - 1)
181
177
182 def test_branches(self):
178 def test_branches(self):
183 # TODO: Need more tests here
179 # TODO: Need more tests here
184 # Removed (those are 'remotes' branches for cloned repo)
180 # Removed (those are 'remotes' branches for cloned repo)
185 #self.assertTrue('master' in self.repo.branches)
181 #assert 'master' in self.repo.branches
186 #self.assertTrue('gittree' in self.repo.branches)
182 #assert 'gittree' in self.repo.branches
187 #self.assertTrue('web-branch' in self.repo.branches)
183 #assert 'web-branch' in self.repo.branches
188 for name, id in self.repo.branches.items():
184 for name, id in self.repo.branches.items():
189 self.assertTrue(isinstance(
185 assert isinstance(self.repo.get_changeset(id), GitChangeset)
190 self.repo.get_changeset(id), GitChangeset))
191
186
192 def test_tags(self):
187 def test_tags(self):
193 # TODO: Need more tests here
188 # TODO: Need more tests here
194 self.assertTrue('v0.1.1' in self.repo.tags)
189 assert 'v0.1.1' in self.repo.tags
195 self.assertTrue('v0.1.2' in self.repo.tags)
190 assert 'v0.1.2' in self.repo.tags
196 for name, id in self.repo.tags.items():
191 for name, id in self.repo.tags.items():
197 self.assertTrue(isinstance(
192 assert isinstance(self.repo.get_changeset(id), GitChangeset)
198 self.repo.get_changeset(id), GitChangeset))
199
193
200 def _test_single_changeset_cache(self, revision):
194 def _test_single_changeset_cache(self, revision):
201 chset = self.repo.get_changeset(revision)
195 chset = self.repo.get_changeset(revision)
202 self.assertTrue(revision in self.repo.changesets)
196 assert revision in self.repo.changesets
203 self.assertTrue(chset is self.repo.changesets[revision])
197 assert chset is self.repo.changesets[revision]
204
198
205 def test_initial_changeset(self):
199 def test_initial_changeset(self):
206 id = self.repo.revisions[0]
200 id = self.repo.revisions[0]
207 init_chset = self.repo.get_changeset(id)
201 init_chset = self.repo.get_changeset(id)
208 self.assertEqual(init_chset.message, 'initial import\n')
202 assert init_chset.message == 'initial import\n'
209 self.assertEqual(init_chset.author,
203 assert init_chset.author == 'Marcin Kuzminski <marcin@python-blog.com>'
210 'Marcin Kuzminski <marcin@python-blog.com>')
211 for path in ('vcs/__init__.py',
204 for path in ('vcs/__init__.py',
212 'vcs/backends/BaseRepository.py',
205 'vcs/backends/BaseRepository.py',
213 'vcs/backends/__init__.py'):
206 'vcs/backends/__init__.py'):
214 self.assertTrue(isinstance(init_chset.get_node(path), FileNode))
207 assert isinstance(init_chset.get_node(path), FileNode)
215 for path in ('', 'vcs', 'vcs/backends'):
208 for path in ('', 'vcs', 'vcs/backends'):
216 self.assertTrue(isinstance(init_chset.get_node(path), DirNode))
209 assert isinstance(init_chset.get_node(path), DirNode)
217
210
218 self.assertRaises(NodeDoesNotExistError, init_chset.get_node, path='foobar')
211 with pytest.raises(NodeDoesNotExistError):
212 init_chset.get_node(path='foobar')
219
213
220 node = init_chset.get_node('vcs/')
214 node = init_chset.get_node('vcs/')
221 self.assertTrue(hasattr(node, 'kind'))
215 assert hasattr(node, 'kind')
222 self.assertEqual(node.kind, NodeKind.DIR)
216 assert node.kind == NodeKind.DIR
223
217
224 node = init_chset.get_node('vcs')
218 node = init_chset.get_node('vcs')
225 self.assertTrue(hasattr(node, 'kind'))
219 assert hasattr(node, 'kind')
226 self.assertEqual(node.kind, NodeKind.DIR)
220 assert node.kind == NodeKind.DIR
227
221
228 node = init_chset.get_node('vcs/__init__.py')
222 node = init_chset.get_node('vcs/__init__.py')
229 self.assertTrue(hasattr(node, 'kind'))
223 assert hasattr(node, 'kind')
230 self.assertEqual(node.kind, NodeKind.FILE)
224 assert node.kind == NodeKind.FILE
231
225
232 def test_not_existing_changeset(self):
226 def test_not_existing_changeset(self):
233 self.assertRaises(RepositoryError, self.repo.get_changeset,
227 with pytest.raises(RepositoryError):
234 'f' * 40)
228 self.repo.get_changeset('f' * 40)
235
229
236 def test_changeset10(self):
230 def test_changeset10(self):
237
231
238 chset10 = self.repo.get_changeset(self.repo.revisions[9])
232 chset10 = self.repo.get_changeset(self.repo.revisions[9])
239 readme = """===
233 readme = """===
240 VCS
234 VCS
241 ===
235 ===
242
236
243 Various Version Control System management abstraction layer for Python.
237 Various Version Control System management abstraction layer for Python.
244
238
245 Introduction
239 Introduction
246 ------------
240 ------------
247
241
248 TODO: To be written...
242 TODO: To be written...
249
243
250 """
244 """
251 node = chset10.get_node('README.rst')
245 node = chset10.get_node('README.rst')
252 self.assertEqual(node.kind, NodeKind.FILE)
246 assert node.kind == NodeKind.FILE
253 self.assertEqual(node.content, readme)
247 assert node.content == readme
254
248
255
249
256 class GitChangesetTest(unittest.TestCase):
250 class TestGitChangeset(object):
257
251
258 def setUp(self):
252 def setup_method(self):
259 self.repo = GitRepository(TEST_GIT_REPO)
253 self.repo = GitRepository(TEST_GIT_REPO)
260
254
261 def test_default_changeset(self):
255 def test_default_changeset(self):
262 tip = self.repo.get_changeset()
256 tip = self.repo.get_changeset()
263 self.assertEqual(tip, self.repo.get_changeset(None))
257 assert tip == self.repo.get_changeset(None)
264 self.assertEqual(tip, self.repo.get_changeset('tip'))
258 assert tip == self.repo.get_changeset('tip')
265
259
266 def test_root_node(self):
260 def test_root_node(self):
267 tip = self.repo.get_changeset()
261 tip = self.repo.get_changeset()
268 self.assertTrue(tip.root is tip.get_node(''))
262 assert tip.root is tip.get_node('')
269
263
270 def test_lazy_fetch(self):
264 def test_lazy_fetch(self):
271 """
265 """
272 Test if changeset's nodes expands and are cached as we walk through
266 Test if changeset's nodes expands and are cached as we walk through
273 the revision. This test is somewhat hard to write as order of tests
267 the revision. This test is somewhat hard to write as order of tests
274 is a key here. Written by running command after command in a shell.
268 is a key here. Written by running command after command in a shell.
275 """
269 """
276 commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
270 commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
277 self.assertTrue(commit_id in self.repo.revisions)
271 assert commit_id in self.repo.revisions
278 chset = self.repo.get_changeset(commit_id)
272 chset = self.repo.get_changeset(commit_id)
279 self.assertTrue(len(chset.nodes) == 0)
273 assert len(chset.nodes) == 0
280 root = chset.root
274 root = chset.root
281 self.assertTrue(len(chset.nodes) == 1)
275 assert len(chset.nodes) == 1
282 self.assertTrue(len(root.nodes) == 8)
276 assert len(root.nodes) == 8
283 # accessing root.nodes updates chset.nodes
277 # accessing root.nodes updates chset.nodes
284 self.assertTrue(len(chset.nodes) == 9)
278 assert len(chset.nodes) == 9
285
279
286 docs = root.get_node('docs')
280 docs = root.get_node('docs')
287 # we haven't yet accessed anything new as docs dir was already cached
281 # we haven't yet accessed anything new as docs dir was already cached
288 self.assertTrue(len(chset.nodes) == 9)
282 assert len(chset.nodes) == 9
289 self.assertTrue(len(docs.nodes) == 8)
283 assert len(docs.nodes) == 8
290 # accessing docs.nodes updates chset.nodes
284 # accessing docs.nodes updates chset.nodes
291 self.assertTrue(len(chset.nodes) == 17)
285 assert len(chset.nodes) == 17
292
286
293 self.assertTrue(docs is chset.get_node('docs'))
287 assert docs is chset.get_node('docs')
294 self.assertTrue(docs is root.nodes[0])
288 assert docs is root.nodes[0]
295 self.assertTrue(docs is root.dirs[0])
289 assert docs is root.dirs[0]
296 self.assertTrue(docs is chset.get_node('docs'))
290 assert docs is chset.get_node('docs')
297
291
298 def test_nodes_with_changeset(self):
292 def test_nodes_with_changeset(self):
299 commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
293 commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
300 chset = self.repo.get_changeset(commit_id)
294 chset = self.repo.get_changeset(commit_id)
301 root = chset.root
295 root = chset.root
302 docs = root.get_node('docs')
296 docs = root.get_node('docs')
303 self.assertTrue(docs is chset.get_node('docs'))
297 assert docs is chset.get_node('docs')
304 api = docs.get_node('api')
298 api = docs.get_node('api')
305 self.assertTrue(api is chset.get_node('docs/api'))
299 assert api is chset.get_node('docs/api')
306 index = api.get_node('index.rst')
300 index = api.get_node('index.rst')
307 self.assertTrue(index is chset.get_node('docs/api/index.rst'))
301 assert index is chset.get_node('docs/api/index.rst')
308 self.assertTrue(index is chset.get_node('docs') \
302 assert index is chset.get_node('docs') \
309 .get_node('api') \
303 .get_node('api') \
310 .get_node('index.rst'))
304 .get_node('index.rst')
311
305
312 def test_branch_and_tags(self):
306 def test_branch_and_tags(self):
313 """
307 """
314 rev0 = self.repo.revisions[0]
308 rev0 = self.repo.revisions[0]
315 chset0 = self.repo.get_changeset(rev0)
309 chset0 = self.repo.get_changeset(rev0)
316 self.assertEqual(chset0.branch, 'master')
310 assert chset0.branch == 'master'
317 self.assertEqual(chset0.tags, [])
311 assert chset0.tags == []
318
312
319 rev10 = self.repo.revisions[10]
313 rev10 = self.repo.revisions[10]
320 chset10 = self.repo.get_changeset(rev10)
314 chset10 = self.repo.get_changeset(rev10)
321 self.assertEqual(chset10.branch, 'master')
315 assert chset10.branch == 'master'
322 self.assertEqual(chset10.tags, [])
316 assert chset10.tags == []
323
317
324 rev44 = self.repo.revisions[44]
318 rev44 = self.repo.revisions[44]
325 chset44 = self.repo.get_changeset(rev44)
319 chset44 = self.repo.get_changeset(rev44)
326 self.assertEqual(chset44.branch, 'web-branch')
320 assert chset44.branch == 'web-branch'
327
321
328 tip = self.repo.get_changeset('tip')
322 tip = self.repo.get_changeset('tip')
329 self.assertTrue('tip' in tip.tags)
323 assert 'tip' in tip.tags
330 """
324 """
331 # Those tests would fail - branches are now going
325 # Those tests would fail - branches are now going
332 # to be changed at main API in order to support git backend
326 # to be changed at main API in order to support git backend
333 pass
327 pass
334
328
335 def _test_slices(self, limit, offset):
329 def _test_slices(self, limit, offset):
336 count = self.repo.count()
330 count = self.repo.count()
337 changesets = self.repo.get_changesets(limit=limit, offset=offset)
331 changesets = self.repo.get_changesets(limit=limit, offset=offset)
338 idx = 0
332 idx = 0
339 for changeset in changesets:
333 for changeset in changesets:
340 rev = offset + idx
334 rev = offset + idx
341 idx += 1
335 idx += 1
342 rev_id = self.repo.revisions[rev]
336 rev_id = self.repo.revisions[rev]
343 if idx > limit:
337 if idx > limit:
344 pytest.fail("Exceeded limit already (getting revision %s, "
338 pytest.fail("Exceeded limit already (getting revision %s, "
345 "there are %s total revisions, offset=%s, limit=%s)"
339 "there are %s total revisions, offset=%s, limit=%s)"
346 % (rev_id, count, offset, limit))
340 % (rev_id, count, offset, limit))
347 self.assertEqual(changeset, self.repo.get_changeset(rev_id))
341 assert changeset == self.repo.get_changeset(rev_id)
348 result = list(self.repo.get_changesets(limit=limit, offset=offset))
342 result = list(self.repo.get_changesets(limit=limit, offset=offset))
349 start = offset
343 start = offset
350 end = limit and offset + limit or None
344 end = limit and offset + limit or None
351 sliced = list(self.repo[start:end])
345 sliced = list(self.repo[start:end])
352 pytest.failUnlessEqual(result, sliced,
346 pytest.failUnlessEqual(result, sliced,
353 msg="Comparison failed for limit=%s, offset=%s"
347 msg="Comparison failed for limit=%s, offset=%s"
354 "(get_changeset returned: %s and sliced: %s"
348 "(get_changeset returned: %s and sliced: %s"
355 % (limit, offset, result, sliced))
349 % (limit, offset, result, sliced))
356
350
357 def _test_file_size(self, revision, path, size):
351 def _test_file_size(self, revision, path, size):
358 node = self.repo.get_changeset(revision).get_node(path)
352 node = self.repo.get_changeset(revision).get_node(path)
359 self.assertTrue(node.is_file())
353 assert node.is_file()
360 self.assertEqual(node.size, size)
354 assert node.size == size
361
355
362 def test_file_size(self):
356 def test_file_size(self):
363 to_check = (
357 to_check = (
364 ('c1214f7e79e02fc37156ff215cd71275450cffc3',
358 ('c1214f7e79e02fc37156ff215cd71275450cffc3',
365 'vcs/backends/BaseRepository.py', 502),
359 'vcs/backends/BaseRepository.py', 502),
366 ('d7e0d30fbcae12c90680eb095a4f5f02505ce501',
360 ('d7e0d30fbcae12c90680eb095a4f5f02505ce501',
367 'vcs/backends/hg.py', 854),
361 'vcs/backends/hg.py', 854),
368 ('6e125e7c890379446e98980d8ed60fba87d0f6d1',
362 ('6e125e7c890379446e98980d8ed60fba87d0f6d1',
369 'setup.py', 1068),
363 'setup.py', 1068),
370 ('d955cd312c17b02143c04fa1099a352b04368118',
364 ('d955cd312c17b02143c04fa1099a352b04368118',
371 'vcs/backends/base.py', 2921),
365 'vcs/backends/base.py', 2921),
372 ('ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
366 ('ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
373 'vcs/backends/base.py', 3936),
367 'vcs/backends/base.py', 3936),
374 ('f50f42baeed5af6518ef4b0cb2f1423f3851a941',
368 ('f50f42baeed5af6518ef4b0cb2f1423f3851a941',
375 'vcs/backends/base.py', 6189),
369 'vcs/backends/base.py', 6189),
376 )
370 )
377 for revision, path, size in to_check:
371 for revision, path, size in to_check:
378 self._test_file_size(revision, path, size)
372 self._test_file_size(revision, path, size)
379
373
380 def _test_dir_size(self, revision, path, size):
374 def _test_dir_size(self, revision, path, size):
381 node = self.repo.get_changeset(revision).get_node(path)
375 node = self.repo.get_changeset(revision).get_node(path)
382 self.assertEqual(node.size, size)
376 assert node.size == size
383
377
384 def test_dir_size(self):
378 def test_dir_size(self):
385 to_check = (
379 to_check = (
386 ('5f2c6ee195929b0be80749243c18121c9864a3b3', '/', 674076),
380 ('5f2c6ee195929b0be80749243c18121c9864a3b3', '/', 674076),
387 ('7ab37bc680b4aa72c34d07b230c866c28e9fc204', '/', 674049),
381 ('7ab37bc680b4aa72c34d07b230c866c28e9fc204', '/', 674049),
388 ('6892503fb8f2a552cef5f4d4cc2cdbd13ae1cd2f', '/', 671830),
382 ('6892503fb8f2a552cef5f4d4cc2cdbd13ae1cd2f', '/', 671830),
389 )
383 )
390 for revision, path, size in to_check:
384 for revision, path, size in to_check:
391 self._test_dir_size(revision, path, size)
385 self._test_dir_size(revision, path, size)
392
386
393 def test_repo_size(self):
387 def test_repo_size(self):
394 self.assertEqual(self.repo.size, 674076)
388 assert self.repo.size == 674076
395
389
396 def test_file_history(self):
390 def test_file_history(self):
397 # we can only check if those revisions are present in the history
391 # we can only check if those revisions are present in the history
398 # as we cannot update this test every time file is changed
392 # as we cannot update this test every time file is changed
399 files = {
393 files = {
400 'setup.py': [
394 'setup.py': [
401 '54386793436c938cff89326944d4c2702340037d',
395 '54386793436c938cff89326944d4c2702340037d',
402 '51d254f0ecf5df2ce50c0b115741f4cf13985dab',
396 '51d254f0ecf5df2ce50c0b115741f4cf13985dab',
403 '998ed409c795fec2012b1c0ca054d99888b22090',
397 '998ed409c795fec2012b1c0ca054d99888b22090',
404 '5e0eb4c47f56564395f76333f319d26c79e2fb09',
398 '5e0eb4c47f56564395f76333f319d26c79e2fb09',
405 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
399 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
406 '7cb3fd1b6d8c20ba89e2264f1c8baebc8a52d36e',
400 '7cb3fd1b6d8c20ba89e2264f1c8baebc8a52d36e',
407 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
401 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
408 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
402 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
409 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
403 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
410 ],
404 ],
411 'vcs/nodes.py': [
405 'vcs/nodes.py': [
412 '33fa3223355104431402a888fa77a4e9956feb3e',
406 '33fa3223355104431402a888fa77a4e9956feb3e',
413 'fa014c12c26d10ba682fadb78f2a11c24c8118e1',
407 'fa014c12c26d10ba682fadb78f2a11c24c8118e1',
414 'e686b958768ee96af8029fe19c6050b1a8dd3b2b',
408 'e686b958768ee96af8029fe19c6050b1a8dd3b2b',
415 'ab5721ca0a081f26bf43d9051e615af2cc99952f',
409 'ab5721ca0a081f26bf43d9051e615af2cc99952f',
416 'c877b68d18e792a66b7f4c529ea02c8f80801542',
410 'c877b68d18e792a66b7f4c529ea02c8f80801542',
417 '4313566d2e417cb382948f8d9d7c765330356054',
411 '4313566d2e417cb382948f8d9d7c765330356054',
418 '6c2303a793671e807d1cfc70134c9ca0767d98c2',
412 '6c2303a793671e807d1cfc70134c9ca0767d98c2',
419 '54386793436c938cff89326944d4c2702340037d',
413 '54386793436c938cff89326944d4c2702340037d',
420 '54000345d2e78b03a99d561399e8e548de3f3203',
414 '54000345d2e78b03a99d561399e8e548de3f3203',
421 '1c6b3677b37ea064cb4b51714d8f7498f93f4b2b',
415 '1c6b3677b37ea064cb4b51714d8f7498f93f4b2b',
422 '2d03ca750a44440fb5ea8b751176d1f36f8e8f46',
416 '2d03ca750a44440fb5ea8b751176d1f36f8e8f46',
423 '2a08b128c206db48c2f0b8f70df060e6db0ae4f8',
417 '2a08b128c206db48c2f0b8f70df060e6db0ae4f8',
424 '30c26513ff1eb8e5ce0e1c6b477ee5dc50e2f34b',
418 '30c26513ff1eb8e5ce0e1c6b477ee5dc50e2f34b',
425 'ac71e9503c2ca95542839af0ce7b64011b72ea7c',
419 'ac71e9503c2ca95542839af0ce7b64011b72ea7c',
426 '12669288fd13adba2a9b7dd5b870cc23ffab92d2',
420 '12669288fd13adba2a9b7dd5b870cc23ffab92d2',
427 '5a0c84f3e6fe3473e4c8427199d5a6fc71a9b382',
421 '5a0c84f3e6fe3473e4c8427199d5a6fc71a9b382',
428 '12f2f5e2b38e6ff3fbdb5d722efed9aa72ecb0d5',
422 '12f2f5e2b38e6ff3fbdb5d722efed9aa72ecb0d5',
429 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
423 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
430 'f50f42baeed5af6518ef4b0cb2f1423f3851a941',
424 'f50f42baeed5af6518ef4b0cb2f1423f3851a941',
431 'd7e390a45f6aa96f04f5e7f583ad4f867431aa25',
425 'd7e390a45f6aa96f04f5e7f583ad4f867431aa25',
432 'f15c21f97864b4f071cddfbf2750ec2e23859414',
426 'f15c21f97864b4f071cddfbf2750ec2e23859414',
433 'e906ef056cf539a4e4e5fc8003eaf7cf14dd8ade',
427 'e906ef056cf539a4e4e5fc8003eaf7cf14dd8ade',
434 'ea2b108b48aa8f8c9c4a941f66c1a03315ca1c3b',
428 'ea2b108b48aa8f8c9c4a941f66c1a03315ca1c3b',
435 '84dec09632a4458f79f50ddbbd155506c460b4f9',
429 '84dec09632a4458f79f50ddbbd155506c460b4f9',
436 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
430 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
437 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
431 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
438 '3bf1c5868e570e39569d094f922d33ced2fa3b2b',
432 '3bf1c5868e570e39569d094f922d33ced2fa3b2b',
439 'b8d04012574729d2c29886e53b1a43ef16dd00a1',
433 'b8d04012574729d2c29886e53b1a43ef16dd00a1',
440 '6970b057cffe4aab0a792aa634c89f4bebf01441',
434 '6970b057cffe4aab0a792aa634c89f4bebf01441',
441 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
435 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
442 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
436 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
443 ],
437 ],
444 'vcs/backends/git.py': [
438 'vcs/backends/git.py': [
445 '4cf116ad5a457530381135e2f4c453e68a1b0105',
439 '4cf116ad5a457530381135e2f4c453e68a1b0105',
446 '9a751d84d8e9408e736329767387f41b36935153',
440 '9a751d84d8e9408e736329767387f41b36935153',
447 'cb681fb539c3faaedbcdf5ca71ca413425c18f01',
441 'cb681fb539c3faaedbcdf5ca71ca413425c18f01',
448 '428f81bb652bcba8d631bce926e8834ff49bdcc6',
442 '428f81bb652bcba8d631bce926e8834ff49bdcc6',
449 '180ab15aebf26f98f714d8c68715e0f05fa6e1c7',
443 '180ab15aebf26f98f714d8c68715e0f05fa6e1c7',
450 '2b8e07312a2e89e92b90426ab97f349f4bce2a3a',
444 '2b8e07312a2e89e92b90426ab97f349f4bce2a3a',
451 '50e08c506174d8645a4bb517dd122ac946a0f3bf',
445 '50e08c506174d8645a4bb517dd122ac946a0f3bf',
452 '54000345d2e78b03a99d561399e8e548de3f3203',
446 '54000345d2e78b03a99d561399e8e548de3f3203',
453 ],
447 ],
454 }
448 }
455 for path, revs in files.items():
449 for path, revs in files.items():
456 node = self.repo.get_changeset(revs[0]).get_node(path)
450 node = self.repo.get_changeset(revs[0]).get_node(path)
457 node_revs = [chset.raw_id for chset in node.history]
451 node_revs = [chset.raw_id for chset in node.history]
458 self.assertTrue(set(revs).issubset(set(node_revs)),
452 assert set(revs).issubset(set(node_revs)), "We assumed that %s is subset of revisions for which file %s " \
459 "We assumed that %s is subset of revisions for which file %s "
453 "has been changed, and history of that node returned: %s" \
460 "has been changed, and history of that node returned: %s"
454 % (revs, path, node_revs)
461 % (revs, path, node_revs))
462
455
463 def test_file_annotate(self):
456 def test_file_annotate(self):
464 files = {
457 files = {
465 'vcs/backends/__init__.py': {
458 'vcs/backends/__init__.py': {
466 'c1214f7e79e02fc37156ff215cd71275450cffc3': {
459 'c1214f7e79e02fc37156ff215cd71275450cffc3': {
467 'lines_no': 1,
460 'lines_no': 1,
468 'changesets': [
461 'changesets': [
469 'c1214f7e79e02fc37156ff215cd71275450cffc3',
462 'c1214f7e79e02fc37156ff215cd71275450cffc3',
470 ],
463 ],
471 },
464 },
472 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647': {
465 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647': {
473 'lines_no': 21,
466 'lines_no': 21,
474 'changesets': [
467 'changesets': [
475 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
468 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
476 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
469 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
477 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
470 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
478 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
471 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
479 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
472 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
480 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
473 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
481 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
474 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
482 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
475 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
483 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
476 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
484 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
477 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
485 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
478 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
486 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
479 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
487 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
480 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
488 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
481 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
489 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
482 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
490 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
483 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
491 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
484 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
492 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
485 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
493 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
486 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
494 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
487 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
495 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
488 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
496 ],
489 ],
497 },
490 },
498 'e29b67bd158580fc90fc5e9111240b90e6e86064': {
491 'e29b67bd158580fc90fc5e9111240b90e6e86064': {
499 'lines_no': 32,
492 'lines_no': 32,
500 'changesets': [
493 'changesets': [
501 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
494 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
502 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
495 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
503 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
496 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
504 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
497 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
505 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
498 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
506 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
499 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
507 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
500 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
508 '54000345d2e78b03a99d561399e8e548de3f3203',
501 '54000345d2e78b03a99d561399e8e548de3f3203',
509 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
502 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
510 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
503 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
511 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
504 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
512 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
505 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
513 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
506 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
514 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
507 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
515 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
508 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
516 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
509 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
517 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
510 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
518 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
511 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
519 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
512 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
520 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
513 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
521 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
514 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
522 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
515 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
523 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
516 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
524 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
517 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
525 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
518 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
526 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
519 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
527 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
520 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
528 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
521 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
529 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
522 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
530 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
523 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
531 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
524 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
532 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
525 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
533 ],
526 ],
534 },
527 },
535 },
528 },
536 }
529 }
537
530
538 for fname, revision_dict in files.items():
531 for fname, revision_dict in files.items():
539 for rev, data in revision_dict.items():
532 for rev, data in revision_dict.items():
540 cs = self.repo.get_changeset(rev)
533 cs = self.repo.get_changeset(rev)
541
534
542 l1_1 = [x[1] for x in cs.get_file_annotate(fname)]
535 l1_1 = [x[1] for x in cs.get_file_annotate(fname)]
543 l1_2 = [x[2]().raw_id for x in cs.get_file_annotate(fname)]
536 l1_2 = [x[2]().raw_id for x in cs.get_file_annotate(fname)]
544 self.assertEqual(l1_1, l1_2)
537 assert l1_1 == l1_2
545 l1 = l1_1
538 l1 = l1_1
546 l2 = files[fname][rev]['changesets']
539 l2 = files[fname][rev]['changesets']
547 self.assertTrue(l1 == l2, "The lists of revision for %s@rev %s"
540 assert l1 == l2, "The lists of revision for %s@rev %s" \
548 "from annotation list should match each other, "
541 "from annotation list should match each other, " \
549 "got \n%s \nvs \n%s " % (fname, rev, l1, l2))
542 "got \n%s \nvs \n%s " % (fname, rev, l1, l2)
550
543
551 def test_files_state(self):
544 def test_files_state(self):
552 """
545 """
553 Tests state of FileNodes.
546 Tests state of FileNodes.
554 """
547 """
555 node = self.repo \
548 node = self.repo \
556 .get_changeset('e6ea6d16e2f26250124a1f4b4fe37a912f9d86a0') \
549 .get_changeset('e6ea6d16e2f26250124a1f4b4fe37a912f9d86a0') \
557 .get_node('vcs/utils/diffs.py')
550 .get_node('vcs/utils/diffs.py')
558 self.assertTrue(node.state, NodeState.ADDED)
551 assert node.state, NodeState.ADDED
559 self.assertTrue(node.added)
552 assert node.added
560 self.assertFalse(node.changed)
553 assert not node.changed
561 self.assertFalse(node.not_changed)
554 assert not node.not_changed
562 self.assertFalse(node.removed)
555 assert not node.removed
563
556
564 node = self.repo \
557 node = self.repo \
565 .get_changeset('33fa3223355104431402a888fa77a4e9956feb3e') \
558 .get_changeset('33fa3223355104431402a888fa77a4e9956feb3e') \
566 .get_node('.hgignore')
559 .get_node('.hgignore')
567 self.assertTrue(node.state, NodeState.CHANGED)
560 assert node.state, NodeState.CHANGED
568 self.assertFalse(node.added)
561 assert not node.added
569 self.assertTrue(node.changed)
562 assert node.changed
570 self.assertFalse(node.not_changed)
563 assert not node.not_changed
571 self.assertFalse(node.removed)
564 assert not node.removed
572
565
573 node = self.repo \
566 node = self.repo \
574 .get_changeset('e29b67bd158580fc90fc5e9111240b90e6e86064') \
567 .get_changeset('e29b67bd158580fc90fc5e9111240b90e6e86064') \
575 .get_node('setup.py')
568 .get_node('setup.py')
576 self.assertTrue(node.state, NodeState.NOT_CHANGED)
569 assert node.state, NodeState.NOT_CHANGED
577 self.assertFalse(node.added)
570 assert not node.added
578 self.assertFalse(node.changed)
571 assert not node.changed
579 self.assertTrue(node.not_changed)
572 assert node.not_changed
580 self.assertFalse(node.removed)
573 assert not node.removed
581
574
582 # If node has REMOVED state then trying to fetch it would raise
575 # If node has REMOVED state then trying to fetch it would raise
583 # ChangesetError exception
576 # ChangesetError exception
584 chset = self.repo.get_changeset(
577 chset = self.repo.get_changeset(
585 'fa6600f6848800641328adbf7811fd2372c02ab2')
578 'fa6600f6848800641328adbf7811fd2372c02ab2')
586 path = 'vcs/backends/BaseRepository.py'
579 path = 'vcs/backends/BaseRepository.py'
587 self.assertRaises(NodeDoesNotExistError, chset.get_node, path)
580 with pytest.raises(NodeDoesNotExistError):
581 chset.get_node(path)
588 # but it would be one of ``removed`` (changeset's attribute)
582 # but it would be one of ``removed`` (changeset's attribute)
589 self.assertTrue(path in [rf.path for rf in chset.removed])
583 assert path in [rf.path for rf in chset.removed]
590
584
591 chset = self.repo.get_changeset(
585 chset = self.repo.get_changeset(
592 '54386793436c938cff89326944d4c2702340037d')
586 '54386793436c938cff89326944d4c2702340037d')
593 changed = ['setup.py', 'tests/test_nodes.py', 'vcs/backends/hg.py',
587 changed = ['setup.py', 'tests/test_nodes.py', 'vcs/backends/hg.py',
594 'vcs/nodes.py']
588 'vcs/nodes.py']
595 self.assertEqual(set(changed), set([f.path for f in chset.changed]))
589 assert set(changed) == set([f.path for f in chset.changed])
596
590
597 def test_commit_message_is_unicode(self):
591 def test_commit_message_is_unicode(self):
598 for cs in self.repo:
592 for cs in self.repo:
599 self.assertEqual(type(cs.message), unicode)
593 assert type(cs.message) == unicode
600
594
601 def test_changeset_author_is_unicode(self):
595 def test_changeset_author_is_unicode(self):
602 for cs in self.repo:
596 for cs in self.repo:
603 self.assertEqual(type(cs.author), unicode)
597 assert type(cs.author) == unicode
604
598
605 def test_repo_files_content_is_unicode(self):
599 def test_repo_files_content_is_unicode(self):
606 changeset = self.repo.get_changeset()
600 changeset = self.repo.get_changeset()
607 for node in changeset.get_node('/'):
601 for node in changeset.get_node('/'):
608 if node.is_file():
602 if node.is_file():
609 self.assertEqual(type(node.content), unicode)
603 assert type(node.content) == unicode
610
604
611 def test_wrong_path(self):
605 def test_wrong_path(self):
612 # There is 'setup.py' in the root dir but not there:
606 # There is 'setup.py' in the root dir but not there:
613 path = 'foo/bar/setup.py'
607 path = 'foo/bar/setup.py'
614 tip = self.repo.get_changeset()
608 tip = self.repo.get_changeset()
615 self.assertRaises(VCSError, tip.get_node, path)
609 with pytest.raises(VCSError):
610 tip.get_node(path)
616
611
617 def test_author_email(self):
612 def test_author_email(self):
618 self.assertEqual('marcin@python-blog.com',
613 assert 'marcin@python-blog.com' == self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3').author_email
619 self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3') \
614 assert 'lukasz.balcerzak@python-center.pl' == self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b').author_email
620 .author_email)
615 assert '' == self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992').author_email
621 self.assertEqual('lukasz.balcerzak@python-center.pl',
622 self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b') \
623 .author_email)
624 self.assertEqual('',
625 self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992') \
626 .author_email)
627
616
628 def test_author_username(self):
617 def test_author_username(self):
629 self.assertEqual('Marcin Kuzminski',
618 assert 'Marcin Kuzminski' == self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3').author_name
630 self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3') \
619 assert 'Lukasz Balcerzak' == self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b').author_name
631 .author_name)
620 assert 'marcink none@none' == self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992').author_name
632 self.assertEqual('Lukasz Balcerzak',
633 self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b') \
634 .author_name)
635 self.assertEqual('marcink none@none',
636 self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992') \
637 .author_name)
638
621
639
622
640 class GitSpecificTest(unittest.TestCase):
623 class TestGitSpecific():
641
624
642 def test_error_is_raised_for_added_if_diff_name_status_is_wrong(self):
625 def test_error_is_raised_for_added_if_diff_name_status_is_wrong(self):
643 repo = mock.MagicMock()
626 repo = mock.MagicMock()
644 changeset = GitChangeset(repo, 'foobar')
627 changeset = GitChangeset(repo, 'foobar')
645 changeset._diff_name_status = 'foobar'
628 changeset._diff_name_status = 'foobar'
646 with self.assertRaises(VCSError):
629 with pytest.raises(VCSError):
647 changeset.added
630 changeset.added
648
631
649 def test_error_is_raised_for_changed_if_diff_name_status_is_wrong(self):
632 def test_error_is_raised_for_changed_if_diff_name_status_is_wrong(self):
650 repo = mock.MagicMock()
633 repo = mock.MagicMock()
651 changeset = GitChangeset(repo, 'foobar')
634 changeset = GitChangeset(repo, 'foobar')
652 changeset._diff_name_status = 'foobar'
635 changeset._diff_name_status = 'foobar'
653 with self.assertRaises(VCSError):
636 with pytest.raises(VCSError):
654 changeset.added
637 changeset.added
655
638
656 def test_error_is_raised_for_removed_if_diff_name_status_is_wrong(self):
639 def test_error_is_raised_for_removed_if_diff_name_status_is_wrong(self):
657 repo = mock.MagicMock()
640 repo = mock.MagicMock()
658 changeset = GitChangeset(repo, 'foobar')
641 changeset = GitChangeset(repo, 'foobar')
659 changeset._diff_name_status = 'foobar'
642 changeset._diff_name_status = 'foobar'
660 with self.assertRaises(VCSError):
643 with pytest.raises(VCSError):
661 changeset.added
644 changeset.added
662
645
663
646
664 class GitSpecificWithRepoTest(_BackendTestMixin, unittest.TestCase):
647 class TestGitSpecificWithRepo(_BackendTestMixin):
665 backend_alias = 'git'
648 backend_alias = 'git'
666
649
667 @classmethod
650 @classmethod
668 def _get_commits(cls):
651 def _get_commits(cls):
669 return [
652 return [
670 {
653 {
671 'message': 'Initial',
654 'message': 'Initial',
672 'author': 'Joe Doe <joe.doe@example.com>',
655 'author': 'Joe Doe <joe.doe@example.com>',
673 'date': datetime.datetime(2010, 1, 1, 20),
656 'date': datetime.datetime(2010, 1, 1, 20),
674 'added': [
657 'added': [
675 FileNode('foobar/static/js/admin/base.js', content='base'),
658 FileNode('foobar/static/js/admin/base.js', content='base'),
676 FileNode('foobar/static/admin', content='admin',
659 FileNode('foobar/static/admin', content='admin',
677 mode=0120000), # this is a link
660 mode=0120000), # this is a link
678 FileNode('foo', content='foo'),
661 FileNode('foo', content='foo'),
679 ],
662 ],
680 },
663 },
681 {
664 {
682 'message': 'Second',
665 'message': 'Second',
683 'author': 'Joe Doe <joe.doe@example.com>',
666 'author': 'Joe Doe <joe.doe@example.com>',
684 'date': datetime.datetime(2010, 1, 1, 22),
667 'date': datetime.datetime(2010, 1, 1, 22),
685 'added': [
668 'added': [
686 FileNode('foo2', content='foo2'),
669 FileNode('foo2', content='foo2'),
687 ],
670 ],
688 },
671 },
689 ]
672 ]
690
673
691 def test_paths_slow_traversing(self):
674 def test_paths_slow_traversing(self):
692 cs = self.repo.get_changeset()
675 cs = self.repo.get_changeset()
693 self.assertEqual(cs.get_node('foobar').get_node('static').get_node('js')
676 assert cs.get_node('foobar').get_node('static').get_node('js').get_node('admin').get_node('base.js').content == 'base'
694 .get_node('admin').get_node('base.js').content, 'base')
695
677
696 def test_paths_fast_traversing(self):
678 def test_paths_fast_traversing(self):
697 cs = self.repo.get_changeset()
679 cs = self.repo.get_changeset()
698 self.assertEqual(cs.get_node('foobar/static/js/admin/base.js').content,
680 assert cs.get_node('foobar/static/js/admin/base.js').content == 'base'
699 'base')
700
681
701 def test_workdir_get_branch(self):
682 def test_workdir_get_branch(self):
702 self.repo.run_git_command(['checkout', '-b', 'production'])
683 self.repo.run_git_command(['checkout', '-b', 'production'])
703 # Regression test: one of following would fail if we don't check
684 # Regression test: one of following would fail if we don't check
704 # .git/HEAD file
685 # .git/HEAD file
705 self.repo.run_git_command(['checkout', 'production'])
686 self.repo.run_git_command(['checkout', 'production'])
706 self.assertEqual(self.repo.workdir.get_branch(), 'production')
687 assert self.repo.workdir.get_branch() == 'production'
707 self.repo.run_git_command(['checkout', 'master'])
688 self.repo.run_git_command(['checkout', 'master'])
708 self.assertEqual(self.repo.workdir.get_branch(), 'master')
689 assert self.repo.workdir.get_branch() == 'master'
709
690
710 def test_get_diff_runs_git_command_with_hashes(self):
691 def test_get_diff_runs_git_command_with_hashes(self):
711 self.repo.run_git_command = mock.Mock(return_value=['', ''])
692 self.repo.run_git_command = mock.Mock(return_value=['', ''])
712 self.repo.get_diff(0, 1)
693 self.repo.get_diff(0, 1)
713 self.repo.run_git_command.assert_called_once_with(
694 self.repo.run_git_command.assert_called_once_with(
714 ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
695 ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
715 self.repo._get_revision(0), self.repo._get_revision(1)])
696 self.repo._get_revision(0), self.repo._get_revision(1)])
716
697
717 def test_get_diff_runs_git_command_with_str_hashes(self):
698 def test_get_diff_runs_git_command_with_str_hashes(self):
718 self.repo.run_git_command = mock.Mock(return_value=['', ''])
699 self.repo.run_git_command = mock.Mock(return_value=['', ''])
719 self.repo.get_diff(self.repo.EMPTY_CHANGESET, 1)
700 self.repo.get_diff(self.repo.EMPTY_CHANGESET, 1)
720 self.repo.run_git_command.assert_called_once_with(
701 self.repo.run_git_command.assert_called_once_with(
721 ['show', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
702 ['show', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
722 self.repo._get_revision(1)])
703 self.repo._get_revision(1)])
723
704
724 def test_get_diff_runs_git_command_with_path_if_its_given(self):
705 def test_get_diff_runs_git_command_with_path_if_its_given(self):
725 self.repo.run_git_command = mock.Mock(return_value=['', ''])
706 self.repo.run_git_command = mock.Mock(return_value=['', ''])
726 self.repo.get_diff(0, 1, 'foo')
707 self.repo.get_diff(0, 1, 'foo')
727 self.repo.run_git_command.assert_called_once_with(
708 self.repo.run_git_command.assert_called_once_with(
728 ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
709 ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40',
729 self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'])
710 self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'])
730
711
731
712
732 class GitRegressionTest(_BackendTestMixin, unittest.TestCase):
713 class TestGitRegression(_BackendTestMixin):
733 backend_alias = 'git'
714 backend_alias = 'git'
734
715
735 @classmethod
716 @classmethod
736 def _get_commits(cls):
717 def _get_commits(cls):
737 return [
718 return [
738 {
719 {
739 'message': 'Initial',
720 'message': 'Initial',
740 'author': 'Joe Doe <joe.doe@example.com>',
721 'author': 'Joe Doe <joe.doe@example.com>',
741 'date': datetime.datetime(2010, 1, 1, 20),
722 'date': datetime.datetime(2010, 1, 1, 20),
742 'added': [
723 'added': [
743 FileNode('bot/__init__.py', content='base'),
724 FileNode('bot/__init__.py', content='base'),
744 FileNode('bot/templates/404.html', content='base'),
725 FileNode('bot/templates/404.html', content='base'),
745 FileNode('bot/templates/500.html', content='base'),
726 FileNode('bot/templates/500.html', content='base'),
746 ],
727 ],
747 },
728 },
748 {
729 {
749 'message': 'Second',
730 'message': 'Second',
750 'author': 'Joe Doe <joe.doe@example.com>',
731 'author': 'Joe Doe <joe.doe@example.com>',
751 'date': datetime.datetime(2010, 1, 1, 22),
732 'date': datetime.datetime(2010, 1, 1, 22),
752 'added': [
733 'added': [
753 FileNode('bot/build/migrations/1.py', content='foo2'),
734 FileNode('bot/build/migrations/1.py', content='foo2'),
754 FileNode('bot/build/migrations/2.py', content='foo2'),
735 FileNode('bot/build/migrations/2.py', content='foo2'),
755 FileNode('bot/build/static/templates/f.html', content='foo2'),
736 FileNode('bot/build/static/templates/f.html', content='foo2'),
756 FileNode('bot/build/static/templates/f1.html', content='foo2'),
737 FileNode('bot/build/static/templates/f1.html', content='foo2'),
757 FileNode('bot/build/templates/err.html', content='foo2'),
738 FileNode('bot/build/templates/err.html', content='foo2'),
758 FileNode('bot/build/templates/err2.html', content='foo2'),
739 FileNode('bot/build/templates/err2.html', content='foo2'),
759 ],
740 ],
760 },
741 },
761 ]
742 ]
762
743
763 def test_similar_paths(self):
744 def test_similar_paths(self):
764 cs = self.repo.get_changeset()
745 cs = self.repo.get_changeset()
765 paths = lambda *n: [x.path for x in n]
746 paths = lambda *n: [x.path for x in n]
766 self.assertEqual(paths(*cs.get_nodes('bot')), ['bot/build', 'bot/templates', 'bot/__init__.py'])
747 assert paths(*cs.get_nodes('bot')) == ['bot/build', 'bot/templates', 'bot/__init__.py']
767 self.assertEqual(paths(*cs.get_nodes('bot/build')), ['bot/build/migrations', 'bot/build/static', 'bot/build/templates'])
748 assert paths(*cs.get_nodes('bot/build')) == ['bot/build/migrations', 'bot/build/static', 'bot/build/templates']
768 self.assertEqual(paths(*cs.get_nodes('bot/build/static')), ['bot/build/static/templates'])
749 assert paths(*cs.get_nodes('bot/build/static')) == ['bot/build/static/templates']
769 # this get_nodes below causes troubles !
750 # this get_nodes below causes troubles !
770 self.assertEqual(paths(*cs.get_nodes('bot/build/static/templates')), ['bot/build/static/templates/f.html', 'bot/build/static/templates/f1.html'])
751 assert paths(*cs.get_nodes('bot/build/static/templates')) == ['bot/build/static/templates/f.html', 'bot/build/static/templates/f1.html']
771 self.assertEqual(paths(*cs.get_nodes('bot/build/templates')), ['bot/build/templates/err.html', 'bot/build/templates/err2.html'])
752 assert paths(*cs.get_nodes('bot/build/templates')) == ['bot/build/templates/err.html', 'bot/build/templates/err2.html']
772 self.assertEqual(paths(*cs.get_nodes('bot/templates/')), ['bot/templates/404.html', 'bot/templates/500.html'])
753 assert paths(*cs.get_nodes('bot/templates/')) == ['bot/templates/404.html', 'bot/templates/500.html']
773
754
774
755
775 class GitHooksTest(unittest.TestCase):
756 class TestGitHooks(object):
776 """
757 """
777 Tests related to hook functionality of Git repositories.
758 Tests related to hook functionality of Git repositories.
778 """
759 """
779
760
780 def setUp(self):
761 def setup_method(self):
781 # For each run we want a fresh repo.
762 # For each run we want a fresh repo.
782 self.repo_directory = get_new_dir("githookrepo")
763 self.repo_directory = get_new_dir("githookrepo")
783 self.repo = GitRepository(self.repo_directory, create=True)
764 self.repo = GitRepository(self.repo_directory, create=True)
784
765
785 # Create a dictionary where keys are hook names, and values are paths to
766 # Create a dictionary where keys are hook names, and values are paths to
786 # them. Deduplicates code in tests a bit.
767 # them. Deduplicates code in tests a bit.
787 self.hook_directory = self.repo.get_hook_location()
768 self.hook_directory = self.repo.get_hook_location()
788 self.kallithea_hooks = dict((h, os.path.join(self.hook_directory, h)) for h in ("pre-receive", "post-receive"))
769 self.kallithea_hooks = dict((h, os.path.join(self.hook_directory, h)) for h in ("pre-receive", "post-receive"))
789
770
790 def test_hooks_created_if_missing(self):
771 def test_hooks_created_if_missing(self):
791 """
772 """
792 Tests if hooks are installed in repository if they are missing.
773 Tests if hooks are installed in repository if they are missing.
793 """
774 """
794
775
795 for hook, hook_path in self.kallithea_hooks.iteritems():
776 for hook, hook_path in self.kallithea_hooks.iteritems():
796 if os.path.exists(hook_path):
777 if os.path.exists(hook_path):
797 os.remove(hook_path)
778 os.remove(hook_path)
798
779
799 ScmModel().install_git_hooks(repo=self.repo)
780 ScmModel().install_git_hooks(repo=self.repo)
800
781
801 for hook, hook_path in self.kallithea_hooks.iteritems():
782 for hook, hook_path in self.kallithea_hooks.iteritems():
802 self.assertTrue(os.path.exists(hook_path))
783 assert os.path.exists(hook_path)
803
784
804 def test_kallithea_hooks_updated(self):
785 def test_kallithea_hooks_updated(self):
805 """
786 """
806 Tests if hooks are updated if they are Kallithea hooks already.
787 Tests if hooks are updated if they are Kallithea hooks already.
807 """
788 """
808
789
809 for hook, hook_path in self.kallithea_hooks.iteritems():
790 for hook, hook_path in self.kallithea_hooks.iteritems():
810 with open(hook_path, "w") as f:
791 with open(hook_path, "w") as f:
811 f.write("KALLITHEA_HOOK_VER=0.0.0\nJUST_BOGUS")
792 f.write("KALLITHEA_HOOK_VER=0.0.0\nJUST_BOGUS")
812
793
813 ScmModel().install_git_hooks(repo=self.repo)
794 ScmModel().install_git_hooks(repo=self.repo)
814
795
815 for hook, hook_path in self.kallithea_hooks.iteritems():
796 for hook, hook_path in self.kallithea_hooks.iteritems():
816 with open(hook_path) as f:
797 with open(hook_path) as f:
817 self.assertNotIn("JUST_BOGUS", f.read())
798 assert "JUST_BOGUS" not in f.read()
818
799
819 def test_custom_hooks_untouched(self):
800 def test_custom_hooks_untouched(self):
820 """
801 """
821 Tests if hooks are left untouched if they are not Kallithea hooks.
802 Tests if hooks are left untouched if they are not Kallithea hooks.
822 """
803 """
823
804
824 for hook, hook_path in self.kallithea_hooks.iteritems():
805 for hook, hook_path in self.kallithea_hooks.iteritems():
825 with open(hook_path, "w") as f:
806 with open(hook_path, "w") as f:
826 f.write("#!/bin/bash\n#CUSTOM_HOOK")
807 f.write("#!/bin/bash\n#CUSTOM_HOOK")
827
808
828 ScmModel().install_git_hooks(repo=self.repo)
809 ScmModel().install_git_hooks(repo=self.repo)
829
810
830 for hook, hook_path in self.kallithea_hooks.iteritems():
811 for hook, hook_path in self.kallithea_hooks.iteritems():
831 with open(hook_path) as f:
812 with open(hook_path) as f:
832 self.assertIn("CUSTOM_HOOK", f.read())
813 assert "CUSTOM_HOOK" in f.read()
833
814
834 def test_custom_hooks_forced_update(self):
815 def test_custom_hooks_forced_update(self):
835 """
816 """
836 Tests if hooks are forcefully updated even though they are custom hooks.
817 Tests if hooks are forcefully updated even though they are custom hooks.
837 """
818 """
838
819
839 for hook, hook_path in self.kallithea_hooks.iteritems():
820 for hook, hook_path in self.kallithea_hooks.iteritems():
840 with open(hook_path, "w") as f:
821 with open(hook_path, "w") as f:
841 f.write("#!/bin/bash\n#CUSTOM_HOOK")
822 f.write("#!/bin/bash\n#CUSTOM_HOOK")
842
823
843 ScmModel().install_git_hooks(repo=self.repo, force_create=True)
824 ScmModel().install_git_hooks(repo=self.repo, force_create=True)
844
825
845 for hook, hook_path in self.kallithea_hooks.iteritems():
826 for hook, hook_path in self.kallithea_hooks.iteritems():
846 with open(hook_path) as f:
827 with open(hook_path) as f:
847 self.assertIn("KALLITHEA_HOOK_VER", f.read())
828 assert "KALLITHEA_HOOK_VER" in f.read()
@@ -1,95 +1,93 b''
1 import datetime
1 import datetime
2
2
3 from kallithea.lib.vcs.utils.compat import unittest
3 import pytest
4
4
5 from kallithea.lib.vcs.nodes import FileNode
5 from kallithea.lib.vcs.nodes import FileNode
6
6
7 from kallithea.tests.vcs.base import _BackendTestMixin
7 from kallithea.tests.vcs.base import _BackendTestMixin
8 from kallithea.tests.vcs.conf import SCM_TESTS
8 from kallithea.tests.vcs.conf import SCM_TESTS
9
9
10
10
11 class WorkdirTestCaseMixin(_BackendTestMixin):
11 class WorkdirTestCaseMixin(_BackendTestMixin):
12
12
13 @classmethod
13 @classmethod
14 def _get_commits(cls):
14 def _get_commits(cls):
15 commits = [
15 commits = [
16 {
16 {
17 'message': u'Initial commit',
17 'message': u'Initial commit',
18 'author': u'Joe Doe <joe.doe@example.com>',
18 'author': u'Joe Doe <joe.doe@example.com>',
19 'date': datetime.datetime(2010, 1, 1, 20),
19 'date': datetime.datetime(2010, 1, 1, 20),
20 'added': [
20 'added': [
21 FileNode('foobar', content='Foobar'),
21 FileNode('foobar', content='Foobar'),
22 FileNode('foobar2', content='Foobar II'),
22 FileNode('foobar2', content='Foobar II'),
23 FileNode('foo/bar/baz', content='baz here!'),
23 FileNode('foo/bar/baz', content='baz here!'),
24 ],
24 ],
25 },
25 },
26 {
26 {
27 'message': u'Changes...',
27 'message': u'Changes...',
28 'author': u'Jane Doe <jane.doe@example.com>',
28 'author': u'Jane Doe <jane.doe@example.com>',
29 'date': datetime.datetime(2010, 1, 1, 21),
29 'date': datetime.datetime(2010, 1, 1, 21),
30 'added': [
30 'added': [
31 FileNode('some/new.txt', content='news...'),
31 FileNode('some/new.txt', content='news...'),
32 ],
32 ],
33 'changed': [
33 'changed': [
34 FileNode('foobar', 'Foobar I'),
34 FileNode('foobar', 'Foobar I'),
35 ],
35 ],
36 'removed': [],
36 'removed': [],
37 },
37 },
38 ]
38 ]
39 return commits
39 return commits
40
40
41 def test_get_branch_for_default_branch(self):
41 def test_get_branch_for_default_branch(self):
42 self.assertEqual(self.repo.workdir.get_branch(),
42 assert self.repo.workdir.get_branch() == self.repo.DEFAULT_BRANCH_NAME
43 self.repo.DEFAULT_BRANCH_NAME)
44
43
45 def test_get_branch_after_adding_one(self):
44 def test_get_branch_after_adding_one(self):
46 self.imc.add(FileNode('docs/index.txt',
45 self.imc.add(FileNode('docs/index.txt',
47 content='Documentation\n'))
46 content='Documentation\n'))
48 self.imc.commit(
47 self.imc.commit(
49 message=u'New branch: foobar',
48 message=u'New branch: foobar',
50 author=u'joe',
49 author=u'joe',
51 branch='foobar',
50 branch='foobar',
52 )
51 )
53 self.assertEqual(self.repo.workdir.get_branch(), self.default_branch)
52 assert self.repo.workdir.get_branch() == self.default_branch
54
53
55 def test_get_changeset(self):
54 def test_get_changeset(self):
56 old_head = self.repo.get_changeset()
55 old_head = self.repo.get_changeset()
57 self.imc.add(FileNode('docs/index.txt',
56 self.imc.add(FileNode('docs/index.txt',
58 content='Documentation\n'))
57 content='Documentation\n'))
59 head = self.imc.commit(
58 head = self.imc.commit(
60 message=u'New branch: foobar',
59 message=u'New branch: foobar',
61 author=u'joe',
60 author=u'joe',
62 branch='foobar',
61 branch='foobar',
63 )
62 )
64 self.assertEqual(self.repo.workdir.get_branch(), self.default_branch)
63 assert self.repo.workdir.get_branch() == self.default_branch
65 self.repo.workdir.checkout_branch('foobar')
64 self.repo.workdir.checkout_branch('foobar')
66 self.assertEqual(self.repo.workdir.get_changeset(), head)
65 assert self.repo.workdir.get_changeset() == head
67
66
68 # Make sure that old head is still there after update to default branch
67 # Make sure that old head is still there after update to default branch
69 self.repo.workdir.checkout_branch(self.default_branch)
68 self.repo.workdir.checkout_branch(self.default_branch)
70 self.assertEqual(self.repo.workdir.get_changeset(), old_head)
69 assert self.repo.workdir.get_changeset() == old_head
71
70
72 def test_checkout_branch(self):
71 def test_checkout_branch(self):
73 from kallithea.lib.vcs.exceptions import BranchDoesNotExistError
72 from kallithea.lib.vcs.exceptions import BranchDoesNotExistError
74 # first, 'foobranch' does not exist.
73 # first, 'foobranch' does not exist.
75 self.assertRaises(BranchDoesNotExistError, self.repo.workdir.checkout_branch,
74 with pytest.raises(BranchDoesNotExistError):
76 branch='foobranch')
75 self.repo.workdir.checkout_branch(branch='foobranch')
77 # create new branch 'foobranch'.
76 # create new branch 'foobranch'.
78 self.imc.add(FileNode('file1', content='blah'))
77 self.imc.add(FileNode('file1', content='blah'))
79 self.imc.commit(message=u'asd', author=u'john', branch='foobranch')
78 self.imc.commit(message=u'asd', author=u'john', branch='foobranch')
80 # go back to the default branch
79 # go back to the default branch
81 self.repo.workdir.checkout_branch()
80 self.repo.workdir.checkout_branch()
82 self.assertEqual(self.repo.workdir.get_branch(), self.backend_class.DEFAULT_BRANCH_NAME)
81 assert self.repo.workdir.get_branch() == self.backend_class.DEFAULT_BRANCH_NAME
83 # checkout 'foobranch'
82 # checkout 'foobranch'
84 self.repo.workdir.checkout_branch('foobranch')
83 self.repo.workdir.checkout_branch('foobranch')
85 self.assertEqual(self.repo.workdir.get_branch(), 'foobranch')
84 assert self.repo.workdir.get_branch() == 'foobranch'
86
85
87
86
88 # For each backend create test case class
87 # For each backend create test case class
89 for alias in SCM_TESTS:
88 for alias in SCM_TESTS:
90 attrs = {
89 attrs = {
91 'backend_alias': alias,
90 'backend_alias': alias,
92 }
91 }
93 cls_name = ''.join(('%s branch test' % alias).title().split())
92 cls_name = ''.join(('test %s branch' % alias).title().split())
94 bases = (WorkdirTestCaseMixin, unittest.TestCase)
93 globals()[cls_name] = type(cls_name, (WorkdirTestCaseMixin, ), attrs)
95 globals()[cls_name] = type(cls_name, bases, attrs)
General Comments 0
You need to be logged in to leave comments. Login now