##// END OF EJS Templates
fixes for stable
marcink -
r1216:8363b0d2 default
parent child Browse files
Show More
@@ -31,12 +31,20 b' using the following credentials:'
31 Source code
31 Source code
32 -----------
32 -----------
33
33
34 The latest source for RhodeCode can be obtained from official RhodeCode instance
34 The latest sources can be obtained from official RhodeCode instance
35 https://hg.rhodecode.org
35 https://hg.rhodecode.org
36
36
37 Rarely updated source code and issue tracker is available at bitbucket
37
38 MIRRORS:
39
40 Issue tracker and sources at bitbucket_
41
38 http://bitbucket.org/marcinkuzminski/rhodecode
42 http://bitbucket.org/marcinkuzminski/rhodecode
39
43
44 Sources at github_
45
46 https://github.com/marcinkuzminski/rhodecode
47
40 Installation
48 Installation
41 ------------
49 ------------
42
50
@@ -48,7 +56,7 b' RhodeCode Features'
48
56
49 - Has it's own middleware to handle mercurial_ protocol requests.
57 - Has it's own middleware to handle mercurial_ protocol requests.
50 Each request can be logged and authenticated.
58 Each request can be logged and authenticated.
51 - Runs on threads unlike hgweb. You can make multiple pulls/pushes simultaneous.
59 - Runs on threads unlike hgweb. You can make multiple pulls/pushes simultaneous.
52 Supports http/https and LDAP
60 Supports http/https and LDAP
53 - Full permissions (private/read/write/admin) and authentication per project.
61 - Full permissions (private/read/write/admin) and authentication per project.
54 One account for web interface and mercurial_ push/pull/clone operations.
62 One account for web interface and mercurial_ push/pull/clone operations.
@@ -94,7 +102,7 b' Incoming / Plans'
94 License
102 License
95 -------
103 -------
96
104
97 ``RhodeCode`` is released under the GPL_ license.
105 ``RhodeCode`` is released under the GPLv3 license.
98
106
99
107
100 Mailing group Q&A
108 Mailing group Q&A
@@ -117,16 +125,17 b' You may also build the documentation for'
117 make html
125 make html
118
126
119 (You need to have sphinx_ installed to build the documentation. If you don't
127 (You need to have sphinx_ installed to build the documentation. If you don't
120 have sphinx_ installed you can install it via the command: ``easy_install sphinx``)
128 have sphinx_ installed you can install it via the command:
129 ``easy_install sphinx``)
121
130
122 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
131 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
123 .. _python: http://www.python.org/
132 .. _python: http://www.python.org/
124 .. _sphinx: http://sphinx.pocoo.org/
133 .. _sphinx: http://sphinx.pocoo.org/
125 .. _mercurial: http://mercurial.selenic.com/
134 .. _mercurial: http://mercurial.selenic.com/
126 .. _bitbucket: http://bitbucket.org/
135 .. _bitbucket: http://bitbucket.org/
136 .. _github: http://github.com/
127 .. _subversion: http://subversion.tigris.org/
137 .. _subversion: http://subversion.tigris.org/
128 .. _git: http://git-scm.com/
138 .. _git: http://git-scm.com/
129 .. _celery: http://celeryproject.org/
139 .. _celery: http://celeryproject.org/
130 .. _Sphinx: http://sphinx.pocoo.org/
140 .. _Sphinx: http://sphinx.pocoo.org/
131 .. _GPL: http://www.gnu.org/licenses/gpl.html
132 .. _vcs: http://pypi.python.org/pypi/vcs No newline at end of file
141 .. _vcs: http://pypi.python.org/pypi/vcs
@@ -4,7 +4,7 b' Changelog'
4 =========
4 =========
5
5
6
6
7 1.1.7 (**2011-03-23**)
7 1.1.8 (**2011-04-XX**)
8 ======================
8 ======================
9
9
10 news
10 news
@@ -15,6 +15,8 b' fixes'
15
15
16 - fixed #140 freeze of python dateutil library, since new version is python2.x
16 - fixed #140 freeze of python dateutil library, since new version is python2.x
17 incompatible
17 incompatible
18 - setup-app will check for write permission in given path
19
18
20
19 1.1.7 (**2011-03-23**)
21 1.1.7 (**2011-03-23**)
20 ======================
22 ======================
@@ -5,26 +5,24 b''
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) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :copyright: (C) 2009-2011 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
14 # This program is free software: you can redistribute it and/or modify
15 # modify it under the terms of the GNU General Public License
15 # it under the terms of the GNU General Public License as published by
16 # as published by the Free Software Foundation; version 2
16 # the Free Software Foundation, either version 3 of the License, or
17 # of the License or (at your opinion) any later version of the license.
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, write to the Free Software
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 # MA 02110-1301, USA.
28
26
29 import os
27 import os
30 import sys
28 import sys
@@ -38,13 +36,14 b' from rhodecode.model import meta'
38 from rhodecode.lib.auth import get_crypt_password
36 from rhodecode.lib.auth import get_crypt_password
39 from rhodecode.lib.utils import ask_ok
37 from rhodecode.lib.utils import ask_ok
40 from rhodecode.model import init_model
38 from rhodecode.model import init_model
41 from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \
39 from rhodecode.model.db import User, Permission, RhodeCodeUi, \
42 UserToPerm, DbMigrateVersion
40 RhodeCodeSettings, UserToPerm, DbMigrateVersion
43
41
44 from sqlalchemy.engine import create_engine
42 from sqlalchemy.engine import create_engine
45
43
46 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
47
45
46
48 class DbManage(object):
47 class DbManage(object):
49 def __init__(self, log_sql, dbconf, root, tests=False):
48 def __init__(self, log_sql, dbconf, root, tests=False):
50 self.dbname = dbconf.split('/')[-1]
49 self.dbname = dbconf.split('/')[-1]
@@ -78,8 +77,6 b' class DbManage(object):'
78 meta.Base.metadata.create_all(checkfirst=checkfirst)
77 meta.Base.metadata.create_all(checkfirst=checkfirst)
79 log.info('Created tables for %s', self.dbname)
78 log.info('Created tables for %s', self.dbname)
80
79
81
82
83 def set_db_version(self):
80 def set_db_version(self):
84 try:
81 try:
85 ver = DbMigrateVersion()
82 ver = DbMigrateVersion()
@@ -93,12 +90,10 b' class DbManage(object):'
93 raise
90 raise
94 log.info('db version set to: %s', __dbversion__)
91 log.info('db version set to: %s', __dbversion__)
95
92
93 def upgrade(self):
94 """Upgrades given database schema to given revision following
95 all needed steps, to perform the upgrade
96
96
97 def upgrade(self):
98 """Upgrades given database schema to given revision following
99 all needed steps, to perform the upgrade
100
101 :param revision: revision to upgrade to
102 """
97 """
103
98
104 from rhodecode.lib.dbmigrate.migrate.versioning import api
99 from rhodecode.lib.dbmigrate.migrate.versioning import api
@@ -135,7 +130,7 b' class DbManage(object):'
135 # UPGRADE STEPS
130 # UPGRADE STEPS
136 #======================================================================
131 #======================================================================
137 class UpgradeSteps(object):
132 class UpgradeSteps(object):
138 """Those steps follow schema versions so for example schema
133 """Those steps follow schema versions so for example schema
139 for example schema with seq 002 == step_2 and so on.
134 for example schema with seq 002 == step_2 and so on.
140 """
135 """
141
136
@@ -162,7 +157,6 b' class DbManage(object):'
162 log.info('Changing ui settings')
157 log.info('Changing ui settings')
163 self.klass.create_ui_settings()
158 self.klass.create_ui_settings()
164
159
165
166 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
160 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
167
161
168 #CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
162 #CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
@@ -170,8 +164,6 b' class DbManage(object):'
170 print ('performing upgrade step %s' % step)
164 print ('performing upgrade step %s' % step)
171 callable = getattr(UpgradeSteps(self), 'step_%s' % step)()
165 callable = getattr(UpgradeSteps(self), 'step_%s' % step)()
172
166
173
174
175 def fix_repo_paths(self):
167 def fix_repo_paths(self):
176 """Fixes a old rhodecode version path into new one without a '*'
168 """Fixes a old rhodecode version path into new one without a '*'
177 """
169 """
@@ -208,15 +200,13 b' class DbManage(object):'
208 self.sa.rollback()
200 self.sa.rollback()
209 raise
201 raise
210
202
211
212
213 def admin_prompt(self, second=False):
203 def admin_prompt(self, second=False):
214 if not self.tests:
204 if not self.tests:
215 import getpass
205 import getpass
216
206
217
218 def get_password():
207 def get_password():
219 password = getpass.getpass('Specify admin password (min 6 chars):')
208 password = getpass.getpass('Specify admin password '
209 '(min 6 chars):')
220 confirm = getpass.getpass('Confirm password:')
210 confirm = getpass.getpass('Confirm password:')
221
211
222 if password != confirm:
212 if password != confirm:
@@ -241,14 +231,17 b' class DbManage(object):'
241 self.create_user(username, password, email, True)
231 self.create_user(username, password, email, True)
242 else:
232 else:
243 log.info('creating admin and regular test users')
233 log.info('creating admin and regular test users')
244 self.create_user('test_admin', 'test12', 'test_admin@mail.com', True)
234 self.create_user('test_admin', 'test12',
245 self.create_user('test_regular', 'test12', 'test_regular@mail.com', False)
235 'test_admin@mail.com', True)
246 self.create_user('test_regular2', 'test12', 'test_regular2@mail.com', False)
236 self.create_user('test_regular', 'test12',
237 'test_regular@mail.com', False)
238 self.create_user('test_regular2', 'test12',
239 'test_regular2@mail.com', False)
247
240
248 def create_ui_settings(self):
241 def create_ui_settings(self):
249 """Creates ui settings, fills out hooks
242 """Creates ui settings, fills out hooks
250 and disables dotencode
243 and disables dotencode
251
244
252 """
245 """
253 #HOOKS
246 #HOOKS
254 hooks1_key = 'changegroup.update'
247 hooks1_key = 'changegroup.update'
@@ -297,7 +290,6 b' class DbManage(object):'
297 self.sa.rollback()
290 self.sa.rollback()
298 raise
291 raise
299
292
300
301 def create_ldap_options(self):
293 def create_ldap_options(self):
302 """Creates ldap settings"""
294 """Creates ldap settings"""
303
295
@@ -316,18 +308,39 b' class DbManage(object):'
316 self.sa.rollback()
308 self.sa.rollback()
317 raise
309 raise
318
310
319 def config_prompt(self, test_repo_path=''):
311 def config_prompt(self, test_repo_path='', retries=3):
320 log.info('Setting up repositories config')
312 if retries == 3:
313 log.info('Setting up repositories config')
321
314
322 if not self.tests and not test_repo_path:
315 if not self.tests and not test_repo_path:
323 path = raw_input('Specify valid full path to your repositories'
316 path = raw_input('Specify valid full path to your repositories'
324 ' you can change this later in application settings:')
317 ' you can change this later in application settings:')
325 else:
318 else:
326 path = test_repo_path
319 path = test_repo_path
320 path_ok = True
327
321
322 #check proper dir
328 if not os.path.isdir(path):
323 if not os.path.isdir(path):
329 log.error('You entered wrong path: %s', path)
324 path_ok = False
325 log.error('Entered path is not a valid directory: %s [%s/3]',
326 path, retries)
327
328 #check write access
329 if not os.access(path, os.W_OK):
330 path_ok = False
331
332 log.error('No write permission to given path: %s [%s/3]',
333 path, retries)
334
335 if retries == 0:
330 sys.exit()
336 sys.exit()
337 if path_ok is False:
338 retries -= 1
339 return self.config_prompt(test_repo_path, retries)
340
341 return path
342
343 def create_settings(self, path):
331
344
332 self.create_ui_settings()
345 self.create_ui_settings()
333
346
@@ -357,11 +370,9 b' class DbManage(object):'
357 paths.ui_key = '/'
370 paths.ui_key = '/'
358 paths.ui_value = path
371 paths.ui_value = path
359
372
360
361 hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication')
373 hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication')
362 hgsettings2 = RhodeCodeSettings('title', 'RhodeCode')
374 hgsettings2 = RhodeCodeSettings('title', 'RhodeCode')
363
375
364
365 try:
376 try:
366 self.sa.add(web1)
377 self.sa.add(web1)
367 self.sa.add(web2)
378 self.sa.add(web2)
@@ -427,8 +438,12 b' class DbManage(object):'
427 ('hg.create.repository', 'Repository create'),
438 ('hg.create.repository', 'Repository create'),
428 ('hg.create.none', 'Repository creation disabled'),
439 ('hg.create.none', 'Repository creation disabled'),
429 ('hg.register.none', 'Register disabled'),
440 ('hg.register.none', 'Register disabled'),
430 ('hg.register.manual_activate', 'Register new user with rhodecode without manual activation'),
441 ('hg.register.manual_activate', ('Register new user with '
431 ('hg.register.auto_activate', 'Register new user with rhodecode without auto activation'),
442 'RhodeCode without '
443 'manual activation')),
444 ('hg.register.auto_activate', ('Register new user with '
445 'RhodeCode without auto '
446 'activation')),
432 ]
447 ]
433
448
434 for p in perms:
449 for p in perms:
@@ -474,4 +489,3 b' class DbManage(object):'
474 except:
489 except:
475 self.sa.rollback()
490 self.sa.rollback()
476 raise
491 raise
477
@@ -7,23 +7,21 b''
7
7
8 :created_on: Apr 9, 2010
8 :created_on: Apr 9, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 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
13 # This program is free software: you can redistribute it and/or modify
14 # modify it under the terms of the GNU General Public License
14 # it under the terms of the GNU General Public License as published by
15 # as published by the Free Software Foundation; version 2
15 # the Free Software Foundation, either version 3 of the License, or
16 # of the License or (at your opinion) any later version of the license.
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, write to the Free Software
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
27 import os
25 import os
28 import time
26 import time
29 import traceback
27 import traceback
@@ -59,10 +57,19 b' log = logging.getLogger(__name__)'
59 class UserTemp(object):
57 class UserTemp(object):
60 def __init__(self, user_id):
58 def __init__(self, user_id):
61 self.user_id = user_id
59 self.user_id = user_id
60
61 def __repr__(self):
62 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
63
64
62 class RepoTemp(object):
65 class RepoTemp(object):
63 def __init__(self, repo_id):
66 def __init__(self, repo_id):
64 self.repo_id = repo_id
67 self.repo_id = repo_id
65
68
69 def __repr__(self):
70 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
71
72
66 class ScmModel(BaseModel):
73 class ScmModel(BaseModel):
67 """Generic Scm Model
74 """Generic Scm Model
68 """
75 """
@@ -77,9 +84,9 b' class ScmModel(BaseModel):'
77 return q.ui_value
84 return q.ui_value
78
85
79 def repo_scan(self, repos_path, baseui):
86 def repo_scan(self, repos_path, baseui):
80 """Listing of repositories in given path. This path should not be a
87 """Listing of repositories in given path. This path should not be a
81 repository itself. Return a dictionary of repository objects
88 repository itself. Return a dictionary of repository objects
82
89
83 :param repos_path: path to directory containing repositories
90 :param repos_path: path to directory containing repositories
84 :param baseui: baseui instance to instantiate MercurialRepostitory with
91 :param baseui: baseui instance to instantiate MercurialRepostitory with
85 """
92 """
@@ -92,7 +99,7 b' class ScmModel(BaseModel):'
92
99
93 for name, path in get_repos(repos_path):
100 for name, path in get_repos(repos_path):
94 try:
101 try:
95 if repos_list.has_key(name):
102 if name in repos_list:
96 raise RepositoryError('Duplicate repository name %s '
103 raise RepositoryError('Duplicate repository name %s '
97 'found in %s' % (name, path))
104 'found in %s' % (name, path))
98 else:
105 else:
@@ -110,9 +117,9 b' class ScmModel(BaseModel):'
110 return repos_list
117 return repos_list
111
118
112 def get_repos(self, all_repos=None):
119 def get_repos(self, all_repos=None):
113 """Get all repos from db and for each repo create it's backend instance.
120 """Get all repos from db and for each repo create it's
114 and fill that backed with information from database
121 backend instance.and fill that backed with information from database
115
122
116 :param all_repos: give specific repositories list, good for filtering
123 :param all_repos: give specific repositories list, good for filtering
117 """
124 """
118
125
@@ -140,7 +147,8 b' class ScmModel(BaseModel):'
140 tmp_d['description'] = repo.dbrepo.description
147 tmp_d['description'] = repo.dbrepo.description
141 tmp_d['description_sort'] = tmp_d['description']
148 tmp_d['description_sort'] = tmp_d['description']
142 tmp_d['last_change'] = last_change
149 tmp_d['last_change'] = last_change
143 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
150 tmp_d['last_change_sort'] = time.mktime(last_change \
151 .timetuple())
144 tmp_d['tip'] = tip.raw_id
152 tmp_d['tip'] = tip.raw_id
145 tmp_d['tip_sort'] = tip.revision
153 tmp_d['tip_sort'] = tip.revision
146 tmp_d['rev'] = tip.revision
154 tmp_d['rev'] = tip.revision
@@ -158,12 +166,12 b' class ScmModel(BaseModel):'
158 def get(self, repo_name, invalidation_list=None):
166 def get(self, repo_name, invalidation_list=None):
159 """Get's repository from given name, creates BackendInstance and
167 """Get's repository from given name, creates BackendInstance and
160 propagates it's data from database with all additional information
168 propagates it's data from database with all additional information
161
169
162 :param repo_name:
170 :param repo_name:
163 :param invalidation_list: if a invalidation list is given the get
171 :param invalidation_list: if a invalidation list is given the get
164 method should not manually check if this repository needs
172 method should not manually check if this repository needs
165 invalidation and just invalidate the repositories in list
173 invalidation and just invalidate the repositories in list
166
174
167 """
175 """
168 if not HasRepoPermissionAny('repository.read', 'repository.write',
176 if not HasRepoPermissionAny('repository.read', 'repository.write',
169 'repository.admin')(repo_name, 'get repo check'):
177 'repository.admin')(repo_name, 'get repo check'):
@@ -224,12 +232,10 b' class ScmModel(BaseModel):'
224
232
225 return _get_repo(repo_name)
233 return _get_repo(repo_name)
226
234
227
235 def mark_for_invalidation(self, repo_name):
236 """Puts cache invalidation task into db for
237 further global cache invalidation
228
238
229 def mark_for_invalidation(self, repo_name):
230 """Puts cache invalidation task into db for
231 further global cache invalidation
232
233 :param repo_name: this repo that should invalidation take place
239 :param repo_name: this repo that should invalidation take place
234 """
240 """
235
241
@@ -251,7 +257,6 b' class ScmModel(BaseModel):'
251 log.error(traceback.format_exc())
257 log.error(traceback.format_exc())
252 self.sa.rollback()
258 self.sa.rollback()
253
259
254
255 def toggle_following_repo(self, follow_repo_id, user_id):
260 def toggle_following_repo(self, follow_repo_id, user_id):
256
261
257 f = self.sa.query(UserFollowing)\
262 f = self.sa.query(UserFollowing)\
@@ -272,7 +277,6 b' class ScmModel(BaseModel):'
272 self.sa.rollback()
277 self.sa.rollback()
273 raise
278 raise
274
279
275
276 try:
280 try:
277 f = UserFollowing()
281 f = UserFollowing()
278 f.user_id = user_id
282 f.user_id = user_id
@@ -287,7 +291,7 b' class ScmModel(BaseModel):'
287 self.sa.rollback()
291 self.sa.rollback()
288 raise
292 raise
289
293
290 def toggle_following_user(self, follow_user_id , user_id):
294 def toggle_following_user(self, follow_user_id, user_id):
291 f = self.sa.query(UserFollowing)\
295 f = self.sa.query(UserFollowing)\
292 .filter(UserFollowing.follows_user_id == follow_user_id)\
296 .filter(UserFollowing.follows_user_id == follow_user_id)\
293 .filter(UserFollowing.user_id == user_id).scalar()
297 .filter(UserFollowing.user_id == user_id).scalar()
@@ -340,14 +344,12 b' class ScmModel(BaseModel):'
340 return self.sa.query(Repository)\
344 return self.sa.query(Repository)\
341 .filter(Repository.fork_id == repo_id).count()
345 .filter(Repository.fork_id == repo_id).count()
342
346
343
344 def get_unread_journal(self):
347 def get_unread_journal(self):
345 return self.sa.query(UserLog).count()
348 return self.sa.query(UserLog).count()
346
349
347
348 def _should_invalidate(self, repo_name):
350 def _should_invalidate(self, repo_name):
349 """Looks up database for invalidation signals for this repo_name
351 """Looks up database for invalidation signals for this repo_name
350
352
351 :param repo_name:
353 :param repo_name:
352 """
354 """
353
355
@@ -361,8 +363,9 b' class ScmModel(BaseModel):'
361 return ret
363 return ret
362
364
363 def _mark_invalidated(self, cache_key):
365 def _mark_invalidated(self, cache_key):
364 """ Marks all occurences of cache to invaldation as already invalidated
366 """ Marks all occurences of cache to invaldation as
365
367 already invalidated
368
366 :param cache_key:
369 :param cache_key:
367 """
370 """
368
371
@@ -375,4 +378,3 b' class ScmModel(BaseModel):'
375 except (DatabaseError,):
378 except (DatabaseError,):
376 log.error(traceback.format_exc())
379 log.error(traceback.format_exc())
377 self.sa.rollback()
380 self.sa.rollback()
378
@@ -85,7 +85,6 b''
85 <div id="footer-inner" class="title bottom-left-rounded-corner bottom-right-rounded-corner">
85 <div id="footer-inner" class="title bottom-left-rounded-corner bottom-right-rounded-corner">
86 <div>
86 <div>
87 <p class="footer-link">${h.link_to(_('Submit a bug'),h.url('bugtracker'))}</p>
87 <p class="footer-link">${h.link_to(_('Submit a bug'),h.url('bugtracker'))}</p>
88 <p class="footer-link">${h.link_to(_('GPL license'),h.url('gpl_license'))}</p>
89 <p class="footer-link-right"><a href="${h.url('rhodecode_official')}">RhodeCode</a> ${c.rhodecode_version} &copy; 2010-2011 by Marcin Kuzminski</p>
88 <p class="footer-link-right"><a href="${h.url('rhodecode_official')}">RhodeCode</a> ${c.rhodecode_version} &copy; 2010-2011 by Marcin Kuzminski</p>
90 </div>
89 </div>
91 </div>
90 </div>
General Comments 0
You need to be logged in to leave comments. Login now