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
Pierre-Yves Chibon 67d1cc
from __future__ import unicode_literals, absolute_import
Aurélien Bompard dcf6f6
Pierre-Yves Chibon 15e568
import textwrap
Pierre-Yves Chibon f6a6e0
import logging
Ryan Lerch 9fe1c6
from os.path import splitext
Pierre-Yves Chibon 15e568
Pierre-Yves Chibon 15e568
import arrow
Pierre-Yves Chibon 267b16
import flask
Jeremy Cline 00ab23
import six
Ryan Lerch 3ec425
import bleach
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 f6a6e0
_log = logging.getLogger(__name__)
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
Ryan Lerch 3ec425
@UI_NS.app_template_filter("linkify")
Ryan Lerch 3ec425
def linkify_text(text):
Ryan Lerch 3ec425
    """ escape all html tags with bleach, then use bleach to linkify
Ryan Lerch 3ec425
    """
Ryan Lerch 3ec425
    if text:
Ryan Lerch 3ec425
        cleaned = bleach.clean(text, tags=[], attributes=[])
Ryan Lerch 3ec425
        return bleach.linkify(cleaned)
Ryan Lerch 3ec425
    else:
Ryan Lerch 3ec425
        return ""
Ryan Lerch 3ec425
Ryan Lerch 3ec425
Ryan Lerch 9fe1c6
@UI_NS.app_template_filter("syntax_alias")
Ryan Lerch 9fe1c6
def get_syntax_alias(filename):
Ryan Lerch 9fe1c6
    """ return an alias based on the filename that is used to
Ryan Lerch 9fe1c6
        override the automatic syntax highlighting dectection
Ryan Lerch 9fe1c6
        by highlight.js
Ryan Lerch 9fe1c6
    """
Ryan Lerch 9fe1c6
Ryan Lerch 9fe1c6
    override_rules = pagure_config.get(
Ryan Lerch 9fe1c6
        "SYNTAX_ALIAS_OVERRIDES", {".spec": "specfile", ".patch": "diff"}
Ryan Lerch 9fe1c6
    )
Ryan Lerch 9fe1c6
    fn, fn_ext = splitext(filename)
Ryan Lerch 9fe1c6
Ryan Lerch 9fe1c6
    output = ""
Ryan Lerch 9fe1c6
    if fn_ext == "":
Ryan Lerch 9fe1c6
        output = "lang-plaintext"
Ryan Lerch 9fe1c6
    elif fn_ext in override_rules:
Ryan Lerch 9fe1c6
        output = "lang-" + override_rules[fn_ext]
Ryan Lerch 9fe1c6
Ryan Lerch 9fe1c6
    return output
Ryan Lerch 9fe1c6
Ryan Lerch 9fe1c6
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 f6a6e0
    commit_hash = commit
Pierre-Yves Chibon f6a6e0
    if hasattr(commit_hash, "hex"):
Pierre-Yves Chibon f6a6e0
        commit_hash = commit_hash.hex
Pierre-Yves Chibon f6a6e0
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 f6a6e0
                and com.commit_id == commit_hash
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 f620a6
                '"%(cnt_lbl)s" data-file-number='
Pierre-Yves Chibon f620a6
                '"%(line)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
                "

"

Julen Landa Alustiza 9b6ae7
                '
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 f620a6
                        "cnt": "_%s__%s" % (index, cnt),
Pierre-Yves Chibon 9c2953
                        "cnt_lbl": cnt,
Pierre-Yves Chibon f620a6
                        "line": index,
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 = (
Julen Landa Alustiza 0e3248
            '
Julen Landa Alustiza 0e3248
            'delete_comment_btn" title="Remove comment" name="drop_comment"'
Julen Landa Alustiza 0e3248
            'value="%(commentid)s" type="submit">'
Julen Landa Alustiza 0e3248
            ''
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 58e90c
                                namespace=comment.parent.project.namespace,
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 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 d156c8
            '
%s
' % no_js(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
Pierre-Yves Chibon f6a6e0
Pierre-Yves Chibon f6a6e0
Pierre-Yves Chibon f6a6e0
@UI_NS.app_template_filter("patch_stats")
Pierre-Yves Chibon f6a6e0
def get_patch_stats(patch):
Pierre-Yves Chibon f6a6e0
    """ Return a dict of stats about the provided patch."""
Pierre-Yves Chibon f6a6e0
    try:
Pierre-Yves Chibon f6a6e0
        output = pagure.lib.git.get_stats_patch(patch)
Pierre-Yves Chibon f6a6e0
    except pagure.exceptions.PagureException:
Pierre-Yves Chibon f6a6e0
        _log.exception("Failed to get stats on a patch")
Pierre-Yves Chibon f6a6e0
        output = {}
Pierre-Yves Chibon f6a6e0
    return output