Blame pagure/ui/filters.py

Pierre-Yves Chibon 15e568
# -*- coding: utf-8 -*-
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
"""
Pierre-Yves Chibon b7c63b
 (c) 2014-2018 - Copyright Red Hat Inc
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
 Authors:
Pierre-Yves Chibon 15e568
   Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
"""
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 22a554
# pylint: disable=too-many-branches
Pierre-Yves Chibon 22a554
# pylint: disable=too-many-arguments
Pierre-Yves Chibon 22a554
# pylint: disable=too-many-locals
Pierre-Yves Chibon 11d3da
Pierre-Yves Chibon 11d3da
Aurélien Bompard dcf6f6
from __future__ import unicode_literals
Aurélien Bompard dcf6f6
Pierre-Yves Chibon 15e568
import textwrap
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
import arrow
Pierre-Yves Chibon 267b16
import flask
Jeremy Cline 00ab23
import six
Pierre-Yves Chibon 15e568
Aurélien Bompard 831553
from six.moves.urllib.parse import urlparse, parse_qsl
Michael Scherer 773db5
from jinja2 import escape
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon fe5017
import pagure.exceptions
Pierre-Yves Chibon 930073
import pagure.lib.query
Pierre-Yves Chibon fe5017
import pagure.forms
Pierre-Yves Chibon b130e5
from pagure.config import config as pagure_config
Pierre-Yves Chibon b130e5
from pagure.ui import UI_NS
Aurélien Bompard 619e2a
from pagure.utils import authenticated, is_repo_committer, is_true
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
# Jinja filters
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("hasattr")
Pierre-Yves Chibon 01d17b
def jinja_hasattr(obj, string):
Pierre-Yves Chibon 01d17b
    """ Template filter checking if the provided object at the provided
Pierre-Yves Chibon 01d17b
    string as attribute
Pierre-Yves Chibon 01d17b
    """
Pierre-Yves Chibon 01d17b
    return hasattr(obj, string)
Pierre-Yves Chibon 01d17b
Pierre-Yves Chibon 01d17b
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("render")
Pierre-Yves Chibon ccc810
def jinja_render(tmpl, **kwargs):
Pierre-Yves Chibon 20f04d
    """ Render the given template with the provided arguments
Pierre-Yves Chibon ccc810
    """
Pierre-Yves Chibon ccc810
    return flask.render_template_string(tmpl, **kwargs)
Pierre-Yves Chibon ccc810
Pierre-Yves Chibon ccc810
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("humanize")
Pierre-Yves Chibon 15e568
def humanize_date(date):
Pierre-Yves Chibon 15e568
    """ Template filter returning the last commit date of the provided repo.
Pierre-Yves Chibon 15e568
    """
Pierre-Yves Chibon 623caa
    if date:
Pierre-Yves Chibon 623caa
        return arrow.get(date).humanize()
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("format_ts")
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("format_datetime")
Pierre-Yves Chibon 15e568
def format_ts(string):
Adam Williamson 6205ad
    """ Template filter transforming a timestamp, datetime or anything
Adam Williamson 6205ad
    else arrow.get() can handle to a human-readable date
Pierre-Yves Chibon 15e568
    """
Adam Williamson 6205ad
    # We *could* enhance this by allowing users to specify preferred
Adam Williamson 6205ad
    # timezone, localized time format etc. and customizing this display
Adam Williamson 6205ad
    # to user's preferences. But we don't have that, so for now, we
Adam Williamson 6205ad
    # always use UTC timezone, and we don't use localized forms like
Adam Williamson 6205ad
    # %b or %d because they will be 'localized' for the *server*.
Adam Williamson 6205ad
    # This format should be pretty 'locale-neutral'.
Adam Williamson 6205ad
    arr = arrow.get(string)
Pierre-Yves Chibon 9c2953
    return arr.strftime("%Y-%m-%d %H:%M:%S %Z")
Pierre-Yves Chibon 9c2953
Pierre-Yves Chibon 9c2953
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("format_loc")
Pierre-Yves Chibon 9c2953
def format_loc(
Pierre-Yves Chibon 9c2953
    loc,
Pierre-Yves Chibon 9c2953
    commit=None,
Pierre-Yves Chibon 9c2953
    filename=None,
Pierre-Yves Chibon 9c2953
    tree_id=None,
Pierre-Yves Chibon 9c2953
    prequest=None,
Pierre-Yves Chibon 9c2953
    index=None,
Pierre-Yves Chibon 9c2953
    isprdiff=False,
Pierre-Yves Chibon 9c2953
):
Pierre-Yves Chibon 15e568
    """ Template filter putting the provided lines of code into a table
Pierre-Yves Chibon 15e568
    """
Pierre-Yves Chibon 15e568
    if loc is None:
