##// END OF EJS Templates
removed .lower() from permission checking of cached repos list since repos can have capital letters now
marcink -
r511:0fce1f9e default
parent child Browse files
Show More
@@ -1,169 +1,169 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, User
31 from pylons_app.model.db import Repository, User
32 from pylons_app.lib import helpers as h
32 from pylons_app.lib import helpers as h
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 """return cached dict with repos
46 """return cached dict with repos
47 """
47 """
48 g = app_globals
48 g = app_globals
49 return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui, initial)
49 return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui, initial)
50
50
51 @cache_region('long_term', 'cached_repo_list')
51 @cache_region('long_term', 'cached_repo_list')
52 def _get_repos_cached():
52 def _get_repos_cached():
53 """return cached dict with repos
53 """return cached dict with repos
54 """
54 """
55 log.info('getting all repositories list')
55 log.info('getting all repositories list')
56 from pylons import app_globals as g
56 from pylons import app_globals as g
57 return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui)
57 return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui)
58
58
59 @cache_region('super_short_term', 'cached_repos_switcher_list')
59 @cache_region('super_short_term', 'cached_repos_switcher_list')
60 def _get_repos_switcher_cached(cached_repo_list):
60 def _get_repos_switcher_cached(cached_repo_list):
61 repos_lst = []
61 repos_lst = []
62 for repo in [x for x in cached_repo_list.values()]:
62 for repo in [x for x in cached_repo_list.values()]:
63 if HasRepoPermissionAny('repository.write', 'repository.read',
63 if HasRepoPermissionAny('repository.write', 'repository.read',
64 'repository.admin')(repo.name.lower(), 'main page check'):
64 'repository.admin')(repo.name, 'main page check'):
65 repos_lst.append((repo.name, repo.dbrepo.private,))
65 repos_lst.append((repo.name, repo.dbrepo.private,))
66
66
67 return sorted(repos_lst, key=lambda k:k[0])
67 return sorted(repos_lst, key=lambda k:k[0].lower())
68
68
69 @cache_region('long_term', 'full_changelog')
69 @cache_region('long_term', 'full_changelog')
70 def _full_changelog_cached(repo_name):
70 def _full_changelog_cached(repo_name):
71 log.info('getting full changelog for %s', repo_name)
71 log.info('getting full changelog for %s', repo_name)
72 return list(reversed(list(HgModel().get_repo(repo_name))))
72 return list(reversed(list(HgModel().get_repo(repo_name))))
73
73
74 class HgModel(object):
74 class HgModel(object):
75 """Mercurial Model
75 """Mercurial Model
76 """
76 """
77
77
78 def __init__(self):
78 def __init__(self):
79 pass
79 pass
80
80
81 @staticmethod
81 @staticmethod
82 def repo_scan(repos_prefix, repos_path, baseui, initial=False):
82 def repo_scan(repos_prefix, repos_path, baseui, initial=False):
83 """
83 """
84 Listing of repositories in given path. This path should not be a
84 Listing of repositories in given path. This path should not be a
85 repository itself. Return a dictionary of repository objects
85 repository itself. Return a dictionary of repository objects
86 :param repos_path: path to directory it could take syntax with
86 :param repos_path: path to directory it could take syntax with
87 * or ** for deep recursive displaying repositories
87 * or ** for deep recursive displaying repositories
88 """
88 """
89 sa = meta.Session()
89 sa = meta.Session()
90 def check_repo_dir(path):
90 def check_repo_dir(path):
91 """Checks the repository
91 """Checks the repository
92 :param path:
92 :param path:
93 """
93 """
94 repos_path = path.split('/')
94 repos_path = path.split('/')
95 if repos_path[-1] in ['*', '**']:
95 if repos_path[-1] in ['*', '**']:
96 repos_path = repos_path[:-1]
96 repos_path = repos_path[:-1]
97 if repos_path[0] != '/':
97 if repos_path[0] != '/':
98 repos_path[0] = '/'
98 repos_path[0] = '/'
99 if not os.path.isdir(os.path.join(*repos_path)):
99 if not os.path.isdir(os.path.join(*repos_path)):
100 raise RepositoryError('Not a valid repository in %s' % path)
100 raise RepositoryError('Not a valid repository in %s' % path)
101 if not repos_path.endswith('*'):
101 if not repos_path.endswith('*'):
102 raise VCSError('You need to specify * or ** at the end of path '
102 raise VCSError('You need to specify * or ** at the end of path '
103 'for recursive scanning')
103 'for recursive scanning')
104
104
105 check_repo_dir(repos_path)
105 check_repo_dir(repos_path)
106 log.info('scanning for repositories in %s', repos_path)
106 log.info('scanning for repositories in %s', repos_path)
107 repos = findrepos([(repos_prefix, repos_path)])
107 repos = findrepos([(repos_prefix, repos_path)])
108 if not isinstance(baseui, ui.ui):
108 if not isinstance(baseui, ui.ui):
109 baseui = ui.ui()
109 baseui = ui.ui()
110
110
111 repos_list = {}
111 repos_list = {}
112 for name, path in repos:
112 for name, path in repos:
113 try:
113 try:
114 #name = name.split('/')[-1]
114 #name = name.split('/')[-1]
115 if repos_list.has_key(name):
115 if repos_list.has_key(name):
116 raise RepositoryError('Duplicate repository name %s found in'
116 raise RepositoryError('Duplicate repository name %s found in'
117 ' %s' % (name, path))
117 ' %s' % (name, path))
118 else:
118 else:
119
119
120 repos_list[name] = MercurialRepository(path, baseui=baseui)
120 repos_list[name] = MercurialRepository(path, baseui=baseui)
121 repos_list[name].name = name
121 repos_list[name].name = name
122
122
123 dbrepo = None
123 dbrepo = None
124 if not initial:
124 if not initial:
125 dbrepo = sa.query(Repository)\
125 dbrepo = sa.query(Repository)\
126 .filter(Repository.repo_name == name).scalar()
126 .filter(Repository.repo_name == name).scalar()
127
127
128 if dbrepo:
128 if dbrepo:
129 log.info('Adding db instance to cached list')
129 log.info('Adding db instance to cached list')
130 repos_list[name].dbrepo = dbrepo
130 repos_list[name].dbrepo = dbrepo
131 repos_list[name].description = dbrepo.description
131 repos_list[name].description = dbrepo.description
132 if dbrepo.user:
132 if dbrepo.user:
133 repos_list[name].contact = dbrepo.user.full_contact
133 repos_list[name].contact = dbrepo.user.full_contact
134 else:
134 else:
135 repos_list[name].contact = sa.query(User)\
135 repos_list[name].contact = sa.query(User)\
136 .filter(User.admin == True).first().full_contact
136 .filter(User.admin == True).first().full_contact
137 except OSError:
137 except OSError:
138 continue
138 continue
139 meta.Session.remove()
139 meta.Session.remove()
140 return repos_list
140 return repos_list
141
141
142 def get_repos(self):
142 def get_repos(self):
143 for name, repo in _get_repos_cached().items():
143 for name, repo in _get_repos_cached().items():
144 if repo._get_hidden():
144 if repo._get_hidden():
145 #skip hidden web repository
145 #skip hidden web repository
146 continue
146 continue
147
147
148 last_change = repo.last_change
148 last_change = repo.last_change
149 tip = h.get_changeset_safe(repo, 'tip')
149 tip = h.get_changeset_safe(repo, 'tip')
150
150
151 tmp_d = {}
151 tmp_d = {}
152 tmp_d['name'] = repo.name
152 tmp_d['name'] = repo.name
153 tmp_d['name_sort'] = tmp_d['name'].lower()
153 tmp_d['name_sort'] = tmp_d['name'].lower()
154 tmp_d['description'] = repo.description
154 tmp_d['description'] = repo.description
155 tmp_d['description_sort'] = tmp_d['description']
155 tmp_d['description_sort'] = tmp_d['description']
156 tmp_d['last_change'] = last_change
156 tmp_d['last_change'] = last_change
157 tmp_d['last_change_sort'] = last_change[1] - last_change[0]
157 tmp_d['last_change_sort'] = last_change[1] - last_change[0]
158 tmp_d['tip'] = tip.raw_id
158 tmp_d['tip'] = tip.raw_id
159 tmp_d['tip_sort'] = tip.revision
159 tmp_d['tip_sort'] = tip.revision
160 tmp_d['rev'] = tip.revision
160 tmp_d['rev'] = tip.revision
161 tmp_d['contact'] = repo.contact
161 tmp_d['contact'] = repo.contact
162 tmp_d['contact_sort'] = tmp_d['contact']
162 tmp_d['contact_sort'] = tmp_d['contact']
163 tmp_d['repo_archives'] = list(repo._get_archives())
163 tmp_d['repo_archives'] = list(repo._get_archives())
164 tmp_d['last_msg'] = tip.message
164 tmp_d['last_msg'] = tip.message
165 tmp_d['repo'] = repo
165 tmp_d['repo'] = repo
166 yield tmp_d
166 yield tmp_d
167
167
168 def get_repo(self, repo_name):
168 def get_repo(self, repo_name):
169 return _get_repos_cached()[repo_name]
169 return _get_repos_cached()[repo_name]
General Comments 0
You need to be logged in to leave comments. Login now