##// END OF EJS Templates
upgrade-db command dummy
marcink -
r684:2abb398c beta
parent child Browse files
Show More
@@ -1,519 +1,544
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # Utilities for RhodeCode
3 # Utilities for RhodeCode
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 # This program is free software; you can redistribute it and/or
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; version 2
7 # as published by the Free Software Foundation; version 2
8 # of the License or (at your opinion) any later version of the license.
8 # of the License or (at your opinion) any later version of the license.
9 #
9 #
10 # This program is distributed in the hope that it will be useful,
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
13 # GNU General Public License for more details.
14 #
14 #
15 # You should have received a copy of the GNU General Public License
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # MA 02110-1301, USA.
18 # MA 02110-1301, USA.
19 """
19 """
20 Created on April 18, 2010
20 Created on April 18, 2010
21 Utilities for RhodeCode
21 Utilities for RhodeCode
22 @author: marcink
22 @author: marcink
23 """
23 """
24
24
25 from UserDict import DictMixin
25 from UserDict import DictMixin
26 from mercurial import ui, config, hg
26 from mercurial import ui, config, hg
27 from mercurial.error import RepoError
27 from mercurial.error import RepoError
28 from rhodecode.model import meta
28 from rhodecode.model import meta
29 from rhodecode.model.caching_query import FromCache
29 from rhodecode.model.caching_query import FromCache
30 from rhodecode.model.db import Repository, User, RhodeCodeUi, RhodeCodeSettings, \
30 from rhodecode.model.db import Repository, User, RhodeCodeUi, RhodeCodeSettings, \
31 UserLog
31 UserLog
32 from rhodecode.model.repo import RepoModel
32 from rhodecode.model.repo import RepoModel
33 from rhodecode.model.user import UserModel
33 from rhodecode.model.user import UserModel
34 from vcs.backends.base import BaseChangeset
34 from vcs.backends.base import BaseChangeset
35 from vcs.backends.git import GitRepository
35 from paste.script import command
36 from vcs.backends.hg import MercurialRepository
36 import ConfigParser
37 from vcs.utils.lazy import LazyProperty
37 from vcs.utils.lazy import LazyProperty
38 import traceback
38 import traceback
39 import datetime
39 import datetime
40 import logging
40 import logging
41 import os
41 import os
42
42
43 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
44
44
45
45
46 def get_repo_slug(request):
46 def get_repo_slug(request):
47 return request.environ['pylons.routes_dict'].get('repo_name')
47 return request.environ['pylons.routes_dict'].get('repo_name')
48
48
49 def is_mercurial(environ):
49 def is_mercurial(environ):
50 """
50 """
51 Returns True if request's target is mercurial server - header
51 Returns True if request's target is mercurial server - header
52 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
52 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
53 """
53 """
54 http_accept = environ.get('HTTP_ACCEPT')
54 http_accept = environ.get('HTTP_ACCEPT')
55 if http_accept and http_accept.startswith('application/mercurial'):
55 if http_accept and http_accept.startswith('application/mercurial'):
56 return True
56 return True
57 return False
57 return False
58
58
59 def is_git(environ):
59 def is_git(environ):
60 """
60 """
61 Returns True if request's target is git server. ``HTTP_USER_AGENT`` would
61 Returns True if request's target is git server. ``HTTP_USER_AGENT`` would
62 then have git client version given.
62 then have git client version given.
63
63
64 :param environ:
64 :param environ:
65 """
65 """
66 http_user_agent = environ.get('HTTP_USER_AGENT')
66 http_user_agent = environ.get('HTTP_USER_AGENT')
67 if http_user_agent.startswith('git'):
67 if http_user_agent.startswith('git'):
68 return True
68 return True
69 return False
69 return False
70
70
71 def action_logger(user, action, repo, ipaddr, sa=None):
71 def action_logger(user, action, repo, ipaddr, sa=None):
72 """
72 """
73 Action logger for various action made by users
73 Action logger for various action made by users
74 """
74 """
75
75
76 if not sa:
76 if not sa:
77 sa = meta.Session()
77 sa = meta.Session()
78
78
79 try:
79 try:
80 if hasattr(user, 'user_id'):
80 if hasattr(user, 'user_id'):
81 user_obj = user
81 user_obj = user
82 elif isinstance(user, basestring):
82 elif isinstance(user, basestring):
83 user_obj = UserModel(sa).get_by_username(user, cache=False)
83 user_obj = UserModel(sa).get_by_username(user, cache=False)
84 else:
84 else:
85 raise Exception('You have to provide user object or username')
85 raise Exception('You have to provide user object or username')
86
86
87 repo_name = repo.lstrip('/')
87 repo_name = repo.lstrip('/')
88 user_log = UserLog()
88 user_log = UserLog()
89 user_log.user_id = user_obj.user_id
89 user_log.user_id = user_obj.user_id
90 user_log.action = action
90 user_log.action = action
91 user_log.repository_name = repo_name
91 user_log.repository_name = repo_name
92 user_log.repository = RepoModel(sa).get(repo_name, cache=False)
92 user_log.repository = RepoModel(sa).get(repo_name, cache=False)
93 user_log.action_date = datetime.datetime.now()
93 user_log.action_date = datetime.datetime.now()
94 user_log.user_ip = ipaddr
94 user_log.user_ip = ipaddr
95 sa.add(user_log)
95 sa.add(user_log)
96 sa.commit()
96 sa.commit()
97
97
98 log.info('Adding user %s, action %s on %s',
98 log.info('Adding user %s, action %s on %s',
99 user_obj.username, action, repo)
99 user_obj.username, action, repo)
100 except:
100 except:
101 log.error(traceback.format_exc())
101 log.error(traceback.format_exc())
102 sa.rollback()
102 sa.rollback()
103
103
104 def get_repos(path, recursive=False, initial=False):
104 def get_repos(path, recursive=False, initial=False):
105 """
105 """
106 Scans given path for repos and return (name,(type,path)) tuple
106 Scans given path for repos and return (name,(type,path)) tuple
107 :param prefix:
107 :param prefix:
108 :param path:
108 :param path:
109 :param recursive:
109 :param recursive:
110 :param initial:
110 :param initial:
111 """
111 """
112 from vcs.utils.helpers import get_scm
112 from vcs.utils.helpers import get_scm
113 from vcs.exceptions import VCSError
113 from vcs.exceptions import VCSError
114
114
115 try:
115 try:
116 scm = get_scm(path)
116 scm = get_scm(path)
117 except:
117 except:
118 pass
118 pass
119 else:
119 else:
120 raise Exception('The given path %s should not be a repository got %s',
120 raise Exception('The given path %s should not be a repository got %s',
121 path, scm)
121 path, scm)
122
122
123 for dirpath in os.listdir(path):
123 for dirpath in os.listdir(path):
124 try:
124 try:
125 yield dirpath, get_scm(os.path.join(path, dirpath))
125 yield dirpath, get_scm(os.path.join(path, dirpath))
126 except VCSError:
126 except VCSError:
127 pass
127 pass
128
128
129 if __name__ == '__main__':
129 if __name__ == '__main__':
130 get_repos('', '/home/marcink/workspace-python')
130 get_repos('', '/home/marcink/workspace-python')
131
131
132
132
133 def check_repo_fast(repo_name, base_path):
133 def check_repo_fast(repo_name, base_path):
134 if os.path.isdir(os.path.join(base_path, repo_name)):return False
134 if os.path.isdir(os.path.join(base_path, repo_name)):return False
135 return True
135 return True
136
136
137 def check_repo(repo_name, base_path, verify=True):
137 def check_repo(repo_name, base_path, verify=True):
138
138
139 repo_path = os.path.join(base_path, repo_name)
139 repo_path = os.path.join(base_path, repo_name)
140
140
141 try:
141 try:
142 if not check_repo_fast(repo_name, base_path):
142 if not check_repo_fast(repo_name, base_path):
143 return False
143 return False
144 r = hg.repository(ui.ui(), repo_path)
144 r = hg.repository(ui.ui(), repo_path)
145 if verify:
145 if verify:
146 hg.verify(r)
146 hg.verify(r)
147 #here we hnow that repo exists it was verified
147 #here we hnow that repo exists it was verified
148 log.info('%s repo is already created', repo_name)
148 log.info('%s repo is already created', repo_name)
149 return False
149 return False
150 except RepoError:
150 except RepoError:
151 #it means that there is no valid repo there...
151 #it means that there is no valid repo there...
152 log.info('%s repo is free for creation', repo_name)
152 log.info('%s repo is free for creation', repo_name)
153 return True
153 return True
154
154
155 def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
155 def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
156 while True:
156 while True:
157 ok = raw_input(prompt)
157 ok = raw_input(prompt)
158 if ok in ('y', 'ye', 'yes'): return True
158 if ok in ('y', 'ye', 'yes'): return True
159 if ok in ('n', 'no', 'nop', 'nope'): return False
159 if ok in ('n', 'no', 'nop', 'nope'): return False
160 retries = retries - 1
160 retries = retries - 1
161 if retries < 0: raise IOError
161 if retries < 0: raise IOError
162 print complaint
162 print complaint
163
163
164 def get_hg_ui_cached():
164 def get_hg_ui_cached():
165 try:
165 try:
166 sa = meta.Session
166 sa = meta.Session
167 ret = sa.query(RhodeCodeUi)\
167 ret = sa.query(RhodeCodeUi)\
168 .options(FromCache("sql_cache_short", "get_hg_ui_settings"))\
168 .options(FromCache("sql_cache_short", "get_hg_ui_settings"))\
169 .all()
169 .all()
170 except:
170 except:
171 pass
171 pass
172 finally:
172 finally:
173 meta.Session.remove()
173 meta.Session.remove()
174 return ret
174 return ret
175
175
176
176
177 def get_hg_settings():
177 def get_hg_settings():
178 try:
178 try:
179 sa = meta.Session()
179 sa = meta.Session()
180 ret = sa.query(RhodeCodeSettings)\
180 ret = sa.query(RhodeCodeSettings)\
181 .options(FromCache("sql_cache_short", "get_hg_settings"))\
181 .options(FromCache("sql_cache_short", "get_hg_settings"))\
182 .all()
182 .all()
183 except:
183 except:
184 pass
184 pass
185 finally:
185 finally:
186 meta.Session.remove()
186 meta.Session.remove()
187
187
188 if not ret:
188 if not ret:
189 raise Exception('Could not get application settings !')
189 raise Exception('Could not get application settings !')
190 settings = {}
190 settings = {}
191 for each in ret:
191 for each in ret:
192 settings['rhodecode_' + each.app_settings_name] = each.app_settings_value
192 settings['rhodecode_' + each.app_settings_name] = each.app_settings_value
193
193
194 return settings
194 return settings
195
195
196 def get_hg_ui_settings():
196 def get_hg_ui_settings():
197 try:
197 try:
198 sa = meta.Session()
198 sa = meta.Session()
199 ret = sa.query(RhodeCodeUi).all()
199 ret = sa.query(RhodeCodeUi).all()
200 except:
200 except:
201 pass
201 pass
202 finally:
202 finally:
203 meta.Session.remove()
203 meta.Session.remove()
204
204
205 if not ret:
205 if not ret:
206 raise Exception('Could not get application ui settings !')
206 raise Exception('Could not get application ui settings !')
207 settings = {}
207 settings = {}
208 for each in ret:
208 for each in ret:
209 k = each.ui_key
209 k = each.ui_key
210 v = each.ui_value
210 v = each.ui_value
211 if k == '/':
211 if k == '/':
212 k = 'root_path'
212 k = 'root_path'
213
213
214 if k.find('.') != -1:
214 if k.find('.') != -1:
215 k = k.replace('.', '_')
215 k = k.replace('.', '_')
216
216
217 if each.ui_section == 'hooks':
217 if each.ui_section == 'hooks':
218 v = each.ui_active
218 v = each.ui_active
219
219
220 settings[each.ui_section + '_' + k] = v
220 settings[each.ui_section + '_' + k] = v
221
221
222 return settings
222 return settings
223
223
224 #propagated from mercurial documentation
224 #propagated from mercurial documentation
225 ui_sections = ['alias', 'auth',
225 ui_sections = ['alias', 'auth',
226 'decode/encode', 'defaults',
226 'decode/encode', 'defaults',
227 'diff', 'email',
227 'diff', 'email',
228 'extensions', 'format',
228 'extensions', 'format',
229 'merge-patterns', 'merge-tools',
229 'merge-patterns', 'merge-tools',
230 'hooks', 'http_proxy',
230 'hooks', 'http_proxy',
231 'smtp', 'patch',
231 'smtp', 'patch',
232 'paths', 'profiling',
232 'paths', 'profiling',
233 'server', 'trusted',
233 'server', 'trusted',
234 'ui', 'web', ]
234 'ui', 'web', ]
235
235
236 def make_ui(read_from='file', path=None, checkpaths=True):
236 def make_ui(read_from='file', path=None, checkpaths=True):
237 """
237 """
238 A function that will read python rc files or database
238 A function that will read python rc files or database
239 and make an mercurial ui object from read options
239 and make an mercurial ui object from read options
240
240
241 :param path: path to mercurial config file
241 :param path: path to mercurial config file
242 :param checkpaths: check the path
242 :param checkpaths: check the path
243 :param read_from: read from 'file' or 'db'
243 :param read_from: read from 'file' or 'db'
244 """
244 """
245
245
246 baseui = ui.ui()
246 baseui = ui.ui()
247
247
248 if read_from == 'file':
248 if read_from == 'file':
249 if not os.path.isfile(path):
249 if not os.path.isfile(path):
250 log.warning('Unable to read config file %s' % path)
250 log.warning('Unable to read config file %s' % path)
251 return False
251 return False
252 log.debug('reading hgrc from %s', path)
252 log.debug('reading hgrc from %s', path)
253 cfg = config.config()
253 cfg = config.config()
254 cfg.read(path)
254 cfg.read(path)
255 for section in ui_sections:
255 for section in ui_sections:
256 for k, v in cfg.items(section):
256 for k, v in cfg.items(section):
257 baseui.setconfig(section, k, v)
257 baseui.setconfig(section, k, v)
258 log.debug('settings ui from file[%s]%s:%s', section, k, v)
258 log.debug('settings ui from file[%s]%s:%s', section, k, v)
259
259
260 elif read_from == 'db':
260 elif read_from == 'db':
261 hg_ui = get_hg_ui_cached()
261 hg_ui = get_hg_ui_cached()
262 for ui_ in hg_ui:
262 for ui_ in hg_ui:
263 if ui_.ui_active:
263 if ui_.ui_active:
264 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section, ui_.ui_key, ui_.ui_value)
264 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section, ui_.ui_key, ui_.ui_value)
265 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
265 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
266
266
267
267
268 return baseui
268 return baseui
269
269
270
270
271 def set_rhodecode_config(config):
271 def set_rhodecode_config(config):
272 hgsettings = get_hg_settings()
272 hgsettings = get_hg_settings()
273
273
274 for k, v in hgsettings.items():
274 for k, v in hgsettings.items():
275 config[k] = v
275 config[k] = v
276
276
277 def invalidate_cache(name, *args):
277 def invalidate_cache(name, *args):
278 """
278 """
279 Puts cache invalidation task into db for
279 Puts cache invalidation task into db for
280 further global cache invalidation
280 further global cache invalidation
281 """
281 """
282 pass
282 pass
283
283
284 class EmptyChangeset(BaseChangeset):
284 class EmptyChangeset(BaseChangeset):
285 """
285 """
286 An dummy empty changeset. It's possible to pass hash when creating
286 An dummy empty changeset. It's possible to pass hash when creating
287 an EmptyChangeset
287 an EmptyChangeset
288 """
288 """
289
289
290 def __init__(self, cs='0' * 40):
290 def __init__(self, cs='0' * 40):
291 self._empty_cs = cs
291 self._empty_cs = cs
292 self.revision = -1
292 self.revision = -1
293 self.message = ''
293 self.message = ''
294 self.author = ''
294 self.author = ''
295 self.date = ''
295 self.date = ''
296
296
297 @LazyProperty
297 @LazyProperty
298 def raw_id(self):
298 def raw_id(self):
299 """
299 """
300 Returns raw string identifying this changeset, useful for web
300 Returns raw string identifying this changeset, useful for web
301 representation.
301 representation.
302 """
302 """
303 return self._empty_cs
303 return self._empty_cs
304
304
305 @LazyProperty
305 @LazyProperty
306 def short_id(self):
306 def short_id(self):
307 return self.raw_id[:12]
307 return self.raw_id[:12]
308
308
309 def get_file_changeset(self, path):
309 def get_file_changeset(self, path):
310 return self
310 return self
311
311
312 def get_file_content(self, path):
312 def get_file_content(self, path):
313 return u''
313 return u''
314
314
315 def get_file_size(self, path):
315 def get_file_size(self, path):
316 return 0
316 return 0
317
317
318 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
318 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
319 """
319 """
320 maps all found repositories into db
320 maps all found repositories into db
321 """
321 """
322
322
323 sa = meta.Session()
323 sa = meta.Session()
324 rm = RepoModel(sa)
324 rm = RepoModel(sa)
325 user = sa.query(User).filter(User.admin == True).first()
325 user = sa.query(User).filter(User.admin == True).first()
326
326
327 for name, repo in initial_repo_list.items():
327 for name, repo in initial_repo_list.items():
328 if not rm.get(name, cache=False):
328 if not rm.get(name, cache=False):
329 log.info('repository %s not found creating default', name)
329 log.info('repository %s not found creating default', name)
330
330
331 form_data = {
331 form_data = {
332 'repo_name':name,
332 'repo_name':name,
333 'repo_type':repo.alias,
333 'repo_type':repo.alias,
334 'description':repo.description \
334 'description':repo.description \
335 if repo.description != 'unknown' else \
335 if repo.description != 'unknown' else \
336 '%s repository' % name,
336 '%s repository' % name,
337 'private':False
337 'private':False
338 }
338 }
339 rm.create(form_data, user, just_db=True)
339 rm.create(form_data, user, just_db=True)
340
340
341 if remove_obsolete:
341 if remove_obsolete:
342 #remove from database those repositories that are not in the filesystem
342 #remove from database those repositories that are not in the filesystem
343 for repo in sa.query(Repository).all():
343 for repo in sa.query(Repository).all():
344 if repo.repo_name not in initial_repo_list.keys():
344 if repo.repo_name not in initial_repo_list.keys():
345 sa.delete(repo)
345 sa.delete(repo)
346 sa.commit()
346 sa.commit()
347
347
348 class OrderedDict(dict, DictMixin):
348 class OrderedDict(dict, DictMixin):
349
349
350 def __init__(self, *args, **kwds):
350 def __init__(self, *args, **kwds):
351 if len(args) > 1:
351 if len(args) > 1:
352 raise TypeError('expected at most 1 arguments, got %d' % len(args))
352 raise TypeError('expected at most 1 arguments, got %d' % len(args))
353 try:
353 try:
354 self.__end
354 self.__end
355 except AttributeError:
355 except AttributeError:
356 self.clear()
356 self.clear()
357 self.update(*args, **kwds)
357 self.update(*args, **kwds)
358
358
359 def clear(self):
359 def clear(self):
360 self.__end = end = []
360 self.__end = end = []
361 end += [None, end, end] # sentinel node for doubly linked list
361 end += [None, end, end] # sentinel node for doubly linked list
362 self.__map = {} # key --> [key, prev, next]
362 self.__map = {} # key --> [key, prev, next]
363 dict.clear(self)
363 dict.clear(self)
364
364
365 def __setitem__(self, key, value):
365 def __setitem__(self, key, value):
366 if key not in self:
366 if key not in self:
367 end = self.__end
367 end = self.__end
368 curr = end[1]
368 curr = end[1]
369 curr[2] = end[1] = self.__map[key] = [key, curr, end]
369 curr[2] = end[1] = self.__map[key] = [key, curr, end]
370 dict.__setitem__(self, key, value)
370 dict.__setitem__(self, key, value)
371
371
372 def __delitem__(self, key):
372 def __delitem__(self, key):
373 dict.__delitem__(self, key)
373 dict.__delitem__(self, key)
374 key, prev, next = self.__map.pop(key)
374 key, prev, next = self.__map.pop(key)
375 prev[2] = next
375 prev[2] = next
376 next[1] = prev
376 next[1] = prev
377
377
378 def __iter__(self):
378 def __iter__(self):
379 end = self.__end
379 end = self.__end
380 curr = end[2]
380 curr = end[2]
381 while curr is not end:
381 while curr is not end:
382 yield curr[0]
382 yield curr[0]
383 curr = curr[2]
383 curr = curr[2]
384
384
385 def __reversed__(self):
385 def __reversed__(self):
386 end = self.__end
386 end = self.__end
387 curr = end[1]
387 curr = end[1]
388 while curr is not end:
388 while curr is not end:
389 yield curr[0]
389 yield curr[0]
390 curr = curr[1]
390 curr = curr[1]
391
391
392 def popitem(self, last=True):
392 def popitem(self, last=True):
393 if not self:
393 if not self:
394 raise KeyError('dictionary is empty')
394 raise KeyError('dictionary is empty')
395 if last:
395 if last:
396 key = reversed(self).next()
396 key = reversed(self).next()
397 else:
397 else:
398 key = iter(self).next()
398 key = iter(self).next()
399 value = self.pop(key)
399 value = self.pop(key)
400 return key, value
400 return key, value
401
401
402 def __reduce__(self):
402 def __reduce__(self):
403 items = [[k, self[k]] for k in self]
403 items = [[k, self[k]] for k in self]
404 tmp = self.__map, self.__end
404 tmp = self.__map, self.__end
405 del self.__map, self.__end
405 del self.__map, self.__end
406 inst_dict = vars(self).copy()
406 inst_dict = vars(self).copy()
407 self.__map, self.__end = tmp
407 self.__map, self.__end = tmp
408 if inst_dict:
408 if inst_dict:
409 return (self.__class__, (items,), inst_dict)
409 return (self.__class__, (items,), inst_dict)
410 return self.__class__, (items,)
410 return self.__class__, (items,)
411
411
412 def keys(self):
412 def keys(self):
413 return list(self)
413 return list(self)
414
414
415 setdefault = DictMixin.setdefault
415 setdefault = DictMixin.setdefault
416 update = DictMixin.update
416 update = DictMixin.update
417 pop = DictMixin.pop
417 pop = DictMixin.pop
418 values = DictMixin.values
418 values = DictMixin.values
419 items = DictMixin.items
419 items = DictMixin.items
420 iterkeys = DictMixin.iterkeys
420 iterkeys = DictMixin.iterkeys
421 itervalues = DictMixin.itervalues
421 itervalues = DictMixin.itervalues
422 iteritems = DictMixin.iteritems
422 iteritems = DictMixin.iteritems
423
423
424 def __repr__(self):
424 def __repr__(self):
425 if not self:
425 if not self:
426 return '%s()' % (self.__class__.__name__,)
426 return '%s()' % (self.__class__.__name__,)
427 return '%s(%r)' % (self.__class__.__name__, self.items())
427 return '%s(%r)' % (self.__class__.__name__, self.items())
428
428
429 def copy(self):
429 def copy(self):
430 return self.__class__(self)
430 return self.__class__(self)
431
431
432 @classmethod
432 @classmethod
433 def fromkeys(cls, iterable, value=None):
433 def fromkeys(cls, iterable, value=None):
434 d = cls()
434 d = cls()
435 for key in iterable:
435 for key in iterable:
436 d[key] = value
436 d[key] = value
437 return d
437 return d
438
438
439 def __eq__(self, other):
439 def __eq__(self, other):
440 if isinstance(other, OrderedDict):
440 if isinstance(other, OrderedDict):
441 return len(self) == len(other) and self.items() == other.items()
441 return len(self) == len(other) and self.items() == other.items()
442 return dict.__eq__(self, other)
442 return dict.__eq__(self, other)
443
443
444 def __ne__(self, other):
444 def __ne__(self, other):
445 return not self == other
445 return not self == other
446
446
447
447
448 #===============================================================================
448 #===============================================================================
449 # TEST FUNCTIONS AND CREATORS
449 # TEST FUNCTIONS AND CREATORS
450 #===============================================================================
450 #===============================================================================
451 def create_test_index(repo_location, full_index):
451 def create_test_index(repo_location, full_index):
452 """Makes default test index
452 """Makes default test index
453 :param repo_location:
453 :param repo_location:
454 :param full_index:
454 :param full_index:
455 """
455 """
456 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
456 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
457 from rhodecode.lib.pidlock import DaemonLock, LockHeld
457 from rhodecode.lib.pidlock import DaemonLock, LockHeld
458 from rhodecode.lib.indexers import IDX_LOCATION
458 from rhodecode.lib.indexers import IDX_LOCATION
459 import shutil
459 import shutil
460
460
461 if os.path.exists(IDX_LOCATION):
461 if os.path.exists(IDX_LOCATION):
462 shutil.rmtree(IDX_LOCATION)
462 shutil.rmtree(IDX_LOCATION)
463
463
464 try:
464 try:
465 l = DaemonLock()
465 l = DaemonLock()
466 WhooshIndexingDaemon(repo_location=repo_location)\
466 WhooshIndexingDaemon(repo_location=repo_location)\
467 .run(full_index=full_index)
467 .run(full_index=full_index)
468 l.release()
468 l.release()
469 except LockHeld:
469 except LockHeld:
470 pass
470 pass
471
471
472 def create_test_env(repos_test_path, config):
472 def create_test_env(repos_test_path, config):
473 """Makes a fresh database and
473 """Makes a fresh database and
474 install test repository into tmp dir
474 install test repository into tmp dir
475 """
475 """
476 from rhodecode.lib.db_manage import DbManage
476 from rhodecode.lib.db_manage import DbManage
477 import tarfile
477 import tarfile
478 import shutil
478 import shutil
479 from os.path import dirname as dn, join as jn, abspath
479 from os.path import dirname as dn, join as jn, abspath
480
480
481 log = logging.getLogger('TestEnvCreator')
481 log = logging.getLogger('TestEnvCreator')
482 # create logger
482 # create logger
483 log.setLevel(logging.DEBUG)
483 log.setLevel(logging.DEBUG)
484 log.propagate = True
484 log.propagate = True
485 # create console handler and set level to debug
485 # create console handler and set level to debug
486 ch = logging.StreamHandler()
486 ch = logging.StreamHandler()
487 ch.setLevel(logging.DEBUG)
487 ch.setLevel(logging.DEBUG)
488
488
489 # create formatter
489 # create formatter
490 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
490 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
491
491
492 # add formatter to ch
492 # add formatter to ch
493 ch.setFormatter(formatter)
493 ch.setFormatter(formatter)
494
494
495 # add ch to logger
495 # add ch to logger
496 log.addHandler(ch)
496 log.addHandler(ch)
497
497
498 #PART ONE create db
498 #PART ONE create db
499 dbname = config['sqlalchemy.db1.url'].split('/')[-1]
499 dbname = config['sqlalchemy.db1.url'].split('/')[-1]
500 log.debug('making test db %s', dbname)
500 log.debug('making test db %s', dbname)
501
501
502 dbmanage = DbManage(log_sql=True, dbname=dbname, root=config['here'],
502 dbmanage = DbManage(log_sql=True, dbname=dbname, root=config['here'],
503 tests=True)
503 tests=True)
504 dbmanage.create_tables(override=True)
504 dbmanage.create_tables(override=True)
505 dbmanage.config_prompt(repos_test_path)
505 dbmanage.config_prompt(repos_test_path)
506 dbmanage.create_default_user()
506 dbmanage.create_default_user()
507 dbmanage.admin_prompt()
507 dbmanage.admin_prompt()
508 dbmanage.create_permissions()
508 dbmanage.create_permissions()
509 dbmanage.populate_default_permissions()
509 dbmanage.populate_default_permissions()
510
510
511 #PART TWO make test repo
511 #PART TWO make test repo
512 log.debug('making test vcs repo')
512 log.debug('making test vcs repo')
513 if os.path.isdir('/tmp/vcs_test'):
513 if os.path.isdir('/tmp/vcs_test'):
514 shutil.rmtree('/tmp/vcs_test')
514 shutil.rmtree('/tmp/vcs_test')
515
515
516 cur_dir = dn(dn(abspath(__file__)))
516 cur_dir = dn(dn(abspath(__file__)))
517 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test.tar.gz"))
517 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test.tar.gz"))
518 tar.extractall('/tmp')
518 tar.extractall('/tmp')
519 tar.close()
519 tar.close()
520
521 class UpgradeDb(command.Command):
522 """Command used for paster to upgrade our database to newer version
523 """
524
525 max_args = 1
526 min_args = 1
527
528 usage = "CONFIG_FILE"
529 summary = "Upgrades current db to newer version given configuration file"
530 group_name = "RhodeCode"
531
532 parser = command.Command.standard_parser(verbose=True)
533
534 parser.add_option('--sql',
535 action='store_true',
536 dest='just_sql',
537 help="Prints upgrade sql for further investigation",
538 default=False)
539 def command(self):
540 config_name = self.args[0]
541 p = config_name.split('/')
542 root = '.' if len(p) == 1 else '/'.join(p[:-1])
543 config = ConfigParser.ConfigParser({'here':root})
544 config.read(config_name)
General Comments 0
You need to be logged in to leave comments. Login now