Pierre-Yves Chibon 15e568
        return
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 9c2953
    output = ['
', '']
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
    comments = {}
Pierre-Yves Chibon 15e568
    if prequest and not isinstance(prequest, flask.wrappers.Request):
Pierre-Yves Chibon 15e568
        for com in prequest.comments:
Pierre-Yves Chibon 9c2953
            if (
Pierre-Yves Chibon 9c2953
                commit
Pierre-Yves Chibon 9c2953
                and com.commit_id == commit.hex
Pierre-Yves Chibon 9c2953
                and com.filename == filename
Pierre-Yves Chibon 9c2953
            ):
Pierre-Yves Chibon 15e568
                if com.line in comments:
Pierre-Yves Chibon 15e568
                    comments[com.line].append(com)
Pierre-Yves Chibon 15e568
                else:
Pierre-Yves Chibon 15e568
                    comments[com.line] = [com]
Pierre-Yves Chibon 15e568
    for key in comments:
Pierre-Yves Chibon 9c2953
        comments[key] = sorted(comments[key], key=lambda obj: obj.date_created)
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
    if not index:
Pierre-Yves Chibon 9c2953
        index = ""
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
    cnt = 1
Pierre-Yves Chibon 9c2953
    for line in loc.split("\n"):
Pierre-Yves Chibon 15e568
        if filename and commit:
Aurélien Bompard 831553
            if isinstance(filename, str) and six.PY2:
Pierre-Yves Chibon 9c2953
                filename = filename.decode("UTF-8")
Pierre-Yves Chibon 9c2953
Pierre-Yves Chibon 9c2953
            if isprdiff and (
Pierre-Yves Chibon 9c2953
                line.startswith("@@")
Pierre-Yves Chibon 9c2953
                or line.startswith("+")
Pierre-Yves Chibon 9c2953
                or line.startswith("-")
Pierre-Yves Chibon 9c2953
            ):
Pierre-Yves Chibon 9c2953
                if line.startswith("@@"):
Ryan Lerch 19dc17
                    output.append(
Ryan Lerch 19dc17
                        '
Ryan Lerch 19dc17
                    id="c-%(commit)s-%(cnt_lbl)s">'
Pierre-Yves Chibon 9c2953
                        % ({"cnt_lbl": cnt, "commit": commit})
Pierre-Yves Chibon 9c2953
                    )
Pierre-Yves Chibon 9c2953
                elif line.startswith("+"):
Ryan Lerch 19dc17
                    output.append(
Ryan Lerch 19dc17
                        '
Ryan Lerch 19dc17
                    id="c-%(commit)s-%(cnt_lbl)s">'
Pierre-Yves Chibon 9c2953
                        % ({"cnt_lbl": cnt, "commit": commit})
Pierre-Yves Chibon 9c2953
                    )
Pierre-Yves Chibon 9c2953
                elif line.startswith("-"):
Ryan Lerch 19dc17
                    output.append(
Ryan Lerch 19dc17
                        '
Ryan Lerch 19dc17
                    id="c-%(commit)s-%(cnt_lbl)s">'
Pierre-Yves Chibon 9c2953
                        % ({"cnt_lbl": cnt, "commit": commit})
Pierre-Yves Chibon 9c2953
                    )
Ryan Lerch 19dc17
            else:
Ryan Lerch 19dc17
                output.append(
Ryan Lerch 19dc17
                    ''
Pierre-Yves Chibon 9c2953
                    % ({"cnt_lbl": cnt, "commit": commit})
Pierre-Yves Chibon 9c2953
                )
Ryan Lerch 19dc17
Pierre-Yves Chibon 15e568
            output.append(
Ryan Lerch 19dc17
                ''
Pierre-Yves Chibon 11d3da
                '
Pierre-Yves Chibon 11d3da
                '"%(cnt_lbl)s">'
Ryan Lerch 19dc17
                '
Pierre-Yves Chibon c72242
                ' data-filename="%(filename)s" data-commit="%(commit)s"'
Pierre-Yves Chibon c2e1f7
                ' data-tree="%(tree_id)s">'
Pierre-Yves Chibon 9c2953
                "

"

Ryan Lerch 2aa95c
                '
Pierre-Yves Chibon 11d3da
                'alt="Add comment" title="Add comment">'
Pierre-Yves Chibon 9c2953
                "

"
Pierre-Yves Chibon 9c2953
                ""
Pierre-Yves Chibon 9c2953
                % (
Pierre-Yves Chibon 15e568
                    {
Pierre-Yves Chibon 9c2953
                        "cnt": "%s_%s" % (index, cnt),
Pierre-Yves Chibon 9c2953
                        "cnt_lbl": cnt,
Pierre-Yves Chibon 9c2953
                        "filename": filename,
Pierre-Yves Chibon 9c2953
                        "commit": commit,
Pierre-Yves Chibon 9c2953
                        "tree_id": tree_id,
Pierre-Yves Chibon 15e568
                    }
Pierre-Yves Chibon 15e568
                )
Pierre-Yves Chibon 15e568
            )
Pierre-Yves Chibon 15e568
        else:
Pierre-Yves Chibon 15e568
            output.append(
Pierre-Yves Chibon 15e568
                ''
Pierre-Yves Chibon 11d3da
                '
Pierre-Yves Chibon 11d3da
                '"%(cnt_lbl)s">'
Pierre-Yves Chibon 9c2953
                % ({"cnt": "%s_%s" % (index, cnt), "cnt_lbl": cnt})
Pierre-Yves Chibon 15e568
            )
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
        cnt += 1
Pierre-Yves Chibon 15e568
        if not line:
Pierre-Yves Chibon 15e568
            output.append(line)
Pierre-Yves Chibon 15e568
            continue
Pierre-Yves Chibon 9c2953
        if line.startswith("@@"):
Pierre-Yves Chibon bb2305
            if prequest and prequest.project_from:
Pierre-Yves Chibon 9c2953
                rangeline = (
Pierre-Yves Chibon 9c2953
                    line.partition("@@ ")[2]
Pierre-Yves Chibon 9c2953
                    if line.partition("@@ ")[1] == "@@ "
Pierre-Yves Chibon 9c2953
                    else None
Pierre-Yves Chibon 9c2953
                )
Pradeep CE (cep) 208647
                if rangeline:
Pierre-Yves Chibon 9c2953
                    rangeline = rangeline.split(" @@")[0]
Pierre-Yves Chibon 9c2953
                    linenumber = rangeline.split("+")[1].split(",")[0]
Pradeep CE (cep) 208647
                    line = line + ' 
Pradeep CE (cep) c90835
                        flask.url_for(
Pierre-Yves Chibon 9c2953
                            "ui_ns.view_file",
Pradeep CE (cep) 208647
                            repo=prequest.project_from.name,
Pradeep CE (cep) 208647
                            username=prequest.project_from.user.username
Pierre-Yves Chibon 9c2953
                            if prequest.project_from.is_fork
Pierre-Yves Chibon 9c2953
                            else None,
Pradeep CE (cep) 208647
                            namespace=prequest.project_from.namespace,
Pradeep CE (cep) 208647
                            identifier=prequest.branch_from,
Pierre-Yves Chibon 9c2953
                            filename=filename,
Pierre-Yves Chibon 9c2953
                        ),
Pierre-Yves Chibon 9c2953
                        linenumber,
Pierre-Yves Chibon 9c2953
                    )
