##// END OF EJS Templates
svn: don't raise duplicate exception. The function already does that.
marcink -
r1926:f9d07533 default
parent child Browse files
Show More
@@ -1,236 +1,236 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2014-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 SVN commit module
23 23 """
24 24
25 25
26 26 import dateutil.parser
27 27 from zope.cachedescriptors.property import Lazy as LazyProperty
28 28
29 29 from rhodecode.lib.utils import safe_str, safe_unicode
30 30 from rhodecode.lib.vcs import nodes, path as vcspath
31 31 from rhodecode.lib.vcs.backends import base
32 32 from rhodecode.lib.vcs.exceptions import CommitError, NodeDoesNotExistError
33 33
34 34
35 35 _SVN_PROP_TRUE = '*'
36 36
37 37
38 38 class SubversionCommit(base.BaseCommit):
39 39 """
40 40 Subversion specific implementation of commits
41 41
42 42 .. attribute:: branch
43 43
44 44 The Subversion backend does not support to assign branches to
45 45 specific commits. This attribute has always the value `None`.
46 46
47 47 """
48 48
49 49 def __init__(self, repository, commit_id):
50 50 self.repository = repository
51 51 self.idx = self.repository._get_commit_idx(commit_id)
52 52 self._svn_rev = self.idx + 1
53 53 self._remote = repository._remote
54 54 # TODO: handling of raw_id should be a method on repository itself,
55 55 # which knows how to translate commit index and commit id
56 56 self.raw_id = commit_id
57 57 self.short_id = commit_id
58 58 self.id = 'r%s' % (commit_id, )
59 59
60 60 # TODO: Implement the following placeholder attributes
61 61 self.nodes = {}
62 62 self.tags = []
63 63
64 64 @property
65 65 def author(self):
66 66 return safe_unicode(self._properties.get('svn:author'))
67 67
68 68 @property
69 69 def date(self):
70 70 return _date_from_svn_properties(self._properties)
71 71
72 72 @property
73 73 def message(self):
74 74 return safe_unicode(self._properties.get('svn:log'))
75 75
76 76 @LazyProperty
77 77 def _properties(self):
78 78 return self._remote.revision_properties(self._svn_rev)
79 79
80 80 @LazyProperty
81 81 def parents(self):
82 82 parent_idx = self.idx - 1
83 83 if parent_idx >= 0:
84 84 parent = self.repository.get_commit(commit_idx=parent_idx)
85 85 return [parent]
86 86 return []
87 87
88 88 @LazyProperty
89 89 def children(self):
90 90 child_idx = self.idx + 1
91 91 if child_idx < len(self.repository.commit_ids):
92 92 child = self.repository.get_commit(commit_idx=child_idx)
93 93 return [child]
94 94 return []
95 95
96 96 def get_file_mode(self, path):
97 97 # Note: Subversion flags files which are executable with a special
98 98 # property `svn:executable` which is set to the value ``"*"``.
99 99 if self._get_file_property(path, 'svn:executable') == _SVN_PROP_TRUE:
100 100 return base.FILEMODE_EXECUTABLE
101 101 else:
102 102 return base.FILEMODE_DEFAULT
103 103
104 104 def is_link(self, path):
105 105 # Note: Subversion has a flag for special files, the content of the
106 106 # file contains the type of that file.
107 107 if self._get_file_property(path, 'svn:special') == _SVN_PROP_TRUE:
108 108 return self.get_file_content(path).startswith('link')
109 109 return False
110 110
111 111 def _get_file_property(self, path, name):
112 112 file_properties = self._remote.node_properties(
113 113 safe_str(path), self._svn_rev)
114 114 return file_properties.get(name)
115 115
116 116 def get_file_content(self, path):
117 117 path = self._fix_path(path)
118 118 return self._remote.get_file_content(safe_str(path), self._svn_rev)
119 119
120 120 def get_file_size(self, path):
121 121 path = self._fix_path(path)
122 122 return self._remote.get_file_size(safe_str(path), self._svn_rev)
123 123
124 124 def get_file_history(self, path, limit=None, pre_load=None):
125 125 path = safe_str(self._fix_path(path))
126 126 history = self._remote.node_history(path, self._svn_rev, limit)
127 127 return [
128 128 self.repository.get_commit(commit_id=str(svn_rev))
129 129 for svn_rev in history]
130 130
131 131 def get_file_annotate(self, path, pre_load=None):
132 132 result = self._remote.file_annotate(safe_str(path), self._svn_rev)
133 133
134 134 for zero_based_line_no, svn_rev, content in result:
135 135 commit_id = str(svn_rev)
136 136 line_no = zero_based_line_no + 1
137 137 yield (
138 138 line_no,
139 139 commit_id,
140 140 lambda: self.repository.get_commit(commit_id=commit_id),
141 141 content)
142 142
143 143 def get_node(self, path, pre_load=None):
144 144 path = self._fix_path(path)
145 145 if path not in self.nodes:
146 146
147 147 if path == '':
148 148 node = nodes.RootNode(commit=self)
149 149 else:
150 150 node_type = self._remote.get_node_type(
151 151 safe_str(path), self._svn_rev)
152 152 if node_type == 'dir':
153 153 node = nodes.DirNode(path, commit=self)
154 154 elif node_type == 'file':
155 155 node = nodes.FileNode(path, commit=self, pre_load=pre_load)
156 156 else:
157 raise NodeDoesNotExistError(self.no_node_at_path(path))
157 raise self.no_node_at_path(path)
158 158
159 159 self.nodes[path] = node
160 160 return self.nodes[path]
161 161
162 162 def get_nodes(self, path):
163 163 if self._get_kind(path) != nodes.NodeKind.DIR:
164 164 raise CommitError(
165 165 "Directory does not exist for commit %s at "
166 166 " '%s'" % (self.raw_id, path))
167 167 path = self._fix_path(path)
168 168
169 169 path_nodes = []
170 170 for name, kind in self._remote.get_nodes(
171 171 safe_str(path), revision=self._svn_rev):
172 172 node_path = vcspath.join(path, name)
173 173 if kind == 'dir':
174 174 node = nodes.DirNode(node_path, commit=self)
175 175 elif kind == 'file':
176 176 node = nodes.FileNode(node_path, commit=self)
177 177 else:
178 178 raise ValueError("Node kind %s not supported." % (kind, ))
179 179 self.nodes[node_path] = node
180 180 path_nodes.append(node)
181 181
182 182 return path_nodes
183 183
184 184 def _get_kind(self, path):
185 185 path = self._fix_path(path)
186 186 kind = self._remote.get_node_type(path, self._svn_rev)
187 187 if kind == 'file':
188 188 return nodes.NodeKind.FILE
189 189 elif kind == 'dir':
190 190 return nodes.NodeKind.DIR
191 191 else:
192 192 raise CommitError(
193 193 "Node does not exist at the given path '%s'" % (path, ))
194 194
195 195 @LazyProperty
196 196 def _changes_cache(self):
197 197 return self._remote.revision_changes(self._svn_rev)
198 198
199 199 @LazyProperty
200 200 def affected_files(self):
201 201 changed_files = set()
202 202 for files in self._changes_cache.itervalues():
203 203 changed_files.update(files)
204 204 return list(changed_files)
205 205
206 206 @LazyProperty
207 207 def id(self):
208 208 return self.raw_id
209 209
210 210 @property
211 211 def added(self):
212 212 return nodes.AddedFileNodesGenerator(
213 213 self._changes_cache['added'], self)
214 214
215 215 @property
216 216 def changed(self):
217 217 return nodes.ChangedFileNodesGenerator(
218 218 self._changes_cache['changed'], self)
219 219
220 220 @property
221 221 def removed(self):
222 222 return nodes.RemovedFileNodesGenerator(
223 223 self._changes_cache['removed'], self)
224 224
225 225
226 226 def _date_from_svn_properties(properties):
227 227 """
228 228 Parses the date out of given svn properties.
229 229
230 230 :return: :class:`datetime.datetime` instance. The object is naive.
231 231 """
232 232
233 233 aware_date = dateutil.parser.parse(properties.get('svn:date'))
234 234 # final_date = aware_date.astimezone(dateutil.tz.tzlocal())
235 235 final_date = aware_date
236 236 return final_date.replace(tzinfo=None)
General Comments 0
You need to be logged in to leave comments. Login now