Esempio n. 1
0
def repositories_statistics(sorting: Optional[str] = None) -> Response:
    autorefresh = flask.request.args.to_dict().get('autorefresh')

    repostats_by_name = {repostat['name']: repostat for repostat in get_db().get_active_repositories()}
    repostats = [repostats_by_name[reponame] for reponame in repometadata.active_names() if reponame in repostats_by_name]

    if sorting == 'newest':
        repostats = sorted(repostats, key=lambda s: cast(int, s['num_metapackages_newest']), reverse=True)
    elif sorting == 'pnewest':
        repostats = sorted(repostats, key=lambda s: safe_percent(s['num_metapackages_newest'], s['num_metapackages_comparable']), reverse=True)
    elif sorting == 'outdated':
        repostats = sorted(repostats, key=lambda s: cast(int, s['num_metapackages_outdated']), reverse=True)
    elif sorting == 'poutdated':
        repostats = sorted(repostats, key=lambda s: safe_percent(s['num_metapackages_outdated'], s['num_metapackages_comparable']), reverse=True)
    elif sorting == 'total':
        repostats = sorted(repostats, key=lambda s: cast(int, s['num_metapackages']), reverse=True)
    elif sorting == 'nonunique':
        repostats = sorted(repostats, key=lambda s: cast(int, s['num_metapackages'] - s['num_metapackages_unique']), reverse=True)
    elif sorting == 'vulnerable':
        repostats = sorted(repostats, key=lambda s: cast(int, s['num_metapackages_vulnerable']), reverse=True)
    elif sorting == 'pvulnerable':
        repostats = sorted(repostats, key=lambda s: safe_percent(s['num_metapackages_vulnerable'], s['num_metapackages']), reverse=True)
    else:
        sorting = 'name'

    return flask.render_template(
        'repositories-statistics.html',
        sorting=sorting,
        repostats=repostats,
        repostats_old={},  # {repo['name']: repo for repo in get_db().GetRepositoriesHistoryAgo(60 * 60 * 24 * 7)},
        counts=get_db().get_counts(),
        autorefresh=autorefresh
    )
Esempio n. 2
0
def badge_vertical_allrepos(name: str) -> Any:
    packages = get_db().get_metapackage_packages(
        name, fields=['repo', 'version', 'versionclass'])
    best_pkg_by_repo = packageset_to_best_by_repo(packages)

    header = flask.request.args.to_dict().get('header', 'Packaging status')
    minversion = flask.request.args.to_dict().get('minversion')

    entries = [{
        'repo':
        repometadata[reponame],
        'package':
        best_pkg_by_repo[reponame],
        'unsatisfying':
        version_compare(best_pkg_by_repo[reponame].version, minversion) < 0
        if minversion else False,
    } for reponame in repometadata.active_names()
               if reponame in best_pkg_by_repo]

    if not entries:
        header = 'No known packages'

    return (flask.render_template('badge-vertical.svg',
                                  entries=entries,
                                  name=name,
                                  header=header), {
                                      'Content-type': 'image/svg+xml'
                                  })
Esempio n. 3
0
def project_versions(name: str) -> Any:
    metapackage = get_db().get_metapackage(name)

    if not metapackage or metapackage['num_repos'] == 0:
        return handle_nonexisting_project(name, metapackage)

    packages = [
        PackageDataDetailed(**item)
        for item in get_db().get_metapackage_packages(name, detailed=True)
    ]

    packages_by_repo: Dict[str, List[PackageDataDetailed]] = defaultdict(list)
    for package in packages:
        packages_by_repo[package.repo].append(package)

    for repo, repo_packages in packages_by_repo.items():
        packages_by_repo[repo] = packageset_sort_by_version(repo_packages)

    return flask.render_template(
        'project-versions.html',
        name=name,
        metapackage=metapackage,
        packages=packages,
        packages_by_repo=packages_by_repo,
        reponames_absent=[
            reponame for reponame in repometadata.active_names()
            if reponame not in packages_by_repo
        ])
