##// END OF EJS Templates
svn: date-parser should use UTC dates to be consistent with other backends.
marcink -
r1348:8875ec9d default
parent child Browse files
Show More
@@ -1,234 +1,236 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2014-2017 RhodeCode GmbH
3 # Copyright (C) 2014-2017 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 SVN commit module
22 SVN commit module
23 """
23 """
24
24
25
25
26 import dateutil.parser
26 import dateutil.parser
27 from zope.cachedescriptors.property import Lazy as LazyProperty
27 from zope.cachedescriptors.property import Lazy as LazyProperty
28
28
29 from rhodecode.lib.utils import safe_str, safe_unicode
29 from rhodecode.lib.utils import safe_str, safe_unicode
30 from rhodecode.lib.vcs import nodes, path as vcspath
30 from rhodecode.lib.vcs import nodes, path as vcspath
31 from rhodecode.lib.vcs.backends import base
31 from rhodecode.lib.vcs.backends import base
32 from rhodecode.lib.vcs.exceptions import CommitError, NodeDoesNotExistError
32 from rhodecode.lib.vcs.exceptions import CommitError, NodeDoesNotExistError
33
33
34
34
35 _SVN_PROP_TRUE = '*'
35 _SVN_PROP_TRUE = '*'
36
36
37
37
38 class SubversionCommit(base.BaseCommit):
38 class SubversionCommit(base.BaseCommit):
39 """
39 """
40 Subversion specific implementation of commits
40 Subversion specific implementation of commits
41
41
42 .. attribute:: branch
42 .. attribute:: branch
43
43
44 The Subversion backend does not support to assign branches to
44 The Subversion backend does not support to assign branches to
45 specific commits. This attribute has always the value `None`.
45 specific commits. This attribute has always the value `None`.
46
46
47 """
47 """
48
48
49 def __init__(self, repository, commit_id):
49 def __init__(self, repository, commit_id):
50 self.repository = repository
50 self.repository = repository
51 self.idx = self.repository._get_commit_idx(commit_id)
51 self.idx = self.repository._get_commit_idx(commit_id)
52 self._svn_rev = self.idx + 1
52 self._svn_rev = self.idx + 1
53 self._remote = repository._remote
53 self._remote = repository._remote
54 # TODO: handling of raw_id should be a method on repository itself,
54 # TODO: handling of raw_id should be a method on repository itself,
55 # which knows how to translate commit index and commit id
55 # which knows how to translate commit index and commit id
56 self.raw_id = commit_id
56 self.raw_id = commit_id
57 self.short_id = commit_id
57 self.short_id = commit_id
58 self.id = 'r%s' % (commit_id, )
58 self.id = 'r%s' % (commit_id, )
59
59
60 # TODO: Implement the following placeholder attributes
60 # TODO: Implement the following placeholder attributes
61 self.nodes = {}
61 self.nodes = {}
62 self.tags = []
62 self.tags = []
63
63
64 @property
64 @property
65 def author(self):
65 def author(self):
66 return safe_unicode(self._properties.get('svn:author'))
66 return safe_unicode(self._properties.get('svn:author'))
67
67
68 @property
68 @property
69 def date(self):
69 def date(self):
70 return _date_from_svn_properties(self._properties)
70 return _date_from_svn_properties(self._properties)
71
71
72 @property
72 @property
73 def message(self):
73 def message(self):
74 return safe_unicode(self._properties.get('svn:log'))
74 return safe_unicode(self._properties.get('svn:log'))
75
75
76 @LazyProperty
76 @LazyProperty
77 def _properties(self):
77 def _properties(self):
78 return self._remote.revision_properties(self._svn_rev)
78 return self._remote.revision_properties(self._svn_rev)
79
79
80 @LazyProperty
80 @LazyProperty
81 def parents(self):
81 def parents(self):
82 parent_idx = self.idx - 1
82 parent_idx = self.idx - 1
83 if parent_idx >= 0:
83 if parent_idx >= 0:
84 parent = self.repository.get_commit(commit_idx=parent_idx)
84 parent = self.repository.get_commit(commit_idx=parent_idx)
85 return [parent]
85 return [parent]
86 return []
86 return []
87
87
88 @LazyProperty
88 @LazyProperty
89 def children(self):
89 def children(self):
90 child_idx = self.idx + 1
90 child_idx = self.idx + 1
91 if child_idx < len(self.repository.commit_ids):
91 if child_idx < len(self.repository.commit_ids):
92 child = self.repository.get_commit(commit_idx=child_idx)
92 child = self.repository.get_commit(commit_idx=child_idx)
93 return [child]
93 return [child]
94 return []
94 return []
95
95
96 def get_file_mode(self, path):
96 def get_file_mode(self, path):
97 # Note: Subversion flags files which are executable with a special
97 # Note: Subversion flags files which are executable with a special
98 # property `svn:executable` which is set to the value ``"*"``.
98 # property `svn:executable` which is set to the value ``"*"``.
99 if self._get_file_property(path, 'svn:executable') == _SVN_PROP_TRUE:
99 if self._get_file_property(path, 'svn:executable') == _SVN_PROP_TRUE:
100 return base.FILEMODE_EXECUTABLE
100 return base.FILEMODE_EXECUTABLE
101 else:
101 else:
102 return base.FILEMODE_DEFAULT
102 return base.FILEMODE_DEFAULT
103
103
104 def is_link(self, path):
104 def is_link(self, path):
105 # Note: Subversion has a flag for special files, the content of the
105 # Note: Subversion has a flag for special files, the content of the
106 # file contains the type of that file.
106 # file contains the type of that file.
107 if self._get_file_property(path, 'svn:special') == _SVN_PROP_TRUE:
107 if self._get_file_property(path, 'svn:special') == _SVN_PROP_TRUE:
108 return self.get_file_content(path).startswith('link')
108 return self.get_file_content(path).startswith('link')
109 return False
109 return False
110
110
111 def _get_file_property(self, path, name):
111 def _get_file_property(self, path, name):
112 file_properties = self._remote.node_properties(
112 file_properties = self._remote.node_properties(
113 safe_str(path), self._svn_rev)
113 safe_str(path), self._svn_rev)
114 return file_properties.get(name)
114 return file_properties.get(name)
115
115
116 def get_file_content(self, path):
116 def get_file_content(self, path):
117 path = self._fix_path(path)
117 path = self._fix_path(path)
118 return self._remote.get_file_content(safe_str(path), self._svn_rev)
118 return self._remote.get_file_content(safe_str(path), self._svn_rev)
119
119
120 def get_file_size(self, path):
120 def get_file_size(self, path):
121 path = self._fix_path(path)
121 path = self._fix_path(path)
122 return self._remote.get_file_size(safe_str(path), self._svn_rev)
122 return self._remote.get_file_size(safe_str(path), self._svn_rev)
123
123
124 def get_file_history(self, path, limit=None, pre_load=None):
124 def get_file_history(self, path, limit=None, pre_load=None):
125 path = safe_str(self._fix_path(path))
125 path = safe_str(self._fix_path(path))
126 history = self._remote.node_history(path, self._svn_rev, limit)
126 history = self._remote.node_history(path, self._svn_rev, limit)
127 return [
127 return [
128 self.repository.get_commit(commit_id=str(svn_rev))
128 self.repository.get_commit(commit_id=str(svn_rev))
129 for svn_rev in history]
129 for svn_rev in history]
130
130
131 def get_file_annotate(self, path, pre_load=None):
131 def get_file_annotate(self, path, pre_load=None):
132 result = self._remote.file_annotate(safe_str(path), self._svn_rev)
132 result = self._remote.file_annotate(safe_str(path), self._svn_rev)
133
133
134 for zero_based_line_no, svn_rev, content in result:
134 for zero_based_line_no, svn_rev, content in result:
135 commit_id = str(svn_rev)
135 commit_id = str(svn_rev)
136 line_no = zero_based_line_no + 1
136 line_no = zero_based_line_no + 1
137 yield (
137 yield (
138 line_no,
138 line_no,
139 commit_id,
139 commit_id,
140 lambda: self.repository.get_commit(commit_id=commit_id),
140 lambda: self.repository.get_commit(commit_id=commit_id),
141 content)
141 content)
142
142
143 def get_node(self, path):
143 def get_node(self, path):
144 path = self._fix_path(path)
144 path = self._fix_path(path)
145 if path not in self.nodes:
145 if path not in self.nodes:
146
146
147 if path == '':
147 if path == '':
148 node = nodes.RootNode(commit=self)
148 node = nodes.RootNode(commit=self)
149 else:
149 else:
150 node_type = self._remote.get_node_type(
150 node_type = self._remote.get_node_type(
151 safe_str(path), self._svn_rev)
151 safe_str(path), self._svn_rev)
152 if node_type == 'dir':
152 if node_type == 'dir':
153 node = nodes.DirNode(path, commit=self)
153 node = nodes.DirNode(path, commit=self)
154 elif node_type == 'file':
154 elif node_type == 'file':
155 node = nodes.FileNode(path, commit=self)
155 node = nodes.FileNode(path, commit=self)
156 else:
156 else:
157 raise NodeDoesNotExistError(self.no_node_at_path(path))
157 raise NodeDoesNotExistError(self.no_node_at_path(path))
158
158
159 self.nodes[path] = node
159 self.nodes[path] = node
160 return self.nodes[path]
160 return self.nodes[path]
161
161
162 def get_nodes(self, path):
162 def get_nodes(self, path):
163 if self._get_kind(path) != nodes.NodeKind.DIR:
163 if self._get_kind(path) != nodes.NodeKind.DIR:
164 raise CommitError(
164 raise CommitError(
165 "Directory does not exist for commit %s at "
165 "Directory does not exist for commit %s at "
166 " '%s'" % (self.raw_id, path))
166 " '%s'" % (self.raw_id, path))
167 path = self._fix_path(path)
167 path = self._fix_path(path)
168
168
169 path_nodes = []
169 path_nodes = []
170 for name, kind in self._remote.get_nodes(
170 for name, kind in self._remote.get_nodes(
171 safe_str(path), revision=self._svn_rev):
171 safe_str(path), revision=self._svn_rev):
172 node_path = vcspath.join(path, name)
172 node_path = vcspath.join(path, name)
173 if kind == 'dir':
173 if kind == 'dir':
174 node = nodes.DirNode(node_path, commit=self)
174 node = nodes.DirNode(node_path, commit=self)
175 elif kind == 'file':
175 elif kind == 'file':
176 node = nodes.FileNode(node_path, commit=self)
176 node = nodes.FileNode(node_path, commit=self)
177 else:
177 else:
178 raise ValueError("Node kind %s not supported." % (kind, ))
178 raise ValueError("Node kind %s not supported." % (kind, ))
179 self.nodes[node_path] = node
179 self.nodes[node_path] = node
180 path_nodes.append(node)
180 path_nodes.append(node)
181
181
182 return path_nodes
182 return path_nodes
183
183
184 def _get_kind(self, path):
184 def _get_kind(self, path):
185 path = self._fix_path(path)
185 path = self._fix_path(path)
186 kind = self._remote.get_node_type(path, self._svn_rev)
186 kind = self._remote.get_node_type(path, self._svn_rev)
187 if kind == 'file':
187 if kind == 'file':
188 return nodes.NodeKind.FILE
188 return nodes.NodeKind.FILE
189 elif kind == 'dir':
189 elif kind == 'dir':
190 return nodes.NodeKind.DIR
190 return nodes.NodeKind.DIR
191 else:
191 else:
192 raise CommitError(
192 raise CommitError(
193 "Node does not exist at the given path '%s'" % (path, ))
193 "Node does not exist at the given path '%s'" % (path, ))
194
194
195 @LazyProperty
195 @LazyProperty
196 def _changes_cache(self):
196 def _changes_cache(self):
197 return self._remote.revision_changes(self._svn_rev)
197 return self._remote.revision_changes(self._svn_rev)
198
198
199 @LazyProperty
199 @LazyProperty
200 def affected_files(self):
200 def affected_files(self):
201 changed_files = set()
201 changed_files = set()
202 for files in self._changes_cache.itervalues():
202 for files in self._changes_cache.itervalues():
203 changed_files.update(files)
203 changed_files.update(files)
204 return list(changed_files)
204 return list(changed_files)
205
205
206 @LazyProperty
206 @LazyProperty
207 def id(self):
207 def id(self):
208 return self.raw_id
208 return self.raw_id
209
209
210 @property
210 @property
211 def added(self):
211 def added(self):
212 return nodes.AddedFileNodesGenerator(
212 return nodes.AddedFileNodesGenerator(
213 self._changes_cache['added'], self)
213 self._changes_cache['added'], self)
214
214
215 @property
215 @property
216 def changed(self):
216 def changed(self):
217 return nodes.ChangedFileNodesGenerator(
217 return nodes.ChangedFileNodesGenerator(
218 self._changes_cache['changed'], self)
218 self._changes_cache['changed'], self)
219
219
220 @property
220 @property
221 def removed(self):
221 def removed(self):
222 return nodes.RemovedFileNodesGenerator(
222 return nodes.RemovedFileNodesGenerator(
223 self._changes_cache['removed'], self)
223 self._changes_cache['removed'], self)
224
224
225
225
226 def _date_from_svn_properties(properties):
226 def _date_from_svn_properties(properties):
227 """
227 """
228 Parses the date out of given svn properties.
228 Parses the date out of given svn properties.
229
229
230 :return: :class:`datetime.datetime` instance. The object is naive.
230 :return: :class:`datetime.datetime` instance. The object is naive.
231 """
231 """
232
232 aware_date = dateutil.parser.parse(properties.get('svn:date'))
233 aware_date = dateutil.parser.parse(properties.get('svn:date'))
233 local_date = aware_date.astimezone(dateutil.tz.tzlocal())
234 # final_date = aware_date.astimezone(dateutil.tz.tzlocal())
234 return local_date.replace(tzinfo=None)
235 final_date = aware_date
236 return final_date.replace(tzinfo=None)
@@ -1,302 +1,301 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 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 from rhodecode.tests import url
24 from rhodecode.tests import url
25
25
26
26
27 @pytest.mark.usefixtures("app")
27 @pytest.mark.usefixtures("app")
28 class TestChangesetController(object):
28 class TestChangesetController(object):
29
29
30 def test_index(self, backend):
30 def test_index(self, backend):
31 commit_id = self.commit_id[backend.alias]
31 commit_id = self.commit_id[backend.alias]
32 response = self.app.get(url(
32 response = self.app.get(url(
33 controller='changeset', action='index',
33 controller='changeset', action='index',
34 repo_name=backend.repo_name, revision=commit_id))
34 repo_name=backend.repo_name, revision=commit_id))
35 response.mustcontain('Added a symlink')
35 response.mustcontain('Added a symlink')
36 response.mustcontain(commit_id)
36 response.mustcontain(commit_id)
37 response.mustcontain('No newline at end of file')
37 response.mustcontain('No newline at end of file')
38
38
39 def test_index_raw(self, backend):
39 def test_index_raw(self, backend):
40 commit_id = self.commit_id[backend.alias]
40 commit_id = self.commit_id[backend.alias]
41 response = self.app.get(url(
41 response = self.app.get(url(
42 controller='changeset', action='changeset_raw',
42 controller='changeset', action='changeset_raw',
43 repo_name=backend.repo_name, revision=commit_id))
43 repo_name=backend.repo_name, revision=commit_id))
44 assert response.body == self.diffs[backend.alias]
44 assert response.body == self.diffs[backend.alias]
45
45
46 def test_index_raw_patch(self, backend):
46 def test_index_raw_patch(self, backend):
47 response = self.app.get(url(
47 response = self.app.get(url(
48 controller='changeset', action='changeset_patch',
48 controller='changeset', action='changeset_patch',
49 repo_name=backend.repo_name,
49 repo_name=backend.repo_name,
50 revision=self.commit_id[backend.alias]))
50 revision=self.commit_id[backend.alias]))
51 assert response.body == self.patches[backend.alias]
51 assert response.body == self.patches[backend.alias]
52
52
53 def test_index_changeset_download(self, backend):
53 def test_index_changeset_download(self, backend):
54 response = self.app.get(url(
54 response = self.app.get(url(
55 controller='changeset', action='changeset_download',
55 controller='changeset', action='changeset_download',
56 repo_name=backend.repo_name,
56 repo_name=backend.repo_name,
57 revision=self.commit_id[backend.alias]))
57 revision=self.commit_id[backend.alias]))
58 assert response.body == self.diffs[backend.alias]
58 assert response.body == self.diffs[backend.alias]
59
59
60 def test_single_commit_page_different_ops(self, backend):
60 def test_single_commit_page_different_ops(self, backend):
61 commit_id = {
61 commit_id = {
62 'hg': '603d6c72c46d953420c89d36372f08d9f305f5dd',
62 'hg': '603d6c72c46d953420c89d36372f08d9f305f5dd',
63 'git': '03fa803d7e9fb14daa9a3089e0d1494eda75d986',
63 'git': '03fa803d7e9fb14daa9a3089e0d1494eda75d986',
64 'svn': '337',
64 'svn': '337',
65 }
65 }
66 commit_id = commit_id[backend.alias]
66 commit_id = commit_id[backend.alias]
67 response = self.app.get(url(
67 response = self.app.get(url(
68 controller='changeset', action='index',
68 controller='changeset', action='index',
69 repo_name=backend.repo_name, revision=commit_id))
69 repo_name=backend.repo_name, revision=commit_id))
70
70
71 response.mustcontain(_shorten_commit_id(commit_id))
71 response.mustcontain(_shorten_commit_id(commit_id))
72 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
72 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
73
73
74 # files op files
74 # files op files
75 response.mustcontain('File no longer present at commit: %s' %
75 response.mustcontain('File no longer present at commit: %s' %
76 _shorten_commit_id(commit_id))
76 _shorten_commit_id(commit_id))
77
77
78 # svn uses a different filename
78 # svn uses a different filename
79 if backend.alias == 'svn':
79 if backend.alias == 'svn':
80 response.mustcontain('new file 10644')
80 response.mustcontain('new file 10644')
81 else:
81 else:
82 response.mustcontain('new file 100644')
82 response.mustcontain('new file 100644')
83 response.mustcontain('Changed theme to ADC theme') # commit msg
83 response.mustcontain('Changed theme to ADC theme') # commit msg
84
84
85 self._check_new_diff_menus(response, right_menu=True)
85 self._check_new_diff_menus(response, right_menu=True)
86
86
87 def test_commit_range_page_different_ops(self, backend):
87 def test_commit_range_page_different_ops(self, backend):
88 commit_id_range = {
88 commit_id_range = {
89 'hg': (
89 'hg': (
90 '25d7e49c18b159446cadfa506a5cf8ad1cb04067',
90 '25d7e49c18b159446cadfa506a5cf8ad1cb04067',
91 '603d6c72c46d953420c89d36372f08d9f305f5dd'),
91 '603d6c72c46d953420c89d36372f08d9f305f5dd'),
92 'git': (
92 'git': (
93 '6fc9270775aaf5544c1deb014f4ddd60c952fcbb',
93 '6fc9270775aaf5544c1deb014f4ddd60c952fcbb',
94 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'),
94 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'),
95 'svn': (
95 'svn': (
96 '335',
96 '335',
97 '337'),
97 '337'),
98 }
98 }
99 commit_ids = commit_id_range[backend.alias]
99 commit_ids = commit_id_range[backend.alias]
100 commit_id = '%s...%s' % (commit_ids[0], commit_ids[1])
100 commit_id = '%s...%s' % (commit_ids[0], commit_ids[1])
101 response = self.app.get(url(
101 response = self.app.get(url(
102 controller='changeset', action='index',
102 controller='changeset', action='index',
103 repo_name=backend.repo_name, revision=commit_id))
103 repo_name=backend.repo_name, revision=commit_id))
104
104
105 response.mustcontain(_shorten_commit_id(commit_ids[0]))
105 response.mustcontain(_shorten_commit_id(commit_ids[0]))
106 response.mustcontain(_shorten_commit_id(commit_ids[1]))
106 response.mustcontain(_shorten_commit_id(commit_ids[1]))
107
107
108 # svn is special
108 # svn is special
109 if backend.alias == 'svn':
109 if backend.alias == 'svn':
110 response.mustcontain('new file 10644')
110 response.mustcontain('new file 10644')
111 response.mustcontain('1 file changed: 5 inserted, 1 deleted')
111 response.mustcontain('1 file changed: 5 inserted, 1 deleted')
112 response.mustcontain('12 files changed: 236 inserted, 22 deleted')
112 response.mustcontain('12 files changed: 236 inserted, 22 deleted')
113 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
113 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
114 else:
114 else:
115 response.mustcontain('new file 100644')
115 response.mustcontain('new file 100644')
116 response.mustcontain('12 files changed: 222 inserted, 20 deleted')
116 response.mustcontain('12 files changed: 222 inserted, 20 deleted')
117 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
117 response.mustcontain('21 files changed: 943 inserted, 288 deleted')
118
118
119 # files op files
119 # files op files
120 response.mustcontain('File no longer present at commit: %s' %
120 response.mustcontain('File no longer present at commit: %s' %
121 _shorten_commit_id(commit_ids[1]))
121 _shorten_commit_id(commit_ids[1]))
122 response.mustcontain('Added docstrings to vcs.cli') # commit msg
122 response.mustcontain('Added docstrings to vcs.cli') # commit msg
123 response.mustcontain('Changed theme to ADC theme') # commit msg
123 response.mustcontain('Changed theme to ADC theme') # commit msg
124
124
125 self._check_new_diff_menus(response)
125 self._check_new_diff_menus(response)
126
126
127 def test_combined_compare_commit_page_different_ops(self, backend):
127 def test_combined_compare_commit_page_different_ops(self, backend):
128 commit_id_range = {
128 commit_id_range = {
129 'hg': (
129 'hg': (
130 '4fdd71e9427417b2e904e0464c634fdee85ec5a7',
130 '4fdd71e9427417b2e904e0464c634fdee85ec5a7',
131 '603d6c72c46d953420c89d36372f08d9f305f5dd'),
131 '603d6c72c46d953420c89d36372f08d9f305f5dd'),
132 'git': (
132 'git': (
133 'f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13',
133 'f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13',
134 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'),
134 '03fa803d7e9fb14daa9a3089e0d1494eda75d986'),
135 'svn': (
135 'svn': (
136 '335',
136 '335',
137 '337'),
137 '337'),
138 }
138 }
139 commit_ids = commit_id_range[backend.alias]
139 commit_ids = commit_id_range[backend.alias]
140 response = self.app.get(url(
140 response = self.app.get(url(
141 controller='compare', action='compare',
141 controller='compare', action='compare',
142 repo_name=backend.repo_name,
142 repo_name=backend.repo_name,
143 source_ref_type='rev', source_ref=commit_ids[0],
143 source_ref_type='rev', source_ref=commit_ids[0],
144 target_ref_type='rev', target_ref=commit_ids[1], ))
144 target_ref_type='rev', target_ref=commit_ids[1], ))
145
145
146 response.mustcontain(_shorten_commit_id(commit_ids[0]))
146 response.mustcontain(_shorten_commit_id(commit_ids[0]))
147 response.mustcontain(_shorten_commit_id(commit_ids[1]))
147 response.mustcontain(_shorten_commit_id(commit_ids[1]))
148
148
149 # files op files
149 # files op files
150 response.mustcontain('File no longer present at commit: %s' %
150 response.mustcontain('File no longer present at commit: %s' %
151 _shorten_commit_id(commit_ids[1]))
151 _shorten_commit_id(commit_ids[1]))
152
152
153 # svn is special
153 # svn is special
154 if backend.alias == 'svn':
154 if backend.alias == 'svn':
155 response.mustcontain('new file 10644')
155 response.mustcontain('new file 10644')
156 response.mustcontain('32 files changed: 1179 inserted, 310 deleted')
156 response.mustcontain('32 files changed: 1179 inserted, 310 deleted')
157 else:
157 else:
158 response.mustcontain('new file 100644')
158 response.mustcontain('new file 100644')
159 response.mustcontain('32 files changed: 1165 inserted, 308 deleted')
159 response.mustcontain('32 files changed: 1165 inserted, 308 deleted')
160
160
161 response.mustcontain('Added docstrings to vcs.cli') # commit msg
161 response.mustcontain('Added docstrings to vcs.cli') # commit msg
162 response.mustcontain('Changed theme to ADC theme') # commit msg
162 response.mustcontain('Changed theme to ADC theme') # commit msg
163
163
164 self._check_new_diff_menus(response)
164 self._check_new_diff_menus(response)
165
165
166 def test_changeset_range(self, backend):
166 def test_changeset_range(self, backend):
167 self._check_changeset_range(
167 self._check_changeset_range(
168 backend, self.commit_id_range, self.commit_id_range_result)
168 backend, self.commit_id_range, self.commit_id_range_result)
169
169
170 def test_changeset_range_with_initial_commit(self, backend):
170 def test_changeset_range_with_initial_commit(self, backend):
171 commit_id_range = {
171 commit_id_range = {
172 'hg': (
172 'hg': (
173 'b986218ba1c9b0d6a259fac9b050b1724ed8e545'
173 'b986218ba1c9b0d6a259fac9b050b1724ed8e545'
174 '...6cba7170863a2411822803fa77a0a264f1310b35'),
174 '...6cba7170863a2411822803fa77a0a264f1310b35'),
175 'git': (
175 'git': (
176 'c1214f7e79e02fc37156ff215cd71275450cffc3'
176 'c1214f7e79e02fc37156ff215cd71275450cffc3'
177 '...fa6600f6848800641328adbf7811fd2372c02ab2'),
177 '...fa6600f6848800641328adbf7811fd2372c02ab2'),
178 'svn': '1...3',
178 'svn': '1...3',
179 }
179 }
180 commit_id_range_result = {
180 commit_id_range_result = {
181 'hg': ['b986218ba1c9', '3d8f361e72ab', '6cba7170863a'],
181 'hg': ['b986218ba1c9', '3d8f361e72ab', '6cba7170863a'],
182 'git': ['c1214f7e79e0', '38b5fe81f109', 'fa6600f68488'],
182 'git': ['c1214f7e79e0', '38b5fe81f109', 'fa6600f68488'],
183 'svn': ['1', '2', '3'],
183 'svn': ['1', '2', '3'],
184 }
184 }
185 self._check_changeset_range(
185 self._check_changeset_range(
186 backend, commit_id_range, commit_id_range_result)
186 backend, commit_id_range, commit_id_range_result)
187
187
188 def _check_changeset_range(
188 def _check_changeset_range(
189 self, backend, commit_id_ranges, commit_id_range_result):
189 self, backend, commit_id_ranges, commit_id_range_result):
190 response = self.app.get(
190 response = self.app.get(
191 url(controller='changeset', action='index',
191 url(controller='changeset', action='index',
192 repo_name=backend.repo_name,
192 repo_name=backend.repo_name,
193 revision=commit_id_ranges[backend.alias]))
193 revision=commit_id_ranges[backend.alias]))
194 expected_result = commit_id_range_result[backend.alias]
194 expected_result = commit_id_range_result[backend.alias]
195 response.mustcontain('{} commits'.format(len(expected_result)))
195 response.mustcontain('{} commits'.format(len(expected_result)))
196 for commit_id in expected_result:
196 for commit_id in expected_result:
197 response.mustcontain(commit_id)
197 response.mustcontain(commit_id)
198
198
199 commit_id = {
199 commit_id = {
200 'hg': '2062ec7beeeaf9f44a1c25c41479565040b930b2',
200 'hg': '2062ec7beeeaf9f44a1c25c41479565040b930b2',
201 'svn': '393',
201 'svn': '393',
202 'git': 'fd627b9e0dd80b47be81af07c4a98518244ed2f7',
202 'git': 'fd627b9e0dd80b47be81af07c4a98518244ed2f7',
203 }
203 }
204
204
205 commit_id_range = {
205 commit_id_range = {
206 'hg': (
206 'hg': (
207 'a53d9201d4bc278910d416d94941b7ea007ecd52'
207 'a53d9201d4bc278910d416d94941b7ea007ecd52'
208 '...2062ec7beeeaf9f44a1c25c41479565040b930b2'),
208 '...2062ec7beeeaf9f44a1c25c41479565040b930b2'),
209 'git': (
209 'git': (
210 '7ab37bc680b4aa72c34d07b230c866c28e9fc204'
210 '7ab37bc680b4aa72c34d07b230c866c28e9fc204'
211 '...fd627b9e0dd80b47be81af07c4a98518244ed2f7'),
211 '...fd627b9e0dd80b47be81af07c4a98518244ed2f7'),
212 'svn': '391...393',
212 'svn': '391...393',
213 }
213 }
214
214
215 commit_id_range_result = {
215 commit_id_range_result = {
216 'hg': ['a53d9201d4bc', '96507bd11ecc', '2062ec7beeea'],
216 'hg': ['a53d9201d4bc', '96507bd11ecc', '2062ec7beeea'],
217 'git': ['7ab37bc680b4', '5f2c6ee19592', 'fd627b9e0dd8'],
217 'git': ['7ab37bc680b4', '5f2c6ee19592', 'fd627b9e0dd8'],
218 'svn': ['391', '392', '393'],
218 'svn': ['391', '392', '393'],
219 }
219 }
220
220
221 diffs = {
221 diffs = {
222 'hg': r"""diff --git a/README b/README
222 'hg': r"""diff --git a/README b/README
223 new file mode 120000
223 new file mode 120000
224 --- /dev/null
224 --- /dev/null
225 +++ b/README
225 +++ b/README
226 @@ -0,0 +1,1 @@
226 @@ -0,0 +1,1 @@
227 +README.rst
227 +README.rst
228 \ No newline at end of file
228 \ No newline at end of file
229 """,
229 """,
230 'git': r"""diff --git a/README b/README
230 'git': r"""diff --git a/README b/README
231 new file mode 120000
231 new file mode 120000
232 index 0000000000000000000000000000000000000000..92cacd285355271487b7e379dba6ca60f9a554a4
232 index 0000000000000000000000000000000000000000..92cacd285355271487b7e379dba6ca60f9a554a4
233 --- /dev/null
233 --- /dev/null
234 +++ b/README
234 +++ b/README
235 @@ -0,0 +1 @@
235 @@ -0,0 +1 @@
236 +README.rst
236 +README.rst
237 \ No newline at end of file
237 \ No newline at end of file
238 """,
238 """,
239 'svn': """Index: README
239 'svn': """Index: README
240 ===================================================================
240 ===================================================================
241 diff --git a/README b/README
241 diff --git a/README b/README
242 new file mode 10644
242 new file mode 10644
243 --- /dev/null\t(revision 0)
243 --- /dev/null\t(revision 0)
244 +++ b/README\t(revision 393)
244 +++ b/README\t(revision 393)
245 @@ -0,0 +1 @@
245 @@ -0,0 +1 @@
246 +link README.rst
246 +link README.rst
247 \\ No newline at end of file
247 \\ No newline at end of file
248 """,
248 """,
249 }
249 }
250
250
251 patches = {
251 patches = {
252 'hg': r"""# HG changeset patch
252 'hg': r"""# HG changeset patch
253 # User Marcin Kuzminski <marcin@python-works.com>
253 # User Marcin Kuzminski <marcin@python-works.com>
254 # Date 2014-01-07 12:21:40
254 # Date 2014-01-07 12:21:40
255 # Node ID 2062ec7beeeaf9f44a1c25c41479565040b930b2
255 # Node ID 2062ec7beeeaf9f44a1c25c41479565040b930b2
256 # Parent 96507bd11ecc815ebc6270fdf6db110928c09c1e
256 # Parent 96507bd11ecc815ebc6270fdf6db110928c09c1e
257
257
258 Added a symlink
258 Added a symlink
259
259
260 """ + diffs['hg'],
260 """ + diffs['hg'],
261 'git': r"""From fd627b9e0dd80b47be81af07c4a98518244ed2f7 2014-01-07 12:22:20
261 'git': r"""From fd627b9e0dd80b47be81af07c4a98518244ed2f7 2014-01-07 12:22:20
262 From: Marcin Kuzminski <marcin@python-works.com>
262 From: Marcin Kuzminski <marcin@python-works.com>
263 Date: 2014-01-07 12:22:20
263 Date: 2014-01-07 12:22:20
264 Subject: [PATCH] Added a symlink
264 Subject: [PATCH] Added a symlink
265
265
266 ---
266 ---
267
267
268 """ + diffs['git'],
268 """ + diffs['git'],
269 'svn': r"""# SVN changeset patch
269 'svn': r"""# SVN changeset patch
270 # User marcin
270 # User marcin
271 # Date 2014-09-02 12:25:22.071142
271 # Date 2014-09-02 12:25:22.071142
272 # Revision 393
272 # Revision 393
273
273
274 Added a symlink
274 Added a symlink
275
275
276 """ + diffs['svn'],
276 """ + diffs['svn'],
277 }
277 }
278
278
279 def _check_diff_menus(self, response, right_menu=False,):
279 def _check_diff_menus(self, response, right_menu=False,):
280 # diff menus
280 # diff menus
281 for elem in ['Show File', 'Unified Diff', 'Side-by-side Diff',
281 for elem in ['Show File', 'Unified Diff', 'Side-by-side Diff',
282 'Raw Diff', 'Download Diff']:
282 'Raw Diff', 'Download Diff']:
283 response.mustcontain(elem)
283 response.mustcontain(elem)
284
284
285 # right pane diff menus
285 # right pane diff menus
286 if right_menu:
286 if right_menu:
287 for elem in ['Ignore whitespace', 'Increase context',
287 for elem in ['Ignore whitespace', 'Increase context',
288 'Hide comments']:
288 'Hide comments']:
289 response.mustcontain(elem)
289 response.mustcontain(elem)
290
290
291
292 def _check_new_diff_menus(self, response, right_menu=False,):
291 def _check_new_diff_menus(self, response, right_menu=False,):
293 # diff menus
292 # diff menus
294 for elem in ['Show file before', 'Show file after',
293 for elem in ['Show file before', 'Show file after',
295 'Raw diff', 'Download diff']:
294 'Raw diff', 'Download diff']:
296 response.mustcontain(elem)
295 response.mustcontain(elem)
297
296
298 # right pane diff menus
297 # right pane diff menus
299 if right_menu:
298 if right_menu:
300 for elem in ['Ignore whitespace', 'Increase context',
299 for elem in ['Ignore whitespace', 'Increase context',
301 'Hide comments']:
300 'Hide comments']:
302 response.mustcontain(elem)
301 response.mustcontain(elem)
General Comments 0
You need to be logged in to leave comments. Login now