##// END OF EJS Templates
fixed hooks broken symlink issue...
marcink -
r679:d85b0948 rhodecode-0.0.1.0.2 default
parent child Browse files
Show More
@@ -1,14 +1,15 b''
1 include rhodecode/config/deployment.ini_tmpl
1 include rhodecode/config/deployment.ini_tmpl
2
2
3 include README.rst
3 include README.rst
4 recursive-include rhodecode/i18n/ *
4 recursive-include rhodecode/i18n/ *
5
5
6 #images
6 #images
7 recursive-include rhodecode/public/css *
7 recursive-include rhodecode/public/css *
8 recursive-include rhodecode/public/images *
8 recursive-include rhodecode/public/images *
9 #js
9 #js
10 include rhodecode/public/js/yui2.js
10 include rhodecode/public/js/yui2.js
11 include rhodecode/public/js/excanvas.min.js
11 include rhodecode/public/js/excanvas.min.js
12 include rhodecode/public/js/yui.flot.js
12 include rhodecode/public/js/yui.flot.js
13 include rhodecode/public/js/graph.js
13 #templates
14 #templates
14 recursive-include rhodecode/templates *
15 recursive-include rhodecode/templates *
@@ -1,46 +1,54 b''
1 .. _changelog:
1 .. _changelog:
2
2
3 Changelog
3 Changelog
4 =========
4 =========
5
5
6 1.0.2 (**2010-11-XX**)
7 ----------------------
8
9 - fixed #59 missing graph.js
10 - fixed repo_size crash when repository had broken symlinks
11 - fixed python2.5 crashes.
12 - tested under python2.7
13 - bumped sqlalcehmy and celery versions
6
14
7 1.0.1 (**2010-11-10**)
15 1.0.1 (**2010-11-10**)
8 ----------------------
16 ----------------------
9
17
10 - fixed #53 python2.5 incompatible enumerate calls
18 - fixed #53 python2.5 incompatible enumerate calls
11 - fixed #52 disable mercurial extension for web
19 - fixed #52 disable mercurial extension for web
12 - fixed #51 deleting repositories don't delete it's dependent objects
20 - fixed #51 deleting repositories don't delete it's dependent objects
13 - small css updated
21 - small css updated
14
22
15
23
16 1.0.0 (**2010-11-02**)
24 1.0.0 (**2010-11-02**)
17 ----------------------
25 ----------------------
18
26
19 - security bugfix simplehg wasn't checking for permissions on commands
27 - security bugfix simplehg wasn't checking for permissions on commands
20 other than pull or push.
28 other than pull or push.
21 - fixed doubled messages after push or pull in admin journal
29 - fixed doubled messages after push or pull in admin journal
22 - templating and css corrections, fixed repo switcher on chrome, updated titles
30 - templating and css corrections, fixed repo switcher on chrome, updated titles
23 - admin menu accessible from options menu on repository view
31 - admin menu accessible from options menu on repository view
24 - permissions cached queries
32 - permissions cached queries
25
33
26 1.0.0rc4 (**2010-10-12**)
34 1.0.0rc4 (**2010-10-12**)
27 --------------------------
35 --------------------------
28
36
29 - fixed python2.5 missing simplejson imports (thanks to Jens BΓ€ckman)
37 - fixed python2.5 missing simplejson imports (thanks to Jens BΓ€ckman)
30 - removed cache_manager settings from sqlalchemy meta
38 - removed cache_manager settings from sqlalchemy meta
31 - added sqlalchemy cache settings to ini files
39 - added sqlalchemy cache settings to ini files
32 - validated password length and added second try of failure on paster setup-app
40 - validated password length and added second try of failure on paster setup-app
33 - fixed setup database destroy prompt even when there was no db
41 - fixed setup database destroy prompt even when there was no db
34
42
35
43
36 1.0.0rc3 (**2010-10-11**)
44 1.0.0rc3 (**2010-10-11**)
37 -------------------------
45 -------------------------
38
46
39 - fixed i18n during installation.
47 - fixed i18n during installation.
40
48
41 1.0.0rc2 (**2010-10-11**)
49 1.0.0rc2 (**2010-10-11**)
42 -------------------------
50 -------------------------
43
51
44 - Disabled dirsize in file browser, it's causing nasty bug when dir renames
52 - Disabled dirsize in file browser, it's causing nasty bug when dir renames
45 occure. After vcs is fixed it'll be put back again.
53 occure. After vcs is fixed it'll be put back again.
46 - templating/css rewrites, optimized css.
54 - templating/css rewrites, optimized css.
@@ -1,35 +1,35 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # RhodeCode, a web based repository management based on pylons
3 # RhodeCode, a web based repository management based on pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 9, 2010
21 Created on April 9, 2010
22 RhodeCode, a web based repository management based on pylons
22 RhodeCode, a web based repository management based on pylons
23 versioning implementation: http://semver.org/
23 versioning implementation: http://semver.org/
24 @author: marcink
24 @author: marcink
25 """
25 """
26
26
27 VERSION = (1, 0, 1,)
27 VERSION = (1, 0, 2,)
28
28
29 __version__ = '.'.join((str(each) for each in VERSION[:4]))
29 __version__ = '.'.join((str(each) for each in VERSION[:4]))
30
30
31 def get_version():
31 def get_version():
32 """
32 """
33 Returns shorter version (digit parts only) as string.
33 Returns shorter version (digit parts only) as string.
34 """
34 """
35 return '.'.join((str(each) for each in VERSION[:3]))
35 return '.'.join((str(each) for each in VERSION[:3]))
@@ -1,64 +1,71 b''
1 from rhodecode.lib.pidlock import DaemonLock, LockHeld
1 from rhodecode.lib.pidlock import DaemonLock, LockHeld
2 from vcs.utils.lazy import LazyProperty
2 from vcs.utils.lazy import LazyProperty
3 from decorator import decorator
3 from decorator import decorator
4 import logging
4 import logging
5 import os
5 import os
6 import sys
6 import sys
7 import traceback
7 import traceback
8 from hashlib import md5
8 from hashlib import md5
9 import socket
9 import socket
10 log = logging.getLogger(__name__)
10 log = logging.getLogger(__name__)
11
11
12 class ResultWrapper(object):
12 class ResultWrapper(object):
13 def __init__(self, task):
13 def __init__(self, task):
14 self.task = task
14 self.task = task
15
15
16 @LazyProperty
16 @LazyProperty
17 def result(self):
17 def result(self):
18 return self.task
18 return self.task
19
19
20 def run_task(task, *args, **kwargs):
20 def run_task(task, *args, **kwargs):
21 try:
21 try:
22 t = task.delay(*args, **kwargs)
22 t = task.delay(*args, **kwargs)
23 log.info('running task %s', t.task_id)
23 log.info('running task %s', t.task_id)
24 return t
24 return t
25 except socket.error, e:
25 except socket.error, e:
26 if e.errno == 111:
26
27 try:
28 conn_failed = e.errno == 111
29 except AttributeError:
30 conn_failed = False
31
32 if conn_failed:
27 log.debug('Unable to connect to celeryd. Sync execution')
33 log.debug('Unable to connect to celeryd. Sync execution')
28 else:
34 else:
29 log.error(traceback.format_exc())
35 log.debug('Unable to connect to celeryd. Sync execution')
36
30 except KeyError, e:
37 except KeyError, e:
31 log.debug('Unable to connect to celeryd. Sync execution')
38 log.debug('Unable to connect to celeryd. Sync execution')
32 except Exception, e:
39 except Exception, e:
33 log.error(traceback.format_exc())
40 log.error(traceback.format_exc())
34
41
35 return ResultWrapper(task(*args, **kwargs))
42 return ResultWrapper(task(*args, **kwargs))
36
43
37
44
38 def locked_task(func):
45 def locked_task(func):
39 def __wrapper(func, *fargs, **fkwargs):
46 def __wrapper(func, *fargs, **fkwargs):
40 params = list(fargs)
47 params = list(fargs)
41 params.extend(['%s-%s' % ar for ar in fkwargs.items()])
48 params.extend(['%s-%s' % ar for ar in fkwargs.items()])
42
49
43 lockkey = 'task_%s' % \
50 lockkey = 'task_%s' % \
44 md5(str(func.__name__) + '-' + \
51 md5(str(func.__name__) + '-' + \
45 '-'.join(map(str, params))).hexdigest()
52 '-'.join(map(str, params))).hexdigest()
46 log.info('running task with lockkey %s', lockkey)
53 log.info('running task with lockkey %s', lockkey)
47 try:
54 try:
48 l = DaemonLock(lockkey)
55 l = DaemonLock(lockkey)
49 ret = func(*fargs, **fkwargs)
56 ret = func(*fargs, **fkwargs)
50 l.release()
57 l.release()
51 return ret
58 return ret
52 except LockHeld:
59 except LockHeld:
53 log.info('LockHeld')
60 log.info('LockHeld')
54 return 'Task with key %s already running' % lockkey
61 return 'Task with key %s already running' % lockkey
55
62
56 return decorator(__wrapper, func)
63 return decorator(__wrapper, func)
57
64
58
65
59
66
60
67
61
68
62
69
63
70
64
71
@@ -1,78 +1,84 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # custom hooks for application
3 # custom hooks for application
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on Aug 6, 2010
21 Created on Aug 6, 2010
22
22
23 @author: marcink
23 @author: marcink
24 """
24 """
25
25
26 import sys
26 import sys
27 import os
27 import os
28 from rhodecode.lib import helpers as h
28 from rhodecode.lib import helpers as h
29 from rhodecode.model import meta
29 from rhodecode.model import meta
30 from rhodecode.model.db import UserLog, User
30 from rhodecode.model.db import UserLog, User
31
31
32 def repo_size(ui, repo, hooktype=None, **kwargs):
32 def repo_size(ui, repo, hooktype=None, **kwargs):
33
33
34 if hooktype != 'changegroup':
34 if hooktype != 'changegroup':
35 return False
35 return False
36 size_hg, size_root = 0, 0
36 size_hg, size_root = 0, 0
37 for path, dirs, files in os.walk(repo.root):
37 for path, dirs, files in os.walk(repo.root):
38 if path.find('.hg') != -1:
38 if path.find('.hg') != -1:
39 for f in files:
39 for f in files:
40 try:
40 size_hg += os.path.getsize(os.path.join(path, f))
41 size_hg += os.path.getsize(os.path.join(path, f))
42 except OSError:
43 pass
41 else:
44 else:
42 for f in files:
45 for f in files:
46 try:
43 size_root += os.path.getsize(os.path.join(path, f))
47 size_root += os.path.getsize(os.path.join(path, f))
48 except OSError:
49 pass
44
50
45 size_hg_f = h.format_byte_size(size_hg)
51 size_hg_f = h.format_byte_size(size_hg)
46 size_root_f = h.format_byte_size(size_root)
52 size_root_f = h.format_byte_size(size_root)
47 size_total_f = h.format_byte_size(size_root + size_hg)
53 size_total_f = h.format_byte_size(size_root + size_hg)
48 sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \
54 sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \
49 % (size_hg_f, size_root_f, size_total_f))
55 % (size_hg_f, size_root_f, size_total_f))
50
56
51 user_action_mapper(ui, repo, hooktype, **kwargs)
57 user_action_mapper(ui, repo, hooktype, **kwargs)
52
58
53 def user_action_mapper(ui, repo, hooktype=None, **kwargs):
59 def user_action_mapper(ui, repo, hooktype=None, **kwargs):
54 """
60 """
55 Maps user last push action to new changeset id, from mercurial
61 Maps user last push action to new changeset id, from mercurial
56 :param ui:
62 :param ui:
57 :param repo:
63 :param repo:
58 :param hooktype:
64 :param hooktype:
59 """
65 """
60
66
61 try:
67 try:
62 sa = meta.Session
68 sa = meta.Session
63 username = kwargs['url'].split(':')[-1]
69 username = kwargs['url'].split(':')[-1]
64 user_log = sa.query(UserLog)\
70 user_log = sa.query(UserLog)\
65 .filter(UserLog.user == sa.query(User)\
71 .filter(UserLog.user == sa.query(User)\
66 .filter(User.username == username).one())\
72 .filter(User.username == username).one())\
67 .order_by(UserLog.user_log_id.desc()).first()
73 .order_by(UserLog.user_log_id.desc()).first()
68
74
69 if user_log and not user_log.revision:
75 if user_log and not user_log.revision:
70 user_log.revision = str(repo['tip'])
76 user_log.revision = str(repo['tip'])
71 sa.add(user_log)
77 sa.add(user_log)
72 sa.commit()
78 sa.commit()
73
79
74 except Exception, e:
80 except Exception, e:
75 sa.rollback()
81 sa.rollback()
76 raise
82 raise
77 finally:
83 finally:
78 meta.Session.remove()
84 meta.Session.remove()
@@ -1,512 +1,515 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # Utilities for RhodeCode
3 # Utilities for RhodeCode
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 # This program is free software; you can redistribute it and/or
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; version 2
7 # as published by the Free Software Foundation; version 2
8 # of the License or (at your opinion) any later version of the license.
8 # of the License or (at your opinion) any later version of the license.
9 #
9 #
10 # This program is distributed in the hope that it will be useful,
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
13 # GNU General Public License for more details.
14 #
14 #
15 # You should have received a copy of the GNU General Public License
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # MA 02110-1301, USA.
18 # MA 02110-1301, USA.
19
19
20 """
20 """
21 Created on April 18, 2010
21 Created on April 18, 2010
22 Utilities for RhodeCode
22 Utilities for RhodeCode
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from beaker.cache import cache_region
25 from beaker.cache import cache_region
26 from mercurial import ui, config, hg
26 from mercurial import ui, config, hg
27 from mercurial.error import RepoError
27 from mercurial.error import RepoError
28 from rhodecode.model import meta
28 from rhodecode.model import meta
29 from rhodecode.model.db import Repository, User, RhodeCodeUi, RhodeCodeSettings, UserLog
29 from rhodecode.model.db import Repository, User, RhodeCodeUi, RhodeCodeSettings, UserLog
30 from vcs.backends.base import BaseChangeset
30 from vcs.backends.base import BaseChangeset
31 from vcs.utils.lazy import LazyProperty
31 from vcs.utils.lazy import LazyProperty
32 import logging
32 import logging
33 import datetime
33 import datetime
34 import os
34 import os
35
35
36 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
37
37
38
38
39 def get_repo_slug(request):
39 def get_repo_slug(request):
40 return request.environ['pylons.routes_dict'].get('repo_name')
40 return request.environ['pylons.routes_dict'].get('repo_name')
41
41
42 def is_mercurial(environ):
42 def is_mercurial(environ):
43 """
43 """
44 Returns True if request's target is mercurial server - header
44 Returns True if request's target is mercurial server - header
45 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
45 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
46 """
46 """
47 http_accept = environ.get('HTTP_ACCEPT')
47 http_accept = environ.get('HTTP_ACCEPT')
48 if http_accept and http_accept.startswith('application/mercurial'):
48 if http_accept and http_accept.startswith('application/mercurial'):
49 return True
49 return True
50 return False
50 return False
51
51
52 def is_git(environ):
52 def is_git(environ):
53 """
53 """
54 Returns True if request's target is git server. ``HTTP_USER_AGENT`` would
54 Returns True if request's target is git server. ``HTTP_USER_AGENT`` would
55 then have git client version given.
55 then have git client version given.
56
56
57 :param environ:
57 :param environ:
58 """
58 """
59 http_user_agent = environ.get('HTTP_USER_AGENT')
59 http_user_agent = environ.get('HTTP_USER_AGENT')
60 if http_user_agent.startswith('git'):
60 if http_user_agent.startswith('git'):
61 return True
61 return True
62 return False
62 return False
63
63
64 def action_logger(user, action, repo, ipaddr, sa=None):
64 def action_logger(user, action, repo, ipaddr, sa=None):
65 """
65 """
66 Action logger for various action made by users
66 Action logger for various action made by users
67 """
67 """
68
68
69 if not sa:
69 if not sa:
70 sa = meta.Session
70 sa = meta.Session
71
71
72 try:
72 try:
73 if hasattr(user, 'user_id'):
73 if hasattr(user, 'user_id'):
74 user_id = user.user_id
74 user_id = user.user_id
75 elif isinstance(user, basestring):
75 elif isinstance(user, basestring):
76 user_id = sa.query(User).filter(User.username == user).one()
76 user_id = sa.query(User).filter(User.username == user).one()
77 else:
77 else:
78 raise Exception('You have to provide user object or username')
78 raise Exception('You have to provide user object or username')
79
79
80 repo_name = repo.lstrip('/')
80 repo_name = repo.lstrip('/')
81 user_log = UserLog()
81 user_log = UserLog()
82 user_log.user_id = user_id
82 user_log.user_id = user_id
83 user_log.action = action
83 user_log.action = action
84 user_log.repository_name = repo_name
84 user_log.repository_name = repo_name
85 user_log.repository = sa.query(Repository)\
85 user_log.repository = sa.query(Repository)\
86 .filter(Repository.repo_name == repo_name).one()
86 .filter(Repository.repo_name == repo_name).one()
87 user_log.action_date = datetime.datetime.now()
87 user_log.action_date = datetime.datetime.now()
88 user_log.user_ip = ipaddr
88 user_log.user_ip = ipaddr
89 sa.add(user_log)
89 sa.add(user_log)
90 sa.commit()
90 sa.commit()
91
91
92 log.info('Adding user %s, action %s on %s',
92 log.info('Adding user %s, action %s on %s',
93 user.username, action, repo)
93 user.username, action, repo)
94 except Exception, e:
94 except Exception, e:
95 sa.rollback()
95 sa.rollback()
96 log.error('could not log user action:%s', str(e))
96 log.error('could not log user action:%s', str(e))
97
97
98 def check_repo_dir(paths):
98 def check_repo_dir(paths):
99 repos_path = paths[0][1].split('/')
99 repos_path = paths[0][1].split('/')
100 if repos_path[-1] in ['*', '**']:
100 if repos_path[-1] in ['*', '**']:
101 repos_path = repos_path[:-1]
101 repos_path = repos_path[:-1]
102 if repos_path[0] != '/':
102 if repos_path[0] != '/':
103 repos_path[0] = '/'
103 repos_path[0] = '/'
104 if not os.path.isdir(os.path.join(*repos_path)):
104 if not os.path.isdir(os.path.join(*repos_path)):
105 raise Exception('Not a valid repository in %s' % paths[0][1])
105 raise Exception('Not a valid repository in %s' % paths[0][1])
106
106
107 def check_repo_fast(repo_name, base_path):
107 def check_repo_fast(repo_name, base_path):
108 if os.path.isdir(os.path.join(base_path, repo_name)):return False
108 if os.path.isdir(os.path.join(base_path, repo_name)):return False
109 return True
109 return True
110
110
111 def check_repo(repo_name, base_path, verify=True):
111 def check_repo(repo_name, base_path, verify=True):
112
112
113 repo_path = os.path.join(base_path, repo_name)
113 repo_path = os.path.join(base_path, repo_name)
114
114
115 try:
115 try:
116 if not check_repo_fast(repo_name, base_path):
116 if not check_repo_fast(repo_name, base_path):
117 return False
117 return False
118 r = hg.repository(ui.ui(), repo_path)
118 r = hg.repository(ui.ui(), repo_path)
119 if verify:
119 if verify:
120 hg.verify(r)
120 hg.verify(r)
121 #here we hnow that repo exists it was verified
121 #here we hnow that repo exists it was verified
122 log.info('%s repo is already created', repo_name)
122 log.info('%s repo is already created', repo_name)
123 return False
123 return False
124 except RepoError:
124 except RepoError:
125 #it means that there is no valid repo there...
125 #it means that there is no valid repo there...
126 log.info('%s repo is free for creation', repo_name)
126 log.info('%s repo is free for creation', repo_name)
127 return True
127 return True
128
128
129 def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
129 def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
130 while True:
130 while True:
131 ok = raw_input(prompt)
131 ok = raw_input(prompt)
132 if ok in ('y', 'ye', 'yes'): return True
132 if ok in ('y', 'ye', 'yes'): return True
133 if ok in ('n', 'no', 'nop', 'nope'): return False
133 if ok in ('n', 'no', 'nop', 'nope'): return False
134 retries = retries - 1
134 retries = retries - 1
135 if retries < 0: raise IOError
135 if retries < 0: raise IOError
136 print complaint
136 print complaint
137
137
138 @cache_region('super_short_term', 'cached_hg_ui')
138 @cache_region('super_short_term', 'cached_hg_ui')
139 def get_hg_ui_cached():
139 def get_hg_ui_cached():
140 try:
140 try:
141 sa = meta.Session
141 sa = meta.Session
142 ret = sa.query(RhodeCodeUi).all()
142 ret = sa.query(RhodeCodeUi).all()
143 finally:
143 finally:
144 meta.Session.remove()
144 meta.Session.remove()
145 return ret
145 return ret
146
146
147
147
148 def get_hg_settings():
148 def get_hg_settings():
149 try:
149 try:
150 sa = meta.Session
150 sa = meta.Session
151 ret = sa.query(RhodeCodeSettings).all()
151 ret = sa.query(RhodeCodeSettings).all()
152 finally:
152 finally:
153 meta.Session.remove()
153 meta.Session.remove()
154
154
155 if not ret:
155 if not ret:
156 raise Exception('Could not get application settings !')
156 raise Exception('Could not get application settings !')
157 settings = {}
157 settings = {}
158 for each in ret:
158 for each in ret:
159 settings['rhodecode_' + each.app_settings_name] = each.app_settings_value
159 settings['rhodecode_' + each.app_settings_name] = each.app_settings_value
160
160
161 return settings
161 return settings
162
162
163 def get_hg_ui_settings():
163 def get_hg_ui_settings():
164 try:
164 try:
165 sa = meta.Session
165 sa = meta.Session
166 ret = sa.query(RhodeCodeUi).all()
166 ret = sa.query(RhodeCodeUi).all()
167 finally:
167 finally:
168 meta.Session.remove()
168 meta.Session.remove()
169
169
170 if not ret:
170 if not ret:
171 raise Exception('Could not get application ui settings !')
171 raise Exception('Could not get application ui settings !')
172 settings = {}
172 settings = {}
173 for each in ret:
173 for each in ret:
174 k = each.ui_key
174 k = each.ui_key
175 v = each.ui_value
175 v = each.ui_value
176 if k == '/':
176 if k == '/':
177 k = 'root_path'
177 k = 'root_path'
178
178
179 if k.find('.') != -1:
179 if k.find('.') != -1:
180 k = k.replace('.', '_')
180 k = k.replace('.', '_')
181
181
182 if each.ui_section == 'hooks':
182 if each.ui_section == 'hooks':
183 v = each.ui_active
183 v = each.ui_active
184
184
185 settings[each.ui_section + '_' + k] = v
185 settings[each.ui_section + '_' + k] = v
186
186
187 return settings
187 return settings
188
188
189 #propagated from mercurial documentation
189 #propagated from mercurial documentation
190 ui_sections = ['alias', 'auth',
190 ui_sections = ['alias', 'auth',
191 'decode/encode', 'defaults',
191 'decode/encode', 'defaults',
192 'diff', 'email',
192 'diff', 'email',
193 'extensions', 'format',
193 'extensions', 'format',
194 'merge-patterns', 'merge-tools',
194 'merge-patterns', 'merge-tools',
195 'hooks', 'http_proxy',
195 'hooks', 'http_proxy',
196 'smtp', 'patch',
196 'smtp', 'patch',
197 'paths', 'profiling',
197 'paths', 'profiling',
198 'server', 'trusted',
198 'server', 'trusted',
199 'ui', 'web', ]
199 'ui', 'web', ]
200
200
201 def make_ui(read_from='file', path=None, checkpaths=True):
201 def make_ui(read_from='file', path=None, checkpaths=True):
202 """
202 """
203 A function that will read python rc files or database
203 A function that will read python rc files or database
204 and make an mercurial ui object from read options
204 and make an mercurial ui object from read options
205
205
206 :param path: path to mercurial config file
206 :param path: path to mercurial config file
207 :param checkpaths: check the path
207 :param checkpaths: check the path
208 :param read_from: read from 'file' or 'db'
208 :param read_from: read from 'file' or 'db'
209 """
209 """
210
210
211 baseui = ui.ui()
211 baseui = ui.ui()
212
212
213 if read_from == 'file':
213 if read_from == 'file':
214 if not os.path.isfile(path):
214 if not os.path.isfile(path):
215 log.warning('Unable to read config file %s' % path)
215 log.warning('Unable to read config file %s' % path)
216 return False
216 return False
217 log.debug('reading hgrc from %s', path)
217 log.debug('reading hgrc from %s', path)
218 cfg = config.config()
218 cfg = config.config()
219 cfg.read(path)
219 cfg.read(path)
220 for section in ui_sections:
220 for section in ui_sections:
221 for k, v in cfg.items(section):
221 for k, v in cfg.items(section):
222 baseui.setconfig(section, k, v)
222 baseui.setconfig(section, k, v)
223 log.debug('settings ui from file[%s]%s:%s', section, k, v)
223 log.debug('settings ui from file[%s]%s:%s', section, k, v)
224
224
225 for k, v in baseui.configitems('extensions'):
225 for k, v in baseui.configitems('extensions'):
226 baseui.setconfig('extensions', k, '0')
226 baseui.setconfig('extensions', k, '0')
227 #just enable mq
227 #just enable mq
228 baseui.setconfig('extensions', 'mq', '1')
228 baseui.setconfig('extensions', 'mq', '1')
229 if checkpaths:check_repo_dir(cfg.items('paths'))
229 if checkpaths:check_repo_dir(cfg.items('paths'))
230
230
231
231
232 elif read_from == 'db':
232 elif read_from == 'db':
233 hg_ui = get_hg_ui_cached()
233 hg_ui = get_hg_ui_cached()
234 for ui_ in hg_ui:
234 for ui_ in hg_ui:
235 if ui_.ui_active:
235 if ui_.ui_active:
236 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section, ui_.ui_key, ui_.ui_value)
236 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section, ui_.ui_key, ui_.ui_value)
237 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
237 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
238
238
239
239
240 return baseui
240 return baseui
241
241
242
242
243 def set_rhodecode_config(config):
243 def set_rhodecode_config(config):
244 hgsettings = get_hg_settings()
244 hgsettings = get_hg_settings()
245
245
246 for k, v in hgsettings.items():
246 for k, v in hgsettings.items():
247 config[k] = v
247 config[k] = v
248
248
249 def invalidate_cache(name, *args):
249 def invalidate_cache(name, *args):
250 """Invalidates given name cache"""
250 """Invalidates given name cache"""
251
251
252 from beaker.cache import region_invalidate
252 from beaker.cache import region_invalidate
253 log.info('INVALIDATING CACHE FOR %s', name)
253 log.info('INVALIDATING CACHE FOR %s', name)
254
254
255 """propagate our arguments to make sure invalidation works. First
255 """propagate our arguments to make sure invalidation works. First
256 argument has to be the name of cached func name give to cache decorator
256 argument has to be the name of cached func name give to cache decorator
257 without that the invalidation would not work"""
257 without that the invalidation would not work"""
258 tmp = [name]
258 tmp = [name]
259 tmp.extend(args)
259 tmp.extend(args)
260 args = tuple(tmp)
260 args = tuple(tmp)
261
261
262 if name == 'cached_repo_list':
262 if name == 'cached_repo_list':
263 from rhodecode.model.hg_model import _get_repos_cached
263 from rhodecode.model.hg_model import _get_repos_cached
264 region_invalidate(_get_repos_cached, None, *args)
264 region_invalidate(_get_repos_cached, None, *args)
265
265
266 if name == 'full_changelog':
266 if name == 'full_changelog':
267 from rhodecode.model.hg_model import _full_changelog_cached
267 from rhodecode.model.hg_model import _full_changelog_cached
268 region_invalidate(_full_changelog_cached, None, *args)
268 region_invalidate(_full_changelog_cached, None, *args)
269
269
270 class EmptyChangeset(BaseChangeset):
270 class EmptyChangeset(BaseChangeset):
271 """
271 """
272 An dummy empty changeset.
272 An dummy empty changeset.
273 """
273 """
274
274
275 revision = -1
275 revision = -1
276 message = ''
276 message = ''
277 author = ''
277 author = ''
278 date = ''
278 date = ''
279 @LazyProperty
279 @LazyProperty
280 def raw_id(self):
280 def raw_id(self):
281 """
281 """
282 Returns raw string identifing this changeset, useful for web
282 Returns raw string identifing this changeset, useful for web
283 representation.
283 representation.
284 """
284 """
285 return '0' * 40
285 return '0' * 40
286
286
287 @LazyProperty
287 @LazyProperty
288 def short_id(self):
288 def short_id(self):
289 return self.raw_id[:12]
289 return self.raw_id[:12]
290
290
291 def get_file_changeset(self, path):
291 def get_file_changeset(self, path):
292 return self
292 return self
293
293
294 def get_file_content(self, path):
294 def get_file_content(self, path):
295 return u''
295 return u''
296
296
297 def get_file_size(self, path):
297 def get_file_size(self, path):
298 return 0
298 return 0
299
299
300 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
300 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
301 """
301 """
302 maps all found repositories into db
302 maps all found repositories into db
303 """
303 """
304 from rhodecode.model.repo_model import RepoModel
304 from rhodecode.model.repo_model import RepoModel
305
305
306 sa = meta.Session
306 sa = meta.Session
307 user = sa.query(User).filter(User.admin == True).first()
307 user = sa.query(User).filter(User.admin == True).first()
308
308
309 rm = RepoModel()
309 rm = RepoModel()
310
310
311 for name, repo in initial_repo_list.items():
311 for name, repo in initial_repo_list.items():
312 if not sa.query(Repository).filter(Repository.repo_name == name).scalar():
312 if not sa.query(Repository).filter(Repository.repo_name == name).scalar():
313 log.info('repository %s not found creating default', name)
313 log.info('repository %s not found creating default', name)
314
314
315 form_data = {
315 form_data = {
316 'repo_name':name,
316 'repo_name':name,
317 'description':repo.description if repo.description != 'unknown' else \
317 'description':repo.description if repo.description != 'unknown' else \
318 'auto description for %s' % name,
318 'auto description for %s' % name,
319 'private':False
319 'private':False
320 }
320 }
321 rm.create(form_data, user, just_db=True)
321 rm.create(form_data, user, just_db=True)
322
322
323
323
324 if remove_obsolete:
324 if remove_obsolete:
325 #remove from database those repositories that are not in the filesystem
325 #remove from database those repositories that are not in the filesystem
326 for repo in sa.query(Repository).all():
326 for repo in sa.query(Repository).all():
327 if repo.repo_name not in initial_repo_list.keys():
327 if repo.repo_name not in initial_repo_list.keys():
328 sa.delete(repo)
328 sa.delete(repo)
329 sa.commit()
329 sa.commit()
330
330
331
331
332 meta.Session.remove()
332 meta.Session.remove()
333
333
334 from UserDict import DictMixin
334 from UserDict import DictMixin
335
335
336 class OrderedDict(dict, DictMixin):
336 class OrderedDict(dict, DictMixin):
337
337
338 def __init__(self, *args, **kwds):
338 def __init__(self, *args, **kwds):
339 if len(args) > 1:
339 if len(args) > 1:
340 raise TypeError('expected at most 1 arguments, got %d' % len(args))
340 raise TypeError('expected at most 1 arguments, got %d' % len(args))
341 try:
341 try:
342 self.__end
342 self.__end
343 except AttributeError:
343 except AttributeError:
344 self.clear()
344 self.clear()
345 self.update(*args, **kwds)
345 self.update(*args, **kwds)
346
346
347 def clear(self):
347 def clear(self):
348 self.__end = end = []
348 self.__end = end = []
349 end += [None, end, end] # sentinel node for doubly linked list
349 end += [None, end, end] # sentinel node for doubly linked list
350 self.__map = {} # key --> [key, prev, next]
350 self.__map = {} # key --> [key, prev, next]
351 dict.clear(self)
351 dict.clear(self)
352
352
353 def __setitem__(self, key, value):
353 def __setitem__(self, key, value):
354 if key not in self:
354 if key not in self:
355 end = self.__end
355 end = self.__end
356 curr = end[1]
356 curr = end[1]
357 curr[2] = end[1] = self.__map[key] = [key, curr, end]
357 curr[2] = end[1] = self.__map[key] = [key, curr, end]
358 dict.__setitem__(self, key, value)
358 dict.__setitem__(self, key, value)
359
359
360 def __delitem__(self, key):
360 def __delitem__(self, key):
361 dict.__delitem__(self, key)
361 dict.__delitem__(self, key)
362 key, prev, next = self.__map.pop(key)
362 key, prev, next = self.__map.pop(key)
363 prev[2] = next
363 prev[2] = next
364 next[1] = prev
364 next[1] = prev
365
365
366 def __iter__(self):
366 def __iter__(self):
367 end = self.__end
367 end = self.__end
368 curr = end[2]
368 curr = end[2]
369 while curr is not end:
369 while curr is not end:
370 yield curr[0]
370 yield curr[0]
371 curr = curr[2]
371 curr = curr[2]
372
372
373 def __reversed__(self):
373 def __reversed__(self):
374 end = self.__end
374 end = self.__end
375 curr = end[1]
375 curr = end[1]
376 while curr is not end:
376 while curr is not end:
377 yield curr[0]
377 yield curr[0]
378 curr = curr[1]
378 curr = curr[1]
379
379
380 def popitem(self, last=True):
380 def popitem(self, last=True):
381 if not self:
381 if not self:
382 raise KeyError('dictionary is empty')
382 raise KeyError('dictionary is empty')
383 if last:
383 if last:
384 key = reversed(self).next()
384 key = reversed(self).next()
385 else:
385 else:
386 key = iter(self).next()
386 key = iter(self).next()
387 value = self.pop(key)
387 value = self.pop(key)
388 return key, value
388 return key, value
389
389
390 def __reduce__(self):
390 def __reduce__(self):
391 items = [[k, self[k]] for k in self]
391 items = [[k, self[k]] for k in self]
392 tmp = self.__map, self.__end
392 tmp = self.__map, self.__end
393 del self.__map, self.__end
393 del self.__map, self.__end
394 inst_dict = vars(self).copy()
394 inst_dict = vars(self).copy()
395 self.__map, self.__end = tmp
395 self.__map, self.__end = tmp
396 if inst_dict:
396 if inst_dict:
397 return (self.__class__, (items,), inst_dict)
397 return (self.__class__, (items,), inst_dict)
398 return self.__class__, (items,)
398 return self.__class__, (items,)
399
399
400 def keys(self):
400 def keys(self):
401 return list(self)
401 return list(self)
402
402
403 setdefault = DictMixin.setdefault
403 setdefault = DictMixin.setdefault
404 update = DictMixin.update
404 update = DictMixin.update
405 pop = DictMixin.pop
405 pop = DictMixin.pop
406 values = DictMixin.values
406 values = DictMixin.values
407 items = DictMixin.items
407 items = DictMixin.items
408 iterkeys = DictMixin.iterkeys
408 iterkeys = DictMixin.iterkeys
409 itervalues = DictMixin.itervalues
409 itervalues = DictMixin.itervalues
410 iteritems = DictMixin.iteritems
410 iteritems = DictMixin.iteritems
411
411
412 def __repr__(self):
412 def __repr__(self):
413 if not self:
413 if not self:
414 return '%s()' % (self.__class__.__name__,)
414 return '%s()' % (self.__class__.__name__,)
415 return '%s(%r)' % (self.__class__.__name__, self.items())
415 return '%s(%r)' % (self.__class__.__name__, self.items())
416
416
417 def copy(self):
417 def copy(self):
418 return self.__class__(self)
418 return self.__class__(self)
419
419
420 @classmethod
420 @classmethod
421 def fromkeys(cls, iterable, value=None):
421 def fromkeys(cls, iterable, value=None):
422 d = cls()
422 d = cls()
423 for key in iterable:
423 for key in iterable:
424 d[key] = value
424 d[key] = value
425 return d
425 return d
426
426
427 def __eq__(self, other):
427 def __eq__(self, other):
428 if isinstance(other, OrderedDict):
428 if isinstance(other, OrderedDict):
429 return len(self) == len(other) and self.items() == other.items()
429 return len(self) == len(other) and self.items() == other.items()
430 return dict.__eq__(self, other)
430 return dict.__eq__(self, other)
431
431
432 def __ne__(self, other):
432 def __ne__(self, other):
433 return not self == other
433 return not self == other
434
434
435
435
436 #===============================================================================
436 #===============================================================================
437 # TEST FUNCTIONS
437 # TEST FUNCTIONS
438 #===============================================================================
438 #===============================================================================
439 def create_test_index(repo_location, full_index):
439 def create_test_index(repo_location, full_index):
440 """Makes default test index
440 """Makes default test index
441 :param repo_location:
441 :param repo_location:
442 :param full_index:
442 :param full_index:
443 """
443 """
444 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
444 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
445 from rhodecode.lib.pidlock import DaemonLock, LockHeld
445 from rhodecode.lib.pidlock import DaemonLock, LockHeld
446 from rhodecode.lib.indexers import IDX_LOCATION
446 from rhodecode.lib.indexers import IDX_LOCATION
447 import shutil
447 import shutil
448
448
449 if os.path.exists(IDX_LOCATION):
449 if os.path.exists(IDX_LOCATION):
450 shutil.rmtree(IDX_LOCATION)
450 shutil.rmtree(IDX_LOCATION)
451
451
452 try:
452 try:
453 l = DaemonLock()
453 l = DaemonLock()
454 WhooshIndexingDaemon(repo_location=repo_location)\
454 WhooshIndexingDaemon(repo_location=repo_location)\
455 .run(full_index=full_index)
455 .run(full_index=full_index)
456 l.release()
456 l.release()
457 except LockHeld:
457 except LockHeld:
458 pass
458 pass
459
459
460 def create_test_env(repos_test_path, config):
460 def create_test_env(repos_test_path, config):
461 """Makes a fresh database and
461 """Makes a fresh database and
462 install test repository into tmp dir
462 install test repository into tmp dir
463 """
463 """
464 from rhodecode.lib.db_manage import DbManage
464 from rhodecode.lib.db_manage import DbManage
465 import tarfile
465 import tarfile
466 import shutil
466 import shutil
467 from os.path import dirname as dn, join as jn, abspath
467 from os.path import dirname as dn, join as jn, abspath
468 from rhodecode.tests import REPO_PATH, NEW_REPO_PATH
468 from rhodecode.tests import REPO_PATH, NEW_REPO_PATH, FORK_REPO_PATH
469
469
470 log = logging.getLogger('TestEnvCreator')
470 log = logging.getLogger('TestEnvCreator')
471 # create logger
471 # create logger
472 log.setLevel(logging.DEBUG)
472 log.setLevel(logging.DEBUG)
473 log.propagate = True
473 log.propagate = True
474 # create console handler and set level to debug
474 # create console handler and set level to debug
475 ch = logging.StreamHandler()
475 ch = logging.StreamHandler()
476 ch.setLevel(logging.DEBUG)
476 ch.setLevel(logging.DEBUG)
477
477
478 # create formatter
478 # create formatter
479 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
479 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
480
480
481 # add formatter to ch
481 # add formatter to ch
482 ch.setFormatter(formatter)
482 ch.setFormatter(formatter)
483
483
484 # add ch to logger
484 # add ch to logger
485 log.addHandler(ch)
485 log.addHandler(ch)
486
486
487 #PART ONE create db
487 #PART ONE create db
488 dbname = config['sqlalchemy.db1.url'].split('/')[-1]
488 dbname = config['sqlalchemy.db1.url'].split('/')[-1]
489 log.debug('making test db %s', dbname)
489 log.debug('making test db %s', dbname)
490
490
491 dbmanage = DbManage(log_sql=True, dbname=dbname, root=config['here'],
491 dbmanage = DbManage(log_sql=True, dbname=dbname, root=config['here'],
492 tests=True)
492 tests=True)
493 dbmanage.create_tables(override=True)
493 dbmanage.create_tables(override=True)
494 dbmanage.config_prompt(repos_test_path)
494 dbmanage.config_prompt(repos_test_path)
495 dbmanage.create_default_user()
495 dbmanage.create_default_user()
496 dbmanage.admin_prompt()
496 dbmanage.admin_prompt()
497 dbmanage.create_permissions()
497 dbmanage.create_permissions()
498 dbmanage.populate_default_permissions()
498 dbmanage.populate_default_permissions()
499
499
500 #PART TWO make test repo
500 #PART TWO make test repo
501 log.debug('making test vcs repo')
501 log.debug('making test vcs repo')
502 if os.path.isdir(REPO_PATH):
502 if os.path.isdir(REPO_PATH):
503 log.debug('REMOVING %s', REPO_PATH)
503 log.debug('REMOVING %s', REPO_PATH)
504 shutil.rmtree(REPO_PATH)
504 shutil.rmtree(REPO_PATH)
505 if os.path.isdir(NEW_REPO_PATH):
505 if os.path.isdir(NEW_REPO_PATH):
506 log.debug('REMOVING %s', NEW_REPO_PATH)
506 log.debug('REMOVING %s', NEW_REPO_PATH)
507 shutil.rmtree(NEW_REPO_PATH)
507 shutil.rmtree(NEW_REPO_PATH)
508 if os.path.isdir(FORK_REPO_PATH):
509 log.debug('REMOVING %s', FORK_REPO_PATH)
510 shutil.rmtree(FORK_REPO_PATH)
508
511
509 cur_dir = dn(dn(abspath(__file__)))
512 cur_dir = dn(dn(abspath(__file__)))
510 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test.tar.gz"))
513 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test.tar.gz"))
511 tar.extractall('/tmp')
514 tar.extractall('/tmp')
512 tar.close()
515 tar.close()
@@ -1,60 +1,61 b''
1 """Pylons application test package
1 """Pylons application test package
2
2
3 This package assumes the Pylons environment is already loaded, such as
3 This package assumes the Pylons environment is already loaded, such as
4 when this script is imported from the `nosetests --with-pylons=test.ini`
4 when this script is imported from the `nosetests --with-pylons=test.ini`
5 command.
5 command.
6
6
7 This module initializes the application via ``websetup`` (`paster
7 This module initializes the application via ``websetup`` (`paster
8 setup-app`) and provides the base testing objects.
8 setup-app`) and provides the base testing objects.
9 """
9 """
10 from unittest import TestCase
10 from unittest import TestCase
11
11
12 from paste.deploy import loadapp
12 from paste.deploy import loadapp
13 from paste.script.appinstall import SetupCommand
13 from paste.script.appinstall import SetupCommand
14 from pylons import config, url
14 from pylons import config, url
15 from routes.util import URLGenerator
15 from routes.util import URLGenerator
16 from webtest import TestApp
16 from webtest import TestApp
17 import os
17 import os
18 from rhodecode.model import meta
18 from rhodecode.model import meta
19 import logging
19 import logging
20
20
21 log = logging.getLogger(__name__)
21 log = logging.getLogger(__name__)
22
22
23 import pylons.test
23 import pylons.test
24
24
25 __all__ = ['environ', 'url', 'TestController']
25 __all__ = ['environ', 'url', 'TestController']
26
26
27 # Invoke websetup with the current config file
27 # Invoke websetup with the current config file
28 #SetupCommand('setup-app').run([config_file])
28 #SetupCommand('setup-app').run([config_file])
29
29
30 ##RUNNING DESIRED TESTS
30 ##RUNNING DESIRED TESTS
31 #nosetests rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account
31 #nosetests rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account
32
32
33 environ = {}
33 environ = {}
34 TEST_DIR = '/tmp'
34 TEST_DIR = '/tmp'
35 REPO_PATH = os.path.join(TEST_DIR, 'vcs_test')
35 REPO_PATH = os.path.join(TEST_DIR, 'vcs_test')
36 NEW_REPO_PATH = os.path.join(TEST_DIR, 'vcs_test_new')
36 NEW_REPO_PATH = os.path.join(TEST_DIR, 'vcs_test_new')
37 FORK_REPO_PATH = os.path.join(TEST_DIR, 'vcs_test_fork')
37
38
38 class TestController(TestCase):
39 class TestController(TestCase):
39
40
40 def __init__(self, *args, **kwargs):
41 def __init__(self, *args, **kwargs):
41 wsgiapp = pylons.test.pylonsapp
42 wsgiapp = pylons.test.pylonsapp
42 config = wsgiapp.config
43 config = wsgiapp.config
43 self.app = TestApp(wsgiapp)
44 self.app = TestApp(wsgiapp)
44 url._push_object(URLGenerator(config['routes.map'], environ))
45 url._push_object(URLGenerator(config['routes.map'], environ))
45 self.sa = meta.Session
46 self.sa = meta.Session
46
47
47 TestCase.__init__(self, *args, **kwargs)
48 TestCase.__init__(self, *args, **kwargs)
48
49
49 def log_user(self, username='test_admin', password='test12'):
50 def log_user(self, username='test_admin', password='test12'):
50 response = self.app.post(url(controller='login', action='index'),
51 response = self.app.post(url(controller='login', action='index'),
51 {'username':username,
52 {'username':username,
52 'password':password})
53 'password':password})
53 print response
54 print response
54
55
55 if 'invalid user name' in response.body:
56 if 'invalid user name' in response.body:
56 assert False, 'could not login using %s %s' % (username, password)
57 assert False, 'could not login using %s %s' % (username, password)
57
58
58 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
59 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
59 assert response.session['rhodecode_user'].username == username, 'wrong logged in user got %s expected %s' % (response.session['rhodecode_user'].username, username)
60 assert response.session['rhodecode_user'].username == username, 'wrong logged in user got %s expected %s' % (response.session['rhodecode_user'].username, username)
60 return response.follow()
61 return response.follow()
@@ -1,88 +1,88 b''
1 from rhodecode import get_version
1 from rhodecode import get_version
2 import sys
2 import sys
3 py_version = sys.version_info
3 py_version = sys.version_info
4
4
5 requirements = [
5 requirements = [
6 "Pylons>=1.0.0",
6 "Pylons>=1.0.0",
7 "SQLAlchemy==0.6.4",
7 "SQLAlchemy==0.6.5",
8 "Mako>=0.3.2",
8 "Mako>=0.3.2",
9 "vcs==0.1.8",
9 "vcs==0.1.8",
10 "pygments>=1.3.0",
10 "pygments>=1.3.0",
11 "mercurial==1.6.4",
11 "mercurial==1.6.4",
12 "whoosh==1.2.5",
12 "whoosh==1.2.5",
13 "celery==2.1.2",
13 "celery==2.1.3",
14 "py-bcrypt",
14 "py-bcrypt",
15 "babel",
15 "babel",
16 ]
16 ]
17
17
18 classifiers = ["Development Status :: 5 - Production/Stable",
18 classifiers = ["Development Status :: 5 - Production/Stable",
19 'Environment :: Web Environment',
19 'Environment :: Web Environment',
20 'Framework :: Pylons',
20 'Framework :: Pylons',
21 'Intended Audience :: Developers',
21 'Intended Audience :: Developers',
22 'License :: OSI Approved :: BSD License',
22 'License :: OSI Approved :: BSD License',
23 'Operating System :: OS Independent',
23 'Operating System :: OS Independent',
24 'Programming Language :: Python', ]
24 'Programming Language :: Python', ]
25
25
26 if sys.version_info < (2, 6):
26 if sys.version_info < (2, 6):
27 requirements.append("simplejson")
27 requirements.append("simplejson")
28 requirements.append("pysqlite")
28 requirements.append("pysqlite")
29
29
30 #additional files from project that goes somewhere in the filesystem
30 #additional files from project that goes somewhere in the filesystem
31 #relative to sys.prefix
31 #relative to sys.prefix
32 data_files = []
32 data_files = []
33
33
34 #additional files that goes into package itself
34 #additional files that goes into package itself
35 package_data = {'rhodecode': ['i18n/*/LC_MESSAGES/*.mo', ], }
35 package_data = {'rhodecode': ['i18n/*/LC_MESSAGES/*.mo', ], }
36
36
37 description = 'Mercurial repository serving and browsing app'
37 description = 'Mercurial repository serving and browsing app'
38 #long description
38 #long description
39 try:
39 try:
40 readme_file = 'README.rst'
40 readme_file = 'README.rst'
41 long_description = open(readme_file).read()
41 long_description = open(readme_file).read()
42 except IOError, err:
42 except IOError, err:
43 sys.stderr.write("[WARNING] Cannot find file specified as "
43 sys.stderr.write("[WARNING] Cannot find file specified as "
44 "long_description (%s)\n skipping that file" % readme_file)
44 "long_description (%s)\n skipping that file" % readme_file)
45 long_description = description
45 long_description = description
46
46
47
47
48 try:
48 try:
49 from setuptools import setup, find_packages
49 from setuptools import setup, find_packages
50 except ImportError:
50 except ImportError:
51 from ez_setup import use_setuptools
51 from ez_setup import use_setuptools
52 use_setuptools()
52 use_setuptools()
53 from setuptools import setup, find_packages
53 from setuptools import setup, find_packages
54 #packages
54 #packages
55 packages = find_packages(exclude=['ez_setup'])
55 packages = find_packages(exclude=['ez_setup'])
56
56
57 setup(
57 setup(
58 name='RhodeCode',
58 name='RhodeCode',
59 version=get_version(),
59 version=get_version(),
60 description=description,
60 description=description,
61 long_description=long_description,
61 long_description=long_description,
62 keywords='rhodiumcode mercurial web hgwebdir replacement serving hgweb rhodecode',
62 keywords='rhodiumcode mercurial web hgwebdir replacement serving hgweb rhodecode',
63 license='BSD',
63 license='BSD',
64 author='Marcin Kuzminski',
64 author='Marcin Kuzminski',
65 author_email='marcin@python-works.com',
65 author_email='marcin@python-works.com',
66 url='http://hg.python-works.com',
66 url='http://hg.python-works.com',
67 install_requires=requirements,
67 install_requires=requirements,
68 classifiers=classifiers,
68 classifiers=classifiers,
69 setup_requires=["PasteScript>=1.6.3"],
69 setup_requires=["PasteScript>=1.6.3"],
70 data_files=data_files,
70 data_files=data_files,
71 packages=packages,
71 packages=packages,
72 include_package_data=True,
72 include_package_data=True,
73 test_suite='nose.collector',
73 test_suite='nose.collector',
74 package_data=package_data,
74 package_data=package_data,
75 message_extractors={'rhodecode': [
75 message_extractors={'rhodecode': [
76 ('**.py', 'python', None),
76 ('**.py', 'python', None),
77 ('templates/**.mako', 'mako', {'input_encoding': 'utf-8'}),
77 ('templates/**.mako', 'mako', {'input_encoding': 'utf-8'}),
78 ('public/**', 'ignore', None)]},
78 ('public/**', 'ignore', None)]},
79 zip_safe=False,
79 zip_safe=False,
80 paster_plugins=['PasteScript', 'Pylons'],
80 paster_plugins=['PasteScript', 'Pylons'],
81 entry_points="""
81 entry_points="""
82 [paste.app_factory]
82 [paste.app_factory]
83 main = rhodecode.config.middleware:make_app
83 main = rhodecode.config.middleware:make_app
84
84
85 [paste.app_install]
85 [paste.app_install]
86 main = pylons.util:PylonsInstaller
86 main = pylons.util:PylonsInstaller
87 """,
87 """,
88 )
88 )
General Comments 0
You need to be logged in to leave comments. Login now