##// END OF EJS Templates
disabled dotencode format for mercurial 1.7 usage and hg <=1.6 compatibility...
marcink -
r773:87677698 beta
parent child Browse files
Show More
@@ -1,303 +1,309
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # database management for RhodeCode
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 management and creation for RhodeCode
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
32 32 from rhodecode.lib.auth import get_crypt_password
33 33 from rhodecode.lib.utils import ask_ok
34 34 from rhodecode.model import init_model
35 35 from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \
36 36 UserToPerm
37 37 from rhodecode.model import meta
38 38 from sqlalchemy.engine import create_engine
39 39 import logging
40 40
41 41 log = logging.getLogger(__name__)
42 42
43 43 class DbManage(object):
44 44 def __init__(self, log_sql, dbname, root, tests=False):
45 45 self.dbname = dbname
46 46 self.tests = tests
47 47 self.root = root
48 48 dburi = 'sqlite:////%s' % jn(self.root, self.dbname)
49 49 engine = create_engine(dburi, echo=log_sql)
50 50 init_model(engine)
51 51 self.sa = meta.Session()
52 52 self.db_exists = False
53 53
54 54 def check_for_db(self, override):
55 55 db_path = jn(self.root, self.dbname)
56 56 log.info('checking for existing db in %s', db_path)
57 57 if os.path.isfile(db_path):
58 58 self.db_exists = True
59 59 if not override:
60 60 raise Exception('database already exists')
61 61
62 62 def create_tables(self, override=False):
63 63 """
64 64 Create a auth database
65 65 """
66 66 self.check_for_db(override)
67 67 if self.db_exists:
68 68 log.info("database exist and it's going to be destroyed")
69 69 if self.tests:
70 70 destroy = True
71 71 else:
72 72 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
73 73 if not destroy:
74 74 sys.exit()
75 75 if self.db_exists and destroy:
76 76 os.remove(jn(self.root, self.dbname))
77 77 checkfirst = not override
78 78 meta.Base.metadata.create_all(checkfirst=checkfirst)
79 79 log.info('Created tables for %s', self.dbname)
80 80
81 81 def admin_prompt(self, second=False):
82 82 if not self.tests:
83 83 import getpass
84 84
85 85
86 86 def get_password():
87 87 password = getpass.getpass('Specify admin password (min 6 chars):')
88 88 confirm = getpass.getpass('Confirm password:')
89 89
90 90 if password != confirm:
91 91 log.error('passwords mismatch')
92 92 return False
93 93 if len(password) < 6:
94 94 log.error('password is to short use at least 6 characters')
95 95 return False
96 96
97 97 return password
98 98
99 99 username = raw_input('Specify admin username:')
100 100
101 101 password = get_password()
102 102 if not password:
103 103 #second try
104 104 password = get_password()
105 105 if not password:
106 106 sys.exit()
107 107
108 108 email = raw_input('Specify admin email:')
109 109 self.create_user(username, password, email, True)
110 110 else:
111 111 log.info('creating admin and regular test users')
112 112 self.create_user('test_admin', 'test12', 'test_admin@mail.com', True)
113 113 self.create_user('test_regular', 'test12', 'test_regular@mail.com', False)
114 114 self.create_user('test_regular2', 'test12', 'test_regular2@mail.com', False)
115 115
116 116
117 117
118 118 def config_prompt(self, test_repo_path=''):
119 119 log.info('Setting up repositories config')
120 120
121 121 if not self.tests and not test_repo_path:
122 122 path = raw_input('Specify valid full path to your repositories'
123 123 ' you can change this later in application settings:')
124 124 else:
125 125 path = test_repo_path
126 126
127 127 if not os.path.isdir(path):
128 128 log.error('You entered wrong path: %s', path)
129 129 sys.exit()
130 130
131 131 hooks1 = RhodeCodeUi()
132 132 hooks1.ui_section = 'hooks'
133 133 hooks1.ui_key = 'changegroup.update'
134 134 hooks1.ui_value = 'hg update >&2'
135 135 hooks1.ui_active = False
136 136
137 137 hooks2 = RhodeCodeUi()
138 138 hooks2.ui_section = 'hooks'
139 139 hooks2.ui_key = 'changegroup.repo_size'
140 140 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
141 141
142 142 hooks3 = RhodeCodeUi()
143 143 hooks3.ui_section = 'hooks'
144 144 hooks3.ui_key = 'pretxnchangegroup.push_logger'
145 145 hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
146 146
147 147 hooks4 = RhodeCodeUi()
148 148 hooks4.ui_section = 'hooks'
149 149 hooks4.ui_key = 'preoutgoing.pull_logger'
150 150 hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
151 151
152 #for mercurial 1.7 set backward comapatibility with format
153
154 dotencode_disable = RhodeCodeUi()
155 dotencode_disable.ui_section = 'format'
156 dotencode_disable.ui_key = 'dotencode'
157 dotencode_disable.ui_section = 'false'
158
152 159
153 160 web1 = RhodeCodeUi()
154 161 web1.ui_section = 'web'
155 162 web1.ui_key = 'push_ssl'
156 163 web1.ui_value = 'false'
157 164
158 165 web2 = RhodeCodeUi()
159 166 web2.ui_section = 'web'
160 167 web2.ui_key = 'allow_archive'
161 168 web2.ui_value = 'gz zip bz2'
162 169
163 170 web3 = RhodeCodeUi()
164 171 web3.ui_section = 'web'
165 172 web3.ui_key = 'allow_push'
166 173 web3.ui_value = '*'
167 174
168 175 web4 = RhodeCodeUi()
169 176 web4.ui_section = 'web'
170 177 web4.ui_key = 'baseurl'
171 178 web4.ui_value = '/'
172 179
173 180 paths = RhodeCodeUi()
174 181 paths.ui_section = 'paths'
175 182 paths.ui_key = '/'
176 183 paths.ui_value = path
177 184
178 185
179 186 hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication')
180 187 hgsettings2 = RhodeCodeSettings('title', 'RhodeCode')
181 188
182 189
183 190 try:
184
185
186 191 self.sa.add(hooks1)
187 192 self.sa.add(hooks2)
188 193 self.sa.add(hooks3)
189 194 self.sa.add(hooks4)
190 195 self.sa.add(web1)
191 196 self.sa.add(web2)
192 197 self.sa.add(web3)
193 198 self.sa.add(web4)
194 199 self.sa.add(paths)
195 200 self.sa.add(hgsettings1)
196 201 self.sa.add(hgsettings2)
202 self.sa.add(dotencode_disable)
197 203 for k in ['ldap_active', 'ldap_host', 'ldap_port', 'ldap_ldaps',
198 204 'ldap_dn_user', 'ldap_dn_pass', 'ldap_base_dn']:
199 205
200 206 setting = RhodeCodeSettings(k, '')
201 207 self.sa.add(setting)
202 208
203 209 self.sa.commit()
204 210 except:
205 211 self.sa.rollback()
206 212 raise
207 213 log.info('created ui config')
208 214
209 215 def create_user(self, username, password, email='', admin=False):
210 216 log.info('creating administrator user %s', username)
211 217 new_user = User()
212 218 new_user.username = username
213 219 new_user.password = get_crypt_password(password)
214 220 new_user.name = 'RhodeCode'
215 221 new_user.lastname = 'Admin'
216 222 new_user.email = email
217 223 new_user.admin = admin
218 224 new_user.active = True
219 225
220 226 try:
221 227 self.sa.add(new_user)
222 228 self.sa.commit()
223 229 except:
224 230 self.sa.rollback()
225 231 raise
226 232
227 233 def create_default_user(self):
228 234 log.info('creating default user')
229 235 #create default user for handling default permissions.
230 236 def_user = User()
231 237 def_user.username = 'default'
232 238 def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
233 239 def_user.name = 'Anonymous'
234 240 def_user.lastname = 'User'
235 241 def_user.email = 'anonymous@rhodecode.org'
236 242 def_user.admin = False
237 243 def_user.active = False
238 244 try:
239 245 self.sa.add(def_user)
240 246 self.sa.commit()
241 247 except:
242 248 self.sa.rollback()
243 249 raise
244 250
245 251 def create_permissions(self):
246 252 #module.(access|create|change|delete)_[name]
247 253 #module.(read|write|owner)
248 254 perms = [('repository.none', 'Repository no access'),
249 255 ('repository.read', 'Repository read access'),
250 256 ('repository.write', 'Repository write access'),
251 257 ('repository.admin', 'Repository admin access'),
252 258 ('hg.admin', 'Hg Administrator'),
253 259 ('hg.create.repository', 'Repository create'),
254 260 ('hg.create.none', 'Repository creation disabled'),
255 261 ('hg.register.none', 'Register disabled'),
256 262 ('hg.register.manual_activate', 'Register new user with rhodecode without manual activation'),
257 263 ('hg.register.auto_activate', 'Register new user with rhodecode without auto activation'),
258 264 ]
259 265
260 266 for p in perms:
261 267 new_perm = Permission()
262 268 new_perm.permission_name = p[0]
263 269 new_perm.permission_longname = p[1]
264 270 try:
265 271 self.sa.add(new_perm)
266 272 self.sa.commit()
267 273 except:
268 274 self.sa.rollback()
269 275 raise
270 276
271 277 def populate_default_permissions(self):
272 278 log.info('creating default user permissions')
273 279
274 280 default_user = self.sa.query(User)\
275 281 .filter(User.username == 'default').scalar()
276 282
277 283 reg_perm = UserToPerm()
278 284 reg_perm.user = default_user
279 285 reg_perm.permission = self.sa.query(Permission)\
280 286 .filter(Permission.permission_name == 'hg.register.manual_activate')\
281 287 .scalar()
282 288
283 289 create_repo_perm = UserToPerm()
284 290 create_repo_perm.user = default_user
285 291 create_repo_perm.permission = self.sa.query(Permission)\
286 292 .filter(Permission.permission_name == 'hg.create.repository')\
287 293 .scalar()
288 294
289 295 default_repo_perm = UserToPerm()
290 296 default_repo_perm.user = default_user
291 297 default_repo_perm.permission = self.sa.query(Permission)\
292 298 .filter(Permission.permission_name == 'repository.read')\
293 299 .scalar()
294 300
295 301 try:
296 302 self.sa.add(reg_perm)
297 303 self.sa.add(create_repo_perm)
298 304 self.sa.add(default_repo_perm)
299 305 self.sa.commit()
300 306 except:
301 307 self.sa.rollback()
302 308 raise
303 309
@@ -1,515 +1,518
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # Utilities for RhodeCode
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 """
20 20 Created on April 18, 2010
21 21 Utilities for RhodeCode
22 22 @author: marcink
23 23 """
24 24
25 25 from UserDict import DictMixin
26 26 from mercurial import ui, config, hg
27 27 from mercurial.error import RepoError
28 28 from rhodecode.model import meta
29 29 from rhodecode.model.caching_query import FromCache
30 30 from rhodecode.model.db import Repository, User, RhodeCodeUi, UserLog
31 31 from rhodecode.model.repo import RepoModel
32 32 from rhodecode.model.user import UserModel
33 33
34 34 from vcs.backends.base import BaseChangeset
35 35 from paste.script import command
36 36 import ConfigParser
37 37 from vcs.utils.lazy import LazyProperty
38 38 import traceback
39 39 import datetime
40 40 import logging
41 41 import os
42 42
43 43 log = logging.getLogger(__name__)
44 44
45 45
46 46 def get_repo_slug(request):
47 47 return request.environ['pylons.routes_dict'].get('repo_name')
48 48
49 49 def action_logger(user, action, repo, ipaddr='', sa=None):
50 50 """
51 51 Action logger for various actions made by users
52 52
53 53 :param user: user that made this action, can be a unique username string or
54 54 object containing user_id attribute
55 55 :param action: action to log, should be on of predefined unique actions for
56 56 easy translations
57 57 :param repo: string name of repository or object containing repo_id,
58 58 that action was made on
59 59 :param ipaddr: optional ip address from what the action was made
60 60 :param sa: optional sqlalchemy session
61 61
62 62 """
63 63
64 64 if not sa:
65 65 sa = meta.Session()
66 66
67 67 try:
68 68 um = UserModel()
69 69 if hasattr(user, 'user_id'):
70 70 user_obj = user
71 71 elif isinstance(user, basestring):
72 72 user_obj = um.get_by_username(user, cache=False)
73 73 else:
74 74 raise Exception('You have to provide user object or username')
75 75
76 76
77 77 rm = RepoModel()
78 78 if hasattr(repo, 'repo_id'):
79 79 repo_obj = rm.get(repo.repo_id, cache=False)
80 80 repo_name = repo_obj.repo_name
81 81 elif isinstance(repo, basestring):
82 82 repo_name = repo.lstrip('/')
83 83 repo_obj = rm.get_by_repo_name(repo_name, cache=False)
84 84 else:
85 85 raise Exception('You have to provide repository to action logger')
86 86
87 87
88 88 user_log = UserLog()
89 89 user_log.user_id = user_obj.user_id
90 90 user_log.action = action
91 91
92 92 user_log.repository_id = repo_obj.repo_id
93 93 user_log.repository_name = repo_name
94 94
95 95 user_log.action_date = datetime.datetime.now()
96 96 user_log.user_ip = ipaddr
97 97 sa.add(user_log)
98 98 sa.commit()
99 99
100 100 log.info('Adding user %s, action %s on %s', user_obj, action, repo)
101 101 except:
102 102 log.error(traceback.format_exc())
103 103 sa.rollback()
104 104
105 105 def get_repos(path, recursive=False, initial=False):
106 106 """
107 107 Scans given path for repos and return (name,(type,path)) tuple
108 108 :param prefix:
109 109 :param path:
110 110 :param recursive:
111 111 :param initial:
112 112 """
113 113 from vcs.utils.helpers import get_scm
114 114 from vcs.exceptions import VCSError
115 115
116 116 try:
117 117 scm = get_scm(path)
118 118 except:
119 119 pass
120 120 else:
121 121 raise Exception('The given path %s should not be a repository got %s',
122 122 path, scm)
123 123
124 124 for dirpath in os.listdir(path):
125 125 try:
126 126 yield dirpath, get_scm(os.path.join(path, dirpath))
127 127 except VCSError:
128 128 pass
129 129
130 130 def check_repo_fast(repo_name, base_path):
131 131 """
132 132 Check given path for existance of directory
133 133 :param repo_name:
134 134 :param base_path:
135 135
136 136 :return False: if this directory is present
137 137 """
138 138 if os.path.isdir(os.path.join(base_path, repo_name)):return False
139 139 return True
140 140
141 141 def check_repo(repo_name, base_path, verify=True):
142 142
143 143 repo_path = os.path.join(base_path, repo_name)
144 144
145 145 try:
146 146 if not check_repo_fast(repo_name, base_path):
147 147 return False
148 148 r = hg.repository(ui.ui(), repo_path)
149 149 if verify:
150 150 hg.verify(r)
151 151 #here we hnow that repo exists it was verified
152 152 log.info('%s repo is already created', repo_name)
153 153 return False
154 154 except RepoError:
155 155 #it means that there is no valid repo there...
156 156 log.info('%s repo is free for creation', repo_name)
157 157 return True
158 158
159 159 def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
160 160 while True:
161 161 ok = raw_input(prompt)
162 162 if ok in ('y', 'ye', 'yes'): return True
163 163 if ok in ('n', 'no', 'nop', 'nope'): return False
164 164 retries = retries - 1
165 165 if retries < 0: raise IOError
166 166 print complaint
167 167
168 168 #propagated from mercurial documentation
169 169 ui_sections = ['alias', 'auth',
170 170 'decode/encode', 'defaults',
171 171 'diff', 'email',
172 172 'extensions', 'format',
173 173 'merge-patterns', 'merge-tools',
174 174 'hooks', 'http_proxy',
175 175 'smtp', 'patch',
176 176 'paths', 'profiling',
177 177 'server', 'trusted',
178 178 'ui', 'web', ]
179 179
180 180 def make_ui(read_from='file', path=None, checkpaths=True):
181 181 """
182 182 A function that will read python rc files or database
183 183 and make an mercurial ui object from read options
184 184
185 185 :param path: path to mercurial config file
186 186 :param checkpaths: check the path
187 187 :param read_from: read from 'file' or 'db'
188 188 """
189 189
190 190 baseui = ui.ui()
191 191
192 192 #clean the baseui object
193 193 baseui._ocfg = config.config()
194 194 baseui._ucfg = config.config()
195 195 baseui._tcfg = config.config()
196 196
197 197 if read_from == 'file':
198 198 if not os.path.isfile(path):
199 199 log.warning('Unable to read config file %s' % path)
200 200 return False
201 201 log.debug('reading hgrc from %s', path)
202 202 cfg = config.config()
203 203 cfg.read(path)
204 204 for section in ui_sections:
205 205 for k, v in cfg.items(section):
206 206 log.debug('settings ui from file[%s]%s:%s', section, k, v)
207 207 baseui.setconfig(section, k, v)
208 208
209 209
210 210 elif read_from == 'db':
211 211 sa = meta.Session()
212 212 ret = sa.query(RhodeCodeUi)\
213 213 .options(FromCache("sql_cache_short",
214 214 "get_hg_ui_settings")).all()
215 meta.Session.remove()
215
216 216 hg_ui = ret
217 217 for ui_ in hg_ui:
218 218 if ui_.ui_active:
219 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section, ui_.ui_key, ui_.ui_value)
219 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
220 ui_.ui_key, ui_.ui_value)
220 221 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
222
223 meta.Session.remove()
221 224 return baseui
222 225
223 226
224 227 def set_rhodecode_config(config):
225 228 """
226 229 Updates pylons config with new settings from database
227 230 :param config:
228 231 """
229 232 from rhodecode.model.settings import SettingsModel
230 233 hgsettings = SettingsModel().get_app_settings()
231 234
232 235 for k, v in hgsettings.items():
233 236 config[k] = v
234 237
235 238 def invalidate_cache(cache_key, *args):
236 239 """
237 240 Puts cache invalidation task into db for
238 241 further global cache invalidation
239 242 """
240 243 from rhodecode.model.scm import ScmModel
241 244
242 245 if cache_key.startswith('get_repo_cached_'):
243 246 name = cache_key.split('get_repo_cached_')[-1]
244 247 ScmModel().mark_for_invalidation(name)
245 248
246 249 class EmptyChangeset(BaseChangeset):
247 250 """
248 251 An dummy empty changeset. It's possible to pass hash when creating
249 252 an EmptyChangeset
250 253 """
251 254
252 255 def __init__(self, cs='0' * 40):
253 256 self._empty_cs = cs
254 257 self.revision = -1
255 258 self.message = ''
256 259 self.author = ''
257 260 self.date = ''
258 261
259 262 @LazyProperty
260 263 def raw_id(self):
261 264 """
262 265 Returns raw string identifying this changeset, useful for web
263 266 representation.
264 267 """
265 268 return self._empty_cs
266 269
267 270 @LazyProperty
268 271 def short_id(self):
269 272 return self.raw_id[:12]
270 273
271 274 def get_file_changeset(self, path):
272 275 return self
273 276
274 277 def get_file_content(self, path):
275 278 return u''
276 279
277 280 def get_file_size(self, path):
278 281 return 0
279 282
280 283 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
281 284 """
282 285 maps all found repositories into db
283 286 """
284 287
285 288 sa = meta.Session()
286 289 rm = RepoModel()
287 290 user = sa.query(User).filter(User.admin == True).first()
288 291
289 292 for name, repo in initial_repo_list.items():
290 293 if not rm.get_by_repo_name(name, cache=False):
291 294 log.info('repository %s not found creating default', name)
292 295
293 296 form_data = {
294 297 'repo_name':name,
295 298 'repo_type':repo.alias,
296 299 'description':repo.description \
297 300 if repo.description != 'unknown' else \
298 301 '%s repository' % name,
299 302 'private':False
300 303 }
301 304 rm.create(form_data, user, just_db=True)
302 305
303 306 if remove_obsolete:
304 307 #remove from database those repositories that are not in the filesystem
305 308 for repo in sa.query(Repository).all():
306 309 if repo.repo_name not in initial_repo_list.keys():
307 310 sa.delete(repo)
308 311 sa.commit()
309 312
310 313 class OrderedDict(dict, DictMixin):
311 314
312 315 def __init__(self, *args, **kwds):
313 316 if len(args) > 1:
314 317 raise TypeError('expected at most 1 arguments, got %d' % len(args))
315 318 try:
316 319 self.__end
317 320 except AttributeError:
318 321 self.clear()
319 322 self.update(*args, **kwds)
320 323
321 324 def clear(self):
322 325 self.__end = end = []
323 326 end += [None, end, end] # sentinel node for doubly linked list
324 327 self.__map = {} # key --> [key, prev, next]
325 328 dict.clear(self)
326 329
327 330 def __setitem__(self, key, value):
328 331 if key not in self:
329 332 end = self.__end
330 333 curr = end[1]
331 334 curr[2] = end[1] = self.__map[key] = [key, curr, end]
332 335 dict.__setitem__(self, key, value)
333 336
334 337 def __delitem__(self, key):
335 338 dict.__delitem__(self, key)
336 339 key, prev, next = self.__map.pop(key)
337 340 prev[2] = next
338 341 next[1] = prev
339 342
340 343 def __iter__(self):
341 344 end = self.__end
342 345 curr = end[2]
343 346 while curr is not end:
344 347 yield curr[0]
345 348 curr = curr[2]
346 349
347 350 def __reversed__(self):
348 351 end = self.__end
349 352 curr = end[1]
350 353 while curr is not end:
351 354 yield curr[0]
352 355 curr = curr[1]
353 356
354 357 def popitem(self, last=True):
355 358 if not self:
356 359 raise KeyError('dictionary is empty')
357 360 if last:
358 361 key = reversed(self).next()
359 362 else:
360 363 key = iter(self).next()
361 364 value = self.pop(key)
362 365 return key, value
363 366
364 367 def __reduce__(self):
365 368 items = [[k, self[k]] for k in self]
366 369 tmp = self.__map, self.__end
367 370 del self.__map, self.__end
368 371 inst_dict = vars(self).copy()
369 372 self.__map, self.__end = tmp
370 373 if inst_dict:
371 374 return (self.__class__, (items,), inst_dict)
372 375 return self.__class__, (items,)
373 376
374 377 def keys(self):
375 378 return list(self)
376 379
377 380 setdefault = DictMixin.setdefault
378 381 update = DictMixin.update
379 382 pop = DictMixin.pop
380 383 values = DictMixin.values
381 384 items = DictMixin.items
382 385 iterkeys = DictMixin.iterkeys
383 386 itervalues = DictMixin.itervalues
384 387 iteritems = DictMixin.iteritems
385 388
386 389 def __repr__(self):
387 390 if not self:
388 391 return '%s()' % (self.__class__.__name__,)
389 392 return '%s(%r)' % (self.__class__.__name__, self.items())
390 393
391 394 def copy(self):
392 395 return self.__class__(self)
393 396
394 397 @classmethod
395 398 def fromkeys(cls, iterable, value=None):
396 399 d = cls()
397 400 for key in iterable:
398 401 d[key] = value
399 402 return d
400 403
401 404 def __eq__(self, other):
402 405 if isinstance(other, OrderedDict):
403 406 return len(self) == len(other) and self.items() == other.items()
404 407 return dict.__eq__(self, other)
405 408
406 409 def __ne__(self, other):
407 410 return not self == other
408 411
409 412
410 413 #===============================================================================
411 414 # TEST FUNCTIONS AND CREATORS
412 415 #===============================================================================
413 416 def create_test_index(repo_location, full_index):
414 417 """Makes default test index
415 418 :param repo_location:
416 419 :param full_index:
417 420 """
418 421 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
419 422 from rhodecode.lib.pidlock import DaemonLock, LockHeld
420 423 import shutil
421 424
422 425 index_location = os.path.join(repo_location, 'index')
423 426 if os.path.exists(index_location):
424 427 shutil.rmtree(index_location)
425 428
426 429 try:
427 430 l = DaemonLock()
428 431 WhooshIndexingDaemon(index_location=index_location,
429 432 repo_location=repo_location)\
430 433 .run(full_index=full_index)
431 434 l.release()
432 435 except LockHeld:
433 436 pass
434 437
435 438 def create_test_env(repos_test_path, config):
436 439 """Makes a fresh database and
437 440 install test repository into tmp dir
438 441 """
439 442 from rhodecode.lib.db_manage import DbManage
440 443 from rhodecode.tests import HG_REPO, GIT_REPO, NEW_HG_REPO, NEW_GIT_REPO, \
441 444 HG_FORK, GIT_FORK, TESTS_TMP_PATH
442 445 import tarfile
443 446 import shutil
444 447 from os.path import dirname as dn, join as jn, abspath
445 448
446 449 log = logging.getLogger('TestEnvCreator')
447 450 # create logger
448 451 log.setLevel(logging.DEBUG)
449 452 log.propagate = True
450 453 # create console handler and set level to debug
451 454 ch = logging.StreamHandler()
452 455 ch.setLevel(logging.DEBUG)
453 456
454 457 # create formatter
455 458 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
456 459
457 460 # add formatter to ch
458 461 ch.setFormatter(formatter)
459 462
460 463 # add ch to logger
461 464 log.addHandler(ch)
462 465
463 466 #PART ONE create db
464 467 dbname = config['sqlalchemy.db1.url'].split('/')[-1]
465 468 log.debug('making test db %s', dbname)
466 469
467 470 dbmanage = DbManage(log_sql=True, dbname=dbname, root=config['here'],
468 471 tests=True)
469 472 dbmanage.create_tables(override=True)
470 473 dbmanage.config_prompt(repos_test_path)
471 474 dbmanage.create_default_user()
472 475 dbmanage.admin_prompt()
473 476 dbmanage.create_permissions()
474 477 dbmanage.populate_default_permissions()
475 478
476 479 #PART TWO make test repo
477 480 log.debug('making test vcs repositories')
478 481
479 482 #remove old one from previos tests
480 483 for r in [HG_REPO, GIT_REPO, NEW_HG_REPO, NEW_GIT_REPO, HG_FORK, GIT_FORK]:
481 484
482 485 if os.path.isdir(jn(TESTS_TMP_PATH, r)):
483 486 log.debug('removing %s', r)
484 487 shutil.rmtree(jn(TESTS_TMP_PATH, r))
485 488
486 489 #CREATE DEFAULT HG REPOSITORY
487 490 cur_dir = dn(dn(abspath(__file__)))
488 491 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_hg.tar.gz"))
489 492 tar.extractall(jn(TESTS_TMP_PATH, HG_REPO))
490 493 tar.close()
491 494
492 495 class UpgradeDb(command.Command):
493 496 """Command used for paster to upgrade our database to newer version
494 497 """
495 498
496 499 max_args = 1
497 500 min_args = 1
498 501
499 502 usage = "CONFIG_FILE"
500 503 summary = "Upgrades current db to newer version given configuration file"
501 504 group_name = "RhodeCode"
502 505
503 506 parser = command.Command.standard_parser(verbose=True)
504 507
505 508 parser.add_option('--sql',
506 509 action='store_true',
507 510 dest='just_sql',
508 511 help="Prints upgrade sql for further investigation",
509 512 default=False)
510 513 def command(self):
511 514 config_name = self.args[0]
512 515 p = config_name.split('/')
513 516 root = '.' if len(p) == 1 else '/'.join(p[:-1])
514 517 config = ConfigParser.ConfigParser({'here':root})
515 518 config.read(config_name)
@@ -1,98 +1,98
1 1 from rhodecode import get_version
2 2 import sys
3 3 py_version = sys.version_info
4 4
5 5 requirements = [
6 6 "Pylons>=1.0.0",
7 7 "SQLAlchemy>=0.6.5",
8 8 "Mako>=0.3.6",
9 9 "vcs>=0.1.10",
10 10 "pygments>=1.3.0",
11 "mercurial>=1.6.4",
11 "mercurial>=1.7.1",
12 12 "whoosh>=1.3.1",
13 13 "celery>=2.1.3",
14 14 "py-bcrypt",
15 15 "babel",
16 16 ]
17 17
18 18 classifiers = ['Development Status :: 4 - Beta',
19 19 'Environment :: Web Environment',
20 20 'Framework :: Pylons',
21 21 'Intended Audience :: Developers',
22 22 'License :: OSI Approved :: BSD License',
23 23 'Operating System :: OS Independent',
24 24 'Programming Language :: Python', ]
25 25
26 26 if sys.version_info < (2, 6):
27 27 requirements.append("simplejson")
28 28 requirements.append("pysqlite")
29 29
30 30 #additional files from project that goes somewhere in the filesystem
31 31 #relative to sys.prefix
32 32 data_files = []
33 33
34 34 #additional files that goes into package itself
35 35 package_data = {'rhodecode': ['i18n/*/LC_MESSAGES/*.mo', ], }
36 36
37 37 description = ('Mercurial repository browser/management with '
38 38 'build in push/pull server and full text search')
39 39 #long description
40 40 try:
41 41 readme_file = 'README.rst'
42 42 changelog_file = 'docs/changelog.rst'
43 43 long_description = open(readme_file).read() + '/n/n' + \
44 44 open(changelog_file).read()
45 45
46 46 except IOError, err:
47 47 sys.stderr.write("[WARNING] Cannot find file specified as "
48 48 "long_description (%s)\n or changelog (%s) skipping that file" \
49 49 % (readme_file, changelog_file))
50 50 long_description = description
51 51
52 52
53 53 try:
54 54 from setuptools import setup, find_packages
55 55 except ImportError:
56 56 from ez_setup import use_setuptools
57 57 use_setuptools()
58 58 from setuptools import setup, find_packages
59 59 #packages
60 60 packages = find_packages(exclude=['ez_setup'])
61 61
62 62 setup(
63 63 name='RhodeCode',
64 64 version=get_version(),
65 65 description=description,
66 66 long_description=long_description,
67 67 keywords='rhodiumcode mercurial web hgwebdir gitweb git replacement serving hgweb rhodecode',
68 68 license='BSD',
69 69 author='Marcin Kuzminski',
70 70 author_email='marcin@python-works.com',
71 71 url='http://hg.python-works.com',
72 72 install_requires=requirements,
73 73 classifiers=classifiers,
74 74 setup_requires=["PasteScript>=1.6.3"],
75 75 data_files=data_files,
76 76 packages=packages,
77 77 include_package_data=True,
78 78 test_suite='nose.collector',
79 79 package_data=package_data,
80 80 message_extractors={'rhodecode': [
81 81 ('**.py', 'python', None),
82 82 ('templates/**.mako', 'mako', {'input_encoding': 'utf-8'}),
83 83 ('public/**', 'ignore', None)]},
84 84 zip_safe=False,
85 85 paster_plugins=['PasteScript', 'Pylons'],
86 86 entry_points="""
87 87 [paste.app_factory]
88 88 main = rhodecode.config.middleware:make_app
89 89
90 90 [paste.app_install]
91 91 main = pylons.util:PylonsInstaller
92 92
93 93 [paste.global_paster_command]
94 94 make-index = rhodecode.lib.indexers:MakeIndex
95 95 upgrade-db = rhodecode.lib.utils:UpgradeDb
96 96
97 97 """,
98 98 )
General Comments 0
You need to be logged in to leave comments. Login now