##// END OF EJS Templates
updated hg-app db manage and global settings
marcink -
r345:bb8f45f6 default
parent child Browse files
Show More
@@ -1,188 +1,193 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 35 from pylons_app.model import init_model
36 from pylons_app.model.db import User, Permission, HgAppUi
36 from pylons_app.model.db import User, Permission, HgAppUi, HgAppSettings
37 37 from pylons_app.model.meta import Session, Base
38 38 from sqlalchemy.engine import create_engine
39 39 import logging
40 40
41 41 log = logging.getLogger('db manage')
42 42 log.setLevel(logging.DEBUG)
43 43 console_handler = logging.StreamHandler()
44 44 console_handler.setFormatter(logging.Formatter("%(asctime)s.%(msecs)03d"
45 45 " %(levelname)-5.5s [%(name)s] %(message)s"))
46 46 log.addHandler(console_handler)
47 47
48 48 class DbManage(object):
49 49 def __init__(self, log_sql):
50 50 self.dbname = 'hg_app.db'
51 51 dburi = 'sqlite:////%s' % jn(ROOT, self.dbname)
52 52 engine = create_engine(dburi, echo=log_sql)
53 53 init_model(engine)
54 54 self.sa = Session()
55 55 self.db_exists = False
56 56
57 57 def check_for_db(self, override):
58 58 log.info('checking for exisiting db')
59 59 if os.path.isfile(jn(ROOT, self.dbname)):
60 60 self.db_exists = True
61 61 log.info('database exisist')
62 62 if not override:
63 63 raise Exception('database already exists')
64 64
65 65 def create_tables(self, override=False):
66 66 """
67 67 Create a auth database
68 68 """
69 69 self.check_for_db(override)
70 70 if override:
71 71 log.info("database exisist and it's going to be destroyed")
72 72 if self.db_exists:
73 73 os.remove(jn(ROOT, self.dbname))
74 74 Base.metadata.create_all(checkfirst=override)
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 log.info('Seting up repositories.config')
84 log.info('Setting up repositories config')
85 85
86 86
87 87 path = raw_input('Specify valid full path to your repositories'
88 88 ' you can change this later application settings:')
89 89
90 90 if not os.path.isdir(path):
91 91 log.error('You entered wrong path')
92 92 sys.exit()
93 93
94 94 hooks = HgAppUi()
95 95 hooks.ui_section = 'hooks'
96 96 hooks.ui_key = 'changegroup'
97 97 hooks.ui_value = 'hg update >&2'
98 98
99 99 web1 = HgAppUi()
100 100 web1.ui_section = 'web'
101 101 web1.ui_key = 'push_ssl'
102 102 web1.ui_value = 'false'
103 103
104 104 web2 = HgAppUi()
105 105 web2.ui_section = 'web'
106 106 web2.ui_key = 'allow_archive'
107 107 web2.ui_value = 'gz zip bz2'
108 108
109 109 web3 = HgAppUi()
110 110 web3.ui_section = 'web'
111 111 web3.ui_key = 'allow_push'
112 112 web3.ui_value = '*'
113 113
114 114 web4 = HgAppUi()
115 115 web4.ui_section = 'web'
116 116 web4.ui_key = 'baseurl'
117 117 web4.ui_value = '/'
118 118
119 119 paths = HgAppUi()
120 120 paths.ui_section = 'paths'
121 121 paths.ui_key = '/'
122 122 paths.ui_value = os.path.join(path, '*')
123 123
124 124
125 hgsettings = HgAppSettings()
126 hgsettings.app_auth_realm = 'hg-app authentication'
127 hgsettings.app_title = 'hg-app'
128
125 129 try:
126 130 self.sa.add(hooks)
127 131 self.sa.add(web1)
128 132 self.sa.add(web2)
129 133 self.sa.add(web3)
130 134 self.sa.add(web4)
131 135 self.sa.add(paths)
136 self.sa.add(hgsettings)
132 137 self.sa.commit()
133 138 except:
134 139 self.sa.rollback()
135 140 raise
136 141 log.info('created ui config')
137 142
138 143 def create_user(self, username, password, admin=False):
139 144
140 145 log.info('creating default user')
141 146 #create default user for handling default permissions.
142 147 def_user = User()
143 148 def_user.username = 'default'
144 149 def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
145 150 def_user.name = 'default'
146 151 def_user.lastname = 'default'
147 152 def_user.email = 'default@default.com'
148 153 def_user.admin = False
149 154 def_user.active = False
150 155
151 156 log.info('creating administrator user %s', username)
152 157 new_user = User()
153 158 new_user.username = username
154 159 new_user.password = get_crypt_password(password)
155 160 new_user.name = 'Hg'
156 161 new_user.lastname = 'Admin'
157 162 new_user.email = 'admin@localhost'
158 163 new_user.admin = admin
159 164 new_user.active = True
160 165
161 166 try:
162 167 self.sa.add(def_user)
163 168 self.sa.add(new_user)
164 169 self.sa.commit()
165 170 except:
166 171 self.sa.rollback()
167 172 raise
168 173
169 174 def create_permissions(self):
170 175 #module.(access|create|change|delete)_[name]
171 176 #module.(read|write|owner)
172 177 perms = [('repository.none', 'Repository no access'),
173 178 ('repository.read', 'Repository read access'),
174 179 ('repository.write', 'Repository write access'),
175 180 ('repository.admin', 'Repository admin access'),
176 181 ('hg.admin', 'Hg Administrator'),
177 182 ]
178 183
179 184 for p in perms:
180 185 new_perm = Permission()
181 186 new_perm.permission_name = p[0]
182 187 new_perm.permission_longname = p[1]
183 188 try:
184 189 self.sa.add(new_perm)
185 190 self.sa.commit()
186 191 except:
187 192 self.sa.rollback()
188 193 raise
@@ -1,194 +1,202 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 19 from beaker.cache import cache_region
20 20
21 21 """
22 22 Created on April 18, 2010
23 23 Utilities for hg app
24 24 @author: marcink
25 25 """
26 26
27 27 import os
28 28 import logging
29 29 from mercurial import ui, config, hg
30 30 from mercurial.error import RepoError
31 from pylons_app.model.db import Repository, User, HgAppUi
31 from pylons_app.model.db import Repository, User, HgAppUi, HgAppSettings
32 from pylons_app.model.meta import Session
32 33 log = logging.getLogger(__name__)
33 34
34 35
35 36 def get_repo_slug(request):
36 37 return request.environ['pylons.routes_dict'].get('repo_name')
37 38
38 39 def is_mercurial(environ):
39 40 """
40 41 Returns True if request's target is mercurial server - header
41 42 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
42 43 """
43 44 http_accept = environ.get('HTTP_ACCEPT')
44 45 if http_accept and http_accept.startswith('application/mercurial'):
45 46 return True
46 47 return False
47 48
48 49 def check_repo_dir(paths):
49 50 repos_path = paths[0][1].split('/')
50 51 if repos_path[-1] in ['*', '**']:
51 52 repos_path = repos_path[:-1]
52 53 if repos_path[0] != '/':
53 54 repos_path[0] = '/'
54 55 if not os.path.isdir(os.path.join(*repos_path)):
55 56 raise Exception('Not a valid repository in %s' % paths[0][1])
56 57
57 58 def check_repo_fast(repo_name, base_path):
58 59 if os.path.isdir(os.path.join(base_path, repo_name)):return False
59 60 return True
60 61
61 62 def check_repo(repo_name, base_path, verify=True):
62 63
63 64 repo_path = os.path.join(base_path, repo_name)
64 65
65 66 try:
66 67 if not check_repo_fast(repo_name, base_path):
67 68 return False
68 69 r = hg.repository(ui.ui(), repo_path)
69 70 if verify:
70 71 hg.verify(r)
71 72 #here we hnow that repo exists it was verified
72 73 log.info('%s repo is already created', repo_name)
73 74 return False
74 75 except RepoError:
75 76 #it means that there is no valid repo there...
76 77 log.info('%s repo is free for creation', repo_name)
77 78 return True
78 79
79 80
80 81 @cache_region('super_short_term', 'cached_hg_ui')
81 82 def get_hg_ui_cached():
82 from pylons_app.model.meta import Session
83 83 sa = Session()
84 84 return sa.query(HgAppUi).all()
85 85
86 def get_hg_settings():
87 sa = Session()
88 ret = sa.query(HgAppSettings).scalar()
89 if not ret:
90 raise Exception('Could not get application settings !')
91 return ret
92
86 93 def make_ui(read_from='file', path=None, checkpaths=True):
87 94 """
88 95 A function that will read python rc files or database
89 96 and make an mercurial ui object from read options
90 97
91 98 @param path: path to mercurial config file
92 99 @param checkpaths: check the path
93 100 @param read_from: read from 'file' or 'db'
94 101 """
95 102 #propagated from mercurial documentation
96 103 sections = ['alias', 'auth',
97 104 'decode/encode', 'defaults',
98 105 'diff', 'email',
99 106 'extensions', 'format',
100 107 'merge-patterns', 'merge-tools',
101 108 'hooks', 'http_proxy',
102 109 'smtp', 'patch',
103 110 'paths', 'profiling',
104 111 'server', 'trusted',
105 112 'ui', 'web', ]
106 113 baseui = ui.ui()
107 114
108 115
109 116 if read_from == 'file':
110 117 if not os.path.isfile(path):
111 118 log.warning('Unable to read config file %s' % path)
112 119 return False
113 120
114 121 cfg = config.config()
115 122 cfg.read(path)
116 123 for section in sections:
117 124 for k, v in cfg.items(section):
118 125 baseui.setconfig(section, k, v)
119 126 if checkpaths:check_repo_dir(cfg.items('paths'))
120 127
121 128
122 129 elif read_from == 'db':
123 130 hg_ui = get_hg_ui_cached()
124 131 for ui_ in hg_ui:
125 132 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
126 133
127 134
128 135 return baseui
129 136
130 137
131 138 def set_hg_app_config(config):
132 config['hg_app_auth_realm'] = 'realm'
133 config['hg_app_name'] = 'app name'
139 hgsettings = get_hg_settings()
140 config['hg_app_auth_realm'] = hgsettings.app_auth_realm
141 config['hg_app_name'] = hgsettings.app_title
134 142
135 143 def invalidate_cache(name, *args):
136 144 """Invalidates given name cache"""
137 145
138 146 from beaker.cache import region_invalidate
139 147 log.info('INVALIDATING CACHE FOR %s', name)
140 148
141 149 """propagate our arguments to make sure invalidation works. First
142 150 argument has to be the name of cached func name give to cache decorator
143 151 without that the invalidation would not work"""
144 152 tmp = [name]
145 153 tmp.extend(args)
146 154 args = tuple(tmp)
147 155
148 156 if name == 'cached_repo_list':
149 157 from pylons_app.model.hg_model import _get_repos_cached
150 158 region_invalidate(_get_repos_cached, None, *args)
151 159
152 160 if name == 'full_changelog':
153 161 from pylons_app.model.hg_model import _full_changelog_cached
154 162 region_invalidate(_full_changelog_cached, None, *args)
155 163
156 164 from vcs.backends.base import BaseChangeset
157 165 from vcs.utils.lazy import LazyProperty
158 166 class EmptyChangeset(BaseChangeset):
159 167
160 168 revision = -1
161 169 message = ''
162 170
163 171 @LazyProperty
164 172 def raw_id(self):
165 173 """
166 174 Returns raw string identifing this changeset, useful for web
167 175 representation.
168 176 """
169 177 return '0' * 12
170 178
171 179
172 180 def repo2db_mapper(initial_repo_list):
173 181 """
174 182 maps all found repositories into db
175 183 """
176 184 from pylons_app.model.meta import Session
177 185 from pylons_app.model.repo_model import RepoModel
178 186
179 187 sa = Session()
180 188 user = sa.query(User).filter(User.admin == True).first()
181 189
182 190 rm = RepoModel()
183 191
184 192 for name, repo in initial_repo_list.items():
185 193 if not sa.query(Repository).get(name):
186 194 log.info('repository %s not found creating default', name)
187 195
188 196 form_data = {
189 197 'repo_name':name,
190 198 'description':repo.description if repo.description != 'unknown' else \
191 199 'auto description for %s' % name,
192 200 'private':False
193 201 }
194 202 rm.create(form_data, user, just_db=True)
General Comments 0
You need to be logged in to leave comments. Login now