Esempio n. 4
0
def badge_vertical_allrepos(name: str) -> Any:
    args = flask.request.args.to_dict()

    packages = get_db().get_metapackage_packages(
        name, fields=['repo', 'version', 'versionclass'])
    best_pkg_by_repo = packageset_to_best_by_repo(packages,
                                                  allow_ignored=args.get(
                                                      'allow_ignored', False))

    header = args.get('header')
    minversion = args.get('minversion')

    cells = []

    for reponame in repometadata.active_names():
        if reponame in best_pkg_by_repo:
            version = best_pkg_by_repo[reponame].version
            versionclass = best_pkg_by_repo[reponame].versionclass
            unsatisfying = minversion and version_compare(version,
                                                          minversion) < 0

            color = badge_color(versionclass, unsatisfying)

            cells.append([
                BadgeCell(repometadata[reponame]['desc'], align='r'),
                BadgeCell(version, color=color, truncate=13, minwidth=60)
            ])

    if header is None:
        header = 'Packaging status' if cells else 'No known packages'

    return render_generic_badge(cells, header=header)
Esempio n. 5
0
def badge_vertical_allrepos(name):
    packages = get_db().get_metapackage_packages(name, fields=['repo', 'version', 'versionclass'])
    best_pkg_by_repo = PackagesetToBestByRepo(packages)

    header = flask.request.args.to_dict().get('header', 'Packaging status')

    entries = [
        {
            'repo': repometadata[reponame],
            'package': best_pkg_by_repo[reponame]
        } for reponame in repometadata.active_names() if reponame in best_pkg_by_repo
    ]

    if not entries:
        header = 'No known packages'

    return (
        flask.render_template(
            'badge-vertical.svg',
            entries=entries,
            name=name,
            header=header
        ),
        {'Content-type': 'image/svg+xml'}
    )
Esempio n. 6
0
def problems_generic(repo: str,
                     maintainer: Optional[str] = None,
                     start: Optional[str] = None,
                     end: Optional[str] = None) -> Response:
    if repo not in repometadata.active_names():
        flask.abort(404)

    problems = get_db().get_problems(repo=repo,
                                     maintainer=maintainer,
                                     start=start,
                                     end=end,
                                     limit=config['PROBLEMS_PER_PAGE'])

    first, last = get_db().get_problems_range(repo=repo, maintainer=maintainer)

    is_first_page, is_last_page = False, False
    for problem in problems:
        if problem['effname'] == first:
            is_first_page = True
        if problem['effname'] == last:
            is_last_page = True

    return flask.render_template('problems.html',
                                 repo=repo,
                                 maintainer=maintainer,
                                 start=start,
                                 end=end,
                                 first=first,
                                 last=last,
                                 is_first_page=is_first_page,
                                 is_last_page=is_last_page,
                                 problems=problems)
Esempio n. 7
0
def repositories_statistics(sorting=None):
    autorefresh = flask.request.args.to_dict().get('autorefresh')

    repostats = {repostat['name']: repostat for repostat in get_db().get_active_repositories()}
    repostats = [repostats[reponame] for reponame in repometadata.active_names() if reponame in repostats]
    showmedals = True

    if sorting == 'newest':
        repostats = sorted(repostats, key=lambda s: s['num_metapackages_newest'], reverse=True)
    elif sorting == 'pnewest':
        repostats = sorted(repostats, key=lambda s: safe_percent(s['num_metapackages_newest'], s['num_metapackages_comparable']), reverse=True)
    elif sorting == 'outdated':
        repostats = sorted(repostats, key=lambda s: s['num_metapackages_outdated'], reverse=True)
    elif sorting == 'poutdated':
        repostats = sorted(repostats, key=lambda s: safe_percent(s['num_metapackages_outdated'], s['num_metapackages_comparable']), reverse=True)
    elif sorting == 'total':
        repostats = sorted(repostats, key=lambda s: s['num_metapackages'], reverse=True)
    else:
        sorting = 'name'
        showmedals = False

    return flask.render_template(
        'repositories-statistics.html',
        sorting=sorting,
        repostats=repostats,
        showmedals=showmedals,
        repostats_old={},  # {repo['name']: repo for repo in get_db().GetRepositoriesHistoryAgo(60 * 60 * 24 * 7)},
        counts=get_db().get_counts(),
        autorefresh=autorefresh
    )
