Marcin Kuzminski avatar Marcin Kuzminski committed 3148c08 Merge

merge with beta

Comments (0)

Files changed (18)

     Vincent Caron <vcaron@bearstech.com>
     Zachary Auclair <zach101@gmail.com>
     Stefan Engel <mail@engel-stefan.de>
+    Andrew Shadura <bugzilla@tut.by>
                "users_group_id" : "<id>",
                "group_name" :     "<groupname>",
                "active":          "<bool>",
-               "members" :  [
-                              { 
-                                "user_id" :  "<user_id>",
-                                "username" : "<username>",
-                                "firstname": "<firstname>",
-                                "lastname" : "<lastname>",
-                                "email" :    "<email>",
-                                "emails":    "<list_of_all_additional_emails>",
-                                "active" :   "<bool>",
-                                "admin" :    "<bool>",
-                                "ldap_dn" :  "<ldap_dn>",
-                                "last_login": "<last_login>",
-                              },
-                              …
-                            ]
                },
               ]
                      "users_group_id" : "<id>",
                      "group_name" :     "<groupname>",
                      "active":          "<bool>",
-                     "members" :  [
-                                  { 
-                                    "user_id" :  "<user_id>",
-                                    "username" : "<username>",
-                                    "firstname": "<firstname>",
-                                    "lastname" : "<lastname>",
-                                    "email" :    "<email>",
-                                    "emails":    "<list_of_all_additional_emails>",
-                                    "active" :   "<bool>",
-                                    "admin" :    "<bool>",
-                                    "ldap_dn" :  "<ldap_dn>",
-                                    "last_login": "<last_login>",
-                                  },
-                                  …
-                     ]
                },
             }
     error:  null

docs/changelog.rst

 - #574 Show pull request status also in shortlog (if any)
 - remember selected tab in my account page
 - Bumped mercurial version to 2.3.2
+- #595 rcextension hook for repository delete
 
 fixes
 +++++
   status. Checks now are made also for the repository.
 - fixes #591 git backend was causing encoding errors when handling binary
   files - added a test case for VCS lib tests
+- fixed #597 commits in future get negative age.
+- fixed #598 API docs methods had wrong members parameter as returned data
 
 1.4.3 (**2012-09-28**)
 ----------------------
 
 This will create `rcextensions` package in the same place that your `ini` file
 lives. With `rcextensions` it's possible to add additional mapping for whoosh, 
-stats and add additional code into the push/pull/create repo hooks. For example
-for sending signals to build-bots such as jenkins.
+stats and add additional code into the push/pull/create/delete repo hooks.
+For example for sending signals to build-bots such as jenkins.
 Please see the `__init__.py` file inside `rcextensions` package 
 for more details.
 

