##// END OF EJS Templates
Fixes #18, removing user, who owns some repositories
marcink -
r376:7fbf8144 default
parent child Browse files
Show More
@@ -1,211 +1,218 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # repos controller for pylons
3 # repos controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 7, 2010
21 Created on April 7, 2010
22 admin controller for pylons
22 admin controller for pylons
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from formencode import htmlfill
25 from formencode import htmlfill
26 from operator import itemgetter
26 from operator import itemgetter
27 from paste.httpexceptions import HTTPInternalServerError
27 from pylons import request, response, session, tmpl_context as c, url
28 from pylons import request, response, session, tmpl_context as c, url
28 from pylons.controllers.util import abort, redirect
29 from pylons.controllers.util import abort, redirect
29 from pylons.i18n.translation import _
30 from pylons.i18n.translation import _
30 from pylons_app.lib import helpers as h
31 from pylons_app.lib import helpers as h
31 from pylons_app.lib.auth import LoginRequired, HasPermissionAllDecorator
32 from pylons_app.lib.auth import LoginRequired, HasPermissionAllDecorator
32 from pylons_app.lib.base import BaseController, render
33 from pylons_app.lib.base import BaseController, render
33 from pylons_app.lib.utils import invalidate_cache
34 from pylons_app.lib.utils import invalidate_cache
35 from pylons_app.model.db import User
34 from pylons_app.model.forms import RepoForm
36 from pylons_app.model.forms import RepoForm
35 from pylons_app.model.hg_model import HgModel
37 from pylons_app.model.hg_model import HgModel
36 from pylons_app.model.repo_model import RepoModel
38 from pylons_app.model.repo_model import RepoModel
37 import formencode
39 import formencode
38 import logging
40 import logging
39 import traceback
41 import traceback
40 from paste.httpexceptions import HTTPInternalServerError
41
42
42 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
43
44
44 class ReposController(BaseController):
45 class ReposController(BaseController):
45 """REST Controller styled on the Atom Publishing Protocol"""
46 """REST Controller styled on the Atom Publishing Protocol"""
46 # To properly map this controller, ensure your config/routing.py
47 # To properly map this controller, ensure your config/routing.py
47 # file has a resource setup:
48 # file has a resource setup:
48 # map.resource('repo', 'repos')
49 # map.resource('repo', 'repos')
49
50
50 @LoginRequired()
51 @LoginRequired()
51 @HasPermissionAllDecorator('hg.admin')
52 @HasPermissionAllDecorator('hg.admin')
52 def __before__(self):
53 def __before__(self):
53 c.admin_user = session.get('admin_user')
54 c.admin_user = session.get('admin_user')
54 c.admin_username = session.get('admin_username')
55 c.admin_username = session.get('admin_username')
55 super(ReposController, self).__before__()
56 super(ReposController, self).__before__()
56
57
57 def index(self, format='html'):
58 def index(self, format='html'):
58 """GET /repos: All items in the collection"""
59 """GET /repos: All items in the collection"""
59 # url('repos')
60 # url('repos')
60 cached_repo_list = HgModel().get_repos()
61 cached_repo_list = HgModel().get_repos()
61 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
62 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
62 return render('admin/repos/repos.html')
63 return render('admin/repos/repos.html')
63
64
64 def create(self):
65 def create(self):
65 """POST /repos: Create a new item"""
66 """POST /repos: Create a new item"""
66 # url('repos')
67 # url('repos')
67 repo_model = RepoModel()
68 repo_model = RepoModel()
68 _form = RepoForm()()
69 _form = RepoForm()()
69 form_result = {}
70 form_result = {}
70 try:
71 try:
71 form_result = _form.to_python(dict(request.POST))
72 form_result = _form.to_python(dict(request.POST))
72 repo_model.create(form_result, c.hg_app_user)
73 repo_model.create(form_result, c.hg_app_user)
73 invalidate_cache('cached_repo_list')
74 invalidate_cache('cached_repo_list')
74 h.flash(_('created repository %s') % form_result['repo_name'],
75 h.flash(_('created repository %s') % form_result['repo_name'],
75 category='success')
76 category='success')
76
77
77 except formencode.Invalid as errors:
78 except formencode.Invalid as errors:
78 c.new_repo = errors.value['repo_name']
79 c.new_repo = errors.value['repo_name']
79 return htmlfill.render(
80 return htmlfill.render(
80 render('admin/repos/repo_add.html'),
81 render('admin/repos/repo_add.html'),
81 defaults=errors.value,
82 defaults=errors.value,
82 errors=errors.error_dict or {},
83 errors=errors.error_dict or {},
83 prefix_error=False,
84 prefix_error=False,
84 encoding="UTF-8")
85 encoding="UTF-8")
85
86
86 except Exception:
87 except Exception:
87 log.error(traceback.format_exc())
88 log.error(traceback.format_exc())
88 msg = _('error occured during creation of repository %s') \
89 msg = _('error occured during creation of repository %s') \
89 % form_result.get('repo_name')
90 % form_result.get('repo_name')
90 h.flash(msg, category='error')
91 h.flash(msg, category='error')
91
92
92 return redirect('repos')
93 return redirect('repos')
93
94
94 def new(self, format='html'):
95 def new(self, format='html'):
95 """GET /repos/new: Form to create a new item"""
96 """GET /repos/new: Form to create a new item"""
96 new_repo = request.GET.get('repo', '')
97 new_repo = request.GET.get('repo', '')
97 c.new_repo = h.repo_name_slug(new_repo)
98 c.new_repo = h.repo_name_slug(new_repo)
98
99
99 return render('admin/repos/repo_add.html')
100 return render('admin/repos/repo_add.html')
100
101
101 def update(self, repo_name):
102 def update(self, repo_name):
102 """PUT /repos/repo_name: Update an existing item"""
103 """PUT /repos/repo_name: Update an existing item"""
103 # Forms posted to this method should contain a hidden field:
104 # Forms posted to this method should contain a hidden field:
104 # <input type="hidden" name="_method" value="PUT" />
105 # <input type="hidden" name="_method" value="PUT" />
105 # Or using helpers:
106 # Or using helpers:
106 # h.form(url('repo', repo_name=ID),
107 # h.form(url('repo', repo_name=ID),
107 # method='put')
108 # method='put')
108 # url('repo', repo_name=ID)
109 # url('repo', repo_name=ID)
109 repo_model = RepoModel()
110 repo_model = RepoModel()
110 changed_name = repo_name
111 changed_name = repo_name
111 _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
112 _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
112
113
113 try:
114 try:
114 form_result = _form.to_python(dict(request.POST))
115 form_result = _form.to_python(dict(request.POST))
115 repo_model.update(repo_name, form_result)
116 repo_model.update(repo_name, form_result)
116 invalidate_cache('cached_repo_list')
117 invalidate_cache('cached_repo_list')
117 h.flash(_('Repository %s updated succesfully' % repo_name),
118 h.flash(_('Repository %s updated succesfully' % repo_name),
118 category='success')
119 category='success')
119 changed_name = form_result['repo_name']
120 changed_name = form_result['repo_name']
120 except formencode.Invalid as errors:
121 except formencode.Invalid as errors:
121 c.repo_info = repo_model.get(repo_name)
122 c.repo_info = repo_model.get(repo_name)
122 c.users_array = repo_model.get_users_js()
123 c.users_array = repo_model.get_users_js()
123 errors.value.update({'user':c.repo_info.user.username})
124 errors.value.update({'user':c.repo_info.user.username})
124 return htmlfill.render(
125 return htmlfill.render(
125 render('admin/repos/repo_edit.html'),
126 render('admin/repos/repo_edit.html'),
126 defaults=errors.value,
127 defaults=errors.value,
127 errors=errors.error_dict or {},
128 errors=errors.error_dict or {},
128 prefix_error=False,
129 prefix_error=False,
129 encoding="UTF-8")
130 encoding="UTF-8")
130
131
131 except Exception:
132 except Exception:
132 log.error(traceback.format_exc())
133 log.error(traceback.format_exc())
133 h.flash(_('error occured during update of repository %s') \
134 h.flash(_('error occured during update of repository %s') \
134 % repo_name, category='error')
135 % repo_name, category='error')
135
136
136 return redirect(url('edit_repo', repo_name=changed_name))
137 return redirect(url('edit_repo', repo_name=changed_name))
137
138
138 def delete(self, repo_name):
139 def delete(self, repo_name):
139 """DELETE /repos/repo_name: Delete an existing item"""
140 """DELETE /repos/repo_name: Delete an existing item"""
140 # Forms posted to this method should contain a hidden field:
141 # Forms posted to this method should contain a hidden field:
141 # <input type="hidden" name="_method" value="DELETE" />
142 # <input type="hidden" name="_method" value="DELETE" />
142 # Or using helpers:
143 # Or using helpers:
143 # h.form(url('repo', repo_name=ID),
144 # h.form(url('repo', repo_name=ID),
144 # method='delete')
145 # method='delete')
145 # url('repo', repo_name=ID)
146 # url('repo', repo_name=ID)
146
147
147 repo_model = RepoModel()
148 repo_model = RepoModel()
148 repo = repo_model.get(repo_name)
149 repo = repo_model.get(repo_name)
149 if not repo:
150 if not repo:
150 h.flash(_('%s repository is not mapped to db perhaps'
151 h.flash(_('%s repository is not mapped to db perhaps'
151 ' it was moved or renamed from the filesystem'
152 ' it was moved or renamed from the filesystem'
152 ' please run the application again'
153 ' please run the application again'
153 ' in order to rescan repositories') % repo_name,
154 ' in order to rescan repositories') % repo_name,
154 category='error')
155 category='error')
155
156
156 return redirect(url('repos'))
157 return redirect(url('repos'))
157 try:
158 try:
158 repo_model.delete(repo)
159 repo_model.delete(repo)
159 invalidate_cache('cached_repo_list')
160 invalidate_cache('cached_repo_list')
160 h.flash(_('deleted repository %s') % repo_name, category='success')
161 h.flash(_('deleted repository %s') % repo_name, category='success')
161 except Exception:
162 except Exception:
162 h.flash(_('An error occured during deletion of %s') % repo_name,
163 h.flash(_('An error occured during deletion of %s') % repo_name,
163 category='error')
164 category='error')
164
165
165 return redirect(url('repos'))
166 return redirect(url('repos'))
166
167
167 def delete_perm_user(self, repo_name):
168 def delete_perm_user(self, repo_name):
168 """
169 """
169 DELETE an existing repository permission user
170 DELETE an existing repository permission user
170 @param repo_name:
171 @param repo_name:
171 """
172 """
172
173
173 try:
174 try:
174 repo_model = RepoModel()
175 repo_model = RepoModel()
175 repo_model.delete_perm_user(request.POST, repo_name)
176 repo_model.delete_perm_user(request.POST, repo_name)
176 except Exception as e:
177 except Exception as e:
177 h.flash(_('An error occured during deletion of repository user'),
178 h.flash(_('An error occured during deletion of repository user'),
178 category='error')
179 category='error')
179 raise HTTPInternalServerError()
180 raise HTTPInternalServerError()
180
181
181 def show(self, repo_name, format='html'):
182 def show(self, repo_name, format='html'):
182 """GET /repos/repo_name: Show a specific item"""
183 """GET /repos/repo_name: Show a specific item"""
183 # url('repo', repo_name=ID)
184 # url('repo', repo_name=ID)
184
185
185 def edit(self, repo_name, format='html'):
186 def edit(self, repo_name, format='html'):
186 """GET /repos/repo_name/edit: Form to edit an existing item"""
187 """GET /repos/repo_name/edit: Form to edit an existing item"""
187 # url('edit_repo', repo_name=ID)
188 # url('edit_repo', repo_name=ID)
188 repo_model = RepoModel()
189 repo_model = RepoModel()
189 c.repo_info = repo = repo_model.get(repo_name)
190 c.repo_info = repo = repo_model.get(repo_name)
190 if not repo:
191 if not repo:
191 h.flash(_('%s repository is not mapped to db perhaps'
192 h.flash(_('%s repository is not mapped to db perhaps'
192 ' it was created or renamed from the filesystem'
193 ' it was created or renamed from the filesystem'
193 ' please run the application again'
194 ' please run the application again'
194 ' in order to rescan repositories') % repo_name,
195 ' in order to rescan repositories') % repo_name,
195 category='error')
196 category='error')
196
197
197 return redirect(url('repos'))
198 return redirect(url('repos'))
198 defaults = c.repo_info.__dict__
199 defaults = c.repo_info.__dict__
200 if c.repo_info.user:
199 defaults.update({'user':c.repo_info.user.username})
201 defaults.update({'user':c.repo_info.user.username})
202 else:
203 replacement_user = self.sa.query(User)\
204 .filter(User.admin == True).first().username
205 defaults.update({'user':replacement_user})
206
200 c.users_array = repo_model.get_users_js()
207 c.users_array = repo_model.get_users_js()
201
208
202 for p in c.repo_info.repo2perm:
209 for p in c.repo_info.repo2perm:
203 defaults.update({'perm_%s' % p.user.username:
210 defaults.update({'perm_%s' % p.user.username:
204 p.permission.permission_name})
211 p.permission.permission_name})
205
212
206 return htmlfill.render(
213 return htmlfill.render(
207 render('admin/repos/repo_edit.html'),
214 render('admin/repos/repo_edit.html'),
208 defaults=defaults,
215 defaults=defaults,
209 encoding="UTF-8",
216 encoding="UTF-8",
210 force_defaults=False
217 force_defaults=False
211 )
218 )
@@ -1,174 +1,178 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # Model for hg app
3 # Model for hg app
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 9, 2010
21 Created on April 9, 2010
22 Model for hg app
22 Model for hg app
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from beaker.cache import cache_region
25 from beaker.cache import cache_region
26 from mercurial import ui
26 from mercurial import ui
27 from mercurial.hgweb.hgwebdir_mod import findrepos
27 from mercurial.hgweb.hgwebdir_mod import findrepos
28 from pylons.i18n.translation import _
28 from pylons.i18n.translation import _
29 from pylons_app.lib.auth import HasRepoPermissionAny
29 from pylons_app.lib.auth import HasRepoPermissionAny
30 from pylons_app.model import meta
30 from pylons_app.model import meta
31 from pylons_app.model.db import Repository
31 from pylons_app.model.db import Repository, User
32 from sqlalchemy.orm import joinedload
32 from sqlalchemy.orm import joinedload
33 from vcs.exceptions import RepositoryError, VCSError
33 from vcs.exceptions import RepositoryError, VCSError
34 import logging
34 import logging
35 import os
35 import os
36 import sys
36 import sys
37 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
38
38
39 try:
39 try:
40 from vcs.backends.hg import MercurialRepository
40 from vcs.backends.hg import MercurialRepository
41 except ImportError:
41 except ImportError:
42 sys.stderr.write('You have to import vcs module')
42 sys.stderr.write('You have to import vcs module')
43 raise Exception('Unable to import vcs')
43 raise Exception('Unable to import vcs')
44
44
45 def _get_repos_cached_initial(app_globals, initial):
45 def _get_repos_cached_initial(app_globals, initial):
46 """
46 """
47 return cached dict with repos
47 return cached dict with repos
48 """
48 """
49 g = app_globals
49 g = app_globals
50 return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui, initial)
50 return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui, initial)
51
51
52 @cache_region('long_term', 'cached_repo_list')
52 @cache_region('long_term', 'cached_repo_list')
53 def _get_repos_cached():
53 def _get_repos_cached():
54 """
54 """
55 return cached dict with repos
55 return cached dict with repos
56 """
56 """
57 log.info('getting all repositories list')
57 log.info('getting all repositories list')
58 from pylons import app_globals as g
58 from pylons import app_globals as g
59 return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui)
59 return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui)
60
60
61 @cache_region('super_short_term', 'cached_repos_switcher_list')
61 @cache_region('super_short_term', 'cached_repos_switcher_list')
62 def _get_repos_switcher_cached(cached_repo_list):
62 def _get_repos_switcher_cached(cached_repo_list):
63 repos_lst = []
63 repos_lst = []
64 for repo in sorted(x.name.lower() for x in cached_repo_list.values()):
64 for repo in sorted(x.name.lower() for x in cached_repo_list.values()):
65 if HasRepoPermissionAny('repository.write', 'repository.read', 'repository.admin')(repo, 'main page check'):
65 if HasRepoPermissionAny('repository.write', 'repository.read', 'repository.admin')(repo, 'main page check'):
66 repos_lst.append(repo)
66 repos_lst.append(repo)
67
67
68 return repos_lst
68 return repos_lst
69
69
70 @cache_region('long_term', 'full_changelog')
70 @cache_region('long_term', 'full_changelog')
71 def _full_changelog_cached(repo_name):
71 def _full_changelog_cached(repo_name):
72 log.info('getting full changelog for %s', repo_name)
72 log.info('getting full changelog for %s', repo_name)
73 return list(reversed(list(HgModel().get_repo(repo_name))))
73 return list(reversed(list(HgModel().get_repo(repo_name))))
74
74
75 class HgModel(object):
75 class HgModel(object):
76 """
76 """
77 Mercurial Model
77 Mercurial Model
78 """
78 """
79
79
80 def __init__(self):
80 def __init__(self):
81 """
81 """
82 Constructor
82 Constructor
83 """
83 """
84
84
85 @staticmethod
85 @staticmethod
86 def repo_scan(repos_prefix, repos_path, baseui, initial=False):
86 def repo_scan(repos_prefix, repos_path, baseui, initial=False):
87 """
87 """
88 Listing of repositories in given path. This path should not be a
88 Listing of repositories in given path. This path should not be a
89 repository itself. Return a dictionary of repository objects
89 repository itself. Return a dictionary of repository objects
90 :param repos_path: path to directory it could take syntax with
90 :param repos_path: path to directory it could take syntax with
91 * or ** for deep recursive displaying repositories
91 * or ** for deep recursive displaying repositories
92 """
92 """
93 sa = meta.Session()
93 sa = meta.Session()
94 def check_repo_dir(path):
94 def check_repo_dir(path):
95 """
95 """
96 Checks the repository
96 Checks the repository
97 :param path:
97 :param path:
98 """
98 """
99 repos_path = path.split('/')
99 repos_path = path.split('/')
100 if repos_path[-1] in ['*', '**']:
100 if repos_path[-1] in ['*', '**']:
101 repos_path = repos_path[:-1]
101 repos_path = repos_path[:-1]
102 if repos_path[0] != '/':
102 if repos_path[0] != '/':
103 repos_path[0] = '/'
103 repos_path[0] = '/'
104 if not os.path.isdir(os.path.join(*repos_path)):
104 if not os.path.isdir(os.path.join(*repos_path)):
105 raise RepositoryError('Not a valid repository in %s' % path[0][1])
105 raise RepositoryError('Not a valid repository in %s' % path[0][1])
106 if not repos_path.endswith('*'):
106 if not repos_path.endswith('*'):
107 raise VCSError('You need to specify * or ** at the end of path '
107 raise VCSError('You need to specify * or ** at the end of path '
108 'for recursive scanning')
108 'for recursive scanning')
109
109
110 check_repo_dir(repos_path)
110 check_repo_dir(repos_path)
111 log.info('scanning for repositories in %s', repos_path)
111 log.info('scanning for repositories in %s', repos_path)
112 repos = findrepos([(repos_prefix, repos_path)])
112 repos = findrepos([(repos_prefix, repos_path)])
113 if not isinstance(baseui, ui.ui):
113 if not isinstance(baseui, ui.ui):
114 baseui = ui.ui()
114 baseui = ui.ui()
115
115
116 repos_list = {}
116 repos_list = {}
117 for name, path in repos:
117 for name, path in repos:
118 try:
118 try:
119 #name = name.split('/')[-1]
119 #name = name.split('/')[-1]
120 if repos_list.has_key(name):
120 if repos_list.has_key(name):
121 raise RepositoryError('Duplicate repository name %s found in'
121 raise RepositoryError('Duplicate repository name %s found in'
122 ' %s' % (name, path))
122 ' %s' % (name, path))
123 else:
123 else:
124
124
125 repos_list[name] = MercurialRepository(path, baseui=baseui)
125 repos_list[name] = MercurialRepository(path, baseui=baseui)
126 repos_list[name].name = name
126 repos_list[name].name = name
127
127
128 dbrepo = None
128 dbrepo = None
129 if not initial:
129 if not initial:
130 dbrepo = sa.query(Repository)\
130 dbrepo = sa.query(Repository)\
131 .filter(Repository.repo_name == name).scalar()
131 .filter(Repository.repo_name == name).scalar()
132
132
133 if dbrepo:
133 if dbrepo:
134 log.info('Adding db instance to cached list')
134 log.info('Adding db instance to cached list')
135 repos_list[name].dbrepo = dbrepo
135 repos_list[name].dbrepo = dbrepo
136 repos_list[name].description = dbrepo.description
136 repos_list[name].description = dbrepo.description
137 if dbrepo.user:
137 repos_list[name].contact = dbrepo.user.full_contact
138 repos_list[name].contact = dbrepo.user.full_contact
139 else:
140 repos_list[name].contact = sa.query(User)\
141 .filter(User.admin == True).first().full_contact
138 except OSError:
142 except OSError:
139 continue
143 continue
140 meta.Session.remove()
144 meta.Session.remove()
141 return repos_list
145 return repos_list
142
146
143 def get_repos(self):
147 def get_repos(self):
144 for name, repo in _get_repos_cached().items():
148 for name, repo in _get_repos_cached().items():
145 if repo._get_hidden():
149 if repo._get_hidden():
146 #skip hidden web repository
150 #skip hidden web repository
147 continue
151 continue
148
152
149 last_change = repo.last_change
153 last_change = repo.last_change
150 try:
154 try:
151 tip = repo.get_changeset('tip')
155 tip = repo.get_changeset('tip')
152 except RepositoryError:
156 except RepositoryError:
153 from pylons_app.lib.utils import EmptyChangeset
157 from pylons_app.lib.utils import EmptyChangeset
154 tip = EmptyChangeset()
158 tip = EmptyChangeset()
155
159
156 tmp_d = {}
160 tmp_d = {}
157 tmp_d['name'] = repo.name
161 tmp_d['name'] = repo.name
158 tmp_d['name_sort'] = tmp_d['name'].lower()
162 tmp_d['name_sort'] = tmp_d['name'].lower()
159 tmp_d['description'] = repo.description
163 tmp_d['description'] = repo.description
160 tmp_d['description_sort'] = tmp_d['description']
164 tmp_d['description_sort'] = tmp_d['description']
161 tmp_d['last_change'] = last_change
165 tmp_d['last_change'] = last_change
162 tmp_d['last_change_sort'] = last_change[1] - last_change[0]
166 tmp_d['last_change_sort'] = last_change[1] - last_change[0]
163 tmp_d['tip'] = tip.raw_id
167 tmp_d['tip'] = tip.raw_id
164 tmp_d['tip_sort'] = tip.revision
168 tmp_d['tip_sort'] = tip.revision
165 tmp_d['rev'] = tip.revision
169 tmp_d['rev'] = tip.revision
166 tmp_d['contact'] = repo.contact
170 tmp_d['contact'] = repo.contact
167 tmp_d['contact_sort'] = tmp_d['contact']
171 tmp_d['contact_sort'] = tmp_d['contact']
168 tmp_d['repo_archives'] = list(repo._get_archives())
172 tmp_d['repo_archives'] = list(repo._get_archives())
169 tmp_d['last_msg'] = tip.message
173 tmp_d['last_msg'] = tip.message
170 tmp_d['repo'] = repo
174 tmp_d['repo'] = repo
171 yield tmp_d
175 yield tmp_d
172
176
173 def get_repo(self, repo_name):
177 def get_repo(self, repo_name):
174 return _get_repos_cached()[repo_name]
178 return _get_repos_cached()[repo_name]
General Comments 0
You need to be logged in to leave comments. Login now