##// END OF EJS Templates
test env update
marcink -
r1416:df04752d beta
parent child Browse files
Show More
@@ -1,116 +1,115 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.hooks
3 rhodecode.lib.hooks
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Hooks runned by rhodecode
6 Hooks runned by rhodecode
7
7
8 :created_on: Aug 6, 2010
8 :created_on: Aug 6, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 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 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 import os
25 import os
26 import sys
26 import sys
27 import getpass
28
27
29 from mercurial.scmutil import revrange
28 from mercurial.scmutil import revrange
30 from mercurial.node import nullrev
29 from mercurial.node import nullrev
31
30
32 from rhodecode.lib import helpers as h
31 from rhodecode.lib import helpers as h
33 from rhodecode.lib.utils import action_logger
32 from rhodecode.lib.utils import action_logger
34
33
35
34
36 def repo_size(ui, repo, hooktype=None, **kwargs):
35 def repo_size(ui, repo, hooktype=None, **kwargs):
37 """Presents size of repository after push
36 """Presents size of repository after push
38
37
39 :param ui:
38 :param ui:
40 :param repo:
39 :param repo:
41 :param hooktype:
40 :param hooktype:
42 """
41 """
43
42
44 if hooktype != 'changegroup':
43 if hooktype != 'changegroup':
45 return False
44 return False
46 size_hg, size_root = 0, 0
45 size_hg, size_root = 0, 0
47 for path, dirs, files in os.walk(repo.root):
46 for path, dirs, files in os.walk(repo.root):
48 if path.find('.hg') != -1:
47 if path.find('.hg') != -1:
49 for f in files:
48 for f in files:
50 try:
49 try:
51 size_hg += os.path.getsize(os.path.join(path, f))
50 size_hg += os.path.getsize(os.path.join(path, f))
52 except OSError:
51 except OSError:
53 pass
52 pass
54 else:
53 else:
55 for f in files:
54 for f in files:
56 try:
55 try:
57 size_root += os.path.getsize(os.path.join(path, f))
56 size_root += os.path.getsize(os.path.join(path, f))
58 except OSError:
57 except OSError:
59 pass
58 pass
60
59
61 size_hg_f = h.format_byte_size(size_hg)
60 size_hg_f = h.format_byte_size(size_hg)
62 size_root_f = h.format_byte_size(size_root)
61 size_root_f = h.format_byte_size(size_root)
63 size_total_f = h.format_byte_size(size_root + size_hg)
62 size_total_f = h.format_byte_size(size_root + size_hg)
64 sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \
63 sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \
65 % (size_hg_f, size_root_f, size_total_f))
64 % (size_hg_f, size_root_f, size_total_f))
66
65
67
66
68 def log_pull_action(ui, repo, **kwargs):
67 def log_pull_action(ui, repo, **kwargs):
69 """Logs user last pull action
68 """Logs user last pull action
70
69
71 :param ui:
70 :param ui:
72 :param repo:
71 :param repo:
73 """
72 """
74
73
75 extra_params = dict(repo.ui.configitems('rhodecode_extras'))
74 extra_params = dict(repo.ui.configitems('rhodecode_extras'))
76 username = extra_params['username']
75 username = extra_params['username']
77 repository = extra_params['repository']
76 repository = extra_params['repository']
78 action = 'pull'
77 action = 'pull'
79
78
80 action_logger(username, action, repository, extra_params['ip'])
79 action_logger(username, action, repository, extra_params['ip'])
81
80
82 return 0
81 return 0
83
82
84
83
85 def log_push_action(ui, repo, **kwargs):
84 def log_push_action(ui, repo, **kwargs):
86 """Maps user last push action to new changeset id, from mercurial
85 """Maps user last push action to new changeset id, from mercurial
87
86
88 :param ui:
87 :param ui:
89 :param repo:
88 :param repo:
90 """
89 """
91
90
92 extra_params = dict(repo.ui.configitems('rhodecode_extras'))
91 extra_params = dict(repo.ui.configitems('rhodecode_extras'))
93 username = extra_params['username']
92 username = extra_params['username']
94 repository = extra_params['repository']
93 repository = extra_params['repository']
95 action = extra_params['action'] + ':%s'
94 action = extra_params['action'] + ':%s'
96 node = kwargs['node']
95 node = kwargs['node']
97
96
98 def get_revs(repo, rev_opt):
97 def get_revs(repo, rev_opt):
99 if rev_opt:
98 if rev_opt:
100 revs = revrange(repo, rev_opt)
99 revs = revrange(repo, rev_opt)
101
100
102 if len(revs) == 0:
101 if len(revs) == 0:
103 return (nullrev, nullrev)
102 return (nullrev, nullrev)
104 return (max(revs), min(revs))
103 return (max(revs), min(revs))
105 else:
104 else:
106 return (len(repo) - 1, 0)
105 return (len(repo) - 1, 0)
107
106
108 stop, start = get_revs(repo, [node + ':'])
107 stop, start = get_revs(repo, [node + ':'])
109
108
110 revs = (str(repo[r]) for r in xrange(start, stop + 1))
109 revs = (str(repo[r]) for r in xrange(start, stop + 1))
111
110
112 action = action % ','.join(revs)
111 action = action % ','.join(revs)
113
112
114 action_logger(username, action, repository, extra_params['ip'])
113 action_logger(username, action, repository, extra_params['ip'])
115
114
116 return 0
115 return 0
@@ -1,628 +1,603 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.utils
3 rhodecode.lib.utils
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Utilities library for RhodeCode
6 Utilities library for RhodeCode
7
7
8 :created_on: Apr 18, 2010
8 :created_on: Apr 18, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 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 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
25
26 import os
26 import os
27 import logging
27 import logging
28 import datetime
28 import datetime
29 import traceback
29 import traceback
30 import paste
30 import paste
31 import beaker
31 import beaker
32 from os.path import dirname as dn, join as jn
32 from os.path import dirname as dn, join as jn
33
33
34 from paste.script.command import Command, BadCommand
34 from paste.script.command import Command, BadCommand
35
35
36 from UserDict import DictMixin
36 from UserDict import DictMixin
37
37
38 from mercurial import ui, config, hg
38 from mercurial import ui, config, hg
39 from mercurial.error import RepoError
39 from mercurial.error import RepoError
40
40
41 from webhelpers.text import collapse, remove_formatting, strip_tags
41 from webhelpers.text import collapse, remove_formatting, strip_tags
42
42
43 from vcs.backends.base import BaseChangeset
43 from vcs.backends.base import BaseChangeset
44 from vcs.utils.lazy import LazyProperty
44 from vcs.utils.lazy import LazyProperty
45
45
46 from rhodecode.model import meta
46 from rhodecode.model import meta
47 from rhodecode.model.caching_query import FromCache
47 from rhodecode.model.caching_query import FromCache
48 from rhodecode.model.db import Repository, User, RhodeCodeUi, UserLog, Group, \
48 from rhodecode.model.db import Repository, User, RhodeCodeUi, UserLog, Group, \
49 RhodeCodeSettings
49 RhodeCodeSettings
50 from rhodecode.model.repo import RepoModel
50 from rhodecode.model.repo import RepoModel
51 from rhodecode.model.user import UserModel
51 from rhodecode.model.user import UserModel
52
52
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55
55
56 def recursive_replace(str, replace=' '):
56 def recursive_replace(str, replace=' '):
57 """Recursive replace of given sign to just one instance
57 """Recursive replace of given sign to just one instance
58
58
59 :param str: given string
59 :param str: given string
60 :param replace: char to find and replace multiple instances
60 :param replace: char to find and replace multiple instances
61
61
62 Examples::
62 Examples::
63 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
63 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
64 'Mighty-Mighty-Bo-sstones'
64 'Mighty-Mighty-Bo-sstones'
65 """
65 """
66
66
67 if str.find(replace * 2) == -1:
67 if str.find(replace * 2) == -1:
68 return str
68 return str
69 else:
69 else:
70 str = str.replace(replace * 2, replace)
70 str = str.replace(replace * 2, replace)
71 return recursive_replace(str, replace)
71 return recursive_replace(str, replace)
72
72
73
73
74 def repo_name_slug(value):
74 def repo_name_slug(value):
75 """Return slug of name of repository
75 """Return slug of name of repository
76 This function is called on each creation/modification
76 This function is called on each creation/modification
77 of repository to prevent bad names in repo
77 of repository to prevent bad names in repo
78 """
78 """
79
79
80 slug = remove_formatting(value)
80 slug = remove_formatting(value)
81 slug = strip_tags(slug)
81 slug = strip_tags(slug)
82
82
83 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
83 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
84 slug = slug.replace(c, '-')
84 slug = slug.replace(c, '-')
85 slug = recursive_replace(slug, '-')
85 slug = recursive_replace(slug, '-')
86 slug = collapse(slug, '-')
86 slug = collapse(slug, '-')
87 return slug
87 return slug
88
88
89
89
90 def get_repo_slug(request):
90 def get_repo_slug(request):
91 return request.environ['pylons.routes_dict'].get('repo_name')
91 return request.environ['pylons.routes_dict'].get('repo_name')
92
92
93
93
94 def action_logger(user, action, repo, ipaddr='', sa=None):
94 def action_logger(user, action, repo, ipaddr='', sa=None):
95 """
95 """
96 Action logger for various actions made by users
96 Action logger for various actions made by users
97
97
98 :param user: user that made this action, can be a unique username string or
98 :param user: user that made this action, can be a unique username string or
99 object containing user_id attribute
99 object containing user_id attribute
100 :param action: action to log, should be on of predefined unique actions for
100 :param action: action to log, should be on of predefined unique actions for
101 easy translations
101 easy translations
102 :param repo: string name of repository or object containing repo_id,
102 :param repo: string name of repository or object containing repo_id,
103 that action was made on
103 that action was made on
104 :param ipaddr: optional ip address from what the action was made
104 :param ipaddr: optional ip address from what the action was made
105 :param sa: optional sqlalchemy session
105 :param sa: optional sqlalchemy session
106
106
107 """
107 """
108
108
109 if not sa:
109 if not sa:
110 sa = meta.Session()
110 sa = meta.Session()
111
111
112 try:
112 try:
113 um = UserModel()
113 um = UserModel()
114 if hasattr(user, 'user_id'):
114 if hasattr(user, 'user_id'):
115 user_obj = user
115 user_obj = user
116 elif isinstance(user, basestring):
116 elif isinstance(user, basestring):
117 user_obj = um.get_by_username(user, cache=False)
117 user_obj = um.get_by_username(user, cache=False)
118 else:
118 else:
119 raise Exception('You have to provide user object or username')
119 raise Exception('You have to provide user object or username')
120
120
121 rm = RepoModel()
121 rm = RepoModel()
122 if hasattr(repo, 'repo_id'):
122 if hasattr(repo, 'repo_id'):
123 repo_obj = rm.get(repo.repo_id, cache=False)
123 repo_obj = rm.get(repo.repo_id, cache=False)
124 repo_name = repo_obj.repo_name
124 repo_name = repo_obj.repo_name
125 elif isinstance(repo, basestring):
125 elif isinstance(repo, basestring):
126 repo_name = repo.lstrip('/')
126 repo_name = repo.lstrip('/')
127 repo_obj = rm.get_by_repo_name(repo_name, cache=False)
127 repo_obj = rm.get_by_repo_name(repo_name, cache=False)
128 else:
128 else:
129 raise Exception('You have to provide repository to action logger')
129 raise Exception('You have to provide repository to action logger')
130
130
131 user_log = UserLog()
131 user_log = UserLog()
132 user_log.user_id = user_obj.user_id
132 user_log.user_id = user_obj.user_id
133 user_log.action = action
133 user_log.action = action
134
134
135 user_log.repository_id = repo_obj.repo_id
135 user_log.repository_id = repo_obj.repo_id
136 user_log.repository_name = repo_name
136 user_log.repository_name = repo_name
137
137
138 user_log.action_date = datetime.datetime.now()
138 user_log.action_date = datetime.datetime.now()
139 user_log.user_ip = ipaddr
139 user_log.user_ip = ipaddr
140 sa.add(user_log)
140 sa.add(user_log)
141 sa.commit()
141 sa.commit()
142
142
143 log.info('Adding user %s, action %s on %s', user_obj, action, repo)
143 log.info('Adding user %s, action %s on %s', user_obj, action, repo)
144 except:
144 except:
145 log.error(traceback.format_exc())
145 log.error(traceback.format_exc())
146 sa.rollback()
146 sa.rollback()
147
147
148
148
149 def get_repos(path, recursive=False):
149 def get_repos(path, recursive=False):
150 """
150 """
151 Scans given path for repos and return (name,(type,path)) tuple
151 Scans given path for repos and return (name,(type,path)) tuple
152
152
153 :param path: path to scann for repositories
153 :param path: path to scann for repositories
154 :param recursive: recursive search and return names with subdirs in front
154 :param recursive: recursive search and return names with subdirs in front
155 """
155 """
156 from vcs.utils.helpers import get_scm
156 from vcs.utils.helpers import get_scm
157 from vcs.exceptions import VCSError
157 from vcs.exceptions import VCSError
158
158
159 if path.endswith(os.sep):
159 if path.endswith(os.sep):
160 #remove ending slash for better results
160 #remove ending slash for better results
161 path = path[:-1]
161 path = path[:-1]
162
162
163 def _get_repos(p):
163 def _get_repos(p):
164 if not os.access(p, os.W_OK):
164 if not os.access(p, os.W_OK):
165 return
165 return
166 for dirpath in os.listdir(p):
166 for dirpath in os.listdir(p):
167 if os.path.isfile(os.path.join(p, dirpath)):
167 if os.path.isfile(os.path.join(p, dirpath)):
168 continue
168 continue
169 cur_path = os.path.join(p, dirpath)
169 cur_path = os.path.join(p, dirpath)
170 try:
170 try:
171 scm_info = get_scm(cur_path)
171 scm_info = get_scm(cur_path)
172 yield scm_info[1].split(path)[-1].lstrip(os.sep), scm_info
172 yield scm_info[1].split(path)[-1].lstrip(os.sep), scm_info
173 except VCSError:
173 except VCSError:
174 if not recursive:
174 if not recursive:
175 continue
175 continue
176 #check if this dir containts other repos for recursive scan
176 #check if this dir containts other repos for recursive scan
177 rec_path = os.path.join(p, dirpath)
177 rec_path = os.path.join(p, dirpath)
178 if os.path.isdir(rec_path):
178 if os.path.isdir(rec_path):
179 for inner_scm in _get_repos(rec_path):
179 for inner_scm in _get_repos(rec_path):
180 yield inner_scm
180 yield inner_scm
181
181
182 return _get_repos(path)
182 return _get_repos(path)
183
183
184
184
185 def check_repo_fast(repo_name, base_path):
185 def check_repo_fast(repo_name, base_path):
186 """
186 """
187 Check given path for existence of directory
187 Check given path for existence of directory
188 :param repo_name:
188 :param repo_name:
189 :param base_path:
189 :param base_path:
190
190
191 :return False: if this directory is present
191 :return False: if this directory is present
192 """
192 """
193 if os.path.isdir(os.path.join(base_path, repo_name)):
193 if os.path.isdir(os.path.join(base_path, repo_name)):
194 return False
194 return False
195 return True
195 return True
196
196
197
197
198 def check_repo(repo_name, base_path, verify=True):
198 def check_repo(repo_name, base_path, verify=True):
199
199
200 repo_path = os.path.join(base_path, repo_name)
200 repo_path = os.path.join(base_path, repo_name)
201
201
202 try:
202 try:
203 if not check_repo_fast(repo_name, base_path):
203 if not check_repo_fast(repo_name, base_path):
204 return False
204 return False
205 r = hg.repository(ui.ui(), repo_path)
205 r = hg.repository(ui.ui(), repo_path)
206 if verify:
206 if verify:
207 hg.verify(r)
207 hg.verify(r)
208 #here we hnow that repo exists it was verified
208 #here we hnow that repo exists it was verified
209 log.info('%s repo is already created', repo_name)
209 log.info('%s repo is already created', repo_name)
210 return False
210 return False
211 except RepoError:
211 except RepoError:
212 #it means that there is no valid repo there...
212 #it means that there is no valid repo there...
213 log.info('%s repo is free for creation', repo_name)
213 log.info('%s repo is free for creation', repo_name)
214 return True
214 return True
215
215
216
216
217 def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
217 def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
218 while True:
218 while True:
219 ok = raw_input(prompt)
219 ok = raw_input(prompt)
220 if ok in ('y', 'ye', 'yes'):
220 if ok in ('y', 'ye', 'yes'):
221 return True
221 return True
222 if ok in ('n', 'no', 'nop', 'nope'):
222 if ok in ('n', 'no', 'nop', 'nope'):
223 return False
223 return False
224 retries = retries - 1
224 retries = retries - 1
225 if retries < 0:
225 if retries < 0:
226 raise IOError
226 raise IOError
227 print complaint
227 print complaint
228
228
229 #propagated from mercurial documentation
229 #propagated from mercurial documentation
230 ui_sections = ['alias', 'auth',
230 ui_sections = ['alias', 'auth',
231 'decode/encode', 'defaults',
231 'decode/encode', 'defaults',
232 'diff', 'email',
232 'diff', 'email',
233 'extensions', 'format',
233 'extensions', 'format',
234 'merge-patterns', 'merge-tools',
234 'merge-patterns', 'merge-tools',
235 'hooks', 'http_proxy',
235 'hooks', 'http_proxy',
236 'smtp', 'patch',
236 'smtp', 'patch',
237 'paths', 'profiling',
237 'paths', 'profiling',
238 'server', 'trusted',
238 'server', 'trusted',
239 'ui', 'web', ]
239 'ui', 'web', ]
240
240
241
241
242 def make_ui(read_from='file', path=None, checkpaths=True):
242 def make_ui(read_from='file', path=None, checkpaths=True):
243 """A function that will read python rc files or database
243 """A function that will read python rc files or database
244 and make an mercurial ui object from read options
244 and make an mercurial ui object from read options
245
245
246 :param path: path to mercurial config file
246 :param path: path to mercurial config file
247 :param checkpaths: check the path
247 :param checkpaths: check the path
248 :param read_from: read from 'file' or 'db'
248 :param read_from: read from 'file' or 'db'
249 """
249 """
250
250
251 baseui = ui.ui()
251 baseui = ui.ui()
252
252
253 #clean the baseui object
253 #clean the baseui object
254 baseui._ocfg = config.config()
254 baseui._ocfg = config.config()
255 baseui._ucfg = config.config()
255 baseui._ucfg = config.config()
256 baseui._tcfg = config.config()
256 baseui._tcfg = config.config()
257
257
258 if read_from == 'file':
258 if read_from == 'file':
259 if not os.path.isfile(path):
259 if not os.path.isfile(path):
260 log.warning('Unable to read config file %s' % path)
260 log.warning('Unable to read config file %s' % path)
261 return False
261 return False
262 log.debug('reading hgrc from %s', path)
262 log.debug('reading hgrc from %s', path)
263 cfg = config.config()
263 cfg = config.config()
264 cfg.read(path)
264 cfg.read(path)
265 for section in ui_sections:
265 for section in ui_sections:
266 for k, v in cfg.items(section):
266 for k, v in cfg.items(section):
267 log.debug('settings ui from file[%s]%s:%s', section, k, v)
267 log.debug('settings ui from file[%s]%s:%s', section, k, v)
268 baseui.setconfig(section, k, v)
268 baseui.setconfig(section, k, v)
269
269
270 elif read_from == 'db':
270 elif read_from == 'db':
271 sa = meta.Session()
271 sa = meta.Session()
272 ret = sa.query(RhodeCodeUi)\
272 ret = sa.query(RhodeCodeUi)\
273 .options(FromCache("sql_cache_short",
273 .options(FromCache("sql_cache_short",
274 "get_hg_ui_settings")).all()
274 "get_hg_ui_settings")).all()
275
275
276 hg_ui = ret
276 hg_ui = ret
277 for ui_ in hg_ui:
277 for ui_ in hg_ui:
278 if ui_.ui_active:
278 if ui_.ui_active:
279 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
279 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
280 ui_.ui_key, ui_.ui_value)
280 ui_.ui_key, ui_.ui_value)
281 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
281 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
282
282
283 meta.Session.remove()
283 meta.Session.remove()
284 return baseui
284 return baseui
285
285
286
286
287 def set_rhodecode_config(config):
287 def set_rhodecode_config(config):
288 """Updates pylons config with new settings from database
288 """Updates pylons config with new settings from database
289
289
290 :param config:
290 :param config:
291 """
291 """
292 hgsettings = RhodeCodeSettings.get_app_settings()
292 hgsettings = RhodeCodeSettings.get_app_settings()
293
293
294 for k, v in hgsettings.items():
294 for k, v in hgsettings.items():
295 config[k] = v
295 config[k] = v
296
296
297
297
298 def invalidate_cache(cache_key, *args):
298 def invalidate_cache(cache_key, *args):
299 """Puts cache invalidation task into db for
299 """Puts cache invalidation task into db for
300 further global cache invalidation
300 further global cache invalidation
301 """
301 """
302
302
303 from rhodecode.model.scm import ScmModel
303 from rhodecode.model.scm import ScmModel
304
304
305 if cache_key.startswith('get_repo_cached_'):
305 if cache_key.startswith('get_repo_cached_'):
306 name = cache_key.split('get_repo_cached_')[-1]
306 name = cache_key.split('get_repo_cached_')[-1]
307 ScmModel().mark_for_invalidation(name)
307 ScmModel().mark_for_invalidation(name)
308
308
309
309
310 class EmptyChangeset(BaseChangeset):
310 class EmptyChangeset(BaseChangeset):
311 """
311 """
312 An dummy empty changeset. It's possible to pass hash when creating
312 An dummy empty changeset. It's possible to pass hash when creating
313 an EmptyChangeset
313 an EmptyChangeset
314 """
314 """
315
315
316 def __init__(self, cs='0' * 40, repo=None):
316 def __init__(self, cs='0' * 40, repo=None):
317 self._empty_cs = cs
317 self._empty_cs = cs
318 self.revision = -1
318 self.revision = -1
319 self.message = ''
319 self.message = ''
320 self.author = ''
320 self.author = ''
321 self.date = ''
321 self.date = ''
322 self.repository = repo
322 self.repository = repo
323
323
324 @LazyProperty
324 @LazyProperty
325 def raw_id(self):
325 def raw_id(self):
326 """Returns raw string identifying this changeset, useful for web
326 """Returns raw string identifying this changeset, useful for web
327 representation.
327 representation.
328 """
328 """
329
329
330 return self._empty_cs
330 return self._empty_cs
331
331
332 @LazyProperty
332 @LazyProperty
333 def short_id(self):
333 def short_id(self):
334 return self.raw_id[:12]
334 return self.raw_id[:12]
335
335
336 def get_file_changeset(self, path):
336 def get_file_changeset(self, path):
337 return self
337 return self
338
338
339 def get_file_content(self, path):
339 def get_file_content(self, path):
340 return u''
340 return u''
341
341
342 def get_file_size(self, path):
342 def get_file_size(self, path):
343 return 0
343 return 0
344
344
345
345
346 def map_groups(groups):
346 def map_groups(groups):
347 """Checks for groups existence, and creates groups structures.
347 """Checks for groups existence, and creates groups structures.
348 It returns last group in structure
348 It returns last group in structure
349
349
350 :param groups: list of groups structure
350 :param groups: list of groups structure
351 """
351 """
352 sa = meta.Session()
352 sa = meta.Session()
353
353
354 parent = None
354 parent = None
355 group = None
355 group = None
356 for lvl, group_name in enumerate(groups[:-1]):
356 for lvl, group_name in enumerate(groups[:-1]):
357 group = sa.query(Group).filter(Group.group_name == group_name).scalar()
357 group = sa.query(Group).filter(Group.group_name == group_name).scalar()
358
358
359 if group is None:
359 if group is None:
360 group = Group(group_name, parent)
360 group = Group(group_name, parent)
361 sa.add(group)
361 sa.add(group)
362 sa.commit()
362 sa.commit()
363
363
364 parent = group
364 parent = group
365
365
366 return group
366 return group
367
367
368
368
369 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
369 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
370 """maps all repos given in initial_repo_list, non existing repositories
370 """maps all repos given in initial_repo_list, non existing repositories
371 are created, if remove_obsolete is True it also check for db entries
371 are created, if remove_obsolete is True it also check for db entries
372 that are not in initial_repo_list and removes them.
372 that are not in initial_repo_list and removes them.
373
373
374 :param initial_repo_list: list of repositories found by scanning methods
374 :param initial_repo_list: list of repositories found by scanning methods
375 :param remove_obsolete: check for obsolete entries in database
375 :param remove_obsolete: check for obsolete entries in database
376 """
376 """
377
377
378 sa = meta.Session()
378 sa = meta.Session()
379 rm = RepoModel()
379 rm = RepoModel()
380 user = sa.query(User).filter(User.admin == True).first()
380 user = sa.query(User).filter(User.admin == True).first()
381 added = []
381 added = []
382 for name, repo in initial_repo_list.items():
382 for name, repo in initial_repo_list.items():
383 group = map_groups(name.split(os.sep))
383 group = map_groups(name.split(os.sep))
384 if not rm.get_by_repo_name(name, cache=False):
384 if not rm.get_by_repo_name(name, cache=False):
385 log.info('repository %s not found creating default', name)
385 log.info('repository %s not found creating default', name)
386 added.append(name)
386 added.append(name)
387 form_data = {
387 form_data = {
388 'repo_name': name,
388 'repo_name': name,
389 'repo_name_full': name,
389 'repo_name_full': name,
390 'repo_type': repo.alias,
390 'repo_type': repo.alias,
391 'description': repo.description \
391 'description': repo.description \
392 if repo.description != 'unknown' else \
392 if repo.description != 'unknown' else \
393 '%s repository' % name,
393 '%s repository' % name,
394 'private': False,
394 'private': False,
395 'group_id': getattr(group, 'group_id', None)
395 'group_id': getattr(group, 'group_id', None)
396 }
396 }
397 rm.create(form_data, user, just_db=True)
397 rm.create(form_data, user, just_db=True)
398
398
399 removed = []
399 removed = []
400 if remove_obsolete:
400 if remove_obsolete:
401 #remove from database those repositories that are not in the filesystem
401 #remove from database those repositories that are not in the filesystem
402 for repo in sa.query(Repository).all():
402 for repo in sa.query(Repository).all():
403 if repo.repo_name not in initial_repo_list.keys():
403 if repo.repo_name not in initial_repo_list.keys():
404 removed.append(repo.repo_name)
404 removed.append(repo.repo_name)
405 sa.delete(repo)
405 sa.delete(repo)
406 sa.commit()
406 sa.commit()
407
407
408 return added, removed
408 return added, removed
409
409
410 #set cache regions for beaker so celery can utilise it
410 #set cache regions for beaker so celery can utilise it
411 def add_cache(settings):
411 def add_cache(settings):
412 cache_settings = {'regions': None}
412 cache_settings = {'regions': None}
413 for key in settings.keys():
413 for key in settings.keys():
414 for prefix in ['beaker.cache.', 'cache.']:
414 for prefix in ['beaker.cache.', 'cache.']:
415 if key.startswith(prefix):
415 if key.startswith(prefix):
416 name = key.split(prefix)[1].strip()
416 name = key.split(prefix)[1].strip()
417 cache_settings[name] = settings[key].strip()
417 cache_settings[name] = settings[key].strip()
418 if cache_settings['regions']:
418 if cache_settings['regions']:
419 for region in cache_settings['regions'].split(','):
419 for region in cache_settings['regions'].split(','):
420 region = region.strip()
420 region = region.strip()
421 region_settings = {}
421 region_settings = {}
422 for key, value in cache_settings.items():
422 for key, value in cache_settings.items():
423 if key.startswith(region):
423 if key.startswith(region):
424 region_settings[key.split('.')[1]] = value
424 region_settings[key.split('.')[1]] = value
425 region_settings['expire'] = int(region_settings.get('expire',
425 region_settings['expire'] = int(region_settings.get('expire',
426 60))
426 60))
427 region_settings.setdefault('lock_dir',
427 region_settings.setdefault('lock_dir',
428 cache_settings.get('lock_dir'))
428 cache_settings.get('lock_dir'))
429 region_settings.setdefault('data_dir',
429 region_settings.setdefault('data_dir',
430 cache_settings.get('data_dir'))
430 cache_settings.get('data_dir'))
431
431
432 if 'type' not in region_settings:
432 if 'type' not in region_settings:
433 region_settings['type'] = cache_settings.get('type',
433 region_settings['type'] = cache_settings.get('type',
434 'memory')
434 'memory')
435 beaker.cache.cache_regions[region] = region_settings
435 beaker.cache.cache_regions[region] = region_settings
436
436
437
437
438 def get_current_revision():
438 def get_current_revision():
439 """Returns tuple of (number, id) from repository containing this package
439 """Returns tuple of (number, id) from repository containing this package
440 or None if repository could not be found.
440 or None if repository could not be found.
441 """
441 """
442
442
443 try:
443 try:
444 from vcs import get_repo
444 from vcs import get_repo
445 from vcs.utils.helpers import get_scm
445 from vcs.utils.helpers import get_scm
446 from vcs.exceptions import RepositoryError, VCSError
446 from vcs.exceptions import RepositoryError, VCSError
447 repopath = os.path.join(os.path.dirname(__file__), '..', '..')
447 repopath = os.path.join(os.path.dirname(__file__), '..', '..')
448 scm = get_scm(repopath)[0]
448 scm = get_scm(repopath)[0]
449 repo = get_repo(path=repopath, alias=scm)
449 repo = get_repo(path=repopath, alias=scm)
450 tip = repo.get_changeset()
450 tip = repo.get_changeset()
451 return (tip.revision, tip.short_id)
451 return (tip.revision, tip.short_id)
452 except (ImportError, RepositoryError, VCSError), err:
452 except (ImportError, RepositoryError, VCSError), err:
453 logging.debug("Cannot retrieve rhodecode's revision. Original error "
453 logging.debug("Cannot retrieve rhodecode's revision. Original error "
454 "was: %s" % err)
454 "was: %s" % err)
455 return None
455 return None
456
456
457
457
458 #==============================================================================
458 #==============================================================================
459 # TEST FUNCTIONS AND CREATORS
459 # TEST FUNCTIONS AND CREATORS
460 #==============================================================================
460 #==============================================================================
461 def create_test_index(repo_location, config, full_index):
461 def create_test_index(repo_location, config, full_index):
462 """
462 """
463 Makes default test index
463 Makes default test index
464
464
465 :param config: test config
465 :param config: test config
466 :param full_index:
466 :param full_index:
467 """
467 """
468
468
469 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
469 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
470 from rhodecode.lib.pidlock import DaemonLock, LockHeld
470 from rhodecode.lib.pidlock import DaemonLock, LockHeld
471
471
472 repo_location = repo_location
472 repo_location = repo_location
473
473
474 index_location = os.path.join(config['app_conf']['index_dir'])
474 index_location = os.path.join(config['app_conf']['index_dir'])
475 if not os.path.exists(index_location):
475 if not os.path.exists(index_location):
476 os.makedirs(index_location)
476 os.makedirs(index_location)
477
477
478 try:
478 try:
479 l = DaemonLock(file=jn(dn(index_location), 'make_index.lock'))
479 l = DaemonLock(file=jn(dn(index_location), 'make_index.lock'))
480 WhooshIndexingDaemon(index_location=index_location,
480 WhooshIndexingDaemon(index_location=index_location,
481 repo_location=repo_location)\
481 repo_location=repo_location)\
482 .run(full_index=full_index)
482 .run(full_index=full_index)
483 l.release()
483 l.release()
484 except LockHeld:
484 except LockHeld:
485 pass
485 pass
486
486
487
487
488 def create_test_env(repos_test_path, config):
488 def create_test_env(repos_test_path, config):
489 """Makes a fresh database and
489 """Makes a fresh database and
490 install test repository into tmp dir
490 install test repository into tmp dir
491 """
491 """
492 from rhodecode.lib.db_manage import DbManage
492 from rhodecode.lib.db_manage import DbManage
493 from rhodecode.tests import HG_REPO, GIT_REPO, NEW_HG_REPO, NEW_GIT_REPO, \
493 from rhodecode.tests import HG_REPO, GIT_REPO, NEW_HG_REPO, NEW_GIT_REPO, \
494 HG_FORK, GIT_FORK, TESTS_TMP_PATH
494 HG_FORK, GIT_FORK, TESTS_TMP_PATH
495 import tarfile
495 import tarfile
496 import shutil
496 import shutil
497 from os.path import dirname as dn, join as jn, abspath
497 from os.path import abspath
498
499 log = logging.getLogger('TestEnvCreator')
500 # create logger
501 log.setLevel(logging.DEBUG)
502 log.propagate = True
503 # create console handler and set level to debug
504 ch = logging.StreamHandler()
505 ch.setLevel(logging.DEBUG)
506
498
507 # create formatter
499 # PART ONE create db
508 formatter = logging.Formatter("%(asctime)s - %(name)s -"
509 " %(levelname)s - %(message)s")
510
511 # add formatter to ch
512 ch.setFormatter(formatter)
513
514 # add ch to logger
515 log.addHandler(ch)
516
517 #PART ONE create db
518 dbconf = config['sqlalchemy.db1.url']
500 dbconf = config['sqlalchemy.db1.url']
519 log.debug('making test db %s', dbconf)
501 log.debug('making test db %s', dbconf)
520
502
521 # create test dir if it doesn't exist
503 # create test dir if it doesn't exist
522 if not os.path.isdir(repos_test_path):
504 if not os.path.isdir(repos_test_path):
523 log.debug('Creating testdir %s' % repos_test_path)
505 log.debug('Creating testdir %s' % repos_test_path)
524 os.makedirs(repos_test_path)
506 os.makedirs(repos_test_path)
525
507
526 dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=config['here'],
508 dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=config['here'],
527 tests=True)
509 tests=True)
528 dbmanage.create_tables(override=True)
510 dbmanage.create_tables(override=True)
529 dbmanage.create_settings(dbmanage.config_prompt(repos_test_path))
511 dbmanage.create_settings(dbmanage.config_prompt(repos_test_path))
530 dbmanage.create_default_user()
512 dbmanage.create_default_user()
531 dbmanage.admin_prompt()
513 dbmanage.admin_prompt()
532 dbmanage.create_permissions()
514 dbmanage.create_permissions()
533 dbmanage.populate_default_permissions()
515 dbmanage.populate_default_permissions()
534
516
535 #PART TWO make test repo
517 # PART TWO make test repo
536 log.debug('making test vcs repositories')
518 log.debug('making test vcs repositories')
537
519
538 #remove old one from previos tests
539 for r in [HG_REPO, GIT_REPO, NEW_HG_REPO, NEW_GIT_REPO, HG_FORK, GIT_FORK]:
540
541 if os.path.isdir(jn(TESTS_TMP_PATH, r)):
542 log.debug('removing %s', r)
543 shutil.rmtree(jn(TESTS_TMP_PATH, r))
544
545 idx_path = config['app_conf']['index_dir']
520 idx_path = config['app_conf']['index_dir']
546 data_path = config['app_conf']['cache_dir']
521 data_path = config['app_conf']['cache_dir']
547
522
548 #clean index and data
523 #clean index and data
549 if idx_path and os.path.exists(idx_path):
524 if idx_path and os.path.exists(idx_path):
550 log.debug('remove %s' % idx_path)
525 log.debug('remove %s' % idx_path)
551 shutil.rmtree(idx_path)
526 shutil.rmtree(idx_path)
552
527
553 if data_path and os.path.exists(data_path):
528 if data_path and os.path.exists(data_path):
554 log.debug('remove %s' % data_path)
529 log.debug('remove %s' % data_path)
555 shutil.rmtree(data_path)
530 shutil.rmtree(data_path)
556
531
557 #CREATE DEFAULT HG REPOSITORY
532 #CREATE DEFAULT HG REPOSITORY
558 cur_dir = dn(dn(abspath(__file__)))
533 cur_dir = dn(dn(abspath(__file__)))
559 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_hg.tar.gz"))
534 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_hg.tar.gz"))
560 tar.extractall(jn(TESTS_TMP_PATH, HG_REPO))
535 tar.extractall(jn(TESTS_TMP_PATH, HG_REPO))
561 tar.close()
536 tar.close()
562
537
563
538
564 #==============================================================================
539 #==============================================================================
565 # PASTER COMMANDS
540 # PASTER COMMANDS
566 #==============================================================================
541 #==============================================================================
567 class BasePasterCommand(Command):
542 class BasePasterCommand(Command):
568 """
543 """
569 Abstract Base Class for paster commands.
544 Abstract Base Class for paster commands.
570
545
571 The celery commands are somewhat aggressive about loading
546 The celery commands are somewhat aggressive about loading
572 celery.conf, and since our module sets the `CELERY_LOADER`
547 celery.conf, and since our module sets the `CELERY_LOADER`
573 environment variable to our loader, we have to bootstrap a bit and
548 environment variable to our loader, we have to bootstrap a bit and
574 make sure we've had a chance to load the pylons config off of the
549 make sure we've had a chance to load the pylons config off of the
575 command line, otherwise everything fails.
550 command line, otherwise everything fails.
576 """
551 """
577 min_args = 1
552 min_args = 1
578 min_args_error = "Please provide a paster config file as an argument."
553 min_args_error = "Please provide a paster config file as an argument."
579 takes_config_file = 1
554 takes_config_file = 1
580 requires_config_file = True
555 requires_config_file = True
581
556
582 def notify_msg(self, msg, log=False):
557 def notify_msg(self, msg, log=False):
583 """Make a notification to user, additionally if logger is passed
558 """Make a notification to user, additionally if logger is passed
584 it logs this action using given logger
559 it logs this action using given logger
585
560
586 :param msg: message that will be printed to user
561 :param msg: message that will be printed to user
587 :param log: logging instance, to use to additionally log this message
562 :param log: logging instance, to use to additionally log this message
588
563
589 """
564 """
590 if log and isinstance(log, logging):
565 if log and isinstance(log, logging):
591 log(msg)
566 log(msg)
592
567
593 def run(self, args):
568 def run(self, args):
594 """
569 """
595 Overrides Command.run
570 Overrides Command.run
596
571
597 Checks for a config file argument and loads it.
572 Checks for a config file argument and loads it.
598 """
573 """
599 if len(args) < self.min_args:
574 if len(args) < self.min_args:
600 raise BadCommand(
575 raise BadCommand(
601 self.min_args_error % {'min_args': self.min_args,
576 self.min_args_error % {'min_args': self.min_args,
602 'actual_args': len(args)})
577 'actual_args': len(args)})
603
578
604 # Decrement because we're going to lob off the first argument.
579 # Decrement because we're going to lob off the first argument.
605 # @@ This is hacky
580 # @@ This is hacky
606 self.min_args -= 1
581 self.min_args -= 1
607 self.bootstrap_config(args[0])
582 self.bootstrap_config(args[0])
608 self.update_parser()
583 self.update_parser()
609 return super(BasePasterCommand, self).run(args[1:])
584 return super(BasePasterCommand, self).run(args[1:])
610
585
611 def update_parser(self):
586 def update_parser(self):
612 """
587 """
613 Abstract method. Allows for the class's parser to be updated
588 Abstract method. Allows for the class's parser to be updated
614 before the superclass's `run` method is called. Necessary to
589 before the superclass's `run` method is called. Necessary to
615 allow options/arguments to be passed through to the underlying
590 allow options/arguments to be passed through to the underlying
616 celery command.
591 celery command.
617 """
592 """
618 raise NotImplementedError("Abstract Method.")
593 raise NotImplementedError("Abstract Method.")
619
594
620 def bootstrap_config(self, conf):
595 def bootstrap_config(self, conf):
621 """
596 """
622 Loads the pylons configuration.
597 Loads the pylons configuration.
623 """
598 """
624 from pylons import config as pylonsconfig
599 from pylons import config as pylonsconfig
625
600
626 path_to_ini_file = os.path.realpath(conf)
601 path_to_ini_file = os.path.realpath(conf)
627 conf = paste.deploy.appconfig('config:' + path_to_ini_file)
602 conf = paste.deploy.appconfig('config:' + path_to_ini_file)
628 pylonsconfig.init_app(conf.global_conf, conf.local_conf)
603 pylonsconfig.init_app(conf.global_conf, conf.local_conf)
@@ -1,81 +1,85 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 import os
10 import os
11 from os.path import join as jn
11 from os.path import join as jn
12
12
13 from unittest import TestCase
13 from unittest import TestCase
14
14
15 from paste.deploy import loadapp
15 from paste.deploy import loadapp
16 from paste.script.appinstall import SetupCommand
16 from paste.script.appinstall import SetupCommand
17 from pylons import config, url
17 from pylons import config, url
18 from routes.util import URLGenerator
18 from routes.util import URLGenerator
19 from webtest import TestApp
19 from webtest import TestApp
20
20
21 from rhodecode.model import meta
21 from rhodecode.model import meta
22 import logging
22 import logging
23
23
24
24
25 log = logging.getLogger(__name__)
25 log = logging.getLogger(__name__)
26
26
27 import pylons.test
27 import pylons.test
28
28
29 __all__ = ['environ', 'url', 'TestController', 'TESTS_TMP_PATH', 'HG_REPO',
29 __all__ = ['environ', 'url', 'TestController', 'TESTS_TMP_PATH', 'HG_REPO',
30 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO', 'HG_FORK', 'GIT_FORK', ]
30 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO', 'HG_FORK', 'GIT_FORK',
31 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS' ]
31
32
32 # Invoke websetup with the current config file
33 # Invoke websetup with the current config file
33 #SetupCommand('setup-app').run([config_file])
34 #SetupCommand('setup-app').run([config_file])
34
35
35 ##RUNNING DESIRED TESTS
36 ##RUNNING DESIRED TESTS
36 #nosetests -x rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account
37 # nosetests -x rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account
37
38 # nosetests --pdb --pdb-failures
38 environ = {}
39 environ = {}
39
40
40 #SOME GLOBALS FOR TESTS
41 #SOME GLOBALS FOR TESTS
41 from tempfile import _RandomNameSequence
42 from tempfile import _RandomNameSequence
42 TESTS_TMP_PATH = jn('/', 'tmp', 'rc_test_%s' % _RandomNameSequence().next())
43 TESTS_TMP_PATH = jn('/', 'tmp', 'rc_test_%s' % _RandomNameSequence().next())
44 TEST_USER_ADMIN_LOGIN = 'test_admin'
45 TEST_USER_ADMIN_PASS = 'test12'
43 HG_REPO = 'vcs_test_hg'
46 HG_REPO = 'vcs_test_hg'
44 GIT_REPO = 'vcs_test_git'
47 GIT_REPO = 'vcs_test_git'
45
48
46 NEW_HG_REPO = 'vcs_test_hg_new'
49 NEW_HG_REPO = 'vcs_test_hg_new'
47 NEW_GIT_REPO = 'vcs_test_git_new'
50 NEW_GIT_REPO = 'vcs_test_git_new'
48
51
49 HG_FORK = 'vcs_test_hg_fork'
52 HG_FORK = 'vcs_test_hg_fork'
50 GIT_FORK = 'vcs_test_git_fork'
53 GIT_FORK = 'vcs_test_git_fork'
51
54
52 class TestController(TestCase):
55 class TestController(TestCase):
53
56
54 def __init__(self, *args, **kwargs):
57 def __init__(self, *args, **kwargs):
55 wsgiapp = pylons.test.pylonsapp
58 wsgiapp = pylons.test.pylonsapp
56 config = wsgiapp.config
59 config = wsgiapp.config
57
60
58 self.app = TestApp(wsgiapp)
61 self.app = TestApp(wsgiapp)
59 url._push_object(URLGenerator(config['routes.map'], environ))
62 url._push_object(URLGenerator(config['routes.map'], environ))
60 self.sa = meta.Session
63 self.sa = meta.Session
61 self.index_location = config['app_conf']['index_dir']
64 self.index_location = config['app_conf']['index_dir']
62 TestCase.__init__(self, *args, **kwargs)
65 TestCase.__init__(self, *args, **kwargs)
63
66
64 def log_user(self, username='test_admin', password='test12'):
67 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
68 password=TEST_USER_ADMIN_PASS):
65 response = self.app.post(url(controller='login', action='index'),
69 response = self.app.post(url(controller='login', action='index'),
66 {'username':username,
70 {'username':username,
67 'password':password})
71 'password':password})
68
72
69 if 'invalid user name' in response.body:
73 if 'invalid user name' in response.body:
70 self.fail('could not login using %s %s' % (username, password))
74 self.fail('could not login using %s %s' % (username, password))
71
75
72 self.assertEqual(response.status, '302 Found')
76 self.assertEqual(response.status, '302 Found')
73 self.assertEqual(response.session['rhodecode_user'].username, username)
77 self.assertEqual(response.session['rhodecode_user'].username, username)
74 return response.follow()
78 return response.follow()
75
79
76
80
77
81
78 def checkSessionFlash(self, response, msg):
82 def checkSessionFlash(self, response, msg):
79 self.assertTrue('flash' in response.session)
83 self.assertTrue('flash' in response.session)
80 self.assertTrue(msg in response.session['flash'][0][1])
84 self.assertTrue(msg in response.session['flash'][0][1])
81
85
@@ -1,94 +1,93 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.tests.test_libs
3 rhodecode.tests.test_libs
4 ~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6
6
7 Package for testing varios lib/helper functions in rhodecode
7 Package for testing various lib/helper functions in rhodecode
8
8
9 :created_on: Jun 9, 2011
9 :created_on: Jun 9, 2011
10 :copyright: (c) 2011 by marcink.
10 :copyright: (c) 2011 by marcink.
11 :license: LICENSE_NAME, see LICENSE_FILE for more details.
11 :license: LICENSE_NAME, see LICENSE_FILE for more details.
12 """
12 """
13
13
14
14
15
15
16 import unittest
16 import unittest
17 from rhodecode.tests import *
17 from rhodecode.tests import *
18
18
19
20 proto = 'http'
19 proto = 'http'
21 TEST_URLS = [
20 TEST_URLS = [
22 ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
21 ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
23 '%s://127.0.0.1' % proto),
22 '%s://127.0.0.1' % proto),
24 ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
23 ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
25 '%s://127.0.0.1' % proto),
24 '%s://127.0.0.1' % proto),
26 ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
25 ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
27 '%s://127.0.0.1' % proto),
26 '%s://127.0.0.1' % proto),
28 ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'],
27 ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'],
29 '%s://127.0.0.1:8080' % proto),
28 '%s://127.0.0.1:8080' % proto),
30 ('%s://domain.org' % proto, ['%s://' % proto, 'domain.org'],
29 ('%s://domain.org' % proto, ['%s://' % proto, 'domain.org'],
31 '%s://domain.org' % proto),
30 '%s://domain.org' % proto),
32 ('%s://user:pass@domain.org:8080' % proto, ['%s://' % proto, 'domain.org',
31 ('%s://user:pass@domain.org:8080' % proto, ['%s://' % proto, 'domain.org',
33 '8080'],
32 '8080'],
34 '%s://domain.org:8080' % proto),
33 '%s://domain.org:8080' % proto),
35 ]
34 ]
36
35
37 proto = 'https'
36 proto = 'https'
38 TEST_URLS += [
37 TEST_URLS += [
39 ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
38 ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
40 '%s://127.0.0.1' % proto),
39 '%s://127.0.0.1' % proto),
41 ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
40 ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
42 '%s://127.0.0.1' % proto),
41 '%s://127.0.0.1' % proto),
43 ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
42 ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
44 '%s://127.0.0.1' % proto),
43 '%s://127.0.0.1' % proto),
45 ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'],
44 ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'],
46 '%s://127.0.0.1:8080' % proto),
45 '%s://127.0.0.1:8080' % proto),
47 ('%s://domain.org' % proto, ['%s://' % proto, 'domain.org'],
46 ('%s://domain.org' % proto, ['%s://' % proto, 'domain.org'],
48 '%s://domain.org' % proto),
47 '%s://domain.org' % proto),
49 ('%s://user:pass@domain.org:8080' % proto, ['%s://' % proto, 'domain.org',
48 ('%s://user:pass@domain.org:8080' % proto, ['%s://' % proto, 'domain.org',
50 '8080'],
49 '8080'],
51 '%s://domain.org:8080' % proto),
50 '%s://domain.org:8080' % proto),
52 ]
51 ]
53
52
54
53
55 class TestLibs(unittest.TestCase):
54 class TestLibs(unittest.TestCase):
56
55
57
56
58 def test_uri_filter(self):
57 def test_uri_filter(self):
59 from rhodecode.lib import uri_filter
58 from rhodecode.lib import uri_filter
60
59
61 for url in TEST_URLS:
60 for url in TEST_URLS:
62 self.assertEqual(uri_filter(url[0]), url[1])
61 self.assertEqual(uri_filter(url[0]), url[1])
63
62
64 def test_credentials_filter(self):
63 def test_credentials_filter(self):
65 from rhodecode.lib import credentials_filter
64 from rhodecode.lib import credentials_filter
66
65
67 for url in TEST_URLS:
66 for url in TEST_URLS:
68 self.assertEqual(credentials_filter(url[0]), url[2])
67 self.assertEqual(credentials_filter(url[0]), url[2])
69
68
70
69
71 def test_str2bool(self):
70 def test_str2bool(self):
72 from rhodecode.lib import str2bool
71 from rhodecode.lib import str2bool
73 test_cases = [
72 test_cases = [
74 ('t', True),
73 ('t', True),
75 ('true', True),
74 ('true', True),
76 ('y', True),
75 ('y', True),
77 ('yes', True),
76 ('yes', True),
78 ('on', True),
77 ('on', True),
79 ('1', True),
78 ('1', True),
80 ('Y', True),
79 ('Y', True),
81 ('yeS', True),
80 ('yeS', True),
82 ('Y', True),
81 ('Y', True),
83 ('TRUE', True),
82 ('TRUE', True),
84 ('T', True),
83 ('T', True),
85 ('False', False),
84 ('False', False),
86 ('F', False),
85 ('F', False),
87 ('FALSE', False),
86 ('FALSE', False),
88 ('0', False),
87 ('0', False),
89 ('-1', False),
88 ('-1', False),
90 ('', False), ]
89 ('', False), ]
91
90
92 for case in test_cases:
91 for case in test_cases:
93 self.assertEqual(str2bool(case[0]), case[1])
92 self.assertEqual(str2bool(case[0]), case[1])
94
93
@@ -1,42 +1,43 b''
1 [egg_info]
1 [egg_info]
2 tag_build = beta
2 tag_build = beta
3 tag_svn_revision = true
3 tag_svn_revision = true
4
4
5 [easy_install]
5 [easy_install]
6 find_links = http://www.pylonshq.com/download/
6 find_links = http://www.pylonshq.com/download/
7
7
8 [nosetests]
8 [nosetests]
9 verbose=True
9 verbose=False
10 verbosity=2
10 verbosity=2
11 with-pylons=test.ini
11 with-pylons=test.ini
12 detailed-errors=1
12 detailed-errors=0
13 nologcapture=1
13
14
14 # Babel configuration
15 # Babel configuration
15 [compile_catalog]
16 [compile_catalog]
16 domain = rhodecode
17 domain = rhodecode
17 directory = rhodecode/i18n
18 directory = rhodecode/i18n
18 statistics = true
19 statistics = true
19
20
20 [extract_messages]
21 [extract_messages]
21 add_comments = TRANSLATORS:
22 add_comments = TRANSLATORS:
22 output_file = rhodecode/i18n/rhodecode.pot
23 output_file = rhodecode/i18n/rhodecode.pot
23 width = 80
24 width = 80
24
25
25 [init_catalog]
26 [init_catalog]
26 domain = rhodecode
27 domain = rhodecode
27 input_file = rhodecode/i18n/rhodecode.pot
28 input_file = rhodecode/i18n/rhodecode.pot
28 output_dir = rhodecode/i18n
29 output_dir = rhodecode/i18n
29
30
30 [update_catalog]
31 [update_catalog]
31 domain = rhodecode
32 domain = rhodecode
32 input_file = rhodecode/i18n/rhodecode.pot
33 input_file = rhodecode/i18n/rhodecode.pot
33 output_dir = rhodecode/i18n
34 output_dir = rhodecode/i18n
34 previous = true
35 previous = true
35
36
36 [build_sphinx]
37 [build_sphinx]
37 source-dir = docs/
38 source-dir = docs/
38 build-dir = docs/_build
39 build-dir = docs/_build
39 all_files = 1
40 all_files = 1
40
41
41 [upload_sphinx]
42 [upload_sphinx]
42 upload-dir = docs/_build/html No newline at end of file
43 upload-dir = docs/_build/html
General Comments 0
You need to be logged in to leave comments. Login now