##// END OF EJS Templates
updated db manage script, and remove broken test
marcink -
r351:d0938159 default
parent child Browse files
Show More
@@ -1,193 +1,192 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # database managment for hg app
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5
5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20
21 21 """
22 22 Created on April 10, 2010
23 23 database managment and creation for hg app
24 24 @author: marcink
25 25 """
26 26
27 27 from os.path import dirname as dn, join as jn
28 28 import os
29 29 import sys
30 30 import uuid
31 31 ROOT = dn(dn(dn(os.path.realpath(__file__))))
32 32 sys.path.append(ROOT)
33 33
34 34 from pylons_app.lib.auth import get_crypt_password
35 from pylons_app.lib.utils import ask_ok
35 36 from pylons_app.model import init_model
36 37 from pylons_app.model.db import User, Permission, HgAppUi, HgAppSettings
37 38 from pylons_app.model import meta
38 39 from sqlalchemy.engine import create_engine
39 40 import logging
40 41
41 log = logging.getLogger('db manage')
42 log.setLevel(logging.DEBUG)
43 console_handler = logging.StreamHandler()
44 console_handler.setFormatter(logging.Formatter("%(asctime)s.%(msecs)03d"
45 " %(levelname)-5.5s [%(name)s] %(message)s"))
46 log.addHandler(console_handler)
42 log = logging.getLogger(__name__)
47 43
48 44 class DbManage(object):
49 45 def __init__(self, log_sql):
50 46 self.dbname = 'hg_app.db'
51 47 dburi = 'sqlite:////%s' % jn(ROOT, self.dbname)
52 48 engine = create_engine(dburi, echo=log_sql)
53 49 init_model(engine)
54 50 self.sa = meta.Session
55 51 self.db_exists = False
56 52
57 53 def check_for_db(self, override):
58 54 log.info('checking for exisiting db')
59 55 if os.path.isfile(jn(ROOT, self.dbname)):
60 56 self.db_exists = True
61 57 log.info('database exisist')
62 58 if not override:
63 59 raise Exception('database already exists')
64 60
65 61 def create_tables(self, override=False):
66 62 """
67 63 Create a auth database
68 64 """
69 65 self.check_for_db(override)
70 66 if override:
71 67 log.info("database exisist and it's going to be destroyed")
72 if self.db_exists:
68 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
69 if not destroy:
70 sys.exit()
71 if self.db_exists and destroy:
73 72 os.remove(jn(ROOT, self.dbname))
74 meta.Base.metadata.create_all(checkfirst=override)
73 checkfirst = not override
74 meta.Base.metadata.create_all(checkfirst=checkfirst)
75 75 log.info('Created tables for %s', self.dbname)
76 76
77 77 def admin_prompt(self):
78 78 import getpass
79 79 username = raw_input('Specify admin username:')
80 80 password = getpass.getpass('Specify admin password:')
81 81 self.create_user(username, password, True)
82 82
83 83 def config_prompt(self):
84 84 log.info('Setting up repositories config')
85 85
86
87 86 path = raw_input('Specify valid full path to your repositories'
88 ' you can change this later application settings:')
87 ' you can change this later in application settings:')
89 88
90 89 if not os.path.isdir(path):
91 90 log.error('You entered wrong path')
92 91 sys.exit()
93 92
94 93 hooks = HgAppUi()
95 94 hooks.ui_section = 'hooks'
96 95 hooks.ui_key = 'changegroup'
97 96 hooks.ui_value = 'hg update >&2'
98 97
99 98 web1 = HgAppUi()
100 99 web1.ui_section = 'web'
101 100 web1.ui_key = 'push_ssl'
102 101 web1.ui_value = 'false'
103 102
104 103 web2 = HgAppUi()
105 104 web2.ui_section = 'web'
106 105 web2.ui_key = 'allow_archive'
107 106 web2.ui_value = 'gz zip bz2'
108 107
109 108 web3 = HgAppUi()
110 109 web3.ui_section = 'web'
111 110 web3.ui_key = 'allow_push'
112 111 web3.ui_value = '*'
113 112
114 113 web4 = HgAppUi()
115 114 web4.ui_section = 'web'
116 115 web4.ui_key = 'baseurl'
117 116 web4.ui_value = '/'
118 117
119 118 paths = HgAppUi()
120 119 paths.ui_section = 'paths'
121 120 paths.ui_key = '/'
122 121 paths.ui_value = os.path.join(path, '*')
123 122
124 123
125 124 hgsettings = HgAppSettings()
126 125 hgsettings.app_auth_realm = 'hg-app authentication'
127 126 hgsettings.app_title = 'hg-app'
128 127
129 128 try:
130 129 self.sa.add(hooks)
131 130 self.sa.add(web1)
132 131 self.sa.add(web2)
133 132 self.sa.add(web3)
134 133 self.sa.add(web4)
135 134 self.sa.add(paths)
136 135 self.sa.add(hgsettings)
137 136 self.sa.commit()
138 137 except:
139 138 self.sa.rollback()
140 139 raise
141 140 log.info('created ui config')
142 141
143 142 def create_user(self, username, password, admin=False):
144 143
145 144 log.info('creating default user')
146 145 #create default user for handling default permissions.
147 146 def_user = User()
148 147 def_user.username = 'default'
149 148 def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
150 149 def_user.name = 'default'
151 150 def_user.lastname = 'default'
152 151 def_user.email = 'default@default.com'
153 152 def_user.admin = False
154 153 def_user.active = False
155 154
156 155 log.info('creating administrator user %s', username)
157 156 new_user = User()
158 157 new_user.username = username
159 158 new_user.password = get_crypt_password(password)
160 159 new_user.name = 'Hg'
161 160 new_user.lastname = 'Admin'
162 161 new_user.email = 'admin@localhost'
163 162 new_user.admin = admin
164 163 new_user.active = True
165 164
166 165 try:
167 166 self.sa.add(def_user)
168 167 self.sa.add(new_user)
169 168 self.sa.commit()
170 169 except:
171 170 self.sa.rollback()
172 171 raise
173 172
174 173 def create_permissions(self):
175 174 #module.(access|create|change|delete)_[name]
176 175 #module.(read|write|owner)
177 176 perms = [('repository.none', 'Repository no access'),
178 177 ('repository.read', 'Repository read access'),
179 178 ('repository.write', 'Repository write access'),
180 179 ('repository.admin', 'Repository admin access'),
181 180 ('hg.admin', 'Hg Administrator'),
182 181 ]
183 182
184 183 for p in perms:
185 184 new_perm = Permission()
186 185 new_perm.permission_name = p[0]
187 186 new_perm.permission_longname = p[1]
188 187 try:
189 188 self.sa.add(new_perm)
190 189 self.sa.commit()
191 190 except:
192 191 self.sa.rollback()
193 192 raise
@@ -1,221 +1,228 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # Utilities for hg app
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 # This program is free software; you can redistribute it and/or
6 6 # modify it under the terms of the GNU General Public License
7 7 # as published by the Free Software Foundation; version 2
8 8 # of the License or (at your opinion) any later version of the license.
9 9 #
10 10 # This program is distributed in the hope that it will be useful,
11 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 # GNU General Public License for more details.
14 14 #
15 15 # You should have received a copy of the GNU General Public License
16 16 # along with this program; if not, write to the Free Software
17 17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 18 # MA 02110-1301, USA.
19 from beaker.cache import cache_region
20 19
21 20 """
22 21 Created on April 18, 2010
23 22 Utilities for hg app
24 23 @author: marcink
25 24 """
26
27 import os
28 import logging
25 from beaker.cache import cache_region
29 26 from mercurial import ui, config, hg
30 27 from mercurial.error import RepoError
28 from pylons_app.model import meta
31 29 from pylons_app.model.db import Repository, User, HgAppUi, HgAppSettings
32 from pylons_app.model import meta
30 from vcs.backends.base import BaseChangeset
31 from vcs.utils.lazy import LazyProperty
32 import logging
33 import os
33 34 log = logging.getLogger(__name__)
34 35
35 36
36 37 def get_repo_slug(request):
37 38 return request.environ['pylons.routes_dict'].get('repo_name')
38 39
39 40 def is_mercurial(environ):
40 41 """
41 42 Returns True if request's target is mercurial server - header
42 43 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
43 44 """
44 45 http_accept = environ.get('HTTP_ACCEPT')
45 46 if http_accept and http_accept.startswith('application/mercurial'):
46 47 return True
47 48 return False
48 49
49 50 def check_repo_dir(paths):
50 51 repos_path = paths[0][1].split('/')
51 52 if repos_path[-1] in ['*', '**']:
52 53 repos_path = repos_path[:-1]
53 54 if repos_path[0] != '/':
54 55 repos_path[0] = '/'
55 56 if not os.path.isdir(os.path.join(*repos_path)):
56 57 raise Exception('Not a valid repository in %s' % paths[0][1])
57 58
58 59 def check_repo_fast(repo_name, base_path):
59 60 if os.path.isdir(os.path.join(base_path, repo_name)):return False
60 61 return True
61 62
62 63 def check_repo(repo_name, base_path, verify=True):
63 64
64 65 repo_path = os.path.join(base_path, repo_name)
65 66
66 67 try:
67 68 if not check_repo_fast(repo_name, base_path):
68 69 return False
69 70 r = hg.repository(ui.ui(), repo_path)
70 71 if verify:
71 72 hg.verify(r)
72 73 #here we hnow that repo exists it was verified
73 74 log.info('%s repo is already created', repo_name)
74 75 return False
75 76 except RepoError:
76 77 #it means that there is no valid repo there...
77 78 log.info('%s repo is free for creation', repo_name)
78 79 return True
79 80
80
81 def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
82 while True:
83 ok = raw_input(prompt)
84 if ok in ('y', 'ye', 'yes'): return True
85 if ok in ('n', 'no', 'nop', 'nope'): return False
86 retries = retries - 1
87 if retries < 0: raise IOError
88 print complaint
89
81 90 @cache_region('super_short_term', 'cached_hg_ui')
82 91 def get_hg_ui_cached():
83 92 try:
84 93 sa = meta.Session
85 94 ret = sa.query(HgAppUi).all()
86 95 finally:
87 96 meta.Session.remove()
88 97 return ret
89 98
90 99
91 100 def get_hg_settings():
92 101 try:
93 102 sa = meta.Session
94 103 ret = sa.query(HgAppSettings).scalar()
95 104 finally:
96 105 meta.Session.remove()
97 106
98 107 if not ret:
99 108 raise Exception('Could not get application settings !')
100 109 return ret
101 110
102 111 def make_ui(read_from='file', path=None, checkpaths=True):
103 112 """
104 113 A function that will read python rc files or database
105 114 and make an mercurial ui object from read options
106 115
107 116 @param path: path to mercurial config file
108 117 @param checkpaths: check the path
109 118 @param read_from: read from 'file' or 'db'
110 119 """
111 120 #propagated from mercurial documentation
112 121 sections = ['alias', 'auth',
113 122 'decode/encode', 'defaults',
114 123 'diff', 'email',
115 124 'extensions', 'format',
116 125 'merge-patterns', 'merge-tools',
117 126 'hooks', 'http_proxy',
118 127 'smtp', 'patch',
119 128 'paths', 'profiling',
120 129 'server', 'trusted',
121 130 'ui', 'web', ]
122 131 baseui = ui.ui()
123 132
124 133
125 134 if read_from == 'file':
126 135 if not os.path.isfile(path):
127 136 log.warning('Unable to read config file %s' % path)
128 137 return False
129 138
130 139 cfg = config.config()
131 140 cfg.read(path)
132 141 for section in sections:
133 142 for k, v in cfg.items(section):
134 143 baseui.setconfig(section, k, v)
135 144 if checkpaths:check_repo_dir(cfg.items('paths'))
136 145
137 146
138 147 elif read_from == 'db':
139 148 hg_ui = get_hg_ui_cached()
140 149 for ui_ in hg_ui:
141 150 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
142 151
143 152
144 153 return baseui
145 154
146 155
147 156 def set_hg_app_config(config):
148 157 hgsettings = get_hg_settings()
149 158 config['hg_app_auth_realm'] = hgsettings.app_auth_realm
150 159 config['hg_app_name'] = hgsettings.app_title
151 160
152 161 def invalidate_cache(name, *args):
153 162 """Invalidates given name cache"""
154 163
155 164 from beaker.cache import region_invalidate
156 165 log.info('INVALIDATING CACHE FOR %s', name)
157 166
158 167 """propagate our arguments to make sure invalidation works. First
159 168 argument has to be the name of cached func name give to cache decorator
160 169 without that the invalidation would not work"""
161 170 tmp = [name]
162 171 tmp.extend(args)
163 172 args = tuple(tmp)
164 173
165 174 if name == 'cached_repo_list':
166 175 from pylons_app.model.hg_model import _get_repos_cached
167 176 region_invalidate(_get_repos_cached, None, *args)
168 177
169 178 if name == 'full_changelog':
170 179 from pylons_app.model.hg_model import _full_changelog_cached
171 180 region_invalidate(_full_changelog_cached, None, *args)
172 181
173 from vcs.backends.base import BaseChangeset
174 from vcs.utils.lazy import LazyProperty
175 182 class EmptyChangeset(BaseChangeset):
176 183
177 184 revision = -1
178 185 message = ''
179 186
180 187 @LazyProperty
181 188 def raw_id(self):
182 189 """
183 190 Returns raw string identifing this changeset, useful for web
184 191 representation.
185 192 """
186 193 return '0' * 12
187 194
188 195
189 196 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
190 197 """
191 198 maps all found repositories into db
192 199 """
193 200 from pylons_app.model.repo_model import RepoModel
194 201
195 202 sa = meta.Session
196 203 user = sa.query(User).filter(User.admin == True).first()
197 204
198 205 rm = RepoModel()
199 206
200 207 for name, repo in initial_repo_list.items():
201 208 if not sa.query(Repository).get(name):
202 209 log.info('repository %s not found creating default', name)
203 210
204 211 form_data = {
205 212 'repo_name':name,
206 213 'description':repo.description if repo.description != 'unknown' else \
207 214 'auto description for %s' % name,
208 215 'private':False
209 216 }
210 217 rm.create(form_data, user, just_db=True)
211 218
212 219
213 220 if remove_obsolete:
214 221 #remove from database those repositories that are not in the filesystem
215 222 for repo in sa.query(Repository).all():
216 223 if repo.repo_name not in initial_repo_list.keys():
217 224 sa.delete(repo)
218 225 sa.commit()
219 226
220 227
221 228 meta.Session.remove()
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now