Esempio n. 8
0
def badge_version_for_repo(repo: str, name: str) -> Response:
    if repo not in repometadata.active_names():
        flask.abort(404)

    args = flask.request.args.to_dict()

    best_package = packageset_to_best(
        (PackageDataMinimal(**item) for item in
         get_db().get_metapackage_packages(name, repo=repo, minimal=True)),
        allow_ignored=args.get('allow_ignored', False))

    left_cell = BadgeCell(flask.request.args.to_dict().get(
        'header', repometadata[repo]['singular']),
                          collapsible=True)

    if best_package is None:
        # Note: it would be more correct to return 404 with content here,
        # but some browsers (e.g. Firefox) won't display the image in that case
        right_cell = BadgeCell('-')
    else:
        minversion = flask.request.args.to_dict().get('minversion')
        unsatisfying = minversion and version_compare(best_package.version,
                                                      minversion) < 0

        right_cell = BadgeCell(best_package.version,
                               badge_color(best_package.versionclass,
                                           unsatisfying),
                               truncate=20)

    return render_generic_badge([[left_cell, right_cell]])
Esempio n. 9
0
def repository_problems(repo):
    if repo not in repometadata.active_names():
        flask.abort(404)

    return flask.render_template('repository-problems.html',
                                 repo=repo,
                                 problems=get_db().get_repository_problems(
                                     repo, config['PROBLEMS_PER_PAGE']))
Esempio n. 10
0
def project_information(name: str) -> Any:
    metapackage = get_db().get_metapackage(name)

    if not metapackage or metapackage['num_repos'] == 0:
        return handle_nonexisting_project(name, metapackage)

    packages = sorted(
        (PackageDataDetailed(**item)
         for item in get_db().get_metapackage_packages(name, detailed=True)),
        key=lambda package: package.repo + package.visiblename + package.
        version)

    information: Dict[str, Any] = {}

    def append_info(infokey: str, infoval: str,
                    package: PackageDataDetailed) -> None:
        if infokey not in information:
            information[infokey] = {}

        if infoval not in information[infokey]:
            information[infokey][infoval] = set()

        information[infokey][infoval].add(package.family)

    for package in packages:
        append_info('names', package.visiblename, package)
        append_info('versions', package.version, package)
        append_info('repos', package.repo, package)

        if package.comment:
            append_info('summaries', package.comment, package)
        for maintainer in package.maintainers:
            append_info('maintainers', maintainer, package)
        if package.category:
            append_info('categories', package.category, package)
        if package.homepage:
            append_info('homepages', package.homepage, package)
        for download in package.downloads:
            append_info('downloads', download, package)
        for license_ in package.licenses:
            append_info('licenses', license_, package)

    if 'repos' in information:
        # preserve repos order
        information['repos'] = [(reponame, information['repos'][reponame])
                                for reponame in repometadata.active_names()
                                if reponame in information['repos']]

    versions = packageset_aggregate_by_version(
        packages, {PackageStatus.LEGACY: PackageStatus.OUTDATED})

    return flask.render_template(
        'project-information.html',
        name=name,
        metapackage=metapackage,
        information=information,
        versions=versions,
        link_statuses=get_db().get_metapackage_link_statuses(name))
Esempio n. 11
0
def metapackages_not_in_repo(repo, bound=None):
    if repo not in repometadata.active_names():
        flask.abort(404)

    return flask.redirect(
        flask.url_for('metapackages',
                      bound=bound,
                      notinrepo=repo,
                      search=flask.request.args.to_dict().get('search')), 301)
Esempio n. 12
0
def metapackages_in_repo(repo: str, bound: Optional[str] = None) -> Any:
    if repo not in repometadata.active_names():
        flask.abort(404)

    return flask.redirect(
        flask.url_for('projects',
                      bound=bound,
                      inrepo=repo,
                      search=flask.request.args.to_dict().get('search')), 301)
