Show More
@@ -1,522 +1,536 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 | """ |
|
2 | """ | |
3 | rhodecode.controllers.admin.repos |
|
3 | rhodecode.controllers.admin.repos | |
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
5 |
|
5 | |||
6 | Repositories controller for RhodeCode |
|
6 | Repositories controller for RhodeCode | |
7 |
|
7 | |||
8 | :created_on: Apr 7, 2010 |
|
8 | :created_on: Apr 7, 2010 | |
9 | :author: marcink |
|
9 | :author: marcink | |
10 | :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com> |
|
10 | :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com> | |
11 | :license: GPLv3, see COPYING for more details. |
|
11 | :license: GPLv3, see COPYING for more details. | |
12 | """ |
|
12 | """ | |
13 | # This program is free software: you can redistribute it and/or modify |
|
13 | # This program is free software: you can redistribute it and/or modify | |
14 | # it under the terms of the GNU General Public License as published by |
|
14 | # it under the terms of the GNU General Public License as published by | |
15 | # the Free Software Foundation, either version 3 of the License, or |
|
15 | # the Free Software Foundation, either version 3 of the License, or | |
16 | # (at your option) any later version. |
|
16 | # (at your option) any later version. | |
17 | # |
|
17 | # | |
18 | # This program is distributed in the hope that it will be useful, |
|
18 | # This program is distributed in the hope that it will be useful, | |
19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | # GNU General Public License for more details. |
|
21 | # GNU General Public License for more details. | |
22 | # |
|
22 | # | |
23 | # You should have received a copy of the GNU General Public License |
|
23 | # You should have received a copy of the GNU General Public License | |
24 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
24 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
25 |
|
25 | |||
26 | import logging |
|
26 | import logging | |
27 | import traceback |
|
27 | import traceback | |
28 | import formencode |
|
28 | import formencode | |
29 | from formencode import htmlfill |
|
29 | from formencode import htmlfill | |
30 |
|
30 | |||
31 | from webob.exc import HTTPInternalServerError, HTTPForbidden |
|
31 | from webob.exc import HTTPInternalServerError, HTTPForbidden | |
32 | from pylons import request, session, tmpl_context as c, url |
|
32 | from pylons import request, session, tmpl_context as c, url | |
33 | from pylons.controllers.util import redirect |
|
33 | from pylons.controllers.util import redirect | |
34 | from pylons.i18n.translation import _ |
|
34 | from pylons.i18n.translation import _ | |
35 | from sqlalchemy.exc import IntegrityError |
|
35 | from sqlalchemy.exc import IntegrityError | |
36 |
|
36 | |||
37 | import rhodecode |
|
37 | import rhodecode | |
38 | from rhodecode.lib import helpers as h |
|
38 | from rhodecode.lib import helpers as h | |
39 | from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \ |
|
39 | from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \ | |
40 | HasPermissionAnyDecorator, HasRepoPermissionAllDecorator, NotAnonymous,\ |
|
40 | HasPermissionAnyDecorator, HasRepoPermissionAllDecorator, NotAnonymous,\ | |
41 | HasPermissionAny, HasReposGroupPermissionAny |
|
41 | HasPermissionAny, HasReposGroupPermissionAny | |
42 | from rhodecode.lib.base import BaseRepoController, render |
|
42 | from rhodecode.lib.base import BaseRepoController, render | |
43 | from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug |
|
43 | from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug | |
44 | from rhodecode.lib.helpers import get_token |
|
44 | from rhodecode.lib.helpers import get_token | |
45 | from rhodecode.model.meta import Session |
|
45 | from rhodecode.model.meta import Session | |
46 | from rhodecode.model.db import User, Repository, UserFollowing, RepoGroup,\ |
|
46 | from rhodecode.model.db import User, Repository, UserFollowing, RepoGroup,\ | |
47 | RhodeCodeSetting, RepositoryField |
|
47 | RhodeCodeSetting, RepositoryField | |
48 | from rhodecode.model.forms import RepoForm, RepoFieldForm |
|
48 | from rhodecode.model.forms import RepoForm, RepoFieldForm | |
49 | from rhodecode.model.scm import ScmModel, GroupList |
|
49 | from rhodecode.model.scm import ScmModel, GroupList | |
50 | from rhodecode.model.repo import RepoModel |
|
50 | from rhodecode.model.repo import RepoModel | |
51 | from rhodecode.lib.compat import json |
|
51 | from rhodecode.lib.compat import json | |
52 | from sqlalchemy.sql.expression import func |
|
52 | from sqlalchemy.sql.expression import func | |
53 |
|
53 | |||
54 | log = logging.getLogger(__name__) |
|
54 | log = logging.getLogger(__name__) | |
55 |
|
55 | |||
56 |
|
56 | |||
57 | class ReposController(BaseRepoController): |
|
57 | class ReposController(BaseRepoController): | |
58 | """ |
|
58 | """ | |
59 | REST Controller styled on the Atom Publishing Protocol""" |
|
59 | REST Controller styled on the Atom Publishing Protocol""" | |
60 | # To properly map this controller, ensure your config/routing.py |
|
60 | # To properly map this controller, ensure your config/routing.py | |
61 | # file has a resource setup: |
|
61 | # file has a resource setup: | |
62 | # map.resource('repo', 'repos') |
|
62 | # map.resource('repo', 'repos') | |
63 |
|
63 | |||
64 | @LoginRequired() |
|
64 | @LoginRequired() | |
65 | def __before__(self): |
|
65 | def __before__(self): | |
66 | c.admin_user = session.get('admin_user') |
|
66 | c.admin_user = session.get('admin_user') | |
67 | c.admin_username = session.get('admin_username') |
|
67 | c.admin_username = session.get('admin_username') | |
68 | super(ReposController, self).__before__() |
|
68 | super(ReposController, self).__before__() | |
69 |
|
69 | |||
70 | def __load_defaults(self): |
|
70 | def __load_defaults(self): | |
71 | acl_groups = GroupList(RepoGroup.query().all(), |
|
71 | acl_groups = GroupList(RepoGroup.query().all(), | |
72 | perm_set=['group.write', 'group.admin']) |
|
72 | perm_set=['group.write', 'group.admin']) | |
73 | c.repo_groups = RepoGroup.groups_choices(groups=acl_groups) |
|
73 | c.repo_groups = RepoGroup.groups_choices(groups=acl_groups) | |
74 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) |
|
74 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) | |
75 |
|
75 | |||
76 | repo_model = RepoModel() |
|
76 | repo_model = RepoModel() | |
77 | c.users_array = repo_model.get_users_js() |
|
77 | c.users_array = repo_model.get_users_js() | |
78 | c.users_groups_array = repo_model.get_users_groups_js() |
|
78 | c.users_groups_array = repo_model.get_users_groups_js() | |
79 | choices, c.landing_revs = ScmModel().get_repo_landing_revs() |
|
79 | choices, c.landing_revs = ScmModel().get_repo_landing_revs() | |
80 | c.landing_revs_choices = choices |
|
80 | c.landing_revs_choices = choices | |
81 |
|
81 | |||
82 | def __load_data(self, repo_name=None): |
|
82 | def __load_data(self, repo_name=None): | |
83 | """ |
|
83 | """ | |
84 | Load defaults settings for edit, and update |
|
84 | Load defaults settings for edit, and update | |
85 |
|
85 | |||
86 | :param repo_name: |
|
86 | :param repo_name: | |
87 | """ |
|
87 | """ | |
88 | self.__load_defaults() |
|
88 | self.__load_defaults() | |
89 |
|
89 | |||
90 | c.repo_info = db_repo = Repository.get_by_repo_name(repo_name) |
|
90 | c.repo_info = db_repo = Repository.get_by_repo_name(repo_name) | |
91 | repo = db_repo.scm_instance |
|
91 | repo = db_repo.scm_instance | |
92 |
|
92 | |||
93 | if c.repo_info is None: |
|
93 | if c.repo_info is None: | |
94 | h.not_mapped_error(repo_name) |
|
94 | h.not_mapped_error(repo_name) | |
95 | return redirect(url('repos')) |
|
95 | return redirect(url('repos')) | |
96 |
|
96 | |||
97 | ##override defaults for exact repo info here git/hg etc |
|
97 | ##override defaults for exact repo info here git/hg etc | |
98 | choices, c.landing_revs = ScmModel().get_repo_landing_revs(c.repo_info) |
|
98 | choices, c.landing_revs = ScmModel().get_repo_landing_revs(c.repo_info) | |
99 | c.landing_revs_choices = choices |
|
99 | c.landing_revs_choices = choices | |
100 |
|
100 | |||
101 | c.default_user_id = User.get_by_username('default').user_id |
|
101 | c.default_user_id = User.get_by_username('default').user_id | |
102 | c.in_public_journal = UserFollowing.query()\ |
|
102 | c.in_public_journal = UserFollowing.query()\ | |
103 | .filter(UserFollowing.user_id == c.default_user_id)\ |
|
103 | .filter(UserFollowing.user_id == c.default_user_id)\ | |
104 | .filter(UserFollowing.follows_repository == c.repo_info).scalar() |
|
104 | .filter(UserFollowing.follows_repository == c.repo_info).scalar() | |
105 |
|
105 | |||
106 | if c.repo_info.stats: |
|
106 | if c.repo_info.stats: | |
107 | # this is on what revision we ended up so we add +1 for count |
|
107 | # this is on what revision we ended up so we add +1 for count | |
108 | last_rev = c.repo_info.stats.stat_on_revision + 1 |
|
108 | last_rev = c.repo_info.stats.stat_on_revision + 1 | |
109 | else: |
|
109 | else: | |
110 | last_rev = 0 |
|
110 | last_rev = 0 | |
111 | c.stats_revision = last_rev |
|
111 | c.stats_revision = last_rev | |
112 |
|
112 | |||
113 | c.repo_last_rev = repo.count() if repo.revisions else 0 |
|
113 | c.repo_last_rev = repo.count() if repo.revisions else 0 | |
114 |
|
114 | |||
115 | if last_rev == 0 or c.repo_last_rev == 0: |
|
115 | if last_rev == 0 or c.repo_last_rev == 0: | |
116 | c.stats_percentage = 0 |
|
116 | c.stats_percentage = 0 | |
117 | else: |
|
117 | else: | |
118 | c.stats_percentage = '%.2f' % ((float((last_rev)) / |
|
118 | c.stats_percentage = '%.2f' % ((float((last_rev)) / | |
119 | c.repo_last_rev) * 100) |
|
119 | c.repo_last_rev) * 100) | |
120 |
|
120 | |||
121 | c.repo_fields = RepositoryField.query()\ |
|
121 | c.repo_fields = RepositoryField.query()\ | |
122 | .filter(RepositoryField.repository == db_repo).all() |
|
122 | .filter(RepositoryField.repository == db_repo).all() | |
123 |
|
123 | |||
124 | defaults = RepoModel()._get_defaults(repo_name) |
|
124 | defaults = RepoModel()._get_defaults(repo_name) | |
125 |
|
125 | |||
126 | c.repos_list = [('', _('--REMOVE FORK--'))] |
|
126 | c.repos_list = [('', _('--REMOVE FORK--'))] | |
127 | c.repos_list += [(x.repo_id, x.repo_name) for x in |
|
127 | c.repos_list += [(x.repo_id, x.repo_name) for x in | |
128 | Repository.query().order_by(Repository.repo_name).all() |
|
128 | Repository.query().order_by(Repository.repo_name).all() | |
129 | if x.repo_id != c.repo_info.repo_id] |
|
129 | if x.repo_id != c.repo_info.repo_id] | |
130 |
|
130 | |||
131 | defaults['id_fork_of'] = db_repo.fork.repo_id if db_repo.fork else '' |
|
131 | defaults['id_fork_of'] = db_repo.fork.repo_id if db_repo.fork else '' | |
132 | return defaults |
|
132 | return defaults | |
133 |
|
133 | |||
134 | @HasPermissionAllDecorator('hg.admin') |
|
134 | @HasPermissionAllDecorator('hg.admin') | |
135 | def index(self, format='html'): |
|
135 | def index(self, format='html'): | |
136 | """GET /repos: All items in the collection""" |
|
136 | """GET /repos: All items in the collection""" | |
137 | # url('repos') |
|
137 | # url('repos') | |
138 |
|
138 | |||
139 | c.repos_list = Repository.query()\ |
|
139 | c.repos_list = Repository.query()\ | |
140 | .order_by(func.lower(Repository.repo_name))\ |
|
140 | .order_by(func.lower(Repository.repo_name))\ | |
141 | .all() |
|
141 | .all() | |
142 |
|
142 | |||
143 | repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list, |
|
143 | repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list, | |
144 | admin=True, |
|
144 | admin=True, | |
145 | super_user_actions=True) |
|
145 | super_user_actions=True) | |
146 | #json used to render the grid |
|
146 | #json used to render the grid | |
147 | c.data = json.dumps(repos_data) |
|
147 | c.data = json.dumps(repos_data) | |
148 |
|
148 | |||
149 | return render('admin/repos/repos.html') |
|
149 | return render('admin/repos/repos.html') | |
150 |
|
150 | |||
151 | @NotAnonymous() |
|
151 | @NotAnonymous() | |
152 | def create(self): |
|
152 | def create(self): | |
153 | """ |
|
153 | """ | |
154 | POST /repos: Create a new item""" |
|
154 | POST /repos: Create a new item""" | |
155 | # url('repos') |
|
155 | # url('repos') | |
156 |
|
156 | |||
157 | self.__load_defaults() |
|
157 | self.__load_defaults() | |
158 | form_result = {} |
|
158 | form_result = {} | |
159 | try: |
|
159 | try: | |
160 | form_result = RepoForm(repo_groups=c.repo_groups_choices, |
|
160 | form_result = RepoForm(repo_groups=c.repo_groups_choices, | |
161 | landing_revs=c.landing_revs_choices)()\ |
|
161 | landing_revs=c.landing_revs_choices)()\ | |
162 | .to_python(dict(request.POST)) |
|
162 | .to_python(dict(request.POST)) | |
163 |
|
163 | |||
164 | new_repo = RepoModel().create(form_result, |
|
164 | new_repo = RepoModel().create(form_result, | |
165 | self.rhodecode_user.user_id) |
|
165 | self.rhodecode_user.user_id) | |
166 | if form_result['clone_uri']: |
|
166 | if form_result['clone_uri']: | |
167 | h.flash(_('created repository %s from %s') \ |
|
167 | h.flash(_('created repository %s from %s') \ | |
168 | % (form_result['repo_name'], form_result['clone_uri']), |
|
168 | % (form_result['repo_name'], form_result['clone_uri']), | |
169 | category='success') |
|
169 | category='success') | |
170 | else: |
|
170 | else: | |
171 | h.flash(_('created repository %s') % form_result['repo_name'], |
|
171 | h.flash(_('created repository %s') % form_result['repo_name'], | |
172 | category='success') |
|
172 | category='success') | |
173 |
|
173 | |||
174 | if request.POST.get('user_created'): |
|
174 | if request.POST.get('user_created'): | |
175 | # created by regular non admin user |
|
175 | # created by regular non admin user | |
176 | action_logger(self.rhodecode_user, 'user_created_repo', |
|
176 | action_logger(self.rhodecode_user, 'user_created_repo', | |
177 | form_result['repo_name_full'], self.ip_addr, |
|
177 | form_result['repo_name_full'], self.ip_addr, | |
178 | self.sa) |
|
178 | self.sa) | |
179 | else: |
|
179 | else: | |
180 | action_logger(self.rhodecode_user, 'admin_created_repo', |
|
180 | action_logger(self.rhodecode_user, 'admin_created_repo', | |
181 | form_result['repo_name_full'], self.ip_addr, |
|
181 | form_result['repo_name_full'], self.ip_addr, | |
182 | self.sa) |
|
182 | self.sa) | |
183 | Session().commit() |
|
183 | Session().commit() | |
184 | except formencode.Invalid, errors: |
|
184 | except formencode.Invalid, errors: | |
185 | return htmlfill.render( |
|
185 | return htmlfill.render( | |
186 | render('admin/repos/repo_add.html'), |
|
186 | render('admin/repos/repo_add.html'), | |
187 | defaults=errors.value, |
|
187 | defaults=errors.value, | |
188 | errors=errors.error_dict or {}, |
|
188 | errors=errors.error_dict or {}, | |
189 | prefix_error=False, |
|
189 | prefix_error=False, | |
190 | encoding="UTF-8") |
|
190 | encoding="UTF-8") | |
191 |
|
191 | |||
192 | except Exception: |
|
192 | except Exception: | |
193 | log.error(traceback.format_exc()) |
|
193 | log.error(traceback.format_exc()) | |
194 | msg = _('error occurred during creation of repository %s') \ |
|
194 | msg = _('error occurred during creation of repository %s') \ | |
195 | % form_result.get('repo_name') |
|
195 | % form_result.get('repo_name') | |
196 | h.flash(msg, category='error') |
|
196 | h.flash(msg, category='error') | |
197 | if c.rhodecode_user.is_admin: |
|
197 | if c.rhodecode_user.is_admin: | |
198 | return redirect(url('repos')) |
|
198 | return redirect(url('repos')) | |
199 | return redirect(url('home')) |
|
199 | return redirect(url('home')) | |
200 | #redirect to our new repo ! |
|
200 | #redirect to our new repo ! | |
201 | return redirect(url('summary_home', repo_name=new_repo.repo_name)) |
|
201 | return redirect(url('summary_home', repo_name=new_repo.repo_name)) | |
202 |
|
202 | |||
203 | @HasPermissionAllDecorator('hg.admin') |
|
203 | @HasPermissionAllDecorator('hg.admin') | |
204 | def new(self, format='html'): |
|
204 | def new(self, format='html'): | |
205 | """ |
|
205 | """ | |
206 | WARNING: this function is depracated see settings.create_repo !! |
|
206 | WARNING: this function is depracated see settings.create_repo !! | |
207 |
|
207 | |||
208 | GET /repos/new: Form to create a new item |
|
208 | GET /repos/new: Form to create a new item | |
209 | """ |
|
209 | """ | |
210 |
|
210 | |||
211 | parent_group = request.GET.get('parent_group') |
|
211 | parent_group = request.GET.get('parent_group') | |
212 | self.__load_defaults() |
|
212 | self.__load_defaults() | |
213 | ## apply the defaults from defaults page |
|
213 | ## apply the defaults from defaults page | |
214 | defaults = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True) |
|
214 | defaults = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True) | |
215 | if parent_group: |
|
215 | if parent_group: | |
216 | defaults.update({'repo_group': parent_group}) |
|
216 | defaults.update({'repo_group': parent_group}) | |
217 |
|
217 | |||
218 | return htmlfill.render( |
|
218 | return htmlfill.render( | |
219 | render('admin/repos/repo_add.html'), |
|
219 | render('admin/repos/repo_add.html'), | |
220 | defaults=defaults, |
|
220 | defaults=defaults, | |
221 | errors={}, |
|
221 | errors={}, | |
222 | prefix_error=False, |
|
222 | prefix_error=False, | |
223 | encoding="UTF-8" |
|
223 | encoding="UTF-8" | |
224 | ) |
|
224 | ) | |
225 |
|
225 | |||
226 | @HasPermissionAllDecorator('hg.admin') |
|
226 | @HasPermissionAllDecorator('hg.admin') | |
227 | def update(self, repo_name): |
|
227 | def update(self, repo_name): | |
228 | """ |
|
228 | """ | |
229 | PUT /repos/repo_name: Update an existing item""" |
|
229 | PUT /repos/repo_name: Update an existing item""" | |
230 | # Forms posted to this method should contain a hidden field: |
|
230 | # Forms posted to this method should contain a hidden field: | |
231 | # <input type="hidden" name="_method" value="PUT" /> |
|
231 | # <input type="hidden" name="_method" value="PUT" /> | |
232 | # Or using helpers: |
|
232 | # Or using helpers: | |
233 | # h.form(url('repo', repo_name=ID), |
|
233 | # h.form(url('repo', repo_name=ID), | |
234 | # method='put') |
|
234 | # method='put') | |
235 | # url('repo', repo_name=ID) |
|
235 | # url('repo', repo_name=ID) | |
236 | self.__load_defaults() |
|
236 | self.__load_defaults() | |
237 | repo_model = RepoModel() |
|
237 | repo_model = RepoModel() | |
238 | changed_name = repo_name |
|
238 | changed_name = repo_name | |
239 | #override the choices with extracted revisions ! |
|
239 | #override the choices with extracted revisions ! | |
240 | choices, c.landing_revs = ScmModel().get_repo_landing_revs(repo_name) |
|
240 | choices, c.landing_revs = ScmModel().get_repo_landing_revs(repo_name) | |
241 | c.landing_revs_choices = choices |
|
241 | c.landing_revs_choices = choices | |
242 |
|
242 | |||
243 | _form = RepoForm(edit=True, old_data={'repo_name': repo_name}, |
|
243 | _form = RepoForm(edit=True, old_data={'repo_name': repo_name}, | |
244 | repo_groups=c.repo_groups_choices, |
|
244 | repo_groups=c.repo_groups_choices, | |
245 | landing_revs=c.landing_revs_choices)() |
|
245 | landing_revs=c.landing_revs_choices)() | |
246 | try: |
|
246 | try: | |
247 | form_result = _form.to_python(dict(request.POST)) |
|
247 | form_result = _form.to_python(dict(request.POST)) | |
248 | repo = repo_model.update(repo_name, **form_result) |
|
248 | repo = repo_model.update(repo_name, **form_result) | |
249 | invalidate_cache('get_repo_cached_%s' % repo_name) |
|
249 | invalidate_cache('get_repo_cached_%s' % repo_name) | |
250 | h.flash(_('Repository %s updated successfully') % repo_name, |
|
250 | h.flash(_('Repository %s updated successfully') % repo_name, | |
251 | category='success') |
|
251 | category='success') | |
252 | changed_name = repo.repo_name |
|
252 | changed_name = repo.repo_name | |
253 | action_logger(self.rhodecode_user, 'admin_updated_repo', |
|
253 | action_logger(self.rhodecode_user, 'admin_updated_repo', | |
254 | changed_name, self.ip_addr, self.sa) |
|
254 | changed_name, self.ip_addr, self.sa) | |
255 | Session().commit() |
|
255 | Session().commit() | |
256 | except formencode.Invalid, errors: |
|
256 | except formencode.Invalid, errors: | |
257 | defaults = self.__load_data(repo_name) |
|
257 | defaults = self.__load_data(repo_name) | |
258 | defaults.update(errors.value) |
|
258 | defaults.update(errors.value) | |
259 | return htmlfill.render( |
|
259 | return htmlfill.render( | |
260 | render('admin/repos/repo_edit.html'), |
|
260 | render('admin/repos/repo_edit.html'), | |
261 | defaults=defaults, |
|
261 | defaults=defaults, | |
262 | errors=errors.error_dict or {}, |
|
262 | errors=errors.error_dict or {}, | |
263 | prefix_error=False, |
|
263 | prefix_error=False, | |
264 | encoding="UTF-8") |
|
264 | encoding="UTF-8") | |
265 |
|
265 | |||
266 | except Exception: |
|
266 | except Exception: | |
267 | log.error(traceback.format_exc()) |
|
267 | log.error(traceback.format_exc()) | |
268 | h.flash(_('error occurred during update of repository %s') \ |
|
268 | h.flash(_('error occurred during update of repository %s') \ | |
269 | % repo_name, category='error') |
|
269 | % repo_name, category='error') | |
270 | return redirect(url('edit_repo', repo_name=changed_name)) |
|
270 | return redirect(url('edit_repo', repo_name=changed_name)) | |
271 |
|
271 | |||
272 | @HasPermissionAllDecorator('hg.admin') |
|
272 | @HasPermissionAllDecorator('hg.admin') | |
273 | def delete(self, repo_name): |
|
273 | def delete(self, repo_name): | |
274 | """ |
|
274 | """ | |
275 | DELETE /repos/repo_name: Delete an existing item""" |
|
275 | DELETE /repos/repo_name: Delete an existing item""" | |
276 | # Forms posted to this method should contain a hidden field: |
|
276 | # Forms posted to this method should contain a hidden field: | |
277 | # <input type="hidden" name="_method" value="DELETE" /> |
|
277 | # <input type="hidden" name="_method" value="DELETE" /> | |
278 | # Or using helpers: |
|
278 | # Or using helpers: | |
279 | # h.form(url('repo', repo_name=ID), |
|
279 | # h.form(url('repo', repo_name=ID), | |
280 | # method='delete') |
|
280 | # method='delete') | |
281 | # url('repo', repo_name=ID) |
|
281 | # url('repo', repo_name=ID) | |
282 |
|
282 | |||
283 | repo_model = RepoModel() |
|
283 | repo_model = RepoModel() | |
284 | repo = repo_model.get_by_repo_name(repo_name) |
|
284 | repo = repo_model.get_by_repo_name(repo_name) | |
285 | if not repo: |
|
285 | if not repo: | |
286 | h.not_mapped_error(repo_name) |
|
286 | h.not_mapped_error(repo_name) | |
287 | return redirect(url('repos')) |
|
287 | return redirect(url('repos')) | |
288 | try: |
|
288 | try: | |
|
289 | _forks = repo.forks.count() | |||
|
290 | if _forks and request.POST.get('forks'): | |||
|
291 | do = request.POST['forks'] | |||
|
292 | if do == 'detach_forks': | |||
|
293 | for r in repo.forks: | |||
|
294 | log.debug('Detaching fork %s from repo %s' % (r, repo)) | |||
|
295 | r.fork = None | |||
|
296 | Session().add(r) | |||
|
297 | h.flash(_('detached %s forks') % _forks, category='success') | |||
|
298 | elif do == 'delete_forks': | |||
|
299 | for r in repo.forks: | |||
|
300 | log.debug('Deleting fork %s of repo %s' % (r, repo)) | |||
|
301 | repo_model.delete(r) | |||
|
302 | h.flash(_('deleted %s forks') % _forks, category='success') | |||
289 | action_logger(self.rhodecode_user, 'admin_deleted_repo', |
|
303 | action_logger(self.rhodecode_user, 'admin_deleted_repo', | |
290 | repo_name, self.ip_addr, self.sa) |
|
304 | repo_name, self.ip_addr, self.sa) | |
291 | repo_model.delete(repo) |
|
305 | repo_model.delete(repo) | |
292 | invalidate_cache('get_repo_cached_%s' % repo_name) |
|
306 | invalidate_cache('get_repo_cached_%s' % repo_name) | |
293 | h.flash(_('deleted repository %s') % repo_name, category='success') |
|
307 | h.flash(_('deleted repository %s') % repo_name, category='success') | |
294 | Session().commit() |
|
308 | Session().commit() | |
295 | except IntegrityError, e: |
|
309 | except IntegrityError, e: | |
296 | if e.message.find('repositories_fork_id_fkey') != -1: |
|
310 | if e.message.find('repositories_fork_id_fkey') != -1: | |
297 | log.error(traceback.format_exc()) |
|
311 | log.error(traceback.format_exc()) | |
298 | h.flash(_('Cannot delete %s it still contains attached ' |
|
312 | h.flash(_('Cannot delete %s it still contains attached ' | |
299 | 'forks') % repo_name, |
|
313 | 'forks') % repo_name, | |
300 | category='warning') |
|
314 | category='warning') | |
301 | else: |
|
315 | else: | |
302 | log.error(traceback.format_exc()) |
|
316 | log.error(traceback.format_exc()) | |
303 | h.flash(_('An error occurred during ' |
|
317 | h.flash(_('An error occurred during ' | |
304 | 'deletion of %s') % repo_name, |
|
318 | 'deletion of %s') % repo_name, | |
305 | category='error') |
|
319 | category='error') | |
306 |
|
320 | |||
307 | except Exception, e: |
|
321 | except Exception, e: | |
308 | log.error(traceback.format_exc()) |
|
322 | log.error(traceback.format_exc()) | |
309 | h.flash(_('An error occurred during deletion of %s') % repo_name, |
|
323 | h.flash(_('An error occurred during deletion of %s') % repo_name, | |
310 | category='error') |
|
324 | category='error') | |
311 |
|
325 | |||
312 | return redirect(url('repos')) |
|
326 | return redirect(url('repos')) | |
313 |
|
327 | |||
314 | @HasRepoPermissionAllDecorator('repository.admin') |
|
328 | @HasRepoPermissionAllDecorator('repository.admin') | |
315 | def delete_perm_user(self, repo_name): |
|
329 | def delete_perm_user(self, repo_name): | |
316 | """ |
|
330 | """ | |
317 | DELETE an existing repository permission user |
|
331 | DELETE an existing repository permission user | |
318 |
|
332 | |||
319 | :param repo_name: |
|
333 | :param repo_name: | |
320 | """ |
|
334 | """ | |
321 | try: |
|
335 | try: | |
322 | RepoModel().revoke_user_permission(repo=repo_name, |
|
336 | RepoModel().revoke_user_permission(repo=repo_name, | |
323 | user=request.POST['user_id']) |
|
337 | user=request.POST['user_id']) | |
324 | Session().commit() |
|
338 | Session().commit() | |
325 | except Exception: |
|
339 | except Exception: | |
326 | log.error(traceback.format_exc()) |
|
340 | log.error(traceback.format_exc()) | |
327 | h.flash(_('An error occurred during deletion of repository user'), |
|
341 | h.flash(_('An error occurred during deletion of repository user'), | |
328 | category='error') |
|
342 | category='error') | |
329 | raise HTTPInternalServerError() |
|
343 | raise HTTPInternalServerError() | |
330 |
|
344 | |||
331 | @HasRepoPermissionAllDecorator('repository.admin') |
|
345 | @HasRepoPermissionAllDecorator('repository.admin') | |
332 | def delete_perm_users_group(self, repo_name): |
|
346 | def delete_perm_users_group(self, repo_name): | |
333 | """ |
|
347 | """ | |
334 | DELETE an existing repository permission users group |
|
348 | DELETE an existing repository permission users group | |
335 |
|
349 | |||
336 | :param repo_name: |
|
350 | :param repo_name: | |
337 | """ |
|
351 | """ | |
338 |
|
352 | |||
339 | try: |
|
353 | try: | |
340 | RepoModel().revoke_users_group_permission( |
|
354 | RepoModel().revoke_users_group_permission( | |
341 | repo=repo_name, group_name=request.POST['users_group_id'] |
|
355 | repo=repo_name, group_name=request.POST['users_group_id'] | |
342 | ) |
|
356 | ) | |
343 | Session().commit() |
|
357 | Session().commit() | |
344 | except Exception: |
|
358 | except Exception: | |
345 | log.error(traceback.format_exc()) |
|
359 | log.error(traceback.format_exc()) | |
346 | h.flash(_('An error occurred during deletion of repository' |
|
360 | h.flash(_('An error occurred during deletion of repository' | |
347 | ' users groups'), |
|
361 | ' users groups'), | |
348 | category='error') |
|
362 | category='error') | |
349 | raise HTTPInternalServerError() |
|
363 | raise HTTPInternalServerError() | |
350 |
|
364 | |||
351 | @HasPermissionAllDecorator('hg.admin') |
|
365 | @HasPermissionAllDecorator('hg.admin') | |
352 | def repo_stats(self, repo_name): |
|
366 | def repo_stats(self, repo_name): | |
353 | """ |
|
367 | """ | |
354 | DELETE an existing repository statistics |
|
368 | DELETE an existing repository statistics | |
355 |
|
369 | |||
356 | :param repo_name: |
|
370 | :param repo_name: | |
357 | """ |
|
371 | """ | |
358 |
|
372 | |||
359 | try: |
|
373 | try: | |
360 | RepoModel().delete_stats(repo_name) |
|
374 | RepoModel().delete_stats(repo_name) | |
361 | Session().commit() |
|
375 | Session().commit() | |
362 | except Exception, e: |
|
376 | except Exception, e: | |
363 | log.error(traceback.format_exc()) |
|
377 | log.error(traceback.format_exc()) | |
364 | h.flash(_('An error occurred during deletion of repository stats'), |
|
378 | h.flash(_('An error occurred during deletion of repository stats'), | |
365 | category='error') |
|
379 | category='error') | |
366 | return redirect(url('edit_repo', repo_name=repo_name)) |
|
380 | return redirect(url('edit_repo', repo_name=repo_name)) | |
367 |
|
381 | |||
368 | @HasPermissionAllDecorator('hg.admin') |
|
382 | @HasPermissionAllDecorator('hg.admin') | |
369 | def repo_cache(self, repo_name): |
|
383 | def repo_cache(self, repo_name): | |
370 | """ |
|
384 | """ | |
371 | INVALIDATE existing repository cache |
|
385 | INVALIDATE existing repository cache | |
372 |
|
386 | |||
373 | :param repo_name: |
|
387 | :param repo_name: | |
374 | """ |
|
388 | """ | |
375 |
|
389 | |||
376 | try: |
|
390 | try: | |
377 | ScmModel().mark_for_invalidation(repo_name) |
|
391 | ScmModel().mark_for_invalidation(repo_name) | |
378 | Session().commit() |
|
392 | Session().commit() | |
379 | except Exception, e: |
|
393 | except Exception, e: | |
380 | log.error(traceback.format_exc()) |
|
394 | log.error(traceback.format_exc()) | |
381 | h.flash(_('An error occurred during cache invalidation'), |
|
395 | h.flash(_('An error occurred during cache invalidation'), | |
382 | category='error') |
|
396 | category='error') | |
383 | return redirect(url('edit_repo', repo_name=repo_name)) |
|
397 | return redirect(url('edit_repo', repo_name=repo_name)) | |
384 |
|
398 | |||
385 | @HasPermissionAllDecorator('hg.admin') |
|
399 | @HasPermissionAllDecorator('hg.admin') | |
386 | def repo_locking(self, repo_name): |
|
400 | def repo_locking(self, repo_name): | |
387 | """ |
|
401 | """ | |
388 | Unlock repository when it is locked ! |
|
402 | Unlock repository when it is locked ! | |
389 |
|
403 | |||
390 | :param repo_name: |
|
404 | :param repo_name: | |
391 | """ |
|
405 | """ | |
392 |
|
406 | |||
393 | try: |
|
407 | try: | |
394 | repo = Repository.get_by_repo_name(repo_name) |
|
408 | repo = Repository.get_by_repo_name(repo_name) | |
395 | if request.POST.get('set_lock'): |
|
409 | if request.POST.get('set_lock'): | |
396 | Repository.lock(repo, c.rhodecode_user.user_id) |
|
410 | Repository.lock(repo, c.rhodecode_user.user_id) | |
397 | elif request.POST.get('set_unlock'): |
|
411 | elif request.POST.get('set_unlock'): | |
398 | Repository.unlock(repo) |
|
412 | Repository.unlock(repo) | |
399 | except Exception, e: |
|
413 | except Exception, e: | |
400 | log.error(traceback.format_exc()) |
|
414 | log.error(traceback.format_exc()) | |
401 | h.flash(_('An error occurred during unlocking'), |
|
415 | h.flash(_('An error occurred during unlocking'), | |
402 | category='error') |
|
416 | category='error') | |
403 | return redirect(url('edit_repo', repo_name=repo_name)) |
|
417 | return redirect(url('edit_repo', repo_name=repo_name)) | |
404 |
|
418 | |||
405 | @HasPermissionAllDecorator('hg.admin') |
|
419 | @HasPermissionAllDecorator('hg.admin') | |
406 | def repo_public_journal(self, repo_name): |
|
420 | def repo_public_journal(self, repo_name): | |
407 | """ |
|
421 | """ | |
408 | Set's this repository to be visible in public journal, |
|
422 | Set's this repository to be visible in public journal, | |
409 | in other words assing default user to follow this repo |
|
423 | in other words assing default user to follow this repo | |
410 |
|
424 | |||
411 | :param repo_name: |
|
425 | :param repo_name: | |
412 | """ |
|
426 | """ | |
413 |
|
427 | |||
414 | cur_token = request.POST.get('auth_token') |
|
428 | cur_token = request.POST.get('auth_token') | |
415 | token = get_token() |
|
429 | token = get_token() | |
416 | if cur_token == token: |
|
430 | if cur_token == token: | |
417 | try: |
|
431 | try: | |
418 | repo_id = Repository.get_by_repo_name(repo_name).repo_id |
|
432 | repo_id = Repository.get_by_repo_name(repo_name).repo_id | |
419 | user_id = User.get_by_username('default').user_id |
|
433 | user_id = User.get_by_username('default').user_id | |
420 | self.scm_model.toggle_following_repo(repo_id, user_id) |
|
434 | self.scm_model.toggle_following_repo(repo_id, user_id) | |
421 | h.flash(_('Updated repository visibility in public journal'), |
|
435 | h.flash(_('Updated repository visibility in public journal'), | |
422 | category='success') |
|
436 | category='success') | |
423 | Session().commit() |
|
437 | Session().commit() | |
424 | except: |
|
438 | except: | |
425 | h.flash(_('An error occurred during setting this' |
|
439 | h.flash(_('An error occurred during setting this' | |
426 | ' repository in public journal'), |
|
440 | ' repository in public journal'), | |
427 | category='error') |
|
441 | category='error') | |
428 |
|
442 | |||
429 | else: |
|
443 | else: | |
430 | h.flash(_('Token mismatch'), category='error') |
|
444 | h.flash(_('Token mismatch'), category='error') | |
431 | return redirect(url('edit_repo', repo_name=repo_name)) |
|
445 | return redirect(url('edit_repo', repo_name=repo_name)) | |
432 |
|
446 | |||
433 | @HasPermissionAllDecorator('hg.admin') |
|
447 | @HasPermissionAllDecorator('hg.admin') | |
434 | def repo_pull(self, repo_name): |
|
448 | def repo_pull(self, repo_name): | |
435 | """ |
|
449 | """ | |
436 | Runs task to update given repository with remote changes, |
|
450 | Runs task to update given repository with remote changes, | |
437 | ie. make pull on remote location |
|
451 | ie. make pull on remote location | |
438 |
|
452 | |||
439 | :param repo_name: |
|
453 | :param repo_name: | |
440 | """ |
|
454 | """ | |
441 | try: |
|
455 | try: | |
442 | ScmModel().pull_changes(repo_name, self.rhodecode_user.username) |
|
456 | ScmModel().pull_changes(repo_name, self.rhodecode_user.username) | |
443 | h.flash(_('Pulled from remote location'), category='success') |
|
457 | h.flash(_('Pulled from remote location'), category='success') | |
444 | except Exception, e: |
|
458 | except Exception, e: | |
445 | h.flash(_('An error occurred during pull from remote location'), |
|
459 | h.flash(_('An error occurred during pull from remote location'), | |
446 | category='error') |
|
460 | category='error') | |
447 |
|
461 | |||
448 | return redirect(url('edit_repo', repo_name=repo_name)) |
|
462 | return redirect(url('edit_repo', repo_name=repo_name)) | |
449 |
|
463 | |||
450 | @HasPermissionAllDecorator('hg.admin') |
|
464 | @HasPermissionAllDecorator('hg.admin') | |
451 | def repo_as_fork(self, repo_name): |
|
465 | def repo_as_fork(self, repo_name): | |
452 | """ |
|
466 | """ | |
453 | Mark given repository as a fork of another |
|
467 | Mark given repository as a fork of another | |
454 |
|
468 | |||
455 | :param repo_name: |
|
469 | :param repo_name: | |
456 | """ |
|
470 | """ | |
457 | try: |
|
471 | try: | |
458 | fork_id = request.POST.get('id_fork_of') |
|
472 | fork_id = request.POST.get('id_fork_of') | |
459 | repo = ScmModel().mark_as_fork(repo_name, fork_id, |
|
473 | repo = ScmModel().mark_as_fork(repo_name, fork_id, | |
460 | self.rhodecode_user.username) |
|
474 | self.rhodecode_user.username) | |
461 | fork = repo.fork.repo_name if repo.fork else _('Nothing') |
|
475 | fork = repo.fork.repo_name if repo.fork else _('Nothing') | |
462 | Session().commit() |
|
476 | Session().commit() | |
463 | h.flash(_('Marked repo %s as fork of %s') % (repo_name, fork), |
|
477 | h.flash(_('Marked repo %s as fork of %s') % (repo_name, fork), | |
464 | category='success') |
|
478 | category='success') | |
465 | except Exception, e: |
|
479 | except Exception, e: | |
466 | log.error(traceback.format_exc()) |
|
480 | log.error(traceback.format_exc()) | |
467 | h.flash(_('An error occurred during this operation'), |
|
481 | h.flash(_('An error occurred during this operation'), | |
468 | category='error') |
|
482 | category='error') | |
469 |
|
483 | |||
470 | return redirect(url('edit_repo', repo_name=repo_name)) |
|
484 | return redirect(url('edit_repo', repo_name=repo_name)) | |
471 |
|
485 | |||
472 | @HasPermissionAllDecorator('hg.admin') |
|
486 | @HasPermissionAllDecorator('hg.admin') | |
473 | def show(self, repo_name, format='html'): |
|
487 | def show(self, repo_name, format='html'): | |
474 | """GET /repos/repo_name: Show a specific item""" |
|
488 | """GET /repos/repo_name: Show a specific item""" | |
475 | # url('repo', repo_name=ID) |
|
489 | # url('repo', repo_name=ID) | |
476 |
|
490 | |||
477 | @HasPermissionAllDecorator('hg.admin') |
|
491 | @HasPermissionAllDecorator('hg.admin') | |
478 | def edit(self, repo_name, format='html'): |
|
492 | def edit(self, repo_name, format='html'): | |
479 | """GET /repos/repo_name/edit: Form to edit an existing item""" |
|
493 | """GET /repos/repo_name/edit: Form to edit an existing item""" | |
480 | # url('edit_repo', repo_name=ID) |
|
494 | # url('edit_repo', repo_name=ID) | |
481 | defaults = self.__load_data(repo_name) |
|
495 | defaults = self.__load_data(repo_name) | |
482 |
|
496 | |||
483 | return htmlfill.render( |
|
497 | return htmlfill.render( | |
484 | render('admin/repos/repo_edit.html'), |
|
498 | render('admin/repos/repo_edit.html'), | |
485 | defaults=defaults, |
|
499 | defaults=defaults, | |
486 | encoding="UTF-8", |
|
500 | encoding="UTF-8", | |
487 | force_defaults=False |
|
501 | force_defaults=False | |
488 | ) |
|
502 | ) | |
489 |
|
503 | |||
490 | @HasPermissionAllDecorator('hg.admin') |
|
504 | @HasPermissionAllDecorator('hg.admin') | |
491 | def create_repo_field(self, repo_name): |
|
505 | def create_repo_field(self, repo_name): | |
492 | try: |
|
506 | try: | |
493 | form_result = RepoFieldForm()().to_python(dict(request.POST)) |
|
507 | form_result = RepoFieldForm()().to_python(dict(request.POST)) | |
494 | new_field = RepositoryField() |
|
508 | new_field = RepositoryField() | |
495 | new_field.repository = Repository.get_by_repo_name(repo_name) |
|
509 | new_field.repository = Repository.get_by_repo_name(repo_name) | |
496 | new_field.field_key = form_result['new_field_key'] |
|
510 | new_field.field_key = form_result['new_field_key'] | |
497 | new_field.field_type = form_result['new_field_type'] # python type |
|
511 | new_field.field_type = form_result['new_field_type'] # python type | |
498 | new_field.field_value = form_result['new_field_value'] # set initial blank value |
|
512 | new_field.field_value = form_result['new_field_value'] # set initial blank value | |
499 | new_field.field_desc = form_result['new_field_desc'] |
|
513 | new_field.field_desc = form_result['new_field_desc'] | |
500 | new_field.field_label = form_result['new_field_label'] |
|
514 | new_field.field_label = form_result['new_field_label'] | |
501 | Session().add(new_field) |
|
515 | Session().add(new_field) | |
502 | Session().commit() |
|
516 | Session().commit() | |
503 |
|
517 | |||
504 | except Exception, e: |
|
518 | except Exception, e: | |
505 | log.error(traceback.format_exc()) |
|
519 | log.error(traceback.format_exc()) | |
506 | msg = _('An error occurred during creation of field') |
|
520 | msg = _('An error occurred during creation of field') | |
507 | if isinstance(e, formencode.Invalid): |
|
521 | if isinstance(e, formencode.Invalid): | |
508 | msg += ". " + e.msg |
|
522 | msg += ". " + e.msg | |
509 | h.flash(msg, category='error') |
|
523 | h.flash(msg, category='error') | |
510 | return redirect(url('edit_repo', repo_name=repo_name)) |
|
524 | return redirect(url('edit_repo', repo_name=repo_name)) | |
511 |
|
525 | |||
512 | @HasPermissionAllDecorator('hg.admin') |
|
526 | @HasPermissionAllDecorator('hg.admin') | |
513 | def delete_repo_field(self, repo_name, field_id): |
|
527 | def delete_repo_field(self, repo_name, field_id): | |
514 | field = RepositoryField.get_or_404(field_id) |
|
528 | field = RepositoryField.get_or_404(field_id) | |
515 | try: |
|
529 | try: | |
516 | Session().delete(field) |
|
530 | Session().delete(field) | |
517 | Session().commit() |
|
531 | Session().commit() | |
518 | except Exception, e: |
|
532 | except Exception, e: | |
519 | log.error(traceback.format_exc()) |
|
533 | log.error(traceback.format_exc()) | |
520 | msg = _('An error occurred during removal of field') |
|
534 | msg = _('An error occurred during removal of field') | |
521 | h.flash(msg, category='error') |
|
535 | h.flash(msg, category='error') | |
522 | return redirect(url('edit_repo', repo_name=repo_name)) |
|
536 | return redirect(url('edit_repo', repo_name=repo_name)) |
@@ -1,368 +1,373 b'' | |||||
1 | ## -*- coding: utf-8 -*- |
|
1 | ## -*- coding: utf-8 -*- | |
2 | <%inherit file="/base/base.html"/> |
|
2 | <%inherit file="/base/base.html"/> | |
3 |
|
3 | |||
4 | <%def name="title()"> |
|
4 | <%def name="title()"> | |
5 | ${_('Edit repository')} ${c.repo_info.repo_name} - ${c.rhodecode_name} |
|
5 | ${_('Edit repository')} ${c.repo_info.repo_name} - ${c.rhodecode_name} | |
6 | </%def> |
|
6 | </%def> | |
7 |
|
7 | |||
8 | <%def name="breadcrumbs_links()"> |
|
8 | <%def name="breadcrumbs_links()"> | |
9 | ${h.link_to(_(u'Home'),h.url('/'))} |
|
9 | ${h.link_to(_(u'Home'),h.url('/'))} | |
10 | » |
|
10 | » | |
11 | ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))} |
|
11 | ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))} | |
12 | » |
|
12 | » | |
13 | ${_('edit')} |
|
13 | ${_('edit')} | |
14 | </%def> |
|
14 | </%def> | |
15 |
|
15 | |||
16 | <%def name="page_nav()"> |
|
16 | <%def name="page_nav()"> | |
17 | ${self.menu('options')} |
|
17 | ${self.menu('options')} | |
18 | </%def> |
|
18 | </%def> | |
19 |
|
19 | |||
20 | <%def name="main()"> |
|
20 | <%def name="main()"> | |
21 | <div class="box box-left"> |
|
21 | <div class="box box-left"> | |
22 | <!-- box / title --> |
|
22 | <!-- box / title --> | |
23 | <div class="title"> |
|
23 | <div class="title"> | |
24 | ${self.breadcrumbs()} |
|
24 | ${self.breadcrumbs()} | |
25 | </div> |
|
25 | </div> | |
26 | ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='put')} |
|
26 | ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='put')} | |
27 | <div class="form"> |
|
27 | <div class="form"> | |
28 | <!-- fields --> |
|
28 | <!-- fields --> | |
29 | <div class="fields"> |
|
29 | <div class="fields"> | |
30 | <div class="field"> |
|
30 | <div class="field"> | |
31 | <div class="label"> |
|
31 | <div class="label"> | |
32 | <label for="repo_name">${_('Name')}:</label> |
|
32 | <label for="repo_name">${_('Name')}:</label> | |
33 | </div> |
|
33 | </div> | |
34 | <div class="input"> |
|
34 | <div class="input"> | |
35 | ${h.text('repo_name',class_="medium")} |
|
35 | ${h.text('repo_name',class_="medium")} | |
36 | </div> |
|
36 | </div> | |
37 | </div> |
|
37 | </div> | |
38 | <div class="field"> |
|
38 | <div class="field"> | |
39 | <div class="label"> |
|
39 | <div class="label"> | |
40 | <label for="clone_uri">${_('Clone uri')}:</label> |
|
40 | <label for="clone_uri">${_('Clone uri')}:</label> | |
41 | </div> |
|
41 | </div> | |
42 | <div class="input"> |
|
42 | <div class="input"> | |
43 | ${h.text('clone_uri',class_="medium")} |
|
43 | ${h.text('clone_uri',class_="medium")} | |
44 | <span class="help-block">${_('Optional http[s] url from which repository should be cloned.')}</span> |
|
44 | <span class="help-block">${_('Optional http[s] url from which repository should be cloned.')}</span> | |
45 | </div> |
|
45 | </div> | |
46 | </div> |
|
46 | </div> | |
47 | <div class="field"> |
|
47 | <div class="field"> | |
48 | <div class="label"> |
|
48 | <div class="label"> | |
49 | <label for="repo_group">${_('Repository group')}:</label> |
|
49 | <label for="repo_group">${_('Repository group')}:</label> | |
50 | </div> |
|
50 | </div> | |
51 | <div class="input"> |
|
51 | <div class="input"> | |
52 | ${h.select('repo_group','',c.repo_groups,class_="medium")} |
|
52 | ${h.select('repo_group','',c.repo_groups,class_="medium")} | |
53 | <span class="help-block">${_('Optional select a group to put this repository into.')}</span> |
|
53 | <span class="help-block">${_('Optional select a group to put this repository into.')}</span> | |
54 | </div> |
|
54 | </div> | |
55 | </div> |
|
55 | </div> | |
56 | <div class="field"> |
|
56 | <div class="field"> | |
57 | <div class="label"> |
|
57 | <div class="label"> | |
58 | <label for="repo_type">${_('Type')}:</label> |
|
58 | <label for="repo_type">${_('Type')}:</label> | |
59 | </div> |
|
59 | </div> | |
60 | <div class="input"> |
|
60 | <div class="input"> | |
61 | ${h.select('repo_type','hg',c.backends,class_="medium")} |
|
61 | ${h.select('repo_type','hg',c.backends,class_="medium")} | |
62 | </div> |
|
62 | </div> | |
63 | </div> |
|
63 | </div> | |
64 | <div class="field"> |
|
64 | <div class="field"> | |
65 | <div class="label"> |
|
65 | <div class="label"> | |
66 | <label for="repo_landing_rev">${_('Landing revision')}:</label> |
|
66 | <label for="repo_landing_rev">${_('Landing revision')}:</label> | |
67 | </div> |
|
67 | </div> | |
68 | <div class="input"> |
|
68 | <div class="input"> | |
69 | ${h.select('repo_landing_rev','',c.landing_revs,class_="medium")} |
|
69 | ${h.select('repo_landing_rev','',c.landing_revs,class_="medium")} | |
70 | <span class="help-block">${_('Default revision for files page, downloads, whoosh and readme')}</span> |
|
70 | <span class="help-block">${_('Default revision for files page, downloads, whoosh and readme')}</span> | |
71 | </div> |
|
71 | </div> | |
72 | </div> |
|
72 | </div> | |
73 | <div class="field"> |
|
73 | <div class="field"> | |
74 | <div class="label label-textarea"> |
|
74 | <div class="label label-textarea"> | |
75 | <label for="repo_description">${_('Description')}:</label> |
|
75 | <label for="repo_description">${_('Description')}:</label> | |
76 | </div> |
|
76 | </div> | |
77 | <div class="textarea text-area editor"> |
|
77 | <div class="textarea text-area editor"> | |
78 | ${h.textarea('repo_description')} |
|
78 | ${h.textarea('repo_description')} | |
79 | <span class="help-block">${_('Keep it short and to the point. Use a README file for longer descriptions.')}</span> |
|
79 | <span class="help-block">${_('Keep it short and to the point. Use a README file for longer descriptions.')}</span> | |
80 | </div> |
|
80 | </div> | |
81 | </div> |
|
81 | </div> | |
82 |
|
82 | |||
83 | <div class="field"> |
|
83 | <div class="field"> | |
84 | <div class="label label-checkbox"> |
|
84 | <div class="label label-checkbox"> | |
85 | <label for="repo_private">${_('Private repository')}:</label> |
|
85 | <label for="repo_private">${_('Private repository')}:</label> | |
86 | </div> |
|
86 | </div> | |
87 | <div class="checkboxes"> |
|
87 | <div class="checkboxes"> | |
88 | ${h.checkbox('repo_private',value="True")} |
|
88 | ${h.checkbox('repo_private',value="True")} | |
89 | <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span> |
|
89 | <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span> | |
90 | </div> |
|
90 | </div> | |
91 | </div> |
|
91 | </div> | |
92 | <div class="field"> |
|
92 | <div class="field"> | |
93 | <div class="label label-checkbox"> |
|
93 | <div class="label label-checkbox"> | |
94 | <label for="repo_enable_statistics">${_('Enable statistics')}:</label> |
|
94 | <label for="repo_enable_statistics">${_('Enable statistics')}:</label> | |
95 | </div> |
|
95 | </div> | |
96 | <div class="checkboxes"> |
|
96 | <div class="checkboxes"> | |
97 | ${h.checkbox('repo_enable_statistics',value="True")} |
|
97 | ${h.checkbox('repo_enable_statistics',value="True")} | |
98 | <span class="help-block">${_('Enable statistics window on summary page.')}</span> |
|
98 | <span class="help-block">${_('Enable statistics window on summary page.')}</span> | |
99 | </div> |
|
99 | </div> | |
100 | </div> |
|
100 | </div> | |
101 | <div class="field"> |
|
101 | <div class="field"> | |
102 | <div class="label label-checkbox"> |
|
102 | <div class="label label-checkbox"> | |
103 | <label for="repo_enable_downloads">${_('Enable downloads')}:</label> |
|
103 | <label for="repo_enable_downloads">${_('Enable downloads')}:</label> | |
104 | </div> |
|
104 | </div> | |
105 | <div class="checkboxes"> |
|
105 | <div class="checkboxes"> | |
106 | ${h.checkbox('repo_enable_downloads',value="True")} |
|
106 | ${h.checkbox('repo_enable_downloads',value="True")} | |
107 | <span class="help-block">${_('Enable download menu on summary page.')}</span> |
|
107 | <span class="help-block">${_('Enable download menu on summary page.')}</span> | |
108 | </div> |
|
108 | </div> | |
109 | </div> |
|
109 | </div> | |
110 | <div class="field"> |
|
110 | <div class="field"> | |
111 | <div class="label label-checkbox"> |
|
111 | <div class="label label-checkbox"> | |
112 | <label for="repo_enable_locking">${_('Enable locking')}:</label> |
|
112 | <label for="repo_enable_locking">${_('Enable locking')}:</label> | |
113 | </div> |
|
113 | </div> | |
114 | <div class="checkboxes"> |
|
114 | <div class="checkboxes"> | |
115 | ${h.checkbox('repo_enable_locking',value="True")} |
|
115 | ${h.checkbox('repo_enable_locking',value="True")} | |
116 | <span class="help-block">${_('Enable lock-by-pulling on repository.')}</span> |
|
116 | <span class="help-block">${_('Enable lock-by-pulling on repository.')}</span> | |
117 | </div> |
|
117 | </div> | |
118 | </div> |
|
118 | </div> | |
119 | <div class="field"> |
|
119 | <div class="field"> | |
120 | <div class="label"> |
|
120 | <div class="label"> | |
121 | <label for="user">${_('Owner')}:</label> |
|
121 | <label for="user">${_('Owner')}:</label> | |
122 | </div> |
|
122 | </div> | |
123 | <div class="input input-medium ac"> |
|
123 | <div class="input input-medium ac"> | |
124 | <div class="perm_ac"> |
|
124 | <div class="perm_ac"> | |
125 | ${h.text('user',class_='yui-ac-input')} |
|
125 | ${h.text('user',class_='yui-ac-input')} | |
126 | <span class="help-block">${_('Change owner of this repository.')}</span> |
|
126 | <span class="help-block">${_('Change owner of this repository.')}</span> | |
127 | <div id="owner_container"></div> |
|
127 | <div id="owner_container"></div> | |
128 | </div> |
|
128 | </div> | |
129 | </div> |
|
129 | </div> | |
130 | </div> |
|
130 | </div> | |
131 | %if c.visual.repository_fields: |
|
131 | %if c.visual.repository_fields: | |
132 | ## EXTRA FIELDS |
|
132 | ## EXTRA FIELDS | |
133 | %for field in c.repo_fields: |
|
133 | %for field in c.repo_fields: | |
134 | <div class="field"> |
|
134 | <div class="field"> | |
135 | <div class="label"> |
|
135 | <div class="label"> | |
136 | <label for="${field.field_key_prefixed}">${field.field_label} (${field.field_key}):</label> |
|
136 | <label for="${field.field_key_prefixed}">${field.field_label} (${field.field_key}):</label> | |
137 | </div> |
|
137 | </div> | |
138 | <div class="input input-medium"> |
|
138 | <div class="input input-medium"> | |
139 | ${h.text(field.field_key_prefixed, field.field_value, class_='medium')} |
|
139 | ${h.text(field.field_key_prefixed, field.field_value, class_='medium')} | |
140 | %if field.field_desc: |
|
140 | %if field.field_desc: | |
141 | <span class="help-block">${field.field_desc}</span> |
|
141 | <span class="help-block">${field.field_desc}</span> | |
142 | %endif |
|
142 | %endif | |
143 | </div> |
|
143 | </div> | |
144 | </div> |
|
144 | </div> | |
145 | %endfor |
|
145 | %endfor | |
146 | %endif |
|
146 | %endif | |
147 | <div class="field"> |
|
147 | <div class="field"> | |
148 | <div class="label"> |
|
148 | <div class="label"> | |
149 | <label for="input">${_('Permissions')}:</label> |
|
149 | <label for="input">${_('Permissions')}:</label> | |
150 | </div> |
|
150 | </div> | |
151 | <div class="input"> |
|
151 | <div class="input"> | |
152 | <%include file="repo_edit_perms.html"/> |
|
152 | <%include file="repo_edit_perms.html"/> | |
153 | </div> |
|
153 | </div> | |
154 |
|
154 | |||
155 | <div class="buttons"> |
|
155 | <div class="buttons"> | |
156 | ${h.submit('save',_('Save'),class_="ui-btn large")} |
|
156 | ${h.submit('save',_('Save'),class_="ui-btn large")} | |
157 | ${h.reset('reset',_('Reset'),class_="ui-btn large")} |
|
157 | ${h.reset('reset',_('Reset'),class_="ui-btn large")} | |
158 | </div> |
|
158 | </div> | |
159 | </div> |
|
159 | </div> | |
160 | </div> |
|
160 | </div> | |
161 | </div> |
|
161 | </div> | |
162 | ${h.end_form()} |
|
162 | ${h.end_form()} | |
163 | </div> |
|
163 | </div> | |
164 |
|
164 | |||
165 | <div class="box box-right"> |
|
165 | <div class="box box-right"> | |
166 | <div class="title"> |
|
166 | <div class="title"> | |
167 | <h5>${_('Administration')}</h5> |
|
167 | <h5>${_('Administration')}</h5> | |
168 | </div> |
|
168 | </div> | |
169 |
|
169 | |||
170 | <h3>${_('Statistics')}</h3> |
|
170 | <h3>${_('Statistics')}</h3> | |
171 | ${h.form(url('repo_stats', repo_name=c.repo_info.repo_name),method='delete')} |
|
171 | ${h.form(url('repo_stats', repo_name=c.repo_info.repo_name),method='delete')} | |
172 | <div class="form"> |
|
172 | <div class="form"> | |
173 | <div class="fields"> |
|
173 | <div class="fields"> | |
174 | ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="ui-btn",onclick="return confirm('"+_('Confirm to remove current statistics')+"');")} |
|
174 | ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="ui-btn",onclick="return confirm('"+_('Confirm to remove current statistics')+"');")} | |
175 | <div class="field" style="border:none;color:#888"> |
|
175 | <div class="field" style="border:none;color:#888"> | |
176 | <ul> |
|
176 | <ul> | |
177 | <li>${_('Fetched to rev')}: ${c.stats_revision}/${c.repo_last_rev}</li> |
|
177 | <li>${_('Fetched to rev')}: ${c.stats_revision}/${c.repo_last_rev}</li> | |
178 | <li>${_('Stats gathered')}: ${c.stats_percentage}%</li> |
|
178 | <li>${_('Stats gathered')}: ${c.stats_percentage}%</li> | |
179 | </ul> |
|
179 | </ul> | |
180 | </div> |
|
180 | </div> | |
181 | </div> |
|
181 | </div> | |
182 | </div> |
|
182 | </div> | |
183 | ${h.end_form()} |
|
183 | ${h.end_form()} | |
184 |
|
184 | |||
185 | %if c.repo_info.clone_uri: |
|
185 | %if c.repo_info.clone_uri: | |
186 | <h3>${_('Remote')}</h3> |
|
186 | <h3>${_('Remote')}</h3> | |
187 | ${h.form(url('repo_pull', repo_name=c.repo_info.repo_name),method='put')} |
|
187 | ${h.form(url('repo_pull', repo_name=c.repo_info.repo_name),method='put')} | |
188 | <div class="form"> |
|
188 | <div class="form"> | |
189 | <div class="fields"> |
|
189 | <div class="fields"> | |
190 | ${h.submit('remote_pull_%s' % c.repo_info.repo_name,_('Pull changes from remote location'),class_="ui-btn",onclick="return confirm('"+_('Confirm to pull changes from remote side')+"');")} |
|
190 | ${h.submit('remote_pull_%s' % c.repo_info.repo_name,_('Pull changes from remote location'),class_="ui-btn",onclick="return confirm('"+_('Confirm to pull changes from remote side')+"');")} | |
191 | <div class="field" style="border:none"> |
|
191 | <div class="field" style="border:none"> | |
192 | <ul> |
|
192 | <ul> | |
193 | <li><a href="${c.repo_info.clone_uri}">${c.repo_info.clone_uri}</a></li> |
|
193 | <li><a href="${c.repo_info.clone_uri}">${c.repo_info.clone_uri}</a></li> | |
194 | </ul> |
|
194 | </ul> | |
195 | </div> |
|
195 | </div> | |
196 | </div> |
|
196 | </div> | |
197 | </div> |
|
197 | </div> | |
198 | ${h.end_form()} |
|
198 | ${h.end_form()} | |
199 | %endif |
|
199 | %endif | |
200 |
|
200 | |||
201 | <h3>${_('Cache')}</h3> |
|
201 | <h3>${_('Cache')}</h3> | |
202 | ${h.form(url('repo_cache', repo_name=c.repo_info.repo_name),method='delete')} |
|
202 | ${h.form(url('repo_cache', repo_name=c.repo_info.repo_name),method='delete')} | |
203 | <div class="form"> |
|
203 | <div class="form"> | |
204 | <div class="fields"> |
|
204 | <div class="fields"> | |
205 | ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate repository cache'),class_="ui-btn",onclick="return confirm('"+_('Confirm to invalidate repository cache')+"');")} |
|
205 | ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate repository cache'),class_="ui-btn",onclick="return confirm('"+_('Confirm to invalidate repository cache')+"');")} | |
206 | <div class="field" style="border:none;color:#888"> |
|
206 | <div class="field" style="border:none;color:#888"> | |
207 | <ul> |
|
207 | <ul> | |
208 | <li>${_('Manually invalidate cache for this repository. On first access repository will be cached again')} |
|
208 | <li>${_('Manually invalidate cache for this repository. On first access repository will be cached again')} | |
209 | </li> |
|
209 | </li> | |
210 | </ul> |
|
210 | </ul> | |
211 | </div> |
|
211 | </div> | |
212 | <div class="field" style="border:none;"> |
|
212 | <div class="field" style="border:none;"> | |
213 | ${_('List of cached values')} |
|
213 | ${_('List of cached values')} | |
214 | <table> |
|
214 | <table> | |
215 | <tr> |
|
215 | <tr> | |
216 | <th>${_('Prefix')}</th> |
|
216 | <th>${_('Prefix')}</th> | |
217 | <th>${_('Key')}</th> |
|
217 | <th>${_('Key')}</th> | |
218 | <th>${_('Active')}</th> |
|
218 | <th>${_('Active')}</th> | |
219 | </tr> |
|
219 | </tr> | |
220 | %for cache in c.repo_info.cache_keys: |
|
220 | %for cache in c.repo_info.cache_keys: | |
221 | <tr> |
|
221 | <tr> | |
222 | <td>${cache.prefix or '-'}</td> |
|
222 | <td>${cache.prefix or '-'}</td> | |
223 | <td>${cache.cache_key}</td> |
|
223 | <td>${cache.cache_key}</td> | |
224 | <td>${h.bool2icon(cache.cache_active)}</td> |
|
224 | <td>${h.bool2icon(cache.cache_active)}</td> | |
225 | </tr> |
|
225 | </tr> | |
226 | %endfor |
|
226 | %endfor | |
227 | </table> |
|
227 | </table> | |
228 | </div> |
|
228 | </div> | |
229 | </div> |
|
229 | </div> | |
230 | </div> |
|
230 | </div> | |
231 | ${h.end_form()} |
|
231 | ${h.end_form()} | |
232 |
|
232 | |||
233 | <h3>${_('Public journal')}</h3> |
|
233 | <h3>${_('Public journal')}</h3> | |
234 | ${h.form(url('repo_public_journal', repo_name=c.repo_info.repo_name),method='put')} |
|
234 | ${h.form(url('repo_public_journal', repo_name=c.repo_info.repo_name),method='put')} | |
235 | <div class="form"> |
|
235 | <div class="form"> | |
236 | ${h.hidden('auth_token',str(h.get_token()))} |
|
236 | ${h.hidden('auth_token',str(h.get_token()))} | |
237 | <div class="field"> |
|
237 | <div class="field"> | |
238 | %if c.in_public_journal: |
|
238 | %if c.in_public_journal: | |
239 | ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Remove from public journal'),class_="ui-btn")} |
|
239 | ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Remove from public journal'),class_="ui-btn")} | |
240 | %else: |
|
240 | %else: | |
241 | ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Add to public journal'),class_="ui-btn")} |
|
241 | ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Add to public journal'),class_="ui-btn")} | |
242 | %endif |
|
242 | %endif | |
243 | </div> |
|
243 | </div> | |
244 | <div class="field" style="border:none;color:#888"> |
|
244 | <div class="field" style="border:none;color:#888"> | |
245 | <ul> |
|
245 | <ul> | |
246 | <li>${_('All actions made on this repository will be accessible to everyone in public journal')} |
|
246 | <li>${_('All actions made on this repository will be accessible to everyone in public journal')} | |
247 | </li> |
|
247 | </li> | |
248 | </ul> |
|
248 | </ul> | |
249 | </div> |
|
249 | </div> | |
250 | </div> |
|
250 | </div> | |
251 | ${h.end_form()} |
|
251 | ${h.end_form()} | |
252 |
|
252 | |||
253 | <h3>${_('Locking')}</h3> |
|
253 | <h3>${_('Locking')}</h3> | |
254 | ${h.form(url('repo_locking', repo_name=c.repo_info.repo_name),method='put')} |
|
254 | ${h.form(url('repo_locking', repo_name=c.repo_info.repo_name),method='put')} | |
255 | <div class="form"> |
|
255 | <div class="form"> | |
256 | <div class="fields"> |
|
256 | <div class="fields"> | |
257 | %if c.repo_info.locked[0]: |
|
257 | %if c.repo_info.locked[0]: | |
258 | ${h.submit('set_unlock' ,_('Unlock locked repo'),class_="ui-btn",onclick="return confirm('"+_('Confirm to unlock repository')+"');")} |
|
258 | ${h.submit('set_unlock' ,_('Unlock locked repo'),class_="ui-btn",onclick="return confirm('"+_('Confirm to unlock repository')+"');")} | |
259 | ${'Locked by %s on %s' % (h.person_by_id(c.repo_info.locked[0]),h.fmt_date(h.time_to_datetime(c.repo_info.locked[1])))} |
|
259 | ${'Locked by %s on %s' % (h.person_by_id(c.repo_info.locked[0]),h.fmt_date(h.time_to_datetime(c.repo_info.locked[1])))} | |
260 | %else: |
|
260 | %else: | |
261 | ${h.submit('set_lock',_('lock repo'),class_="ui-btn",onclick="return confirm('"+_('Confirm to lock repository')+"');")} |
|
261 | ${h.submit('set_lock',_('lock repo'),class_="ui-btn",onclick="return confirm('"+_('Confirm to lock repository')+"');")} | |
262 | ${_('Repository is not locked')} |
|
262 | ${_('Repository is not locked')} | |
263 | %endif |
|
263 | %endif | |
264 | </div> |
|
264 | </div> | |
265 | <div class="field" style="border:none;color:#888"> |
|
265 | <div class="field" style="border:none;color:#888"> | |
266 | <ul> |
|
266 | <ul> | |
267 | <li>${_('Force locking on repository. Works only when anonymous access is disabled')} |
|
267 | <li>${_('Force locking on repository. Works only when anonymous access is disabled')} | |
268 | </li> |
|
268 | </li> | |
269 | </ul> |
|
269 | </ul> | |
270 | </div> |
|
270 | </div> | |
271 | </div> |
|
271 | </div> | |
272 | ${h.end_form()} |
|
272 | ${h.end_form()} | |
273 |
|
273 | |||
274 | <h3>${_('Set as fork of')}</h3> |
|
274 | <h3>${_('Set as fork of')}</h3> | |
275 | ${h.form(url('repo_as_fork', repo_name=c.repo_info.repo_name),method='put')} |
|
275 | ${h.form(url('repo_as_fork', repo_name=c.repo_info.repo_name),method='put')} | |
276 | <div class="form"> |
|
276 | <div class="form"> | |
277 | <div class="fields"> |
|
277 | <div class="fields"> | |
278 | ${h.select('id_fork_of','',c.repos_list,class_="medium")} |
|
278 | ${h.select('id_fork_of','',c.repos_list,class_="medium")} | |
279 | ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('set'),class_="ui-btn",)} |
|
279 | ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('set'),class_="ui-btn",)} | |
280 | </div> |
|
280 | </div> | |
281 | <div class="field" style="border:none;color:#888"> |
|
281 | <div class="field" style="border:none;color:#888"> | |
282 | <ul> |
|
282 | <ul> | |
283 | <li>${_('''Manually set this repository as a fork of another from the list''')}</li> |
|
283 | <li>${_('''Manually set this repository as a fork of another from the list''')}</li> | |
284 | </ul> |
|
284 | </ul> | |
285 | </div> |
|
285 | </div> | |
286 | </div> |
|
286 | </div> | |
287 | ${h.end_form()} |
|
287 | ${h.end_form()} | |
288 |
|
288 | |||
289 | <h3>${_('Delete')}</h3> |
|
289 | <h3>${_('Delete')}</h3> | |
290 | ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='delete')} |
|
290 | ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='delete')} | |
291 | <div class="form"> |
|
291 | <div class="form"> | |
292 | <div class="fields"> |
|
292 | <div class="fields"> | |
293 | ${h.submit('remove_%s' % c.repo_info.repo_name,_('Remove this repository'),class_="ui-btn red",onclick="return confirm('"+_('Confirm to delete this repository')+"');")} |
|
293 | ${h.submit('remove_%s' % c.repo_info.repo_name,_('Remove this repository'),class_="ui-btn red",onclick="return confirm('"+_('Confirm to delete this repository')+"');")} | |
|
294 | %if c.repo_info.forks.count(): | |||
|
295 | - ${ungettext('this repository has %s fork', 'this repository has %s forks', c.repo_info.forks.count()) % c.repo_info.forks.count()} | |||
|
296 | <input type="radio" name="forks" value="detach_forks" checked="checked"/> <label for="forks">${_('Detach forks')}</label> | |||
|
297 | <input type="radio" name="forks" value="delete_forks" /> <label for="forks">${_('Delete forks')}</label> | |||
|
298 | %endif | |||
294 | </div> |
|
299 | </div> | |
295 | <div class="field" style="border:none;color:#888"> |
|
300 | <div class="field" style="border:none;color:#888"> | |
296 | <ul> |
|
301 | <ul> | |
297 | <li>${_('This repository will be renamed in a special way in order to be unaccesible for RhodeCode and VCS systems. If you need to fully delete it from file system please do it manually')}</li> |
|
302 | <li>${_('This repository will be renamed in a special way in order to be unaccesible for RhodeCode and VCS systems. If you need to fully delete it from file system please do it manually')}</li> | |
298 | </ul> |
|
303 | </ul> | |
299 | </div> |
|
304 | </div> | |
300 | </div> |
|
305 | </div> | |
301 | ${h.end_form()} |
|
306 | ${h.end_form()} | |
302 | </div> |
|
307 | </div> | |
303 |
|
308 | |||
304 | ##TODO: this should be controlled by the VISUAL setting |
|
309 | ##TODO: this should be controlled by the VISUAL setting | |
305 | %if c.visual.repository_fields: |
|
310 | %if c.visual.repository_fields: | |
306 | <div class="box box-left" style="clear:left"> |
|
311 | <div class="box box-left" style="clear:left"> | |
307 | <!-- box / title --> |
|
312 | <!-- box / title --> | |
308 | <div class="title"> |
|
313 | <div class="title"> | |
309 | <h5>${_('Extra fields')}</h5> |
|
314 | <h5>${_('Extra fields')}</h5> | |
310 | </div> |
|
315 | </div> | |
311 |
|
316 | |||
312 | <div class="emails_wrap"> |
|
317 | <div class="emails_wrap"> | |
313 | <table class="noborder"> |
|
318 | <table class="noborder"> | |
314 | %for field in c.repo_fields: |
|
319 | %for field in c.repo_fields: | |
315 | <tr> |
|
320 | <tr> | |
316 | <td>${field.field_label} (${field.field_key})</td> |
|
321 | <td>${field.field_label} (${field.field_key})</td> | |
317 | <td>${field.field_type}</td> |
|
322 | <td>${field.field_type}</td> | |
318 | <td> |
|
323 | <td> | |
319 | ${h.form(url('delete_repo_fields', repo_name=c.repo_info.repo_name, field_id=field.repo_field_id),method='delete')} |
|
324 | ${h.form(url('delete_repo_fields', repo_name=c.repo_info.repo_name, field_id=field.repo_field_id),method='delete')} | |
320 | ${h.submit('remove_%s' % field.repo_field_id, _('delete'), id="remove_field_%s" % field.repo_field_id, |
|
325 | ${h.submit('remove_%s' % field.repo_field_id, _('delete'), id="remove_field_%s" % field.repo_field_id, | |
321 | class_="delete_icon action_button", onclick="return confirm('"+_('Confirm to delete this field: %s') % field.field_key+"');")} |
|
326 | class_="delete_icon action_button", onclick="return confirm('"+_('Confirm to delete this field: %s') % field.field_key+"');")} | |
322 | ${h.end_form()} |
|
327 | ${h.end_form()} | |
323 | </td> |
|
328 | </td> | |
324 | </tr> |
|
329 | </tr> | |
325 | %endfor |
|
330 | %endfor | |
326 | </table> |
|
331 | </table> | |
327 | </div> |
|
332 | </div> | |
328 |
|
333 | |||
329 | ${h.form(url('create_repo_fields', repo_name=c.repo_info.repo_name),method='put')} |
|
334 | ${h.form(url('create_repo_fields', repo_name=c.repo_info.repo_name),method='put')} | |
330 | <div class="form"> |
|
335 | <div class="form"> | |
331 | <!-- fields --> |
|
336 | <!-- fields --> | |
332 | <div class="fields"> |
|
337 | <div class="fields"> | |
333 | <div class="field"> |
|
338 | <div class="field"> | |
334 | <div class="label"> |
|
339 | <div class="label"> | |
335 | <label for="new_field_key">${_('New field key')}:</label> |
|
340 | <label for="new_field_key">${_('New field key')}:</label> | |
336 | </div> |
|
341 | </div> | |
337 | <div class="input"> |
|
342 | <div class="input"> | |
338 | ${h.text('new_field_key', class_='small')} |
|
343 | ${h.text('new_field_key', class_='small')} | |
339 | </div> |
|
344 | </div> | |
340 | </div> |
|
345 | </div> | |
341 | <div class="field"> |
|
346 | <div class="field"> | |
342 | <div class="label"> |
|
347 | <div class="label"> | |
343 | <label for="new_field_label">${_('New field label')}:</label> |
|
348 | <label for="new_field_label">${_('New field label')}:</label> | |
344 | </div> |
|
349 | </div> | |
345 | <div class="input"> |
|
350 | <div class="input"> | |
346 | ${h.text('new_field_label', class_='small', placeholder=_('Enter short label'))} |
|
351 | ${h.text('new_field_label', class_='small', placeholder=_('Enter short label'))} | |
347 | </div> |
|
352 | </div> | |
348 | </div> |
|
353 | </div> | |
349 |
|
354 | |||
350 | <div class="field"> |
|
355 | <div class="field"> | |
351 | <div class="label"> |
|
356 | <div class="label"> | |
352 | <label for="new_field_desc">${_('New field description')}:</label> |
|
357 | <label for="new_field_desc">${_('New field description')}:</label> | |
353 | </div> |
|
358 | </div> | |
354 | <div class="input"> |
|
359 | <div class="input"> | |
355 | ${h.text('new_field_desc', class_='small', placeholder=_('Enter description of a field'))} |
|
360 | ${h.text('new_field_desc', class_='small', placeholder=_('Enter description of a field'))} | |
356 | </div> |
|
361 | </div> | |
357 | </div> |
|
362 | </div> | |
358 |
|
363 | |||
359 | <div class="buttons"> |
|
364 | <div class="buttons"> | |
360 | ${h.submit('save',_('Add'),class_="ui-btn large")} |
|
365 | ${h.submit('save',_('Add'),class_="ui-btn large")} | |
361 | ${h.reset('reset',_('Reset'),class_="ui-btn large")} |
|
366 | ${h.reset('reset',_('Reset'),class_="ui-btn large")} | |
362 | </div> |
|
367 | </div> | |
363 | </div> |
|
368 | </div> | |
364 | </div> |
|
369 | </div> | |
365 | ${h.end_form()} |
|
370 | ${h.end_form()} | |
366 | </div> |
|
371 | </div> | |
367 | %endif |
|
372 | %endif | |
368 | </%def> |
|
373 | </%def> |
General Comments 0
You need to be logged in to leave comments.
Login now