Show More
@@ -0,0 +1,49 b'' | |||||
|
1 | # Copyright (C) 2016-2016 RhodeCode GmbH | |||
|
2 | # | |||
|
3 | # This program is free software: you can redistribute it and/or modify | |||
|
4 | # it under the terms of the GNU Affero General Public License, version 3 | |||
|
5 | # (only), as published by the Free Software Foundation. | |||
|
6 | # | |||
|
7 | # This program is distributed in the hope that it will be useful, | |||
|
8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
10 | # GNU General Public License for more details. | |||
|
11 | # | |||
|
12 | # You should have received a copy of the GNU Affero General Public License | |||
|
13 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
|
14 | # | |||
|
15 | # This program is dual-licensed. If you wish to learn more about the | |||
|
16 | # RhodeCode Enterprise Edition, including its added features, Support services, | |||
|
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |||
|
18 | ||||
|
19 | from pyramid.threadlocal import get_current_registry | |||
|
20 | ||||
|
21 | ||||
|
22 | class RhodecodeEvent(object): | |||
|
23 | """ | |||
|
24 | Base event class for all Rhodecode events | |||
|
25 | """ | |||
|
26 | ||||
|
27 | ||||
|
28 | def trigger(event): | |||
|
29 | """ | |||
|
30 | Helper method to send an event. This wraps the pyramid logic to send an | |||
|
31 | event. | |||
|
32 | """ | |||
|
33 | # For the first step we are using pyramids thread locals here. If the | |||
|
34 | # event mechanism works out as a good solution we should think about | |||
|
35 | # passing the registry as an argument to get rid of it. | |||
|
36 | registry = get_current_registry() | |||
|
37 | registry.notify(event) | |||
|
38 | ||||
|
39 | ||||
|
40 | from rhodecode.events.user import ( | |||
|
41 | UserPreCreate, UserPreUpdate, UserRegistered | |||
|
42 | ) | |||
|
43 | ||||
|
44 | from rhodecode.events.repo import ( | |||
|
45 | RepoPreCreateEvent, RepoCreatedEvent, | |||
|
46 | RepoPreDeleteEvent, RepoDeletedEvent, | |||
|
47 | RepoPrePushEvent, RepoPushEvent, | |||
|
48 | RepoPrePullEvent, RepoPullEvent, | |||
|
49 | ) No newline at end of file |
@@ -0,0 +1,115 b'' | |||||
|
1 | # Copyright (C) 2016-2016 RhodeCode GmbH | |||
|
2 | # | |||
|
3 | # This program is free software: you can redistribute it and/or modify | |||
|
4 | # it under the terms of the GNU Affero General Public License, version 3 | |||
|
5 | # (only), as published by the Free Software Foundation. | |||
|
6 | # | |||
|
7 | # This program is distributed in the hope that it will be useful, | |||
|
8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
10 | # GNU General Public License for more details. | |||
|
11 | # | |||
|
12 | # You should have received a copy of the GNU Affero General Public License | |||
|
13 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
|
14 | # | |||
|
15 | # This program is dual-licensed. If you wish to learn more about the | |||
|
16 | # RhodeCode Enterprise Edition, including its added features, Support services, | |||
|
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |||
|
18 | ||||
|
19 | from rhodecode.model.db import Repository, Session | |||
|
20 | from rhodecode.events import RhodecodeEvent | |||
|
21 | ||||
|
22 | ||||
|
23 | class RepoEvent(RhodecodeEvent): | |||
|
24 | """ | |||
|
25 | Base class for events acting on a repository. | |||
|
26 | ||||
|
27 | :param repo: a :class:`Repository` instance | |||
|
28 | """ | |||
|
29 | def __init__(self, repo): | |||
|
30 | self.repo = repo | |||
|
31 | ||||
|
32 | ||||
|
33 | class RepoPreCreateEvent(RepoEvent): | |||
|
34 | """ | |||
|
35 | An instance of this class is emitted as an :term:`event` before a repo is | |||
|
36 | created. | |||
|
37 | ||||
|
38 | :param repo_name: repository name | |||
|
39 | """ | |||
|
40 | name = 'repo-pre-create' | |||
|
41 | ||||
|
42 | ||||
|
43 | class RepoCreatedEvent(RepoEvent): | |||
|
44 | """ | |||
|
45 | An instance of this class is emitted as an :term:`event` whenever a repo is | |||
|
46 | created. | |||
|
47 | """ | |||
|
48 | name = 'repo-created' | |||
|
49 | ||||
|
50 | ||||
|
51 | class RepoPreDeleteEvent(RepoEvent): | |||
|
52 | """ | |||
|
53 | An instance of this class is emitted as an :term:`event` whenever a repo is | |||
|
54 | created. | |||
|
55 | """ | |||
|
56 | name = 'repo-pre-delete' | |||
|
57 | ||||
|
58 | ||||
|
59 | class RepoDeletedEvent(RepoEvent): | |||
|
60 | """ | |||
|
61 | An instance of this class is emitted as an :term:`event` whenever a repo is | |||
|
62 | created. | |||
|
63 | """ | |||
|
64 | name = 'repo-deleted' | |||
|
65 | ||||
|
66 | ||||
|
67 | class RepoVCSEvent(RepoEvent): | |||
|
68 | """ | |||
|
69 | Base class for events triggered by the VCS | |||
|
70 | """ | |||
|
71 | def __init__(self, repo_name, extras): | |||
|
72 | self.repo = Repository.get_by_repo_name(repo_name) | |||
|
73 | if not self.repo: | |||
|
74 | raise Exception('repo by this name %s does not exist' % repo_name) | |||
|
75 | self.extras = extras | |||
|
76 | super(RepoVCSEvent, self).__init__(self.repo) | |||
|
77 | ||||
|
78 | ||||
|
79 | class RepoPrePullEvent(RepoVCSEvent): | |||
|
80 | """ | |||
|
81 | An instance of this class is emitted as an :term:`event` before commits | |||
|
82 | are pulled from a repo. | |||
|
83 | """ | |||
|
84 | name = 'repo-pre-pull' | |||
|
85 | ||||
|
86 | ||||
|
87 | class RepoPullEvent(RepoVCSEvent): | |||
|
88 | """ | |||
|
89 | An instance of this class is emitted as an :term:`event` after commits | |||
|
90 | are pulled from a repo. | |||
|
91 | """ | |||
|
92 | name = 'repo-pull' | |||
|
93 | ||||
|
94 | ||||
|
95 | class RepoPrePushEvent(RepoVCSEvent): | |||
|
96 | """ | |||
|
97 | An instance of this class is emitted as an :term:`event` before commits | |||
|
98 | are pushed to a repo. | |||
|
99 | """ | |||
|
100 | name = 'repo-pre-push' | |||
|
101 | ||||
|
102 | ||||
|
103 | class RepoPushEvent(RepoVCSEvent): | |||
|
104 | """ | |||
|
105 | An instance of this class is emitted as an :term:`event` after commits | |||
|
106 | are pushed to a repo. | |||
|
107 | ||||
|
108 | :param extras: (optional) dict of data from proxied VCS actions | |||
|
109 | """ | |||
|
110 | name = 'repo-push' | |||
|
111 | ||||
|
112 | def __init__(self, repo_name, pushed_commit_ids, extras): | |||
|
113 | super(RepoPushEvent, self).__init__(repo_name, extras) | |||
|
114 | self.pushed_commit_ids = pushed_commit_ids | |||
|
115 |
@@ -0,0 +1,19 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | # Copyright (C) 2010-2016 RhodeCode GmbH | |||
|
4 | # | |||
|
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 | |||
|
7 | # (only), as published by the Free Software Foundation. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
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/>. | |||
|
16 | # | |||
|
17 | # This program is dual-licensed. If you wish to learn more about the | |||
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |||
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
@@ -0,0 +1,38 b'' | |||||
|
1 | # Copyright (C) 2016-2016 RhodeCode GmbH | |||
|
2 | # | |||
|
3 | # This program is free software: you can redistribute it and/or modify | |||
|
4 | # it under the terms of the GNU Affero General Public License, version 3 | |||
|
5 | # (only), as published by the Free Software Foundation. | |||
|
6 | # | |||
|
7 | # This program is distributed in the hope that it will be useful, | |||
|
8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
10 | # GNU General Public License for more details. | |||
|
11 | # | |||
|
12 | # You should have received a copy of the GNU Affero General Public License | |||
|
13 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
|
14 | # | |||
|
15 | # This program is dual-licensed. If you wish to learn more about the | |||
|
16 | # RhodeCode Enterprise Edition, including its added features, Support services, | |||
|
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |||
|
18 | ||||
|
19 | import mock | |||
|
20 | import decorator | |||
|
21 | ||||
|
22 | ||||
|
23 | def assert_fires_events(*expected_events): | |||
|
24 | """ Testing decorator to check if the function fires events in order """ | |||
|
25 | def deco(func): | |||
|
26 | def wrapper(func, *args, **kwargs): | |||
|
27 | with mock.patch('rhodecode.events.trigger') as mock_trigger: | |||
|
28 | result = func(*args, **kwargs) | |||
|
29 | ||||
|
30 | captured_events = [] | |||
|
31 | for call in mock_trigger.call_args_list: | |||
|
32 | event = call[0][0] | |||
|
33 | captured_events.append(type(event)) | |||
|
34 | ||||
|
35 | assert set(captured_events) == set(expected_events) | |||
|
36 | return result | |||
|
37 | return decorator.decorator(wrapper, func) | |||
|
38 | return deco No newline at end of file |
@@ -0,0 +1,68 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | # Copyright (C) 2010-2016 RhodeCode GmbH | |||
|
4 | # | |||
|
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 | |||
|
7 | # (only), as published by the Free Software Foundation. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
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/>. | |||
|
16 | # | |||
|
17 | # This program is dual-licensed. If you wish to learn more about the | |||
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |||
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |||
|
20 | ||||
|
21 | import pytest | |||
|
22 | ||||
|
23 | from rhodecode.tests.events.conftest import assert_fires_events | |||
|
24 | ||||
|
25 | from rhodecode.lib import hooks_base, utils2 | |||
|
26 | from rhodecode.model.repo import RepoModel | |||
|
27 | from rhodecode.events.repo import ( | |||
|
28 | RepoPrePullEvent, RepoPullEvent, | |||
|
29 | RepoPrePushEvent, RepoPushEvent, | |||
|
30 | RepoPreCreateEvent, RepoCreatedEvent, | |||
|
31 | RepoPreDeleteEvent, RepoDeletedEvent, | |||
|
32 | ) | |||
|
33 | ||||
|
34 | ||||
|
35 | @pytest.fixture | |||
|
36 | def scm_extras(user_regular, repo_stub): | |||
|
37 | extras = utils2.AttributeDict({ | |||
|
38 | 'ip': '127.0.0.1', | |||
|
39 | 'username': user_regular.username, | |||
|
40 | 'action': '', | |||
|
41 | 'repository': repo_stub.repo_name, | |||
|
42 | 'scm': repo_stub.scm_instance().alias, | |||
|
43 | 'config': '', | |||
|
44 | 'server_url': 'http://example.com', | |||
|
45 | 'make_lock': None, | |||
|
46 | 'locked_by': [None], | |||
|
47 | 'commit_ids': ['a' * 40] * 3, | |||
|
48 | }) | |||
|
49 | return extras | |||
|
50 | ||||
|
51 | ||||
|
52 | @assert_fires_events( | |||
|
53 | RepoPreCreateEvent, RepoCreatedEvent, RepoPreDeleteEvent, RepoDeletedEvent) | |||
|
54 | def test_create_delete_repo_fires_events(backend): | |||
|
55 | repo = backend.create_repo() | |||
|
56 | RepoModel().delete(repo) | |||
|
57 | ||||
|
58 | ||||
|
59 | @assert_fires_events(RepoPrePushEvent, RepoPushEvent) | |||
|
60 | def test_pull_fires_events(scm_extras): | |||
|
61 | hooks_base.pre_push(scm_extras) | |||
|
62 | hooks_base.post_push(scm_extras) | |||
|
63 | ||||
|
64 | ||||
|
65 | @assert_fires_events(RepoPrePullEvent, RepoPullEvent) | |||
|
66 | def test_push_fires_events(scm_extras): | |||
|
67 | hooks_base.pre_pull(scm_extras) | |||
|
68 | hooks_base.post_pull(scm_extras) |
1 | NO CONTENT: file renamed from rhodecode/interfaces.py to rhodecode/events/interfaces.py |
|
NO CONTENT: file renamed from rhodecode/interfaces.py to rhodecode/events/interfaces.py |
@@ -17,12 +17,13 b'' | |||||
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
18 |
|
18 | |||
19 | from zope.interface import implementer |
|
19 | from zope.interface import implementer | |
20 |
from rhodecode. |
|
20 | from rhodecode.events import RhodecodeEvent | |
|
21 | from rhodecode.events.interfaces import ( | |||
21 | IUserRegistered, IUserPreCreate, IUserPreUpdate) |
|
22 | IUserRegistered, IUserPreCreate, IUserPreUpdate) | |
22 |
|
23 | |||
23 |
|
24 | |||
24 | @implementer(IUserRegistered) |
|
25 | @implementer(IUserRegistered) | |
25 |
class UserRegistered( |
|
26 | class UserRegistered(RhodecodeEvent): | |
26 | """ |
|
27 | """ | |
27 | An instance of this class is emitted as an :term:`event` whenever a user |
|
28 | An instance of this class is emitted as an :term:`event` whenever a user | |
28 | account is registered. |
|
29 | account is registered. | |
@@ -33,7 +34,7 b' class UserRegistered(object):' | |||||
33 |
|
34 | |||
34 |
|
35 | |||
35 | @implementer(IUserPreCreate) |
|
36 | @implementer(IUserPreCreate) | |
36 |
class UserPreCreate( |
|
37 | class UserPreCreate(RhodecodeEvent): | |
37 | """ |
|
38 | """ | |
38 | An instance of this class is emitted as an :term:`event` before a new user |
|
39 | An instance of this class is emitted as an :term:`event` before a new user | |
39 | object is created. |
|
40 | object is created. | |
@@ -43,7 +44,7 b' class UserPreCreate(object):' | |||||
43 |
|
44 | |||
44 |
|
45 | |||
45 | @implementer(IUserPreUpdate) |
|
46 | @implementer(IUserPreUpdate) | |
46 |
class UserPreUpdate( |
|
47 | class UserPreUpdate(RhodecodeEvent): | |
47 | """ |
|
48 | """ | |
48 | An instance of this class is emitted as an :term:`event` before a user |
|
49 | An instance of this class is emitted as an :term:`event` before a user | |
49 | object is updated. |
|
50 | object is updated. |
@@ -27,6 +27,7 b' import os' | |||||
27 | import collections |
|
27 | import collections | |
28 |
|
28 | |||
29 | import rhodecode |
|
29 | import rhodecode | |
|
30 | from rhodecode import events | |||
30 | from rhodecode.lib import helpers as h |
|
31 | from rhodecode.lib import helpers as h | |
31 | from rhodecode.lib.utils import action_logger |
|
32 | from rhodecode.lib.utils import action_logger | |
32 | from rhodecode.lib.utils2 import safe_str |
|
33 | from rhodecode.lib.utils2 import safe_str | |
@@ -102,6 +103,9 b' def pre_push(extras):' | |||||
102 | # Calling hooks after checking the lock, for consistent behavior |
|
103 | # Calling hooks after checking the lock, for consistent behavior | |
103 | pre_push_extension(repo_store_path=Repository.base_path(), **extras) |
|
104 | pre_push_extension(repo_store_path=Repository.base_path(), **extras) | |
104 |
|
105 | |||
|
106 | events.trigger(events.RepoPrePushEvent(repo_name=extras.repository, | |||
|
107 | extras=extras)) | |||
|
108 | ||||
105 | return HookResponse(0, output) |
|
109 | return HookResponse(0, output) | |
106 |
|
110 | |||
107 |
|
111 | |||
@@ -128,6 +132,8 b' def pre_pull(extras):' | |||||
128 |
|
132 | |||
129 | # Calling hooks after checking the lock, for consistent behavior |
|
133 | # Calling hooks after checking the lock, for consistent behavior | |
130 | pre_pull_extension(**extras) |
|
134 | pre_pull_extension(**extras) | |
|
135 | events.trigger(events.RepoPrePullEvent(repo_name=extras.repository, | |||
|
136 | extras=extras)) | |||
131 |
|
137 | |||
132 | return HookResponse(0, output) |
|
138 | return HookResponse(0, output) | |
133 |
|
139 | |||
@@ -138,6 +144,8 b' def post_pull(extras):' | |||||
138 | action = 'pull' |
|
144 | action = 'pull' | |
139 | action_logger(user, action, extras.repository, extras.ip, commit=True) |
|
145 | action_logger(user, action, extras.repository, extras.ip, commit=True) | |
140 |
|
146 | |||
|
147 | events.trigger(events.RepoPullEvent(repo_name=extras.repository, | |||
|
148 | extras=extras)) | |||
141 | # extension hook call |
|
149 | # extension hook call | |
142 | post_pull_extension(**extras) |
|
150 | post_pull_extension(**extras) | |
143 |
|
151 | |||
@@ -171,6 +179,10 b' def post_push(extras):' | |||||
171 | action_logger( |
|
179 | action_logger( | |
172 | extras.username, action, extras.repository, extras.ip, commit=True) |
|
180 | extras.username, action, extras.repository, extras.ip, commit=True) | |
173 |
|
181 | |||
|
182 | events.trigger(events.RepoPushEvent(repo_name=extras.repository, | |||
|
183 | pushed_commit_ids=commit_ids, | |||
|
184 | extras=extras)) | |||
|
185 | ||||
174 | # extension hook call |
|
186 | # extension hook call | |
175 | post_push_extension( |
|
187 | post_push_extension( | |
176 | repo_store_path=Repository.base_path(), |
|
188 | repo_store_path=Repository.base_path(), |
@@ -145,17 +145,6 b' class BaseModel(object):' | |||||
145 | return self._get_instance( |
|
145 | return self._get_instance( | |
146 | db.Permission, permission, callback=db.Permission.get_by_key) |
|
146 | db.Permission, permission, callback=db.Permission.get_by_key) | |
147 |
|
147 | |||
148 | def send_event(self, event): |
|
|||
149 | """ |
|
|||
150 | Helper method to send an event. This wraps the pyramid logic to send an |
|
|||
151 | event. |
|
|||
152 | """ |
|
|||
153 | # For the first step we are using pyramids thread locals here. If the |
|
|||
154 | # event mechanism works out as a good solution we should think about |
|
|||
155 | # passing the registry into the constructor to get rid of it. |
|
|||
156 | registry = get_current_registry() |
|
|||
157 | registry.notify(event) |
|
|||
158 |
|
||||
159 | @classmethod |
|
148 | @classmethod | |
160 | def get_all(cls): |
|
149 | def get_all(cls): | |
161 | """ |
|
150 | """ |
@@ -34,6 +34,7 b' from sqlalchemy.sql import func' | |||||
34 | from sqlalchemy.sql.expression import true, or_ |
|
34 | from sqlalchemy.sql.expression import true, or_ | |
35 | from zope.cachedescriptors.property import Lazy as LazyProperty |
|
35 | from zope.cachedescriptors.property import Lazy as LazyProperty | |
36 |
|
36 | |||
|
37 | from rhodecode import events | |||
37 | from rhodecode.lib import helpers as h |
|
38 | from rhodecode.lib import helpers as h | |
38 | from rhodecode.lib.auth import HasUserGroupPermissionAny |
|
39 | from rhodecode.lib.auth import HasUserGroupPermissionAny | |
39 | from rhodecode.lib.caching_query import FromCache |
|
40 | from rhodecode.lib.caching_query import FromCache | |
@@ -470,6 +471,8 b' class RepoModel(BaseModel):' | |||||
470 | parent_repo = fork_of |
|
471 | parent_repo = fork_of | |
471 | new_repo.fork = parent_repo |
|
472 | new_repo.fork = parent_repo | |
472 |
|
473 | |||
|
474 | events.trigger(events.RepoPreCreateEvent(new_repo)) | |||
|
475 | ||||
473 | self.sa.add(new_repo) |
|
476 | self.sa.add(new_repo) | |
474 |
|
477 | |||
475 | EMPTY_PERM = 'repository.none' |
|
478 | EMPTY_PERM = 'repository.none' | |
@@ -525,11 +528,13 b' class RepoModel(BaseModel):' | |||||
525 | # now automatically start following this repository as owner |
|
528 | # now automatically start following this repository as owner | |
526 | ScmModel(self.sa).toggle_following_repo(new_repo.repo_id, |
|
529 | ScmModel(self.sa).toggle_following_repo(new_repo.repo_id, | |
527 | owner.user_id) |
|
530 | owner.user_id) | |
|
531 | ||||
528 | # we need to flush here, in order to check if database won't |
|
532 | # we need to flush here, in order to check if database won't | |
529 | # throw any exceptions, create filesystem dirs at the very end |
|
533 | # throw any exceptions, create filesystem dirs at the very end | |
530 | self.sa.flush() |
|
534 | self.sa.flush() | |
|
535 | events.trigger(events.RepoCreatedEvent(new_repo)) | |||
|
536 | return new_repo | |||
531 |
|
537 | |||
532 | return new_repo |
|
|||
533 | except Exception: |
|
538 | except Exception: | |
534 | log.error(traceback.format_exc()) |
|
539 | log.error(traceback.format_exc()) | |
535 | raise |
|
540 | raise | |
@@ -633,6 +638,7 b' class RepoModel(BaseModel):' | |||||
633 | raise AttachedForksError() |
|
638 | raise AttachedForksError() | |
634 |
|
639 | |||
635 | old_repo_dict = repo.get_dict() |
|
640 | old_repo_dict = repo.get_dict() | |
|
641 | events.trigger(events.RepoPreDeleteEvent(repo)) | |||
636 | try: |
|
642 | try: | |
637 | self.sa.delete(repo) |
|
643 | self.sa.delete(repo) | |
638 | if fs_remove: |
|
644 | if fs_remove: | |
@@ -644,6 +650,7 b' class RepoModel(BaseModel):' | |||||
644 | 'deleted_on': time.time(), |
|
650 | 'deleted_on': time.time(), | |
645 | }) |
|
651 | }) | |
646 | log_delete_repository(**old_repo_dict) |
|
652 | log_delete_repository(**old_repo_dict) | |
|
653 | events.trigger(events.RepoDeletedEvent(repo)) | |||
647 | except Exception: |
|
654 | except Exception: | |
648 | log.error(traceback.format_exc()) |
|
655 | log.error(traceback.format_exc()) | |
649 | raise |
|
656 | raise |
@@ -32,7 +32,7 b' import ipaddress' | |||||
32 | from sqlalchemy.exc import DatabaseError |
|
32 | from sqlalchemy.exc import DatabaseError | |
33 | from sqlalchemy.sql.expression import true, false |
|
33 | from sqlalchemy.sql.expression import true, false | |
34 |
|
34 | |||
35 | from rhodecode.events import UserPreCreate, UserPreUpdate |
|
35 | from rhodecode import events | |
36 | from rhodecode.lib.utils2 import ( |
|
36 | from rhodecode.lib.utils2 import ( | |
37 | safe_unicode, get_current_rhodecode_user, action_logger_generic, |
|
37 | safe_unicode, get_current_rhodecode_user, action_logger_generic, | |
38 | AttributeDict) |
|
38 | AttributeDict) | |
@@ -270,12 +270,12 b' class UserModel(BaseModel):' | |||||
270 | # raises UserCreationError if it's not allowed for any reason to |
|
270 | # raises UserCreationError if it's not allowed for any reason to | |
271 | # create new active user, this also executes pre-create hooks |
|
271 | # create new active user, this also executes pre-create hooks | |
272 | check_allowed_create_user(user_data, cur_user, strict_check=True) |
|
272 | check_allowed_create_user(user_data, cur_user, strict_check=True) | |
273 |
|
|
273 | events.trigger(events.UserPreCreate(user_data)) | |
274 | new_user = User() |
|
274 | new_user = User() | |
275 | edit = False |
|
275 | edit = False | |
276 | else: |
|
276 | else: | |
277 | log.debug('updating user %s', username) |
|
277 | log.debug('updating user %s', username) | |
278 |
|
|
278 | events.trigger(events.UserPreUpdate(user, user_data)) | |
279 | new_user = user |
|
279 | new_user = user | |
280 | edit = True |
|
280 | edit = True | |
281 |
|
281 |
@@ -28,12 +28,12 b' from rhodecode.lib import hooks_base, ut' | |||||
28 | action_logger=mock.Mock(), |
|
28 | action_logger=mock.Mock(), | |
29 | post_push_extension=mock.Mock(), |
|
29 | post_push_extension=mock.Mock(), | |
30 | Repository=mock.Mock()) |
|
30 | Repository=mock.Mock()) | |
31 | def test_post_push_truncates_commits(): |
|
31 | def test_post_push_truncates_commits(user_regular, repo_stub): | |
32 | extras = { |
|
32 | extras = { | |
33 | 'ip': '127.0.0.1', |
|
33 | 'ip': '127.0.0.1', | |
34 |
'username': |
|
34 | 'username': user_regular.username, | |
35 | 'action': 'push_local', |
|
35 | 'action': 'push_local', | |
36 |
'repository': |
|
36 | 'repository': repo_stub.repo_name, | |
37 | 'scm': 'git', |
|
37 | 'scm': 'git', | |
38 | 'config': '', |
|
38 | 'config': '', | |
39 | 'server_url': 'http://example.com', |
|
39 | 'server_url': 'http://example.com', |
@@ -271,6 +271,7 b' class TestPullRequestModel:' | |||||
271 | '6126b7bfcc82ad2d3deaee22af926b082ce54cc6', |
|
271 | '6126b7bfcc82ad2d3deaee22af926b082ce54cc6', | |
272 | MergeFailureReason.NONE) |
|
272 | MergeFailureReason.NONE) | |
273 |
|
273 | |||
|
274 | merge_extras['repository'] = pull_request.target_repo.repo_name | |||
274 | PullRequestModel().merge( |
|
275 | PullRequestModel().merge( | |
275 | pull_request, pull_request.author, extras=merge_extras) |
|
276 | pull_request, pull_request.author, extras=merge_extras) | |
276 |
|
277 | |||
@@ -308,6 +309,7 b' class TestPullRequestModel:' | |||||
308 | '6126b7bfcc82ad2d3deaee22af926b082ce54cc6', |
|
309 | '6126b7bfcc82ad2d3deaee22af926b082ce54cc6', | |
309 | MergeFailureReason.MERGE_FAILED) |
|
310 | MergeFailureReason.MERGE_FAILED) | |
310 |
|
311 | |||
|
312 | merge_extras['repository'] = pull_request.target_repo.repo_name | |||
311 | PullRequestModel().merge( |
|
313 | PullRequestModel().merge( | |
312 | pull_request, pull_request.author, extras=merge_extras) |
|
314 | pull_request, pull_request.author, extras=merge_extras) | |
313 |
|
315 | |||
@@ -364,6 +366,7 b' class TestIntegrationMerge(object):' | |||||
364 | pull_request = pr_util.create_pull_request( |
|
366 | pull_request = pr_util.create_pull_request( | |
365 | approved=True, mergeable=True) |
|
367 | approved=True, mergeable=True) | |
366 | # TODO: johbo: Needed for sqlite, try to find an automatic way for it |
|
368 | # TODO: johbo: Needed for sqlite, try to find an automatic way for it | |
|
369 | merge_extras['repository'] = pull_request.target_repo.repo_name | |||
367 | Session().commit() |
|
370 | Session().commit() | |
368 |
|
371 | |||
369 | with mock.patch.dict(rhodecode.CONFIG, extra_config, clear=False): |
|
372 | with mock.patch.dict(rhodecode.CONFIG, extra_config, clear=False): | |
@@ -379,6 +382,7 b' class TestIntegrationMerge(object):' | |||||
379 | pull_request = pr_util.create_pull_request( |
|
382 | pull_request = pr_util.create_pull_request( | |
380 | approved=True, mergeable=True) |
|
383 | approved=True, mergeable=True) | |
381 | # TODO: johbo: Needed for sqlite, try to find an automatic way for it |
|
384 | # TODO: johbo: Needed for sqlite, try to find an automatic way for it | |
|
385 | merge_extras['repository'] = pull_request.target_repo.repo_name | |||
382 | Session().commit() |
|
386 | Session().commit() | |
383 |
|
387 | |||
384 | with mock.patch('rhodecode.EXTENSIONS.PRE_PUSH_HOOK') as pre_pull: |
|
388 | with mock.patch('rhodecode.EXTENSIONS.PRE_PUSH_HOOK') as pre_pull: | |
@@ -400,6 +404,7 b' class TestIntegrationMerge(object):' | |||||
400 | # all data is pre-computed, that's why just updating the DB is not |
|
404 | # all data is pre-computed, that's why just updating the DB is not | |
401 | # enough. |
|
405 | # enough. | |
402 | merge_extras['locked_by'] = locked_by |
|
406 | merge_extras['locked_by'] = locked_by | |
|
407 | merge_extras['repository'] = pull_request.target_repo.repo_name | |||
403 | # TODO: johbo: Needed for sqlite, try to find an automatic way for it |
|
408 | # TODO: johbo: Needed for sqlite, try to find an automatic way for it | |
404 | Session().commit() |
|
409 | Session().commit() | |
405 | merge_status = PullRequestModel().merge( |
|
410 | merge_status = PullRequestModel().merge( |
General Comments 0
You need to be logged in to leave comments.
Login now