Esempio n. 13
0
def project_badges(name: str) -> Any:
    repos_present_in = set([package.repo for package in get_db().get_metapackage_packages(name)])
    repos = [repo for repo in repometadata.active_names() if repo in repos_present_in]
    return flask.render_template(
        'project-badges.html',
        metapackage=get_db().get_metapackage(name),
        name=name,
        repos=repos
    )
Esempio n. 14
0
def metapackages_candidates_for_repo(repo, bound=None):
    if repo not in repometadata.active_names():
        flask.abort(404)

    return flask.redirect(
        flask.url_for('projects',
                      bound=bound,
                      inrepo=repo,
                      families='5-',
                      search=flask.request.args.to_dict().get('search')), 301)
Esempio n. 15
0
def badge_vertical_allrepos(name: str) -> Response:
    args = flask.request.args.to_dict()

    best_pkg_by_repo = packageset_to_best_by_repo(
        (PackageDataMinimal(**item)
         for item in get_db().get_metapackage_packages(name, minimal=True)),
        allow_ignored=args.get('allow_ignored', False))

    header = args.get('header')
    minversion = args.get('minversion')

    repo_filter = RepositoryFilter(args)

    cells = []

    for reponame in repometadata.active_names():
        if not repo_filter.check(reponame):
            continue

        if reponame in best_pkg_by_repo:
            version = best_pkg_by_repo[reponame].version
            versionclass = best_pkg_by_repo[reponame].versionclass
            unsatisfying = minversion and version_compare(version,
                                                          minversion) < 0

            color = badge_color(versionclass, unsatisfying)

            cells.append([
                BadgeCell(repometadata[reponame]['desc'], align='r'),
                BadgeCell(version, color=color, truncate=13, minwidth=60)
            ])

    try:
        columns = min(int(args.get('columns', '1')), len(cells))
    except:
        columns = 1

    if columns > 1:
        chunks = []
        columnsize = (len(cells) + columns - 1) // columns
        for column in range(columns):
            chunks.append(cells[column * columnsize:column * columnsize +
                                columnsize])

        empty_filler = [BadgeCell(''), BadgeCell('')]

        cells = [
            sum(cells, [])
            for cells in zip_longest(*chunks, fillvalue=empty_filler)
        ]

    if header is None:
        header = 'Packaging status' if cells else 'No known packages'

    return render_generic_badge(cells, header=header)
Esempio n. 16
0
def repositories_packages() -> Response:
    autorefresh = flask.request.args.to_dict().get('autorefresh')

    repostats_by_name = {repostat['name']: repostat for repostat in get_db().get_active_repositories()}
    repostats = [repostats_by_name[reponame] for reponame in repometadata.active_names() if reponame in repostats_by_name]

    return flask.render_template(
        'repositories-packages.html',
        repostats=repostats,
        counts=get_db().get_counts(),
        autorefresh=autorefresh
    )
Esempio n. 17
0
def metapackage_information(name):
    packages = get_db().get_metapackage_packages(name)
    packages = sorted(
        packages,
        key=lambda package: package.repo + package.name + package.version)

    information = {}

    def append_info(infokey, infoval, package):
        if infokey not in information:
            information[infokey] = {}

        if infoval not in information[infokey]:
            information[infokey][infoval] = set()

        information[infokey][infoval].add(package.family)

    for package in packages:
        append_info('names', package.name, package)
        append_info('versions', package.version, package)
        append_info('repos', package.repo, package)

        if package.comment:
            append_info('summaries', package.comment, package)
        for maintainer in package.maintainers:
            append_info('maintainers', maintainer, package)
        if package.category:
            append_info('categories', package.category, package)
        if package.homepage:
            append_info('homepages', package.homepage, package)
        for download in package.downloads:
            append_info('downloads', download, package)
        for license_ in package.licenses:
            append_info('licenses', license_, package)

    if 'repos' in information:
        # preserve repos order
        information['repos'] = [(reponame, information['repos'][reponame])
                                for reponame in repometadata.active_names()
                                if reponame in information['repos']]

    versions = PackagesetAggregateByVersion(
        packages, {VersionClass.legacy: VersionClass.outdated})

    return flask.render_template(
        'metapackage-information.html',
        information=information,
        versions=versions,
        metapackage=get_db().get_metapackage(name),
        name=name,
        link_statuses=get_db().get_metapackage_link_statuses(name))
