#!/usr/bin/python3

# vim: fileencoding=utf-8
#
# Copyright (C) 2014       Google, Inc.
#
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

"""Check the format and dumpability of debian/copyright filenames on stdin.

Usage:

    find /tmp/packages -type f -name copyright | ./check_parse_and_dump.py

The --suppress_warnings and --summary flags can be used to make the program
output less verbose.
"""

import argparse
import codecs
import sys
from typing import Any
import warnings

from debian import copyright


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser()
    parser.add_argument('--summary', action='store_true',
                        help='Whether to print only a summary')
    parser.add_argument('--suppress_warnings', action='store_true',
                        help='Whether to suppress copyright warnings')
    return parser.parse_args()


def main() -> None:
    args = parse_args()

    if args.suppress_warnings:
        warnings.filterwarnings('ignore', module='debian.copyright')

    problems: dict[tuple[int, str], list[tuple[str, Any]]] = {}

    total = 0
    for filename in sys.stdin:
        total += 1
        filename = filename.rstrip()
        with open(filename, encoding='utf-8') as f:
            try:
                c = copyright.Copyright(f)
            except Exception as e:
                problems.setdefault((1, 'Parse failures'), []).append(
                    (filename, e))
                continue

            try:
                c.dump()
            except Exception as e:
                problems.setdefault((2, 'Dump failures'), []).append(
                    (filename, e))

            if not c.header.known_format():
                problems.setdefault((3, 'Unknown format'), []).append(
                    (filename, c.header.format))

            invalid_globs = []
            globs_with_leading_dot_slash = []
            globs_with_trailing_comma = []
            globs_with_double_star = []
            for p in c.all_files_paragraphs():
                try:
                    p.files_pattern()
                except Exception as e:
                    invalid_globs.append(e)
                for glob in p.files:
                    if glob.startswith('./'):
                        globs_with_leading_dot_slash.append(glob)
                    if glob.endswith(','):
                        globs_with_trailing_comma.append(glob)
                    if '**' in glob:
                        globs_with_double_star.append(glob)

            if invalid_globs:
                problems.setdefault((4, 'Invalid glob'), []).append(
                    (filename, invalid_globs))
            if globs_with_leading_dot_slash:
                problems.setdefault((5, 'Globs with leading ./'), []).append(
                    (filename, globs_with_leading_dot_slash))
            if globs_with_trailing_comma:
                problems.setdefault((6, 'Globs with trailing ,'), []).append(
                    (filename, globs_with_trailing_comma))
            if globs_with_double_star:
                problems.setdefault((7, 'Globs with **'), []).append(
                    (filename, globs_with_double_star))

    f_out = codecs.getwriter(encoding='utf-8')(sys.stdout)
    for (_, heading), details in sorted(problems.items()):
        f_out.write(f"\n{heading}: ({len(details)} / {total})\n")
        if not args.summary:
            for filename, problem in details:
                f_out.write(f" {filename}: {problem}\n")


if __name__ == '__main__':
    main()
