#!/usr/bin/python3
#vim:set fileencoding=utf-8:
#
#   apt-blacklist - Check packages that apt wants to install and abort the
#                   installation process if some criteria are met.
#
#   Copyright (C) 2009       Andrey Rahmatullin <wrar@altlinux.org>
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public
#   License along with this program; if not, see
#   <http://www.gnu.org/licenses/>.
#


import os
import sys

import rpm
from rpm import error as rpm_error

packagerBlacklistPath = '/etc/apt-blacklist/packagers'
packagerWarnlistPath = '/etc/apt-blacklist/warning'
packagerWatchlistPath = '/etc/apt-blacklist/watch'

def getHeaders(filename):
    """Get package name and last two packagers for .rpm file.
    """
    try:
        with open(filename) as f:
            ts = rpm.TransactionSet()
            headers = ts.hdrFromFdno(f.fileno())
    except rpm_error:
        return ("", "", "")                          # return dummy info on rpm error
    changelogEntry1 = headers[rpm.RPMTAG_CHANGELOGNAME][0] # 'Who1 <email1> 1.0-alt2'
    newpackager = changelogEntry1[:changelogEntry1.rfind(' ')]
    try:
        changelogEntry2 = headers[rpm.RPMTAG_CHANGELOGNAME][1] # 'Who2 <email2> 1.0-alt1'
        oldpackager = changelogEntry2[:changelogEntry2.rfind(' ')]
    except:
        oldpackager = None          # package with one changelog entry
    return (headers[rpm.RPMTAG_NAME],
            newpackager,
            oldpackager)

if __name__ == '__main__':
    if not os.path.exists(packagerBlacklistPath):
        sys.exit(0)

    filenames = sys.stdin.readlines()
    pkgInfos = [getHeaders(f.rstrip()) for f in filenames]

    with open(packagerBlacklistPath) as f:
        packagerBlacklist = [p.strip() for p in f.readlines() if len(p.strip()) > 0]

    badPackages = {}            # key: packager, value: list of packages
    for pkg, packager, dummy in pkgInfos:
        for badPackager in packagerBlacklist:
            if packager.lower().find(badPackager) > -1:
                if packager not in badPackages:
                    badPackages[packager] = []
                badPackages[packager].append(pkg)
                break

    if os.path.exists(packagerWarnlistPath):
        with open(packagerWarnlistPath) as f:
            packagerWarnlist = [p.strip() for p in f.readlines() if len(p.strip()) > 0]

        warnPackages = {}       # key: packager, value: list of packages
        for pkg, packager, dummy in pkgInfos:
            for warnPackager in packagerWarnlist:
                if packager.lower().find(warnPackager) > -1:
                    if packager not in warnPackages:
                        warnPackages[packager] = []
                    warnPackages[packager].append(pkg)

        if len(warnPackages) > 0:
            print()
            print('=== apt-blacklist-warning ===')
            for packager in sorted(warnPackages):
                print('Package(s) %s is changed by maintainer in warning list: "%s"' % (', '.join(warnPackages[packager]), packager))
            print()

    if os.path.exists(packagerWatchlistPath):
        with open(packagerWatchlistPath) as f:
            packagerWatchlist = [p.strip() for p in f.readlines() if len(p.strip()) > 0]

        watchPackages = {}    # key: (oldpackager,newpackager), value: list of packages
        for pkg, newpackager, oldpackager in pkgInfos:
            for watchPackager in packagerWatchlist:
                if oldpackager and (oldpackager.lower().find(watchPackager) > -1) and (newpackager.lower() != oldpackager.lower()):
                    key = (oldpackager,newpackager)
                    if key not in watchPackages:
                        watchPackages[key] = []
                    watchPackages[key].append(pkg)

        if len(watchPackages) > 0:
            print()
            print('=== apt-blacklist-watch ===')
            for oldpackager, newpackager in sorted(watchPackages):
                print('Note: package(s) %s was built by %s (after %s)' % (', '.join(watchPackages[(oldpackager,newpackager)]), newpackager, oldpackager))
            print()

    if len(badPackages) > 0:
        print()
        print('=== apt-blacklist ===')
        for packager in sorted(badPackages):
            print('Package(s) %s is blacklisted: "%s"' % (', '.join(badPackages[packager]), packager))
        print()
        sys.exit(1)
