# python-helpers -- lintian check script -*- perl -*-
#
# Copyright © 2011 Jakub Wilk
#
# 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 2 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, you can find it on the World Wide
# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
# MA 02110-1301, USA.

package Lintian::helpers;

use strict;
use warnings;

use Lintian::Tags qw(tag);
use Util;

# FIXME: copied from checks/files
my @METAPKG_REGEX =
    (qr/meta[ -]?package/, qr/dummy/,
     qr/(?:dependency|empty|transitional|virtual) package/);

sub run {

    my ($pkg, $type, $info) = @_;
    if ($type eq 'source') {
        return run_source(@_);
    } else {
        return run_binary(@_);
    }

}

sub run_source {

    my ($pkg, $type, $info) = @_;

    return if $pkg =~ m/^python(?:\d\.\d)?$/;
    return if $pkg =~ m/^python\d?-(?:stdlib-extensions|profiler|old-doctools)$/;
    return if $pkg =~ m/^python-defaults$/;
    return if $pkg =~ m/^python-(?:central|support)$/;

    my %python_depends = ();

    my $binpkgs = $info->binaries;
    for my $binpkg (keys %$binpkgs) {
        if ($info->binary_relation($binpkg, 'all')->implies('${python:Depends}')) {
            $python_depends{$binpkg} = 1;
        } elsif ($binpkg =~ /^python-/) {
            my $description = $info->binary_field($binpkg, 'description') // '';
            my $metapkg = 0;
            for my $regex (@METAPKG_REGEX) {
                # FIXME: this duplicates logic checks/files logic
                if ($description =~ /$regex/) {
                    $metapkg = 1;
                    last;
                }
            }
            tag 'python-module-but-no-python-depends', $binpkg
                unless $binpkg =~ /-(dbg|doc|dev)$/ or $metapkg;
        }
    }

    if (keys %python_depends) {
        my $rules = $info->debfiles('rules');
        if (-l $rules or not -f $rules) {
            return;
        }
        open(RULES, '<', $rules) or fail("cannot open rules: $!");
        while (<RULES>) {
            while (s,\\$,, and defined (my $cont = <RULES>)) {
                $_ .= $cont;
            }
            next if /^\s*\#/;
            if (m,\bpython:Depends\b,) {
                # generated by hand
                %python_depends = ();
                last;
            } elsif (m,\bdh_(?:python2?|pysupport|pycentral)\b,) {
                # generated by explicit call to a Python helper
                %python_depends = ();
                last;
            } elsif (m,^include\s+/usr/share/cdbs/1/class/python-,m) {
                # generated by Python helper via CDBS
                %python_depends = ();
                last;
            } elsif (m,\bdh\b,) {
                # Lintian proper already takes care of this part.
                %python_depends = ();
                last;
            }
        }
        close(RULES);
        if (keys %python_depends) {
            tag 'python-depends-but-no-python-helper', keys %python_depends;
        }
    }

}

sub run_binary {

    my ($pkg, $type, $info) = @_;
    my $pycentral_data_path = "usr/share/pyshared-data/$pkg";
    my $pycentral_data_stat = $info->index->{$pycentral_data_path};
    if (defined($pycentral_data_stat) and $pycentral_data_stat->{'type'} eq '-') {
        my %files = ();
        open(PYSHARED, '<', $info->unpacked($pycentral_data_path)) or fail("cannot open python-central metadata: $!");
        my $files_section = 0;
        while (<PYSHARED>) {
            if (m,^\[files\]$,) {
                $files_section = 1;
                next;
            } elsif (m,^\[,) {
                $files_section = 0;
                next;
            } elsif ($files_section) {
                if (m,^/(.+)=([fdYN])$,) {
                    my ($filename, $type) = ($1, $2);
                    $files{$filename} = 1;
                } else {
                    tag 'cannot-parse-python-central-metadata', "line $.: $_";
                    last;
                }
            }
        }
        close(PYSHARED);
        while (my ($filename, $type) = each %files) {
            my $fileinfo =
                $info->index->{$filename} ||
                $info->index->{"$filename/"};
            if (not defined $fileinfo) {
                tag 'python-central-metadata-for-missing-files', $filename;
            }
        }
    }

}

1;

# Local Variables:
# indent-tabs-mode: nil
# cperl-indent-level: 4
# End:
# vim: syntax=perl sw=4 sts=4 sr et
