Changeset - 523382549c45
[Not reviewed]
beta
0 3 1
Marcin Kuzminski - 15 years ago 2011-04-01 18:46:24
marcin@python-works.com
Added repo group page showing what reposiories are inside a group
4 files changed with 167 insertions and 2 deletions:
0 comments (0 inline, 0 general)
rhodecode/controllers/admin/repos_groups.py
Show inline comments
 
import logging
 
from operator import itemgetter
 

	
 
from pylons import request, response, session, tmpl_context as c, url
 
from pylons.controllers.util import abort, redirect
 

	
 
from rhodecode.lib.base import BaseController, render
 
from rhodecode.model.db import Group
 

	
 
log = logging.getLogger(__name__)
 

	
 
class ReposGroupsController(BaseController):
 
    """REST Controller styled on the Atom Publishing Protocol"""
 
    # To properly map this controller, ensure your config/routing.py
 
    # file has a resource setup:
 
    #     map.resource('repos_group', 'repos_groups')
 

	
 
    def index(self, format='html'):
 
        """GET /repos_groups: All items in the collection"""
 
        # url('repos_groups')
 

	
 
    def create(self):
 
        """POST /repos_groups: Create a new item"""
 
        # url('repos_groups')
 

	
 
    def new(self, format='html'):
 
        """GET /repos_groups/new: Form to create a new item"""
 
        # url('new_repos_group')
 

	
 
    def update(self, id):
 
        """PUT /repos_groups/id: Update an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="PUT" />
 
        # Or using helpers:
 
        #    h.form(url('repos_group', id=ID),
 
        #           method='put')
 
        # url('repos_group', id=ID)
 

	
 
    def delete(self, id):
 
        """DELETE /repos_groups/id: Delete an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="DELETE" />
 
        # Or using helpers:
 
        #    h.form(url('repos_group', id=ID),
 
        #           method='delete')
 
        # url('repos_group', id=ID)
 

	
 
    def show(self, id, format='html'):
 
        """GET /repos_groups/id: Show a specific item"""
 
        # url('repos_group', id=ID)
 

	
 
        c.group = Group.get(id)
 
        if c.group:
 
            c.group_repos = c.group.repositories
 
        else:
 
            return redirect(url('repos_group'))
 

	
 
        sortables = ['name', 'description', 'last_change', 'tip', 'owner']
 
        current_sort = request.GET.get('sort', 'name')
 
        current_sort_slug = current_sort.replace('-', '')
 

	
 
        if current_sort_slug not in sortables:
 
            c.sort_by = 'name'
 
            current_sort_slug = c.sort_by
 
        else:
 
            c.sort_by = current_sort
 
        c.sort_slug = current_sort_slug
 

	
 
        sort_key = current_sort_slug + '_sort'
 

	
 

	
 
        #overwrite our cached list with current filter
 
        gr_filter = [r.repo_name for r in c.group_repos]
 
        c.cached_repo_list = self.scm_model.get_repos(all_repos=gr_filter)
 

	
 
        if c.sort_by.startswith('-'):
 
            c.repos_list = sorted(c.cached_repo_list, key=itemgetter(sort_key),
 
                                  reverse=True)
 
        else:
 
            c.repos_list = sorted(c.cached_repo_list, key=itemgetter(sort_key),
 
                                  reverse=False)
 

	
 
        c.repo_cnt = len(c.repos_list)
 

	
 

	
 
        return render('admin/repos_groups/repos_groups.html')
 

	
 

	
 
    def edit(self, id, format='html'):
 
        """GET /repos_groups/id/edit: Form to edit an existing item"""
 
        # url('edit_repos_group', id=ID)
rhodecode/model/db.py
Show inline comments
 
