##// END OF EJS Templates
db model fix, added repo instance to cached repos list
marcink -
r303:3a66e742 default
parent child Browse files
Show More
@@ -1,71 +1,71 b''
1 from pylons_app.model.meta import Base
1 from pylons_app.model.meta import Base
2 from sqlalchemy.orm import relation, backref
2 from sqlalchemy.orm import relation, backref
3 from sqlalchemy import *
3 from sqlalchemy import *
4 from vcs.utils.lazy import LazyProperty
4 from vcs.utils.lazy import LazyProperty
5
5
6 class User(Base):
6 class User(Base):
7 __tablename__ = 'users'
7 __tablename__ = 'users'
8 __table_args__ = {'useexisting':True}
8 __table_args__ = {'useexisting':True}
9 user_id = Column("user_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
9 user_id = Column("user_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
10 username = Column("username", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
10 username = Column("username", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
11 password = Column("password", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
11 password = Column("password", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
12 active = Column("active", BOOLEAN(), nullable=True, unique=None, default=None)
12 active = Column("active", BOOLEAN(), nullable=True, unique=None, default=None)
13 admin = Column("admin", BOOLEAN(), nullable=True, unique=None, default=None)
13 admin = Column("admin", BOOLEAN(), nullable=True, unique=None, default=False)
14 name = Column("name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
14 name = Column("name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
15 lastname = Column("lastname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
15 lastname = Column("lastname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
16 email = Column("email", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
16 email = Column("email", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
17 last_login = Column("last_login", DATETIME(timezone=False), nullable=True, unique=None, default=None)
17 last_login = Column("last_login", DATETIME(timezone=False), nullable=True, unique=None, default=None)
18
18
19 user_log = relation('UserLog')
19 user_log = relation('UserLog')
20
20
21 @LazyProperty
21 @LazyProperty
22 def full_contact(self):
22 def full_contact(self):
23 return '%s %s <%s>' % (self.name, self.lastname, self.email)
23 return '%s %s <%s>' % (self.name, self.lastname, self.email)
24
24
25 def __repr__(self):
25 def __repr__(self):
26 return "<User('%s:%s')>" % (self.user_id, self.username)
26 return "<User('%s:%s')>" % (self.user_id, self.username)
27
27
28 class UserLog(Base):
28 class UserLog(Base):
29 __tablename__ = 'user_logs'
29 __tablename__ = 'user_logs'
30 __table_args__ = {'useexisting':True}
30 __table_args__ = {'useexisting':True}
31 user_log_id = Column("user_log_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
31 user_log_id = Column("user_log_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
32 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
32 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
33 user_ip = Column("user_ip", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
33 user_ip = Column("user_ip", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
34 repository = Column("repository", TEXT(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_name'), nullable=False, unique=None, default=None)
34 repository = Column("repository", TEXT(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_name'), nullable=False, unique=None, default=None)
35 action = Column("action", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
35 action = Column("action", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
36 action_date = Column("action_date", DATETIME(timezone=False), nullable=True, unique=None, default=None)
36 action_date = Column("action_date", DATETIME(timezone=False), nullable=True, unique=None, default=None)
37
37
38 user = relation('User')
38 user = relation('User')
39
39
40 class Repository(Base):
40 class Repository(Base):
41 __tablename__ = 'repositories'
41 __tablename__ = 'repositories'
42 __table_args__ = {'useexisting':True}
42 __table_args__ = {'useexisting':True}
43 repo_name = Column("repo_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None, primary_key=True)
43 repo_name = Column("repo_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None, primary_key=True)
44 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=False, default=None)
44 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=False, default=None)
45 private = Column("private", BOOLEAN(), nullable=True, unique=None, default=None)
45 private = Column("private", BOOLEAN(), nullable=True, unique=None, default=None)
46 description = Column("description", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
46 description = Column("description", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
47
47
48 user = relation('User')
48 user = relation('User')
49 repo2perm = relation('Repo2Perm', cascade='all')
49 repo2perm = relation('Repo2Perm', cascade='all')
50
50
51 class Permission(Base):
51 class Permission(Base):
52 __tablename__ = 'permissions'
52 __tablename__ = 'permissions'
53 __table_args__ = {'useexisting':True}
53 __table_args__ = {'useexisting':True}
54 permission_id = Column("permission_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
54 permission_id = Column("permission_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
55 permission_name = Column("permission_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
55 permission_name = Column("permission_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
56 permission_longname = Column("permission_longname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
56 permission_longname = Column("permission_longname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
57
57
58 def __repr__(self):
58 def __repr__(self):
59 return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
59 return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
60
60
61 class Repo2Perm(Base):
61 class Repo2Perm(Base):
62 __tablename__ = 'repo_to_perm'
62 __tablename__ = 'repo_to_perm'
63 __table_args__ = (UniqueConstraint('user_id', 'permission_id', 'repository'), {'useexisting':True})
63 __table_args__ = (UniqueConstraint('user_id', 'permission_id', 'repository'), {'useexisting':True})
64 repo2perm_id = Column("repo2perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
64 repo2perm_id = Column("repo2perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
65 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
65 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
66 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
66 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
67 repository = Column("repository", TEXT(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_name'), nullable=False, unique=None, default=None)
67 repository = Column("repository", TEXT(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_name'), nullable=False, unique=None, default=None)
68
68
69 user = relation('User')
69 user = relation('User')
70 permission = relation('Permission')
70 permission = relation('Permission')
71
71
@@ -1,156 +1,158 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 from sqlalchemy.orm import joinedload
5
6
6 # This program is free software; you can redistribute it and/or
7 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
9 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
10 # of the License or (at your opinion) any later version of the license.
10 #
11 #
11 # This program is distributed in the hope that it will be useful,
12 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 # GNU General Public License for more details.
15 #
16 #
16 # You should have received a copy of the GNU General Public License
17 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
20 # MA 02110-1301, USA.
20
21
21 """
22 """
22 Created on April 9, 2010
23 Created on April 9, 2010
23 Model for hg app
24 Model for hg app
24 @author: marcink
25 @author: marcink
25 """
26 """
26
27
27 from beaker.cache import cache_region
28 from beaker.cache import cache_region
28 from mercurial import ui
29 from mercurial import ui
29 from mercurial.hgweb.hgwebdir_mod import findrepos
30 from mercurial.hgweb.hgwebdir_mod import findrepos
30 from vcs.exceptions import RepositoryError, VCSError
31 from vcs.exceptions import RepositoryError, VCSError
31 from pylons_app.model.meta import Session
32 from pylons_app.model.meta import Session
32 from pylons_app.model.db import Repository
33 from pylons_app.model.db import Repository
33 import logging
34 import logging
34 import os
35 import os
35 import sys
36 import sys
36 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
37
38
38 try:
39 try:
39 from vcs.backends.hg import MercurialRepository
40 from vcs.backends.hg import MercurialRepository
40 except ImportError:
41 except ImportError:
41 sys.stderr.write('You have to import vcs module')
42 sys.stderr.write('You have to import vcs module')
42 raise Exception('Unable to import vcs')
43 raise Exception('Unable to import vcs')
43
44
44 def _get_repos_cached_initial(app_globals):
45 def _get_repos_cached_initial(app_globals):
45 """
46 """
46 return cached dict with repos
47 return cached dict with repos
47 """
48 """
48 g = app_globals
49 g = app_globals
49 return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui)
50 return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui)
50
51
51 @cache_region('long_term', 'cached_repo_list')
52 @cache_region('long_term', 'cached_repo_list')
52 def _get_repos_cached():
53 def _get_repos_cached():
53 """
54 """
54 return cached dict with repos
55 return cached dict with repos
55 """
56 """
56 log.info('getting all repositories list')
57 log.info('getting all repositories list')
57 from pylons import app_globals as g
58 from pylons import app_globals as g
58 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)
59
60
60 @cache_region('long_term', 'full_changelog')
61 @cache_region('long_term', 'full_changelog')
61 def _full_changelog_cached(repo_name):
62 def _full_changelog_cached(repo_name):
62 log.info('getting full changelog for %s', repo_name)
63 log.info('getting full changelog for %s', repo_name)
63 return list(reversed(list(HgModel().get_repo(repo_name))))
64 return list(reversed(list(HgModel().get_repo(repo_name))))
64
65
65 class HgModel(object):
66 class HgModel(object):
66 """
67 """
67 Mercurial Model
68 Mercurial Model
68 """
69 """
69
70
70 def __init__(self):
71 def __init__(self):
71 """
72 """
72 Constructor
73 Constructor
73 """
74 """
74
75
75 @staticmethod
76 @staticmethod
76 def repo_scan(repos_prefix, repos_path, baseui):
77 def repo_scan(repos_prefix, repos_path, baseui):
77 """
78 """
78 Listing of repositories in given path. This path should not be a
79 Listing of repositories in given path. This path should not be a
79 repository itself. Return a dictionary of repository objects
80 repository itself. Return a dictionary of repository objects
80 :param repos_path: path to directory it could take syntax with
81 :param repos_path: path to directory it could take syntax with
81 * or ** for deep recursive displaying repositories
82 * or ** for deep recursive displaying repositories
82 """
83 """
83 sa = Session()
84 sa = Session()
84 def check_repo_dir(path):
85 def check_repo_dir(path):
85 """
86 """
86 Checks the repository
87 Checks the repository
87 :param path:
88 :param path:
88 """
89 """
89 repos_path = path.split('/')
90 repos_path = path.split('/')
90 if repos_path[-1] in ['*', '**']:
91 if repos_path[-1] in ['*', '**']:
91 repos_path = repos_path[:-1]
92 repos_path = repos_path[:-1]
92 if repos_path[0] != '/':
93 if repos_path[0] != '/':
93 repos_path[0] = '/'
94 repos_path[0] = '/'
94 if not os.path.isdir(os.path.join(*repos_path)):
95 if not os.path.isdir(os.path.join(*repos_path)):
95 raise RepositoryError('Not a valid repository in %s' % path[0][1])
96 raise RepositoryError('Not a valid repository in %s' % path[0][1])
96 if not repos_path.endswith('*'):
97 if not repos_path.endswith('*'):
97 raise VCSError('You need to specify * or ** at the end of path '
98 raise VCSError('You need to specify * or ** at the end of path '
98 'for recursive scanning')
99 'for recursive scanning')
99
100
100 check_repo_dir(repos_path)
101 check_repo_dir(repos_path)
101 log.info('scanning for repositories in %s', repos_path)
102 log.info('scanning for repositories in %s', repos_path)
102 repos = findrepos([(repos_prefix, repos_path)])
103 repos = findrepos([(repos_prefix, repos_path)])
103 if not isinstance(baseui, ui.ui):
104 if not isinstance(baseui, ui.ui):
104 baseui = ui.ui()
105 baseui = ui.ui()
105
106
106 repos_list = {}
107 repos_list = {}
107 for name, path in repos:
108 for name, path in repos:
108 try:
109 try:
109 #name = name.split('/')[-1]
110 #name = name.split('/')[-1]
110 if repos_list.has_key(name):
111 if repos_list.has_key(name):
111 raise RepositoryError('Duplicate repository name %s found in'
112 raise RepositoryError('Duplicate repository name %s found in'
112 ' %s' % (name, path))
113 ' %s' % (name, path))
113 else:
114 else:
114
115
115 repos_list[name] = MercurialRepository(path, baseui=baseui)
116 repos_list[name] = MercurialRepository(path, baseui=baseui)
116 repos_list[name].name = name
117 repos_list[name].name = name
117 dbrepo = sa.query(Repository).get(name)
118 dbrepo = sa.query(Repository).get(name)
118 if dbrepo:
119 if dbrepo:
120 repos_list[name].dbrepo = dbrepo
119 repos_list[name].description = dbrepo.description
121 repos_list[name].description = dbrepo.description
120 repos_list[name].contact = dbrepo.user.full_contact
122 repos_list[name].contact = dbrepo.user.full_contact
121 except OSError:
123 except OSError:
122 continue
124 continue
123 return repos_list
125 return repos_list
124
126
125 def get_repos(self):
127 def get_repos(self):
126 for name, repo in _get_repos_cached().items():
128 for name, repo in _get_repos_cached().items():
127 if repo._get_hidden():
129 if repo._get_hidden():
128 #skip hidden web repository
130 #skip hidden web repository
129 continue
131 continue
130
132
131 last_change = repo.last_change
133 last_change = repo.last_change
132 try:
134 try:
133 tip = repo.get_changeset('tip')
135 tip = repo.get_changeset('tip')
134 except RepositoryError:
136 except RepositoryError:
135 from pylons_app.lib.utils import EmptyChangeset
137 from pylons_app.lib.utils import EmptyChangeset
136 tip = EmptyChangeset()
138 tip = EmptyChangeset()
137
139
138 tmp_d = {}
140 tmp_d = {}
139 tmp_d['name'] = repo.name
141 tmp_d['name'] = repo.name
140 tmp_d['name_sort'] = tmp_d['name'].lower()
142 tmp_d['name_sort'] = tmp_d['name'].lower()
141 tmp_d['description'] = repo.description
143 tmp_d['description'] = repo.description
142 tmp_d['description_sort'] = tmp_d['description']
144 tmp_d['description_sort'] = tmp_d['description']
143 tmp_d['last_change'] = last_change
145 tmp_d['last_change'] = last_change
144 tmp_d['last_change_sort'] = last_change[1] - last_change[0]
146 tmp_d['last_change_sort'] = last_change[1] - last_change[0]
145 tmp_d['tip'] = tip.raw_id
147 tmp_d['tip'] = tip.raw_id
146 tmp_d['tip_sort'] = tip.revision
148 tmp_d['tip_sort'] = tip.revision
147 tmp_d['rev'] = tip.revision
149 tmp_d['rev'] = tip.revision
148 tmp_d['contact'] = repo.contact
150 tmp_d['contact'] = repo.contact
149 tmp_d['contact_sort'] = tmp_d['contact']
151 tmp_d['contact_sort'] = tmp_d['contact']
150 tmp_d['repo_archives'] = list(repo._get_archives())
152 tmp_d['repo_archives'] = list(repo._get_archives())
151 tmp_d['last_msg'] = tip.message
153 tmp_d['last_msg'] = tip.message
152
154 tmp_d['repo'] = repo
153 yield tmp_d
155 yield tmp_d
154
156
155 def get_repo(self, repo_name):
157 def get_repo(self, repo_name):
156 return _get_repos_cached()[repo_name]
158 return _get_repos_cached()[repo_name]
General Comments 0
You need to be logged in to leave comments. Login now