Changeset - 9dacacc5b7c2
[Not reviewed]
beta
0 3 0
Marcin Kuzminski - 14 years ago 2011-05-22 21:09:02
marcin@python-works.com
When creating a remote repository, with credentials filled, it's good to hide username and password from the clone url. Only administrators can see this in repository settings page
3 files changed with 100 insertions and 29 deletions:
0 comments (0 inline, 0 general)
rhodecode/lib/__init__.py
Show inline comments
 
@@ -80,96 +80,165 @@ def str2bool(_str):
 
    if _str in (True, False):
 
        return _str
 
    _str = str(_str).strip().lower()
 
    return _str in ('t', 'true', 'y', 'yes', 'on', '1')
 

	
 

	
 
def convert_line_endings(temp, mode):
 
    from string import replace
 
    #modes:  0 - Unix, 1 - Mac, 2 - DOS
 
    if mode == 0:
 
            temp = replace(temp, '\r\n', '\n')
 
            temp = replace(temp, '\r', '\n')
 
    elif mode == 1:
 
            temp = replace(temp, '\r\n', '\r')
 
            temp = replace(temp, '\n', '\r')
 
    elif mode == 2:
 
            import re
 
            temp = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", temp)
 
    return temp
 

	
 

	
 
def detect_mode(line, default):
 
    """
 
    Detects line break for given line, if line break couldn't be found
 
    given default value is returned
 

	
 
    :param line: str line
 
    :param default: default
 
    :rtype: int
 
    :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
 
    """
 
    if line.endswith('\r\n'):
 
        return 2
 
    elif line.endswith('\n'):
 
        return 0
 
    elif line.endswith('\r'):
 
        return 1
 
    else:
 
        return default
 

	
 

	
 
def generate_api_key(username, salt=None):
 
    """
 
    Generates unique API key for given username,if salt is not given
 
    it'll be generated from some random string
 

	
 
    :param username: username as string
 
    :param salt: salt to hash generate KEY
 
    :rtype: str
 
    :returns: sha1 hash from username+salt
 
    """
 
    from tempfile import _RandomNameSequence
 
    import hashlib
 

	
 
    if salt is None:
 
        salt = _RandomNameSequence().next()
 

	
 
    return hashlib.sha1(username + salt).hexdigest()
 

	
 

	
 
def safe_unicode(_str, from_encoding='utf8'):
 
    """
 
    safe unicode function. In case of UnicodeDecode error we try to return
 
    unicode with errors replace
 

	
 
    :param _str: string to decode
 
    :rtype: unicode
 
    :returns: unicode object
 
    """
 

	
 
    if isinstance(_str, unicode):
 
        return _str
 

	
 
    try:
 
        u_str = unicode(_str, from_encoding)
 
    except UnicodeDecodeError:
 
        u_str = unicode(_str, from_encoding, 'replace')
 

	
 
    return u_str
 

	
 

	
 
def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
 
    """
 
    Custom engine_from_config functions that makes sure we use NullPool for
 
    file based sqlite databases. This prevents errors on sqlite.
 

	
 
    """
 
    from sqlalchemy import engine_from_config as efc
 
    from sqlalchemy.pool import NullPool
 

	
 
    url = configuration[prefix + 'url']
 

	
 
    if url.startswith('sqlite'):
 
        kwargs.update({'poolclass': NullPool})
 

	
 
    return efc(configuration, prefix, **kwargs)
 

	
 

	
 
def age(curdate):
 
    """
 
    turns a datetime into an age string.
 
    
 
    :param curdate: datetime object
 
    :rtype: unicode
 
    :returns: unicode words describing age
 
    """
 

	
 
    from datetime import datetime
 
    from webhelpers.date import time_ago_in_words
 

	
 
    _ = lambda s:s
 

	
 
    if not curdate:
 
        return ''
 

	
 
    agescales = [(_(u"year"), 3600 * 24 * 365),
 
                 (_(u"month"), 3600 * 24 * 30),
 
                 (_(u"day"), 3600 * 24),
 
                 (_(u"hour"), 3600),
 
                 (_(u"minute"), 60),
 
                 (_(u"second"), 1), ]
 

	
 
    age = datetime.now() - curdate
 
    age_seconds = (age.days * agescales[2][1]) + age.seconds
 
    pos = 1
 
    for scale in agescales:
 
        if scale[1] <= age_seconds:
 
            if pos == 6:pos = 5
 
            return '%s %s' % (time_ago_in_words(curdate,
 
                                                agescales[pos][0]), _('ago'))
 
        pos += 1
 

	
 
    return _(u'just now')
 

	
 

	
 
