Show More
@@ -22,7 +22,8 b'' | |||||
22 | import pytest |
|
22 | import pytest | |
23 |
|
23 | |||
24 | from rhodecode.model.repo import RepoModel |
|
24 | from rhodecode.model.repo import RepoModel | |
25 |
from rhodecode.api.tests.utils import |
|
25 | from rhodecode.api.tests.utils import ( | |
|
26 | build_data, api_call, assert_ok, assert_error, jsonify) | |||
26 | from rhodecode.model.db import User |
|
27 | from rhodecode.model.db import User | |
27 |
|
28 | |||
28 |
|
29 | |||
@@ -40,6 +41,76 b' class TestGetRepos(object):' | |||||
40 | expected = ret |
|
41 | expected = ret | |
41 | assert_ok(id_, expected, given=response.body) |
|
42 | assert_ok(id_, expected, given=response.body) | |
42 |
|
43 | |||
|
44 | def test_api_get_repos_only_toplevel(self, user_util): | |||
|
45 | repo_group = user_util.create_repo_group(auto_cleanup=True) | |||
|
46 | user_util.create_repo(parent=repo_group) | |||
|
47 | ||||
|
48 | id_, params = build_data(self.apikey, 'get_repos', traverse=0) | |||
|
49 | response = api_call(self.app, params) | |||
|
50 | ||||
|
51 | result = [] | |||
|
52 | for repo in RepoModel().get_repos_for_root(root=None): | |||
|
53 | result.append(repo.get_api_data(include_secrets=True)) | |||
|
54 | expected = jsonify(result) | |||
|
55 | ||||
|
56 | assert_ok(id_, expected, given=response.body) | |||
|
57 | ||||
|
58 | def test_api_get_repos_with_wrong_root(self): | |||
|
59 | id_, params = build_data(self.apikey, 'get_repos', root='abracadabra') | |||
|
60 | response = api_call(self.app, params) | |||
|
61 | ||||
|
62 | expected = 'Root repository group `abracadabra` does not exist' | |||
|
63 | assert_error(id_, expected, given=response.body) | |||
|
64 | ||||
|
65 | def test_api_get_repos_with_root(self, user_util): | |||
|
66 | repo_group = user_util.create_repo_group(auto_cleanup=True) | |||
|
67 | repo_group_name = repo_group.group_name | |||
|
68 | ||||
|
69 | user_util.create_repo(parent=repo_group) | |||
|
70 | user_util.create_repo(parent=repo_group) | |||
|
71 | ||||
|
72 | # nested, should not show up | |||
|
73 | user_util._test_name = '{}/'.format(repo_group_name) | |||
|
74 | sub_repo_group = user_util.create_repo_group(auto_cleanup=True) | |||
|
75 | user_util.create_repo(parent=sub_repo_group) | |||
|
76 | ||||
|
77 | id_, params = build_data(self.apikey, 'get_repos', | |||
|
78 | root=repo_group_name, traverse=0) | |||
|
79 | response = api_call(self.app, params) | |||
|
80 | ||||
|
81 | result = [] | |||
|
82 | for repo in RepoModel().get_repos_for_root(repo_group): | |||
|
83 | result.append(repo.get_api_data(include_secrets=True)) | |||
|
84 | ||||
|
85 | assert len(result) == 2 | |||
|
86 | expected = jsonify(result) | |||
|
87 | assert_ok(id_, expected, given=response.body) | |||
|
88 | ||||
|
89 | def test_api_get_repos_with_root_and_traverse(self, user_util): | |||
|
90 | repo_group = user_util.create_repo_group(auto_cleanup=True) | |||
|
91 | repo_group_name = repo_group.group_name | |||
|
92 | ||||
|
93 | user_util.create_repo(parent=repo_group) | |||
|
94 | user_util.create_repo(parent=repo_group) | |||
|
95 | ||||
|
96 | # nested, should not show up | |||
|
97 | user_util._test_name = '{}/'.format(repo_group_name) | |||
|
98 | sub_repo_group = user_util.create_repo_group(auto_cleanup=True) | |||
|
99 | user_util.create_repo(parent=sub_repo_group) | |||
|
100 | ||||
|
101 | id_, params = build_data(self.apikey, 'get_repos', | |||
|
102 | root=repo_group_name, traverse=1) | |||
|
103 | response = api_call(self.app, params) | |||
|
104 | ||||
|
105 | result = [] | |||
|
106 | for repo in RepoModel().get_repos_for_root( | |||
|
107 | repo_group_name, traverse=True): | |||
|
108 | result.append(repo.get_api_data(include_secrets=True)) | |||
|
109 | ||||
|
110 | assert len(result) == 3 | |||
|
111 | expected = jsonify(result) | |||
|
112 | assert_ok(id_, expected, given=response.body) | |||
|
113 | ||||
43 | def test_api_get_repos_non_admin(self): |
|
114 | def test_api_get_repos_non_admin(self): | |
44 | id_, params = build_data(self.apikey_regular, 'get_repos') |
|
115 | id_, params = build_data(self.apikey_regular, 'get_repos') | |
45 | response = api_call(self.app, params) |
|
116 | response = api_call(self.app, params) |
@@ -36,7 +36,7 b' from rhodecode.lib.ext_json import json' | |||||
36 | from rhodecode.model.changeset_status import ChangesetStatusModel |
|
36 | from rhodecode.model.changeset_status import ChangesetStatusModel | |
37 | from rhodecode.model.comment import ChangesetCommentsModel |
|
37 | from rhodecode.model.comment import ChangesetCommentsModel | |
38 | from rhodecode.model.db import ( |
|
38 | from rhodecode.model.db import ( | |
39 | Session, ChangesetStatus, RepositoryField, Repository) |
|
39 | Session, ChangesetStatus, RepositoryField, Repository, RepoGroup) | |
40 | from rhodecode.model.repo import RepoModel |
|
40 | from rhodecode.model.repo import RepoModel | |
41 | from rhodecode.model.scm import ScmModel, RepoList |
|
41 | from rhodecode.model.scm import ScmModel, RepoList | |
42 | from rhodecode.model.settings import SettingsModel, VcsSettingsModel |
|
42 | from rhodecode.model.settings import SettingsModel, VcsSettingsModel | |
@@ -217,7 +217,7 b' def get_repo(request, apiuser, repoid, c' | |||||
217 |
|
217 | |||
218 |
|
218 | |||
219 | @jsonrpc_method() |
|
219 | @jsonrpc_method() | |
220 | def get_repos(request, apiuser): |
|
220 | def get_repos(request, apiuser, root=Optional(None), traverse=Optional(True)): | |
221 | """ |
|
221 | """ | |
222 | Lists all existing repositories. |
|
222 | Lists all existing repositories. | |
223 |
|
223 | |||
@@ -226,6 +226,14 b' def get_repos(request, apiuser):' | |||||
226 |
|
226 | |||
227 | :param apiuser: This is filled automatically from the |authtoken|. |
|
227 | :param apiuser: This is filled automatically from the |authtoken|. | |
228 | :type apiuser: AuthUser |
|
228 | :type apiuser: AuthUser | |
|
229 | :param root: specify root repository group to fetch repositories. | |||
|
230 | filters the returned repositories to be members of given root group. | |||
|
231 | :type root: Optional(None) | |||
|
232 | :param traverse: traverse given root into subrepositories. With this flag | |||
|
233 | set to False, it will only return top-level repositories from `root`. | |||
|
234 | if root is empty it will return just top-level repositories. | |||
|
235 | :type traverse: Optional(True) | |||
|
236 | ||||
229 |
|
237 | |||
230 | Example output: |
|
238 | Example output: | |
231 |
|
239 | |||
@@ -257,8 +265,28 b' def get_repos(request, apiuser):' | |||||
257 | _perms = ('repository.read', 'repository.write', 'repository.admin',) |
|
265 | _perms = ('repository.read', 'repository.write', 'repository.admin',) | |
258 | extras = {'user': apiuser} |
|
266 | extras = {'user': apiuser} | |
259 |
|
267 | |||
260 | repo_list = RepoList( |
|
268 | root = Optional.extract(root) | |
261 | RepoModel().get_all(), perm_set=_perms, extra_kwargs=extras) |
|
269 | traverse = Optional.extract(traverse, binary=True) | |
|
270 | ||||
|
271 | if root: | |||
|
272 | # verify parent existance, if it's empty return an error | |||
|
273 | parent = RepoGroup.get_by_group_name(root) | |||
|
274 | if not parent: | |||
|
275 | raise JSONRPCError( | |||
|
276 | 'Root repository group `{}` does not exist'.format(root)) | |||
|
277 | ||||
|
278 | if traverse: | |||
|
279 | repos = RepoModel().get_repos_for_root(root=root, traverse=traverse) | |||
|
280 | else: | |||
|
281 | repos = RepoModel().get_repos_for_root(root=parent) | |||
|
282 | else: | |||
|
283 | if traverse: | |||
|
284 | repos = RepoModel().get_all() | |||
|
285 | else: | |||
|
286 | # return just top-level | |||
|
287 | repos = RepoModel().get_repos_for_root(root=None) | |||
|
288 | ||||
|
289 | repo_list = RepoList(repos, perm_set=_perms, extra_kwargs=extras) | |||
262 | return [repo.get_api_data(include_secrets=include_secrets) |
|
290 | return [repo.get_api_data(include_secrets=include_secrets) | |
263 | for repo in repo_list] |
|
291 | for repo in repo_list] | |
264 |
|
292 |
@@ -143,6 +143,19 b' class RepoModel(BaseModel):' | |||||
143 |
|
143 | |||
144 | return None |
|
144 | return None | |
145 |
|
145 | |||
|
146 | def get_repos_for_root(self, root, traverse=False): | |||
|
147 | if traverse: | |||
|
148 | like_expression = u'{}%'.format(safe_unicode(root)) | |||
|
149 | repos = Repository.query().filter( | |||
|
150 | Repository.repo_name.like(like_expression)).all() | |||
|
151 | else: | |||
|
152 | if root and not isinstance(root, RepoGroup): | |||
|
153 | raise ValueError( | |||
|
154 | 'Root must be an instance ' | |||
|
155 | 'of RepoGroup, got:{} instead'.format(type(root))) | |||
|
156 | repos = Repository.query().filter(Repository.group == root).all() | |||
|
157 | return repos | |||
|
158 | ||||
146 | def get_url(self, repo): |
|
159 | def get_url(self, repo): | |
147 | return h.url('summary_home', repo_name=safe_str(repo.repo_name), |
|
160 | return h.url('summary_home', repo_name=safe_str(repo.repo_name), | |
148 | qualified=True) |
|
161 | qualified=True) |
General Comments 0
You need to be logged in to leave comments.
Login now