Changeset - 203af05539e0
[Not reviewed]
beta
0 8 0
Marcin Kuzminski - 14 years ago 2011-12-28 03:12:27
marcin@python-works.com
implements #330 api method for listing nodes at particular revision
- improved filtering by files in file list
8 files changed with 125 insertions and 39 deletions:
0 comments (0 inline, 0 general)
docs/api/api.rst
Show inline comments
 
@@ -214,49 +214,49 @@ INPUT::
 
                "name":  "<name>",
 
                "active":"<bool> = True"
 
              }
 

	
 
OUTPUT::
 

	
 
    result: {
 
              "id":  "<newusersgroupid>",
 
              "msg": "created new users group <name>"
 
            }
 
    error:  null
 

	
 
add_user_to_users_group
 
-----------------------
 

	
 
Adds a user to a users group. This command can be executed only using api_key
 
belonging to user with admin rights
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "add_user_users_group"
 
    args:     {
 
                "group_name" :  "<groupname>",
 
                "user_name" :   "<username>"
 
                "username" :   "<username>"
 
              }
 

	
 
OUTPUT::
 

	
 
    result: {
 
              "id":  "<newusersgroupmemberid>",
 
              "msg": "created new users group member"
 
            }
 
    error:  null
 

	
 
get_repos
 
---------
 

	
 
Lists all existing repositories. This command can be executed only using api_key
 
belonging to user with admin rights
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "get_repos"
 
    args:     { }
 

	
 
OUTPUT::
 

	
 
@@ -295,88 +295,120 @@ OUTPUT::
 
                "description" : "<description>",
 
                "members" :     [
 
                                  { "id" :         "<userid>",
 
	                                "username" :   "<username>",
 
	                                "firstname":   "<firstname>",
 
	                                "lastname" :   "<lastname>",
 
	                                "email" :      "<email>",
 
	                                "active" :     "<bool>",
 
	                                "admin" :      "<bool>",
 
	                                "ldap" :       "<ldap_dn>",
 
	                                "permission" : "repository.(read|write|admin)"
 
	                              },
 
 
                                  {
 
                                    "id" :       "<usersgroupid>",
 
                                    "name" :     "<usersgroupname>",
 
                                    "active":    "<bool>",
 
                                    "permission" : "repository.(read|write|admin)"
 
                                  },
 
 
                                ]
 
            }
 
    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
 
-----------
 

	
 
Creates a repository. This command can be executed only using api_key
 
belonging to user with admin rights.
 
If repository name contains "/", all needed repository groups will be created.
 
For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent),
 
and create "baz" repository with "bar" as group.
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "create_repo"
 
    args:     {
 
                "name" :        "<name>",
 
                "owner_name" :  "<ownername>",
 
                "description" : "<description> = ''",
 
                "repo_type" :   "<type> = 'hg'",
 
                "private" :     "<bool> = False"
 
              }
 

	
 
OUTPUT::
 

	
 
    result: None
 
    error:  null
 

	
 
add_user_to_repo
 
----------------
 

	
 
Add a user to a repository. This command can be executed only using api_key
 
belonging to user with admin rights.
 
If "perm" is None, user will be removed from the repository.
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "add_user_to_repo"
 
    args:     {
 
                "repo_name" :  "<reponame>",
 
                "user_name" :  "<username>",
 
                "username" :  "<username>",
 
                "perm" :       "(None|repository.(read|write|admin))",
 
              }
 

	
 
OUTPUT::
 

	
 
    result: None
 
    error:  null
 

	
 
add_users_group_to_repo
 
-----------------------
 

	
 
Add a users group to a repository. This command can be executed only using 
 
api_key belonging to user with admin rights. If "perm" is None, group will 
 
be removed from the repository.
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "add_users_group_to_repo"
 
    args:     {
 
                "repo_name" :  "<reponame>",
 
                "group_name" :  "<groupname>",
 
                "perm" :       "(None|repository.(read|write|admin))",
 
              }
 
\ No newline at end of file
docs/changelog.rst
Show inline comments
 
@@ -8,55 +8,58 @@ Changelog
 
======================
 

	
 
:status: in-progress
 
:branch: beta
 

	
 
news
 
----
 

	
 
- code review, inspired by github code-comments 
 
- #215 rst and markdown README files support
 
- #252 Container-based and proxy pass-through authentication support
 
- #44 branch browser. Filtering of changelog by branches
 
- mercurial bookmarks support
 
- hover top menu
 
- configurable clone url template with possibility to specify  protocol like 
 
  ssh:// or http:// and also manually alter other parts of clone_url.
 
