#!/usr/bin/env python3

# Copyright (C) 2020-2025 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
# GCC 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, or (at your option) any later
# version.
#
# GCC 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 GCC; see the file COPYING3.  If not see
# <http://www.gnu.org/licenses/>.

import os
import re
import sys
from itertools import takewhile

from dateutil.parser import parse

from git_commit import GitCommit, GitInfo, decode_path

from unidiff import PatchSet, PatchedFile

DATE_PREFIX = 'Date: '
FROM_PREFIX = 'From: '
SUBJECT_PREFIX = 'Subject: '
subject_patch_regex = re.compile(r'^\[PATCH( \d+/\d+)?\] ')
unidiff_supports_renaming = hasattr(PatchedFile(), 'is_rename')


class GitEmail(GitCommit):
    def __init__(self, filename):
        self.filename = filename
        date = None
        author = None
        subject = ''

        subject_last = False
        with open(self.filename, newline='\n') as f:
            data = f.read()
            diff = PatchSet(data)
            lines = data.splitlines()
        lines = list(takewhile(lambda line: line != '---', lines))
        for line in lines:
            if line.startswith(DATE_PREFIX):
                date = parse(line[len(DATE_PREFIX):])
            elif line.startswith(FROM_PREFIX):
                author = GitCommit.format_git_author(line[len(FROM_PREFIX):])
            elif line.startswith(SUBJECT_PREFIX):
                subject = line[len(SUBJECT_PREFIX):]
                subject_last = True
            elif subject_last and line.startswith(' '):
                subject += line
            elif line == '':
                break
            else:
                subject_last = False

        if subject:
            subject = subject_patch_regex.sub('', subject)
        header = list(takewhile(lambda line: line != '', lines))
        # Note: commit message consists of email subject, empty line, email body
        message = [subject] + lines[len(header):]

        modified_files = []
        for f in diff:
            # Strip "a/" and "b/" prefixes
            source = decode_path(f.source_file)[2:]
            target = decode_path(f.target_file)[2:]

            if f.is_added_file:
                t = 'A'
            elif f.is_removed_file:
                t = 'D'
            elif unidiff_supports_renaming and f.is_rename:
                # Consider that renamed files are two operations: the deletion
                # of the original name and the addition of the new one.
                modified_files.append((source, 'D'))
                t = 'A'
            else:
                t = 'M'
            modified_files.append((target if t != 'D' else source, t))
        git_info = GitInfo(None, date, author, message, modified_files)
        super().__init__(git_info, commit_to_info_hook=None)


def show_help():
    print("""usage: git_email.py [--help] [patch file ...]

Check git ChangeLog format of a patch

With zero arguments, process every patch file in the
./patches directory.
With one argument, process the named patch file.

Patch files must be in 'git format-patch' format.""")
    sys.exit(0)


if __name__ == '__main__':
    if len(sys.argv) == 2 and (sys.argv[1] == '-h' or sys.argv[1] == '--help'):
        show_help()

    if len(sys.argv) == 1:
        allfiles = []
        for root, _dirs, files in os.walk('patches'):
            for f in files:
                full = os.path.join(root, f)
                allfiles.append(full)

        success = 0
        for full in sorted(allfiles):
            email = GitEmail(full)
            print(email.filename)
            if email.success:
                success += 1
                print('  OK')
                for warning in email.warnings:
                    print('  WARN: %s' % warning)
            else:
                for error in email.errors:
                    print('  ERR: %s' % error)

        print()
        print('Successfully parsed: %d/%d' % (success, len(allfiles)))
    else:
        email = GitEmail(sys.argv[1])
        if email.success:
            print('OK')
            email.print_output()
            email.print_warnings()
        else:
            if not email.info.lines:
                print('Error: patch contains no parsed lines', file=sys.stderr)
            email.print_errors()
            sys.exit(1)
