changeset 1810:203af05539e0 beta

implements #330 api method for listing nodes at particular revision - improved filtering by files in file list
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 28 Dec 2011 04:12:27 +0200
parents ef0066e95be5
children 58df0b3ed377 320dec24fb9a
files docs/api/api.rst docs/changelog.rst rhodecode/controllers/api/api.py rhodecode/controllers/files.py rhodecode/lib/indexers/__init__.py rhodecode/model/scm.py rhodecode/public/js/rhodecode.js rhodecode/templates/files/files_browser.html
diffstat 8 files changed, 125 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/docs/api/api.rst	Sat Dec 24 02:21:22 2011 +0200
+++ b/docs/api/api.rst	Wed Dec 28 04:12:27 2011 +0200
@@ -235,7 +235,7 @@
     method :  "add_user_users_group"
     args:     {
                 "group_name" :  "<groupname>",
-                "user_name" :   "<username>"
+                "username" :   "<username>"
               }
 
 OUTPUT::
@@ -316,6 +316,38 @@
             }
     error:  null
 
+get_repo_nodes
+--------------
+
+returns a list of nodes and it's children in a flat list for a given path 
+at given revision. It's possible to specify ret_type to show only files or 
+dirs. This command can be executed only using api_key belonging to user 
+with admin rights
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "get_repo_nodes"
+    args:     {
+                "repo_name" : "<name>",
+                "revision"  : "<revision>",
+                "root_path" : "<root_path>",
+                "ret_type"  : "<ret_type>" = 'all'
+              }
+
+OUTPUT::
+
+    result: [
+              {
+                "name" :        "<name>"
+                "type" :        "<type>",
+              },
+              …
+            ]
+    error:  null
+
+
+
 create_repo
 -----------
 
@@ -355,7 +387,7 @@
     method :  "add_user_to_repo"
     args:     {
                 "repo_name" :  "<reponame>",
-                "user_name" :  "<username>",
+                "username" :  "<username>",
                 "perm" :       "(None|repository.(read|write|admin))",
               }
 
--- a/docs/changelog.rst	Sat Dec 24 02:21:22 2011 +0200
+++ b/docs/changelog.rst	Wed Dec 28 04:12:27 2011 +0200
@@ -29,6 +29,8 @@
 - diff configuration, toggle white lines and context lines
 - #307 configurable diffs, whitespace toggle, increasing context lines
 - sorting on branches, tags and bookmarks using YUI datatable
+- improved file filter on files page
+- implements #330 api method for listing nodes ar particular revision
 
 fixes
 -----
@@ -36,6 +38,7 @@
 - rewrote dbsession management for atomic operations, and better error handling
 - fixed sorting of repo tables
 - #326 escape of special html entities in diffs
+- normalized user_name => username in api attributes
 
 1.2.3 (**2011-11-02**)
 ======================
--- a/rhodecode/controllers/api/api.py	Sat Dec 24 02:21:22 2011 +0200
+++ b/rhodecode/controllers/api/api.py	Wed Dec 28 04:12:27 2011 +0200
@@ -212,13 +212,13 @@
             raise JSONRPCError('failed to create group %s' % name)
 
     @HasPermissionAllDecorator('hg.admin')
-    def add_user_to_users_group(self, apiuser, group_name, user_name):
+    def add_user_to_users_group(self, apiuser, group_name, username):
         """"
         Add a user to a group
 
         :param apiuser:
         :param group_name:
-        :param user_name:
+        :param username:
         """
 
         try:
@@ -227,9 +227,9 @@
                 raise JSONRPCError('unknown users group %s' % group_name)
 
             try:
-                user = User.get_by_username(user_name)
+                user = User.get_by_username(username)
             except NoResultFound:
-                raise JSONRPCError('unknown user %s' % user_name)
+                raise JSONRPCError('unknown user %s' % username)
 
             ugm = UsersGroupModel().add_user_to_group(users_group, user)
             Session.commit()
@@ -311,6 +311,34 @@
             )
         return result
 
+    @HasPermissionAnyDecorator('hg.admin')
+    def get_repo_nodes(self, apiuser, repo_name, revision, root_path,
+                       ret_type='all'):
+        """
+        returns a list of nodes and it's children
+        for a given path at given revision. It's possible to specify ret_type
+        to show only files or dirs
+
+        :param apiuser:
+        :param repo_name: name of repository
+        :param revision: revision for which listing should be done
+        :param root_path: path from which start displaying
+        :param ret_type: return type 'all|files|dirs' nodes
+        """
+        try:
+            _d, _f = ScmModel().get_nodes(repo_name, revision, root_path,
+                                          flat=False)
+            _map = {
+                'all': _d + _f,
+                'files': _f,
+                'dirs': _d,
+            }
+            return _map[ret_type]
+        except KeyError:
+            raise JSONRPCError('ret_type must be one of %s' % _map.keys())
+        except Exception, e:
+            raise JSONRPCError(e)
+
     @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
     def create_repo(self, apiuser, name, owner_name, description='',
                     repo_type='hg', private=False):