def credentials_hidder(uri):
 
    """
 
    Removes user:password from given url string
 
    
 
    :param uri:
 
    :rtype: unicode
 
    :returns: filtered list of strings    
 
    """
 
    if not uri:
 
        return ''
 

	
 
    proto = ''
 

	
 
    for pat in ('https://', 'http://'):
 
        if uri.startswith(pat):
 
            uri = uri[len(pat):]
 
            proto = pat
 
            break
 

	
 
    # remove passwords and username
 
    uri = uri[uri.find('@') + 1:]
 

	
 
    # get the port
 
    cred_pos = uri.find(':')
 
    if cred_pos == -1:
 
        host, port = uri, None
 
    else:
 
        host, port = uri[:cred_pos], uri[cred_pos + 1:]
 

	
 
    return filter(None, [proto, host, port])
rhodecode/lib/helpers.py
Show inline comments
 
@@ -227,468 +227,470 @@ class CodeHtmlFormatter(HtmlFormatter):
 

	
 

	
 
def pygmentize(filenode, **kwargs):
 
    """pygmentize function using pygments
 

	
 
    :param filenode:
 
    """
 

	
 
    return literal(code_highlight(filenode.content,
 
                                  filenode.lexer, CodeHtmlFormatter(**kwargs)))
 

	
 
def pygmentize_annotation(repo_name, filenode, **kwargs):
 
    """pygmentize function for annotation
 

	
 
    :param filenode:
 
    """
 

	
 
    color_dict = {}
 
    def gen_color(n=10000):
 
        """generator for getting n of evenly distributed colors using
 
        hsv color and golden ratio. It always return same order of colors
 

	
 
        :returns: RGB tuple
 
        """
 
        import colorsys
 
        golden_ratio = 0.618033988749895
 
        h = 0.22717784590367374
 

	
 
        for _ in xrange(n):
 
            h += golden_ratio
 
            h %= 1
 
            HSV_tuple = [h, 0.95, 0.95]
 
            RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
 
            yield map(lambda x:str(int(x * 256)), RGB_tuple)
 

	
 
    cgenerator = gen_color()
 

	
 
    def get_color_string(cs):
 
        if color_dict.has_key(cs):
 
            col = color_dict[cs]
 
        else:
 
            col = color_dict[cs] = cgenerator.next()
 
        return "color: rgb(%s)! important;" % (', '.join(col))
 

	
 
    def url_func(repo_name):
 
        def _url_func(changeset):
 
            tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
 
            " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
 

	
 
            tooltip_html = tooltip_html % (changeset.author,
 
                                                   changeset.date,
 
                                                   tooltip(changeset.message))
 
            lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
 
                                     short_id(changeset.raw_id))
 
            uri = link_to(
 
                    lnk_format,
 
                    url('changeset_home', repo_name=repo_name,
 
                        revision=changeset.raw_id),
 
                    style=get_color_string(changeset.raw_id),
 
                    class_='tooltip',
 
                    title=tooltip_html
 
                  )
 

	
 
            uri += '\n'
 
            return uri
 
        return _url_func
 

	
 
    return literal(annotate_highlight(filenode, url_func(repo_name), **kwargs))
 

	
 
def get_changeset_safe(repo, rev):
 
    from vcs.backends.base import BaseRepository
 
    from vcs.exceptions import RepositoryError
 
    if not isinstance(repo, BaseRepository):
 
        raise Exception('You must pass an Repository '
 
                        'object as first argument got %s', type(repo))
 

	
 
    try:
 
        cs = repo.get_changeset(rev)
 
    except RepositoryError:
 
        from rhodecode.lib.utils import EmptyChangeset
 
        cs = EmptyChangeset()
 
    return cs
 

	
 

	
 
def is_following_repo(repo_name, user_id):
 
    from rhodecode.model.scm import ScmModel
 
    return ScmModel().is_following_repo(repo_name, user_id)
 

	
 
