diff --git a/docs/api/api.rst b/docs/api/api.rst --- a/docs/api/api.rst +++ b/docs/api/api.rst @@ -235,7 +235,7 @@ INPUT:: method : "add_user_users_group" args: { "group_name" : "", - "user_name" : "" + "username" : "" } OUTPUT:: @@ -316,6 +316,38 @@ OUTPUT:: } 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 : "" + method : "get_repo_nodes" + args: { + "repo_name" : "", + "revision" : "", + "root_path" : "", + "ret_type" : "" = 'all' + } + +OUTPUT:: + + result: [ + { + "name" : "" + "type" : "", + }, + … + ] + error: null + + + create_repo ----------- @@ -355,7 +387,7 @@ INPUT:: method : "add_user_to_repo" args: { "repo_name" : "", - "user_name" : "", + "username" : "", "perm" : "(None|repository.(read|write|admin))", } diff --git a/docs/changelog.rst b/docs/changelog.rst --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -29,6 +29,8 @@ news - 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 @@ fixes - 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**) ====================== diff --git a/rhodecode/controllers/api/api.py b/rhodecode/controllers/api/api.py --- a/rhodecode/controllers/api/api.py +++ b/rhodecode/controllers/api/api.py @@ -212,13 +212,13 @@ class ApiController(JSONRPCController): 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 @@ class ApiController(JSONRPCController): 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 @@ class ApiController(JSONRPCController): ) 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 @@ class ApiController(JSONRPCController): 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 @@ class ApiController(JSONRPCController): 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 @@ class ApiController(JSONRPCController): 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 ) ) diff --git a/rhodecode/controllers/files.py b/rhodecode/controllers/files.py --- a/rhodecode/controllers/files.py +++ b/rhodecode/controllers/files.py @@ -49,6 +49,7 @@ from rhodecode.model.repo import RepoMod 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 @@ class FilesController(BaseRepoController 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 @@ class FilesController(BaseRepoController 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 diff --git a/rhodecode/lib/indexers/__init__.py b/rhodecode/lib/indexers/__init__.py --- a/rhodecode/lib/indexers/__init__.py +++ b/rhodecode/lib/indexers/__init__.py @@ -129,6 +129,7 @@ class MakeIndex(BasePasterCommand): " 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 @@ class ResultWrapper(object): 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 @@ class ResultWrapper(object): 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: """ diff --git a/rhodecode/model/scm.py b/rhodecode/model/scm.py --- a/rhodecode/model/scm.py +++ b/rhodecode/model/scm.py @@ -391,5 +391,35 @@ class ScmModel(BaseModel): 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() diff --git a/rhodecode/public/js/rhodecode.js b/rhodecode/public/js/rhodecode.js --- a/rhodecode/public/js/rhodecode.js +++ b/rhodecode/public/js/rhodecode.js @@ -418,6 +418,11 @@ var fileBrowserListeners = function(curr 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 @@ var fileBrowserListeners = function(curr 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{0}".format(n.substring(pos,pos+query.length)) +n.substring(pos+query.length) - match.push('{1}'.format(node_url.replace('__FPATH__',n),n_hl)); + match.push('{2}'.format(t,node_url.replace('__FPATH__',n),n_hl)); } if(match.length >= matches_max){ match.push('{0}'.format(truncated_lbl)); @@ -479,7 +486,10 @@ var fileBrowserListeners = function(curr 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); diff --git a/rhodecode/templates/files/files_browser.html b/rhodecode/templates/files/files_browser.html --- a/rhodecode/templates/files/files_browser.html +++ b/rhodecode/templates/files/files_browser.html @@ -34,7 +34,7 @@