Esempio n. 18
0
def metapackage_versions(name):
    packages_by_repo = defaultdict(list)
    for package in get_db().get_metapackage_packages(name):
        packages_by_repo[package.repo].append(package)

    for repo, packages in packages_by_repo.items():
        packages_by_repo[repo] = PackagesetSortByVersion(packages)

    return flask.render_template(
        'metapackage-versions.html',
        reponames_absent=[reponame for reponame in repometadata.active_names() if reponame not in packages_by_repo],
        packages_by_repo=packages_by_repo,
        name=name
    )
Esempio n. 19
0
def repository(repo):
    if repo not in repometadata.all_names():
        flask.abort(404)
        #return (flask.render_template('repository-404.html', repo=repo), 404)
    if repo not in repometadata.active_names():
        # HTTP code is intentionally 404
        return (flask.render_template(
            'repository-410.html',
            repo=repo,
            repo_info=get_db().get_repository_information(repo)), 404)

    return flask.render_template(
        'repository.html',
        repo=repo,
        repo_info=get_db().get_repository_information(repo))
Esempio n. 20
0
def tool_project_by() -> Response:
    repo = flask.request.args.get('repo')
    name_type = flask.request.args.get('name_type')
    name = flask.request.args.get('name')
    noautoresolve = bool(flask.request.args.get('noautoresolve'))

    target_page = None

    for allowed_target_page in _ALLOWED_TARGET_PAGES:
        if allowed_target_page.endpoint == flask.request.args.get('target_page'):
            target_page = allowed_target_page
            break

    template_url = None

    if repo and name_type and target_page:
        if repo not in repometadata.active_names():
            return (flask.render_template('project-by-failed.html', reason='no_repo'), 404)
        elif not repometadata[repo]['family'] in _ALLOWED_FAMILIES:
            return (flask.render_template('project-by-failed.html', reason='disallowed_repo'), 403)
        elif name:
            targets = []

            for project in get_db().get_projects_by_name(repo=repo, name_type=name_type, name=name):
                possible_args = {'name': project, 'repo': repo}
                real_args = {k: possible_args[k] for k in target_page.args}

                targets.append((project, flask.url_for(target_page.endpoint, **real_args)))

            if not targets:
                return (flask.render_template('project-by-failed.html', reason='no_package'), 404)
            elif noautoresolve and len(targets) > 1:
                return flask.render_template(
                    'project-by-ambiguity.html',
                    targets=targets,
                )
            else:
                return flask.redirect(targets[0][1], 302)
        else:
            args = {k: v for k, v in flask.request.args.items() if k in _EXTRA_ALLOWED_ARGS | {'repo', 'name_type', 'noautoresolve', 'target_page'}}
            template_url = url_for_self(**args)

    return flask.render_template(
        'project-by.html',
        allowed_target_pages=_ALLOWED_TARGET_PAGES,
        template_url=template_url,
        allowed_families=_ALLOWED_FAMILIES,
    )
Esempio n. 21
0
def graph_repo_generic(repo: str, getvalue: Callable[[Any], float], color: str, suffix: str = '') -> Response:
    if repo not in repometadata.active_names():
        flask.abort(404)

    def get_graph(period: int) -> GraphProcessor:
        graph = GraphProcessor()

        for histentry in get_db().get_repository_history_since(repo, datetime.timedelta(seconds=period)):
            try:
                graph.add_point(histentry['timedelta'], getvalue(histentry['snapshot']))
            except:
                pass  # ignore missing keys, division errors etc.

        return graph

    return graph_generic(get_graph, color, suffix)