flash = _Flash()
 

	
 

	
 
#==============================================================================
 
# MERCURIAL FILTERS available via h.
 
#==============================================================================
 
from mercurial import util
 
from mercurial.templatefilters import person as _person
 

	
 
def _age(curdate):
 
    """turns a datetime into an age string."""
 

	
 
    if not curdate:
 
        return ''
 
from rhodecode.lib import credentials_hidder, age as _age
 

	
 
    agescales = [("year", 3600 * 24 * 365),
 
                 ("month", 3600 * 24 * 30),
 
                 ("day", 3600 * 24),
 
                 ("hour", 3600),
 
                 ("minute", 60),
 
                 ("second", 1), ]
 

	
 
    age = datetime.now() - curdate
 
    age_seconds = (age.days * agescales[2][1]) + age.seconds
 
    pos = 1
 
    for scale in agescales:
 
        if scale[1] <= age_seconds:
 
            if pos == 6:pos = 5
 
            return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
 
        pos += 1
 

	
 
    return _('just now')
 

	
 
age = lambda  x:_age(x)
 
capitalize = lambda x: x.capitalize()
 
email = util.email
 
email_or_none = lambda x: util.email(x) if util.email(x) != x else None
 
person = lambda x: _person(x)
 
short_id = lambda x: x[:12]
 

	
 
hide_credentials = lambda x: ''.join(credentials_hidder(x))
 

	
 
def bool2icon(value):
 
    """Returns True/False values represented as small html image of true/false
 
    icons
 

	
 
    :param value: bool value
 
    """
 

	
 
    if value is True:
 
        return HTML.tag('img', src=url("/images/icons/accept.png"),
 
                        alt=_('True'))
 

	
 
    if value is False:
 
        return HTML.tag('img', src=url("/images/icons/cancel.png"),
 
                        alt=_('False'))
 

	
 
    return value
 

	
 

	
 
def action_parser(user_log, feed=False):
 
    """This helper will action_map the specified string action into translated
 
    fancy names with icons and links
 

	
 
    :param user_log: user log instance
 
    :param feed: use output for feeds (no html and fancy icons)
 
    """
 

	
 
    action = user_log.action
 
    action_params = ' '
 

	
 
    x = action.split(':')
 

	
 
    if len(x) > 1:
 
        action, action_params = x
 

	
 
    def get_cs_links():
 
        revs_limit = 5 #display this amount always
 
        revs_top_limit = 50 #show upto this amount of changesets hidden
 
        revs = action_params.split(',')
 
        repo_name = user_log.repository.repo_name
 

	
 
        from rhodecode.model.scm import ScmModel
 
        repo, dbrepo = ScmModel().get(repo_name, retval='repo',
 
                                      invalidation_list=[])
 

	
 
        message = lambda rev: get_changeset_safe(repo, rev).message
 

	
 
        cs_links = " " + ', '.join ([link_to(rev,
 
                url('changeset_home',
 
                repo_name=repo_name,
 
                revision=rev), title=tooltip(message(rev)),
 
                class_='tooltip') for rev in revs[:revs_limit] ])
 

	
 
        compare_view = (' <div class="compare_view tooltip" title="%s">'
 
                        '<a href="%s">%s</a> '
 
                        '</div>' % (_('Show all combined changesets %s->%s' \
 
                                      % (revs[0], revs[-1])),
 
                                    url('changeset_home', repo_name=repo_name,
 
                                        revision='%s...%s' % (revs[0], revs[-1])
 
                                    ),
 
                                    _('compare view'))
 
                        )
 

	
 
        if len(revs) > revs_limit:
 
            uniq_id = revs[0]
 
            html_tmpl = ('<span> %s '
 
            '<a class="show_more" id="_%s" href="#more">%s</a> '
 
            '%s</span>')
 
            if not feed:
 
                cs_links += html_tmpl % (_('and'), uniq_id, _('%s more') \
 
                                        % (len(revs) - revs_limit),
 
                                        _('revisions'))
 

	
 
            if not feed:
 
                html_tmpl = '<span id="%s" style="display:none"> %s </span>'
 
            else:
 
                html_tmpl = '<span id="%s"> %s </span>'
 

	
 
            cs_links += html_tmpl % (uniq_id, ', '.join([link_to(rev,
 
                url('changeset_home',
 
                repo_name=repo_name, revision=rev),
 
                title=message(rev), class_='tooltip')
 
                for rev in revs[revs_limit:revs_top_limit]]))
 
        if len(revs) > 1:
 
            cs_links += compare_view
 
        return cs_links
 

	
 
    def get_fork_name():
 
        repo_name = action_params
 
        return _('fork name ') + str(link_to(action_params, url('summary_home',
 
                                          repo_name=repo_name,)))
 

	
 
    action_map = {'user_deleted_repo':(_('[deleted] repository'), None),
 
           'user_created_repo':(_('[created] repository'), None),
 
           'user_forked_repo':(_('[forked] repository'), get_fork_name),
 
           'user_updated_repo':(_('[updated] repository'), None),
 
           'admin_deleted_repo':(_('[delete] repository'), None),
 
           'admin_created_repo':(_('[created] repository'), None),
 
           'admin_forked_repo':(_('[forked] repository'), None),
 
           'admin_updated_repo':(_('[updated] repository'), None),
 
           'push':(_('[pushed] into'), get_cs_links),
 
           'push_local':(_('[committed via RhodeCode] into'), get_cs_links),
 
           'push_remote':(_('[pulled from remote] into'), get_cs_links),
 
           'pull':(_('[pulled] from'), None),
 
           'started_following_repo':(_('[started following] repository'), None),
 
           'stopped_following_repo':(_('[stopped following] repository'), None),
 
            }
 

	
 
    action_str = action_map.get(action, action)
 
    if feed:
 
        action = action_str[0].replace('[', '').replace(']', '')
 
    else:
 
        action = action_str[0].replace('[', '<span class="journal_highlight">')\
 
                   .replace(']', '</span>')
 

	
 
    action_params_func = lambda :""
 

	
 
    if callable(action_str[1]):
 
        action_params_func = action_str[1]
 

	
 
    return [literal(action), action_params_func]
 

	
 