rhodecode/config/rcextensions/__init__.py

      :param group_id:
      :param created_by:
     """
-
     return 0
 CREATE_REPO_HOOK = _crhook
 
 
 #==============================================================================
+# POST DELETE REPOSITORY HOOK
+#==============================================================================
+# this function will be executed after each repository deletion
+def _dlhook(*args, **kwargs):
+    """
+    Post create repository HOOK
+    kwargs available:
+     :param repo_name:
+     :param repo_type:
+     :param description:
+     :param private:
+     :param created_on:
+     :param enable_downloads:
+     :param repo_id:
+     :param user_id:
+     :param enable_statistics:
+     :param clone_uri:
+     :param fork_id:
+     :param group_id:
+     :param deleted_by:
+     :param deleted_on:
+    """
+    return 0
+DELETE_REPO_HOOK = _dlhook
+
+
+#==============================================================================
 # POST PUSH HOOK
 #==============================================================================
 

rhodecode/controllers/settings.py

             h.flash(_('An error occurred during unlocking'),
                     category='error')
         return redirect(url('summary_home', repo_name=repo_name))
-

rhodecode/lib/db_manage.py

         if not __py_version__ >= (2, 6):
             notify('Python2.5 detected, please switch '
                    'egg:waitress#main -> egg:Paste#http '
-                   'in your .ini file')
+                   'in your .ini file')

rhodecode/lib/hooks.py

 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import os
 import sys
+import time
 import binascii
 from inspect import isfunction
 
 from rhodecode.lib.utils2 import safe_str
 from rhodecode.model.db import Repository, User
 
+
 def _get_scm_size(alias, root_path):
 
     if not alias.startswith('.'):
 
     :param repository: dict dump of repository object
     :param created_by: username who created repository
-    :param created_date: date of creation
 
     available keys of repository_dict:
 
 
     return 0
 
+
+def log_delete_repository(repository_dict, deleted_by, **kwargs):
+    """
+    Post delete repository Hook. This is a dummy function for admins to re-use
+    if needed. It's taken from rhodecode-extensions module and executed
+    if present
+
+    :param repository: dict dump of repository object
+    :param deleted_by: username who deleted the repository
+
+    available keys of repository_dict:
+
+     'repo_type',
+     'description',
+     'private',
+     'created_on',
+     'enable_downloads',
+     'repo_id',
+     'user_id',
+     'enable_statistics',
+     'clone_uri',
+     'fork_id',
+     'group_id',
+     'repo_name'
+
+    """
+    from rhodecode import EXTENSIONS
+    callback = getattr(EXTENSIONS, 'DELETE_REPO_HOOK', None)
+    if isfunction(callback):
+        kw = {}
+        kw.update(repository_dict)
+        kw.update({'deleted_by': deleted_by,
+                   'deleted_on': time.time()})
+        kw.update(kwargs)
+        return callback(**kw)
+
+    return 0
+
+
 handle_git_pre_receive = (lambda repo_path, revs, env:
     handle_git_receive(repo_path, revs, env, hook_type='pre'))
 handle_git_post_receive = (lambda repo_path, revs, env:

rhodecode/lib/utils.py

         elif isinstance(user, basestring):
             user_obj = User.get_by_username(user)
         else:
-            raise Exception('You have to provide user object or username')
+            raise Exception('You have to provide a user object or a username')
 
         if hasattr(repo, 'repo_id'):
             repo_obj = Repository.get(repo.repo_id)
     return False
 
 
-def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
+def ask_ok(prompt, retries=4, complaint='Yes or no please!'):
     while True:
         ok = raw_input(prompt)
         if ok in ('y', 'ye', 'yes'):
 
     if read_from == 'file':
         if not os.path.isfile(path):
-            log.debug('hgrc file is not present at %s skipping...' % path)
+            log.debug('hgrc file is not present at %s, skipping...' % path)
             return False
         log.debug('reading hgrc from %s' % path)
         cfg = config.config()
     rm = RepoModel()
     user = sa.query(User).filter(User.admin == True).first()
     if user is None:
-        raise Exception('Missing administrative account !')
+        raise Exception('Missing administrative account!')
     added = []
 
 #    # clear cache keys
         db_repo = rm.get_by_repo_name(name)
         # found repo that is on filesystem not in RhodeCode database
         if not db_repo:
-            log.info('repository %s not found creating now' % name)
+            log.info('repository %s not found, creating now' % name)
             added.append(name)
             desc = (repo.description
                     if repo.description != 'unknown'
         # during starting install all cache keys for all repositories in the
         # system, this will register all repos and multiple instances
         key, _prefix, _org_key = CacheInvalidation._get_key(name)
-        log.debug("Creating cache key for %s instance_id:`%s`" % (name, _prefix))
+        log.debug("Creating a cache key for %s instance_id:`%s`" % (name, _prefix))
         CacheInvalidation._get_or_create_key(key, _prefix, _org_key, commit=False)
     sa.commit()
     removed = []
         # remove from database those repositories that are not in the filesystem
         for repo in sa.query(Repository).all():
             if repo.repo_name not in initial_repo_list.keys():
-                log.debug("Removing non existing repository found in db `%s`" %
+                log.debug("Removing non-existing repository found in db `%s`" %
                           repo.repo_name)
                 try:
                     sa.delete(repo)
 def check_git_version():
     """
     Checks what version of git is installed in system, and issues a warning