@@ -368,13 +396,13 @@
             raise JSONRPCError('failed to create repository %s' % name)
 
     @HasPermissionAnyDecorator('hg.admin')
-    def add_user_to_repo(self, apiuser, repo_name, user_name, perm):
+    def add_user_to_repo(self, apiuser, repo_name, username, perm):
         """
         Add permission for a user to a repository
 
         :param apiuser:
         :param repo_name:
-        :param user_name:
+        :param username:
         :param perm:
         """
 
@@ -384,7 +412,7 @@
                 raise JSONRPCError('unknown repository %s' % repo)
 
             try:
-                user = User.get_by_username(user_name)
+                user = User.get_by_username(username)
             except NoResultFound:
                 raise JSONRPCError('unknown user %s' % user)
 
@@ -394,14 +422,14 @@
 
             return dict(
                 msg='Added perm: %s for %s in repo: %s' % (
-                    perm, user_name, repo_name
+                    perm, username, repo_name
                 )
             )
         except Exception:
             log.error(traceback.format_exc())
             raise JSONRPCError(
                 'failed to edit permission %(repo)s for %(user)s' % dict(
-                    user=user_name, repo=repo_name
+                    user=username, repo=repo_name
                 )
             )
 
--- a/rhodecode/controllers/files.py	Sat Dec 24 02:21:22 2011 +0200
+++ b/rhodecode/controllers/files.py	Wed Dec 28 04:12:27 2011 +0200
@@ -49,6 +49,7 @@
 from rhodecode.controllers.changeset import anchor_url, _ignorews_url,\
     _context_url, get_line_ctx, get_ignore_ws
 from rhodecode.lib.diffs import wrapped_diff
+from rhodecode.model.scm import ScmModel
 
 log = logging.getLogger(__name__)
 
@@ -107,25 +108,6 @@
 
         return file_node
 
-    def __get_paths(self, changeset, starting_path):
-        """recursive walk in root dir and return a set of all path in that dir
-        based on repository walk function
-        """
-        _files = list()
-        _dirs = list()
-
-        try:
-            tip = changeset
-            for topnode, dirs, files in tip.walk(starting_path):
-                for f in files:
-                    _files.append(f.path)
-                for d in dirs:
-                    _dirs.append(d.path)
-        except RepositoryError, e:
-            log.debug(traceback.format_exc())
-            pass
-        return _dirs, _files
-
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                    'repository.admin')
     def index(self, repo_name, revision, f_path):
@@ -505,6 +487,7 @@
     def nodelist(self, repo_name, revision, f_path):
         if request.environ.get('HTTP_X_PARTIAL_XHR'):
             cs = self.__get_cs_or_redirect(revision, repo_name)
-            _d, _f = self.__get_paths(cs, f_path)
+            _d, _f = ScmModel().get_nodes(repo_name, cs.raw_id, f_path,
+                                          flat=False)
             return _d + _f
 
--- a/rhodecode/lib/indexers/__init__.py	Sat Dec 24 02:21:22 2011 +0200
+++ b/rhodecode/lib/indexers/__init__.py	Wed Dec 28 04:12:27 2011 +0200
@@ -129,6 +129,7 @@
                                 " destroy old and build from scratch",
                           default=False)
 
+
 class ResultWrapper(object):
     def __init__(self, search_type, searcher, matcher, highlight_items):
         self.search_type = search_type
@@ -176,7 +177,6 @@
             slice.append(self.get_full_content(docid))
         return slice
 
