##// END OF EJS Templates
exc: fixed exceptions prefix (again)
milka -
r4606:ba9a97a8 stable
parent child
Show More
@@ -1,233 +1,234
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2014-2020 RhodeCode GmbH
3 # Copyright (C) 2014-2020 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 Custom vcs exceptions module.
22 Custom vcs exceptions module.
23 """
23 """
24 import logging
24 import logging
25 import functools
25 import functools
26 import urllib2
26 import urllib2
27 import rhodecode
27 import rhodecode
28 from pyramid import compat
28 from pyramid import compat
29
29
30 log = logging.getLogger(__name__)
30 log = logging.getLogger(__name__)
31
31
32
32
33 class VCSCommunicationError(Exception):
33 class VCSCommunicationError(Exception):
34 pass
34 pass
35
35
36
36
37 class HttpVCSCommunicationError(VCSCommunicationError):
37 class HttpVCSCommunicationError(VCSCommunicationError):
38 pass
38 pass
39
39
40
40
41 class VCSError(Exception):
41 class VCSError(Exception):
42 pass
42 pass
43
43
44
44
45 class RepositoryError(VCSError):
45 class RepositoryError(VCSError):
46 pass
46 pass
47
47
48
48
49 class RepositoryRequirementError(RepositoryError):
49 class RepositoryRequirementError(RepositoryError):
50 pass
50 pass
51
51
52
52
53 class UnresolvedFilesInRepo(RepositoryError):
53 class UnresolvedFilesInRepo(RepositoryError):
54 pass
54 pass
55
55
56
56
57 class VCSBackendNotSupportedError(VCSError):
57 class VCSBackendNotSupportedError(VCSError):
58 """
58 """
59 Exception raised when VCSServer does not support requested backend
59 Exception raised when VCSServer does not support requested backend
60 """
60 """
61
61
62
62
63 class EmptyRepositoryError(RepositoryError):
63 class EmptyRepositoryError(RepositoryError):
64 pass
64 pass
65
65
66
66
67 class TagAlreadyExistError(RepositoryError):
67 class TagAlreadyExistError(RepositoryError):
68 pass
68 pass
69
69
70
70
71 class TagDoesNotExistError(RepositoryError):
71 class TagDoesNotExistError(RepositoryError):
72 pass
72 pass
73
73
74
74
75 class BranchAlreadyExistError(RepositoryError):
75 class BranchAlreadyExistError(RepositoryError):
76 pass
76 pass
77
77
78
78
79 class BranchDoesNotExistError(RepositoryError):
79 class BranchDoesNotExistError(RepositoryError):
80 pass
80 pass
81
81
82
82
83 class CommitError(RepositoryError):
83 class CommitError(RepositoryError):
84 """
84 """
85 Exceptions related to an existing commit
85 Exceptions related to an existing commit
86 """
86 """
87
87
88
88
89 class CommitDoesNotExistError(CommitError):
89 class CommitDoesNotExistError(CommitError):
90 pass
90 pass
91
91
92
92
93 class CommittingError(RepositoryError):
93 class CommittingError(RepositoryError):
94 """
94 """
95 Exceptions happening while creating a new commit
95 Exceptions happening while creating a new commit
96 """
96 """
97
97
98
98
99 class NothingChangedError(CommittingError):
99 class NothingChangedError(CommittingError):
100 pass
100 pass
101
101
102
102
103 class NodeError(VCSError):
103 class NodeError(VCSError):
104 pass
104 pass
105
105
106
106
107 class RemovedFileNodeError(NodeError):
107 class RemovedFileNodeError(NodeError):
108 pass
108 pass
109
109
110
110
111 class NodeAlreadyExistsError(CommittingError):
111 class NodeAlreadyExistsError(CommittingError):
112 pass
112 pass
113
113
114
114
115 class NodeAlreadyChangedError(CommittingError):
115 class NodeAlreadyChangedError(CommittingError):
116 pass
116 pass
117
117
118
118
119 class NodeDoesNotExistError(CommittingError):
119 class NodeDoesNotExistError(CommittingError):
120 pass
120 pass
121
121
122
122
123 class NodeNotChangedError(CommittingError):
123 class NodeNotChangedError(CommittingError):
124 pass
124 pass
125
125
126
126
127 class NodeAlreadyAddedError(CommittingError):
127 class NodeAlreadyAddedError(CommittingError):
128 pass
128 pass
129
129
130
130
131 class NodeAlreadyRemovedError(CommittingError):
131 class NodeAlreadyRemovedError(CommittingError):
132 pass
132 pass
133
133
134
134
135 class SubrepoMergeError(RepositoryError):
135 class SubrepoMergeError(RepositoryError):
136 """
136 """
137 This happens if we try to merge a repository which contains subrepos and
137 This happens if we try to merge a repository which contains subrepos and
138 the subrepos cannot be merged. The subrepos are not merged itself but
138 the subrepos cannot be merged. The subrepos are not merged itself but
139 their references in the root repo are merged.
139 their references in the root repo are merged.
140 """
140 """
141
141
142
142
143 class ImproperArchiveTypeError(VCSError):
143 class ImproperArchiveTypeError(VCSError):
144 pass
144 pass
145
145
146
146
147 class CommandError(VCSError):
147 class CommandError(VCSError):
148 pass
148 pass
149
149
150
150
151 class UnhandledException(VCSError):
151 class UnhandledException(VCSError):
152 """
152 """
153 Signals that something unexpected went wrong.
153 Signals that something unexpected went wrong.
154
154
155 This usually means we have a programming error on the side of the VCSServer
155 This usually means we have a programming error on the side of the VCSServer
156 and should inspect the logfile of the VCSServer to find more details.
156 and should inspect the logfile of the VCSServer to find more details.
157 """
157 """
158
158
159
159
160 _EXCEPTION_MAP = {
160 _EXCEPTION_MAP = {
161 'abort': RepositoryError,
161 'abort': RepositoryError,
162 'archive': ImproperArchiveTypeError,
162 'archive': ImproperArchiveTypeError,
163 'error': RepositoryError,
163 'error': RepositoryError,
164 'lookup': CommitDoesNotExistError,
164 'lookup': CommitDoesNotExistError,
165 'repo_locked': RepositoryError,
165 'repo_locked': RepositoryError,
166 'requirement': RepositoryRequirementError,
166 'requirement': RepositoryRequirementError,
167 'unhandled': UnhandledException,
167 'unhandled': UnhandledException,
168 # TODO: johbo: Define our own exception for this and stop abusing
168 # TODO: johbo: Define our own exception for this and stop abusing
169 # urllib's exception class.
169 # urllib's exception class.
170 'url_error': urllib2.URLError,
170 'url_error': urllib2.URLError,
171 'subrepo_merge_error': SubrepoMergeError,
171 'subrepo_merge_error': SubrepoMergeError,
172 }
172 }
173
173
174
174
175 def map_vcs_exceptions(func):
175 def map_vcs_exceptions(func):
176 """
176 """
177 Utility to decorate functions so that plain exceptions are translated.
177 Utility to decorate functions so that plain exceptions are translated.
178
178
179 The translation is based on `exc_map` which maps a `str` indicating
179 The translation is based on `exc_map` which maps a `str` indicating
180 the error type into an exception class representing this error inside
180 the error type into an exception class representing this error inside
181 of the vcs layer.
181 of the vcs layer.
182 """
182 """
183
183
184 @functools.wraps(func)
184 @functools.wraps(func)
185 def wrapper(*args, **kwargs):
185 def wrapper(*args, **kwargs):
186 try:
186 try:
187 return func(*args, **kwargs)
187 return func(*args, **kwargs)
188 except Exception as e:
188 except Exception as e:
189 from rhodecode.lib.utils2 import str2bool
189 from rhodecode.lib.utils2 import str2bool
190 debug = str2bool(rhodecode.CONFIG.get('debug'))
190 debug = str2bool(rhodecode.CONFIG.get('debug'))
191
191
192 # The error middleware adds information if it finds
192 # The error middleware adds information if it finds
193 # __traceback_info__ in a frame object. This way the remote
193 # __traceback_info__ in a frame object. This way the remote
194 # traceback information is made available in error reports.
194 # traceback information is made available in error reports.
195 remote_tb = getattr(e, '_vcs_server_traceback', None)
195 remote_tb = getattr(e, '_vcs_server_traceback', None)
196 org_remote_tb = getattr(e, '_vcs_server_org_exc_tb', '')
196 org_remote_tb = getattr(e, '_vcs_server_org_exc_tb', '')
197 __traceback_info__ = None
197 __traceback_info__ = None
198 if remote_tb:
198 if remote_tb:
199 if isinstance(remote_tb, compat.string_types):
199 if isinstance(remote_tb, compat.string_types):
200 remote_tb = [remote_tb]
200 remote_tb = [remote_tb]
201 __traceback_info__ = (
201 __traceback_info__ = (
202 'Found VCSServer remote traceback information:\n'
202 'Found VCSServer remote traceback information:\n'
203 '{}\n'
203 '{}\n'
204 '+++ BEG SOURCE EXCEPTION +++\n\n'
204 '+++ BEG SOURCE EXCEPTION +++\n\n'
205 '{}\n'
205 '{}\n'
206 '+++ END SOURCE EXCEPTION +++\n'
206 '+++ END SOURCE EXCEPTION +++\n'
207 ''.format('\n'.join(remote_tb), org_remote_tb)
207 ''.format('\n'.join(remote_tb), org_remote_tb)
208 )
208 )
209
209
210 # Avoid that remote_tb also appears in the frame
210 # Avoid that remote_tb also appears in the frame
211 del remote_tb
211 del remote_tb
212
212
213 # Special vcs errors had an attribute "_vcs_kind" which is used
213 # Special vcs errors had an attribute "_vcs_kind" which is used
214 # to translate them to the proper exception class in the vcs
214 # to translate them to the proper exception class in the vcs
215 # client layer.
215 # client layer.
216 kind = getattr(e, '_vcs_kind', None)
216 kind = getattr(e, '_vcs_kind', None)
217 exc_name = getattr(e, '_vcs_server_org_exc_name', None)
217 exc_name = getattr(e, '_vcs_server_org_exc_name', None)
218
218
219 if kind:
219 if kind:
220 if any(e.args):
220 if any(e.args):
221 args = [a for a in e.args]
221 _args = [a for a in e.args]
222 args.insert(0, '{}:'.format(exc_name)) # prefix first arg with org exc name
222 # replace the first argument with a prefix exc name
223 args = ['{}:'.format(exc_name, _args[0] if _args else '?')] + _args[1:]
223 else:
224 else:
224 args = [__traceback_info__ or '{}: UnhandledException'.format(exc_name)]
225 args = [__traceback_info__ or '{}: UnhandledException'.format(exc_name)]
225 if debug or __traceback_info__ and kind not in ['unhandled', 'lookup']:
226 if debug or __traceback_info__ and kind not in ['unhandled', 'lookup']:
226 # for other than unhandled errors also log the traceback
227 # for other than unhandled errors also log the traceback
227 # can be useful for debugging
228 # can be useful for debugging
228 log.error(__traceback_info__)
229 log.error(__traceback_info__)
229
230
230 raise _EXCEPTION_MAP[kind](*args)
231 raise _EXCEPTION_MAP[kind](*args)
231 else:
232 else:
232 raise
233 raise
233 return wrapper
234 return wrapper
General Comments 0
You need to be logged in to leave comments. Login now