def action_parser_icon(user_log):
 
    action = user_log.action
 
    action_params = None
 
    x = action.split(':')
 

	
 
    if len(x) > 1:
 
        action, action_params = x
 

	
 
    tmpl = """<img src="%s%s" alt="%s"/>"""
 
    map = {'user_deleted_repo':'database_delete.png',
 
           'user_created_repo':'database_add.png',
 
           'user_forked_repo':'arrow_divide.png',
 
           'user_updated_repo':'database_edit.png',
 
           'admin_deleted_repo':'database_delete.png',
 
           'admin_created_repo':'database_add.png',
 
           'admin_forked_repo':'arrow_divide.png',
 
           'admin_updated_repo':'database_edit.png',
 
           'push':'script_add.png',
 
           'push_local':'script_edit.png',
 
           'push_remote':'connect.png',
 
           'pull':'down_16.png',
 
           'started_following_repo':'heart_add.png',
 
           'stopped_following_repo':'heart_delete.png',
 
            }
 
    return literal(tmpl % ((url('/images/icons/')),
 
                           map.get(action, action), action))
 

	
 

	
 
#==============================================================================
 
# PERMS
 
#==============================================================================
 
from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
 
HasRepoPermissionAny, HasRepoPermissionAll
 

	
 
#==============================================================================
 
# GRAVATAR URL
 
#==============================================================================
 

	
 
def gravatar_url(email_address, size=30):
 
    if not str2bool(config['app_conf'].get('use_gravatar')) or \
 
        email_address == 'anonymous@rhodecode.org':
 
        return "/images/user%s.png" % size
 

	
 
    ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
 
    default = 'identicon'
 
    baseurl_nossl = "http://www.gravatar.com/avatar/"
 
    baseurl_ssl = "https://secure.gravatar.com/avatar/"
 
    baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
 

	
 
    if isinstance(email_address, unicode):
 
        #hashlib crashes on unicode items
 
        email_address = email_address.encode('utf8', 'replace')
 
    # construct the url
 
    gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
 
    gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
 

	
 
    return gravatar_url
 

	
 

	
 
#==============================================================================
 
# REPO PAGER
 