Esempio n. 22
0
def repository(repo: str) -> Response:
    autorefresh = flask.request.args.to_dict().get('autorefresh')

    if repo not in repometadata.all_names():
        flask.abort(404)
        #return (flask.render_template('repository-404.html', repo=repo), 404)
    if repo not in repometadata.active_names():
        # HTTP code is intentionally 404
        return (flask.render_template('repository-410.html', repo=repo, repo_info=get_db().get_repository_information(repo)), 404)

    return flask.render_template(
        'repository.html',
        repo=repo,
        repo_info=get_db().get_repository_information(repo),
        autorefresh=autorefresh
    )
Esempio n. 23
0
def metapackage_packages(name):
    packages_by_repo = defaultdict(list)

    for package in get_db().get_metapackage_packages(name):
        packages_by_repo[package.repo].append(package)

    packages = []
    for repo in repometadata.active_names():
        if repo in packages_by_repo:
            packages.extend(PackagesetSortByNameVersion(packages_by_repo[repo]))

    return flask.render_template(
        'metapackage-packages.html',
        packages=packages,
        name=name,
        link_statuses=get_db().get_metapackage_link_statuses(name)
    )
Esempio n. 24
0
def project_badges(name: str) -> Any:
    metapackage = get_db().get_metapackage(name)

    if not metapackage or metapackage['num_repos'] == 0:
        return handle_nonexisting_project(name, metapackage)

    packages = get_db().get_metapackage_packages(name)

    repos_present_in = set([package.repo for package in packages])
    repos = [repo for repo in repometadata.active_names() if repo in repos_present_in]

    return flask.render_template(
        'project-badges.html',
        name=name,
        metapackage=metapackage,
        repos=repos
    )
Esempio n. 25
0
def project_packages(name):
    packages_by_repo = defaultdict(list)

    for package in get_db().get_metapackage_packages(name):
        packages_by_repo[package.repo].append(package)

    packages = []
    for repo in repometadata.active_names():
        if repo in packages_by_repo:
            packages.extend(
                packageset_sort_by_name_version(packages_by_repo[repo]))

    return flask.render_template(
        'project-packages.html',
        packages=packages,
        metapackage=get_db().get_metapackage(name),
        name=name,
        link_statuses=get_db().get_metapackage_link_statuses(name))
Esempio n. 26
0
def project_versions(name: str) -> Any:
    packages_by_repo: Dict[str, List[Package]] = defaultdict(list)

    packages = get_db().get_metapackage_packages(name)

    for package in packages:
        packages_by_repo[package.repo].append(package)

    for repo, repo_packages in packages_by_repo.items():
        packages_by_repo[repo] = packageset_sort_by_version(repo_packages)

    return flask.render_template(
        'project-versions.html',
        reponames_absent=[reponame for reponame in repometadata.active_names() if reponame not in packages_by_repo],
        packages=packages,
        packages_by_repo=packages_by_repo,
        metapackage=get_db().get_metapackage(name),
        name=name
    )
Esempio n. 27
0
def project_packages(name: str) -> Any:
    metapackage = get_db().get_metapackage(name)

    if not metapackage or metapackage['num_repos'] == 0:
        return handle_nonexisting_project(name, metapackage)

    packages_by_repo: Dict[str, List[Package]] = defaultdict(list)
    for package in get_db().get_metapackage_packages(name):
        packages_by_repo[package.repo].append(package)

    packages: List[Package] = []
    for repo in repometadata.active_names():
        if repo in packages_by_repo:
            packages.extend(packageset_sort_by_name_version(packages_by_repo[repo]))

    return flask.render_template(
        'project-packages.html',
        name=name,
        metapackage=metapackage,
        packages=packages,
        link_statuses=get_db().get_metapackage_link_statuses(name)
    )
Esempio n. 28
0
def metapackage_badges(name):
    repos_present_in = set([package.repo for package in get_db().get_metapackage_packages(name)])
    repos = [repo for repo in repometadata.active_names() if repo in repos_present_in]
    return flask.render_template('metapackage-badges.html', name=name, repos=repos)
