##// END OF EJS Templates
Added missing migrations, and move update_repoinfo to RepoModel...
marcink -
r3309:b3cf4539 beta
parent child Browse files
Show More
@@ -0,0 +1,28 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.model.db_1_6_0
4 ~~~~~~~~~~~~~~~~~~~~~~~~
5
6 Database Models for RhodeCode <=1.5.X
7
8 :created_on: Apr 08, 2010
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
26 #TODO: replace that will db.py content after next
27
28 from rhodecode.model.db import *
@@ -0,0 +1,36 b''
1 import logging
2 import datetime
3
4 from sqlalchemy import *
5 from sqlalchemy.exc import DatabaseError
6 from sqlalchemy.orm import relation, backref, class_mapper, joinedload
7 from sqlalchemy.orm.session import Session
8 from sqlalchemy.ext.declarative import declarative_base
9
10 from rhodecode.lib.dbmigrate.migrate import *
11 from rhodecode.lib.dbmigrate.migrate.changeset import *
12
13 from rhodecode.model.meta import Base
14 from rhodecode.model import meta
15 from rhodecode.lib.dbmigrate.versions import _reset_base
16
17 log = logging.getLogger(__name__)
18
19
20 def upgrade(migrate_engine):
21 """
22 Upgrade operations go here.
23 Don't create your own engine; bind migrate_engine to your metadata
24 """
25 _reset_base(migrate_engine)
26 #==========================================================================
27 # USER LOGS
28 #==========================================================================
29 from rhodecode.lib.dbmigrate.schema.db_1_6_0 import RepositoryField
30 tbl = RepositoryField.__table__
31 tbl.create()
32
33
34 def downgrade(migrate_engine):
35 meta = MetaData()
36 meta.bind = migrate_engine
@@ -1,715 +1,722 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.db_manage
3 rhodecode.lib.db_manage
4 ~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Database creation, and setup module for RhodeCode. Used for creation
6 Database creation, and setup module for RhodeCode. Used for creation
7 of database as well as for migration operations
7 of database as well as for migration operations
8
8
9 :created_on: Apr 10, 2010
9 :created_on: Apr 10, 2010
10 :author: marcink
10 :author: marcink
11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 :license: GPLv3, see COPYING for more details.
12 :license: GPLv3, see COPYING for more details.
13 """
13 """
14 # This program is free software: you can redistribute it and/or modify
14 # This program is free software: you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation, either version 3 of the License, or
16 # the Free Software Foundation, either version 3 of the License, or
17 # (at your option) any later version.
17 # (at your option) any later version.
18 #
18 #
19 # This program is distributed in the hope that it will be useful,
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
22 # GNU General Public License for more details.
23 #
23 #
24 # You should have received a copy of the GNU General Public License
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26
26
27 import os
27 import os
28 import sys
28 import sys
29 import uuid
29 import uuid
30 import logging
30 import logging
31 from os.path import dirname as dn, join as jn
31 from os.path import dirname as dn, join as jn
32
32
33 from rhodecode import __dbversion__, __py_version__
33 from rhodecode import __dbversion__, __py_version__
34
34
35 from rhodecode.model.user import UserModel
35 from rhodecode.model.user import UserModel
36 from rhodecode.lib.utils import ask_ok
36 from rhodecode.lib.utils import ask_ok
37 from rhodecode.model import init_model
37 from rhodecode.model import init_model
38 from rhodecode.model.db import User, Permission, RhodeCodeUi, \
38 from rhodecode.model.db import User, Permission, RhodeCodeUi, \
39 RhodeCodeSetting, UserToPerm, DbMigrateVersion, RepoGroup, \
39 RhodeCodeSetting, UserToPerm, DbMigrateVersion, RepoGroup, \
40 UserRepoGroupToPerm
40 UserRepoGroupToPerm
41
41
42 from sqlalchemy.engine import create_engine
42 from sqlalchemy.engine import create_engine
43 from rhodecode.model.repos_group import ReposGroupModel
43 from rhodecode.model.repos_group import ReposGroupModel
44 #from rhodecode.model import meta
44 #from rhodecode.model import meta
45 from rhodecode.model.meta import Session, Base
45 from rhodecode.model.meta import Session, Base
46 from rhodecode.model.repo import RepoModel
46
47
47
48
48 log = logging.getLogger(__name__)
49 log = logging.getLogger(__name__)
49
50
50
51
51 def notify(msg):
52 def notify(msg):
52 """
53 """
53 Notification for migrations messages
54 Notification for migrations messages
54 """
55 """
55 ml = len(msg) + (4 * 2)
56 ml = len(msg) + (4 * 2)
56 print >> sys.stdout, ('*** %s ***\n%s' % (msg, '*' * ml)).upper()
57 print >> sys.stdout, ('*** %s ***\n%s' % (msg, '*' * ml)).upper()
57
58
58
59
59 class DbManage(object):
60 class DbManage(object):
60 def __init__(self, log_sql, dbconf, root, tests=False, cli_args={}):
61 def __init__(self, log_sql, dbconf, root, tests=False, cli_args={}):
61 self.dbname = dbconf.split('/')[-1]
62 self.dbname = dbconf.split('/')[-1]
62 self.tests = tests
63 self.tests = tests
63 self.root = root
64 self.root = root
64 self.dburi = dbconf
65 self.dburi = dbconf
65 self.log_sql = log_sql
66 self.log_sql = log_sql
66 self.db_exists = False
67 self.db_exists = False
67 self.cli_args = cli_args
68 self.cli_args = cli_args
68 self.init_db()
69 self.init_db()
69 global ask_ok
70 global ask_ok
70
71
71 if self.cli_args.get('force_ask') is True:
72 if self.cli_args.get('force_ask') is True:
72 ask_ok = lambda *args, **kwargs: True
73 ask_ok = lambda *args, **kwargs: True
73 elif self.cli_args.get('force_ask') is False:
74 elif self.cli_args.get('force_ask') is False:
74 ask_ok = lambda *args, **kwargs: False
75 ask_ok = lambda *args, **kwargs: False
75
76
76 def init_db(self):
77 def init_db(self):
77 engine = create_engine(self.dburi, echo=self.log_sql)
78 engine = create_engine(self.dburi, echo=self.log_sql)
78 init_model(engine)
79 init_model(engine)
79 self.sa = Session()
80 self.sa = Session()
80
81
81 def create_tables(self, override=False):
82 def create_tables(self, override=False):
82 """
83 """
83 Create a auth database
84 Create a auth database
84 """
85 """
85
86
86 log.info("Any existing database is going to be destroyed")
87 log.info("Any existing database is going to be destroyed")
87 if self.tests:
88 if self.tests:
88 destroy = True
89 destroy = True
89 else:
90 else:
90 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
91 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
91 if not destroy:
92 if not destroy:
92 sys.exit('Nothing done')
93 sys.exit('Nothing done')
93 if destroy:
94 if destroy:
94 Base.metadata.drop_all()
95 Base.metadata.drop_all()
95
96
96 checkfirst = not override
97 checkfirst = not override
97 Base.metadata.create_all(checkfirst=checkfirst)
98 Base.metadata.create_all(checkfirst=checkfirst)
98 log.info('Created tables for %s' % self.dbname)
99 log.info('Created tables for %s' % self.dbname)
99
100
100 def set_db_version(self):
101 def set_db_version(self):
101 ver = DbMigrateVersion()
102 ver = DbMigrateVersion()
102 ver.version = __dbversion__
103 ver.version = __dbversion__
103 ver.repository_id = 'rhodecode_db_migrations'
104 ver.repository_id = 'rhodecode_db_migrations'
104 ver.repository_path = 'versions'
105 ver.repository_path = 'versions'
105 self.sa.add(ver)
106 self.sa.add(ver)
106 log.info('db version set to: %s' % __dbversion__)
107 log.info('db version set to: %s' % __dbversion__)
107
108
108 def upgrade(self):
109 def upgrade(self):
109 """
110 """
110 Upgrades given database schema to given revision following
111 Upgrades given database schema to given revision following
111 all needed steps, to perform the upgrade
112 all needed steps, to perform the upgrade
112
113
113 """
114 """
114
115
115 from rhodecode.lib.dbmigrate.migrate.versioning import api
116 from rhodecode.lib.dbmigrate.migrate.versioning import api
116 from rhodecode.lib.dbmigrate.migrate.exceptions import \
117 from rhodecode.lib.dbmigrate.migrate.exceptions import \
117 DatabaseNotControlledError
118 DatabaseNotControlledError
118
119
119 if 'sqlite' in self.dburi:
120 if 'sqlite' in self.dburi:
120 print (
121 print (
121 '********************** WARNING **********************\n'
122 '********************** WARNING **********************\n'
122 'Make sure your version of sqlite is at least 3.7.X. \n'
123 'Make sure your version of sqlite is at least 3.7.X. \n'
123 'Earlier versions are known to fail on some migrations\n'
124 'Earlier versions are known to fail on some migrations\n'
124 '*****************************************************\n'
125 '*****************************************************\n'
125 )
126 )
126 upgrade = ask_ok('You are about to perform database upgrade, make '
127 upgrade = ask_ok('You are about to perform database upgrade, make '
127 'sure You backed up your database before. '
128 'sure You backed up your database before. '
128 'Continue ? [y/n]')
129 'Continue ? [y/n]')
129 if not upgrade:
130 if not upgrade:
130 sys.exit('Nothing done')
131 sys.exit('Nothing done')
131
132
132 repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))),
133 repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))),
133 'rhodecode/lib/dbmigrate')
134 'rhodecode/lib/dbmigrate')
134 db_uri = self.dburi
135 db_uri = self.dburi
135
136
136 try:
137 try:
137 curr_version = api.db_version(db_uri, repository_path)
138 curr_version = api.db_version(db_uri, repository_path)
138 msg = ('Found current database under version'
139 msg = ('Found current database under version'
139 ' control with version %s' % curr_version)
140 ' control with version %s' % curr_version)
140
141
141 except (RuntimeError, DatabaseNotControlledError):
142 except (RuntimeError, DatabaseNotControlledError):
142 curr_version = 1
143 curr_version = 1
143 msg = ('Current database is not under version control. Setting'
144 msg = ('Current database is not under version control. Setting'
144 ' as version %s' % curr_version)
145 ' as version %s' % curr_version)
145 api.version_control(db_uri, repository_path, curr_version)
146 api.version_control(db_uri, repository_path, curr_version)
146
147
147 notify(msg)
148 notify(msg)
148
149
149 if curr_version == __dbversion__:
150 if curr_version == __dbversion__:
150 sys.exit('This database is already at the newest version')
151 sys.exit('This database is already at the newest version')
151
152
152 #======================================================================
153 #======================================================================
153 # UPGRADE STEPS
154 # UPGRADE STEPS
154 #======================================================================
155 #======================================================================
155
156
156 class UpgradeSteps(object):
157 class UpgradeSteps(object):
157 """
158 """
158 Those steps follow schema versions so for example schema
159 Those steps follow schema versions so for example schema
159 for example schema with seq 002 == step_2 and so on.
160 for example schema with seq 002 == step_2 and so on.
160 """
161 """
161
162
162 def __init__(self, klass):
163 def __init__(self, klass):
163 self.klass = klass
164 self.klass = klass
164
165
165 def step_0(self):
166 def step_0(self):
166 # step 0 is the schema upgrade, and than follow proper upgrades
167 # step 0 is the schema upgrade, and than follow proper upgrades
167 notify('attempting to do database upgrade from '
168 notify('attempting to do database upgrade from '
168 'version %s to version %s' %(curr_version, __dbversion__))
169 'version %s to version %s' %(curr_version, __dbversion__))
169 api.upgrade(db_uri, repository_path, __dbversion__)
170 api.upgrade(db_uri, repository_path, __dbversion__)
170 notify('Schema upgrade completed')
171 notify('Schema upgrade completed')
171
172
172 def step_1(self):
173 def step_1(self):
173 pass
174 pass
174
175
175 def step_2(self):
176 def step_2(self):
176 notify('Patching repo paths for newer version of RhodeCode')
177 notify('Patching repo paths for newer version of RhodeCode')
177 self.klass.fix_repo_paths()
178 self.klass.fix_repo_paths()
178
179
179 notify('Patching default user of RhodeCode')
180 notify('Patching default user of RhodeCode')
180 self.klass.fix_default_user()
181 self.klass.fix_default_user()
181
182
182 log.info('Changing ui settings')
183 log.info('Changing ui settings')
183 self.klass.create_ui_settings()
184 self.klass.create_ui_settings()
184
185
185 def step_3(self):
186 def step_3(self):
186 notify('Adding additional settings into RhodeCode db')
187 notify('Adding additional settings into RhodeCode db')
187 self.klass.fix_settings()
188 self.klass.fix_settings()
188 notify('Adding ldap defaults')
189 notify('Adding ldap defaults')
189 self.klass.create_ldap_options(skip_existing=True)
190 self.klass.create_ldap_options(skip_existing=True)
190
191
191 def step_4(self):
192 def step_4(self):
192 notify('create permissions and fix groups')
193 notify('create permissions and fix groups')
193 self.klass.create_permissions()
194 self.klass.create_permissions()
194 self.klass.fixup_groups()
195 self.klass.fixup_groups()
195
196
196 def step_5(self):
197 def step_5(self):
197 pass
198 pass
198
199
199 def step_6(self):
200 def step_6(self):
200
201
201 notify('re-checking permissions')
202 notify('re-checking permissions')
202 self.klass.create_permissions()
203 self.klass.create_permissions()
203
204
204 notify('installing new UI options')
205 notify('installing new UI options')
205 sett4 = RhodeCodeSetting('show_public_icon', True)
206 sett4 = RhodeCodeSetting('show_public_icon', True)
206 Session().add(sett4)
207 Session().add(sett4)
207 sett5 = RhodeCodeSetting('show_private_icon', True)
208 sett5 = RhodeCodeSetting('show_private_icon', True)
208 Session().add(sett5)
209 Session().add(sett5)
209 sett6 = RhodeCodeSetting('stylify_metatags', False)
210 sett6 = RhodeCodeSetting('stylify_metatags', False)
210 Session().add(sett6)
211 Session().add(sett6)
211
212
212 notify('fixing old PULL hook')
213 notify('fixing old PULL hook')
213 _pull = RhodeCodeUi.get_by_key('preoutgoing.pull_logger')
214 _pull = RhodeCodeUi.get_by_key('preoutgoing.pull_logger')
214 if _pull:
215 if _pull:
215 _pull.ui_key = RhodeCodeUi.HOOK_PULL
216 _pull.ui_key = RhodeCodeUi.HOOK_PULL
216 Session().add(_pull)
217 Session().add(_pull)
217
218
218 notify('fixing old PUSH hook')
219 notify('fixing old PUSH hook')
219 _push = RhodeCodeUi.get_by_key('pretxnchangegroup.push_logger')
220 _push = RhodeCodeUi.get_by_key('pretxnchangegroup.push_logger')
220 if _push:
221 if _push:
221 _push.ui_key = RhodeCodeUi.HOOK_PUSH
222 _push.ui_key = RhodeCodeUi.HOOK_PUSH
222 Session().add(_push)
223 Session().add(_push)
223
224
224 notify('installing new pre-push hook')
225 notify('installing new pre-push hook')
225 hooks4 = RhodeCodeUi()
226 hooks4 = RhodeCodeUi()
226 hooks4.ui_section = 'hooks'
227 hooks4.ui_section = 'hooks'
227 hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH
228 hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH
228 hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push'
229 hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push'
229 Session().add(hooks4)
230 Session().add(hooks4)
230
231
231 notify('installing new pre-pull hook')
232 notify('installing new pre-pull hook')
232 hooks6 = RhodeCodeUi()
233 hooks6 = RhodeCodeUi()
233 hooks6.ui_section = 'hooks'
234 hooks6.ui_section = 'hooks'
234 hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL
235 hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL
235 hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull'
236 hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull'
236 Session().add(hooks6)
237 Session().add(hooks6)
237
238
238 notify('installing hgsubversion option')
239 notify('installing hgsubversion option')
239 # enable hgsubversion disabled by default
240 # enable hgsubversion disabled by default
240 hgsubversion = RhodeCodeUi()
241 hgsubversion = RhodeCodeUi()
241 hgsubversion.ui_section = 'extensions'
242 hgsubversion.ui_section = 'extensions'
242 hgsubversion.ui_key = 'hgsubversion'
243 hgsubversion.ui_key = 'hgsubversion'
243 hgsubversion.ui_value = ''
244 hgsubversion.ui_value = ''
244 hgsubversion.ui_active = False
245 hgsubversion.ui_active = False
245 Session().add(hgsubversion)
246 Session().add(hgsubversion)
246
247
247 notify('installing hg git option')
248 notify('installing hg git option')
248 # enable hggit disabled by default
249 # enable hggit disabled by default
249 hggit = RhodeCodeUi()
250 hggit = RhodeCodeUi()
250 hggit.ui_section = 'extensions'
251 hggit.ui_section = 'extensions'
251 hggit.ui_key = 'hggit'
252 hggit.ui_key = 'hggit'
252 hggit.ui_value = ''
253 hggit.ui_value = ''
253 hggit.ui_active = False
254 hggit.ui_active = False
254 Session().add(hggit)
255 Session().add(hggit)
255
256
256 notify('re-check default permissions')
257 notify('re-check default permissions')
257 default_user = User.get_by_username(User.DEFAULT_USER)
258 default_user = User.get_by_username(User.DEFAULT_USER)
258 perm = Permission.get_by_key('hg.fork.repository')
259 perm = Permission.get_by_key('hg.fork.repository')
259 reg_perm = UserToPerm()
260 reg_perm = UserToPerm()
260 reg_perm.user = default_user
261 reg_perm.user = default_user
261 reg_perm.permission = perm
262 reg_perm.permission = perm
262 Session().add(reg_perm)
263 Session().add(reg_perm)
263
264
264 def step_7(self):
265 def step_7(self):
265 perm_fixes = self.klass.reset_permissions(User.DEFAULT_USER)
266 perm_fixes = self.klass.reset_permissions(User.DEFAULT_USER)
266 Session().commit()
267 Session().commit()
267 if perm_fixes:
268 if perm_fixes:
268 notify('There was an inconsistent state of permissions '
269 notify('There was an inconsistent state of permissions '
269 'detected for default user. Permissions are now '
270 'detected for default user. Permissions are now '
270 'reset to the default value for default user. '
271 'reset to the default value for default user. '
271 'Please validate and check default permissions '
272 'Please validate and check default permissions '
272 'in admin panel')
273 'in admin panel')
273
274
274 def step_8(self):
275 def step_8(self):
275 self.klass.populate_default_permissions()
276 self.klass.populate_default_permissions()
276 self.klass.create_default_options(skip_existing=True)
277 self.klass.create_default_options(skip_existing=True)
277 Session().commit()
278 Session().commit()
278
279
279 def step_9(self):
280 def step_9(self):
280 perm_fixes = self.klass.reset_permissions(User.DEFAULT_USER)
281 perm_fixes = self.klass.reset_permissions(User.DEFAULT_USER)
281 Session().commit()
282 Session().commit()
282 if perm_fixes:
283 if perm_fixes:
283 notify('There was an inconsistent state of permissions '
284 notify('There was an inconsistent state of permissions '
284 'detected for default user. Permissions are now '
285 'detected for default user. Permissions are now '
285 'reset to the default value for default user. '
286 'reset to the default value for default user. '
286 'Please validate and check default permissions '
287 'Please validate and check default permissions '
287 'in admin panel')
288 'in admin panel')
288
289
289 def step_10(self):
290 def step_10(self):
290 pass
291 pass
291
292
293 def step_11(self):
294 self.klass.update_repo_info()
295
292 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
296 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
293
297
294 # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
298 # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
295 _step = None
299 _step = None
296 for step in upgrade_steps:
300 for step in upgrade_steps:
297 notify('performing upgrade step %s' % step)
301 notify('performing upgrade step %s' % step)
298 getattr(UpgradeSteps(self), 'step_%s' % step)()
302 getattr(UpgradeSteps(self), 'step_%s' % step)()
299 self.sa.commit()
303 self.sa.commit()
300 _step = step
304 _step = step
301
305
302 notify('upgrade to version %s successful' % _step)
306 notify('upgrade to version %s successful' % _step)
303
307
304 def fix_repo_paths(self):
308 def fix_repo_paths(self):
305 """
309 """
306 Fixes a old rhodecode version path into new one without a '*'
310 Fixes a old rhodecode version path into new one without a '*'
307 """
311 """
308
312
309 paths = self.sa.query(RhodeCodeUi)\
313 paths = self.sa.query(RhodeCodeUi)\
310 .filter(RhodeCodeUi.ui_key == '/')\
314 .filter(RhodeCodeUi.ui_key == '/')\
311 .scalar()
315 .scalar()
312
316
313 paths.ui_value = paths.ui_value.replace('*', '')
317 paths.ui_value = paths.ui_value.replace('*', '')
314
318
315 try:
319 try:
316 self.sa.add(paths)
320 self.sa.add(paths)
317 self.sa.commit()
321 self.sa.commit()
318 except:
322 except:
319 self.sa.rollback()
323 self.sa.rollback()
320 raise
324 raise
321
325
322 def fix_default_user(self):
326 def fix_default_user(self):
323 """
327 """
324 Fixes a old default user with some 'nicer' default values,
328 Fixes a old default user with some 'nicer' default values,
325 used mostly for anonymous access
329 used mostly for anonymous access
326 """
330 """
327 def_user = self.sa.query(User)\
331 def_user = self.sa.query(User)\
328 .filter(User.username == 'default')\
332 .filter(User.username == 'default')\
329 .one()
333 .one()
330
334
331 def_user.name = 'Anonymous'
335 def_user.name = 'Anonymous'
332 def_user.lastname = 'User'
336 def_user.lastname = 'User'
333 def_user.email = 'anonymous@rhodecode.org'
337 def_user.email = 'anonymous@rhodecode.org'
334
338
335 try:
339 try:
336 self.sa.add(def_user)
340 self.sa.add(def_user)
337 self.sa.commit()
341 self.sa.commit()
338 except:
342 except:
339 self.sa.rollback()
343 self.sa.rollback()
340 raise
344 raise
341
345
342 def fix_settings(self):
346 def fix_settings(self):
343 """
347 """
344 Fixes rhodecode settings adds ga_code key for google analytics
348 Fixes rhodecode settings adds ga_code key for google analytics
345 """
349 """
346
350
347 hgsettings3 = RhodeCodeSetting('ga_code', '')
351 hgsettings3 = RhodeCodeSetting('ga_code', '')
348
352
349 try:
353 try:
350 self.sa.add(hgsettings3)
354 self.sa.add(hgsettings3)
351 self.sa.commit()
355 self.sa.commit()
352 except:
356 except:
353 self.sa.rollback()
357 self.sa.rollback()
354 raise
358 raise
355
359
356 def admin_prompt(self, second=False):
360 def admin_prompt(self, second=False):
357 if not self.tests:
361 if not self.tests:
358 import getpass
362 import getpass
359
363
360 # defaults
364 # defaults
361 defaults = self.cli_args
365 defaults = self.cli_args
362 username = defaults.get('username')
366 username = defaults.get('username')
363 password = defaults.get('password')
367 password = defaults.get('password')
364 email = defaults.get('email')
368 email = defaults.get('email')
365
369
366 def get_password():
370 def get_password():
367 password = getpass.getpass('Specify admin password '
371 password = getpass.getpass('Specify admin password '
368 '(min 6 chars):')
372 '(min 6 chars):')
369 confirm = getpass.getpass('Confirm password:')
373 confirm = getpass.getpass('Confirm password:')
370
374
371 if password != confirm:
375 if password != confirm:
372 log.error('passwords mismatch')
376 log.error('passwords mismatch')
373 return False
377 return False
374 if len(password) < 6:
378 if len(password) < 6:
375 log.error('password is to short use at least 6 characters')
379 log.error('password is to short use at least 6 characters')
376 return False
380 return False
377
381
378 return password
382 return password
379 if username is None:
383 if username is None:
380 username = raw_input('Specify admin username:')
384 username = raw_input('Specify admin username:')
381 if password is None:
385 if password is None:
382 password = get_password()
386 password = get_password()
383 if not password:
387 if not password:
384 #second try
388 #second try
385 password = get_password()
389 password = get_password()
386 if not password:
390 if not password:
387 sys.exit()
391 sys.exit()
388 if email is None:
392 if email is None:
389 email = raw_input('Specify admin email:')
393 email = raw_input('Specify admin email:')
390 self.create_user(username, password, email, True)
394 self.create_user(username, password, email, True)
391 else:
395 else:
392 log.info('creating admin and regular test users')
396 log.info('creating admin and regular test users')
393 from rhodecode.tests import TEST_USER_ADMIN_LOGIN, \
397 from rhodecode.tests import TEST_USER_ADMIN_LOGIN, \
394 TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \
398 TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \
395 TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \
399 TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \
396 TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \
400 TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \
397 TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL
401 TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL
398
402
399 self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS,
403 self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS,
400 TEST_USER_ADMIN_EMAIL, True)
404 TEST_USER_ADMIN_EMAIL, True)
401
405
402 self.create_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,
406 self.create_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,
403 TEST_USER_REGULAR_EMAIL, False)
407 TEST_USER_REGULAR_EMAIL, False)
404
408
405 self.create_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS,
409 self.create_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS,
406 TEST_USER_REGULAR2_EMAIL, False)
410 TEST_USER_REGULAR2_EMAIL, False)
407
411
408 def create_ui_settings(self):
412 def create_ui_settings(self):
409 """
413 """
410 Creates ui settings, fills out hooks
414 Creates ui settings, fills out hooks
411 and disables dotencode
415 and disables dotencode
412 """
416 """
413
417
414 #HOOKS
418 #HOOKS
415 hooks1_key = RhodeCodeUi.HOOK_UPDATE
419 hooks1_key = RhodeCodeUi.HOOK_UPDATE
416 hooks1_ = self.sa.query(RhodeCodeUi)\
420 hooks1_ = self.sa.query(RhodeCodeUi)\
417 .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()
421 .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()
418
422
419 hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_
423 hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_
420 hooks1.ui_section = 'hooks'
424 hooks1.ui_section = 'hooks'
421 hooks1.ui_key = hooks1_key
425 hooks1.ui_key = hooks1_key
422 hooks1.ui_value = 'hg update >&2'
426 hooks1.ui_value = 'hg update >&2'
423 hooks1.ui_active = False
427 hooks1.ui_active = False
424 self.sa.add(hooks1)
428 self.sa.add(hooks1)
425
429
426 hooks2_key = RhodeCodeUi.HOOK_REPO_SIZE
430 hooks2_key = RhodeCodeUi.HOOK_REPO_SIZE
427 hooks2_ = self.sa.query(RhodeCodeUi)\
431 hooks2_ = self.sa.query(RhodeCodeUi)\
428 .filter(RhodeCodeUi.ui_key == hooks2_key).scalar()
432 .filter(RhodeCodeUi.ui_key == hooks2_key).scalar()
429 hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_
433 hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_
430 hooks2.ui_section = 'hooks'
434 hooks2.ui_section = 'hooks'
431 hooks2.ui_key = hooks2_key
435 hooks2.ui_key = hooks2_key
432 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
436 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
433 self.sa.add(hooks2)
437 self.sa.add(hooks2)
434
438
435 hooks3 = RhodeCodeUi()
439 hooks3 = RhodeCodeUi()
436 hooks3.ui_section = 'hooks'
440 hooks3.ui_section = 'hooks'
437 hooks3.ui_key = RhodeCodeUi.HOOK_PUSH
441 hooks3.ui_key = RhodeCodeUi.HOOK_PUSH
438 hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
442 hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
439 self.sa.add(hooks3)
443 self.sa.add(hooks3)
440
444
441 hooks4 = RhodeCodeUi()
445 hooks4 = RhodeCodeUi()
442 hooks4.ui_section = 'hooks'
446 hooks4.ui_section = 'hooks'
443 hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH
447 hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH
444 hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push'
448 hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push'
445 self.sa.add(hooks4)
449 self.sa.add(hooks4)
446
450
447 hooks5 = RhodeCodeUi()
451 hooks5 = RhodeCodeUi()
448 hooks5.ui_section = 'hooks'
452 hooks5.ui_section = 'hooks'
449 hooks5.ui_key = RhodeCodeUi.HOOK_PULL
453 hooks5.ui_key = RhodeCodeUi.HOOK_PULL
450 hooks5.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
454 hooks5.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
451 self.sa.add(hooks5)
455 self.sa.add(hooks5)
452
456
453 hooks6 = RhodeCodeUi()
457 hooks6 = RhodeCodeUi()
454 hooks6.ui_section = 'hooks'
458 hooks6.ui_section = 'hooks'
455 hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL
459 hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL
456 hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull'
460 hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull'
457 self.sa.add(hooks6)
461 self.sa.add(hooks6)
458
462
459 # enable largefiles
463 # enable largefiles
460 largefiles = RhodeCodeUi()
464 largefiles = RhodeCodeUi()
461 largefiles.ui_section = 'extensions'
465 largefiles.ui_section = 'extensions'
462 largefiles.ui_key = 'largefiles'
466 largefiles.ui_key = 'largefiles'
463 largefiles.ui_value = ''
467 largefiles.ui_value = ''
464 self.sa.add(largefiles)
468 self.sa.add(largefiles)
465
469
466 # enable hgsubversion disabled by default
470 # enable hgsubversion disabled by default
467 hgsubversion = RhodeCodeUi()
471 hgsubversion = RhodeCodeUi()
468 hgsubversion.ui_section = 'extensions'
472 hgsubversion.ui_section = 'extensions'
469 hgsubversion.ui_key = 'hgsubversion'
473 hgsubversion.ui_key = 'hgsubversion'
470 hgsubversion.ui_value = ''
474 hgsubversion.ui_value = ''
471 hgsubversion.ui_active = False
475 hgsubversion.ui_active = False
472 self.sa.add(hgsubversion)
476 self.sa.add(hgsubversion)
473
477
474 # enable hggit disabled by default
478 # enable hggit disabled by default
475 hggit = RhodeCodeUi()
479 hggit = RhodeCodeUi()
476 hggit.ui_section = 'extensions'
480 hggit.ui_section = 'extensions'
477 hggit.ui_key = 'hggit'
481 hggit.ui_key = 'hggit'
478 hggit.ui_value = ''
482 hggit.ui_value = ''
479 hggit.ui_active = False
483 hggit.ui_active = False
480 self.sa.add(hggit)
484 self.sa.add(hggit)
481
485
482 def create_ldap_options(self, skip_existing=False):
486 def create_ldap_options(self, skip_existing=False):
483 """Creates ldap settings"""
487 """Creates ldap settings"""
484
488
485 for k, v in [('ldap_active', 'false'), ('ldap_host', ''),
489 for k, v in [('ldap_active', 'false'), ('ldap_host', ''),
486 ('ldap_port', '389'), ('ldap_tls_kind', 'PLAIN'),
490 ('ldap_port', '389'), ('ldap_tls_kind', 'PLAIN'),
487 ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''),
491 ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''),
488 ('ldap_dn_pass', ''), ('ldap_base_dn', ''),
492 ('ldap_dn_pass', ''), ('ldap_base_dn', ''),
489 ('ldap_filter', ''), ('ldap_search_scope', ''),
493 ('ldap_filter', ''), ('ldap_search_scope', ''),
490 ('ldap_attr_login', ''), ('ldap_attr_firstname', ''),
494 ('ldap_attr_login', ''), ('ldap_attr_firstname', ''),
491 ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]:
495 ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]:
492
496
493 if skip_existing and RhodeCodeSetting.get_by_name(k) != None:
497 if skip_existing and RhodeCodeSetting.get_by_name(k) != None:
494 log.debug('Skipping option %s' % k)
498 log.debug('Skipping option %s' % k)
495 continue
499 continue
496 setting = RhodeCodeSetting(k, v)
500 setting = RhodeCodeSetting(k, v)
497 self.sa.add(setting)
501 self.sa.add(setting)
498
502
499 def create_default_options(self, skip_existing=False):
503 def create_default_options(self, skip_existing=False):
500 """Creates default settings"""
504 """Creates default settings"""
501
505
502 for k, v in [
506 for k, v in [
503 ('default_repo_enable_locking', False),
507 ('default_repo_enable_locking', False),
504 ('default_repo_enable_downloads', False),
508 ('default_repo_enable_downloads', False),
505 ('default_repo_enable_statistics', False),
509 ('default_repo_enable_statistics', False),
506 ('default_repo_private', False),
510 ('default_repo_private', False),
507 ('default_repo_type', 'hg')]:
511 ('default_repo_type', 'hg')]:
508
512
509 if skip_existing and RhodeCodeSetting.get_by_name(k) != None:
513 if skip_existing and RhodeCodeSetting.get_by_name(k) != None:
510 log.debug('Skipping option %s' % k)
514 log.debug('Skipping option %s' % k)
511 continue
515 continue
512 setting = RhodeCodeSetting(k, v)
516 setting = RhodeCodeSetting(k, v)
513 self.sa.add(setting)
517 self.sa.add(setting)
514
518
515 def fixup_groups(self):
519 def fixup_groups(self):
516 def_usr = User.get_by_username('default')
520 def_usr = User.get_by_username('default')
517 for g in RepoGroup.query().all():
521 for g in RepoGroup.query().all():
518 g.group_name = g.get_new_name(g.name)
522 g.group_name = g.get_new_name(g.name)
519 self.sa.add(g)
523 self.sa.add(g)
520 # get default perm
524 # get default perm
521 default = UserRepoGroupToPerm.query()\
525 default = UserRepoGroupToPerm.query()\
522 .filter(UserRepoGroupToPerm.group == g)\
526 .filter(UserRepoGroupToPerm.group == g)\
523 .filter(UserRepoGroupToPerm.user == def_usr)\
527 .filter(UserRepoGroupToPerm.user == def_usr)\
524 .scalar()
528 .scalar()
525
529
526 if default is None:
530 if default is None:
527 log.debug('missing default permission for group %s adding' % g)
531 log.debug('missing default permission for group %s adding' % g)
528 ReposGroupModel()._create_default_perms(g)
532 ReposGroupModel()._create_default_perms(g)
529
533
530 def reset_permissions(self, username):
534 def reset_permissions(self, username):
531 """
535 """
532 Resets permissions to default state, usefull when old systems had
536 Resets permissions to default state, usefull when old systems had
533 bad permissions, we must clean them up
537 bad permissions, we must clean them up
534
538
535 :param username:
539 :param username:
536 :type username:
540 :type username:
537 """
541 """
538 default_user = User.get_by_username(username)
542 default_user = User.get_by_username(username)
539 if not default_user:
543 if not default_user:
540 return
544 return
541
545
542 u2p = UserToPerm.query()\
546 u2p = UserToPerm.query()\
543 .filter(UserToPerm.user == default_user).all()
547 .filter(UserToPerm.user == default_user).all()
544 fixed = False
548 fixed = False
545 if len(u2p) != len(User.DEFAULT_PERMISSIONS):
549 if len(u2p) != len(User.DEFAULT_PERMISSIONS):
546 for p in u2p:
550 for p in u2p:
547 Session().delete(p)
551 Session().delete(p)
548 fixed = True
552 fixed = True
549 self.populate_default_permissions()
553 self.populate_default_permissions()
550 return fixed
554 return fixed
551
555
556 def update_repo_info(self):
557 RepoModel.update_repoinfo()
558
552 def config_prompt(self, test_repo_path='', retries=3):
559 def config_prompt(self, test_repo_path='', retries=3):
553 defaults = self.cli_args
560 defaults = self.cli_args
554 _path = defaults.get('repos_location')
561 _path = defaults.get('repos_location')
555 if retries == 3:
562 if retries == 3:
556 log.info('Setting up repositories config')
563 log.info('Setting up repositories config')
557
564
558 if _path is not None:
565 if _path is not None:
559 path = _path
566 path = _path
560 elif not self.tests and not test_repo_path:
567 elif not self.tests and not test_repo_path:
561 path = raw_input(
568 path = raw_input(
562 'Enter a valid absolute path to store repositories. '
569 'Enter a valid absolute path to store repositories. '
563 'All repositories in that path will be added automatically:'
570 'All repositories in that path will be added automatically:'
564 )
571 )
565 else:
572 else:
566 path = test_repo_path
573 path = test_repo_path
567 path_ok = True
574 path_ok = True
568
575
569 # check proper dir
576 # check proper dir
570 if not os.path.isdir(path):
577 if not os.path.isdir(path):
571 path_ok = False
578 path_ok = False
572 log.error('Given path %s is not a valid directory' % path)
579 log.error('Given path %s is not a valid directory' % path)
573
580
574 elif not os.path.isabs(path):
581 elif not os.path.isabs(path):
575 path_ok = False
582 path_ok = False
576 log.error('Given path %s is not an absolute path' % path)
583 log.error('Given path %s is not an absolute path' % path)
577
584
578 # check write access
585 # check write access
579 elif not os.access(path, os.W_OK) and path_ok:
586 elif not os.access(path, os.W_OK) and path_ok:
580 path_ok = False
587 path_ok = False
581 log.error('No write permission to given path %s' % path)
588 log.error('No write permission to given path %s' % path)
582
589
583 if retries == 0:
590 if retries == 0:
584 sys.exit('max retries reached')
591 sys.exit('max retries reached')
585 if path_ok is False:
592 if path_ok is False:
586 retries -= 1
593 retries -= 1
587 return self.config_prompt(test_repo_path, retries)
594 return self.config_prompt(test_repo_path, retries)
588
595
589 real_path = os.path.normpath(os.path.realpath(path))
596 real_path = os.path.normpath(os.path.realpath(path))
590
597
591 if real_path != os.path.normpath(path):
598 if real_path != os.path.normpath(path):
592 if not ask_ok(('Path looks like a symlink, Rhodecode will store '
599 if not ask_ok(('Path looks like a symlink, Rhodecode will store '
593 'given path as %s ? [y/n]') % (real_path)):
600 'given path as %s ? [y/n]') % (real_path)):
594 log.error('Canceled by user')
601 log.error('Canceled by user')
595 sys.exit(-1)
602 sys.exit(-1)
596
603
597 return real_path
604 return real_path
598
605
599 def create_settings(self, path):
606 def create_settings(self, path):
600
607
601 self.create_ui_settings()
608 self.create_ui_settings()
602
609
603 #HG UI OPTIONS
610 #HG UI OPTIONS
604 web1 = RhodeCodeUi()
611 web1 = RhodeCodeUi()
605 web1.ui_section = 'web'
612 web1.ui_section = 'web'
606 web1.ui_key = 'push_ssl'
613 web1.ui_key = 'push_ssl'
607 web1.ui_value = 'false'
614 web1.ui_value = 'false'
608
615
609 web2 = RhodeCodeUi()
616 web2 = RhodeCodeUi()
610 web2.ui_section = 'web'
617 web2.ui_section = 'web'
611 web2.ui_key = 'allow_archive'
618 web2.ui_key = 'allow_archive'
612 web2.ui_value = 'gz zip bz2'
619 web2.ui_value = 'gz zip bz2'
613
620
614 web3 = RhodeCodeUi()
621 web3 = RhodeCodeUi()
615 web3.ui_section = 'web'
622 web3.ui_section = 'web'
616 web3.ui_key = 'allow_push'
623 web3.ui_key = 'allow_push'
617 web3.ui_value = '*'
624 web3.ui_value = '*'
618
625
619 web4 = RhodeCodeUi()
626 web4 = RhodeCodeUi()
620 web4.ui_section = 'web'
627 web4.ui_section = 'web'
621 web4.ui_key = 'baseurl'
628 web4.ui_key = 'baseurl'
622 web4.ui_value = '/'
629 web4.ui_value = '/'
623
630
624 paths = RhodeCodeUi()
631 paths = RhodeCodeUi()
625 paths.ui_section = 'paths'
632 paths.ui_section = 'paths'
626 paths.ui_key = '/'
633 paths.ui_key = '/'
627 paths.ui_value = path
634 paths.ui_value = path
628
635
629 phases = RhodeCodeUi()
636 phases = RhodeCodeUi()
630 phases.ui_section = 'phases'
637 phases.ui_section = 'phases'
631 phases.ui_key = 'publish'
638 phases.ui_key = 'publish'
632 phases.ui_value = False
639 phases.ui_value = False
633
640
634 sett1 = RhodeCodeSetting('realm', 'RhodeCode authentication')
641 sett1 = RhodeCodeSetting('realm', 'RhodeCode authentication')
635 sett2 = RhodeCodeSetting('title', 'RhodeCode')
642 sett2 = RhodeCodeSetting('title', 'RhodeCode')
636 sett3 = RhodeCodeSetting('ga_code', '')
643 sett3 = RhodeCodeSetting('ga_code', '')
637
644
638 sett4 = RhodeCodeSetting('show_public_icon', True)
645 sett4 = RhodeCodeSetting('show_public_icon', True)
639 sett5 = RhodeCodeSetting('show_private_icon', True)
646 sett5 = RhodeCodeSetting('show_private_icon', True)
640 sett6 = RhodeCodeSetting('stylify_metatags', False)
647 sett6 = RhodeCodeSetting('stylify_metatags', False)
641
648
642 self.sa.add(web1)
649 self.sa.add(web1)
643 self.sa.add(web2)
650 self.sa.add(web2)
644 self.sa.add(web3)
651 self.sa.add(web3)
645 self.sa.add(web4)
652 self.sa.add(web4)
646 self.sa.add(paths)
653 self.sa.add(paths)
647 self.sa.add(sett1)
654 self.sa.add(sett1)
648 self.sa.add(sett2)
655 self.sa.add(sett2)
649 self.sa.add(sett3)
656 self.sa.add(sett3)
650 self.sa.add(sett4)
657 self.sa.add(sett4)
651 self.sa.add(sett5)
658 self.sa.add(sett5)
652 self.sa.add(sett6)
659 self.sa.add(sett6)
653
660
654 self.create_ldap_options()
661 self.create_ldap_options()
655 self.create_default_options()
662 self.create_default_options()
656
663
657 log.info('created ui config')
664 log.info('created ui config')
658
665
659 def create_user(self, username, password, email='', admin=False):
666 def create_user(self, username, password, email='', admin=False):
660 log.info('creating user %s' % username)
667 log.info('creating user %s' % username)
661 UserModel().create_or_update(username, password, email,
668 UserModel().create_or_update(username, password, email,
662 firstname='RhodeCode', lastname='Admin',
669 firstname='RhodeCode', lastname='Admin',
663 active=True, admin=admin)
670 active=True, admin=admin)
664
671
665 def create_default_user(self):
672 def create_default_user(self):
666 log.info('creating default user')
673 log.info('creating default user')
667 # create default user for handling default permissions.
674 # create default user for handling default permissions.
668 UserModel().create_or_update(username='default',
675 UserModel().create_or_update(username='default',
669 password=str(uuid.uuid1())[:8],
676 password=str(uuid.uuid1())[:8],
670 email='anonymous@rhodecode.org',
677 email='anonymous@rhodecode.org',
671 firstname='Anonymous', lastname='User')
678 firstname='Anonymous', lastname='User')
672
679
673 def create_permissions(self):
680 def create_permissions(self):
674 # module.(access|create|change|delete)_[name]
681 # module.(access|create|change|delete)_[name]
675 # module.(none|read|write|admin)
682 # module.(none|read|write|admin)
676
683
677 for p in Permission.PERMS:
684 for p in Permission.PERMS:
678 if not Permission.get_by_key(p[0]):
685 if not Permission.get_by_key(p[0]):
679 new_perm = Permission()
686 new_perm = Permission()
680 new_perm.permission_name = p[0]
687 new_perm.permission_name = p[0]
681 new_perm.permission_longname = p[0]
688 new_perm.permission_longname = p[0]
682 self.sa.add(new_perm)
689 self.sa.add(new_perm)
683
690
684 def populate_default_permissions(self):
691 def populate_default_permissions(self):
685 log.info('creating default user permissions')
692 log.info('creating default user permissions')
686
693
687 default_user = User.get_by_username('default')
694 default_user = User.get_by_username('default')
688
695
689 for def_perm in User.DEFAULT_PERMISSIONS:
696 for def_perm in User.DEFAULT_PERMISSIONS:
690
697
691 perm = self.sa.query(Permission)\
698 perm = self.sa.query(Permission)\
692 .filter(Permission.permission_name == def_perm)\
699 .filter(Permission.permission_name == def_perm)\
693 .scalar()
700 .scalar()
694 if not perm:
701 if not perm:
695 raise Exception(
702 raise Exception(
696 'CRITICAL: permission %s not found inside database !!'
703 'CRITICAL: permission %s not found inside database !!'
697 % def_perm
704 % def_perm
698 )
705 )
699 if not UserToPerm.query()\
706 if not UserToPerm.query()\
700 .filter(UserToPerm.permission == perm)\
707 .filter(UserToPerm.permission == perm)\
701 .filter(UserToPerm.user == default_user).scalar():
708 .filter(UserToPerm.user == default_user).scalar():
702 reg_perm = UserToPerm()
709 reg_perm = UserToPerm()
703 reg_perm.user = default_user
710 reg_perm.user = default_user
704 reg_perm.permission = perm
711 reg_perm.permission = perm
705 self.sa.add(reg_perm)
712 self.sa.add(reg_perm)
706
713
707 @staticmethod
714 @staticmethod
708 def check_waitress():
715 def check_waitress():
709 """
716 """
710 Function executed at the end of setup
717 Function executed at the end of setup
711 """
718 """
712 if not __py_version__ >= (2, 6):
719 if not __py_version__ >= (2, 6):
713 notify('Python2.5 detected, please switch '
720 notify('Python2.5 detected, please switch '
714 'egg:waitress#main -> egg:Paste#http '
721 'egg:waitress#main -> egg:Paste#http '
715 'in your .ini file')
722 'in your .ini file')
@@ -1,87 +1,87 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 package.rhodecode.lib.cleanup
3 package.rhodecode.lib.cleanup
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 :created_on: Jul 14, 2012
6 :created_on: Jul 14, 2012
7 :author: marcink
7 :author: marcink
8 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
8 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
9 :license: GPLv3, see COPYING for more details.
9 :license: GPLv3, see COPYING for more details.
10 """
10 """
11 # This program is free software: you can redistribute it and/or modify
11 # This program is free software: you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation, either version 3 of the License, or
13 # the Free Software Foundation, either version 3 of the License, or
14 # (at your option) any later version.
14 # (at your option) any later version.
15 #
15 #
16 # This program is distributed in the hope that it will be useful,
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
19 # GNU General Public License for more details.
20 #
20 #
21 # You should have received a copy of the GNU General Public License
21 # You should have received a copy of the GNU General Public License
22 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 from __future__ import with_statement
23 from __future__ import with_statement
24
24
25 import os
25 import os
26 import sys
26 import sys
27 import re
27 import re
28 import shutil
28 import shutil
29 import logging
29 import logging
30 import datetime
30 import datetime
31 import string
31 import string
32
32
33 from os.path import dirname as dn, join as jn
33 from os.path import dirname as dn, join as jn
34 from rhodecode.model import init_model
34 from rhodecode.model import init_model
35 from rhodecode.lib.utils2 import engine_from_config, safe_str
35 from rhodecode.lib.utils2 import engine_from_config
36 from rhodecode.model.db import RhodeCodeUi, Repository
36 from rhodecode.model.db import Repository
37 from rhodecode.lib.vcs.backends.base import EmptyChangeset
37 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.meta import Session
38
39
39
40
40 #to get the rhodecode import
41 #to get the rhodecode import
41 sys.path.append(dn(dn(dn(os.path.realpath(__file__)))))
42 sys.path.append(dn(dn(dn(os.path.realpath(__file__)))))
42
43
43 from rhodecode.lib.utils import BasePasterCommand, Command, add_cache
44 from rhodecode.lib.utils import BasePasterCommand, Command, add_cache
44
45
45 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
46
47
47
48
48 class UpdateCommand(BasePasterCommand):
49 class UpdateCommand(BasePasterCommand):
49
50
50 max_args = 1
51 max_args = 1
51 min_args = 1
52 min_args = 1
52
53
53 usage = "CONFIG_FILE"
54 usage = "CONFIG_FILE"
54 summary = "Cleanup deleted repos"
55 summary = "Cleanup deleted repos"
55 group_name = "RhodeCode"
56 group_name = "RhodeCode"
56 takes_config_file = -1
57 takes_config_file = -1
57 parser = Command.standard_parser(verbose=True)
58 parser = Command.standard_parser(verbose=True)
58
59
59 def command(self):
60 def command(self):
60 logging.config.fileConfig(self.path_to_ini_file)
61 logging.config.fileConfig(self.path_to_ini_file)
61 from pylons import config
62 from pylons import config
62
63
63 #get to remove repos !!
64 #get to remove repos !!
64 add_cache(config)
65 add_cache(config)
65 engine = engine_from_config(config, 'sqlalchemy.db1.')
66 engine = engine_from_config(config, 'sqlalchemy.db1.')
66 init_model(engine)
67 init_model(engine)
67
68
68 repo_update_list = map(string.strip,
69 repo_update_list = map(string.strip,
69 self.options.repo_update_list.split(',')) \
70 self.options.repo_update_list.split(',')) \
70 if self.options.repo_update_list else None
71 if self.options.repo_update_list else None
71
72
72 if repo_update_list:
73 if repo_update_list:
73 repo_list = Repository.query().filter(Repository.repo_name.in_(repo_update_list))
74 repo_list = Repository.query()\
75 .filter(Repository.repo_name.in_(repo_update_list))
74 else:
76 else:
75 repo_list = Repository.getAll()
77 repo_list = Repository.getAll()
76 for repo in repo_list:
78 RepoModel.update_repoinfo(repositories=repo_list)
77 last_cs = (repo.scm_instance.get_changeset() if repo.scm_instance
79 Session().commit()
78 else EmptyChangeset())
79 repo.update_changeset_cache(last_cs)
80
80
81 def update_parser(self):
81 def update_parser(self):
82 self.parser.add_option('--update-only',
82 self.parser.add_option('--update-only',
83 action='store',
83 action='store',
84 dest='repo_update_list',
84 dest='repo_update_list',
85 help="Specifies a comma separated list of repositores "
85 help="Specifies a comma separated list of repositores "
86 "to update last commit info for. OPTIONAL",
86 "to update last commit info for. OPTIONAL",
87 )
87 )
@@ -1,693 +1,705 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.repo
3 rhodecode.model.repo
4 ~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~
5
5
6 Repository model for rhodecode
6 Repository model for rhodecode
7
7
8 :created_on: Jun 5, 2010
8 :created_on: Jun 5, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 from __future__ import with_statement
25 from __future__ import with_statement
26 import os
26 import os
27 import shutil
27 import shutil
28 import logging
28 import logging
29 import traceback
29 import traceback
30 from datetime import datetime
30 from datetime import datetime
31
31
32 from rhodecode.lib.vcs.backends import get_backend
32 from rhodecode.lib.vcs.backends import get_backend
33 from rhodecode.lib.compat import json
33 from rhodecode.lib.compat import json
34 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode,\
34 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode,\
35 remove_prefix
35 remove_prefix
36 from rhodecode.lib.caching_query import FromCache
36 from rhodecode.lib.caching_query import FromCache
37 from rhodecode.lib.hooks import log_create_repository, log_delete_repository
37 from rhodecode.lib.hooks import log_create_repository, log_delete_repository
38
38
39 from rhodecode.model import BaseModel
39 from rhodecode.model import BaseModel
40 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
40 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
41 Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup,\
41 Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup,\
42 RhodeCodeSetting, RepositoryField
42 RhodeCodeSetting, RepositoryField
43 from rhodecode.lib import helpers as h
43 from rhodecode.lib import helpers as h
44 from rhodecode.lib.auth import HasRepoPermissionAny
44 from rhodecode.lib.auth import HasRepoPermissionAny
45 from rhodecode.lib.vcs.backends.base import EmptyChangeset
45
46
46
47
47 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
48
49
49
50
50 class RepoModel(BaseModel):
51 class RepoModel(BaseModel):
51
52
52 cls = Repository
53 cls = Repository
53 URL_SEPARATOR = Repository.url_sep()
54 URL_SEPARATOR = Repository.url_sep()
54
55
55 def __get_users_group(self, users_group):
56 def __get_users_group(self, users_group):
56 return self._get_instance(UsersGroup, users_group,
57 return self._get_instance(UsersGroup, users_group,
57 callback=UsersGroup.get_by_group_name)
58 callback=UsersGroup.get_by_group_name)
58
59
59 def _get_repos_group(self, repos_group):
60 def _get_repos_group(self, repos_group):
60 return self._get_instance(RepoGroup, repos_group,
61 return self._get_instance(RepoGroup, repos_group,
61 callback=RepoGroup.get_by_group_name)
62 callback=RepoGroup.get_by_group_name)
62
63
63 @LazyProperty
64 @LazyProperty
64 def repos_path(self):
65 def repos_path(self):
65 """
66 """
66 Get's the repositories root path from database
67 Get's the repositories root path from database
67 """
68 """
68
69
69 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
70 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
70 return q.ui_value
71 return q.ui_value
71
72
72 def get(self, repo_id, cache=False):
73 def get(self, repo_id, cache=False):
73 repo = self.sa.query(Repository)\
74 repo = self.sa.query(Repository)\
74 .filter(Repository.repo_id == repo_id)
75 .filter(Repository.repo_id == repo_id)
75
76
76 if cache:
77 if cache:
77 repo = repo.options(FromCache("sql_cache_short",
78 repo = repo.options(FromCache("sql_cache_short",
78 "get_repo_%s" % repo_id))
79 "get_repo_%s" % repo_id))
79 return repo.scalar()
80 return repo.scalar()
80
81
81 def get_repo(self, repository):
82 def get_repo(self, repository):
82 return self._get_repo(repository)
83 return self._get_repo(repository)
83
84
84 def get_by_repo_name(self, repo_name, cache=False):
85 def get_by_repo_name(self, repo_name, cache=False):
85 repo = self.sa.query(Repository)\
86 repo = self.sa.query(Repository)\
86 .filter(Repository.repo_name == repo_name)
87 .filter(Repository.repo_name == repo_name)
87
88
88 if cache:
89 if cache:
89 repo = repo.options(FromCache("sql_cache_short",
90 repo = repo.options(FromCache("sql_cache_short",
90 "get_repo_%s" % repo_name))
91 "get_repo_%s" % repo_name))
91 return repo.scalar()
92 return repo.scalar()
92
93
93 def get_all_user_repos(self, user):
94 def get_all_user_repos(self, user):
94 """
95 """
95 Get's all repositories that user have at least read access
96 Get's all repositories that user have at least read access
96
97
97 :param user:
98 :param user:
98 :type user:
99 :type user:
99 """
100 """
100 from rhodecode.lib.auth import AuthUser
101 from rhodecode.lib.auth import AuthUser
101 user = self._get_user(user)
102 user = self._get_user(user)
102 repos = AuthUser(user_id=user.user_id).permissions['repositories']
103 repos = AuthUser(user_id=user.user_id).permissions['repositories']
103 access_check = lambda r: r[1] in ['repository.read',
104 access_check = lambda r: r[1] in ['repository.read',
104 'repository.write',
105 'repository.write',
105 'repository.admin']
106 'repository.admin']
106 repos = [x[0] for x in filter(access_check, repos.items())]
107 repos = [x[0] for x in filter(access_check, repos.items())]
107 return Repository.query().filter(Repository.repo_name.in_(repos))
108 return Repository.query().filter(Repository.repo_name.in_(repos))
108
109
109 def get_users_js(self):
110 def get_users_js(self):
110 users = self.sa.query(User).filter(User.active == True).all()
111 users = self.sa.query(User).filter(User.active == True).all()
111 return json.dumps([
112 return json.dumps([
112 {
113 {
113 'id': u.user_id,
114 'id': u.user_id,
114 'fname': u.name,
115 'fname': u.name,
115 'lname': u.lastname,
116 'lname': u.lastname,
116 'nname': u.username,
117 'nname': u.username,
117 'gravatar_lnk': h.gravatar_url(u.email, 14)
118 'gravatar_lnk': h.gravatar_url(u.email, 14)
118 } for u in users]
119 } for u in users]
119 )
120 )
120
121
121 def get_users_groups_js(self):
122 def get_users_groups_js(self):
122 users_groups = self.sa.query(UsersGroup)\
123 users_groups = self.sa.query(UsersGroup)\
123 .filter(UsersGroup.users_group_active == True).all()
124 .filter(UsersGroup.users_group_active == True).all()
124
125
125 return json.dumps([
126 return json.dumps([
126 {
127 {
127 'id': gr.users_group_id,
128 'id': gr.users_group_id,
128 'grname': gr.users_group_name,
129 'grname': gr.users_group_name,
129 'grmembers': len(gr.members),
130 'grmembers': len(gr.members),
130 } for gr in users_groups]
131 } for gr in users_groups]
131 )
132 )
132
133
133 @classmethod
134 @classmethod
134 def _render_datatable(cls, tmpl, *args, **kwargs):
135 def _render_datatable(cls, tmpl, *args, **kwargs):
135 import rhodecode
136 import rhodecode
136 from pylons import tmpl_context as c
137 from pylons import tmpl_context as c
137 from pylons.i18n.translation import _
138 from pylons.i18n.translation import _
138
139
139 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
140 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
140 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
141 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
141
142
142 tmpl = template.get_def(tmpl)
143 tmpl = template.get_def(tmpl)
143 kwargs.update(dict(_=_, h=h, c=c))
144 kwargs.update(dict(_=_, h=h, c=c))
144 return tmpl.render(*args, **kwargs)
145 return tmpl.render(*args, **kwargs)
145
146
147 @classmethod
148 def update_repoinfo(cls, repositories=None):
149 if not repositories:
150 repositories = Repository.getAll()
151 for repo in repositories:
152 scm_repo = repo.scm_instance_no_cache
153 last_cs = EmptyChangeset()
154 if scm_repo:
155 last_cs = scm_repo.get_changeset()
156 repo.update_changeset_cache(last_cs)
157
146 def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
158 def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
147 super_user_actions=False):
159 super_user_actions=False):
148 _render = self._render_datatable
160 _render = self._render_datatable
149
161
150 def quick_menu(repo_name):
162 def quick_menu(repo_name):
151 return _render('quick_menu', repo_name)
163 return _render('quick_menu', repo_name)
152
164
153 def repo_lnk(name, rtype, private, fork_of):
165 def repo_lnk(name, rtype, private, fork_of):
154 return _render('repo_name', name, rtype, private, fork_of,
166 return _render('repo_name', name, rtype, private, fork_of,
155 short_name=not admin, admin=False)
167 short_name=not admin, admin=False)
156
168
157 def last_change(last_change):
169 def last_change(last_change):
158 return _render("last_change", last_change)
170 return _render("last_change", last_change)
159
171
160 def rss_lnk(repo_name):
172 def rss_lnk(repo_name):
161 return _render("rss", repo_name)
173 return _render("rss", repo_name)
162
174
163 def atom_lnk(repo_name):
175 def atom_lnk(repo_name):
164 return _render("atom", repo_name)
176 return _render("atom", repo_name)
165
177
166 def last_rev(repo_name, cs_cache):
178 def last_rev(repo_name, cs_cache):
167 return _render('revision', repo_name, cs_cache.get('revision'),
179 return _render('revision', repo_name, cs_cache.get('revision'),
168 cs_cache.get('raw_id'), cs_cache.get('author'),
180 cs_cache.get('raw_id'), cs_cache.get('author'),
169 cs_cache.get('message'))
181 cs_cache.get('message'))
170
182
171 def desc(desc):
183 def desc(desc):
172 from pylons import tmpl_context as c
184 from pylons import tmpl_context as c
173 if c.visual.stylify_metatags:
185 if c.visual.stylify_metatags:
174 return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
186 return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
175 else:
187 else:
176 return h.urlify_text(h.truncate(desc, 60))
188 return h.urlify_text(h.truncate(desc, 60))
177
189
178 def repo_actions(repo_name):
190 def repo_actions(repo_name):
179 return _render('repo_actions', repo_name, super_user_actions)
191 return _render('repo_actions', repo_name, super_user_actions)
180
192
181 def owner_actions(user_id, username):
193 def owner_actions(user_id, username):
182 return _render('user_name', user_id, username)
194 return _render('user_name', user_id, username)
183
195
184 repos_data = []
196 repos_data = []
185 for repo in repos_list:
197 for repo in repos_list:
186 if perm_check:
198 if perm_check:
187 # check permission at this level
199 # check permission at this level
188 if not HasRepoPermissionAny(
200 if not HasRepoPermissionAny(
189 'repository.read', 'repository.write', 'repository.admin'
201 'repository.read', 'repository.write', 'repository.admin'
190 )(repo.repo_name, 'get_repos_as_dict check'):
202 )(repo.repo_name, 'get_repos_as_dict check'):
191 continue
203 continue
192 cs_cache = repo.changeset_cache
204 cs_cache = repo.changeset_cache
193 row = {
205 row = {
194 "menu": quick_menu(repo.repo_name),
206 "menu": quick_menu(repo.repo_name),
195 "raw_name": repo.repo_name.lower(),
207 "raw_name": repo.repo_name.lower(),
196 "name": repo_lnk(repo.repo_name, repo.repo_type,
208 "name": repo_lnk(repo.repo_name, repo.repo_type,
197 repo.private, repo.fork),
209 repo.private, repo.fork),
198 "last_change": last_change(repo.last_db_change),
210 "last_change": last_change(repo.last_db_change),
199 "last_changeset": last_rev(repo.repo_name, cs_cache),
211 "last_changeset": last_rev(repo.repo_name, cs_cache),
200 "raw_tip": cs_cache.get('revision'),
212 "raw_tip": cs_cache.get('revision'),
201 "desc": desc(repo.description),
213 "desc": desc(repo.description),
202 "owner": h.person(repo.user.username),
214 "owner": h.person(repo.user.username),
203 "rss": rss_lnk(repo.repo_name),
215 "rss": rss_lnk(repo.repo_name),
204 "atom": atom_lnk(repo.repo_name),
216 "atom": atom_lnk(repo.repo_name),
205
217
206 }
218 }
207 if admin:
219 if admin:
208 row.update({
220 row.update({
209 "action": repo_actions(repo.repo_name),
221 "action": repo_actions(repo.repo_name),
210 "owner": owner_actions(repo.user.user_id,
222 "owner": owner_actions(repo.user.user_id,
211 h.person(repo.user.username))
223 h.person(repo.user.username))
212 })
224 })
213 repos_data.append(row)
225 repos_data.append(row)
214
226
215 return {
227 return {
216 "totalRecords": len(repos_list),
228 "totalRecords": len(repos_list),
217 "startIndex": 0,
229 "startIndex": 0,
218 "sort": "name",
230 "sort": "name",
219 "dir": "asc",
231 "dir": "asc",
220 "records": repos_data
232 "records": repos_data
221 }
233 }
222
234
223 def _get_defaults(self, repo_name):
235 def _get_defaults(self, repo_name):
224 """
236 """
225 Get's information about repository, and returns a dict for
237 Get's information about repository, and returns a dict for
226 usage in forms
238 usage in forms
227
239
228 :param repo_name:
240 :param repo_name:
229 """
241 """
230
242
231 repo_info = Repository.get_by_repo_name(repo_name)
243 repo_info = Repository.get_by_repo_name(repo_name)
232
244
233 if repo_info is None:
245 if repo_info is None:
234 return None
246 return None
235
247
236 defaults = repo_info.get_dict()
248 defaults = repo_info.get_dict()
237 group, repo_name = repo_info.groups_and_repo
249 group, repo_name = repo_info.groups_and_repo
238 defaults['repo_name'] = repo_name
250 defaults['repo_name'] = repo_name
239 defaults['repo_group'] = getattr(group[-1] if group else None,
251 defaults['repo_group'] = getattr(group[-1] if group else None,
240 'group_id', None)
252 'group_id', None)
241
253
242 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
254 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
243 (1, 'repo_description'), (1, 'repo_enable_locking'),
255 (1, 'repo_description'), (1, 'repo_enable_locking'),
244 (1, 'repo_landing_rev'), (0, 'clone_uri'),
256 (1, 'repo_landing_rev'), (0, 'clone_uri'),
245 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
257 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
246 attr = k
258 attr = k
247 if strip:
259 if strip:
248 attr = remove_prefix(k, 'repo_')
260 attr = remove_prefix(k, 'repo_')
249
261
250 defaults[k] = defaults[attr]
262 defaults[k] = defaults[attr]
251
263
252 # fill owner
264 # fill owner
253 if repo_info.user:
265 if repo_info.user:
254 defaults.update({'user': repo_info.user.username})
266 defaults.update({'user': repo_info.user.username})
255 else:
267 else:
256 replacement_user = User.query().filter(User.admin ==
268 replacement_user = User.query().filter(User.admin ==
257 True).first().username
269 True).first().username
258 defaults.update({'user': replacement_user})
270 defaults.update({'user': replacement_user})
259
271
260 # fill repository users
272 # fill repository users
261 for p in repo_info.repo_to_perm:
273 for p in repo_info.repo_to_perm:
262 defaults.update({'u_perm_%s' % p.user.username:
274 defaults.update({'u_perm_%s' % p.user.username:
263 p.permission.permission_name})
275 p.permission.permission_name})
264
276
265 # fill repository groups
277 # fill repository groups
266 for p in repo_info.users_group_to_perm:
278 for p in repo_info.users_group_to_perm:
267 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
279 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
268 p.permission.permission_name})
280 p.permission.permission_name})
269
281
270 return defaults
282 return defaults
271
283
272 def update(self, org_repo_name, **kwargs):
284 def update(self, org_repo_name, **kwargs):
273 try:
285 try:
274 cur_repo = self.get_by_repo_name(org_repo_name, cache=False)
286 cur_repo = self.get_by_repo_name(org_repo_name, cache=False)
275
287
276 # update permissions
288 # update permissions
277 for member, perm, member_type in kwargs['perms_updates']:
289 for member, perm, member_type in kwargs['perms_updates']:
278 if member_type == 'user':
290 if member_type == 'user':
279 # this updates existing one
291 # this updates existing one
280 RepoModel().grant_user_permission(
292 RepoModel().grant_user_permission(
281 repo=cur_repo, user=member, perm=perm
293 repo=cur_repo, user=member, perm=perm
282 )
294 )
283 else:
295 else:
284 RepoModel().grant_users_group_permission(
296 RepoModel().grant_users_group_permission(
285 repo=cur_repo, group_name=member, perm=perm
297 repo=cur_repo, group_name=member, perm=perm
286 )
298 )
287 # set new permissions
299 # set new permissions
288 for member, perm, member_type in kwargs['perms_new']:
300 for member, perm, member_type in kwargs['perms_new']:
289 if member_type == 'user':
301 if member_type == 'user':
290 RepoModel().grant_user_permission(
302 RepoModel().grant_user_permission(
291 repo=cur_repo, user=member, perm=perm
303 repo=cur_repo, user=member, perm=perm
292 )
304 )
293 else:
305 else:
294 RepoModel().grant_users_group_permission(
306 RepoModel().grant_users_group_permission(
295 repo=cur_repo, group_name=member, perm=perm
307 repo=cur_repo, group_name=member, perm=perm
296 )
308 )
297
309
298 if 'user' in kwargs:
310 if 'user' in kwargs:
299 cur_repo.user = User.get_by_username(kwargs['user'])
311 cur_repo.user = User.get_by_username(kwargs['user'])
300
312
301 if 'repo_group' in kwargs:
313 if 'repo_group' in kwargs:
302 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
314 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
303
315
304 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
316 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
305 (1, 'repo_description'), (1, 'repo_enable_locking'),
317 (1, 'repo_description'), (1, 'repo_enable_locking'),
306 (1, 'repo_landing_rev'), (0, 'clone_uri'),
318 (1, 'repo_landing_rev'), (0, 'clone_uri'),
307 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
319 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
308 if k in kwargs:
320 if k in kwargs:
309 val = kwargs[k]
321 val = kwargs[k]
310 if strip:
322 if strip:
311 k = remove_prefix(k, 'repo_')
323 k = remove_prefix(k, 'repo_')
312 setattr(cur_repo, k, val)
324 setattr(cur_repo, k, val)
313
325
314 new_name = cur_repo.get_new_name(kwargs['repo_name'])
326 new_name = cur_repo.get_new_name(kwargs['repo_name'])
315 cur_repo.repo_name = new_name
327 cur_repo.repo_name = new_name
316
328
317 #handle extra fields
329 #handle extra fields
318 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
330 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
319 k = RepositoryField.un_prefix_key(field)
331 k = RepositoryField.un_prefix_key(field)
320 ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo)
332 ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo)
321 if ex_field:
333 if ex_field:
322 ex_field.field_value = kwargs[field]
334 ex_field.field_value = kwargs[field]
323 self.sa.add(ex_field)
335 self.sa.add(ex_field)
324 self.sa.add(cur_repo)
336 self.sa.add(cur_repo)
325
337
326 if org_repo_name != new_name:
338 if org_repo_name != new_name:
327 # rename repository
339 # rename repository
328 self.__rename_repo(old=org_repo_name, new=new_name)
340 self.__rename_repo(old=org_repo_name, new=new_name)
329
341
330 return cur_repo
342 return cur_repo
331 except:
343 except:
332 log.error(traceback.format_exc())
344 log.error(traceback.format_exc())
333 raise
345 raise
334
346
335 def create_repo(self, repo_name, repo_type, description, owner,
347 def create_repo(self, repo_name, repo_type, description, owner,
336 private=False, clone_uri=None, repos_group=None,
348 private=False, clone_uri=None, repos_group=None,
337 landing_rev='tip', just_db=False, fork_of=None,
349 landing_rev='tip', just_db=False, fork_of=None,
338 copy_fork_permissions=False, enable_statistics=False,
350 copy_fork_permissions=False, enable_statistics=False,
339 enable_locking=False, enable_downloads=False):
351 enable_locking=False, enable_downloads=False):
340 """
352 """
341 Create repository
353 Create repository
342
354
343 """
355 """
344 from rhodecode.model.scm import ScmModel
356 from rhodecode.model.scm import ScmModel
345
357
346 owner = self._get_user(owner)
358 owner = self._get_user(owner)
347 fork_of = self._get_repo(fork_of)
359 fork_of = self._get_repo(fork_of)
348 repos_group = self._get_repos_group(repos_group)
360 repos_group = self._get_repos_group(repos_group)
349 try:
361 try:
350
362
351 # repo name is just a name of repository
363 # repo name is just a name of repository
352 # while repo_name_full is a full qualified name that is combined
364 # while repo_name_full is a full qualified name that is combined
353 # with name and path of group
365 # with name and path of group
354 repo_name_full = repo_name
366 repo_name_full = repo_name
355 repo_name = repo_name.split(self.URL_SEPARATOR)[-1]
367 repo_name = repo_name.split(self.URL_SEPARATOR)[-1]
356
368
357 new_repo = Repository()
369 new_repo = Repository()
358 new_repo.enable_statistics = False
370 new_repo.enable_statistics = False
359 new_repo.repo_name = repo_name_full
371 new_repo.repo_name = repo_name_full
360 new_repo.repo_type = repo_type
372 new_repo.repo_type = repo_type
361 new_repo.user = owner
373 new_repo.user = owner
362 new_repo.group = repos_group
374 new_repo.group = repos_group
363 new_repo.description = description or repo_name
375 new_repo.description = description or repo_name
364 new_repo.private = private
376 new_repo.private = private
365 new_repo.clone_uri = clone_uri
377 new_repo.clone_uri = clone_uri
366 new_repo.landing_rev = landing_rev
378 new_repo.landing_rev = landing_rev
367
379
368 new_repo.enable_statistics = enable_statistics
380 new_repo.enable_statistics = enable_statistics
369 new_repo.enable_locking = enable_locking
381 new_repo.enable_locking = enable_locking
370 new_repo.enable_downloads = enable_downloads
382 new_repo.enable_downloads = enable_downloads
371
383
372 if repos_group:
384 if repos_group:
373 new_repo.enable_locking = repos_group.enable_locking
385 new_repo.enable_locking = repos_group.enable_locking
374
386
375 if fork_of:
387 if fork_of:
376 parent_repo = fork_of
388 parent_repo = fork_of
377 new_repo.fork = parent_repo
389 new_repo.fork = parent_repo
378
390
379 self.sa.add(new_repo)
391 self.sa.add(new_repo)
380
392
381 def _create_default_perms():
393 def _create_default_perms():
382 # create default permission
394 # create default permission
383 repo_to_perm = UserRepoToPerm()
395 repo_to_perm = UserRepoToPerm()
384 default = 'repository.read'
396 default = 'repository.read'
385 for p in User.get_by_username('default').user_perms:
397 for p in User.get_by_username('default').user_perms:
386 if p.permission.permission_name.startswith('repository.'):
398 if p.permission.permission_name.startswith('repository.'):
387 default = p.permission.permission_name
399 default = p.permission.permission_name
388 break
400 break
389
401
390 default_perm = 'repository.none' if private else default
402 default_perm = 'repository.none' if private else default
391
403
392 repo_to_perm.permission_id = self.sa.query(Permission)\
404 repo_to_perm.permission_id = self.sa.query(Permission)\
393 .filter(Permission.permission_name == default_perm)\
405 .filter(Permission.permission_name == default_perm)\
394 .one().permission_id
406 .one().permission_id
395
407
396 repo_to_perm.repository = new_repo
408 repo_to_perm.repository = new_repo
397 repo_to_perm.user_id = User.get_by_username('default').user_id
409 repo_to_perm.user_id = User.get_by_username('default').user_id
398
410
399 self.sa.add(repo_to_perm)
411 self.sa.add(repo_to_perm)
400
412
401 if fork_of:
413 if fork_of:
402 if copy_fork_permissions:
414 if copy_fork_permissions:
403 repo = fork_of
415 repo = fork_of
404 user_perms = UserRepoToPerm.query()\
416 user_perms = UserRepoToPerm.query()\
405 .filter(UserRepoToPerm.repository == repo).all()
417 .filter(UserRepoToPerm.repository == repo).all()
406 group_perms = UsersGroupRepoToPerm.query()\
418 group_perms = UsersGroupRepoToPerm.query()\
407 .filter(UsersGroupRepoToPerm.repository == repo).all()
419 .filter(UsersGroupRepoToPerm.repository == repo).all()
408
420
409 for perm in user_perms:
421 for perm in user_perms:
410 UserRepoToPerm.create(perm.user, new_repo,
422 UserRepoToPerm.create(perm.user, new_repo,
411 perm.permission)
423 perm.permission)
412
424
413 for perm in group_perms:
425 for perm in group_perms:
414 UsersGroupRepoToPerm.create(perm.users_group, new_repo,
426 UsersGroupRepoToPerm.create(perm.users_group, new_repo,
415 perm.permission)
427 perm.permission)
416 else:
428 else:
417 _create_default_perms()
429 _create_default_perms()
418 else:
430 else:
419 _create_default_perms()
431 _create_default_perms()
420
432
421 if not just_db:
433 if not just_db:
422 self.__create_repo(repo_name, repo_type,
434 self.__create_repo(repo_name, repo_type,
423 repos_group,
435 repos_group,
424 clone_uri)
436 clone_uri)
425 log_create_repository(new_repo.get_dict(),
437 log_create_repository(new_repo.get_dict(),
426 created_by=owner.username)
438 created_by=owner.username)
427
439
428 # now automatically start following this repository as owner
440 # now automatically start following this repository as owner
429 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
441 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
430 owner.user_id)
442 owner.user_id)
431 return new_repo
443 return new_repo
432 except:
444 except:
433 log.error(traceback.format_exc())
445 log.error(traceback.format_exc())
434 raise
446 raise
435
447
436 def create(self, form_data, cur_user, just_db=False, fork=None):
448 def create(self, form_data, cur_user, just_db=False, fork=None):
437 """
449 """
438 Backward compatibility function, just a wrapper on top of create_repo
450 Backward compatibility function, just a wrapper on top of create_repo
439
451
440 :param form_data:
452 :param form_data:
441 :param cur_user:
453 :param cur_user:
442 :param just_db:
454 :param just_db:
443 :param fork:
455 :param fork:
444 """
456 """
445 owner = cur_user
457 owner = cur_user
446 repo_name = form_data['repo_name_full']
458 repo_name = form_data['repo_name_full']
447 repo_type = form_data['repo_type']
459 repo_type = form_data['repo_type']
448 description = form_data['repo_description']
460 description = form_data['repo_description']
449 private = form_data['repo_private']
461 private = form_data['repo_private']
450 clone_uri = form_data.get('clone_uri')
462 clone_uri = form_data.get('clone_uri')
451 repos_group = form_data['repo_group']
463 repos_group = form_data['repo_group']
452 landing_rev = form_data['repo_landing_rev']
464 landing_rev = form_data['repo_landing_rev']
453 copy_fork_permissions = form_data.get('copy_permissions')
465 copy_fork_permissions = form_data.get('copy_permissions')
454 fork_of = form_data.get('fork_parent_id')
466 fork_of = form_data.get('fork_parent_id')
455
467
456 ## repo creation defaults, private and repo_type are filled in form
468 ## repo creation defaults, private and repo_type are filled in form
457 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
469 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
458 enable_statistics = defs.get('repo_enable_statistics')
470 enable_statistics = defs.get('repo_enable_statistics')
459 enable_locking = defs.get('repo_enable_locking')
471 enable_locking = defs.get('repo_enable_locking')
460 enable_downloads = defs.get('repo_enable_downloads')
472 enable_downloads = defs.get('repo_enable_downloads')
461
473
462 return self.create_repo(
474 return self.create_repo(
463 repo_name, repo_type, description, owner, private, clone_uri,
475 repo_name, repo_type, description, owner, private, clone_uri,
464 repos_group, landing_rev, just_db, fork_of, copy_fork_permissions,
476 repos_group, landing_rev, just_db, fork_of, copy_fork_permissions,
465 enable_statistics, enable_locking, enable_downloads
477 enable_statistics, enable_locking, enable_downloads
466 )
478 )
467
479
468 def create_fork(self, form_data, cur_user):
480 def create_fork(self, form_data, cur_user):
469 """
481 """
470 Simple wrapper into executing celery task for fork creation
482 Simple wrapper into executing celery task for fork creation
471
483
472 :param form_data:
484 :param form_data:
473 :param cur_user:
485 :param cur_user:
474 """
486 """
475 from rhodecode.lib.celerylib import tasks, run_task
487 from rhodecode.lib.celerylib import tasks, run_task
476 run_task(tasks.create_repo_fork, form_data, cur_user)
488 run_task(tasks.create_repo_fork, form_data, cur_user)
477
489
478 def delete(self, repo):
490 def delete(self, repo):
479 repo = self._get_repo(repo)
491 repo = self._get_repo(repo)
480 if repo:
492 if repo:
481 old_repo_dict = repo.get_dict()
493 old_repo_dict = repo.get_dict()
482 owner = repo.user
494 owner = repo.user
483 try:
495 try:
484 self.sa.delete(repo)
496 self.sa.delete(repo)
485 self.__delete_repo(repo)
497 self.__delete_repo(repo)
486 log_delete_repository(old_repo_dict,
498 log_delete_repository(old_repo_dict,
487 deleted_by=owner.username)
499 deleted_by=owner.username)
488 except:
500 except:
489 log.error(traceback.format_exc())
501 log.error(traceback.format_exc())
490 raise
502 raise
491
503
492 def grant_user_permission(self, repo, user, perm):
504 def grant_user_permission(self, repo, user, perm):
493 """
505 """
494 Grant permission for user on given repository, or update existing one
506 Grant permission for user on given repository, or update existing one
495 if found
507 if found
496
508
497 :param repo: Instance of Repository, repository_id, or repository name
509 :param repo: Instance of Repository, repository_id, or repository name
498 :param user: Instance of User, user_id or username
510 :param user: Instance of User, user_id or username
499 :param perm: Instance of Permission, or permission_name
511 :param perm: Instance of Permission, or permission_name
500 """
512 """
501 user = self._get_user(user)
513 user = self._get_user(user)
502 repo = self._get_repo(repo)
514 repo = self._get_repo(repo)
503 permission = self._get_perm(perm)
515 permission = self._get_perm(perm)
504
516
505 # check if we have that permission already
517 # check if we have that permission already
506 obj = self.sa.query(UserRepoToPerm)\
518 obj = self.sa.query(UserRepoToPerm)\
507 .filter(UserRepoToPerm.user == user)\
519 .filter(UserRepoToPerm.user == user)\
508 .filter(UserRepoToPerm.repository == repo)\
520 .filter(UserRepoToPerm.repository == repo)\
509 .scalar()
521 .scalar()
510 if obj is None:
522 if obj is None:
511 # create new !
523 # create new !
512 obj = UserRepoToPerm()
524 obj = UserRepoToPerm()
513 obj.repository = repo
525 obj.repository = repo
514 obj.user = user
526 obj.user = user
515 obj.permission = permission
527 obj.permission = permission
516 self.sa.add(obj)
528 self.sa.add(obj)
517 log.debug('Granted perm %s to %s on %s' % (perm, user, repo))
529 log.debug('Granted perm %s to %s on %s' % (perm, user, repo))
518
530
519 def revoke_user_permission(self, repo, user):
531 def revoke_user_permission(self, repo, user):
520 """
532 """
521 Revoke permission for user on given repository
533 Revoke permission for user on given repository
522
534
523 :param repo: Instance of Repository, repository_id, or repository name
535 :param repo: Instance of Repository, repository_id, or repository name
524 :param user: Instance of User, user_id or username
536 :param user: Instance of User, user_id or username
525 """
537 """
526
538
527 user = self._get_user(user)
539 user = self._get_user(user)
528 repo = self._get_repo(repo)
540 repo = self._get_repo(repo)
529
541
530 obj = self.sa.query(UserRepoToPerm)\
542 obj = self.sa.query(UserRepoToPerm)\
531 .filter(UserRepoToPerm.repository == repo)\
543 .filter(UserRepoToPerm.repository == repo)\
532 .filter(UserRepoToPerm.user == user)\
544 .filter(UserRepoToPerm.user == user)\
533 .scalar()
545 .scalar()
534 if obj:
546 if obj:
535 self.sa.delete(obj)
547 self.sa.delete(obj)
536 log.debug('Revoked perm on %s on %s' % (repo, user))
548 log.debug('Revoked perm on %s on %s' % (repo, user))
537
549
538 def grant_users_group_permission(self, repo, group_name, perm):
550 def grant_users_group_permission(self, repo, group_name, perm):
539 """
551 """
540 Grant permission for users group on given repository, or update
552 Grant permission for users group on given repository, or update
541 existing one if found
553 existing one if found
542
554
543 :param repo: Instance of Repository, repository_id, or repository name
555 :param repo: Instance of Repository, repository_id, or repository name
544 :param group_name: Instance of UserGroup, users_group_id,
556 :param group_name: Instance of UserGroup, users_group_id,
545 or users group name
557 or users group name
546 :param perm: Instance of Permission, or permission_name
558 :param perm: Instance of Permission, or permission_name
547 """
559 """
548 repo = self._get_repo(repo)
560 repo = self._get_repo(repo)
549 group_name = self.__get_users_group(group_name)
561 group_name = self.__get_users_group(group_name)
550 permission = self._get_perm(perm)
562 permission = self._get_perm(perm)
551
563
552 # check if we have that permission already
564 # check if we have that permission already
553 obj = self.sa.query(UsersGroupRepoToPerm)\
565 obj = self.sa.query(UsersGroupRepoToPerm)\
554 .filter(UsersGroupRepoToPerm.users_group == group_name)\
566 .filter(UsersGroupRepoToPerm.users_group == group_name)\
555 .filter(UsersGroupRepoToPerm.repository == repo)\
567 .filter(UsersGroupRepoToPerm.repository == repo)\
556 .scalar()
568 .scalar()
557
569
558 if obj is None:
570 if obj is None:
559 # create new
571 # create new
560 obj = UsersGroupRepoToPerm()
572 obj = UsersGroupRepoToPerm()
561
573
562 obj.repository = repo
574 obj.repository = repo
563 obj.users_group = group_name
575 obj.users_group = group_name
564 obj.permission = permission
576 obj.permission = permission
565 self.sa.add(obj)
577 self.sa.add(obj)
566 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo))
578 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo))
567
579
568 def revoke_users_group_permission(self, repo, group_name):
580 def revoke_users_group_permission(self, repo, group_name):
569 """
581 """
570 Revoke permission for users group on given repository
582 Revoke permission for users group on given repository
571
583
572 :param repo: Instance of Repository, repository_id, or repository name
584 :param repo: Instance of Repository, repository_id, or repository name
573 :param group_name: Instance of UserGroup, users_group_id,
585 :param group_name: Instance of UserGroup, users_group_id,
574 or users group name
586 or users group name
575 """
587 """
576 repo = self._get_repo(repo)
588 repo = self._get_repo(repo)
577 group_name = self.__get_users_group(group_name)
589 group_name = self.__get_users_group(group_name)
578
590
579 obj = self.sa.query(UsersGroupRepoToPerm)\
591 obj = self.sa.query(UsersGroupRepoToPerm)\
580 .filter(UsersGroupRepoToPerm.repository == repo)\
592 .filter(UsersGroupRepoToPerm.repository == repo)\
581 .filter(UsersGroupRepoToPerm.users_group == group_name)\
593 .filter(UsersGroupRepoToPerm.users_group == group_name)\
582 .scalar()
594 .scalar()
583 if obj:
595 if obj:
584 self.sa.delete(obj)
596 self.sa.delete(obj)
585 log.debug('Revoked perm to %s on %s' % (repo, group_name))
597 log.debug('Revoked perm to %s on %s' % (repo, group_name))
586
598
587 def delete_stats(self, repo_name):
599 def delete_stats(self, repo_name):
588 """
600 """
589 removes stats for given repo
601 removes stats for given repo
590
602
591 :param repo_name:
603 :param repo_name:
592 """
604 """
593 try:
605 try:
594 obj = self.sa.query(Statistics)\
606 obj = self.sa.query(Statistics)\
595 .filter(Statistics.repository ==
607 .filter(Statistics.repository ==
596 self.get_by_repo_name(repo_name))\
608 self.get_by_repo_name(repo_name))\
597 .one()
609 .one()
598 self.sa.delete(obj)
610 self.sa.delete(obj)
599 except:
611 except:
600 log.error(traceback.format_exc())
612 log.error(traceback.format_exc())
601 raise
613 raise
602
614
603 def __create_repo(self, repo_name, alias, parent, clone_uri=False):
615 def __create_repo(self, repo_name, alias, parent, clone_uri=False):
604 """
616 """
605 makes repository on filesystem. It's group aware means it'll create
617 makes repository on filesystem. It's group aware means it'll create
606 a repository within a group, and alter the paths accordingly of
618 a repository within a group, and alter the paths accordingly of
607 group location
619 group location
608
620
609 :param repo_name:
621 :param repo_name:
610 :param alias:
622 :param alias:
611 :param parent_id:
623 :param parent_id:
612 :param clone_uri:
624 :param clone_uri:
613 """
625 """
614 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
626 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
615 from rhodecode.model.scm import ScmModel
627 from rhodecode.model.scm import ScmModel
616
628
617 if parent:
629 if parent:
618 new_parent_path = os.sep.join(parent.full_path_splitted)
630 new_parent_path = os.sep.join(parent.full_path_splitted)
619 else:
631 else:
620 new_parent_path = ''
632 new_parent_path = ''
621
633
622 # we need to make it str for mercurial
634 # we need to make it str for mercurial
623 repo_path = os.path.join(*map(lambda x: safe_str(x),
635 repo_path = os.path.join(*map(lambda x: safe_str(x),
624 [self.repos_path, new_parent_path, repo_name]))
636 [self.repos_path, new_parent_path, repo_name]))
625
637
626 # check if this path is not a repository
638 # check if this path is not a repository
627 if is_valid_repo(repo_path, self.repos_path):
639 if is_valid_repo(repo_path, self.repos_path):
628 raise Exception('This path %s is a valid repository' % repo_path)
640 raise Exception('This path %s is a valid repository' % repo_path)
629
641
630 # check if this path is a group
642 # check if this path is a group
631 if is_valid_repos_group(repo_path, self.repos_path):
643 if is_valid_repos_group(repo_path, self.repos_path):
632 raise Exception('This path %s is a valid group' % repo_path)
644 raise Exception('This path %s is a valid group' % repo_path)
633
645
634 log.info('creating repo %s in %s @ %s' % (
646 log.info('creating repo %s in %s @ %s' % (
635 repo_name, safe_unicode(repo_path), clone_uri
647 repo_name, safe_unicode(repo_path), clone_uri
636 )
648 )
637 )
649 )
638 backend = get_backend(alias)
650 backend = get_backend(alias)
639 if alias == 'hg':
651 if alias == 'hg':
640 backend(repo_path, create=True, src_url=clone_uri)
652 backend(repo_path, create=True, src_url=clone_uri)
641 elif alias == 'git':
653 elif alias == 'git':
642 r = backend(repo_path, create=True, src_url=clone_uri, bare=True)
654 r = backend(repo_path, create=True, src_url=clone_uri, bare=True)
643 # add rhodecode hook into this repo
655 # add rhodecode hook into this repo
644 ScmModel().install_git_hook(repo=r)
656 ScmModel().install_git_hook(repo=r)
645 else:
657 else:
646 raise Exception('Undefined alias %s' % alias)
658 raise Exception('Undefined alias %s' % alias)
647
659
648 def __rename_repo(self, old, new):
660 def __rename_repo(self, old, new):
649 """
661 """
650 renames repository on filesystem
662 renames repository on filesystem
651
663
652 :param old: old name
664 :param old: old name
653 :param new: new name
665 :param new: new name
654 """
666 """
655 log.info('renaming repo from %s to %s' % (old, new))
667 log.info('renaming repo from %s to %s' % (old, new))
656
668
657 old_path = os.path.join(self.repos_path, old)
669 old_path = os.path.join(self.repos_path, old)
658 new_path = os.path.join(self.repos_path, new)
670 new_path = os.path.join(self.repos_path, new)
659 if os.path.isdir(new_path):
671 if os.path.isdir(new_path):
660 raise Exception(
672 raise Exception(
661 'Was trying to rename to already existing dir %s' % new_path
673 'Was trying to rename to already existing dir %s' % new_path
662 )
674 )
663 shutil.move(old_path, new_path)
675 shutil.move(old_path, new_path)
664
676
665 def __delete_repo(self, repo):
677 def __delete_repo(self, repo):
666 """
678 """
667 removes repo from filesystem, the removal is acctually made by
679 removes repo from filesystem, the removal is acctually made by
668 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
680 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
669 repository is no longer valid for rhodecode, can be undeleted later on
681 repository is no longer valid for rhodecode, can be undeleted later on
670 by reverting the renames on this repository
682 by reverting the renames on this repository
671
683
672 :param repo: repo object
684 :param repo: repo object
673 """
685 """
674 rm_path = os.path.join(self.repos_path, repo.repo_name)
686 rm_path = os.path.join(self.repos_path, repo.repo_name)
675 log.info("Removing %s" % (rm_path))
687 log.info("Removing %s" % (rm_path))
676 # disable hg/git internal that it doesn't get detected as repo
688 # disable hg/git internal that it doesn't get detected as repo
677 alias = repo.repo_type
689 alias = repo.repo_type
678
690
679 bare = getattr(repo.scm_instance, 'bare', False)
691 bare = getattr(repo.scm_instance, 'bare', False)
680
692
681 if not bare:
693 if not bare:
682 # skip this for bare git repos
694 # skip this for bare git repos
683 shutil.move(os.path.join(rm_path, '.%s' % alias),
695 shutil.move(os.path.join(rm_path, '.%s' % alias),
684 os.path.join(rm_path, 'rm__.%s' % alias))
696 os.path.join(rm_path, 'rm__.%s' % alias))
685 # disable repo
697 # disable repo
686 _now = datetime.now()
698 _now = datetime.now()
687 _ms = str(_now.microsecond).rjust(6, '0')
699 _ms = str(_now.microsecond).rjust(6, '0')
688 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
700 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
689 repo.just_name)
701 repo.just_name)
690 if repo.group:
702 if repo.group:
691 args = repo.group.full_path_splitted + [_d]
703 args = repo.group.full_path_splitted + [_d]
692 _d = os.path.join(*args)
704 _d = os.path.join(*args)
693 shutil.move(rm_path, os.path.join(self.repos_path, _d))
705 shutil.move(rm_path, os.path.join(self.repos_path, _d))
General Comments 0
You need to be logged in to leave comments. Login now