# REPO PAGER, PAGER FOR REPOSITORY
 
#==============================================================================
 
class RepoPage(Page):
 

	
 
    def __init__(self, collection, page=1, items_per_page=20,
 
        item_count=None, url=None, branch_name=None, **kwargs):
 

	
 
        """Create a "RepoPage" instance. special pager for paging
 
        repository
 
        """
 
        self._url_generator = url
 

	
 
        # Safe the kwargs class-wide so they can be used in the pager() method
 
        self.kwargs = kwargs
 

	
 
        # Save a reference to the collection
 
        self.original_collection = collection
 

	
 
        self.collection = collection
 

	
 
        # The self.page is the number of the current page.
 
        # The first page has the number 1!
 
        try:
 
            self.page = int(page) # make it int() if we get it as a string
 
        except (ValueError, TypeError):
 
            self.page = 1
 

	
 
        self.items_per_page = items_per_page
 

	
 
        # Unless the user tells us how many items the collections has
 
        # we calculate that ourselves.
 
        if item_count is not None:
 
            self.item_count = item_count
 
        else:
 
            self.item_count = len(self.collection)
 

	
 
        # Compute the number of the first and last available page
 
        if self.item_count > 0:
 
            self.first_page = 1
 
            self.page_count = ((self.item_count - 1) / self.items_per_page) + 1
 
            self.last_page = self.first_page + self.page_count - 1
 

	
 
            # Make sure that the requested page number is the range of valid pages
 
            if self.page > self.last_page:
 
                self.page = self.last_page
 
            elif self.page < self.first_page:
 
                self.page = self.first_page
 

	
 
            # Note: the number of items on this page can be less than
 
            #       items_per_page if the last page is not full
 
            self.first_item = max(0, (self.item_count) - (self.page * items_per_page))
 
            self.last_item = ((self.item_count - 1) - items_per_page * (self.page - 1))
 

	
 
            iterator = self.collection.get_changesets(start=self.first_item,
 
                                                      end=self.last_item,
 
                                                      reverse=True,
 
                                                      branch_name=branch_name)
 
            self.items = list(iterator)
 

	
 
            # Links to previous and next page
 
            if self.page > self.first_page:
 
                self.previous_page = self.page - 1
 
            else:
 
                self.previous_page = None
 

	
 
            if self.page < self.last_page:
 
                self.next_page = self.page + 1
 
            else:
 
                self.next_page = None
 

	
 
        # No items available
 
        else:
 
            self.first_page = None
 
            self.page_count = 0
 
            self.last_page = None
 
            self.first_item = None
 
            self.last_item = None
 
            self.previous_page = None
 
            self.next_page = None
 
            self.items = []
 

	
 
        # This is a subclass of the 'list' type. Initialise the list now.
 
        list.__init__(self, self.items)
 

	
 

	
 
def changed_tooltip(nodes):
 
    """
 
    Generates a html string for changed nodes in changeset page.
 
    It limits the output to 30 entries
 
    
 
    :param nodes: LazyNodesGenerator
 
    """
 
    if nodes:
 
        pref = ': <br/> '
 
        suf = ''
 
        if len(nodes) > 30:
 
            suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
 
        return literal(pref + '<br/> '.join([safe_unicode(x.path)
 
                                             for x in nodes[:30]]) + suf)
 
    else:
 
        return ': ' + _('No Files')
 

	
 

	
 

	
 
def repo_link(groups_and_repos):
 
    """
 
    Makes a breadcrumbs link to repo within a group
 
    joins &raquo; on each group to create a fancy link
 
    
 
    ex::
 
        group >> subgroup >> repo
 
    
 
    :param groups_and_repos:
 
    """
 
    groups, repo_name = groups_and_repos
 

	
 
    if not groups:
 
        return repo_name
 
    else:
 
        def make_link(group):
 
            return link_to(group.group_name, url('repos_group',
 
                                                 id=group.group_id))
 
        return literal(' &raquo; '.join(map(make_link, groups)) + \
 
                       " &raquo; " + repo_name)
 

	
 

	
 