Esempio n. 29
0
def project_information(name: str) -> Response:
    metapackage = get_db().get_metapackage(name)

    if not metapackage or metapackage['num_repos'] == 0:
        return handle_nonexisting_project(name, metapackage)

    packages = sorted(
        (PackageDataDetailed(**item)
         for item in get_db().get_metapackage_packages(name, detailed=True)),
        key=lambda package:
        (package.repo, package.visiblename, package.version))

    information: Dict[str, Any] = {}

    def append_info(infokey: str, infoval: Any,
                    package: PackageDataDetailed) -> None:
        if infokey not in information:
            information[infokey] = {}

        if infoval not in information[infokey]:
            information[infokey][infoval] = set()

        information[infokey][infoval].add(package.family)

    for package in packages:
        append_info('names', package.projectname_seed, package)
        append_info('versions', package.version, package)
        append_info('repos', package.repo, package)

        if package.comment:
            append_info('summaries', package.comment, package)
        if package.maintainers is not None:
            for maintainer in package.maintainers:
                append_info('maintainers', maintainer, package)
        if package.category:
            append_info('categories', package.category, package)
        if package.licenses is not None:
            for license_ in package.licenses:
                append_info('licenses', license_, package)
        if package.links is not None:
            maybe_raw_links = defaultdict(list)
            for link_type, link_id in package.links:
                if link_type in [
                        LinkType.UPSTREAM_HOMEPAGE, LinkType.PROJECT_HOMEPAGE
                ]:
                    append_info('homepages', link_id, package)
                elif link_type in [
                        LinkType.UPSTREAM_DOWNLOAD, LinkType.PROJECT_DOWNLOAD
                ]:
                    append_info('downloads', link_id, package)
                elif link_type == LinkType.UPSTREAM_ISSUE_TRACKER:
                    append_info('issues', link_id, package)
                elif link_type == LinkType.UPSTREAM_REPOSITORY:
                    append_info('repositories', link_id, package)
                elif link_type == LinkType.UPSTREAM_DOCUMENTATION:
                    append_info('documentation', link_id, package)
                elif link_type == LinkType.PACKAGE_HOMEPAGE:
                    append_info('packages', link_id, package)
                elif link_type == LinkType.PACKAGE_RECIPE:
                    maybe_raw_links['recipes'].append(link_id)
                elif link_type == LinkType.PACKAGE_RECIPE_RAW:
                    maybe_raw_links['recipes_raw'].append(link_id)
                elif link_type == LinkType.PACKAGE_PATCH:
                    maybe_raw_links['patches'].append(link_id)
                elif link_type == LinkType.PACKAGE_PATCH_RAW:
                    maybe_raw_links['patches_raw'].append(link_id)
                elif link_type == LinkType.PACKAGE_BUILD_LOG:
                    maybe_raw_links['buildlogs'].append(link_id)
                elif link_type == LinkType.PACKAGE_BUILD_LOG_RAW:
                    maybe_raw_links['buildlogs_raw'].append(link_id)

            # for links which may have both human-readlabe and raw flavors, we
            # prefer human-readable ones here
            for key in ['recipes', 'patches', 'buildlogs']:
                if key in maybe_raw_links:
                    for link_id in maybe_raw_links[key]:
                        append_info(key, link_id, package)
                elif key + '_raw' in maybe_raw_links:
                    for link_id in maybe_raw_links[key + '_raw']:
                        append_info(key, link_id, package)

    if 'repos' in information:
        # preserve repos order
        information['repos'] = [(reponame, information['repos'][reponame])
                                for reponame in repometadata.active_names()
                                if reponame in information['repos']]

    versions = packageset_aggregate_by_version(
        packages, {PackageStatus.LEGACY: PackageStatus.OUTDATED})

    links = get_db().get_project_links(name)

    for key in [
            'homepages', 'downloads', 'issues', 'repositories', 'patches',
            'buildlogs', 'documentation', 'recipes'
    ]:
        if key in information:
            information[key] = sorted(
                information[key].items(),
                key=lambda l: links[l[0]]['url'].lower()  # type: ignore
            )

    return flask.render_template('project-information.html',
                                 name=name,
                                 metapackage=metapackage,
                                 information=information,
                                 versions=versions,
                                 links=links)