-
     def get_full_content(self, docid):
         res = self.searcher.stored_fields(docid[0])
         f_path = res['path'][res['path'].find(res['repository']) \
@@ -198,7 +198,7 @@
         Smart function that implements chunking the content
         but not overlap chunks so it doesn't highlight the same
         close occurrences twice.
-        
+
         :param matcher:
         :param size:
         """
--- a/rhodecode/model/scm.py	Sat Dec 24 02:21:22 2011 +0200
+++ b/rhodecode/model/scm.py	Wed Dec 28 04:12:27 2011 +0200
@@ -391,5 +391,35 @@
 
         self.mark_for_invalidation(repo_name)
 
+    def get_nodes(self, repo_name, revision, root_path='/', flat=True):
+        """
+        recursive walk in root dir and return a set of all path in that dir
+        based on repository walk function
+
+        :param repo_name: name of repository
+        :param revision: revision for which to list nodes
+        :param root_path: root path to list
+        :param flat: return as a list, if False returns a dict with decription
+
+        """
+        _files = list()
+        _dirs = list()
+        try:
+            _repo = self.__get_repo(repo_name)
+            changeset = _repo.scm_instance.get_changeset(revision)
+            root_path = root_path.lstrip('/')
+            for topnode, dirs, files in changeset.walk(root_path):
+                for f in files:
+                    _files.append(f.path if flat else {"name": f.path,
+                                                       "type": "file"})
+                for d in dirs:
+                    _dirs.append(d.path if flat else {"name": d.path,
+                                                      "type": "dir"})
+        except RepositoryError:
+            log.debug(traceback.format_exc())
+            raise
+
+        return _dirs, _files
+
     def get_unread_journal(self):
         return self.sa.query(UserLog).count()
--- a/rhodecode/public/js/rhodecode.js	Sat Dec 24 02:21:22 2011 +0200
+++ b/rhodecode/public/js/rhodecode.js	Wed Dec 28 04:12:27 2011 +0200
@@ -418,6 +418,11 @@
 	        nodes = JSON.parse(o.responseText);
 	        YUD.setStyle('node_filter_box_loading','display','none');
 	        YUD.setStyle('node_filter_box','display','');
+	        n_filter.focus();
+			if(YUD.hasClass(n_filter,'init')){
+				n_filter.value = '';
+				YUD.removeClass(n_filter,'init');
+			}   
 	      },
 	      failure:function(o){
 	          console.log('failed to load');
@@ -430,13 +435,14 @@
 	    return function(){
 	        // Reset timeout 
 	        F.filterTimeout = null;
-	        var query = e.target.value;
+	        var query = e.target.value.toLowerCase();
 	        var match = [];
 	        var matches = 0;
 	        var matches_max = 20;
 	        if (query != ""){
 	            for(var i=0;i<nodes.length;i++){
-	                var pos = nodes[i].toLowerCase().indexOf(query)
+	            	
+	                var pos = nodes[i].name.toLowerCase().indexOf(query)
 	                if(query && pos != -1){
 	                    
 	                    matches++
@@ -445,11 +451,12 @@
 	                        break;
 	                    }
 	                    
-	                    var n = nodes[i];
+	                    var n = nodes[i].name;
+	                    var t = nodes[i].type;
 	                    var n_hl = n.substring(0,pos)
 	                      +"<b>{0}</b>".format(n.substring(pos,pos+query.length))
 	                      +n.substring(pos+query.length)                    
-	                    match.push('<tr><td><a class="browser-file" href="{0}">{1}</a></td><td colspan="5"></td></tr>'.format(node_url.replace('__FPATH__',n),n_hl));
+	                    match.push('<tr><td><a class="browser-{0}" href="{1}">{2}</a></td><td colspan="5"></td></tr>'.format(t,node_url.replace('__FPATH__',n),n_hl));
 	                }
 	                if(match.length >= matches_max){
 	                    match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(truncated_lbl));
@@ -479,7 +486,10 @@
 	    F.initFilter();
 	})
 	YUE.on(n_filter,'click',function(){
-	    n_filter.value = '';
+		if(YUD.hasClass(n_filter,'init')){
+			n_filter.value = '';
+			YUD.removeClass(n_filter,'init');
+		}
 	 });
 	YUE.on(n_filter,'keyup',function(e){
 	    clearTimeout(F.filterTimeout); 
--- a/rhodecode/templates/files/files_browser.html	Sat Dec 24 02:21:22 2011 +0200
+++ b/rhodecode/templates/files/files_browser.html	Wed Dec 28 04:12:27 2011 +0200
@@ -34,7 +34,7 @@
         <div>
             <div id="node_filter_box_loading" style="display:none">${_('Loading file list...')}</div>
             <div id="node_filter_box" style="display:none">
-            ${h.files_breadcrumbs(c.repo_name,c.changeset.raw_id,c.file.path)}/<input type="text" value="type to search..." name="filter" size="25" id="node_filter" autocomplete="off">
+            ${h.files_breadcrumbs(c.repo_name,c.changeset.raw_id,c.file.path)}/<input class="init" type="text" value="type to search..." name="filter" size="25" id="node_filter" autocomplete="off">
             </div>        
         </div>
         </div>