def fancy_file_stats(stats):
 
    """
 
    Displays a fancy two colored bar for number of added/deleted
 
    lines of code on file
 
    
 
    :param stats: two element list of added/deleted lines of code
 
    """
 

	
 
    a, d, t = stats[0], stats[1], stats[0] + stats[1]
 
    width = 100
 
    unit = float(width) / (t or 1)
 

	
 
    a_p = max(9, unit * a) if a > 0 else 0# needs > 9% to be visible
 
    d_p = max(9, unit * d) if d > 0 else 0 # needs > 9% to be visible
 
    # needs > 9% of width to be visible or 0 to be hidden
 
    a_p = max(9, unit * a) if a > 0 else 0
 
    d_p = max(9, unit * d) if d > 0 else 0
 
    p_sum = a_p + d_p
 

	
 
    if p_sum > width:
 
        #adjust the percentage to be == 100% since we adjusted to 9
 
        if a_p > d_p:
 
            a_p = a_p - (p_sum - width)
 
        else:
 
            d_p = d_p - (p_sum - width)
 

	
 
    a_v = a if a > 0 else ''
 
    d_v = d if d > 0 else ''
 

	
 

	
 
    def cgen(l_type):
 
        mapping = {'tr':'top-right-rounded-corner',
 
                   'tl':'top-left-rounded-corner',
 
                   'br':'bottom-right-rounded-corner',
 
                   'bl':'bottom-left-rounded-corner'}
 
        map_getter = lambda x:mapping[x]
 

	
 
        if l_type == 'a' and d_v:
 
            #case when added and deleted are present
 
            return ' '.join(map(map_getter, ['tl', 'bl']))
 

	
 
        if l_type == 'a' and not d_v:
 
            return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
 

	
 
        if l_type == 'd' and a_v:
 
            return ' '.join(map(map_getter, ['tr', 'br']))
 

	
 
        if l_type == 'd' and not a_v:
 
            return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
 

	
 

	
 

	
 
    d_a = '<div class="added %s" style="width:%s%%">%s</div>' % (cgen('a'),
 
                                                                 a_p, a_v)
 
    d_d = '<div class="deleted %s" style="width:%s%%">%s</div>' % (cgen('d'),
 
                                                                   d_p, d_v)
 
    return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
rhodecode/templates/summary/summary.html
Show inline comments
 
<%inherit file="/base/base.html"/>
 

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

	
 
<%def name="breadcrumbs_links()">
 
    ${h.link_to(u'Home',h.url('/'))}
 
    &raquo; 
 
    ${h.link_to(c.dbrepo.just_name,h.url('summary_home',repo_name=c.repo_name))}
 
    &raquo;
 
    ${_('summary')}
 
</%def>
 

	
 
<%def name="page_nav()">
 
	${self.menu('summary')}    
 
</%def>
 

	
 
<%def name="main()">
 