@@ -225,96 +225,100 @@ class Repository(Base):
 
        while 1:
 
            gr = getattr(cur_gr, 'parent_group', None)
 
            cur_gr = cur_gr.parent_group
 
            if gr is None:
 
                break
 
            groups.insert(0, gr)
 

	
 
        return groups
 

	
 
    @property
 
    def groups_and_repo(self):
 
        return self.groups_with_parents, self.just_name
 

	
 

	
 
class Group(Base):
 
    __tablename__ = 'groups'
 
    __table_args__ = (UniqueConstraint('group_name'), {'useexisting':True},)
 

	
 
    group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
 

	
 
    parent_group = relationship('Group', remote_side=group_id)
 

	
 

	
 
    def __init__(self, group_name='', parent_group=None):
 
        self.group_name = group_name
 
        self.parent_group = parent_group
 

	
 
    def __repr__(self):
 
        return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
 
                                  self.group_name)
 

	
 
    @property
 
    def parents(self):
 
        groups = []
 
        if self.parent_group is None:
 
            return groups
 
        cur_gr = self.parent_group
 
        groups.insert(0, cur_gr)
 
        while 1:
 
            gr = getattr(cur_gr, 'parent_group', None)
 
            cur_gr = cur_gr.parent_group
 
            if gr is None:
 
                break
 
            groups.insert(0, gr)
 
        return groups
 

	
 
    @property
 
    def repositories(self):
 
        return Session.query(Repository).filter(Repository.group == self).all()
 

	
 
class Permission(Base):
 
    __tablename__ = 'permissions'
 
    __table_args__ = {'useexisting':True}
 
    permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __repr__(self):
 
        return "<%s('%s:%s')>" % (self.__class__.__name__,
 
                                  self.permission_id, self.permission_name)
 

	
 
class RepoToPerm(Base):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
 
    repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
class UserToPerm(Base):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
 
    user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission')
 

	
 

	
 
class UsersGroupToPerm(Base):
 
    __tablename__ = 'users_group_to_perm'
 
    __table_args__ = (UniqueConstraint('users_group_id', 'permission_id'), {'useexisting':True})
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
class GroupToPerm(Base):
 
    __tablename__ = 'group_to_perm'
rhodecode/model/scm.py
Show inline comments
 