- enabled largefiles extension by default
 
- optimized summary file pages and saved a lot of unused space in them
 
- #239 option to manually mark repository as fork
 
- #320 mapping of commit authors to RhodeCode users
 
- #304 hashes are displayed using monospace font    
 
- 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
 
-----
 

	
 
- 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**)
 
======================
 

	
 
news
 
----
 

	
 
- added option to manage repos group for non admin users
 
- added following API methods for get_users, create_user, get_users_groups, 
 
  get_users_group, create_users_group, add_user_to_users_groups, get_repos, 
 
  get_repo, create_repo, add_user_to_repo
 
- implements #237 added password confirmation for my account 
 
  and admin edit user.
 
- implements #291 email notification for global events are now sent to all
 
  administrator users, and global config email.
 
     
 
fixes
 
-----
 

	
 
- added option for passing auth method for smtp mailer
 
- #276 issue with adding a single user with id>10 to usergroups
 
- #277 fixes windows LDAP settings in which missing values breaks the ldap auth 
 
- #288 fixes managing of repos in a group for non admin user
 

	
rhodecode/controllers/api/api.py
Show inline comments
 
@@ -191,66 +191,66 @@ class ApiController(JSONRPCController):
 
        return result
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def create_users_group(self, apiuser, name, active=True):
 
        """
 
        Creates an new usergroup
 

	
 
        :param name:
 
        :param active:
 
        """
 

	
 
        if self.get_users_group(apiuser, name):
 
            raise JSONRPCError("users group %s already exist" % name)
 

	
 
        try:
 
            ug = UsersGroupModel().create(name=name, active=active)
 
            Session.commit()
 
            return dict(id=ug.users_group_id,
 
                        msg='created new users group %s' % name)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            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:
 
            users_group = UsersGroup.get_by_group_name(group_name)
 
            if not users_group:
 
                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()
 
            return dict(id=ugm.users_group_member_id,
 
                        msg='created new users group member')
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to create users group member')
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def get_repo(self, apiuser, repo_name):
 
        """"
 
        Get repository by name
 

	
 
        :param apiuser:
 
        :param repo_name:
 
        """
 

	
 
        repo = Repository.get_by_repo_name(repo_name)
 
        if repo is None:
 
            raise JSONRPCError('unknown repository %s' % repo)
 

	
 
        members = []
 
        for user in repo.repo_to_perm:
 
@@ -290,48 +290,76 @@ class ApiController(JSONRPCController):
 
            description=repo.description,
 
            members=members
 
        )
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def get_repos(self, apiuser):
 
        """"
 
        Get all repositories
 

	
 
        :param apiuser:
 
        """
 

	
 
        result = []
 
        for repository in Repository.getAll():
 
            result.append(
 
                dict(
 
                    id=repository.repo_id,
 
                    name=repository.repo_name,
 
                    type=repository.repo_type,
 
                    description=repository.description
 
                )
 
            )
 
        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):
 
        """
 
        Create a repository
 

	
 
        :param apiuser:
 
        :param name:
 
        :param description:
 
        :param type:
 
        :param private:
 
        :param owner_name:
 
        """
 

	
 
        try:
 
            try:
 
                owner = User.get_by_username(owner_name)
 
            except NoResultFound:
 
                raise JSONRPCError('unknown user %s' % owner)
 

	
 
            if self.get_repo(apiuser, name):
 
                raise JSONRPCError("repo %s already exist" % name)
 

	
 
            groups = name.split('/')
 