-    if it's to old for RhodeCode to properly work.
+    if it's too old for RhodeCode to properly work.
     """
     import subprocess
     from distutils.version import StrictVersion
         if stderr:
             log.warning('Unable to detect git version org error was:%r' % stderr)
         elif to_old_git:
-            log.warning('RhodeCode detected git version %s, which is to old '
-                        'for the system to function properly make sure '
-                        'it is at least in version %s' % (ver, req_ver))
-    return _ver
+            log.warning('RhodeCode detected git version %s, which is too old '
+                        'for the system to function properly. Make sure '
+                        'its version is at least %s' % (ver, req_ver))
+    return _ver

rhodecode/lib/utils2.py

 
     order = ['year', 'month', 'day', 'hour', 'minute', 'second']
     deltas = {}
+    future = False
 
     # Get date parts deltas
     now = datetime.datetime.now()
+    if prevdate > now:
+        now, prevdate = prevdate, now
+        future = True
+
     for part in order:
         deltas[part] = getattr(now, part) - getattr(prevdate, part)
 
             sub_value = 0
 
         if sub_value == 0:
-            return _(u'%s ago') % fmt_funcs[part](value)
-
-        return _(u'%s and %s ago') % (fmt_funcs[part](value),
-            fmt_funcs[sub_part](sub_value))
+            if future:
+                return _(u'in %s') % fmt_funcs[part](value)
+            else:
+                return _(u'%s ago') % fmt_funcs[part](value)
+        if future:
+            return _(u'in %s and %s') % (fmt_funcs[part](value),
+                fmt_funcs[sub_part](sub_value))
+        else:
+            return _(u'%s and %s ago') % (fmt_funcs[part](value),
+                fmt_funcs[sub_part](sub_value))
 
     return _(u'just now')
 
     url = url.make_url(engine)
     if url.password:
         url.password = 'XXXXX'
-    return str(url)
+    return str(url)

rhodecode/model/repo.py

 from rhodecode.lib.compat import json
 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode
 from rhodecode.lib.caching_query import FromCache
-from rhodecode.lib.hooks import log_create_repository
+from rhodecode.lib.hooks import log_create_repository, log_delete_repository
 
 from rhodecode.model import BaseModel
 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
     def delete(self, repo):
         repo = self._get_repo(repo)
         if repo:
+            old_repo_dict = repo.get_dict()
+            owner = repo.user
             try:
                 self.sa.delete(repo)
                 self.__delete_repo(repo)
+                log_delete_repository(old_repo_dict,
+                                      deleted_by=owner.username)
             except:
                 log.error(traceback.format_exc())
                 raise

rhodecode/templates/admin/users/user_edit_my_account.html

     YUD.setStyle('my','display','none');
     YUD.setStyle('pullrequests','display','none');
     YUD.setStyle('perms','display','');
-    YUD.setStyle('q_filter','display','none');	
+    YUD.setStyle('q_filter','display','none');
 }
 YUE.on('show_perms','click',function(e){
     show_perms();
     YUD.setStyle('my','display','');
     YUD.setStyle('q_filter','display','');
 
-    
+
     var url = "${h.url('admin_settings_my_repos')}";
     ypjax(url, 'my', function(){
         table_sort();
         filter_activate();
-    });	
+    });
 }
 YUE.on('show_my','click',function(e){
 	show_my(e);
     YUD.setStyle('perms','display','none');
     YUD.setStyle('pullrequests','display','');
     YUD.setStyle('q_filter','display','none');
-    
+
     var url = "${h.url('admin_settings_my_pullrequests')}";
-    ypjax(url, 'pullrequests');	
+    ypjax(url, 'pullrequests');
 }
 YUE.on('show_pullrequests','click',function(e){
 	show_pullrequests(e)
     'my': show_my,
     'pullrequests': show_pullrequests
 }
-var url = location.href.split('#'); 
-if (url[1]) { 
-    //We have a hash 
+var url = location.href.split('#');
+if (url[1]) {
+    //We have a hash
     var tabHash = url[1];
     console.log(tabs, tabHash)
-    tabs[tabHash]();   
+    tabs[tabHash]();
 }
 
 // main table sorting

rhodecode/templates/pullrequests/pullrequest.html

   PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
 
   var other_repos_info = ${c.other_repos_info|n};
-  
+
   var loadPreview = function(){
 	  YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','none');
       var url = "${h.url('compare_url',
         var select_ref_data = select_ref.value.split(':');
         var key = null;
         var val = null;
-        
+
         if(select_ref_data.length>1){
           key = select_ref.name+"_type";
           val = select_ref_data[0];
           url = url.replace(key,val);
           rev_data[key] = val;
-          
+
           key = select_ref.name;
           val = select_ref_data[1];
           url = url.replace(key,val);
           rev_data[key] = val;
-          
+
         }else{
           key = select_ref.name;
           val = select_ref.value;
     	  // replace the <select> of changed repo
     	  YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
       });
-      
+
       ypjax(url,'pull_request_overview', function(data){
     	  var sel_box = YUQ('#pull_request_form #other_repo')[0];
     	  var repo_name = sel_box.options[sel_box.selectedIndex].value;

rhodecode/templates/pullrequests/pullrequest_show.html

             % if len(c.pull_request_pending_reviewers) > 0:
                 <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>
             %else:
-                <div>${_('pull request was reviewed by all reviewers')}</div>            
+                <div>${_('pull request was reviewed by all reviewers')}</div>
             %endif
           </div>
          </div>

rhodecode/templates/shortlog/shortlog_data.html

                 %endif
                 </div>
               %endif
-            </div>            
+            </div>
             <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>
          </div>
         </td>

rhodecode/tests/functional/test_compare.py

             self.assertFalse("""line1-from-new-parent"""  in response.body)
         finally:
             RepoModel().delete(r2_id)
-            RepoModel().delete(r1_id)
+            RepoModel().delete(r1_id)

rhodecode/tests/test_libs.py

         self.assertEqual(age(n - delt(hours=1)), u'1 hour ago')
         self.assertEqual(age(n - delt(hours=24)), u'1 day ago')
         self.assertEqual(age(n - delt(hours=24 * 5)), u'5 days ago')
-        self.assertEqual(age(n - delt(hours=24 * (calendar.mdays[n.month-1] + 2))),
+        self.assertEqual(age(n - delt(hours=24 * (calendar.mdays[n.month - 1] + 2))),
                          u'1 month and 2 days ago')
         self.assertEqual(age(n - delt(hours=24 * 400)), u'1 year and 1 month ago')
 
+    def test_age_in_future(self):
+        import calendar
+        from rhodecode.lib.utils2 import age
+        n = datetime.datetime.now()
+        delt = lambda *args, **kwargs: datetime.timedelta(*args, **kwargs)
+        self.assertEqual(age(n), u'just now')
+        self.assertEqual(age(n + delt(seconds=1)), u'in 1 second')
+        self.assertEqual(age(n + delt(seconds=60 * 2)), u'in 2 minutes')
+        self.assertEqual(age(n + delt(hours=1)), u'in 1 hour')
+        self.assertEqual(age(n + delt(hours=24)), u'in 1 day')
+        self.assertEqual(age(n + delt(hours=24 * 5)), u'in 5 days')
+        self.assertEqual(age(n + delt(hours=24 * (calendar.mdays[n.month - 1] + 2))),
+                         u'in 1 month and 1 day')
+        self.assertEqual(age(n + delt(hours=24 * 400)), u'in 1 year and 1 month')
+
     def test_tag_exctrator(self):
         sample = (
             "hello pta[tag] gog [[]] [[] sda ero[or]d [me =>>< sa]"
                 em = 'test@foo.com'
                 grav = gravatar_url(email_address=em, size=24)
                 assert grav == 'https://server.com/%s/%s' % (_md5(em), 24)
-

rhodecode/tests/test_validators.py

 from rhodecode.model.meta import Session
 from rhodecode.model.repos_group import ReposGroupModel
 from rhodecode.config.routing import ADMIN_PREFIX
-from rhodecode.model.db import ChangesetStatus
+from rhodecode.model.db import ChangesetStatus, Repository
 from rhodecode.model.changeset_status import ChangesetStatusModel
 from rhodecode.model.comment import ChangesetCommentsModel
 
         self.assertRaises(formencode.Invalid, validator.to_python, 123)
 
     def test_NotReviewedRevisions(self):
-        validator = v.NotReviewedRevisions()
+        repo_id = Repository.get_by_repo_name(HG_REPO).repo_id
+        validator = v.NotReviewedRevisions(repo_id)
         rev = '0' * 40
         # add status for a rev, that should throw an error because it is already
         # reviewed
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.