<div class="box box-left">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
    </div>
 
    <!-- end box / title -->
 
	<div class="form">
 
	  <div id="summary" class="fields">
 
		 
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Name')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
                  %if c.rhodecode_user.username != 'default':
 
                      %if c.following:
 
                      <span id="follow_toggle" class="following" title="${_('Stop following this repository')}"
 
                            onclick="javascript:toggleFollowingRepo(this,${c.dbrepo.repo_id},'${str(h.get_token())}')">
 
                      </span>                 
 
                      %else:
 
                      <span id="follow_toggle" class="follow" title="${_('Start following this repository')}"
 
                            onclick="javascript:toggleFollowingRepo(this,${c.dbrepo.repo_id},'${str(h.get_token())}')">
 
                      </span>
 
                      %endif
 
                  %endif:			  
 
                 
 
                 ##REPO TYPE
 
		         %if c.dbrepo.repo_type =='hg':
 
		           <img style="margin-bottom:2px" class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
 
		         %endif
 
		         %if c.dbrepo.repo_type =='git':
 
		           <img style="margin-bottom:2px" class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
 
		         %endif 
 
                            
 
                 ##PUBLIC/PRIVATE     			  
 
	             %if c.dbrepo.private:
 
	                <img style="margin-bottom:2px" class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url("/images/icons/lock.png")}"/>
 
	             %else:
 
	                <img style="margin-bottom:2px" class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url("/images/icons/lock_open.png")}"/>
 
	             %endif
 
	             
 
	              ##REPO NAME
 
			      <span class="repo_name">${h.repo_link(c.dbrepo.groups_and_repo)}</span>
 
                  
 
                  ##FORK
 
		          %if c.dbrepo.fork:
 
	            	<div style="margin-top:5px;clear:both"">
 
	            	<a href="${h.url('summary_home',repo_name=c.dbrepo.fork.repo_name)}">
 
	            	<img class="icon" alt="${_('public')}"
 
	            	title="${_('Fork of')} ${c.dbrepo.fork.repo_name}" 
 
	            	src="${h.url("/images/icons/arrow_divide.png")}"/>
 
	            	${_('Fork of')} ${c.dbrepo.fork.repo_name}
 
	            	</a>
 
	            	</div>
 
		          %endif
 
		          ##REMOTE
 
				  %if c.dbrepo.clone_uri:
 
                    <div style="margin-top:5px;clear:both">
 
                    <a href="${h.url(str(c.dbrepo.clone_uri))}">
 
                    <a href="${h.url(str(h.hide_credentials(c.dbrepo.clone_uri)))}">
 
                    <img class="icon" alt="${_('remote clone')}"
 
                    title="${_('Clone from')} ${c.dbrepo.clone_uri}" 
 
                    title="${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}" 
 
                    src="${h.url("/images/icons/connect.png")}"/>
 
                    ${_('Clone from')} ${c.dbrepo.clone_uri}
 
                    ${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}
 
                    </a>
 
                    </div>					
 
				  %endif		            		      
 
			  </div>
 
			 </div>
 
			
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Description')}:</label>
 
			  </div>
 
			  <div class="input-short desc">${c.dbrepo.description}</div>
 
			 </div>
 
			
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Contact')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			  	<div class="gravatar">
 
			  		<img alt="gravatar" src="${h.gravatar_url(c.dbrepo.user.email)}"/>
 
			  	</div>
 
			  		${_('Username')}: ${c.dbrepo.user.username}<br/>
 
			  		${_('Name')}: ${c.dbrepo.user.name} ${c.dbrepo.user.lastname}<br/>
 
			  		${_('Email')}: <a href="mailto:${c.dbrepo.user.email}">${c.dbrepo.user.email}</a>
 
			  </div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Last change')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
                  <b>${'r%s:%s' % (h.get_changeset_safe(c.rhodecode_repo,'tip').revision,
 
                            h.get_changeset_safe(c.rhodecode_repo,'tip').short_id)}</b> - 
 
			      <span class="tooltip" title="${c.rhodecode_repo.last_change}">
 
			      ${h.age(c.rhodecode_repo.last_change)}</span><br/>
 
			      ${_('by')} ${h.get_changeset_safe(c.rhodecode_repo,'tip').author} 
 
			      
 
			  </div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Clone url')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			      <input type="text" id="clone_url" readonly="readonly" value="${c.rhodecode_repo.alias} clone ${c.clone_repo_url}" size="70"/>
 
			  </div>
 
			 </div>
 
			 
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Trending source files')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			    <div id="lang_stats"></div> 			   
 
			  </div>
 
			 </div>
 
			 			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Download')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
		        %if len(c.rhodecode_repo.revisions) == 0:
 
		          ${_('There are no downloads yet')}
 
		        %elif c.enable_downloads is False:
 
		          ${_('Downloads are disabled for this repository')}
 
                    %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
 
                        [${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name))}]
 
                    %endif  		          
 
		        %else:
 
			        ${h.select('download_options',c.rhodecode_repo.get_changeset().raw_id,c.download_options)}
 
			        %for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
 
			             %if cnt >=1:
 
			             |
 
			             %endif
 
			             <span class="tooltip" title="${_('Download %s as %s') %('tip',archive['type'])}" 
 
			                  id="${archive['type']+'_link'}">${h.link_to(archive['type'],
 
			                h.url('files_archive_home',repo_name=c.dbrepo.repo_name,
 
			                fname='tip'+archive['extension']),class_="archive_icon")}</span>
 
			        %endfor
 
			    %endif
 
			  </div>
 
			 </div>
 
			 
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Feeds')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			   %if c.rhodecode_user.username != 'default':
 
	            ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key),class_='rss_icon')}
 
	            ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key),class_='atom_icon')}
0 comments (0 inline, 0 general)