#!/usr/bin/env python3
# Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

import subprocess
import sys
import re
import r8_release


class Branch:

    def __init__(self, name, first, last=None):
        self.name = name
        self.first = first
        self.last = last  # optional last for testing purposes.

    def origin(self):
        return "origin/%s" % self.name

    def last_or_origin(self):
        return self.last if self.last else self.origin()

    def __str__(self):
        return self.name


# The initial commit is the furthest back we need to search on main.
# Currently, it is the merge point of main onto 4.0.23-dev
MAIN = Branch('main', 'a2e203580aa00a36f85cd68d3d584b97aef34d59')
OLDEST_BRANCH_VERSION = (4, 0)
DEV_BRANCH_VERSION = [int(s) for s in r8_release.R8_DEV_BRANCH.split('.')]

# List of change ids that should not be reported.
IGNORED = ['I92d7bf3afbf609fdea21683941cfd15c90305cf2']

VERBOSE = False


# Helper to call and decode a shell command.
def run_cmd(cmd):
    if VERBOSE:
        print(' '.join(cmd))
    return subprocess.check_output(cmd).decode('UTF-8')


# Comparator on major and minor branch versions.
def branch_version_less_than(b1, b2):
    if b1[0] < b2[0]:
        return True
    if b1[0] == b2[0] and b1[1] < b2[1]:
        return True
    return False


# Find all release branches between OLDEST_BRANCH and DEV_BRANCH
def get_release_branches():
    # Release branches are assumed to be of the form 'origin/X.Y'
    out = run_cmd(['git', 'branch', '-r', '-l'])
    pattern = re.compile('origin/(\d+).(\d+)')
    releases = []
    for line in out.split('\n'):
        m = pattern.search(line.strip())
        if m:
            major = m.group(1)
            minor = m.group(2)
            if major and minor:
                candidate = (int(major), int(minor))
                if branch_version_less_than(candidate, OLDEST_BRANCH_VERSION):
                    continue
                if branch_version_less_than(candidate, DEV_BRANCH_VERSION):
                    releases.extend(find_dev_cutoff(candidate))
    return releases


# Find the most recent commit hash that is for a -dev version.
# This is the starting point for the map of commits after cutoff from main.
def find_dev_cutoff(branch_version):
    out = run_cmd([
        'git',
        'log',
        'origin/%d.%d' % branch_version,
        '--grep',
        'Version .*-dev',
        '--pretty=oneline',
    ])
    # Format of output is: <hash> Version <version>-dev
    try:
        hash = out[0:out.index(' ')]
        return [Branch('%d.%d' % branch_version, hash)]
    except ValueError:
        throw_error("Failed to find dev cutoff for branch %d.%d" %
                    branch_version)


# Build a map from each "Change-Id" hash to the hash of its commit.
def get_change_id_map(branch):
    out = run_cmd(
        ['git', 'log',
         '%s..%s' % (branch.first, branch.last_or_origin())])
    map = {}
    current_commit = None
    for line in out.split('\n'):
        if line.startswith('commit '):
            current_commit = line[len('commit '):]
            assert len(current_commit) == 40
        elif line.strip().startswith('Change-Id: '):
            change_id = line.strip()[len('Change-Id: '):]
            assert len(change_id) == 41
            map[change_id] = current_commit
    return map


# Check if a specific commit is present on a specific branch.
def is_commit_in(commit, branch):
    out = run_cmd(
        ['git', 'branch', '-r',
         branch.origin(), '--contains', commit])
    return out.strip() == branch.origin()


def main():
    found_errors = False
    # The main map is all commits back to the "init" point.
    main_map = get_change_id_map(MAIN)
    # Compute the release branches.
    release_branches = get_release_branches()
    # Populate the release maps with all commits after the last -dev point.
    release_maps = {}
    for branch in release_branches:
        release_maps[branch.name] = get_change_id_map(branch)
    # Each branch is then compared forwards with each subsequent branch.
    for i in range(len(release_branches)):
        branch = release_branches[i]
        newer_branches = release_branches[i + 1:]
        if (len(newer_branches) == 0):
            print('Last non-dev release branch is %s, nothing to check.' %
                  branch)
            continue
        print('Checking branch %s.' % branch)
        changes = release_maps[branch.name]
        cherry_picks_count = 0
        for change in changes.keys():
            is_cherry_pick = False
            missing_from = None
            commit_on_main = main_map.get(change)
            for newer_branch in newer_branches:
                if change in release_maps[newer_branch.name]:
                    is_cherry_pick = True
                    # If the change is in the release mappings check for holes.
                    if missing_from:
                        found_errors |= change_error(
                            change, 'Error: missing Change-Id %s on branch %s. '
                            'Is present on %s and again on %s.' % (
                                change,
                                missing_from,
                                branch,
                                newer_branch,
                            ))
                elif commit_on_main:
                    is_cherry_pick = True
                    # The change is not in the non-dev part of the branch, so we need to
                    # check that the fork from main included the change.
                    if not is_commit_in(commit_on_main, newer_branch):
                        found_errors |= change_error(
                            change, 'Error: missing Change-Id %s on branch %s. '
                            'Is present on %s and on main as commit %s.' %
                            (change, newer_branch, branch, commit_on_main))
                else:
                    # The change is not on "main" so we just record for holes on releases.
                    missing_from = newer_branch
            if is_cherry_pick:
                cherry_picks_count += 1
        print('Found %d cherry-picks (out of %d commits).' %
              (cherry_picks_count, len(changes)))

    if found_errors:
        return 1
    return 0


def change_error(change, msg):
    if change in IGNORED:
        return False
    error(msg)
    return True


def throw_error(msg):
    raise ValueError(msg)


def error(msg):
    print(msg, file=sys.stderr)


if __name__ == '__main__':
    sys.exit(main())