@@ -347,82 +375,82 @@ class ApiController(JSONRPCController):
 
                            group_description='',
 
                            group_parent_id=parent_id
 
                        )
 
                    )
 
                parent_id = group.group_id
 

	
 
            RepoModel().create(
 
                dict(
 
                    repo_name=real_name,
 
                    repo_name_full=name,
 
                    description=description,
 
                    private=private,
 
                    repo_type=repo_type,
 
                    repo_group=parent_id,
 
                    clone_uri=None
 
                ),
 
                owner
 
            )
 
            Session.commit()
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            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:
 
        """
 

	
 
        try:
 
            repo = Repository.get_by_repo_name(repo_name)
 
            if repo is None:
 
                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)
 

	
 
            RepositoryPermissionModel()\
 
                .update_or_delete_user_permission(repo, user, perm)
 
            Session.commit()
 

	
 
            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
 
                )
 
            )
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def add_users_group_to_repo(self, apiuser, repo_name, group_name, perm):
 
        """
 
        Add permission for a users group to a repository
 

	
 
        :param apiuser:
 
        :param repo_name:
 
        :param group_name:
 
        :param perm:
 
        """
 

	
 
        try:
 
            repo = Repository.get_by_repo_name(repo_name)
 
            if repo is None:
 
                raise JSONRPCError('unknown repository %s' % repo)
 

	
 
            try:
 
                user_group = UsersGroup.get_by_group_name(group_name)
 
            except NoResultFound:
 
                raise JSONRPCError('unknown users group %s' % user_group)
 

	
rhodecode/controllers/files.py
Show inline comments
 
@@ -28,48 +28,49 @@ import logging
 
import traceback
 

	
 
from pylons import request, response, tmpl_context as c, url
 
from pylons.i18n.translation import _
 
from pylons.controllers.util import redirect
 
from pylons.decorators import jsonify
 

	
 
from vcs.conf import settings
 
from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
 
    EmptyRepositoryError, ImproperArchiveTypeError, VCSError, \
 
    NodeAlreadyExistsError
 
from vcs.nodes import FileNode
 

	
 
from rhodecode.lib.compat import OrderedDict
 
from rhodecode.lib import convert_line_endings, detect_mode, safe_str
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 
from rhodecode.lib.base import BaseRepoController, render
 
from rhodecode.lib.utils import EmptyChangeset
 
from rhodecode.lib import diffs
 
import rhodecode.lib.helpers as h
 
from rhodecode.model.repo import RepoModel
 
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__)
 

	
 

	
 
class FilesController(BaseRepoController):
 

	
 
    @LoginRequired()
 
    def __before__(self):
 
        super(FilesController, self).__before__()
 
        c.cut_off_limit = self.cut_off_limit
 

	
 
    def __get_cs_or_redirect(self, rev, repo_name, redirect_after=True):
 
        """
 
        Safe way to get changeset if error occur it redirects to tip with
 
        proper message
 

	
 
        :param rev: revision to fetch
 
        :param repo_name: repo name to redirect after
 
        """
 

	
 
        try:
 
            return c.rhodecode_repo.get_changeset(rev)
 
        except EmptyRepositoryError, e:
 
            if not redirect_after:
 
@@ -86,67 +87,48 @@ class FilesController(BaseRepoController
 
            h.flash(str(e), category='warning')
 
            redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
 

	
 
    def __get_filenode_or_redirect(self, repo_name, cs, path):
 
        """
 
        Returns file_node, if error occurs or given path is directory,
 
        it'll redirect to top level path
 

	
 
        :param repo_name: repo_name
 
        :param cs: given changeset
 
        :param path: path to lookup
 
        """
 

	
 
        try:
 
            file_node = cs.get_node(path)
 
            if file_node.is_dir():
 
                raise RepositoryError('given path is a directory')
 
        except RepositoryError, e:
 
            h.flash(str(e), category='warning')
 
            redirect(h.url('files_home', repo_name=repo_name,
 
                           revision=cs.raw_id))
 

	
 
        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):
 
        # redirect to given revision from form if given
 
        post_revision = request.POST.get('at_rev', None)
 
        if post_revision:
 
            cs = self.__get_cs_or_redirect(post_revision, repo_name)
 
            redirect(url('files_home', repo_name=c.repo_name,
 
                         revision=cs.raw_id, f_path=f_path))
 

	
 
        c.changeset = self.__get_cs_or_redirect(revision, repo_name)
 
        c.branch = request.GET.get('branch', None)
 
        c.f_path = f_path
 

	
 
        cur_rev = c.changeset.revision
 

	
 
        # prev link
 
        try:
 
            prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
 
            c.url_prev = url('files_home', repo_name=c.repo_name,
 
                         revision=prev_rev.raw_id, f_path=f_path)
 
            if c.branch:
 
                c.url_prev += '?branch=%s' % c.branch
 
        except (ChangesetDoesNotExistError, VCSError):
 
@@ -484,27 +466,28 @@ class FilesController(BaseRepoController
 
        tags_group = ([], _("Tags"))
 

	
 
        for chs in changesets:
 
            n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
 
            changesets_group[0].append((chs.raw_id, n_desc,))
 

	
 
        hist_l.append(changesets_group)
 

	
 
        for name, chs in c.rhodecode_repo.branches.items():
 
            branches_group[0].append((chs, name),)
 
        hist_l.append(branches_group)
 

	
 
        for name, chs in c.rhodecode_repo.tags.items():
 
            tags_group[0].append((chs, name),)
 
        hist_l.append(tags_group)
 

	
 
        return hist_l
 

	
 
    @jsonify
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    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
 

	
rhodecode/lib/indexers/__init__.py
Show inline comments
 
@@ -108,118 +108,118 @@ class MakeIndex(BasePasterCommand):
 
                .run(full_index=self.options.full_index)
 
            l.release()
 
        except LockHeld:
 
            sys.exit(1)
 

	
 
    def update_parser(self):
 
        self.parser.add_option('--repo-location',
 
                          action='store',
 
                          dest='repo_location',
 
                          help="Specifies repositories location to index OPTIONAL",
 
                          )
 
        self.parser.add_option('--index-only',
 
                          action='store',
 
                          dest='repo_list',
 
                          help="Specifies a comma separated list of repositores "
 
                                "to build index on OPTIONAL",
 
                          )
 
        self.parser.add_option('-f',
 
                          action='store_true',
 
                          dest='full_index',
 
                          help="Specifies that index should be made full i.e"
 
                                " 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
 
        self.searcher = searcher
 
        self.matcher = matcher
 
        self.highlight_items = highlight_items
 
        self.fragment_size = 200 / 2
 

	
 
    @LazyProperty
 
    def doc_ids(self):
 
        docs_id = []
 
        while self.matcher.is_active():
 
            docnum = self.matcher.id()
 
            chunks = [offsets for offsets in self.get_chunks()]
 
            docs_id.append([docnum, chunks])
 
            self.matcher.next()
 
        return docs_id
 

	
 
    def __str__(self):
 
        return '<%s at %s>' % (self.__class__.__name__, len(self.doc_ids))
 

	
 
    def __repr__(self):
 
        return self.__str__()
 

	
 
    def __len__(self):
 
        return len(self.doc_ids)
 

	
 
    def __iter__(self):
 
        """
 
        Allows Iteration over results,and lazy generate content
 

	
 
        *Requires* implementation of ``__getitem__`` method.
 
        """
 
        for docid in self.doc_ids:
 
            yield self.get_full_content(docid)
 

	
 
    def __getitem__(self, key):
 
        """
 
        Slicing of resultWrapper
 
        """
 
        i, j = key.start, key.stop
 

	
 
        slice = []
 
        for docid in self.doc_ids[i:j]:
 
            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']) \
 
                             + len(res['repository']):].lstrip('/')
 

	
 
        content_short = self.get_short_content(res, docid[1])
 
        res.update({'content_short':content_short,
 
                    'content_short_hl':self.highlight(content_short),
 
                    'f_path':f_path})
 

	
 
        return res
 

	
 
    def get_short_content(self, res, chunks):
 

	
 
        return ''.join([res['content'][chunk[0]:chunk[1]] for chunk in chunks])
 

	
 
    def get_chunks(self):
 
        """
 
        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:
 
        """
 
        memory = [(0, 0)]
 
        for span in self.matcher.spans():
 
            start = span.startchar or 0
 
            end = span.endchar or 0
 
            start_offseted = max(0, start - self.fragment_size)
 
            end_offseted = end + self.fragment_size
 

	
 
            if start_offseted < memory[-1][1]:
 
                start_offseted = memory[-1][1]
 
            memory.append((start_offseted, end_offseted,))
 
            yield (start_offseted, end_offseted,)
 

	
 
    def highlight(self, content, top=5):
 
        if self.search_type != 'content':
 
            return ''
 
        hl = highlight(escape(content),
 
                 self.highlight_items,
 
                 analyzer=ANALYZER,
 
                 fragmenter=FRAGMENTER,
 
                 formatter=FORMATTER,
 
                 top=top)
rhodecode/model/scm.py
Show inline comments
 
@@ -370,26 +370,56 @@ class ScmModel(BaseModel):
 
            ))
 

	
 
        message = safe_str(message)
 
        path = safe_str(f_path)
 
        author = safe_str(author)
 
        m = IMC(repo)
 

	
 
        if isinstance(cs, EmptyChangeset):
 
            # Emptychangeset means we we're editing empty repository
 
            parents = None
 
        else:
 
            parents = [cs]
 

	
 
        m.add(FileNode(path, content=content))
 
        tip = m.commit(message=message,
 
                 author=author,
 
                 parents=parents, branch=cs.branch)
 
        new_cs = tip.short_id
 
        action = 'push_local:%s' % new_cs
 

	
 
        action_logger(user, action, repo_name)
 

	
 
        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()
rhodecode/public/js/rhodecode.js
Show inline comments
 
@@ -397,110 +397,120 @@ var fileBrowserListeners = function(curr
 
	        uri = uri.replace('__BRANCH__',e.target.value);
 
	        window.location = uri;
 
	    }
 
	    else{
 
	        window.location = current_url;
 
	    }
 
	})            
 

	
 
	var n_filter = YUD.get('node_filter');
 
	var F = YAHOO.namespace('node_filter');
 
	
 
	F.filterTimeout = null;
 
	var nodes = null;
 

	
 
	F.initFilter = function(){
 
	  YUD.setStyle('node_filter_box_loading','display','');
 
	  YUD.setStyle('search_activate_id','display','none');
 
	  YUD.setStyle('add_node_id','display','none');
 
	  YUC.initHeader('X-PARTIAL-XHR',true);
 
	  YUC.asyncRequest('GET',url,{
 
	      success:function(o){
 
	        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');
 
	      }
 
	  },null);            
 
	}
 

	
 
	F.updateFilter  = function(e) {
 
	    
 
	    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++
 
	                    //show only certain amount to not kill browser 
 
	                    if (matches > matches_max){
 
	                        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));
 
	                }
 
	                
 
	            }                       
 
	        }
 
	        if(query != ""){
 
	            YUD.setStyle('tbody','display','none');
 
	            YUD.setStyle('tbody_filtered','display','');
 
	            
 
	            if (match.length==0){
 
	              match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(nomatch_lbl));
 
	            }                           
 
	            
 
	            YUD.get('tbody_filtered').innerHTML = match.join("");   
 
	        }
 
	        else{
 
	            YUD.setStyle('tbody','display','');
 
	            YUD.setStyle('tbody_filtered','display','none');
 
	        }
 
	        
 
	    }
 
	};
 

	
 
	YUE.on(YUD.get('filter_activate'),'click',function(){
 
	    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); 
 
	    F.filterTimeout = setTimeout(F.updateFilter(e),600);
 
	});
 
};
 

	
 

	
 
var initCodeMirror = function(textAreadId,resetUrl){  
 
    var myCodeMirror = CodeMirror.fromTextArea(YUD.get(textAreadId),{
 
           mode:  "null",
 
           lineNumbers:true
 
         });
 
    YUE.on('reset','click',function(e){
 
        window.location=resetUrl
 
    });
 
    
 
    YUE.on('file_enable','click',function(){
 
        YUD.setStyle('editor_container','display','');
 
        YUD.setStyle('upload_file_container','display','none');
 
        YUD.setStyle('filename_container','display','');
 
    });
 
    
 
    YUE.on('upload_file_enable','click',function(){
rhodecode/templates/files/files_browser.html
Show inline comments
 
@@ -13,49 +13,49 @@
 
	          <span class="rev">${_('view')}@rev</span> 
 
	          <a class="ui-btn" href="${c.url_prev}" title="${_('previous revision')}">&laquo;</a>
 
	          ${h.text('at_rev',value=c.changeset.revision,size=5)}
 
	          <a class="ui-btn" href="${c.url_next}" title="${_('next revision')}">&raquo;</a>
 
	          ## ${h.submit('view',_('view'),class_="ui-btn")}
 
		    </div>           
 
			${h.end_form()}
 
		</div>
 
	    <div class="browser-branch">
 
	       ${h.checkbox('stay_at_branch',c.changeset.branch,c.changeset.branch==c.branch)}
 
	       <label>${_('follow current branch')}</label>
 
	    </div>
 
        <div class="browser-search">
 
              <div id="search_activate_id" class="search_activate">
 
                  <a class="ui-btn" id="filter_activate" href="#">${_('search file list')}</a>
 
              </div>
 
              % if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):            
 
                    <div id="add_node_id" class="add_node">
 
                        <a class="ui-btn" href="${h.url('files_add_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path)}">${_('add new file')}</a>
 
                    </div>
 
              % endif               
 
        <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>      
 
    </div>
 
    
 
	<div class="browser-body">
 
		<table class="code-browser">
 
		         <thead>
 
		             <tr>
 
		                 <th>${_('Name')}</th>
 
		                 <th>${_('Size')}</th>
 
		                 <th>${_('Mimetype')}</th>
 
		                 <th>${_('Revision')}</th>
 
		                 <th>${_('Last modified')}</th>
 
		                 <th>${_('Last commiter')}</th>
 
		             </tr>
 
		         </thead>
 
                
 
                <tbody id="tbody">
 
          		%if c.file.parent:
 
         		<tr class="parity0">
 
	          		<td>		          		
 
	          			${h.link_to('..',h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.file.parent.path),class_="browser-dir ypjax-link")}
 
	          		</td>
0 comments (0 inline, 0 general)