##// END OF EJS Templates
merge with beta
marcink -
r2908:3148c08c merge rhodecode-0.0.1.4.4 default
parent child Browse files
Show More
@@ -28,3 +28,4 b' List of contributors to RhodeCode projec'
28 Vincent Caron <vcaron@bearstech.com>
28 Vincent Caron <vcaron@bearstech.com>
29 Zachary Auclair <zach101@gmail.com>
29 Zachary Auclair <zach101@gmail.com>
30 Stefan Engel <mail@engel-stefan.de>
30 Stefan Engel <mail@engel-stefan.de>
31 Andrew Shadura <bugzilla@tut.by> No newline at end of file
@@ -438,21 +438,6 b' OUTPUT::'
438 "users_group_id" : "<id>",
438 "users_group_id" : "<id>",
439 "group_name" : "<groupname>",
439 "group_name" : "<groupname>",
440 "active": "<bool>",
440 "active": "<bool>",
441 "members" : [
442 {
443 "user_id" : "<user_id>",
444 "username" : "<username>",
445 "firstname": "<firstname>",
446 "lastname" : "<lastname>",
447 "email" : "<email>",
448 "emails": "<list_of_all_additional_emails>",
449 "active" : "<bool>",
450 "admin" :  "<bool>",
451 "ldap_dn" : "<ldap_dn>",
452 "last_login": "<last_login>",
453 },
454
455 ]
456 },
441 },
457
442
458 ]
443 ]
@@ -485,21 +470,6 b' OUTPUT::'
485 "users_group_id" : "<id>",
470 "users_group_id" : "<id>",
486 "group_name" : "<groupname>",
471 "group_name" : "<groupname>",
487 "active": "<bool>",
472 "active": "<bool>",
488 "members" : [
489 {
490 "user_id" : "<user_id>",
491 "username" : "<username>",
492 "firstname": "<firstname>",
493 "lastname" : "<lastname>",
494 "email" : "<email>",
495 "emails": "<list_of_all_additional_emails>",
496 "active" : "<bool>",
497 "admin" :  "<bool>",
498 "ldap_dn" : "<ldap_dn>",
499 "last_login": "<last_login>",
500 },
501
502 ]
503 },
473 },
504 }
474 }
505 error: null
475 error: null
@@ -14,6 +14,7 b' news'
14 - #574 Show pull request status also in shortlog (if any)
14 - #574 Show pull request status also in shortlog (if any)
15 - remember selected tab in my account page
15 - remember selected tab in my account page
16 - Bumped mercurial version to 2.3.2
16 - Bumped mercurial version to 2.3.2
17 - #595 rcextension hook for repository delete
17
18
18 fixes
19 fixes
19 +++++
20 +++++
@@ -30,6 +31,8 b' fixes'
30 status. Checks now are made also for the repository.
31 status. Checks now are made also for the repository.
31 - fixes #591 git backend was causing encoding errors when handling binary
32 - fixes #591 git backend was causing encoding errors when handling binary
32 files - added a test case for VCS lib tests
33 files - added a test case for VCS lib tests
34 - fixed #597 commits in future get negative age.
35 - fixed #598 API docs methods had wrong members parameter as returned data
33
36
34 1.4.3 (**2012-09-28**)
37 1.4.3 (**2012-09-28**)
35 ----------------------
38 ----------------------
@@ -71,8 +71,8 b' functionality. To do this simply execute'
71
71
72 This will create `rcextensions` package in the same place that your `ini` file
72 This will create `rcextensions` package in the same place that your `ini` file
73 lives. With `rcextensions` it's possible to add additional mapping for whoosh,
73 lives. With `rcextensions` it's possible to add additional mapping for whoosh,
74 stats and add additional code into the push/pull/create repo hooks. For example
74 stats and add additional code into the push/pull/create/delete repo hooks.
75 for sending signals to build-bots such as jenkins.
75 For example for sending signals to build-bots such as jenkins.
76 Please see the `__init__.py` file inside `rcextensions` package
76 Please see the `__init__.py` file inside `rcextensions` package
77 for more details.
77 for more details.
78
78
@@ -40,12 +40,38 b' def _crhook(*args, **kwargs):'
40 :param group_id:
40 :param group_id:
41 :param created_by:
41 :param created_by:
42 """
42 """
43
44 return 0
43 return 0
45 CREATE_REPO_HOOK = _crhook
44 CREATE_REPO_HOOK = _crhook
46
45
47
46
48 #==============================================================================
47 #==============================================================================
48 # POST DELETE REPOSITORY HOOK
49 #==============================================================================
50 # this function will be executed after each repository deletion
51 def _dlhook(*args, **kwargs):
52 """
53 Post create repository HOOK
54 kwargs available:
55 :param repo_name:
56 :param repo_type:
57 :param description:
58 :param private:
59 :param created_on:
60 :param enable_downloads:
61 :param repo_id:
62 :param user_id:
63 :param enable_statistics:
64 :param clone_uri:
65 :param fork_id:
66 :param group_id:
67 :param deleted_by:
68 :param deleted_on:
69 """
70 return 0
71 DELETE_REPO_HOOK = _dlhook
72
73
74 #==============================================================================
49 # POST PUSH HOOK
75 # POST PUSH HOOK
50 #==============================================================================
76 #==============================================================================
51
77
@@ -188,4 +188,3 b' class SettingsController(BaseRepoControl'
188 h.flash(_('An error occurred during unlocking'),
188 h.flash(_('An error occurred during unlocking'),
189 category='error')
189 category='error')
190 return redirect(url('summary_home', repo_name=repo_name))
190 return redirect(url('summary_home', repo_name=repo_name))
191
@@ -667,4 +667,4 b' class DbManage(object):'
667 if not __py_version__ >= (2, 6):
667 if not __py_version__ >= (2, 6):
668 notify('Python2.5 detected, please switch '
668 notify('Python2.5 detected, please switch '
669 'egg:waitress#main -> egg:Paste#http '
669 'egg:waitress#main -> egg:Paste#http '
670 'in your .ini file') No newline at end of file
670 'in your .ini file')
@@ -24,6 +24,7 b''
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 time
27 import binascii
28 import binascii
28 from inspect import isfunction
29 from inspect import isfunction
29
30
@@ -38,6 +39,7 b' from rhodecode.lib.exceptions import HTT'
38 from rhodecode.lib.utils2 import safe_str
39 from rhodecode.lib.utils2 import safe_str
39 from rhodecode.model.db import Repository, User
40 from rhodecode.model.db import Repository, User
40
41
42
41 def _get_scm_size(alias, root_path):
43 def _get_scm_size(alias, root_path):
42
44
43 if not alias.startswith('.'):
45 if not alias.startswith('.'):
@@ -262,7 +264,6 b' def log_create_repository(repository_dic'
262
264
263 :param repository: dict dump of repository object
265 :param repository: dict dump of repository object
264 :param created_by: username who created repository
266 :param created_by: username who created repository
265 :param created_date: date of creation
266
267
267 available keys of repository_dict:
268 available keys of repository_dict:
268
269
@@ -291,6 +292,45 b' def log_create_repository(repository_dic'
291
292
292 return 0
293 return 0
293
294
295
296 def log_delete_repository(repository_dict, deleted_by, **kwargs):
297 """
298 Post delete repository Hook. This is a dummy function for admins to re-use
299 if needed. It's taken from rhodecode-extensions module and executed
300 if present
301
302 :param repository: dict dump of repository object
303 :param deleted_by: username who deleted the repository
304
305 available keys of repository_dict:
306
307 'repo_type',
308 'description',
309 'private',
310 'created_on',
311 'enable_downloads',
312 'repo_id',
313 'user_id',
314 'enable_statistics',
315 'clone_uri',
316 'fork_id',
317 'group_id',
318 'repo_name'
319
320 """
321 from rhodecode import EXTENSIONS
322 callback = getattr(EXTENSIONS, 'DELETE_REPO_HOOK', None)
323 if isfunction(callback):
324 kw = {}
325 kw.update(repository_dict)
326 kw.update({'deleted_by': deleted_by,
327 'deleted_on': time.time()})
328 kw.update(kwargs)
329 return callback(**kw)
330
331 return 0
332
333
294 handle_git_pre_receive = (lambda repo_path, revs, env:
334 handle_git_pre_receive = (lambda repo_path, revs, env:
295 handle_git_receive(repo_path, revs, env, hook_type='pre'))
335 handle_git_receive(repo_path, revs, env, hook_type='pre'))
296 handle_git_post_receive = (lambda repo_path, revs, env:
336 handle_git_post_receive = (lambda repo_path, revs, env:
@@ -136,7 +136,7 b' def action_logger(user, action, repo, ip'
136 elif isinstance(user, basestring):
136 elif isinstance(user, basestring):
137 user_obj = User.get_by_username(user)
137 user_obj = User.get_by_username(user)
138 else:
138 else:
139 raise Exception('You have to provide user object or username')
139 raise Exception('You have to provide a user object or a username')
140
140
141 if hasattr(repo, 'repo_id'):
141 if hasattr(repo, 'repo_id'):
142 repo_obj = Repository.get(repo.repo_id)
142 repo_obj = Repository.get(repo.repo_id)
@@ -255,7 +255,7 b' def is_valid_repos_group(repos_group_nam'
255 return False
255 return False
256
256
257
257
258 def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
258 def ask_ok(prompt, retries=4, complaint='Yes or no please!'):
259 while True:
259 while True:
260 ok = raw_input(prompt)
260 ok = raw_input(prompt)
261 if ok in ('y', 'ye', 'yes'):
261 if ok in ('y', 'ye', 'yes'):
@@ -299,7 +299,7 b" def make_ui(read_from='file', path=None,"
299
299
300 if read_from == 'file':
300 if read_from == 'file':
301 if not os.path.isfile(path):
301 if not os.path.isfile(path):
302 log.debug('hgrc file is not present at %s skipping...' % path)
302 log.debug('hgrc file is not present at %s, skipping...' % path)
303 return False
303 return False
304 log.debug('reading hgrc from %s' % path)
304 log.debug('reading hgrc from %s' % path)
305 cfg = config.config()
305 cfg = config.config()
@@ -410,7 +410,7 b' def repo2db_mapper(initial_repo_list, re'
410 rm = RepoModel()
410 rm = RepoModel()
411 user = sa.query(User).filter(User.admin == True).first()
411 user = sa.query(User).filter(User.admin == True).first()
412 if user is None:
412 if user is None:
413 raise Exception('Missing administrative account !')
413 raise Exception('Missing administrative account!')
414 added = []
414 added = []
415
415
416 # # clear cache keys
416 # # clear cache keys
@@ -423,7 +423,7 b' def repo2db_mapper(initial_repo_list, re'
423 db_repo = rm.get_by_repo_name(name)
423 db_repo = rm.get_by_repo_name(name)
424 # found repo that is on filesystem not in RhodeCode database
424 # found repo that is on filesystem not in RhodeCode database
425 if not db_repo:
425 if not db_repo:
426 log.info('repository %s not found creating now' % name)
426 log.info('repository %s not found, creating now' % name)
427 added.append(name)
427 added.append(name)
428 desc = (repo.description
428 desc = (repo.description
429 if repo.description != 'unknown'
429 if repo.description != 'unknown'
@@ -446,7 +446,7 b' def repo2db_mapper(initial_repo_list, re'
446 # during starting install all cache keys for all repositories in the
446 # during starting install all cache keys for all repositories in the
447 # system, this will register all repos and multiple instances
447 # system, this will register all repos and multiple instances
448 key, _prefix, _org_key = CacheInvalidation._get_key(name)
448 key, _prefix, _org_key = CacheInvalidation._get_key(name)
449 log.debug("Creating cache key for %s instance_id:`%s`" % (name, _prefix))
449 log.debug("Creating a cache key for %s instance_id:`%s`" % (name, _prefix))
450 CacheInvalidation._get_or_create_key(key, _prefix, _org_key, commit=False)
450 CacheInvalidation._get_or_create_key(key, _prefix, _org_key, commit=False)
451 sa.commit()
451 sa.commit()
452 removed = []
452 removed = []
@@ -454,7 +454,7 b' def repo2db_mapper(initial_repo_list, re'
454 # remove from database those repositories that are not in the filesystem
454 # remove from database those repositories that are not in the filesystem
455 for repo in sa.query(Repository).all():
455 for repo in sa.query(Repository).all():
456 if repo.repo_name not in initial_repo_list.keys():
456 if repo.repo_name not in initial_repo_list.keys():
457 log.debug("Removing non existing repository found in db `%s`" %
457 log.debug("Removing non-existing repository found in db `%s`" %
458 repo.repo_name)
458 repo.repo_name)
459 try:
459 try:
460 sa.delete(repo)
460 sa.delete(repo)
@@ -677,7 +677,7 b' class BasePasterCommand(Command):'
677 def check_git_version():
677 def check_git_version():
678 """
678 """
679 Checks what version of git is installed in system, and issues a warning
679 Checks what version of git is installed in system, and issues a warning
680 if it's to old for RhodeCode to properly work.
680 if it's too old for RhodeCode to properly work.
681 """
681 """
682 import subprocess
682 import subprocess
683 from distutils.version import StrictVersion
683 from distutils.version import StrictVersion
@@ -703,7 +703,7 b' def check_git_version():'
703 if stderr:
703 if stderr:
704 log.warning('Unable to detect git version org error was:%r' % stderr)
704 log.warning('Unable to detect git version org error was:%r' % stderr)
705 elif to_old_git:
705 elif to_old_git:
706 log.warning('RhodeCode detected git version %s, which is to old '
706 log.warning('RhodeCode detected git version %s, which is too old '
707 'for the system to function properly make sure '
707 'for the system to function properly. Make sure '
708 'it is at least in version %s' % (ver, req_ver))
708 'its version is at least %s' % (ver, req_ver))
709 return _ver No newline at end of file
709 return _ver
@@ -314,9 +314,14 b' def age(prevdate):'
314
314
315 order = ['year', 'month', 'day', 'hour', 'minute', 'second']
315 order = ['year', 'month', 'day', 'hour', 'minute', 'second']
316 deltas = {}
316 deltas = {}
317 future = False
317
318
318 # Get date parts deltas
319 # Get date parts deltas
319 now = datetime.datetime.now()
320 now = datetime.datetime.now()
321 if prevdate > now:
322 now, prevdate = prevdate, now
323 future = True
324
320 for part in order:
325 for part in order:
321 deltas[part] = getattr(now, part) - getattr(prevdate, part)
326 deltas[part] = getattr(now, part) - getattr(prevdate, part)
322
327
@@ -369,10 +374,16 b' def age(prevdate):'
369 sub_value = 0
374 sub_value = 0
370
375
371 if sub_value == 0:
376 if sub_value == 0:
372 return _(u'%s ago') % fmt_funcs[part](value)
377 if future:
373
378 return _(u'in %s') % fmt_funcs[part](value)
374 return _(u'%s and %s ago') % (fmt_funcs[part](value),
379 else:
375 fmt_funcs[sub_part](sub_value))
380 return _(u'%s ago') % fmt_funcs[part](value)
381 if future:
382 return _(u'in %s and %s') % (fmt_funcs[part](value),
383 fmt_funcs[sub_part](sub_value))
384 else:
385 return _(u'%s and %s ago') % (fmt_funcs[part](value),
386 fmt_funcs[sub_part](sub_value))
376
387
377 return _(u'just now')
388 return _(u'just now')
378
389
@@ -504,4 +515,4 b' def obfuscate_url_pw(engine):'
504 url = url.make_url(engine)
515 url = url.make_url(engine)
505 if url.password:
516 if url.password:
506 url.password = 'XXXXX'
517 url.password = 'XXXXX'
507 return str(url) No newline at end of file
518 return str(url)
@@ -33,7 +33,7 b' from rhodecode.lib.vcs.backends import g'
33 from rhodecode.lib.compat import json
33 from rhodecode.lib.compat import json
34 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode
34 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode
35 from rhodecode.lib.caching_query import FromCache
35 from rhodecode.lib.caching_query import FromCache
36 from rhodecode.lib.hooks import log_create_repository
36 from rhodecode.lib.hooks import log_create_repository, log_delete_repository
37
37
38 from rhodecode.model import BaseModel
38 from rhodecode.model import BaseModel
39 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
39 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
@@ -336,9 +336,13 b' class RepoModel(BaseModel):'
336 def delete(self, repo):
336 def delete(self, repo):
337 repo = self._get_repo(repo)
337 repo = self._get_repo(repo)
338 if repo:
338 if repo:
339 old_repo_dict = repo.get_dict()
340 owner = repo.user
339 try:
341 try:
340 self.sa.delete(repo)
342 self.sa.delete(repo)
341 self.__delete_repo(repo)
343 self.__delete_repo(repo)
344 log_delete_repository(old_repo_dict,
345 deleted_by=owner.username)
342 except:
346 except:
343 log.error(traceback.format_exc())
347 log.error(traceback.format_exc())
344 raise
348 raise
@@ -118,7 +118,7 b' var show_perms = function(e){'
118 YUD.setStyle('my','display','none');
118 YUD.setStyle('my','display','none');
119 YUD.setStyle('pullrequests','display','none');
119 YUD.setStyle('pullrequests','display','none');
120 YUD.setStyle('perms','display','');
120 YUD.setStyle('perms','display','');
121 YUD.setStyle('q_filter','display','none');
121 YUD.setStyle('q_filter','display','none');
122 }
122 }
123 YUE.on('show_perms','click',function(e){
123 YUE.on('show_perms','click',function(e){
124 show_perms();
124 show_perms();
@@ -134,12 +134,12 b' var show_my = function(e){'
134 YUD.setStyle('my','display','');
134 YUD.setStyle('my','display','');
135 YUD.setStyle('q_filter','display','');
135 YUD.setStyle('q_filter','display','');
136
136
137
137
138 var url = "${h.url('admin_settings_my_repos')}";
138 var url = "${h.url('admin_settings_my_repos')}";
139 ypjax(url, 'my', function(){
139 ypjax(url, 'my', function(){
140 table_sort();
140 table_sort();
141 filter_activate();
141 filter_activate();
142 });
142 });
143 }
143 }
144 YUE.on('show_my','click',function(e){
144 YUE.on('show_my','click',function(e){
145 show_my(e);
145 show_my(e);
@@ -154,9 +154,9 b' var show_pullrequests = function(e){'
154 YUD.setStyle('perms','display','none');
154 YUD.setStyle('perms','display','none');
155 YUD.setStyle('pullrequests','display','');
155 YUD.setStyle('pullrequests','display','');
156 YUD.setStyle('q_filter','display','none');
156 YUD.setStyle('q_filter','display','none');
157
157
158 var url = "${h.url('admin_settings_my_pullrequests')}";
158 var url = "${h.url('admin_settings_my_pullrequests')}";
159 ypjax(url, 'pullrequests');
159 ypjax(url, 'pullrequests');
160 }
160 }
161 YUE.on('show_pullrequests','click',function(e){
161 YUE.on('show_pullrequests','click',function(e){
162 show_pullrequests(e)
162 show_pullrequests(e)
@@ -167,12 +167,12 b' var tabs = {'
167 'my': show_my,
167 'my': show_my,
168 'pullrequests': show_pullrequests
168 'pullrequests': show_pullrequests
169 }
169 }
170 var url = location.href.split('#');
170 var url = location.href.split('#');
171 if (url[1]) {
171 if (url[1]) {
172 //We have a hash
172 //We have a hash
173 var tabHash = url[1];
173 var tabHash = url[1];
174 console.log(tabs, tabHash)
174 console.log(tabs, tabHash)
175 tabs[tabHash]();
175 tabs[tabHash]();
176 }
176 }
177
177
178 // main table sorting
178 // main table sorting
@@ -133,7 +133,7 b''
133 PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
133 PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
134
134
135 var other_repos_info = ${c.other_repos_info|n};
135 var other_repos_info = ${c.other_repos_info|n};
136
136
137 var loadPreview = function(){
137 var loadPreview = function(){
138 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','none');
138 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','none');
139 var url = "${h.url('compare_url',
139 var url = "${h.url('compare_url',
@@ -150,18 +150,18 b''
150 var select_ref_data = select_ref.value.split(':');
150 var select_ref_data = select_ref.value.split(':');
151 var key = null;
151 var key = null;
152 var val = null;
152 var val = null;
153
153
154 if(select_ref_data.length>1){
154 if(select_ref_data.length>1){
155 key = select_ref.name+"_type";
155 key = select_ref.name+"_type";
156 val = select_ref_data[0];
156 val = select_ref_data[0];
157 url = url.replace(key,val);
157 url = url.replace(key,val);
158 rev_data[key] = val;
158 rev_data[key] = val;
159
159
160 key = select_ref.name;
160 key = select_ref.name;
161 val = select_ref_data[1];
161 val = select_ref_data[1];
162 url = url.replace(key,val);
162 url = url.replace(key,val);
163 rev_data[key] = val;
163 rev_data[key] = val;
164
164
165 }else{
165 }else{
166 key = select_ref.name;
166 key = select_ref.name;
167 val = select_ref.value;
167 val = select_ref.value;
@@ -175,7 +175,7 b''
175 // replace the <select> of changed repo
175 // replace the <select> of changed repo
176 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
176 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
177 });
177 });
178
178
179 ypjax(url,'pull_request_overview', function(data){
179 ypjax(url,'pull_request_overview', function(data){
180 var sel_box = YUQ('#pull_request_form #other_repo')[0];
180 var sel_box = YUQ('#pull_request_form #other_repo')[0];
181 var repo_name = sel_box.options[sel_box.selectedIndex].value;
181 var repo_name = sel_box.options[sel_box.selectedIndex].value;
@@ -47,7 +47,7 b''
47 % if len(c.pull_request_pending_reviewers) > 0:
47 % if len(c.pull_request_pending_reviewers) > 0:
48 <div class="tooltip" title="${h.tooltip(','.join([x.username for x in c.pull_request_pending_reviewers]))}">${ungettext('%d reviewer', '%d reviewers',len(c.pull_request_pending_reviewers)) % len(c.pull_request_pending_reviewers)}</div>
48 <div class="tooltip" title="${h.tooltip(','.join([x.username for x in c.pull_request_pending_reviewers]))}">${ungettext('%d reviewer', '%d reviewers',len(c.pull_request_pending_reviewers)) % len(c.pull_request_pending_reviewers)}</div>
49 %else:
49 %else:
50 <div>${_('pull request was reviewed by all reviewers')}</div>
50 <div>${_('pull request was reviewed by all reviewers')}</div>
51 %endif
51 %endif
52 </div>
52 </div>
53 </div>
53 </div>
@@ -25,7 +25,7 b''
25 %endif
25 %endif
26 </div>
26 </div>
27 %endif
27 %endif
28 </div>
28 </div>
29 <pre><a href="${h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id)}">r${cs.revision}:${h.short_id(cs.raw_id)}</a></pre>
29 <pre><a href="${h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id)}">r${cs.revision}:${h.short_id(cs.raw_id)}</a></pre>
30 </div>
30 </div>
31 </td>
31 </td>
@@ -400,4 +400,4 b' class TestCompareController(TestControll'
400 self.assertFalse("""line1-from-new-parent""" in response.body)
400 self.assertFalse("""line1-from-new-parent""" in response.body)
401 finally:
401 finally:
402 RepoModel().delete(r2_id)
402 RepoModel().delete(r2_id)
403 RepoModel().delete(r1_id) No newline at end of file
403 RepoModel().delete(r1_id)
@@ -129,10 +129,25 b' class TestLibs(unittest.TestCase):'
129 self.assertEqual(age(n - delt(hours=1)), u'1 hour ago')
129 self.assertEqual(age(n - delt(hours=1)), u'1 hour ago')
130 self.assertEqual(age(n - delt(hours=24)), u'1 day ago')
130 self.assertEqual(age(n - delt(hours=24)), u'1 day ago')
131 self.assertEqual(age(n - delt(hours=24 * 5)), u'5 days ago')
131 self.assertEqual(age(n - delt(hours=24 * 5)), u'5 days ago')
132 self.assertEqual(age(n - delt(hours=24 * (calendar.mdays[n.month-1] + 2))),
132 self.assertEqual(age(n - delt(hours=24 * (calendar.mdays[n.month - 1] + 2))),
133 u'1 month and 2 days ago')
133 u'1 month and 2 days ago')
134 self.assertEqual(age(n - delt(hours=24 * 400)), u'1 year and 1 month ago')
134 self.assertEqual(age(n - delt(hours=24 * 400)), u'1 year and 1 month ago')
135
135
136 def test_age_in_future(self):
137 import calendar
138 from rhodecode.lib.utils2 import age
139 n = datetime.datetime.now()
140 delt = lambda *args, **kwargs: datetime.timedelta(*args, **kwargs)
141 self.assertEqual(age(n), u'just now')
142 self.assertEqual(age(n + delt(seconds=1)), u'in 1 second')
143 self.assertEqual(age(n + delt(seconds=60 * 2)), u'in 2 minutes')
144 self.assertEqual(age(n + delt(hours=1)), u'in 1 hour')
145 self.assertEqual(age(n + delt(hours=24)), u'in 1 day')
146 self.assertEqual(age(n + delt(hours=24 * 5)), u'in 5 days')
147 self.assertEqual(age(n + delt(hours=24 * (calendar.mdays[n.month - 1] + 2))),
148 u'in 1 month and 1 day')
149 self.assertEqual(age(n + delt(hours=24 * 400)), u'in 1 year and 1 month')
150
136 def test_tag_exctrator(self):
151 def test_tag_exctrator(self):
137 sample = (
152 sample = (
138 "hello pta[tag] gog [[]] [[] sda ero[or]d [me =>>< sa]"
153 "hello pta[tag] gog [[]] [[] sda ero[or]d [me =>>< sa]"
@@ -195,4 +210,3 b' class TestLibs(unittest.TestCase):'
195 em = 'test@foo.com'
210 em = 'test@foo.com'
196 grav = gravatar_url(email_address=em, size=24)
211 grav = gravatar_url(email_address=em, size=24)
197 assert grav == 'https://server.com/%s/%s' % (_md5(em), 24)
212 assert grav == 'https://server.com/%s/%s' % (_md5(em), 24)
198
@@ -10,7 +10,7 b' from rhodecode.model.users_group import '
10 from rhodecode.model.meta import Session
10 from rhodecode.model.meta import Session
11 from rhodecode.model.repos_group import ReposGroupModel
11 from rhodecode.model.repos_group import ReposGroupModel
12 from rhodecode.config.routing import ADMIN_PREFIX
12 from rhodecode.config.routing import ADMIN_PREFIX
13 from rhodecode.model.db import ChangesetStatus
13 from rhodecode.model.db import ChangesetStatus, Repository
14 from rhodecode.model.changeset_status import ChangesetStatusModel
14 from rhodecode.model.changeset_status import ChangesetStatusModel
15 from rhodecode.model.comment import ChangesetCommentsModel
15 from rhodecode.model.comment import ChangesetCommentsModel
16
16
@@ -227,7 +227,8 b' class TestReposGroups(unittest.TestCase)'
227 self.assertRaises(formencode.Invalid, validator.to_python, 123)
227 self.assertRaises(formencode.Invalid, validator.to_python, 123)
228
228
229 def test_NotReviewedRevisions(self):
229 def test_NotReviewedRevisions(self):
230 validator = v.NotReviewedRevisions()
230 repo_id = Repository.get_by_repo_name(HG_REPO).repo_id
231 validator = v.NotReviewedRevisions(repo_id)
231 rev = '0' * 40
232 rev = '0' * 40
232 # add status for a rev, that should throw an error because it is already
233 # add status for a rev, that should throw an error because it is already
233 # reviewed
234 # reviewed
General Comments 0
You need to be logged in to leave comments. Login now