##// END OF EJS Templates
enabled largefiles for stable release
marcink -
r1797:c60c54e7 default
parent child Browse files
Show More
@@ -1,505 +1,512 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.db_manage
4 4 ~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Database creation, and setup module for RhodeCode. Used for creation
7 7 of database as well as for migration operations
8 8
9 9 :created_on: Apr 10, 2010
10 10 :author: marcink
11 11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26
27 27 import os
28 28 import sys
29 29 import uuid
30 30 import logging
31 31 from os.path import dirname as dn, join as jn
32 32
33 33 from rhodecode import __dbversion__
34 34 from rhodecode.model import meta
35 35
36 36 from rhodecode.lib.auth import get_crypt_password, generate_api_key
37 37 from rhodecode.lib.utils import ask_ok
38 38 from rhodecode.model import init_model
39 39 from rhodecode.model.db import User, Permission, RhodeCodeUi, \
40 40 RhodeCodeSettings, UserToPerm, DbMigrateVersion
41 41
42 42 from sqlalchemy.engine import create_engine
43 43
44 44 log = logging.getLogger(__name__)
45 45
46 46
47 47 class DbManage(object):
48 48 def __init__(self, log_sql, dbconf, root, tests=False):
49 49 self.dbname = dbconf.split('/')[-1]
50 50 self.tests = tests
51 51 self.root = root
52 52 self.dburi = dbconf
53 53 self.log_sql = log_sql
54 54 self.db_exists = False
55 55 self.init_db()
56 56
57 57 def init_db(self):
58 58 engine = create_engine(self.dburi, echo=self.log_sql)
59 59 init_model(engine)
60 60 self.sa = meta.Session()
61 61
62 62 def create_tables(self, override=False):
63 63 """Create a auth database
64 64 """
65 65
66 66 log.info("Any existing database is going to be destroyed")
67 67 if self.tests:
68 68 destroy = True
69 69 else:
70 70 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
71 71 if not destroy:
72 72 sys.exit()
73 73 if destroy:
74 74 meta.Base.metadata.drop_all()
75 75
76 76 checkfirst = not override
77 77 meta.Base.metadata.create_all(checkfirst=checkfirst)
78 78 log.info('Created tables for %s', self.dbname)
79 79
80 80 def set_db_version(self):
81 81 try:
82 82 ver = DbMigrateVersion()
83 83 ver.version = __dbversion__
84 84 ver.repository_id = 'rhodecode_db_migrations'
85 85 ver.repository_path = 'versions'
86 86 self.sa.add(ver)
87 87 self.sa.commit()
88 88 except:
89 89 self.sa.rollback()
90 90 raise
91 91 log.info('db version set to: %s', __dbversion__)
92 92
93 93 def upgrade(self):
94 94 """Upgrades given database schema to given revision following
95 95 all needed steps, to perform the upgrade
96 96
97 97 """
98 98
99 99 from rhodecode.lib.dbmigrate.migrate.versioning import api
100 100 from rhodecode.lib.dbmigrate.migrate.exceptions import \
101 101 DatabaseNotControlledError
102 102
103 103 upgrade = ask_ok('You are about to perform database upgrade, make '
104 104 'sure You backed up your database before. '
105 105 'Continue ? [y/n]')
106 106 if not upgrade:
107 107 sys.exit('Nothing done')
108 108
109 109 repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))),
110 110 'rhodecode/lib/dbmigrate')
111 111 db_uri = self.dburi
112 112
113 113 try:
114 114 curr_version = api.db_version(db_uri, repository_path)
115 115 msg = ('Found current database under version'
116 116 ' control with version %s' % curr_version)
117 117
118 118 except (RuntimeError, DatabaseNotControlledError):
119 119 curr_version = 1
120 120 msg = ('Current database is not under version control. Setting'
121 121 ' as version %s' % curr_version)
122 122 api.version_control(db_uri, repository_path, curr_version)
123 123
124 124 print (msg)
125 125
126 126 if curr_version == __dbversion__:
127 127 sys.exit('This database is already at the newest version')
128 128
129 129 #======================================================================
130 130 # UPGRADE STEPS
131 131 #======================================================================
132 132 class UpgradeSteps(object):
133 133 """Those steps follow schema versions so for example schema
134 134 for example schema with seq 002 == step_2 and so on.
135 135 """
136 136
137 137 def __init__(self, klass):
138 138 self.klass = klass
139 139
140 140 def step_0(self):
141 141 #step 0 is the schema upgrade, and than follow proper upgrades
142 142 print ('attempting to do database upgrade to version %s' \
143 143 % __dbversion__)
144 144 api.upgrade(db_uri, repository_path, __dbversion__)
145 145 print ('Schema upgrade completed')
146 146
147 147 def step_1(self):
148 148 pass
149 149
150 150 def step_2(self):
151 151 print ('Patching repo paths for newer version of RhodeCode')
152 152 self.klass.fix_repo_paths()
153 153
154 154 print ('Patching default user of RhodeCode')
155 155 self.klass.fix_default_user()
156 156
157 157 log.info('Changing ui settings')
158 158 self.klass.create_ui_settings()
159 159
160 160 def step_3(self):
161 161 print ('Adding additional settings into RhodeCode db')
162 162 self.klass.fix_settings()
163 163 print ('Adding ldap defaults')
164 164 self.klass.create_ldap_options(skip_existing=True)
165 165
166 166 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
167 167
168 168 #CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
169 169 for step in upgrade_steps:
170 170 print ('performing upgrade step %s' % step)
171 171 callable = getattr(UpgradeSteps(self), 'step_%s' % step)()
172 172
173 173 def fix_repo_paths(self):
174 174 """Fixes a old rhodecode version path into new one without a '*'
175 175 """
176 176
177 177 paths = self.sa.query(RhodeCodeUi)\
178 178 .filter(RhodeCodeUi.ui_key == '/')\
179 179 .scalar()
180 180
181 181 paths.ui_value = paths.ui_value.replace('*', '')
182 182
183 183 try:
184 184 self.sa.add(paths)
185 185 self.sa.commit()
186 186 except:
187 187 self.sa.rollback()
188 188 raise
189 189
190 190 def fix_default_user(self):
191 191 """Fixes a old default user with some 'nicer' default values,
192 192 used mostly for anonymous access
193 193 """
194 194 def_user = self.sa.query(User)\
195 195 .filter(User.username == 'default')\
196 196 .one()
197 197
198 198 def_user.name = 'Anonymous'
199 199 def_user.lastname = 'User'
200 200 def_user.email = 'anonymous@rhodecode.org'
201 201
202 202 try:
203 203 self.sa.add(def_user)
204 204 self.sa.commit()
205 205 except:
206 206 self.sa.rollback()
207 207 raise
208 208
209 209 def fix_settings(self):
210 210 """Fixes rhodecode settings adds ga_code key for google analytics
211 211 """
212 212
213 213 hgsettings3 = RhodeCodeSettings('ga_code', '')
214 214
215 215 try:
216 216 self.sa.add(hgsettings3)
217 217 self.sa.commit()
218 218 except:
219 219 self.sa.rollback()
220 220 raise
221 221
222 222 def admin_prompt(self, second=False):
223 223 if not self.tests:
224 224 import getpass
225 225
226 226 def get_password():
227 227 password = getpass.getpass('Specify admin password '
228 228 '(min 6 chars):')
229 229 confirm = getpass.getpass('Confirm password:')
230 230
231 231 if password != confirm:
232 232 log.error('passwords mismatch')
233 233 return False
234 234 if len(password) < 6:
235 235 log.error('password is to short use at least 6 characters')
236 236 return False
237 237
238 238 return password
239 239
240 240 username = raw_input('Specify admin username:')
241 241
242 242 password = get_password()
243 243 if not password:
244 244 #second try
245 245 password = get_password()
246 246 if not password:
247 247 sys.exit()
248 248
249 249 email = raw_input('Specify admin email:')
250 250 self.create_user(username, password, email, True)
251 251 else:
252 252 log.info('creating admin and regular test users')
253 253 self.create_user('test_admin', 'test12',
254 254 'test_admin@mail.com', True)
255 255 self.create_user('test_regular', 'test12',
256 256 'test_regular@mail.com', False)
257 257 self.create_user('test_regular2', 'test12',
258 258 'test_regular2@mail.com', False)
259 259
260 260 def create_ui_settings(self):
261 261 """Creates ui settings, fills out hooks
262 262 and disables dotencode
263 263
264 264 """
265 265 #HOOKS
266 266 hooks1_key = RhodeCodeUi.HOOK_UPDATE
267 267 hooks1_ = self.sa.query(RhodeCodeUi)\
268 268 .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()
269 269
270 270 hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_
271 271 hooks1.ui_section = 'hooks'
272 272 hooks1.ui_key = hooks1_key
273 273 hooks1.ui_value = 'hg update >&2'
274 274 hooks1.ui_active = False
275 275
276 276 hooks2_key = RhodeCodeUi.HOOK_REPO_SIZE
277 277 hooks2_ = self.sa.query(RhodeCodeUi)\
278 278 .filter(RhodeCodeUi.ui_key == hooks2_key).scalar()
279 279
280 280 hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_
281 281 hooks2.ui_section = 'hooks'
282 282 hooks2.ui_key = hooks2_key
283 283 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
284 284
285 285 hooks3 = RhodeCodeUi()
286 286 hooks3.ui_section = 'hooks'
287 287 hooks3.ui_key = RhodeCodeUi.HOOK_PUSH
288 288 hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
289 289
290 290 hooks4 = RhodeCodeUi()
291 291 hooks4.ui_section = 'hooks'
292 292 hooks4.ui_key = RhodeCodeUi.HOOK_PULL
293 293 hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
294 294
295 295 #For mercurial 1.7 set backward comapatibility with format
296 296 dotencode_disable = RhodeCodeUi()
297 297 dotencode_disable.ui_section = 'format'
298 298 dotencode_disable.ui_key = 'dotencode'
299 299 dotencode_disable.ui_value = 'false'
300 300
301 # enable largefiles
302 largefiles = RhodeCodeUi()
303 largefiles.ui_section = 'extensions'
304 largefiles.ui_key = 'largefiles'
305 largefiles.ui_value = ''
306
301 307 try:
302 308 self.sa.add(hooks1)
303 309 self.sa.add(hooks2)
304 310 self.sa.add(hooks3)
305 311 self.sa.add(hooks4)
306 312 self.sa.add(dotencode_disable)
313 self.sa.add(largefiles)
307 314 self.sa.commit()
308 315 except:
309 316 self.sa.rollback()
310 317 raise
311 318
312 319 def create_ldap_options(self,skip_existing=False):
313 320 """Creates ldap settings"""
314 321
315 322 try:
316 323 for k, v in [('ldap_active', 'false'), ('ldap_host', ''),
317 324 ('ldap_port', '389'), ('ldap_tls_kind', 'PLAIN'),
318 325 ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''),
319 326 ('ldap_dn_pass', ''), ('ldap_base_dn', ''),
320 327 ('ldap_filter', ''), ('ldap_search_scope', ''),
321 328 ('ldap_attr_login', ''), ('ldap_attr_firstname', ''),
322 329 ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]:
323 330
324 331 if skip_existing and RhodeCodeSettings.get_by_name(k) != None:
325 332 log.debug('Skipping option %s' % k)
326 333 continue
327 334 setting = RhodeCodeSettings(k, v)
328 335 self.sa.add(setting)
329 336 self.sa.commit()
330 337 except:
331 338 self.sa.rollback()
332 339 raise
333 340
334 341 def config_prompt(self, test_repo_path='', retries=3):
335 342 if retries == 3:
336 343 log.info('Setting up repositories config')
337 344
338 345 if not self.tests and not test_repo_path:
339 346 path = raw_input('Specify valid full path to your repositories'
340 347 ' you can change this later in application settings:')
341 348 else:
342 349 path = test_repo_path
343 350 path_ok = True
344 351
345 352 #check proper dir
346 353 if not os.path.isdir(path):
347 354 path_ok = False
348 355 log.error('Given path %s is not a valid directory', path)
349 356
350 357 #check write access
351 358 if not os.access(path, os.W_OK) and path_ok:
352 359 path_ok = False
353 360 log.error('No write permission to given path %s', path)
354 361
355 362
356 363 if retries == 0:
357 364 sys.exit('max retries reached')
358 365 if path_ok is False:
359 366 retries -= 1
360 367 return self.config_prompt(test_repo_path, retries)
361 368
362 369 return path
363 370
364 371 def create_settings(self, path):
365 372
366 373 self.create_ui_settings()
367 374
368 375 #HG UI OPTIONS
369 376 web1 = RhodeCodeUi()
370 377 web1.ui_section = 'web'
371 378 web1.ui_key = 'push_ssl'
372 379 web1.ui_value = 'false'
373 380
374 381 web2 = RhodeCodeUi()
375 382 web2.ui_section = 'web'
376 383 web2.ui_key = 'allow_archive'
377 384 web2.ui_value = 'gz zip bz2'
378 385
379 386 web3 = RhodeCodeUi()
380 387 web3.ui_section = 'web'
381 388 web3.ui_key = 'allow_push'
382 389 web3.ui_value = '*'
383 390
384 391 web4 = RhodeCodeUi()
385 392 web4.ui_section = 'web'
386 393 web4.ui_key = 'baseurl'
387 394 web4.ui_value = '/'
388 395
389 396 paths = RhodeCodeUi()
390 397 paths.ui_section = 'paths'
391 398 paths.ui_key = '/'
392 399 paths.ui_value = path
393 400
394 401 hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication')
395 402 hgsettings2 = RhodeCodeSettings('title', 'RhodeCode')
396 403 hgsettings3 = RhodeCodeSettings('ga_code', '')
397 404
398 405 try:
399 406 self.sa.add(web1)
400 407 self.sa.add(web2)
401 408 self.sa.add(web3)
402 409 self.sa.add(web4)
403 410 self.sa.add(paths)
404 411 self.sa.add(hgsettings1)
405 412 self.sa.add(hgsettings2)
406 413 self.sa.add(hgsettings3)
407 414
408 415 self.sa.commit()
409 416 except:
410 417 self.sa.rollback()
411 418 raise
412 419
413 420 self.create_ldap_options()
414 421
415 422 log.info('created ui config')
416 423
417 424 def create_user(self, username, password, email='', admin=False):
418 425 log.info('creating administrator user %s', username)
419 426
420 427 form_data = dict(username=username,
421 428 password=password,
422 429 active=True,
423 430 admin=admin,
424 431 name='RhodeCode',
425 432 lastname='Admin',
426 433 email=email)
427 434 User.create(form_data)
428 435
429 436
430 437 def create_default_user(self):
431 438 log.info('creating default user')
432 439 #create default user for handling default permissions.
433 440
434 441 form_data = dict(username='default',
435 442 password=str(uuid.uuid1())[:8],
436 443 active=False,
437 444 admin=False,
438 445 name='Anonymous',
439 446 lastname='User',
440 447 email='anonymous@rhodecode.org')
441 448 User.create(form_data)
442 449
443 450 def create_permissions(self):
444 451 #module.(access|create|change|delete)_[name]
445 452 #module.(read|write|owner)
446 453 perms = [('repository.none', 'Repository no access'),
447 454 ('repository.read', 'Repository read access'),
448 455 ('repository.write', 'Repository write access'),
449 456 ('repository.admin', 'Repository admin access'),
450 457 ('hg.admin', 'Hg Administrator'),
451 458 ('hg.create.repository', 'Repository create'),
452 459 ('hg.create.none', 'Repository creation disabled'),
453 460 ('hg.register.none', 'Register disabled'),
454 461 ('hg.register.manual_activate', 'Register new user with '
455 462 'RhodeCode without manual'
456 463 'activation'),
457 464
458 465 ('hg.register.auto_activate', 'Register new user with '
459 466 'RhodeCode without auto '
460 467 'activation'),
461 468 ]
462 469
463 470 for p in perms:
464 471 new_perm = Permission()
465 472 new_perm.permission_name = p[0]
466 473 new_perm.permission_longname = p[1]
467 474 try:
468 475 self.sa.add(new_perm)
469 476 self.sa.commit()
470 477 except:
471 478 self.sa.rollback()
472 479 raise
473 480
474 481 def populate_default_permissions(self):
475 482 log.info('creating default user permissions')
476 483
477 484 default_user = self.sa.query(User)\
478 485 .filter(User.username == 'default').scalar()
479 486
480 487 reg_perm = UserToPerm()
481 488 reg_perm.user = default_user
482 489 reg_perm.permission = self.sa.query(Permission)\
483 490 .filter(Permission.permission_name == 'hg.register.manual_activate')\
484 491 .scalar()
485 492
486 493 create_repo_perm = UserToPerm()
487 494 create_repo_perm.user = default_user
488 495 create_repo_perm.permission = self.sa.query(Permission)\
489 496 .filter(Permission.permission_name == 'hg.create.repository')\
490 497 .scalar()
491 498
492 499 default_repo_perm = UserToPerm()
493 500 default_repo_perm.user = default_user
494 501 default_repo_perm.permission = self.sa.query(Permission)\
495 502 .filter(Permission.permission_name == 'repository.read')\
496 503 .scalar()
497 504
498 505 try:
499 506 self.sa.add(reg_perm)
500 507 self.sa.add(create_repo_perm)
501 508 self.sa.add(default_repo_perm)
502 509 self.sa.commit()
503 510 except:
504 511 self.sa.rollback()
505 512 raise
@@ -1,125 +1,126 b''
1 1 import sys
2 2 from rhodecode import get_version
3 3 from rhodecode import __platform__
4 4 from rhodecode import __license__
5 5 from rhodecode import PLATFORM_OTHERS
6 6
7 7 py_version = sys.version_info
8 8
9 9 if py_version < (2, 5):
10 10 raise Exception('RhodeCode requires python 2.5 or later')
11 11
12 12 requirements = [
13 13 "Pylons==1.0.0",
14 14 "Beaker==1.5.4",
15 15 "WebHelpers>=1.2",
16 16 "formencode==1.2.4",
17 17 "SQLAlchemy==0.7.3",
18 18 "Mako==0.5.0",
19 19 "pygments>=1.4",
20 "mercurial>=1.9.3,<2.0",
20 "mercurial>=2.0,<2.1",
21 21 "whoosh<1.8",
22 22 "celery>=2.2.5,<2.3",
23 23 "babel",
24 24 "python-dateutil>=1.5.0,<2.0.0",
25 25 "dulwich>=0.8.0,<0.9.0",
26 "vcs==0.2.2",
27 "webob==1.0.8"
26 "vcs==0.2.3",
27 "webob==1.0.8"
28 28 ]
29 29
30 30 dependency_links = [
31 31 ]
32 32
33 33 classifiers = ['Development Status :: 5 - Production/Stable',
34 34 'Environment :: Web Environment',
35 35 'Framework :: Pylons',
36 36 'Intended Audience :: Developers',
37 37 'License :: OSI Approved :: GNU General Public License (GPL)',
38 38 'Operating System :: OS Independent',
39 39 'Programming Language :: Python',
40 40 'Programming Language :: Python :: 2.5',
41 41 'Programming Language :: Python :: 2.6',
42 42 'Programming Language :: Python :: 2.7', ]
43 43
44 44 if py_version < (2, 6):
45 45 requirements.append("simplejson")
46 46 requirements.append("pysqlite")
47 47
48 48 if __platform__ in PLATFORM_OTHERS:
49 49 requirements.append("py-bcrypt")
50 50
51 51
52 #additional files from project that goes somewhere in the filesystem
53 #relative to sys.prefix
52 # additional files from project that goes somewhere in the filesystem
53 # relative to sys.prefix
54 54 data_files = []
55 55
56 #additional files that goes into package itself
56 # additional files that goes into package itself
57 57 package_data = {'rhodecode': ['i18n/*/LC_MESSAGES/*.mo', ], }
58 58
59 59 description = ('Mercurial repository browser/management with '
60 60 'build in push/pull server and full text search')
61 61 keywords = ' '.join(['rhodecode', 'rhodiumcode', 'mercurial', 'git',
62 'code review', 'repo groups', 'ldap'
62 63 'repository management', 'hgweb replacement'
63 64 'hgwebdir', 'gitweb replacement', 'serving hgweb', ])
64 #long description
65 # long description
65 66 try:
66 67 readme_file = 'README.rst'
67 68 changelog_file = 'docs/changelog.rst'
68 69 long_description = open(readme_file).read() + '\n\n' + \
69 70 open(changelog_file).read()
70 71
71 72 except IOError, err:
72 73 sys.stderr.write("[WARNING] Cannot find file specified as "
73 74 "long_description (%s)\n or changelog (%s) skipping that file" \
74 75 % (readme_file, changelog_file))
75 76 long_description = description
76 77
77 78
78 79 try:
79 80 from setuptools import setup, find_packages
80 81 except ImportError:
81 82 from ez_setup import use_setuptools
82 83 use_setuptools()
83 84 from setuptools import setup, find_packages
84 #packages
85 # packages
85 86 packages = find_packages(exclude=['ez_setup'])
86 87
87 88 setup(
88 89 name='RhodeCode',
89 90 version=get_version(),
90 91 description=description,
91 92 long_description=long_description,
92 93 keywords=keywords,
93 94 license=__license__,
94 95 author='Marcin Kuzminski',
95 96 author_email='marcin@python-works.com',
96 97 dependency_links=dependency_links,
97 98 url='http://rhodecode.org',
98 99 install_requires=requirements,
99 100 classifiers=classifiers,
100 101 setup_requires=["PasteScript>=1.6.3"],
101 102 data_files=data_files,
102 103 packages=packages,
103 104 include_package_data=True,
104 105 test_suite='nose.collector',
105 106 package_data=package_data,
106 107 message_extractors={'rhodecode': [
107 108 ('**.py', 'python', None),
108 109 ('templates/**.mako', 'mako', {'input_encoding': 'utf-8'}),
109 110 ('templates/**.html', 'mako', {'input_encoding': 'utf-8'}),
110 111 ('public/**', 'ignore', None)]},
111 112 zip_safe=False,
112 113 paster_plugins=['PasteScript', 'Pylons'],
113 114 entry_points="""
114 115 [paste.app_factory]
115 116 main = rhodecode.config.middleware:make_app
116 117
117 118 [paste.app_install]
118 119 main = pylons.util:PylonsInstaller
119 120
120 121 [paste.global_paster_command]
121 122 make-index = rhodecode.lib.indexers:MakeIndex
122 123 upgrade-db = rhodecode.lib.dbmigrate:UpgradeDb
123 124 celeryd=rhodecode.lib.celerypylons.commands:CeleryDaemonCommand
124 125 """,
125 126 )
General Comments 0
You need to be logged in to leave comments. Login now