@@ -80,98 +80,99 @@ class ScmModel(BaseModel):
 
        """
 

	
 
        q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
 

	
 
        return q.ui_value
 

	
 
    def repo_scan(self, repos_path=None):
 
        """Listing of repositories in given path. This path should not be a 
 
        repository itself. Return a dictionary of repository objects
 
        
 
        :param repos_path: path to directory containing repositories
 
        """
 

	
 
        log.info('scanning for repositories in %s', repos_path)
 

	
 
        if repos_path is None:
 
            repos_path = self.repos_path
 

	
 
        baseui = make_ui('db')
 
        repos_list = {}
 

	
 
        for name, path in get_filesystem_repos(repos_path, recursive=True):
 
            try:
 
                if repos_list.has_key(name):
 
                    raise RepositoryError('Duplicate repository name %s '
 
                                    'found in %s' % (name, path))
 
                else:
 

	
 
                    klass = get_backend(path[0])
 

	
 
                    if path[0] == 'hg' and path[0] in BACKENDS.keys():
 
                        repos_list[name] = klass(path[1], baseui=baseui)
 

	
 
                    if path[0] == 'git' and path[0] in BACKENDS.keys():
 
                        repos_list[name] = klass(path[1])
 
            except OSError:
 
                continue
 

	
 
        return repos_list
 

	
 
    def get_repos(self, all_repos=None):
 
        """Get all repos from db and for each repo create it's backend instance.
 
        and fill that backed with information from database
 
        
 
        :param all_repos: give specific repositories list, good for filtering
 
            this have to be a list of  just the repository names
 
        """
 
        if all_repos is None:
 
            all_repos = [r.repo_name for r in self.sa.query(Repository)\
 
                .order_by(Repository.repo_name).all()]
 
            repos = self.sa.query(Repository)\
 
                        .order_by(Repository.repo_name).all()
 
            all_repos = [r.repo_name for r in repos]
 

	
 
        #get the repositories that should be invalidated
 
        invalidation_list = [str(x.cache_key) for x in \
 
                             self.sa.query(CacheInvalidation.cache_key)\
 
                             .filter(CacheInvalidation.cache_active == False)\
 
                             .all()]
 
        for r_name in all_repos:
 
            r_dbr = self.get(r_name, invalidation_list)
 
            if r_dbr is not None:
 
                repo, dbrepo = r_dbr
 

	
 
                last_change = repo.last_change
 
                tip = h.get_changeset_safe(repo, 'tip')
 

	
 
                tmp_d = {}
 
                tmp_d['name'] = dbrepo.repo_name
 
                tmp_d['name_sort'] = tmp_d['name'].lower()
 
                tmp_d['description'] = dbrepo.description
 
                tmp_d['description_sort'] = tmp_d['description']
 
                tmp_d['last_change'] = last_change
 
                tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
 
                tmp_d['tip'] = tip.raw_id
 
                tmp_d['tip_sort'] = tip.revision
 
                tmp_d['rev'] = tip.revision
 
                tmp_d['contact'] = dbrepo.user.full_contact
 
                tmp_d['contact_sort'] = tmp_d['contact']
 
                tmp_d['owner_sort'] = tmp_d['contact']
 
                tmp_d['repo_archives'] = list(repo._get_archives())
 
                tmp_d['last_msg'] = tip.message
 
                tmp_d['repo'] = repo
 
                tmp_d['dbrepo'] = dbrepo.get_dict()
 
                tmp_d['dbrepo_fork'] = dbrepo.fork.get_dict() if dbrepo.fork else {}
 
                yield tmp_d
 

	
 
    def get(self, repo_name, invalidation_list=None, retval='all'):
 
        """Returns a tuple of Repository,DbRepository,
 
        Get's repository from given name, creates BackendInstance and
 
        propagates it's data from database with all additional information
 
        
 
        :param repo_name:
 
        :param invalidation_list: if a invalidation list is given the get
 
            method should not manually check if this repository needs 
 
            invalidation and just invalidate the repositories in list
 
        :param retval: string specifing what to return one of 'repo','dbrepo',
 
            'all'if repo or dbrepo is given it'll just lazy load chosen type
 
            and return None as the second
 
        """
 
        if not HasRepoPermissionAny('repository.read', 'repository.write',
rhodecode/templates/admin/repos_groups/repos_groups.html
Show inline comments
 
new file 100644
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('Repository group')} - ${c.rhodecode_name}
 
</%def>
 

	
 

	
 
<%def name="breadcrumbs_links()">
 
    ${_('Group')} &raquo; ${c.group.group_name} - ${_(' %s repositories' % c.repo_cnt)} 
 
</%def>
 
<%def name="page_nav()">
 
    ${self.menu('admin')}
 
</%def>
 
<%def name="main()">
 
    <%def name="get_sort(name)">
 
        <%name_slug = name.lower().replace(' ','_') %>
 
        
 
        %if name_slug == c.sort_slug:
 
          %if c.sort_by.startswith('-'):
 
            <a href="?sort=${name_slug}">${name}&uarr;</a>
 
          %else:
 
            <a href="?sort=-${name_slug}">${name}&darr;</a>
 
          %endif:
 
        %else:
 
            <a href="?sort=${name_slug}">${name}</a>
 
        %endif
 
    </%def>
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}       
 
    </div>
 
    <!-- end box / title -->
 
        <div class="table">
 
            <table>
 
            <thead>
 
                <tr>
 
                    <th class="left">${get_sort(_('Name'))}</th>
 
                    <th class="left">${get_sort(_('Description'))}</th>
 
                    <th class="left">${get_sort(_('Last change'))}</th>
 
                    <th class="left">${get_sort(_('Tip'))}</th>
 
                    <th class="left">${get_sort(_('Owner'))}</th>
 
                    <th class="left">${_('RSS')}</th>
 
                    <th class="left">${_('Atom')}</th>
 
                </tr>
 
            </thead>
 
            <tbody>
 
            %for cnt,repo in enumerate(c.repos_list):
 
                <tr class="parity${cnt%2}">
 
                    <td>
 
                    <div style="white-space: nowrap">
 
                     ## TYPE OF REPO
 
                     %if repo['dbrepo']['repo_type'] =='hg':
 
                       <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
 
                     %elif repo['dbrepo']['repo_type'] =='git':
 
                       <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
 
                     %else:
 
                       
 
                     %endif 
 
                    
 
                     ##PRIVATE/PUBLIC
 
                     %if repo['dbrepo']['private']:
 
                        <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url("/images/icons/lock.png")}"/>
 
                     %else:
 
                        <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url("/images/icons/lock_open.png")}"/>
 
                     %endif
 
                    
 
                    ##NAME   
 
                    ${h.link_to(repo['name'],
 
                        h.url('summary_home',repo_name=repo['name']),class_="repo_name")}
 
                    %if repo['dbrepo_fork']:
 
                        <a href="${h.url('summary_home',repo_name=repo['dbrepo_fork']['repo_name'])}">
 
                        <img class="icon" alt="${_('fork')}"
 
                        title="${_('Fork of')} ${repo['dbrepo_fork']['repo_name']}" 
 
                        src="${h.url("/images/icons/arrow_divide.png")}"/></a>
 
                    %endif
 
                    </div>
 
                    </td>
 
                    ##DESCRIPTION
 
                    <td><span class="tooltip" title="${h.tooltip(repo['description'])}">
 
                       ${h.truncate(repo['description'],60)}</span>
 
                    </td>
 
                    ##LAST CHANGE
 
                    <td>
 
                      <span class="tooltip" title="${repo['last_change']}">
 
                      ${h.age(repo['last_change'])}</span>
 
                    </td>
 
                    <td>
 
                        %if repo['rev']>=0:
 
                        ${h.link_to('r%s:%s' % (repo['rev'],h.short_id(repo['tip'])),
 
                        h.url('changeset_home',repo_name=repo['name'],revision=repo['tip']),
 
                        class_="tooltip",
 
                        title=h.tooltip(repo['last_msg']))}
 
                        %else:
 
                            ${_('No changesets yet')}
 
                        %endif    
 
                    </td>
 
                    <td title="${repo['contact']}">${h.person(repo['contact'])}</td>
 
                    <td>
 
                      %if c.rhodecode_user.username != 'default':
 
                        <a title="${_('Subscribe to %s rss feed')%repo['name']}" class="rss_icon"  href="${h.url('rss_feed_home',repo_name=repo['name'],api_key=c.rhodecode_user.api_key)}"></a>
 
                      %else:
 
                        <a title="${_('Subscribe to %s rss feed')%repo['name']}" class="rss_icon"  href="${h.url('rss_feed_home',repo_name=repo['name'])}"></a>
 
                      %endif:                       
 
                    </td>        
 
                    <td>
 
                      %if c.rhodecode_user.username != 'default':
 
                        <a title="${_('Subscribe to %s atom feed')%repo['name']}"  class="atom_icon" href="${h.url('atom_feed_home',repo_name=repo['name'],api_key=c.rhodecode_user.api_key)}"></a>
 
                      %else:
 
                        <a title="${_('Subscribe to %s atom feed')%repo['name']}"  class="atom_icon" href="${h.url('atom_feed_home',repo_name=repo['name'])}"></a>
 
                      %endif:
 
                    </td>
 
                </tr>
 
            %endfor
 
            </tbody>
 
            </table>
 
            </div>
 
</div> 
 
           
 
</%def>    
0 comments (0 inline, 0 general)