@@ -235,7 +235,7 @@ INPUT::
method : "add_user_users_group"
args: {
"group_name" : "<groupname>",
"user_name" : "<username>"
"username" : "<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 : "<api_key>"
method : "get_repo_nodes"
"repo_name" : "<name>",
"revision" : "<revision>",
"root_path" : "<root_path>",
"ret_type" : "<ret_type>" = 'all'
result: [
{
"name" : "<name>"
"type" : "<type>",
},
…
]
create_repo
-----------
@@ -355,7 +387,7 @@ INPUT::
method : "add_user_to_repo"
"repo_name" : "<reponame>",
"user_name" : "<username>",
"username" : "<username>",
"perm" : "(None|repository.(read|write|admin))",
@@ -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**)
======================
@@ -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)
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 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
_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)
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 repo_name:
:param perm:
@@ -384,7 +412,7 @@ class ApiController(JSONRPCController):
raise JSONRPCError('unknown repository %s' % repo)
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
@@ -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()
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,
return _d + _f
@@ -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:
@@ -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
: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
_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):
_files.append(f.path if flat else {"name": f.path,
"type": "file"})
_dirs.append(d.path if flat else {"name": d.path,
"type": "dir"})
except RepositoryError:
raise
def get_unread_journal(self):
return self.sa.query(UserLog).count()
@@ -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<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 @@ var fileBrowserListeners = function(curr
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 @@ var fileBrowserListeners = function(curr
F.initFilter();
})
YUE.on(n_filter,'click',function(){
});
YUE.on(n_filter,'keyup',function(e){
clearTimeout(F.filterTimeout);
@@ -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>
Status change: