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