##// END OF EJS Templates
tests: fixes after some later code changes
marcink -
r3873:927faae7 default
parent child Browse files
Show More
@@ -1,143 +1,143 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 import pytest
22 import pytest
23 import urlobject
23 import urlobject
24
24
25 from rhodecode.api.tests.utils import (
25 from rhodecode.api.tests.utils import (
26 build_data, api_call, assert_error, assert_ok)
26 build_data, api_call, assert_error, assert_ok)
27 from rhodecode.lib import helpers as h
27 from rhodecode.lib import helpers as h
28 from rhodecode.lib.utils2 import safe_unicode
28 from rhodecode.lib.utils2 import safe_unicode
29
29
30 pytestmark = pytest.mark.backends("git", "hg")
30 pytestmark = pytest.mark.backends("git", "hg")
31
31
32
32
33 @pytest.mark.usefixtures("testuser_api", "app")
33 @pytest.mark.usefixtures("testuser_api", "app")
34 class TestGetPullRequest(object):
34 class TestGetPullRequest(object):
35
35
36 def test_api_get_pull_request(self, pr_util, http_host_only_stub):
36 def test_api_get_pull_request(self, pr_util, http_host_only_stub):
37 from rhodecode.model.pull_request import PullRequestModel
37 from rhodecode.model.pull_request import PullRequestModel
38 pull_request = pr_util.create_pull_request(mergeable=True)
38 pull_request = pr_util.create_pull_request(mergeable=True)
39 id_, params = build_data(
39 id_, params = build_data(
40 self.apikey, 'get_pull_request',
40 self.apikey, 'get_pull_request',
41 pullrequestid=pull_request.pull_request_id)
41 pullrequestid=pull_request.pull_request_id, merge_state=True)
42
42
43 response = api_call(self.app, params)
43 response = api_call(self.app, params)
44
44
45 assert response.status == '200 OK'
45 assert response.status == '200 OK'
46
46
47 url_obj = urlobject.URLObject(
47 url_obj = urlobject.URLObject(
48 h.route_url(
48 h.route_url(
49 'pullrequest_show',
49 'pullrequest_show',
50 repo_name=pull_request.target_repo.repo_name,
50 repo_name=pull_request.target_repo.repo_name,
51 pull_request_id=pull_request.pull_request_id))
51 pull_request_id=pull_request.pull_request_id))
52
52
53 pr_url = safe_unicode(
53 pr_url = safe_unicode(
54 url_obj.with_netloc(http_host_only_stub))
54 url_obj.with_netloc(http_host_only_stub))
55 source_url = safe_unicode(
55 source_url = safe_unicode(
56 pull_request.source_repo.clone_url().with_netloc(http_host_only_stub))
56 pull_request.source_repo.clone_url().with_netloc(http_host_only_stub))
57 target_url = safe_unicode(
57 target_url = safe_unicode(
58 pull_request.target_repo.clone_url().with_netloc(http_host_only_stub))
58 pull_request.target_repo.clone_url().with_netloc(http_host_only_stub))
59 shadow_url = safe_unicode(
59 shadow_url = safe_unicode(
60 PullRequestModel().get_shadow_clone_url(pull_request))
60 PullRequestModel().get_shadow_clone_url(pull_request))
61
61
62 expected = {
62 expected = {
63 'pull_request_id': pull_request.pull_request_id,
63 'pull_request_id': pull_request.pull_request_id,
64 'url': pr_url,
64 'url': pr_url,
65 'title': pull_request.title,
65 'title': pull_request.title,
66 'description': pull_request.description,
66 'description': pull_request.description,
67 'status': pull_request.status,
67 'status': pull_request.status,
68 'state': pull_request.pull_request_state,
68 'state': pull_request.pull_request_state,
69 'created_on': pull_request.created_on,
69 'created_on': pull_request.created_on,
70 'updated_on': pull_request.updated_on,
70 'updated_on': pull_request.updated_on,
71 'commit_ids': pull_request.revisions,
71 'commit_ids': pull_request.revisions,
72 'review_status': pull_request.calculated_review_status(),
72 'review_status': pull_request.calculated_review_status(),
73 'mergeable': {
73 'mergeable': {
74 'status': True,
74 'status': True,
75 'message': 'This pull request can be automatically merged.',
75 'message': 'This pull request can be automatically merged.',
76 },
76 },
77 'source': {
77 'source': {
78 'clone_url': source_url,
78 'clone_url': source_url,
79 'repository': pull_request.source_repo.repo_name,
79 'repository': pull_request.source_repo.repo_name,
80 'reference': {
80 'reference': {
81 'name': pull_request.source_ref_parts.name,
81 'name': pull_request.source_ref_parts.name,
82 'type': pull_request.source_ref_parts.type,
82 'type': pull_request.source_ref_parts.type,
83 'commit_id': pull_request.source_ref_parts.commit_id,
83 'commit_id': pull_request.source_ref_parts.commit_id,
84 },
84 },
85 },
85 },
86 'target': {
86 'target': {
87 'clone_url': target_url,
87 'clone_url': target_url,
88 'repository': pull_request.target_repo.repo_name,
88 'repository': pull_request.target_repo.repo_name,
89 'reference': {
89 'reference': {
90 'name': pull_request.target_ref_parts.name,
90 'name': pull_request.target_ref_parts.name,
91 'type': pull_request.target_ref_parts.type,
91 'type': pull_request.target_ref_parts.type,
92 'commit_id': pull_request.target_ref_parts.commit_id,
92 'commit_id': pull_request.target_ref_parts.commit_id,
93 },
93 },
94 },
94 },
95 'merge': {
95 'merge': {
96 'clone_url': shadow_url,
96 'clone_url': shadow_url,
97 'reference': {
97 'reference': {
98 'name': pull_request.shadow_merge_ref.name,
98 'name': pull_request.shadow_merge_ref.name,
99 'type': pull_request.shadow_merge_ref.type,
99 'type': pull_request.shadow_merge_ref.type,
100 'commit_id': pull_request.shadow_merge_ref.commit_id,
100 'commit_id': pull_request.shadow_merge_ref.commit_id,
101 },
101 },
102 },
102 },
103 'author': pull_request.author.get_api_data(include_secrets=False,
103 'author': pull_request.author.get_api_data(include_secrets=False,
104 details='basic'),
104 details='basic'),
105 'reviewers': [
105 'reviewers': [
106 {
106 {
107 'user': reviewer.get_api_data(include_secrets=False,
107 'user': reviewer.get_api_data(include_secrets=False,
108 details='basic'),
108 details='basic'),
109 'reasons': reasons,
109 'reasons': reasons,
110 'review_status': st[0][1].status if st else 'not_reviewed',
110 'review_status': st[0][1].status if st else 'not_reviewed',
111 }
111 }
112 for obj, reviewer, reasons, mandatory, st in
112 for obj, reviewer, reasons, mandatory, st in
113 pull_request.reviewers_statuses()
113 pull_request.reviewers_statuses()
114 ]
114 ]
115 }
115 }
116 assert_ok(id_, expected, response.body)
116 assert_ok(id_, expected, response.body)
117
117
118 def test_api_get_pull_request_repo_error(self, pr_util):
118 def test_api_get_pull_request_repo_error(self, pr_util):
119 pull_request = pr_util.create_pull_request()
119 pull_request = pr_util.create_pull_request()
120 id_, params = build_data(
120 id_, params = build_data(
121 self.apikey, 'get_pull_request',
121 self.apikey, 'get_pull_request',
122 repoid=666, pullrequestid=pull_request.pull_request_id)
122 repoid=666, pullrequestid=pull_request.pull_request_id)
123 response = api_call(self.app, params)
123 response = api_call(self.app, params)
124
124
125 expected = 'repository `666` does not exist'
125 expected = 'repository `666` does not exist'
126 assert_error(id_, expected, given=response.body)
126 assert_error(id_, expected, given=response.body)
127
127
128 def test_api_get_pull_request_pull_request_error(self):
128 def test_api_get_pull_request_pull_request_error(self):
129 id_, params = build_data(
129 id_, params = build_data(
130 self.apikey, 'get_pull_request', pullrequestid=666)
130 self.apikey, 'get_pull_request', pullrequestid=666)
131 response = api_call(self.app, params)
131 response = api_call(self.app, params)
132
132
133 expected = 'pull request `666` does not exist'
133 expected = 'pull request `666` does not exist'
134 assert_error(id_, expected, given=response.body)
134 assert_error(id_, expected, given=response.body)
135
135
136 def test_api_get_pull_request_pull_request_error_just_pr_id(self):
136 def test_api_get_pull_request_pull_request_error_just_pr_id(self):
137 id_, params = build_data(
137 id_, params = build_data(
138 self.apikey, 'get_pull_request',
138 self.apikey, 'get_pull_request',
139 pullrequestid=666)
139 pullrequestid=666)
140 response = api_call(self.app, params)
140 response = api_call(self.app, params)
141
141
142 expected = 'pull request `666` does not exist'
142 expected = 'pull request `666` does not exist'
143 assert_error(id_, expected, given=response.body)
143 assert_error(id_, expected, given=response.body)
@@ -1,305 +1,318 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import pytest
21 import pytest
22
22
23 from rhodecode.lib.helpers import _shorten_commit_id
23 from rhodecode.lib.helpers import _shorten_commit_id
24
24
25
25
26 def route_path(name, params=None, **kwargs):
26 def route_path(name, params=None, **kwargs):
27 import urllib
27 import urllib
28
28
29 base_url = {
29 base_url = {
30 'repo_commit': '/{repo_name}/changeset/{commit_id}',
30 'repo_commit': '/{repo_name}/changeset/{commit_id}',
31 'repo_commit_children': '/{repo_name}/changeset_children/{commit_id}',
31 'repo_commit_children': '/{repo_name}/changeset_children/{commit_id}',
32 'repo_commit_parents': '/{repo_name}/changeset_parents/{commit_id}',
32 'repo_commit_parents': '/{repo_name}/changeset_parents/{commit_id}',
33 'repo_commit_raw': '/{repo_name}/changeset-diff/{commit_id}',
33 'repo_commit_raw': '/{repo_name}/changeset-diff/{commit_id}',
34 'repo_commit_patch': '/{repo_name}/changeset-patch/{commit_id}',
34 'repo_commit_patch': '/{repo_name}/changeset-patch/{commit_id}',
35 'repo_commit_download': '/{repo_name}/changeset-download/{commit_id}',
35 'repo_commit_download': '/{repo_name}/changeset-download/{commit_id}',
36 'repo_commit_data': '/{repo_name}/changeset-data/{commit_id}',
36 'repo_commit_data': '/{repo_name}/changeset-data/{commit_id}',
37 'repo_compare': '/{repo_name}/compare/{source_ref_type}@{source_ref}...{target_ref_type}@{target_ref}',
37 'repo_compare': '/{repo_name}/compare/{source_ref_type}@{source_ref}...{target_ref_type}@{target_ref}',
38 }[name].format(**kwargs)
38 }[name].format(**kwargs)
39
39
40 if params:
40 if params:
41 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
41 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
42 return base_url
42 return base_url
43
43
44
44
45 @pytest.mark.usefixtures("app")
45 @pytest.mark.usefixtures("app")
46 class TestRepoCommitView(object):
46 class TestRepoCommitView(object):
47
47
48 def test_show_commit(self, backend):
48 def test_show_commit(self, backend):
49 commit_id = self.commit_id[backend.alias]
49 commit_id = self.commit_id[backend.alias]
50 response = self.app.get(route_path(
50 response = self.app.get(route_path(
51 'repo_commit', repo_name=backend.repo_name, commit_id=commit_id))
51 'repo_commit', repo_name=backend.repo_name, commit_id=commit_id))
52 response.mustcontain('Added a symlink')
52 response.mustcontain('Added a symlink')
53 response.mustcontain(commit_id)
53 response.mustcontain(commit_id)
54 response.mustcontain('No newline at end of file')
54 response.mustcontain('No newline at end of file')
55
55
56 def test_show_raw(self, backend):
56 def test_show_raw(self, backend):
57 commit_id = self.commit_id[backend.alias]
57 commit_id = self.commit_id[backend.alias]
58 response = self.app.get(route_path(
58 response = self.app.get(route_path(
59 'repo_commit_raw',
59 'repo_commit_raw',
60 repo_name=backend.repo_name, commit_id=commit_id))
60 repo_name=backend.repo_name, commit_id=commit_id))
61 assert response.body == self.diffs[backend.alias]
61 assert response.body == self.diffs[backend.alias]
62
62
63 def test_show_raw_patch(self, backend):
63 def test_show_raw_patch(self, backend):
64 response = self.app.get(route_path(
64 response = self.app.get(route_path(
65 'repo_commit_patch', repo_name=backend.repo_name,
65 'repo_commit_patch', repo_name=backend.repo_name,
66 commit_id=self.commit_id[backend.alias]))
66 commit_id=self.commit_id[backend.alias]))
67 assert response.body == self.patches[backend.alias]
67 assert response.body == self.patches[backend.alias]
68
68
69 def test_commit_download(self, backend):
69 def test_commit_download(self, backend):
70 response = self.app.get(route_path(
70 response = self.app.get(route_path(
71 'repo_commit_download',
71 'repo_commit_download',
72 repo_name=backend.repo_name,
72 repo_name=backend.repo_name,
73 commit_id=self.commit_id[backend.alias]))
73 commit_id=self.commit_id[backend.alias]))
74 assert response.body == self.diffs[backend.alias]
74 assert response.body == self.diffs[backend.alias]
75
75
76 def test_single_commit_page_different_ops(self, backend):
76 def test_single_commit_page_different_ops(self, backend):
77 commit_id = {
77 commit_id = {
78 'hg': '603d6c72c46d953420c89d36372f08d9f305f5dd',
78 'hg': '603d6c72c46d953420c89d36372f08d9f305f5dd',
79 'git': '03fa803d7e9fb14daa9a3089e0d1494eda75d986',
79 'git': '03fa803d7e9fb14daa9a3089e0d1494eda75d986',
80 'svn': '337',
80 'svn': '337',
81 }
81 }
82 diff_stat = {
83 'git': '20 files changed: 941 inserted, 286 deleted',
84 'svn': '21 files changed: 943 inserted, 288 deleted',
85 'hg': '21 files changed: 943 inserted, 288 deleted',
86
87 }
82 commit_id = commit_id[backend.alias]
88 commit_id = commit_id[backend.alias]
83 response = self.app.get(route_path(
89 response = self.app.get(route_path(
84 'repo_commit',
90 'repo_commit',
85 repo_name=backend.repo_name, commit_id=commit_id))
91 repo_name=backend.repo_name, commit_id=commit_id))
86
92
87 response.mustcontain(_shorten_commit_id(commit_id))
93 response.mustcontain(_shorten_commit_id(commit_id))
88 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
94 response.mustcontain(diff_stat[backend.alias])
89
95
90 # files op files
96 # files op files
91 response.mustcontain('File not present at commit: %s' %
97 response.mustcontain('File not present at commit: %s' %
92 _shorten_commit_id(commit_id))
98 _shorten_commit_id(commit_id))
93
99
94 # svn uses a different filename
100 # svn uses a different filename
95 if backend.alias == 'svn':
101 if backend.alias == 'svn':
96 response.mustcontain('new file 10644')
102 response.mustcontain('new file 10644')
97 else:
103 else:
98 response.mustcontain('new file 100644')
104 response.mustcontain('new file 100644')
99 response.mustcontain('Changed theme to ADC theme') # commit msg
105 response.mustcontain('Changed theme to ADC theme') # commit msg
100
106
101 self._check_new_diff_menus(response, right_menu=True)
107 self._check_new_diff_menus(response, right_menu=True)
102
108
103 def test_commit_range_page_different_ops(self, backend):
109 def test_commit_range_page_different_ops(self, backend):
104 commit_id_range = {
110 commit_id_range = {
105 'hg': (
111 'hg': (
106 '25d7e49c18b159446cadfa506a5cf8ad1cb04067',
112 '25d7e49c18b159446cadfa506a5cf8ad1cb04067',
107 '603d6c72c46d953420c89d36372f08d9f305f5dd'),
113 '603d6c72c46d953420c89d36372f08d9f305f5dd'),
108 'git': (
114 'git': (
109 '6fc9270775aaf5544c1deb014f4ddd60c952fcbb',
115 '6fc9270775aaf5544c1deb014f4ddd60c952fcbb',
110 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'),
116 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'),
111 'svn': (
117 'svn': (
112 '335',
118 '335',
113 '337'),
119 '337'),
114 }
120 }
115 commit_ids = commit_id_range[backend.alias]
121 commit_ids = commit_id_range[backend.alias]
116 commit_id = '%s...%s' % (commit_ids[0], commit_ids[1])
122 commit_id = '%s...%s' % (commit_ids[0], commit_ids[1])
117 response = self.app.get(route_path(
123 response = self.app.get(route_path(
118 'repo_commit',
124 'repo_commit',
119 repo_name=backend.repo_name, commit_id=commit_id))
125 repo_name=backend.repo_name, commit_id=commit_id))
120
126
121 response.mustcontain(_shorten_commit_id(commit_ids[0]))
127 response.mustcontain(_shorten_commit_id(commit_ids[0]))
122 response.mustcontain(_shorten_commit_id(commit_ids[1]))
128 response.mustcontain(_shorten_commit_id(commit_ids[1]))
123
129
124 # svn is special
130 # svn is special
125 if backend.alias == 'svn':
131 if backend.alias == 'svn':
126 response.mustcontain('new file 10644')
132 response.mustcontain('new file 10644')
127 response.mustcontain('1 file changed: 5 inserted, 1 deleted')
133 response.mustcontain('1 file changed: 5 inserted, 1 deleted')
128 response.mustcontain('12 files changed: 236 inserted, 22 deleted')
134 response.mustcontain('12 files changed: 236 inserted, 22 deleted')
129 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
135 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
136 elif backend.alias == 'git':
137 response.mustcontain('new file 100644')
138 response.mustcontain('12 files changed: 222 inserted, 20 deleted')
139 response.mustcontain('20 files changed: 941 inserted, 286 deleted')
130 else:
140 else:
131 response.mustcontain('new file 100644')
141 response.mustcontain('new file 100644')
132 response.mustcontain('12 files changed: 222 inserted, 20 deleted')
142 response.mustcontain('12 files changed: 222 inserted, 20 deleted')
133 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
143 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
134
144
135 # files op files
145 # files op files
136 response.mustcontain('File not present at commit: %s' %
146 response.mustcontain('File not present at commit: %s' %
137 _shorten_commit_id(commit_ids[1]))
147 _shorten_commit_id(commit_ids[1]))
138 response.mustcontain('Added docstrings to vcs.cli') # commit msg
148 response.mustcontain('Added docstrings to vcs.cli') # commit msg
139 response.mustcontain('Changed theme to ADC theme') # commit msg
149 response.mustcontain('Changed theme to ADC theme') # commit msg
140
150
141 self._check_new_diff_menus(response)
151 self._check_new_diff_menus(response)
142
152
143 def test_combined_compare_commit_page_different_ops(self, backend):
153 def test_combined_compare_commit_page_different_ops(self, backend):
144 commit_id_range = {
154 commit_id_range = {
145 'hg': (
155 'hg': (
146 '4fdd71e9427417b2e904e0464c634fdee85ec5a7',
156 '4fdd71e9427417b2e904e0464c634fdee85ec5a7',
147 '603d6c72c46d953420c89d36372f08d9f305f5dd'),
157 '603d6c72c46d953420c89d36372f08d9f305f5dd'),
148 'git': (
158 'git': (
149 'f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13',
159 'f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13',
150 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'),
160 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'),
151 'svn': (
161 'svn': (
152 '335',
162 '335',
153 '337'),
163 '337'),
154 }
164 }
155 commit_ids = commit_id_range[backend.alias]
165 commit_ids = commit_id_range[backend.alias]
156 response = self.app.get(route_path(
166 response = self.app.get(route_path(
157 'repo_compare',
167 'repo_compare',
158 repo_name=backend.repo_name,
168 repo_name=backend.repo_name,
159 source_ref_type='rev', source_ref=commit_ids[0],
169 source_ref_type='rev', source_ref=commit_ids[0],
160 target_ref_type='rev', target_ref=commit_ids[1], ))
170 target_ref_type='rev', target_ref=commit_ids[1], ))
161
171
162 response.mustcontain(_shorten_commit_id(commit_ids[0]))
172 response.mustcontain(_shorten_commit_id(commit_ids[0]))
163 response.mustcontain(_shorten_commit_id(commit_ids[1]))
173 response.mustcontain(_shorten_commit_id(commit_ids[1]))
164
174
165 # files op files
175 # files op files
166 response.mustcontain('File not present at commit: %s' %
176 response.mustcontain('File not present at commit: %s' %
167 _shorten_commit_id(commit_ids[1]))
177 _shorten_commit_id(commit_ids[1]))
168
178
169 # svn is special
179 # svn is special
170 if backend.alias == 'svn':
180 if backend.alias == 'svn':
171 response.mustcontain('new file 10644')
181 response.mustcontain('new file 10644')
172 response.mustcontain('32 files changed: 1179 inserted, 310 deleted')
182 response.mustcontain('32 files changed: 1179 inserted, 310 deleted')
183 elif backend.alias == 'git':
184 response.mustcontain('new file 100644')
185 response.mustcontain('31 files changed: 1163 inserted, 306 deleted')
173 else:
186 else:
174 response.mustcontain('new file 100644')
187 response.mustcontain('new file 100644')
175 response.mustcontain('32 files changed: 1165 inserted, 308 deleted')
188 response.mustcontain('32 files changed: 1165 inserted, 308 deleted')
176
189
177 response.mustcontain('Added docstrings to vcs.cli') # commit msg
190 response.mustcontain('Added docstrings to vcs.cli') # commit msg
178 response.mustcontain('Changed theme to ADC theme') # commit msg
191 response.mustcontain('Changed theme to ADC theme') # commit msg
179
192
180 self._check_new_diff_menus(response)
193 self._check_new_diff_menus(response)
181
194
182 def test_changeset_range(self, backend):
195 def test_changeset_range(self, backend):
183 self._check_changeset_range(
196 self._check_changeset_range(
184 backend, self.commit_id_range, self.commit_id_range_result)
197 backend, self.commit_id_range, self.commit_id_range_result)
185
198
186 def test_changeset_range_with_initial_commit(self, backend):
199 def test_changeset_range_with_initial_commit(self, backend):
187 commit_id_range = {
200 commit_id_range = {
188 'hg': (
201 'hg': (
189 'b986218ba1c9b0d6a259fac9b050b1724ed8e545'
202 'b986218ba1c9b0d6a259fac9b050b1724ed8e545'
190 '...6cba7170863a2411822803fa77a0a264f1310b35'),
203 '...6cba7170863a2411822803fa77a0a264f1310b35'),
191 'git': (
204 'git': (
192 'c1214f7e79e02fc37156ff215cd71275450cffc3'
205 'c1214f7e79e02fc37156ff215cd71275450cffc3'
193 '...fa6600f6848800641328adbf7811fd2372c02ab2'),
206 '...fa6600f6848800641328adbf7811fd2372c02ab2'),
194 'svn': '1...3',
207 'svn': '1...3',
195 }
208 }
196 commit_id_range_result = {
209 commit_id_range_result = {
197 'hg': ['b986218ba1c9', '3d8f361e72ab', '6cba7170863a'],
210 'hg': ['b986218ba1c9', '3d8f361e72ab', '6cba7170863a'],
198 'git': ['c1214f7e79e0', '38b5fe81f109', 'fa6600f68488'],
211 'git': ['c1214f7e79e0', '38b5fe81f109', 'fa6600f68488'],
199 'svn': ['1', '2', '3'],
212 'svn': ['1', '2', '3'],
200 }
213 }
201 self._check_changeset_range(
214 self._check_changeset_range(
202 backend, commit_id_range, commit_id_range_result)
215 backend, commit_id_range, commit_id_range_result)
203
216
204 def _check_changeset_range(
217 def _check_changeset_range(
205 self, backend, commit_id_ranges, commit_id_range_result):
218 self, backend, commit_id_ranges, commit_id_range_result):
206 response = self.app.get(
219 response = self.app.get(
207 route_path('repo_commit',
220 route_path('repo_commit',
208 repo_name=backend.repo_name,
221 repo_name=backend.repo_name,
209 commit_id=commit_id_ranges[backend.alias]))
222 commit_id=commit_id_ranges[backend.alias]))
210
223
211 expected_result = commit_id_range_result[backend.alias]
224 expected_result = commit_id_range_result[backend.alias]
212 response.mustcontain('{} commits'.format(len(expected_result)))
225 response.mustcontain('{} commits'.format(len(expected_result)))
213 for commit_id in expected_result:
226 for commit_id in expected_result:
214 response.mustcontain(commit_id)
227 response.mustcontain(commit_id)
215
228
216 commit_id = {
229 commit_id = {
217 'hg': '2062ec7beeeaf9f44a1c25c41479565040b930b2',
230 'hg': '2062ec7beeeaf9f44a1c25c41479565040b930b2',
218 'svn': '393',
231 'svn': '393',
219 'git': 'fd627b9e0dd80b47be81af07c4a98518244ed2f7',
232 'git': 'fd627b9e0dd80b47be81af07c4a98518244ed2f7',
220 }
233 }
221
234
222 commit_id_range = {
235 commit_id_range = {
223 'hg': (
236 'hg': (
224 'a53d9201d4bc278910d416d94941b7ea007ecd52'
237 'a53d9201d4bc278910d416d94941b7ea007ecd52'
225 '...2062ec7beeeaf9f44a1c25c41479565040b930b2'),
238 '...2062ec7beeeaf9f44a1c25c41479565040b930b2'),
226 'git': (
239 'git': (
227 '7ab37bc680b4aa72c34d07b230c866c28e9fc204'
240 '7ab37bc680b4aa72c34d07b230c866c28e9fc204'
228 '...fd627b9e0dd80b47be81af07c4a98518244ed2f7'),
241 '...fd627b9e0dd80b47be81af07c4a98518244ed2f7'),
229 'svn': '391...393',
242 'svn': '391...393',
230 }
243 }
231
244
232 commit_id_range_result = {
245 commit_id_range_result = {
233 'hg': ['a53d9201d4bc', '96507bd11ecc', '2062ec7beeea'],
246 'hg': ['a53d9201d4bc', '96507bd11ecc', '2062ec7beeea'],
234 'git': ['7ab37bc680b4', '5f2c6ee19592', 'fd627b9e0dd8'],
247 'git': ['7ab37bc680b4', '5f2c6ee19592', 'fd627b9e0dd8'],
235 'svn': ['391', '392', '393'],
248 'svn': ['391', '392', '393'],
236 }
249 }
237
250
238 diffs = {
251 diffs = {
239 'hg': r"""diff --git a/README b/README
252 'hg': r"""diff --git a/README b/README
240 new file mode 120000
253 new file mode 120000
241 --- /dev/null
254 --- /dev/null
242 +++ b/README
255 +++ b/README
243 @@ -0,0 +1,1 @@
256 @@ -0,0 +1,1 @@
244 +README.rst
257 +README.rst
245 \ No newline at end of file
258 \ No newline at end of file
246 """,
259 """,
247 'git': r"""diff --git a/README b/README
260 'git': r"""diff --git a/README b/README
248 new file mode 120000
261 new file mode 120000
249 index 0000000000000000000000000000000000000000..92cacd285355271487b7e379dba6ca60f9a554a4
262 index 0000000..92cacd2
250 --- /dev/null
263 --- /dev/null
251 +++ b/README
264 +++ b/README
252 @@ -0,0 +1 @@
265 @@ -0,0 +1 @@
253 +README.rst
266 +README.rst
254 \ No newline at end of file
267 \ No newline at end of file
255 """,
268 """,
256 'svn': """Index: README
269 'svn': """Index: README
257 ===================================================================
270 ===================================================================
258 diff --git a/README b/README
271 diff --git a/README b/README
259 new file mode 10644
272 new file mode 10644
260 --- /dev/null\t(revision 0)
273 --- /dev/null\t(revision 0)
261 +++ b/README\t(revision 393)
274 +++ b/README\t(revision 393)
262 @@ -0,0 +1 @@
275 @@ -0,0 +1 @@
263 +link README.rst
276 +link README.rst
264 \\ No newline at end of file
277 \\ No newline at end of file
265 """,
278 """,
266 }
279 }
267
280
268 patches = {
281 patches = {
269 'hg': r"""# HG changeset patch
282 'hg': r"""# HG changeset patch
270 # User Marcin Kuzminski <marcin@python-works.com>
283 # User Marcin Kuzminski <marcin@python-works.com>
271 # Date 2014-01-07 12:21:40
284 # Date 2014-01-07 12:21:40
272 # Node ID 2062ec7beeeaf9f44a1c25c41479565040b930b2
285 # Node ID 2062ec7beeeaf9f44a1c25c41479565040b930b2
273 # Parent 96507bd11ecc815ebc6270fdf6db110928c09c1e
286 # Parent 96507bd11ecc815ebc6270fdf6db110928c09c1e
274
287
275 Added a symlink
288 Added a symlink
276
289
277 """ + diffs['hg'],
290 """ + diffs['hg'],
278 'git': r"""From fd627b9e0dd80b47be81af07c4a98518244ed2f7 2014-01-07 12:22:20
291 'git': r"""From fd627b9e0dd80b47be81af07c4a98518244ed2f7 2014-01-07 12:22:20
279 From: Marcin Kuzminski <marcin@python-works.com>
292 From: Marcin Kuzminski <marcin@python-works.com>
280 Date: 2014-01-07 12:22:20
293 Date: 2014-01-07 12:22:20
281 Subject: [PATCH] Added a symlink
294 Subject: [PATCH] Added a symlink
282
295
283 ---
296 ---
284
297
285 """ + diffs['git'],
298 """ + diffs['git'],
286 'svn': r"""# SVN changeset patch
299 'svn': r"""# SVN changeset patch
287 # User marcin
300 # User marcin
288 # Date 2014-09-02 12:25:22.071142
301 # Date 2014-09-02 12:25:22.071142
289 # Revision 393
302 # Revision 393
290
303
291 Added a symlink
304 Added a symlink
292
305
293 """ + diffs['svn'],
306 """ + diffs['svn'],
294 }
307 }
295
308
296 def _check_new_diff_menus(self, response, right_menu=False,):
309 def _check_new_diff_menus(self, response, right_menu=False,):
297 # individual file diff menus
310 # individual file diff menus
298 for elem in ['Show file before', 'Show file after']:
311 for elem in ['Show file before', 'Show file after']:
299 response.mustcontain(elem)
312 response.mustcontain(elem)
300
313
301 # right pane diff menus
314 # right pane diff menus
302 if right_menu:
315 if right_menu:
303 for elem in ['Hide whitespace changes', 'Toggle Wide Mode diff',
316 for elem in ['Hide whitespace changes', 'Toggle Wide Mode diff',
304 'Show full context diff']:
317 'Show full context diff']:
305 response.mustcontain(elem)
318 response.mustcontain(elem)
@@ -1,167 +1,167 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import pytest
21 import pytest
22
22
23 from .test_repo_compare import ComparePage
23 from .test_repo_compare import ComparePage
24
24
25
25
26 def route_path(name, params=None, **kwargs):
26 def route_path(name, params=None, **kwargs):
27 import urllib
27 import urllib
28
28
29 base_url = {
29 base_url = {
30 'repo_compare_select': '/{repo_name}/compare',
30 'repo_compare_select': '/{repo_name}/compare',
31 'repo_compare': '/{repo_name}/compare/{source_ref_type}@{source_ref}...{target_ref_type}@{target_ref}',
31 'repo_compare': '/{repo_name}/compare/{source_ref_type}@{source_ref}...{target_ref_type}@{target_ref}',
32 }[name].format(**kwargs)
32 }[name].format(**kwargs)
33
33
34 if params:
34 if params:
35 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
35 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
36 return base_url
36 return base_url
37
37
38
38
39 @pytest.mark.usefixtures("autologin_user", "app")
39 @pytest.mark.usefixtures("autologin_user", "app")
40 class TestCompareView(object):
40 class TestCompareView(object):
41
41
42 @pytest.mark.xfail_backends("svn", msg="Depends on branch and tag support")
42 @pytest.mark.xfail_backends("svn", msg="Depends on branch and tag support")
43 def test_compare_tag(self, backend):
43 def test_compare_tag(self, backend):
44 tag1 = 'v0.1.2'
44 tag1 = 'v0.1.2'
45 tag2 = 'v0.1.3'
45 tag2 = 'v0.1.3'
46 response = self.app.get(
46 response = self.app.get(
47 route_path(
47 route_path(
48 'repo_compare',
48 'repo_compare',
49 repo_name=backend.repo_name,
49 repo_name=backend.repo_name,
50 source_ref_type="tag", source_ref=tag1,
50 source_ref_type="tag", source_ref=tag1,
51 target_ref_type="tag", target_ref=tag2),
51 target_ref_type="tag", target_ref=tag2),
52 status=200)
52 status=200)
53
53
54 response.mustcontain('%s@%s' % (backend.repo_name, tag1))
54 response.mustcontain('%s@%s' % (backend.repo_name, tag1))
55 response.mustcontain('%s@%s' % (backend.repo_name, tag2))
55 response.mustcontain('%s@%s' % (backend.repo_name, tag2))
56
56
57 # outgoing commits between tags
57 # outgoing commits between tags
58 commit_indexes = {
58 commit_indexes = {
59 'git': [113] + range(115, 121),
59 'git': [113] + range(115, 121),
60 'hg': [112] + range(115, 121),
60 'hg': [112] + range(115, 121),
61 }
61 }
62 repo = backend.repo
62 repo = backend.repo
63 commits = (repo.get_commit(commit_idx=idx)
63 commits = (repo.get_commit(commit_idx=idx)
64 for idx in commit_indexes[backend.alias])
64 for idx in commit_indexes[backend.alias])
65 compare_page = ComparePage(response)
65 compare_page = ComparePage(response)
66 compare_page.contains_change_summary(11, 94, 64)
66 compare_page.contains_change_summary(11, 94, 64)
67 compare_page.contains_commits(commits)
67 compare_page.contains_commits(commits)
68
68
69 # files diff
69 # files diff
70 short_id = short_id_new = ''
70 short_id = short_id_new = ''
71 if backend.alias == 'git':
71 if backend.alias == 'git':
72 short_id = '5a3a8fb00555'
72 short_id = '5a3a8fb00555'
73 short_id_new = '0ba5f8a46600'
73 short_id_new = '0ba5f8a46600'
74 if backend.alias == 'hg':
74 if backend.alias == 'hg':
75 short_id = '17544fbfcd33'
75 short_id = '17544fbfcd33'
76 short_id_new = 'a7e60bff65d5'
76 short_id_new = 'a7e60bff65d5'
77
77
78 compare_page.contains_file_links_and_anchors([
78 compare_page.contains_file_links_and_anchors([
79 # modified
79 # modified
80 ('docs/api/utils/index.rst', 'a_c-{}-1c5cf9e91c12'.format(short_id)),
80 ('docs/api/utils/index.rst', 'a_c-{}-1c5cf9e91c12'.format(short_id)),
81 ('test_and_report.sh', 'a_c-{}-e3305437df55'.format(short_id)),
81 ('test_and_report.sh', 'a_c-{}-e3305437df55'.format(short_id)),
82 # added
82 # added
83 ('.hgignore', 'a_c-{}-c8e92ef85cd1'.format(short_id_new)),
83 ('.hgignore', 'a_c-{}-c8e92ef85cd1'.format(short_id_new)),
84 ('.hgtags', 'a_c-{}-6e08b694d687'.format(short_id_new)),
84 ('.hgtags', 'a_c-{}-6e08b694d687'.format(short_id_new)),
85 ('docs/api/index.rst', 'a_c-{}-2c14b00f3393'.format(short_id_new)),
85 ('docs/api/index.rst', 'a_c-{}-2c14b00f3393'.format(short_id_new)),
86 ('vcs/__init__.py', 'a_c-{}-430ccbc82bdf'.format(short_id_new)),
86 ('vcs/__init__.py', 'a_c-{}-430ccbc82bdf'.format(short_id_new)),
87 ('vcs/backends/hg.py', 'a_c-{}-9c390eb52cd6'.format(short_id_new)),
87 ('vcs/backends/hg.py', 'a_c-{}-9c390eb52cd6'.format(short_id_new)),
88 ('vcs/utils/__init__.py', 'a_c-{}-ebb592c595c0'.format(short_id_new)),
88 ('vcs/utils/__init__.py', 'a_c-{}-ebb592c595c0'.format(short_id_new)),
89 ('vcs/utils/annotate.py', 'a_c-{}-7abc741b5052'.format(short_id_new)),
89 ('vcs/utils/annotate.py', 'a_c-{}-7abc741b5052'.format(short_id_new)),
90 ('vcs/utils/diffs.py', 'a_c-{}-2ef0ef106c56'.format(short_id_new)),
90 ('vcs/utils/diffs.py', 'a_c-{}-2ef0ef106c56'.format(short_id_new)),
91 ('vcs/utils/lazy.py', 'a_c-{}-3150cb87d4b7'.format(short_id_new)),
91 ('vcs/utils/lazy.py', 'a_c-{}-3150cb87d4b7'.format(short_id_new)),
92 ])
92 ])
93
93
94 @pytest.mark.xfail_backends("svn", msg="Depends on branch and tag support")
94 @pytest.mark.xfail_backends("svn", msg="Depends on branch and tag support")
95 def test_compare_tag_branch(self, backend):
95 def test_compare_tag_branch(self, backend):
96 revisions = {
96 revisions = {
97 'hg': {
97 'hg': {
98 'tag': 'v0.2.0',
98 'tag': 'v0.2.0',
99 'branch': 'default',
99 'branch': 'default',
100 'response': (147, 5701, 10177)
100 'response': (147, 5701, 10177)
101 },
101 },
102 'git': {
102 'git': {
103 'tag': 'v0.2.2',
103 'tag': 'v0.2.2',
104 'branch': 'master',
104 'branch': 'master',
105 'response': (71, 2269, 3416)
105 'response': (70, 1855, 3002)
106 },
106 },
107 }
107 }
108
108
109 # Backend specific data, depends on the test repository for
109 # Backend specific data, depends on the test repository for
110 # functional tests.
110 # functional tests.
111 data = revisions[backend.alias]
111 data = revisions[backend.alias]
112
112
113 response = self.app.get(
113 response = self.app.get(
114 route_path(
114 route_path(
115 'repo_compare',
115 'repo_compare',
116 repo_name=backend.repo_name,
116 repo_name=backend.repo_name,
117 source_ref_type='branch', source_ref=data['branch'],
117 source_ref_type='branch', source_ref=data['branch'],
118 target_ref_type="tag", target_ref=data['tag'],
118 target_ref_type="tag", target_ref=data['tag'],
119 ))
119 ))
120
120
121 response.mustcontain('%s@%s' % (backend.repo_name, data['branch']))
121 response.mustcontain('%s@%s' % (backend.repo_name, data['branch']))
122 response.mustcontain('%s@%s' % (backend.repo_name, data['tag']))
122 response.mustcontain('%s@%s' % (backend.repo_name, data['tag']))
123 compare_page = ComparePage(response)
123 compare_page = ComparePage(response)
124 compare_page.contains_change_summary(*data['response'])
124 compare_page.contains_change_summary(*data['response'])
125
125
126 def test_index_branch(self, backend):
126 def test_index_branch(self, backend):
127 head_id = backend.default_head_id
127 head_id = backend.default_head_id
128 response = self.app.get(
128 response = self.app.get(
129 route_path(
129 route_path(
130 'repo_compare',
130 'repo_compare',
131 repo_name=backend.repo_name,
131 repo_name=backend.repo_name,
132 source_ref_type="branch", source_ref=head_id,
132 source_ref_type="branch", source_ref=head_id,
133 target_ref_type="branch", target_ref=head_id,
133 target_ref_type="branch", target_ref=head_id,
134 ))
134 ))
135
135
136 response.mustcontain('%s@%s' % (backend.repo_name, head_id))
136 response.mustcontain('%s@%s' % (backend.repo_name, head_id))
137
137
138 # branches are equal
138 # branches are equal
139 response.mustcontain('No files')
139 response.mustcontain('No files')
140 response.mustcontain('No commits in this compare')
140 response.mustcontain('No commits in this compare')
141
141
142 def test_compare_commits(self, backend):
142 def test_compare_commits(self, backend):
143 repo = backend.repo
143 repo = backend.repo
144 commit1 = repo.get_commit(commit_idx=0)
144 commit1 = repo.get_commit(commit_idx=0)
145 commit1_short_id = commit1.short_id
145 commit1_short_id = commit1.short_id
146 commit2 = repo.get_commit(commit_idx=1)
146 commit2 = repo.get_commit(commit_idx=1)
147 commit2_short_id = commit2.short_id
147 commit2_short_id = commit2.short_id
148
148
149 response = self.app.get(
149 response = self.app.get(
150 route_path(
150 route_path(
151 'repo_compare',
151 'repo_compare',
152 repo_name=backend.repo_name,
152 repo_name=backend.repo_name,
153 source_ref_type="rev", source_ref=commit1.raw_id,
153 source_ref_type="rev", source_ref=commit1.raw_id,
154 target_ref_type="rev", target_ref=commit2.raw_id,
154 target_ref_type="rev", target_ref=commit2.raw_id,
155 ))
155 ))
156 response.mustcontain('%s@%s' % (backend.repo_name, commit1.raw_id))
156 response.mustcontain('%s@%s' % (backend.repo_name, commit1.raw_id))
157 response.mustcontain('%s@%s' % (backend.repo_name, commit2.raw_id))
157 response.mustcontain('%s@%s' % (backend.repo_name, commit2.raw_id))
158 compare_page = ComparePage(response)
158 compare_page = ComparePage(response)
159
159
160 # files
160 # files
161 compare_page.contains_change_summary(1, 7, 0)
161 compare_page.contains_change_summary(1, 7, 0)
162
162
163 # outgoing commits between those commits
163 # outgoing commits between those commits
164 compare_page.contains_commits([commit2])
164 compare_page.contains_commits([commit2])
165 anchor = 'a_c-{}-c8e92ef85cd1'.format(commit2_short_id)
165 anchor = 'a_c-{}-c8e92ef85cd1'.format(commit2_short_id)
166 response.mustcontain(anchor)
166 response.mustcontain(anchor)
167 compare_page.contains_file_links_and_anchors([('.hgignore', anchor),])
167 compare_page.contains_file_links_and_anchors([('.hgignore', anchor),])
@@ -1,259 +1,259 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import pytest
21 import pytest
22
22
23 from rhodecode.lib.vcs import nodes
23 from rhodecode.lib.vcs import nodes
24 from rhodecode.lib.vcs.backends.base import EmptyCommit
24 from rhodecode.lib.vcs.backends.base import EmptyCommit
25 from rhodecode.tests.fixture import Fixture
25 from rhodecode.tests.fixture import Fixture
26 from rhodecode.tests.utils import commit_change
26 from rhodecode.tests.utils import commit_change
27
27
28 fixture = Fixture()
28 fixture = Fixture()
29
29
30
30
31 def route_path(name, params=None, **kwargs):
31 def route_path(name, params=None, **kwargs):
32 import urllib
32 import urllib
33
33
34 base_url = {
34 base_url = {
35 'repo_compare_select': '/{repo_name}/compare',
35 'repo_compare_select': '/{repo_name}/compare',
36 'repo_compare': '/{repo_name}/compare/{source_ref_type}@{source_ref}...{target_ref_type}@{target_ref}',
36 'repo_compare': '/{repo_name}/compare/{source_ref_type}@{source_ref}...{target_ref_type}@{target_ref}',
37 }[name].format(**kwargs)
37 }[name].format(**kwargs)
38
38
39 if params:
39 if params:
40 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
40 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
41 return base_url
41 return base_url
42
42
43
43
44 @pytest.mark.usefixtures("autologin_user", "app")
44 @pytest.mark.usefixtures("autologin_user", "app")
45 class TestSideBySideDiff(object):
45 class TestSideBySideDiff(object):
46
46
47 def test_diff_sidebyside_single_commit(self, app, backend):
47 def test_diff_sidebyside_single_commit(self, app, backend):
48 commit_id_range = {
48 commit_id_range = {
49 'hg': {
49 'hg': {
50 'commits': ['25d7e49c18b159446cadfa506a5cf8ad1cb04067',
50 'commits': ['25d7e49c18b159446cadfa506a5cf8ad1cb04067',
51 '603d6c72c46d953420c89d36372f08d9f305f5dd'],
51 '603d6c72c46d953420c89d36372f08d9f305f5dd'],
52 'changes': '21 files changed: 943 inserted, 288 deleted'
52 'changes': '21 files changed: 943 inserted, 288 deleted'
53 },
53 },
54 'git': {
54 'git': {
55 'commits': ['6fc9270775aaf5544c1deb014f4ddd60c952fcbb',
55 'commits': ['6fc9270775aaf5544c1deb014f4ddd60c952fcbb',
56 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'],
56 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'],
57 'changes': '21 files changed: 943 inserted, 288 deleted'
57 'changes': '20 files changed: 941 inserted, 286 deleted'
58 },
58 },
59
59
60 'svn': {
60 'svn': {
61 'commits': ['336',
61 'commits': ['336',
62 '337'],
62 '337'],
63 'changes': '21 files changed: 943 inserted, 288 deleted'
63 'changes': '21 files changed: 943 inserted, 288 deleted'
64 },
64 },
65 }
65 }
66
66
67 commit_info = commit_id_range[backend.alias]
67 commit_info = commit_id_range[backend.alias]
68 commit2, commit1 = commit_info['commits']
68 commit2, commit1 = commit_info['commits']
69 file_changes = commit_info['changes']
69 file_changes = commit_info['changes']
70
70
71 response = self.app.get(route_path(
71 response = self.app.get(route_path(
72 'repo_compare',
72 'repo_compare',
73 repo_name=backend.repo_name,
73 repo_name=backend.repo_name,
74 source_ref_type='rev',
74 source_ref_type='rev',
75 source_ref=commit2,
75 source_ref=commit2,
76 target_repo=backend.repo_name,
76 target_repo=backend.repo_name,
77 target_ref_type='rev',
77 target_ref_type='rev',
78 target_ref=commit1,
78 target_ref=commit1,
79 params=dict(target_repo=backend.repo_name, diffmode='sidebyside')
79 params=dict(target_repo=backend.repo_name, diffmode='sidebyside')
80 ))
80 ))
81
81
82 response.mustcontain(file_changes)
82 response.mustcontain(file_changes)
83 response.mustcontain('Expand 1 commit')
83 response.mustcontain('Expand 1 commit')
84
84
85 def test_diff_sidebyside_two_commits(self, app, backend):
85 def test_diff_sidebyside_two_commits(self, app, backend):
86 commit_id_range = {
86 commit_id_range = {
87 'hg': {
87 'hg': {
88 'commits': ['4fdd71e9427417b2e904e0464c634fdee85ec5a7',
88 'commits': ['4fdd71e9427417b2e904e0464c634fdee85ec5a7',
89 '603d6c72c46d953420c89d36372f08d9f305f5dd'],
89 '603d6c72c46d953420c89d36372f08d9f305f5dd'],
90 'changes': '32 files changed: 1165 inserted, 308 deleted'
90 'changes': '32 files changed: 1165 inserted, 308 deleted'
91 },
91 },
92 'git': {
92 'git': {
93 'commits': ['f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13',
93 'commits': ['f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13',
94 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'],
94 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'],
95 'changes': '32 files changed: 1165 inserted, 308 deleted'
95 'changes': '31 files changed: 1163 inserted, 306 deleted'
96 },
96 },
97
97
98 'svn': {
98 'svn': {
99 'commits': ['335',
99 'commits': ['335',
100 '337'],
100 '337'],
101 'changes': '32 files changed: 1179 inserted, 310 deleted'
101 'changes': '32 files changed: 1179 inserted, 310 deleted'
102 },
102 },
103 }
103 }
104
104
105 commit_info = commit_id_range[backend.alias]
105 commit_info = commit_id_range[backend.alias]
106 commit2, commit1 = commit_info['commits']
106 commit2, commit1 = commit_info['commits']
107 file_changes = commit_info['changes']
107 file_changes = commit_info['changes']
108
108
109 response = self.app.get(route_path(
109 response = self.app.get(route_path(
110 'repo_compare',
110 'repo_compare',
111 repo_name=backend.repo_name,
111 repo_name=backend.repo_name,
112 source_ref_type='rev',
112 source_ref_type='rev',
113 source_ref=commit2,
113 source_ref=commit2,
114 target_repo=backend.repo_name,
114 target_repo=backend.repo_name,
115 target_ref_type='rev',
115 target_ref_type='rev',
116 target_ref=commit1,
116 target_ref=commit1,
117 params=dict(target_repo=backend.repo_name, diffmode='sidebyside')
117 params=dict(target_repo=backend.repo_name, diffmode='sidebyside')
118 ))
118 ))
119
119
120 response.mustcontain(file_changes)
120 response.mustcontain(file_changes)
121 response.mustcontain('Expand 2 commits')
121 response.mustcontain('Expand 2 commits')
122
122
123 @pytest.mark.xfail(reason='GIT does not handle empty commit compare correct (missing 1 commit)')
123 @pytest.mark.xfail(reason='GIT does not handle empty commit compare correct (missing 1 commit)')
124 def test_diff_side_by_side_from_0_commit(self, app, backend, backend_stub):
124 def test_diff_side_by_side_from_0_commit(self, app, backend, backend_stub):
125 f_path = 'test_sidebyside_file.py'
125 f_path = 'test_sidebyside_file.py'
126 commit1_content = 'content-25d7e49c18b159446c\n'
126 commit1_content = 'content-25d7e49c18b159446c\n'
127 commit2_content = 'content-603d6c72c46d953420\n'
127 commit2_content = 'content-603d6c72c46d953420\n'
128 repo = backend.create_repo()
128 repo = backend.create_repo()
129
129
130 commit1 = commit_change(
130 commit1 = commit_change(
131 repo.repo_name, filename=f_path, content=commit1_content,
131 repo.repo_name, filename=f_path, content=commit1_content,
132 message='A', vcs_type=backend.alias, parent=None, newfile=True)
132 message='A', vcs_type=backend.alias, parent=None, newfile=True)
133
133
134 commit2 = commit_change(
134 commit2 = commit_change(
135 repo.repo_name, filename=f_path, content=commit2_content,
135 repo.repo_name, filename=f_path, content=commit2_content,
136 message='B, child of A', vcs_type=backend.alias, parent=commit1)
136 message='B, child of A', vcs_type=backend.alias, parent=commit1)
137
137
138 response = self.app.get(route_path(
138 response = self.app.get(route_path(
139 'repo_compare',
139 'repo_compare',
140 repo_name=repo.repo_name,
140 repo_name=repo.repo_name,
141 source_ref_type='rev',
141 source_ref_type='rev',
142 source_ref=EmptyCommit().raw_id,
142 source_ref=EmptyCommit().raw_id,
143 target_ref_type='rev',
143 target_ref_type='rev',
144 target_ref=commit2.raw_id,
144 target_ref=commit2.raw_id,
145 params=dict(diffmode='sidebyside')
145 params=dict(diffmode='sidebyside')
146 ))
146 ))
147
147
148 response.mustcontain('Expand 2 commits')
148 response.mustcontain('Expand 2 commits')
149 response.mustcontain('123 file changed')
149 response.mustcontain('123 file changed')
150
150
151 response.mustcontain(
151 response.mustcontain(
152 'r%s:%s...r%s:%s' % (
152 'r%s:%s...r%s:%s' % (
153 commit1.idx, commit1.short_id, commit2.idx, commit2.short_id))
153 commit1.idx, commit1.short_id, commit2.idx, commit2.short_id))
154
154
155 response.mustcontain('<strong>{}</strong>'.format(f_path))
155 response.mustcontain('<strong>{}</strong>'.format(f_path))
156
156
157 @pytest.mark.xfail(reason='GIT does not handle empty commit compare correct (missing 1 commit)')
157 @pytest.mark.xfail(reason='GIT does not handle empty commit compare correct (missing 1 commit)')
158 def test_diff_side_by_side_from_0_commit_with_file_filter(self, app, backend, backend_stub):
158 def test_diff_side_by_side_from_0_commit_with_file_filter(self, app, backend, backend_stub):
159 f_path = 'test_sidebyside_file.py'
159 f_path = 'test_sidebyside_file.py'
160 commit1_content = 'content-25d7e49c18b159446c\n'
160 commit1_content = 'content-25d7e49c18b159446c\n'
161 commit2_content = 'content-603d6c72c46d953420\n'
161 commit2_content = 'content-603d6c72c46d953420\n'
162 repo = backend.create_repo()
162 repo = backend.create_repo()
163
163
164 commit1 = commit_change(
164 commit1 = commit_change(
165 repo.repo_name, filename=f_path, content=commit1_content,
165 repo.repo_name, filename=f_path, content=commit1_content,
166 message='A', vcs_type=backend.alias, parent=None, newfile=True)
166 message='A', vcs_type=backend.alias, parent=None, newfile=True)
167
167
168 commit2 = commit_change(
168 commit2 = commit_change(
169 repo.repo_name, filename=f_path, content=commit2_content,
169 repo.repo_name, filename=f_path, content=commit2_content,
170 message='B, child of A', vcs_type=backend.alias, parent=commit1)
170 message='B, child of A', vcs_type=backend.alias, parent=commit1)
171
171
172 response = self.app.get(route_path(
172 response = self.app.get(route_path(
173 'repo_compare',
173 'repo_compare',
174 repo_name=repo.repo_name,
174 repo_name=repo.repo_name,
175 source_ref_type='rev',
175 source_ref_type='rev',
176 source_ref=EmptyCommit().raw_id,
176 source_ref=EmptyCommit().raw_id,
177 target_ref_type='rev',
177 target_ref_type='rev',
178 target_ref=commit2.raw_id,
178 target_ref=commit2.raw_id,
179 params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside')
179 params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside')
180 ))
180 ))
181
181
182 response.mustcontain('Expand 2 commits')
182 response.mustcontain('Expand 2 commits')
183 response.mustcontain('1 file changed')
183 response.mustcontain('1 file changed')
184
184
185 response.mustcontain(
185 response.mustcontain(
186 'r%s:%s...r%s:%s' % (
186 'r%s:%s...r%s:%s' % (
187 commit1.idx, commit1.short_id, commit2.idx, commit2.short_id))
187 commit1.idx, commit1.short_id, commit2.idx, commit2.short_id))
188
188
189 response.mustcontain('<strong>{}</strong>'.format(f_path))
189 response.mustcontain('<strong>{}</strong>'.format(f_path))
190
190
191 def test_diff_side_by_side_with_empty_file(self, app, backend, backend_stub):
191 def test_diff_side_by_side_with_empty_file(self, app, backend, backend_stub):
192 commits = [
192 commits = [
193 {'message': 'First commit'},
193 {'message': 'First commit'},
194 {'message': 'Second commit'},
194 {'message': 'Second commit'},
195 {'message': 'Commit with binary',
195 {'message': 'Commit with binary',
196 'added': [nodes.FileNode('file.empty', content='')]},
196 'added': [nodes.FileNode('file.empty', content='')]},
197 ]
197 ]
198 f_path = 'file.empty'
198 f_path = 'file.empty'
199 repo = backend.create_repo(commits=commits)
199 repo = backend.create_repo(commits=commits)
200 commit1 = repo.get_commit(commit_idx=0)
200 commit1 = repo.get_commit(commit_idx=0)
201 commit2 = repo.get_commit(commit_idx=1)
201 commit2 = repo.get_commit(commit_idx=1)
202 commit3 = repo.get_commit(commit_idx=2)
202 commit3 = repo.get_commit(commit_idx=2)
203
203
204 response = self.app.get(route_path(
204 response = self.app.get(route_path(
205 'repo_compare',
205 'repo_compare',
206 repo_name=repo.repo_name,
206 repo_name=repo.repo_name,
207 source_ref_type='rev',
207 source_ref_type='rev',
208 source_ref=commit1.raw_id,
208 source_ref=commit1.raw_id,
209 target_ref_type='rev',
209 target_ref_type='rev',
210 target_ref=commit3.raw_id,
210 target_ref=commit3.raw_id,
211 params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside')
211 params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside')
212 ))
212 ))
213
213
214 response.mustcontain('Expand 2 commits')
214 response.mustcontain('Expand 2 commits')
215 response.mustcontain('1 file changed')
215 response.mustcontain('1 file changed')
216
216
217 response.mustcontain(
217 response.mustcontain(
218 'r%s:%s...r%s:%s' % (
218 'r%s:%s...r%s:%s' % (
219 commit2.idx, commit2.short_id, commit3.idx, commit3.short_id))
219 commit2.idx, commit2.short_id, commit3.idx, commit3.short_id))
220
220
221 response.mustcontain('<strong>{}</strong>'.format(f_path))
221 response.mustcontain('<strong>{}</strong>'.format(f_path))
222
222
223 def test_diff_sidebyside_two_commits_with_file_filter(self, app, backend):
223 def test_diff_sidebyside_two_commits_with_file_filter(self, app, backend):
224 commit_id_range = {
224 commit_id_range = {
225 'hg': {
225 'hg': {
226 'commits': ['4fdd71e9427417b2e904e0464c634fdee85ec5a7',
226 'commits': ['4fdd71e9427417b2e904e0464c634fdee85ec5a7',
227 '603d6c72c46d953420c89d36372f08d9f305f5dd'],
227 '603d6c72c46d953420c89d36372f08d9f305f5dd'],
228 'changes': '1 file changed: 3 inserted, 3 deleted'
228 'changes': '1 file changed: 3 inserted, 3 deleted'
229 },
229 },
230 'git': {
230 'git': {
231 'commits': ['f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13',
231 'commits': ['f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13',
232 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'],
232 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'],
233 'changes': '1 file changed: 3 inserted, 3 deleted'
233 'changes': '1 file changed: 3 inserted, 3 deleted'
234 },
234 },
235
235
236 'svn': {
236 'svn': {
237 'commits': ['335',
237 'commits': ['335',
238 '337'],
238 '337'],
239 'changes': '1 file changed: 3 inserted, 3 deleted'
239 'changes': '1 file changed: 3 inserted, 3 deleted'
240 },
240 },
241 }
241 }
242 f_path = 'docs/conf.py'
242 f_path = 'docs/conf.py'
243
243
244 commit_info = commit_id_range[backend.alias]
244 commit_info = commit_id_range[backend.alias]
245 commit2, commit1 = commit_info['commits']
245 commit2, commit1 = commit_info['commits']
246 file_changes = commit_info['changes']
246 file_changes = commit_info['changes']
247
247
248 response = self.app.get(route_path(
248 response = self.app.get(route_path(
249 'repo_compare',
249 'repo_compare',
250 repo_name=backend.repo_name,
250 repo_name=backend.repo_name,
251 source_ref_type='rev',
251 source_ref_type='rev',
252 source_ref=commit2,
252 source_ref=commit2,
253 target_ref_type='rev',
253 target_ref_type='rev',
254 target_ref=commit1,
254 target_ref=commit1,
255 params=dict(f_path=f_path, target_repo=backend.repo_name, diffmode='sidebyside')
255 params=dict(f_path=f_path, target_repo=backend.repo_name, diffmode='sidebyside')
256 ))
256 ))
257
257
258 response.mustcontain('Expand 2 commits')
258 response.mustcontain('Expand 2 commits')
259 response.mustcontain(file_changes)
259 response.mustcontain(file_changes)
@@ -1,548 +1,548 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import datetime
21 import datetime
22 import pytest
22 import pytest
23
23
24 from rhodecode.lib.vcs.nodes import FileNode
24 from rhodecode.lib.vcs.nodes import FileNode
25 from rhodecode.tests.vcs.conftest import BackendTestMixin
25 from rhodecode.tests.vcs.conftest import BackendTestMixin
26
26
27
27
28 class TestGetDiffValidation:
28 class TestGetDiffValidation:
29
29
30 def test_raises_on_string_input(self, vcsbackend):
30 def test_raises_on_string_input(self, vcsbackend):
31 repo = vcsbackend.repo
31 repo = vcsbackend.repo
32 with pytest.raises(TypeError):
32 with pytest.raises(TypeError):
33 repo.get_diff("1", "2")
33 repo.get_diff("1", "2")
34
34
35 def test_raises_if_commits_not_of_this_repository(self, vcsbackend):
35 def test_raises_if_commits_not_of_this_repository(self, vcsbackend):
36 repo = vcsbackend.repo
36 repo = vcsbackend.repo
37 target_repo = vcsbackend.create_repo(number_of_commits=1)
37 target_repo = vcsbackend.create_repo(number_of_commits=1)
38 repo_commit = repo[0]
38 repo_commit = repo[0]
39 wrong_commit = target_repo[0]
39 wrong_commit = target_repo[0]
40 with pytest.raises(ValueError):
40 with pytest.raises(ValueError):
41 repo.get_diff(repo_commit, wrong_commit)
41 repo.get_diff(repo_commit, wrong_commit)
42
42
43 def test_allows_empty_commit(self, vcsbackend):
43 def test_allows_empty_commit(self, vcsbackend):
44 repo = vcsbackend.repo
44 repo = vcsbackend.repo
45 commit = repo[0]
45 commit = repo[0]
46 repo.get_diff(repo.EMPTY_COMMIT, commit)
46 repo.get_diff(repo.EMPTY_COMMIT, commit)
47
47
48 def test_raise_if_both_commits_are_empty(self, vcsbackend):
48 def test_raise_if_both_commits_are_empty(self, vcsbackend):
49 repo = vcsbackend.repo
49 repo = vcsbackend.repo
50 empty_commit = repo.EMPTY_COMMIT
50 empty_commit = repo.EMPTY_COMMIT
51 with pytest.raises(ValueError):
51 with pytest.raises(ValueError):
52 repo.get_diff(empty_commit, empty_commit)
52 repo.get_diff(empty_commit, empty_commit)
53
53
54 def test_supports_path1_parameter(self, vcsbackend):
54 def test_supports_path1_parameter(self, vcsbackend):
55 repo = vcsbackend.repo
55 repo = vcsbackend.repo
56 commit = repo[1]
56 commit = repo[1]
57 repo.get_diff(
57 repo.get_diff(
58 repo.EMPTY_COMMIT, commit,
58 repo.EMPTY_COMMIT, commit,
59 path='vcs/__init__.py', path1='vcs/__init__.py')
59 path='vcs/__init__.py', path1='vcs/__init__.py')
60
60
61 @pytest.mark.backends("git", "hg")
61 @pytest.mark.backends("git", "hg")
62 def test_raises_value_error_if_paths_not_supported(self, vcsbackend):
62 def test_raises_value_error_if_paths_not_supported(self, vcsbackend):
63 repo = vcsbackend.repo
63 repo = vcsbackend.repo
64 commit = repo[1]
64 commit = repo[1]
65 with pytest.raises(ValueError):
65 with pytest.raises(ValueError):
66 repo.get_diff(
66 repo.get_diff(
67 repo.EMPTY_COMMIT, commit,
67 repo.EMPTY_COMMIT, commit,
68 path='trunk/example.py', path1='branches/argparse/example.py')
68 path='trunk/example.py', path1='branches/argparse/example.py')
69
69
70
70
71 @pytest.mark.usefixtures("vcs_repository_support")
71 @pytest.mark.usefixtures("vcs_repository_support")
72 class TestRepositoryGetDiff(BackendTestMixin):
72 class TestRepositoryGetDiff(BackendTestMixin):
73
73
74 recreate_repo_per_test = False
74 recreate_repo_per_test = False
75
75
76 @classmethod
76 @classmethod
77 def _get_commits(cls):
77 def _get_commits(cls):
78 commits = [
78 commits = [
79 {
79 {
80 'message': 'Initial commit',
80 'message': 'Initial commit',
81 'author': 'Joe Doe <joe.doe@example.com>',
81 'author': 'Joe Doe <joe.doe@example.com>',
82 'date': datetime.datetime(2010, 1, 1, 20),
82 'date': datetime.datetime(2010, 1, 1, 20),
83 'added': [
83 'added': [
84 FileNode('foobar', content='foobar'),
84 FileNode('foobar', content='foobar'),
85 FileNode('foobar2', content='foobar2'),
85 FileNode('foobar2', content='foobar2'),
86 ],
86 ],
87 },
87 },
88 {
88 {
89 'message': 'Changed foobar, added foobar3',
89 'message': 'Changed foobar, added foobar3',
90 'author': 'Jane Doe <jane.doe@example.com>',
90 'author': 'Jane Doe <jane.doe@example.com>',
91 'date': datetime.datetime(2010, 1, 1, 21),
91 'date': datetime.datetime(2010, 1, 1, 21),
92 'added': [
92 'added': [
93 FileNode('foobar3', content='foobar3'),
93 FileNode('foobar3', content='foobar3'),
94 ],
94 ],
95 'changed': [
95 'changed': [
96 FileNode('foobar', 'FOOBAR'),
96 FileNode('foobar', 'FOOBAR'),
97 ],
97 ],
98 },
98 },
99 {
99 {
100 'message': 'Removed foobar, changed foobar3',
100 'message': 'Removed foobar, changed foobar3',
101 'author': 'Jane Doe <jane.doe@example.com>',
101 'author': 'Jane Doe <jane.doe@example.com>',
102 'date': datetime.datetime(2010, 1, 1, 22),
102 'date': datetime.datetime(2010, 1, 1, 22),
103 'changed': [
103 'changed': [
104 FileNode('foobar3', content='FOOBAR\nFOOBAR\nFOOBAR\n'),
104 FileNode('foobar3', content='FOOBAR\nFOOBAR\nFOOBAR\n'),
105 ],
105 ],
106 'removed': [FileNode('foobar')],
106 'removed': [FileNode('foobar')],
107 },
107 },
108 {
108 {
109 'message': 'Whitespace changes',
109 'message': 'Whitespace changes',
110 'author': 'Jane Doe <jane.doe@example.com>',
110 'author': 'Jane Doe <jane.doe@example.com>',
111 'date': datetime.datetime(2010, 1, 1, 23),
111 'date': datetime.datetime(2010, 1, 1, 23),
112 'changed': [
112 'changed': [
113 FileNode('foobar3', content='FOOBAR \nFOOBAR\nFOOBAR\n'),
113 FileNode('foobar3', content='FOOBAR \nFOOBAR\nFOOBAR\n'),
114 ],
114 ],
115 },
115 },
116 ]
116 ]
117 return commits
117 return commits
118
118
119 def test_initial_commit_diff(self):
119 def test_initial_commit_diff(self):
120 initial_commit = self.repo[0]
120 initial_commit = self.repo[0]
121 diff = self.repo.get_diff(self.repo.EMPTY_COMMIT, initial_commit)
121 diff = self.repo.get_diff(self.repo.EMPTY_COMMIT, initial_commit)
122 assert diff.raw == self.first_commit_diffs[self.repo.alias]
122 assert diff.raw == self.first_commit_diffs[self.repo.alias]
123
123
124 def test_second_commit_diff(self):
124 def test_second_commit_diff(self):
125 diff = self.repo.get_diff(self.repo[0], self.repo[1])
125 diff = self.repo.get_diff(self.repo[0], self.repo[1])
126 assert diff.raw == self.second_commit_diffs[self.repo.alias]
126 assert diff.raw == self.second_commit_diffs[self.repo.alias]
127
127
128 def test_third_commit_diff(self):
128 def test_third_commit_diff(self):
129 diff = self.repo.get_diff(self.repo[1], self.repo[2])
129 diff = self.repo.get_diff(self.repo[1], self.repo[2])
130 assert diff.raw == self.third_commit_diffs[self.repo.alias]
130 assert diff.raw == self.third_commit_diffs[self.repo.alias]
131
131
132 def test_ignore_whitespace(self):
132 def test_ignore_whitespace(self):
133 diff = self.repo.get_diff(
133 diff = self.repo.get_diff(
134 self.repo[2], self.repo[3], ignore_whitespace=True)
134 self.repo[2], self.repo[3], ignore_whitespace=True)
135 assert '@@' not in diff.raw
135 assert '@@' not in diff.raw
136
136
137 def test_only_one_file(self):
137 def test_only_one_file(self):
138 diff = self.repo.get_diff(
138 diff = self.repo.get_diff(
139 self.repo.EMPTY_COMMIT, self.repo[0], path='foobar')
139 self.repo.EMPTY_COMMIT, self.repo[0], path='foobar')
140 assert 'foobar2' not in diff.raw
140 assert 'foobar2' not in diff.raw
141
141
142 def test_context_parameter(self):
142 def test_context_parameter(self):
143 first_commit = self.repo.get_commit(commit_idx=0)
143 first_commit = self.repo.get_commit(commit_idx=0)
144 diff = self.repo.get_diff(
144 diff = self.repo.get_diff(
145 self.repo.EMPTY_COMMIT, first_commit, context=2)
145 self.repo.EMPTY_COMMIT, first_commit, context=2)
146 assert diff.raw == self.first_commit_diffs[self.repo.alias]
146 assert diff.raw == self.first_commit_diffs[self.repo.alias]
147
147
148 def test_context_only_one_file(self):
148 def test_context_only_one_file(self):
149 diff = self.repo.get_diff(
149 diff = self.repo.get_diff(
150 self.repo.EMPTY_COMMIT, self.repo[0], path='foobar', context=2)
150 self.repo.EMPTY_COMMIT, self.repo[0], path='foobar', context=2)
151 assert diff.raw == self.first_commit_one_file[self.repo.alias]
151 assert diff.raw == self.first_commit_one_file[self.repo.alias]
152
152
153 first_commit_diffs = {
153 first_commit_diffs = {
154 'git': r"""diff --git a/foobar b/foobar
154 'git': r"""diff --git a/foobar b/foobar
155 new file mode 100644
155 new file mode 100644
156 index 0000000000000000000000000000000000000000..f6ea0495187600e7b2288c8ac19c5886383a4632
156 index 0000000..f6ea049
157 --- /dev/null
157 --- /dev/null
158 +++ b/foobar
158 +++ b/foobar
159 @@ -0,0 +1 @@
159 @@ -0,0 +1 @@
160 +foobar
160 +foobar
161 \ No newline at end of file
161 \ No newline at end of file
162 diff --git a/foobar2 b/foobar2
162 diff --git a/foobar2 b/foobar2
163 new file mode 100644
163 new file mode 100644
164 index 0000000000000000000000000000000000000000..e8c9d6b98e3dce993a464935e1a53f50b56a3783
164 index 0000000..e8c9d6b
165 --- /dev/null
165 --- /dev/null
166 +++ b/foobar2
166 +++ b/foobar2
167 @@ -0,0 +1 @@
167 @@ -0,0 +1 @@
168 +foobar2
168 +foobar2
169 \ No newline at end of file
169 \ No newline at end of file
170 """,
170 """,
171 'hg': r"""diff --git a/foobar b/foobar
171 'hg': r"""diff --git a/foobar b/foobar
172 new file mode 100644
172 new file mode 100644
173 --- /dev/null
173 --- /dev/null
174 +++ b/foobar
174 +++ b/foobar
175 @@ -0,0 +1,1 @@
175 @@ -0,0 +1,1 @@
176 +foobar
176 +foobar
177 \ No newline at end of file
177 \ No newline at end of file
178 diff --git a/foobar2 b/foobar2
178 diff --git a/foobar2 b/foobar2
179 new file mode 100644
179 new file mode 100644
180 --- /dev/null
180 --- /dev/null
181 +++ b/foobar2
181 +++ b/foobar2
182 @@ -0,0 +1,1 @@
182 @@ -0,0 +1,1 @@
183 +foobar2
183 +foobar2
184 \ No newline at end of file
184 \ No newline at end of file
185 """,
185 """,
186 'svn': """Index: foobar
186 'svn': """Index: foobar
187 ===================================================================
187 ===================================================================
188 diff --git a/foobar b/foobar
188 diff --git a/foobar b/foobar
189 new file mode 10644
189 new file mode 10644
190 --- /dev/null\t(revision 0)
190 --- /dev/null\t(revision 0)
191 +++ b/foobar\t(revision 1)
191 +++ b/foobar\t(revision 1)
192 @@ -0,0 +1 @@
192 @@ -0,0 +1 @@
193 +foobar
193 +foobar
194 \\ No newline at end of file
194 \\ No newline at end of file
195 Index: foobar2
195 Index: foobar2
196 ===================================================================
196 ===================================================================
197 diff --git a/foobar2 b/foobar2
197 diff --git a/foobar2 b/foobar2
198 new file mode 10644
198 new file mode 10644
199 --- /dev/null\t(revision 0)
199 --- /dev/null\t(revision 0)
200 +++ b/foobar2\t(revision 1)
200 +++ b/foobar2\t(revision 1)
201 @@ -0,0 +1 @@
201 @@ -0,0 +1 @@
202 +foobar2
202 +foobar2
203 \\ No newline at end of file
203 \\ No newline at end of file
204 """,
204 """,
205 }
205 }
206
206
207 second_commit_diffs = {
207 second_commit_diffs = {
208 'git': r"""diff --git a/foobar b/foobar
208 'git': r"""diff --git a/foobar b/foobar
209 index f6ea0495187600e7b2288c8ac19c5886383a4632..389865bb681b358c9b102d79abd8d5f941e96551 100644
209 index f6ea049..389865b 100644
210 --- a/foobar
210 --- a/foobar
211 +++ b/foobar
211 +++ b/foobar
212 @@ -1 +1 @@
212 @@ -1 +1 @@
213 -foobar
213 -foobar
214 \ No newline at end of file
214 \ No newline at end of file
215 +FOOBAR
215 +FOOBAR
216 \ No newline at end of file
216 \ No newline at end of file
217 diff --git a/foobar3 b/foobar3
217 diff --git a/foobar3 b/foobar3
218 new file mode 100644
218 new file mode 100644
219 index 0000000000000000000000000000000000000000..c11c37d41d33fb47741cff93fa5f9d798c1535b0
219 index 0000000..c11c37d
220 --- /dev/null
220 --- /dev/null
221 +++ b/foobar3
221 +++ b/foobar3
222 @@ -0,0 +1 @@
222 @@ -0,0 +1 @@
223 +foobar3
223 +foobar3
224 \ No newline at end of file
224 \ No newline at end of file
225 """,
225 """,
226 'hg': r"""diff --git a/foobar b/foobar
226 'hg': r"""diff --git a/foobar b/foobar
227 --- a/foobar
227 --- a/foobar
228 +++ b/foobar
228 +++ b/foobar
229 @@ -1,1 +1,1 @@
229 @@ -1,1 +1,1 @@
230 -foobar
230 -foobar
231 \ No newline at end of file
231 \ No newline at end of file
232 +FOOBAR
232 +FOOBAR
233 \ No newline at end of file
233 \ No newline at end of file
234 diff --git a/foobar3 b/foobar3
234 diff --git a/foobar3 b/foobar3
235 new file mode 100644
235 new file mode 100644
236 --- /dev/null
236 --- /dev/null
237 +++ b/foobar3
237 +++ b/foobar3
238 @@ -0,0 +1,1 @@
238 @@ -0,0 +1,1 @@
239 +foobar3
239 +foobar3
240 \ No newline at end of file
240 \ No newline at end of file
241 """,
241 """,
242 'svn': """Index: foobar
242 'svn': """Index: foobar
243 ===================================================================
243 ===================================================================
244 diff --git a/foobar b/foobar
244 diff --git a/foobar b/foobar
245 --- a/foobar\t(revision 1)
245 --- a/foobar\t(revision 1)
246 +++ b/foobar\t(revision 2)
246 +++ b/foobar\t(revision 2)
247 @@ -1 +1 @@
247 @@ -1 +1 @@
248 -foobar
248 -foobar
249 \\ No newline at end of file
249 \\ No newline at end of file
250 +FOOBAR
250 +FOOBAR
251 \\ No newline at end of file
251 \\ No newline at end of file
252 Index: foobar3
252 Index: foobar3
253 ===================================================================
253 ===================================================================
254 diff --git a/foobar3 b/foobar3
254 diff --git a/foobar3 b/foobar3
255 new file mode 10644
255 new file mode 10644
256 --- /dev/null\t(revision 0)
256 --- /dev/null\t(revision 0)
257 +++ b/foobar3\t(revision 2)
257 +++ b/foobar3\t(revision 2)
258 @@ -0,0 +1 @@
258 @@ -0,0 +1 @@
259 +foobar3
259 +foobar3
260 \\ No newline at end of file
260 \\ No newline at end of file
261 """,
261 """,
262 }
262 }
263
263
264 third_commit_diffs = {
264 third_commit_diffs = {
265 'git': r"""diff --git a/foobar b/foobar
265 'git': r"""diff --git a/foobar b/foobar
266 deleted file mode 100644
266 deleted file mode 100644
267 index 389865bb681b358c9b102d79abd8d5f941e96551..0000000000000000000000000000000000000000
267 index 389865b..0000000
268 --- a/foobar
268 --- a/foobar
269 +++ /dev/null
269 +++ /dev/null
270 @@ -1 +0,0 @@
270 @@ -1 +0,0 @@
271 -FOOBAR
271 -FOOBAR
272 \ No newline at end of file
272 \ No newline at end of file
273 diff --git a/foobar3 b/foobar3
273 diff --git a/foobar3 b/foobar3
274 index c11c37d41d33fb47741cff93fa5f9d798c1535b0..f9324477362684ff692aaf5b9a81e01b9e9a671c 100644
274 index c11c37d..f932447 100644
275 --- a/foobar3
275 --- a/foobar3
276 +++ b/foobar3
276 +++ b/foobar3
277 @@ -1 +1,3 @@
277 @@ -1 +1,3 @@
278 -foobar3
278 -foobar3
279 \ No newline at end of file
279 \ No newline at end of file
280 +FOOBAR
280 +FOOBAR
281 +FOOBAR
281 +FOOBAR
282 +FOOBAR
282 +FOOBAR
283 """,
283 """,
284 'hg': r"""diff --git a/foobar b/foobar
284 'hg': r"""diff --git a/foobar b/foobar
285 deleted file mode 100644
285 deleted file mode 100644
286 --- a/foobar
286 --- a/foobar
287 +++ /dev/null
287 +++ /dev/null
288 @@ -1,1 +0,0 @@
288 @@ -1,1 +0,0 @@
289 -FOOBAR
289 -FOOBAR
290 \ No newline at end of file
290 \ No newline at end of file
291 diff --git a/foobar3 b/foobar3
291 diff --git a/foobar3 b/foobar3
292 --- a/foobar3
292 --- a/foobar3
293 +++ b/foobar3
293 +++ b/foobar3
294 @@ -1,1 +1,3 @@
294 @@ -1,1 +1,3 @@
295 -foobar3
295 -foobar3
296 \ No newline at end of file
296 \ No newline at end of file
297 +FOOBAR
297 +FOOBAR
298 +FOOBAR
298 +FOOBAR
299 +FOOBAR
299 +FOOBAR
300 """,
300 """,
301 'svn': """Index: foobar
301 'svn': """Index: foobar
302 ===================================================================
302 ===================================================================
303 diff --git a/foobar b/foobar
303 diff --git a/foobar b/foobar
304 deleted file mode 10644
304 deleted file mode 10644
305 --- a/foobar\t(revision 2)
305 --- a/foobar\t(revision 2)
306 +++ /dev/null\t(revision 3)
306 +++ /dev/null\t(revision 3)
307 @@ -1 +0,0 @@
307 @@ -1 +0,0 @@
308 -FOOBAR
308 -FOOBAR
309 \\ No newline at end of file
309 \\ No newline at end of file
310 Index: foobar3
310 Index: foobar3
311 ===================================================================
311 ===================================================================
312 diff --git a/foobar3 b/foobar3
312 diff --git a/foobar3 b/foobar3
313 --- a/foobar3\t(revision 2)
313 --- a/foobar3\t(revision 2)
314 +++ b/foobar3\t(revision 3)
314 +++ b/foobar3\t(revision 3)
315 @@ -1 +1,3 @@
315 @@ -1 +1,3 @@
316 -foobar3
316 -foobar3
317 \\ No newline at end of file
317 \\ No newline at end of file
318 +FOOBAR
318 +FOOBAR
319 +FOOBAR
319 +FOOBAR
320 +FOOBAR
320 +FOOBAR
321 """,
321 """,
322 }
322 }
323
323
324 first_commit_one_file = {
324 first_commit_one_file = {
325 'git': r"""diff --git a/foobar b/foobar
325 'git': r"""diff --git a/foobar b/foobar
326 new file mode 100644
326 new file mode 100644
327 index 0000000000000000000000000000000000000000..f6ea0495187600e7b2288c8ac19c5886383a4632
327 index 0000000..f6ea049
328 --- /dev/null
328 --- /dev/null
329 +++ b/foobar
329 +++ b/foobar
330 @@ -0,0 +1 @@
330 @@ -0,0 +1 @@
331 +foobar
331 +foobar
332 \ No newline at end of file
332 \ No newline at end of file
333 """,
333 """,
334 'hg': r"""diff --git a/foobar b/foobar
334 'hg': r"""diff --git a/foobar b/foobar
335 new file mode 100644
335 new file mode 100644
336 --- /dev/null
336 --- /dev/null
337 +++ b/foobar
337 +++ b/foobar
338 @@ -0,0 +1,1 @@
338 @@ -0,0 +1,1 @@
339 +foobar
339 +foobar
340 \ No newline at end of file
340 \ No newline at end of file
341 """,
341 """,
342 'svn': """Index: foobar
342 'svn': """Index: foobar
343 ===================================================================
343 ===================================================================
344 diff --git a/foobar b/foobar
344 diff --git a/foobar b/foobar
345 new file mode 10644
345 new file mode 10644
346 --- /dev/null\t(revision 0)
346 --- /dev/null\t(revision 0)
347 +++ b/foobar\t(revision 1)
347 +++ b/foobar\t(revision 1)
348 @@ -0,0 +1 @@
348 @@ -0,0 +1 @@
349 +foobar
349 +foobar
350 \\ No newline at end of file
350 \\ No newline at end of file
351 """,
351 """,
352 }
352 }
353
353
354
354
355 class TestSvnGetDiff:
355 class TestSvnGetDiff(object):
356
356
357 @pytest.mark.parametrize('path, path1', [
357 @pytest.mark.parametrize('path, path1', [
358 ('trunk/example.py', 'tags/v0.2/example.py'),
358 ('trunk/example.py', 'tags/v0.2/example.py'),
359 ('trunk', 'tags/v0.2')
359 ('trunk', 'tags/v0.2')
360 ], ids=['file', 'dir'])
360 ], ids=['file', 'dir'])
361 def test_diff_to_tagged_version(self, vcsbackend_svn, path, path1):
361 def test_diff_to_tagged_version(self, vcsbackend_svn, path, path1):
362 repo = vcsbackend_svn['svn-simple-layout']
362 repo = vcsbackend_svn['svn-simple-layout']
363 commit1 = repo[-2]
363 commit1 = repo[-2]
364 commit2 = repo[-1]
364 commit2 = repo[-1]
365 diff = repo.get_diff(commit1, commit2, path=path, path1=path1)
365 diff = repo.get_diff(commit1, commit2, path=path, path1=path1)
366 assert diff.raw == self.expected_diff_v_0_2
366 assert diff.raw == self.expected_diff_v_0_2
367
367
368 expected_diff_v_0_2 = '''Index: example.py
368 expected_diff_v_0_2 = '''Index: example.py
369 ===================================================================
369 ===================================================================
370 diff --git a/example.py b/example.py
370 diff --git a/example.py b/example.py
371 --- a/example.py\t(revision 25)
371 --- a/example.py\t(revision 25)
372 +++ b/example.py\t(revision 26)
372 +++ b/example.py\t(revision 26)
373 @@ -7,8 +7,12 @@
373 @@ -7,8 +7,12 @@
374
374
375 @click.command()
375 @click.command()
376 def main():
376 def main():
377 + """
377 + """
378 + Will print out a useful message on invocation.
378 + Will print out a useful message on invocation.
379 + """
379 + """
380 click.echo("Hello world!")
380 click.echo("Hello world!")
381
381
382
382
383 +# Main entry point
383 +# Main entry point
384 if __name__ == '__main__':
384 if __name__ == '__main__':
385 main()
385 main()
386 '''
386 '''
387
387
388 def test_diff_of_moved_directory(self, vcsbackend_svn):
388 def test_diff_of_moved_directory(self, vcsbackend_svn):
389 repo = vcsbackend_svn['svn-move-directory']
389 repo = vcsbackend_svn['svn-move-directory']
390 diff = repo.get_diff(repo[0], repo[1])
390 diff = repo.get_diff(repo[0], repo[1])
391 # TODO: johbo: Think about supporting svn directory nodes
391 # TODO: johbo: Think about supporting svn directory nodes
392 # a little bit better, source is here like a file
392 # a little bit better, source is here like a file
393 expected_diff = """Index: source
393 expected_diff = """Index: source
394 ===================================================================
394 ===================================================================
395 diff --git a/source b/source
395 diff --git a/source b/source
396 deleted file mode 10644
396 deleted file mode 10644
397 --- a/source\t(revision 1)
397 --- a/source\t(revision 1)
398 +++ /dev/null\t(revision 2)
398 +++ /dev/null\t(revision 2)
399 Index: target/file
399 Index: target/file
400 ===================================================================
400 ===================================================================
401 diff --git a/target/file b/target/file
401 diff --git a/target/file b/target/file
402 new file mode 10644
402 new file mode 10644
403 --- /dev/null\t(revision 0)
403 --- /dev/null\t(revision 0)
404 +++ b/target/file\t(revision 2)
404 +++ b/target/file\t(revision 2)
405 """
405 """
406 assert diff.raw == expected_diff
406 assert diff.raw == expected_diff
407
407
408
408
409 @pytest.mark.usefixtures("vcs_repository_support")
409 @pytest.mark.usefixtures("vcs_repository_support")
410 class TestGetDiffBinary(BackendTestMixin):
410 class TestGetDiffBinary(BackendTestMixin):
411
411
412 recreate_repo_per_test = False
412 recreate_repo_per_test = False
413
413
414 # Note: "Fake" PNG files, has the correct magic as prefix
414 # Note: "Fake" PNG files, has the correct magic as prefix
415 BINARY = """\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00"""
415 BINARY = """\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00"""
416 BINARY2 = """\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x01\x00\x00"""
416 BINARY2 = """\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x01\x00\x00"""
417
417
418 @staticmethod
418 @staticmethod
419 def _get_commits():
419 def _get_commits():
420 commits = [
420 commits = [
421 {
421 {
422 'message': 'Add binary file image.png',
422 'message': 'Add binary file image.png',
423 'author': 'Joe Doe <joe.deo@example.com>',
423 'author': 'Joe Doe <joe.deo@example.com>',
424 'date': datetime.datetime(2010, 1, 1, 20),
424 'date': datetime.datetime(2010, 1, 1, 20),
425 'added': [
425 'added': [
426 FileNode('image.png', content=TestGetDiffBinary.BINARY),
426 FileNode('image.png', content=TestGetDiffBinary.BINARY),
427 ]},
427 ]},
428 {
428 {
429 'message': 'Modify image.png',
429 'message': 'Modify image.png',
430 'author': 'Joe Doe <joe.deo@example.com>',
430 'author': 'Joe Doe <joe.deo@example.com>',
431 'date': datetime.datetime(2010, 1, 1, 21),
431 'date': datetime.datetime(2010, 1, 1, 21),
432 'changed': [
432 'changed': [
433 FileNode('image.png', content=TestGetDiffBinary.BINARY2),
433 FileNode('image.png', content=TestGetDiffBinary.BINARY2),
434 ]},
434 ]},
435 {
435 {
436 'message': 'Remove image.png',
436 'message': 'Remove image.png',
437 'author': 'Joe Doe <joe.deo@example.com>',
437 'author': 'Joe Doe <joe.deo@example.com>',
438 'date': datetime.datetime(2010, 1, 1, 21),
438 'date': datetime.datetime(2010, 1, 1, 21),
439 'removed': [
439 'removed': [
440 FileNode('image.png'),
440 FileNode('image.png'),
441 ]},
441 ]},
442 ]
442 ]
443 return commits
443 return commits
444
444
445 def test_add_a_binary_file(self):
445 def test_add_a_binary_file(self):
446 diff = self.repo.get_diff(self.repo.EMPTY_COMMIT, self.repo[0])
446 diff = self.repo.get_diff(self.repo.EMPTY_COMMIT, self.repo[0])
447
447
448 expected = {
448 expected = {
449 'git': """diff --git a/image.png b/image.png
449 'git': """diff --git a/image.png b/image.png
450 new file mode 100644
450 new file mode 100644
451 index 0000000000000000000000000000000000000000..28380fd4a25c58be1b68b523ba2a314f4459ee9c
451 index 0000000000000000000000000000000000000000..28380fd4a25c58be1b68b523ba2a314f4459ee9c
452 GIT binary patch
452 GIT binary patch
453 literal 19
453 literal 19
454 YcmeAS@N?(olHy`uVBq!ia0vp^03%2O-T(jq
454 Yc%17D@N?(olHy`uVBq!ia0vp^03%2O-T(jq
455
455
456 literal 0
456 literal 0
457 HcmV?d00001
457 Hc$@<O00001
458
458
459 """,
459 """,
460 'hg': """diff --git a/image.png b/image.png
460 'hg': """diff --git a/image.png b/image.png
461 new file mode 100644
461 new file mode 100644
462 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..28380fd4a25c58be1b68b523ba2a314f4459ee9c
462 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..28380fd4a25c58be1b68b523ba2a314f4459ee9c
463 GIT binary patch
463 GIT binary patch
464 literal 19
464 literal 19
465 Yc%17D@N?(olHy`uVBq!ia0vp^03%2O-T(jq
465 Yc%17D@N?(olHy`uVBq!ia0vp^03%2O-T(jq
466
466
467 """,
467 """,
468 'svn': """===================================================================
468 'svn': """===================================================================
469 Cannot display: file marked as a binary type.
469 Cannot display: file marked as a binary type.
470 svn:mime-type = application/octet-stream
470 svn:mime-type = application/octet-stream
471 Index: image.png
471 Index: image.png
472 ===================================================================
472 ===================================================================
473 diff --git a/image.png b/image.png
473 diff --git a/image.png b/image.png
474 new file mode 10644
474 new file mode 10644
475 --- /dev/null\t(revision 0)
475 --- /dev/null\t(revision 0)
476 +++ b/image.png\t(revision 1)
476 +++ b/image.png\t(revision 1)
477 """,
477 """,
478 }
478 }
479 assert diff.raw == expected[self.repo.alias]
479 assert diff.raw == expected[self.repo.alias]
480
480
481 def test_update_a_binary_file(self):
481 def test_update_a_binary_file(self):
482 diff = self.repo.get_diff(self.repo[0], self.repo[1])
482 diff = self.repo.get_diff(self.repo[0], self.repo[1])
483
483
484 expected = {
484 expected = {
485 'git': """diff --git a/image.png b/image.png
485 'git': """diff --git a/image.png b/image.png
486 index 28380fd4a25c58be1b68b523ba2a314f4459ee9c..1008a77cd372386a1c24fbd96019333f67ad0065 100644
486 index 28380fd4a25c58be1b68b523ba2a314f4459ee9c..1008a77cd372386a1c24fbd96019333f67ad0065 100644
487 GIT binary patch
487 GIT binary patch
488 literal 19
488 literal 19
489 acmeAS@N?(olHy`uVBq!ia0y~$U;qFkO9I~j
489 ac%17D@N?(olHy`uVBq!ia0y~$U;qFkO9I~j
490
490
491 literal 19
491 literal 19
492 YcmeAS@N?(olHy`uVBq!ia0vp^03%2O-T(jq
492 Yc%17D@N?(olHy`uVBq!ia0vp^03%2O-T(jq
493
493
494 """,
494 """,
495 'hg': """diff --git a/image.png b/image.png
495 'hg': """diff --git a/image.png b/image.png
496 index 28380fd4a25c58be1b68b523ba2a314f4459ee9c..1008a77cd372386a1c24fbd96019333f67ad0065
496 index 28380fd4a25c58be1b68b523ba2a314f4459ee9c..1008a77cd372386a1c24fbd96019333f67ad0065
497 GIT binary patch
497 GIT binary patch
498 literal 19
498 literal 19
499 ac%17D@N?(olHy`uVBq!ia0y~$U;qFkO9I~j
499 ac%17D@N?(olHy`uVBq!ia0y~$U;qFkO9I~j
500
500
501 """,
501 """,
502 'svn': """===================================================================
502 'svn': """===================================================================
503 Cannot display: file marked as a binary type.
503 Cannot display: file marked as a binary type.
504 svn:mime-type = application/octet-stream
504 svn:mime-type = application/octet-stream
505 Index: image.png
505 Index: image.png
506 ===================================================================
506 ===================================================================
507 diff --git a/image.png b/image.png
507 diff --git a/image.png b/image.png
508 --- a/image.png\t(revision 1)
508 --- a/image.png\t(revision 1)
509 +++ b/image.png\t(revision 2)
509 +++ b/image.png\t(revision 2)
510 """,
510 """,
511 }
511 }
512 assert diff.raw == expected[self.repo.alias]
512 assert diff.raw == expected[self.repo.alias]
513
513
514 def test_remove_a_binary_file(self):
514 def test_remove_a_binary_file(self):
515 diff = self.repo.get_diff(self.repo[1], self.repo[2])
515 diff = self.repo.get_diff(self.repo[1], self.repo[2])
516
516
517 expected = {
517 expected = {
518 'git': """diff --git a/image.png b/image.png
518 'git': """diff --git a/image.png b/image.png
519 deleted file mode 100644
519 deleted file mode 100644
520 index 1008a77cd372386a1c24fbd96019333f67ad0065..0000000000000000000000000000000000000000
520 index 1008a77cd372386a1c24fbd96019333f67ad0065..0000000000000000000000000000000000000000
521 GIT binary patch
521 GIT binary patch
522 literal 0
522 literal 0
523 HcmV?d00001
523 Hc$@<O00001
524
524
525 literal 19
525 literal 19
526 acmeAS@N?(olHy`uVBq!ia0y~$U;qFkO9I~j
526 ac%17D@N?(olHy`uVBq!ia0y~$U;qFkO9I~j
527
527
528 """,
528 """,
529 'hg': """diff --git a/image.png b/image.png
529 'hg': """diff --git a/image.png b/image.png
530 deleted file mode 100644
530 deleted file mode 100644
531 index 1008a77cd372386a1c24fbd96019333f67ad0065..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
531 index 1008a77cd372386a1c24fbd96019333f67ad0065..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
532 GIT binary patch
532 GIT binary patch
533 literal 0
533 literal 0
534 Hc$@<O00001
534 Hc$@<O00001
535
535
536 """,
536 """,
537 'svn': """===================================================================
537 'svn': """===================================================================
538 Cannot display: file marked as a binary type.
538 Cannot display: file marked as a binary type.
539 svn:mime-type = application/octet-stream
539 svn:mime-type = application/octet-stream
540 Index: image.png
540 Index: image.png
541 ===================================================================
541 ===================================================================
542 diff --git a/image.png b/image.png
542 diff --git a/image.png b/image.png
543 deleted file mode 10644
543 deleted file mode 10644
544 --- a/image.png\t(revision 2)
544 --- a/image.png\t(revision 2)
545 +++ /dev/null\t(revision 3)
545 +++ /dev/null\t(revision 3)
546 """,
546 """,
547 }
547 }
548 assert diff.raw == expected[self.repo.alias]
548 assert diff.raw == expected[self.repo.alias]
General Comments 0
You need to be logged in to leave comments. Login now