Pierre-Yves Chibon 9c2953
                    line = (
Pierre-Yves Chibon 9c2953
                        line
Pierre-Yves Chibon 9c2953
                        + 'class="open_changed_file_icon_wrap">'
Pierre-Yves Chibon 9c2953
                        + '
Pierre-Yves Chibon 9c2953
                        + 'alt="Open changed file" '
Pierre-Yves Chibon 9c2953
                        + 'title="Open changed file">'
Pierre-Yves Chibon 9c2953
                    )
Pierre-Yves Chibon 9c2953
Pierre-Yves Chibon 9c2953
        if isprdiff and (
Pierre-Yves Chibon 9c2953
            line.startswith("@@")
Pierre-Yves Chibon 9c2953
            or line.startswith("+")
Pierre-Yves Chibon 9c2953
            or line.startswith("-")
Pierre-Yves Chibon 9c2953
        ):
Pierre-Yves Chibon 9c2953
            if line.startswith("@@"):
Ryan Lerch 19dc17
                output.append(
Ryan Lerch 19dc17
                    '\
Ryan Lerch 19dc17
                    
%s
'
Pierre-Yves Chibon 9c2953
                    % line
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 9c2953
            elif line.startswith("+"):
Ryan Lerch 19dc17
                output.append(
Ryan Lerch 19dc17
                    '\
Ryan Lerch 19dc17
                    
%s
'
Ryan Lerch 1fffee
                    % escape(line)
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 9c2953
            elif line.startswith("-"):
Ryan Lerch 19dc17
                output.append(
Ryan Lerch 19dc17
                    '\
Ryan Lerch 19dc17
                    
%s
'
Ryan Lerch 1fffee
                    % escape(line)
Pierre-Yves Chibon 9c2953
                )
Ryan Lerch 19dc17
        else:
Ryan Lerch 19dc17
            output.append(
Ryan Lerch 1fffee
                '
%s
'
Ryan Lerch 1fffee
                % (escape(line))
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
Pierre-Yves Chibon 9c2953
        output.append("")
Pierre-Yves Chibon 9c2953
Pierre-Yves Chibon 9c2953
        tpl_edit = (
Pierre-Yves Chibon 9c2953
            '
Pierre-Yves Chibon 9c2953
            'class="btn btn-outline-primary border-0" '
Pierre-Yves Chibon 9c2953
            'data-comment="%(commentid)s" '
Pierre-Yves Chibon 9c2953
            'data-objid="%(requestid)s">'
Pierre-Yves Chibon 9c2953
            ''
Pierre-Yves Chibon 9c2953
            ""
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
        tpl_edited = (
Pierre-Yves Chibon 9c2953
            '<small class="text-muted" title="%(edit_date)s"> '</small>
Pierre-Yves Chibon 9c2953
            "Edited %(human_edit_date)s by %(user)s "
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
Pierre-Yves Chibon 9c2953
        tpl_delete = (
Pierre-Yves Chibon 9c2953
            '
Pierre-Yves Chibon 9c2953
            'title="Remove comment" '
Pierre-Yves Chibon 9c2953
            'name="drop_comment" value="%(commentid)s" type="submit" '
Pierre-Yves Chibon 9c2953
            "onclick=\"return confirm('Do you really want to remove this"
Pierre-Yves Chibon 9c2953
            ' comment?\');" >'
Pierre-Yves Chibon 9c2953
            ""
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon cbbc7b
Pierre-Yves Chibon 15e568
        if cnt - 1 in comments:
Pierre-Yves Chibon 15e568
            for comment in comments[cnt - 1]:
Pierre-Yves Chibon cbbc7b
Pierre-Yves Chibon 9c2953
                templ_delete = ""
Pierre-Yves Chibon 9c2953
                templ_edit = ""
Pierre-Yves Chibon 9c2953
                templ_edited = ""
Pierre-Yves Chibon b8c7ae
                if authenticated() and (
Pierre-Yves Chibon 9c2953
                    (
Pierre-Yves Chibon 9c2953
                        is_true(comment.parent.status, ["true", "open"])
Pierre-Yves Chibon 9c2953
                        and comment.user.user == flask.g.fas_user.username
Pierre-Yves Chibon 9c2953
                    )
Pierre-Yves Chibon 9c2953
                    or is_repo_committer(comment.parent.project)
Pierre-Yves Chibon 9c2953
                ):
Pierre-Yves Chibon 9c2953
                    templ_delete = tpl_delete % ({"commentid": comment.id})
Pierre-Yves Chibon 9c2953
                    templ_edit = tpl_edit % (
Pierre-Yves Chibon 9c2953
                        {
Pierre-Yves Chibon 9c2953
                            "edit_url": flask.url_for(
Pierre-Yves Chibon 9c2953
                                "ui_ns.pull_request_edit_comment",
Pierre-Yves Chibon 9c2953
                                repo=comment.parent.project.name,
Pierre-Yves Chibon 9c2953
                                requestid=comment.parent.id,
Pierre-Yves Chibon 9c2953
                                commentid=comment.id,
Pierre-Yves Chibon 9c2953
                                username=comment.parent.user.user
Pierre-Yves Chibon 9c2953
                                if comment.parent.project.is_fork
Pierre-Yves Chibon 9c2953
                                else None,
Pierre-Yves Chibon 9c2953
                            ),
Pierre-Yves Chibon 9c2953
                            "requestid": comment.parent.id,
Pierre-Yves Chibon 9c2953
                            "commentid": comment.id,
Pierre-Yves Chibon 9c2953
                        }
Pierre-Yves Chibon 9c2953
                    )
Pierre-Yves Chibon cbbc7b
Pierre-Yves Chibon 91f4c6
                if comment.edited_on:
Pierre-Yves Chibon 9c2953
                    templ_edited = tpl_edited % (
Pierre-Yves Chibon 9c2953
                        {
Pierre-Yves Chibon 9c2953
                            "edit_date": format_ts(comment.edited_on),
Pierre-Yves Chibon 9c2953
                            "human_edit_date": humanize_date(
Pierre-Yves Chibon 9c2953
                                comment.edited_on
Pierre-Yves Chibon 9c2953
                            ),
Pierre-Yves Chibon 9c2953
                            "user": comment.editor.user,
Pierre-Yves Chibon 9c2953
                        }
Pierre-Yves Chibon 9c2953
                    )
Pierre-Yves Chibon 91f4c6
Pierre-Yves Chibon 15e568
                output.append(
Ryan Lerch 1fa495
                    ''
Ryan Lerch 19dc17
                    ''
Ryan Lerch 19dc17
                    '
'
Ryan Lerch 1fa495
                    '
Ryan Lerch 1fa495
                    'align-items-center px-3 py-2">'
Pierre-Yves Chibon 9c2953
                    "
"
Ryan Lerch 1fa495
                    '
'
Pierre-Yves Chibon bc4f2b
                    ''
Pierre-Yves Chibon 71f685
                    ''
Pierre-Yves Chibon 9c2953
                    "%(user)s commented "
Ryan Lerch 79145c
                    '
Pierre-Yves Chibon c7f2f6
                    'to this headline" href="#comment-%(commentid)s">'
Pierre-Yves Chibon bc4f2b
                    '%(human_date)s'
Pierre-Yves Chibon 9c2953
                    ""
Pierre-Yves Chibon 9c2953
                    ""
Ryan Lerch 19dc17
                    '
'
Pierre-Yves Chibon 9c2953
                    "%(templ_edit)s"
Pierre-Yves Chibon 9c2953
                    "%(templ_delete)s"
Pierre-Yves Chibon 9c2953
                    ""
Pierre-Yves Chibon 9c2953
                    ""
Ryan Lerch 1fa495
                    '
'
Pierre-Yves Chibon 9c2953
                    "<small></small>"
Pierre-Yves Chibon bc4f2b
                    '<section class="issue_comment">'</section>
Pierre-Yves Chibon bc4f2b
                    '
'
Pierre-Yves Chibon 9c2953
                    "%(comment)s"
Pierre-Yves Chibon 9c2953
                    ""
Pierre-Yves Chibon 9c2953
                    ""
Pierre-Yves Chibon 9c2953
                    ""
Pierre-Yves Chibon 9c2953
                    ""
Pierre-Yves Chibon 9c2953
                    % (
Pierre-Yves Chibon 15e568
                        {
Pierre-Yves Chibon 9c2953
                            "url": flask.url_for(
Pierre-Yves Chibon 9c2953
                                "ui_ns.view_user", username=comment.user.user
Pierre-Yves Chibon 9c2953
                            ),
Pierre-Yves Chibon 9c2953
                            "templ_delete": templ_delete,
Pierre-Yves Chibon 9c2953
                            "templ_edit": templ_edit,
Pierre-Yves Chibon 9c2953
                            "templ_edited": templ_edited,
Pierre-Yves Chibon 9c2953
                            "user": comment.user.user,
Pierre-Yves Chibon 9c2953
                            "user_html": comment.user.html_title,
Pierre-Yves Chibon 9c2953
                            "avatar_url": avatar_url(
Pierre-Yves Chibon 9c2953
                                comment.user.default_email, 16
Pierre-Yves Chibon 9c2953
                            ),
Pierre-Yves Chibon 9c2953
                            "date": format_ts(comment.date_created),
Pierre-Yves Chibon 9c2953
                            "human_date": humanize_date(comment.date_created),
Pierre-Yves Chibon 9c2953
                            "comment": markdown_filter(comment.comment),
Pierre-Yves Chibon 9c2953
                            "commentid": comment.id,
Pierre-Yves Chibon 15e568
                        }
Pierre-Yves Chibon 15e568
                    )
Pierre-Yves Chibon 15e568
                )
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 9c2953
    output.append("")
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 9c2953
    return "\n".join(output)
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("blame_loc")
Pierre-Yves Chibon 833d1f
def blame_loc(loc, repo, username, blame):
Pierre-Yves Chibon 833d1f
    """ Template filter putting the provided lines of code into a table
Pierre-Yves Chibon 17526c
Pierre-Yves Chibon 17526c
Pierre-Yves Chibon 17526c
    This method blame lines of code (loc) takes as input a text (lines of
Pierre-Yves Chibon 17526c
    code) concerning a given repo, with its repo and a pygit2.Blame object
Pierre-Yves Chibon 17526c
    and convert it into a html table displayed to the user with the git
Pierre-Yves Chibon 17526c
    blame information (user, commit, commit date).
Pierre-Yves Chibon 17526c
Jeremy Cline 00ab23
    :arg loc: a unicode object of the lines of code to display (in this case,
Pierre-Yves Chibon 17526c
        most likely the content of a file).
Pierre-Yves Chibon 17526c
    :arg repo: the name of the repo in which this file is.
Pierre-Yves Chibon 17526c
    :arg username: the user name of the user whose repo this is, if the repo
Pierre-Yves Chibon 17526c
        is not a *fork*, this value is ``None``.
Pierre-Yves Chibon 17526c
    :arg blame: a pygit2.Blame object allowing us to link a given line of
Pierre-Yves Chibon 17526c
        code to a commit.
Pierre-Yves Chibon 17526c
Pierre-Yves Chibon 833d1f
    """
Pierre-Yves Chibon 833d1f
    if loc is None:
Pierre-Yves Chibon 833d1f
        return
Pierre-Yves Chibon 833d1f
Jeremy Cline 00ab23
    if not isinstance(loc, six.text_type):
Pierre-Yves Chibon 9c2953
        raise ValueError('"loc" must be a unicode string, not %s' % type(loc))
Jeremy Cline 00ab23
Pierre-Yves Chibon 9c2953
    output = ['
', '']
Pierre-Yves Chibon 833d1f
Pierre-Yves Chibon 9c2953
    for idx, line in enumerate(loc.split("\n")):
Pierre-Yves Chibon 9c2953
        if line == "":
Pierre-Yves Chibon 833d1f
            break
Pierre-Yves Chibon a2e119
Pierre-Yves Chibon a2e119
        try:
Pierre-Yves Chibon a2e119
            diff = blame.for_line(idx + 1)
Pierre-Yves Chibon a2e119
        except IndexError:
Pierre-Yves Chibon a2e119
            # Happens at the end of the file, since we are using idx + 1
Pierre-Yves Chibon a2e119
            continue
Pierre-Yves Chibon a2e119
Pierre-Yves Chibon 91539b
        if '
' in line:
Pierre-Yves Chibon a2e119
            line = line.split('
')[1]
Pierre-Yves Chibon a2e119
Pierre-Yves Chibon 833d1f
        output.append(
Pierre-Yves Chibon 833d1f
            ''
Pierre-Yves Chibon 833d1f
            '
Pierre-Yves Chibon 9c2953
            '"%(cnt)s">' % ({"cnt": idx + 1})
Pierre-Yves Chibon 833d1f
        )
Pierre-Yves Chibon 833d1f
Pierre-Yves Chibon 71b6e5
        committer = None
Pierre-Yves Chibon 71b6e5
        try:
Pierre-Yves Chibon 71b6e5
            committer = diff.orig_committer
Pierre-Yves Chibon 71b6e5
        except ValueError:
Pierre-Yves Chibon 71b6e5
            pass
Pierre-Yves Chibon 833d1f
        output.append(
Pierre-Yves Chibon 9c2953
            '%s'
Pierre-Yves Chibon 9c2953
            % (
Pierre-Yves Chibon 9c2953
                author_to_user(committer, with_name=False)
Pierre-Yves Chibon 9c2953
                if committer
Pierre-Yves Chibon 9c2953
                else " "
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 833d1f
        )
Pierre-Yves Chibon a2e119
Pierre-Yves Chibon 833d1f
        output.append(
Pierre-Yves Chibon 9c2953
            '%s'
Pierre-Yves Chibon 9c2953
            % (
Pierre-Yves Chibon 0c0047
                flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.view_commit",
Pierre-Yves Chibon 0c0047
                    repo=repo.name,
Pierre-Yves Chibon 0c0047
                    username=username,
Pierre-Yves Chibon 0c0047
                    namespace=repo.namespace,
Pierre-Yves Chibon 9c2953
                    commitid=diff.final_commit_id,
Pierre-Yves Chibon 833d1f
                ),
Pierre-Yves Chibon 9c2953
                shorted_commit(diff.final_commit_id),
Pierre-Yves Chibon 833d1f
            )
Pierre-Yves Chibon 833d1f
        )
Pierre-Yves Chibon 967e77
        output.append(
Pierre-Yves Chibon 9c2953
            '
%s
' % line
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
        output.append("")
Pierre-Yves Chibon 833d1f
Pierre-Yves Chibon 9c2953
    output.append("")
Pierre-Yves Chibon 833d1f
Pierre-Yves Chibon 9c2953
    return "\n".join(output)
Pierre-Yves Chibon 833d1f
Pierre-Yves Chibon 833d1f
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("wraps")
Pierre-Yves Chibon 15e568
def text_wraps(text, size=10):
Pierre-Yves Chibon 15e568
    """ Template filter to wrap text at a specified size
Pierre-Yves Chibon 15e568
    """
Pierre-Yves Chibon 15e568
    if text:
Pierre-Yves Chibon 15e568
        parts = textwrap.wrap(text, size)
Pierre-Yves Chibon 15e568
        if len(parts) > 1:
Pierre-Yves Chibon 9c2953
            parts = "%s..." % parts[0]
Pierre-Yves Chibon 15e568
        else:
Pierre-Yves Chibon 15e568
            parts = parts[0]
Pierre-Yves Chibon 15e568
        return parts
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("avatar")
Ryan Lerch 6d2e06
def avatar(packager, size=64, css_class=None):
chocos10 6e4a4f
    """ Template filter that returns html for avatar of any given Username.
Pierre-Yves Chibon 15e568
    """
Aurélien Bompard 619e2a
    if not isinstance(packager, six.text_type):
Pierre-Yves Chibon 9c2953
        packager = packager.decode("utf-8")
Aurélien Bompard 831553
Pierre-Yves Chibon 9c2953
    if "@" not in packager:
Pierre-Yves Chibon 930073
        user = pagure.lib.query.search_user(flask.g.session, username=packager)
Pierre-Yves Chibon f6cf03
        if user:
Pierre-Yves Chibon f6cf03
            packager = user.default_email
Pierre-Yves Chibon f6cf03
Ryan Lerch 6d2e06
    class_string = "avatar circle"
Ryan Lerch 6d2e06
    if css_class:
Pierre-Yves Chibon 77bdcd
        class_string = class_string + " " + css_class
Ryan Lerch 6d2e06
Ryan Lerch 6d2e06
    output = '' % (
Ryan Lerch 6d2e06
        class_string,
Pierre-Yves Chibon 9c2953
        avatar_url(packager, size),
Pierre-Yves Chibon 15e568
    )
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
    return output
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("avatar_url")
Pierre-Yves Chibon 13de4a
def avatar_url(email, size=64):
chocos10 6e4a4f
    """ Template filter that returns html for avatar of any given Email.
Pierre-Yves Chibon 13de4a
    """
Pierre-Yves Chibon 930073
    return pagure.lib.query.avatar_url_from_email(email, size)
Pierre-Yves Chibon 13de4a
Pierre-Yves Chibon 13de4a
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("short")
Pierre-Yves Chibon 15e568
def shorted_commit(cid):
Pierre-Yves Chibon 15e568
    """Gets short version of the commit id"""
Pierre-Yves Chibon 9c2953
    return ("%s" % cid)[: pagure_config["SHORT_LENGTH"]]
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("markdown")
Pierre-Yves Chibon 15e568
def markdown_filter(text):
Pierre-Yves Chibon 15e568
    """ Template filter converting a string into html content using the
Pierre-Yves Chibon 15e568
    markdown library.
Pierre-Yves Chibon 15e568
    """
Pierre-Yves Chibon 930073
    return pagure.lib.query.text2markdown(text)
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("patch_to_diff")
Pierre-Yves Chibon 15e568
def patch_to_diff(patch):
Pierre-Yves Chibon 15e568
    """Render a hunk as a diff"""
Patrick Uiterwijk b68dfe
    content = []
Pierre-Yves Chibon 15e568
    for hunk in patch.hunks:
Pierre-Yves Chibon 9c2953
        content.append(
Pierre-Yves Chibon 9c2953
            "@@ -%i,%i +%i,%i @@\n"
Pierre-Yves Chibon 9c2953
            % (hunk.old_start, hunk.old_lines, hunk.new_start, hunk.new_lines)
Pierre-Yves Chibon 9c2953
        )
Patrick Uiterwijk b68dfe
Pierre-Yves Chibon 15e568
        for line in hunk.lines:
Pierre-Yves Chibon 9c2953
            if hasattr(line, "content"):
Pierre-Yves Chibon 2767e0
                origin = line.origin
Pierre-Yves Chibon 9c2953
                if line.origin in ["<", ">", "="]:
Pierre-Yves Chibon 9c2953
                    origin = ""
Pierre-Yves Chibon 9c2953
                content.append(origin + " " + line.content)
Pierre-Yves Chibon a55741
            else:
Pierre-Yves Chibon 44cd3f
                # Avoid situation where at the end of a file we get:
Pierre-Yves Chibon 44cd3f
                # + foo<
Pierre-Yves Chibon 44cd3f
                # \ No newline at end of file
Pierre-Yves Chibon 9c2953
                if line[0] in ["<", ">", "="]:
Pierre-Yves Chibon 9c2953
                    line = ("", line[1])
Pierre-Yves Chibon 9c2953
                content.append(" ".join(line))
Pierre-Yves Chibon 44cd3f
Pierre-Yves Chibon 9c2953
    return "".join(content)
Pierre-Yves Chibon 10a437
Pierre-Yves Chibon 10a437
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("author2user")
Pierre-Yves Chibon 833d1f
def author_to_user(author, size=16, cssclass=None, with_name=True):
Pierre-Yves Chibon 10a437
    """ Template filter transforming a pygit2 Author object into a text
Pierre-Yves Chibon 10a437
    either with just the username or linking to the user in pagure.
Pierre-Yves Chibon 10a437
    """
Michael Scherer 773db5
    output = escape(author.name)
Pierre-Yves Chibon 86c3f2
    if not author.email:
Pierre-Yves Chibon 86c3f2
        return output
Pierre-Yves Chibon 930073
    user = pagure.lib.query.search_user(flask.g.session, email=author.email)
Pierre-Yves Chibon 10a437
    if user:
Pierre-Yves Chibon 9c2953
        output = (
Pierre-Yves Chibon 9c2953
            "%(avatar)s 
Pierre-Yves Chibon 833d1f
            "%(cssclass)s>%(username)s"
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 833d1f
        if not with_name:
Pierre-Yves Chibon 9c2953
            output = (
Pierre-Yves Chibon 9c2953
                "
Pierre-Yves Chibon 833d1f
                "%(cssclass)s>%(avatar)s"
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 833d1f
Pierre-Yves Chibon 833d1f
        output = output % (
Pierre-Yves Chibon 833d1f
            {
Pierre-Yves Chibon 9c2953
                "avatar": avatar(user.default_email, size),
Pierre-Yves Chibon 9c2953
                "url": flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.view_user", username=user.username
Pierre-Yves Chibon 9c2953
                ),
Pierre-Yves Chibon 9c2953
                "cssclass": ('class="%s"' % cssclass) if cssclass else "",
Pierre-Yves Chibon 9c2953
                "username": user.username,
Pierre-Yves Chibon 9c2953
                "name": escape(author.name),
Pierre-Yves Chibon 833d1f
            }
Pierre-Yves Chibon c1b151
        )
Pierre-Yves Chibon c1b151
Pierre-Yves Chibon 10a437
    return output
Pierre-Yves Chibon bcc50f
Pierre-Yves Chibon bcc50f
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("author2avatar")
Pierre-Yves Chibon b8c7ae
def author_to_avatar(author, size=32):
Pierre-Yves Chibon b8c7ae
    """ Template filter transforming a pygit2 Author object into an avatar.
Pierre-Yves Chibon bcc50f
    """
Pierre-Yves Chibon b7c63b
    if not author.email:
Pierre-Yves Chibon 9c2953
        return ""
Pierre-Yves Chibon 930073
    user = pagure.lib.query.search_user(flask.g.session, email=author.email)
Pierre-Yves Chibon 570175
    output = user.default_email if user else author.email
Pierre-Yves Chibon 9c2953
    return avatar(output.encode("utf-8"), size)
Pierre-Yves Chibon 3578fd
Pierre-Yves Chibon 3578fd
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("author2user_commits")
Pierre-Yves Chibon bea195
def author_to_user_commits(author, link, size=16, cssclass=None):
Pierre-Yves Chibon bea195
    """ Template filter transforming a pygit2 Author object into a text
Pierre-Yves Chibon bea195
    either with just the username or linking to the user in pagure.
Pierre-Yves Chibon bea195
    """
Pierre-Yves Chibon bea195
    output = author.name
Pierre-Yves Chibon bea195
    if not author.email:
Pierre-Yves Chibon bea195
        return output
Pierre-Yves Chibon 930073
    user = pagure.lib.query.search_user(flask.g.session, email=author.email)
Pierre-Yves Chibon bea195
    if user:
Pierre-Yves Chibon bea195
        output = "%s %s" % (
Pierre-Yves Chibon 9c2953
            flask.url_for("ui_ns.view_user", username=user.username),
Pierre-Yves Chibon bea195
            avatar(user.default_email, size),
Pierre-Yves Chibon bea195
            link,
Pierre-Yves Chibon 9c2953
            ('class="%s"' % cssclass) if cssclass else "",
Pierre-Yves Chibon bea195
            author.name,
Pierre-Yves Chibon bea195
        )
Pierre-Yves Chibon bea195
Pierre-Yves Chibon bea195
    return output
Pierre-Yves Chibon bea195
Pierre-Yves Chibon 833d1f
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("InsertDiv")
Pierre-Yves Chibon 3578fd
def insert_div(content):
Pierre-Yves Chibon 3578fd
    """ Template filter inserting an opening 
and closing
Pierre-Yves Chibon 3578fd
    after the first title and then at the end of the content.
Pierre-Yves Chibon 3578fd
    """
Pierre-Yves Chibon 3578fd
    # This is quite a hack but simpler solution using .replace() didn't work
Pierre-Yves Chibon 3578fd
    # for some reasons...
Pierre-Yves Chibon 9c2953
    content = content.split("\n")
Pierre-Yves Chibon 3578fd
    output = []
Pierre-Yves Chibon 3578fd
    for row in content:
Pierre-Yves Chibon 3578fd
        if row.startswith('
Pierre-Yves Chibon 3578fd
            continue
Pierre-Yves Chibon 562e03
        if '

' in row:

Aurélien Bompard 619e2a
            row = ("%s" % row).replace(
Pierre-Yves Chibon 562e03
                '

',

Pierre-Yves Chibon 562e03
                '

'

Pierre-Yves Chibon 9c2953
                '  ',
Pierre-Yves Chibon 562e03
            )
Pierre-Yves Chibon 3578fd
        output.append(row)
Pierre-Yves Chibon 3578fd
    output = "\n".join(output)
Pierre-Yves Chibon 9c2953
    output = output.replace("", "\n
", 1)
Pierre-Yves Chibon 9c2953
    output = output.replace("h1", "h3")
Pierre-Yves Chibon 3578fd
Pierre-Yves Chibon 3578fd
    return output
Pierre-Yves Chibon bc85d8
Pierre-Yves Chibon bc85d8
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("noJS")
Pierre-Yves Chibon 2f90ea
def no_js(content, ignore=None):
Pierre-Yves Chibon bc85d8
    """ Template filter replacing <script &lt;script="" <="" and="" by="" script=""> by</script>
Pierre-Yves Chibon bc85d8
    </script>
Pierre-Yves Chibon bc85d8
    """
Pierre-Yves Chibon 930073
    return pagure.lib.query.clean_input(content, ignore=ignore)
Pierre-Yves Chibon 0c1b4c
Pierre-Yves Chibon 0c1b4c
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("toRGB")
Pierre-Yves Chibon 0c1b4c
def int_to_rgb(percent):
Pierre-Yves Chibon 0c1b4c
    """ Template filter converting a given percentage to a css RGB value.
Pierre-Yves Chibon 0c1b4c
    """
Pierre-Yves Chibon 0c1b4c
    output = "rgb(255, 0, 0);"
Pierre-Yves Chibon 0c1b4c
    try:
Pierre-Yves Chibon 0c1b4c
        percent = int(percent)
Pierre-Yves Chibon 0c1b4c
        if percent < 50:
Pierre-Yves Chibon 0c1b4c
            red = 255
Pierre-Yves Chibon 0c0047
            green = (255.0 / 50) * percent
Pierre-Yves Chibon 0c1b4c
        else:
Pierre-Yves Chibon 0c1b4c
            green = 255
Pierre-Yves Chibon 0c0047
            red = (255.0 / 50) * (100 - percent)
Pierre-Yves Chibon 0c1b4c
        output = "rgb(%s, %s, 0);" % (int(red), int(green))
Pierre-Yves Chibon 0c1b4c
    except ValueError:
Pierre-Yves Chibon 0c1b4c
        pass
Pierre-Yves Chibon 0c1b4c
    return output
Ryan Lerch e914ef
Pierre-Yves Chibon f6cf03
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("increment_largest_priority")
Pierre-Yves Chibon 11d3da
def largest_priority(dictionary):
Ryan Lerch bf08ec
    """ Template filter to return the largest priority +1
Ryan Lerch bf08ec
    """
Pierre-Yves Chibon fb7a0a
    if dictionary:
Pierre-Yves Chibon 7b3aee
        keys = [int(k) for k in dictionary if k]
Pierre-Yves Chibon 7b3aee
        if keys:
Pierre-Yves Chibon 7b3aee
            return max(keys) + 1
Pierre-Yves Chibon 7b3aee
    return 1
Ryan Lerch 9dad14
Pierre-Yves Chibon f5f5d6
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("unicode")
Ryan Lerch 9dad14
def convert_unicode(text):
Pierre-Yves Chibon 9c2953
    """ If the provided string is a binary string, this filter converts it
Pierre-Yves Chibon 11d3da
    to UTF-8 (unicode).
Pierre-Yves Chibon 9c2953
    """
Aurélien Bompard 831553
    if isinstance(text, str) and six.PY2:
Pierre-Yves Chibon f5f5d6
        return text.decode("utf8")
Pierre-Yves Chibon f5f5d6
    else:
Pierre-Yves Chibon f5f5d6
        return text
Pierre-Yves Chibon a5aa6b
Pierre-Yves Chibon a5aa6b
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("combine_url")
Pierre-Yves Chibon a5aa6b
def combine_url(url, page, pagetitle, **kwargs):
Pierre-Yves Chibon a5aa6b
    """ Add the specified arguments in the provided kwargs dictionary to
Pierre-Yves Chibon a5aa6b
    the given URL.
Pierre-Yves Chibon a5aa6b
    """
Aurélien Bompard 831553
    url_obj = urlparse(url)
Pierre-Yves Chibon 9c2953
    url = url_obj.geturl().replace(url_obj.query, "").rstrip("?")
Pierre-Yves Chibon bc789a
    query = {}
Aurélien Bompard 831553
    for k, v in parse_qsl(url_obj.query):
Pierre-Yves Chibon bc789a
        if k in query:
Pierre-Yves Chibon bc789a
            if isinstance(query[k], list):
Pierre-Yves Chibon bc789a
                query[k].append(v)
Pierre-Yves Chibon bc789a
            else:
Pierre-Yves Chibon bc789a
                query[k] = [query[k], v]
Pierre-Yves Chibon bc789a
        else:
Pierre-Yves Chibon bc789a
            query[k] = v
Pierre-Yves Chibon a5aa6b
    query[pagetitle] = page
Pierre-Yves Chibon a5aa6b
    query.update(kwargs)
Pierre-Yves Chibon 9c2953
    args = ""
Pierre-Yves Chibon bc789a
    for key in query:
Pierre-Yves Chibon bc789a
        if isinstance(query[key], list):
Pierre-Yves Chibon bc789a
            for val in query[key]:
Pierre-Yves Chibon 9c2953
                args += "&%s=%s" % (key, val)
Pierre-Yves Chibon bc789a
        else:
Pierre-Yves Chibon 9c2953
            args += "&%s=%s" % (key, query[key])
Pierre-Yves Chibon 9c2953
    return url + "?" + args[1:]
Pierre-Yves Chibon 366fac
Pierre-Yves Chibon 366fac
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("add_or_remove")
Pierre-Yves Chibon 366fac
def add_or_remove(item, items):
Pierre-Yves Chibon 366fac
    """ Adds the item to the list if it is not in there and remove it
Pierre-Yves Chibon 366fac
    otherwise.
Pierre-Yves Chibon 366fac
    """
Pierre-Yves Chibon 366fac
    if item in items:
Pierre-Yves Chibon 366fac
        items.remove(item)
Pierre-Yves Chibon 366fac
    else:
Pierre-Yves Chibon 366fac
        items.append(item)
Pierre-Yves Chibon 366fac
    return items
mprahl a6fb93
mprahl a6fb93
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("table_sort_arrow")
mprahl a6fb93
def table_sort_arrow(column, order_key, order):
mprahl a6fb93
    """ Outputs an arrow icon if the column is currently being sorted on
mprahl a6fb93
    """
Pierre-Yves Chibon 9c2953
    arrow_html = ''
mprahl a6fb93
    if column == order_key:
Pierre-Yves Chibon 9c2953
        if order == "desc":
Pierre-Yves Chibon 9c2953
            return arrow_html.format("bottom")
mprahl a6fb93
        else:
Pierre-Yves Chibon 9c2953
            return arrow_html.format("top")
Pierre-Yves Chibon 9c2953
    return ""
mprahl a6fb93
mprahl a6fb93
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("table_get_link_order")
mprahl a6fb93
def table_get_link_order(column, order_key, order):
mprahl a6fb93
    """ Get the correct order parameter value for the table heading link
mprahl a6fb93
    """
mprahl a6fb93
    if column == order_key:
mprahl a6fb93
        # If the user is clicking on the column again, they want the
mprahl a6fb93
        # oposite order
Pierre-Yves Chibon 9c2953
        if order == "desc":
Pierre-Yves Chibon 9c2953
            return "asc"
mprahl a6fb93
        else:
Pierre-Yves Chibon 9c2953
            return "desc"
mprahl a6fb93
    else:
mprahl a6fb93
        # Default to descending
Pierre-Yves Chibon 9c2953
        return "desc"
Pierre-Yves Chibon b15d96
Pierre-Yves Chibon b15d96
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("flag2label")
Pierre-Yves Chibon b15d96
def flag_to_label(flag):
Pierre-Yves Chibon b15d96
    """ For a given flag return the bootstrap label to use
Pierre-Yves Chibon b15d96
    """
Pierre-Yves Chibon 9c2953
    return pagure_config["FLAG_STATUSES_LABELS"][flag.status.lower()]
Lubomír Sedlář 59889e
Lubomír Sedlář 59889e
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("join_prefix")
Lubomír Sedlář 59889e
def join_prefix(values, num):
Lubomír Sedlář 59889e
    """Produce a string joining first `num` items in the list and indicate
Lubomír Sedlář 59889e
    total number total number of items.
Lubomír Sedlář 59889e
    """
Lubomír Sedlář 59889e
    if len(values) <= 1:
Lubomír Sedlář 59889e
        return "".join(values)
Lubomír Sedlář 59889e
    if len(values) <= num:
Lubomír Sedlář 59889e
        return ", ".join(values[:-1]) + " and " + values[-1]
Lubomír Sedlář 59889e
    return "%s and %d others" % (", ".join(values[:num]), len(values) - num)
Pierre-Yves Chibon 9aba91
Pierre-Yves Chibon 9aba91
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("user_can_clone_ssh")
Pierre-Yves Chibon 9aba91
def user_can_clone_ssh(username):
Patrick Uiterwijk 9b237b
    has_ssh_keys = False
Pierre-Yves Chibon 9aba91
    if flask.g.authenticated:
Patrick Uiterwijk 9b237b
        has_ssh_keys = (
Patrick Uiterwijk 9b237b
            len(
Pierre-Yves Chibon 930073
                pagure.lib.query.search_user(
Patrick Uiterwijk 9b237b
                    flask.g.session, username=flask.g.fas_user.username
Patrick Uiterwijk 9b237b
                ).sshkeys
Patrick Uiterwijk 9b237b
            )
Patrick Uiterwijk 9b237b
            != 0
Pierre-Yves Chibon 9c2953
        )
Patrick Uiterwijk 9b237b
    always_render = pagure_config.get("ALWAYS_RENDER_SSH_CLONE_URL")
Patrick Uiterwijk 9b237b
    return always_render or has_ssh_keys
Pierre-Yves Chibon 9aba91
Pierre-Yves Chibon 9aba91
Pierre-Yves Chibon 9c2953
@UI_NS.app_template_filter("git_url_ssh")
Pierre-Yves Chibon 9c2953
def get_git_url_ssh(complement=""):
Pierre-Yves Chibon 9aba91
    """ Return the GIT SSH URL to be displayed in the UI based on the
Pierre-Yves Chibon 9aba91
    content of the configuration file.
Pierre-Yves Chibon 9aba91
    """
Pierre-Yves Chibon 9c2953
    git_url_ssh = pagure_config.get("GIT_URL_SSH")
Pierre-Yves Chibon 9aba91
    if flask.g.authenticated and git_url_ssh:
Pierre-Yves Chibon 9aba91
        try:
Pierre-Yves Chibon 9aba91
            git_url_ssh = git_url_ssh.format(
Pierre-Yves Chibon 9c2953
                username=flask.g.fas_user.username
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9aba91
        except (KeyError, IndexError):
Pierre-Yves Chibon 9aba91
            pass
Pierre-Yves Chibon 9aba91
    return git_url_ssh + complement