#!/usr/bin/python

import pathlib
import re
import urllib

import click
import git


all_modules = {
    '389-ds': ['1.4'],
    'ant': ['1.10'],
    'container-tools': ['rhel8', '1.0', '2.0', '3.0', '4.0'],
    'freeradius': ['3.0'],
    'gimp': ['2.8'],
    'go-toolset': ['rhel8'],
    'httpd': ['2.4'],
    'idm': ['DL1', 'client'],
    'inkscape': ['0.92.3'],
    'javapackages-runtime': ['201801'],
    'javapackages-tools': ['201801'],
    'jmc': ['rhel8'],
    'libselinux-python': ['2.8'],
    'llvm-toolset': ['rhel8'],
    'log4j': ['2'],
    'mailman': ['2.1'],
    'mariadb': ['10.3', '10.5'],
    'maven': ['3.5', '3.6'],
    'mercurial': ['4.8'],
    'mod_auth_openidc': ['2.3'],
    'mysql': ['8.0'],
    'nginx': ['1.14', '1.16', '1.18', '1.20'],
    'nodejs': ['10', '12', '14', '16', '18'],
    'parfait': ['0.5'],
    'perl': ['5.24', '5.26', '5.30', '5.32'],
    'perl-App-cpanminus': ['1.7044'],
    'perl-DBD-MySQL': ['4.046'],
    'perl-DBD-Pg': ['3.7'],
    'perl-DBD-SQLite': ['1.58'],
    'perl-DBI': ['1.641'],
    'perl-FCGI': ['0.78'],
    'perl-IO-Socket-SSL': ['2.066'],
    'perl-YAML': ['1.24'],
    'perl-libwww-perl': ['6.34'],
    'php': ['7.2', '7.3', '7.4', '8.0'],
    'pki-core': ['10.6'],
    'pki-deps': ['10.6'],
    'pmdk': ['1_fileformat_v6'],
    'postgresql': ['9.6', '10', '12', '13'],
    'python27': ['2.7'],
    'python36': ['3.6'],
    'python38': ['3.8'],
    'python39': ['3.9'],
    'redis': ['5', '6'],
    'rhn-tools': ['1.0'],
    'ruby': ['2.5', '2.6', '2.7', '3.0', '3.1'],
    'rust-toolset': ['rhel8'],
    'satellite-5-client': ['1.0'],
    'scala': ['2.10'],
    'squid': ['4'],
    'subversion': ['1.10', '1.14'],
    'swig': ['3.0', '4.0'],
    'varnish': ['6'],
    'virt': ['rhel']
}


@click.command()
@click.option(
    '-b', '--base',
    default=pathlib.Path.home() / 'packaging' / 'centos' / 'modules',
    help='parent directory for module checkouts',
)
@click.option(
    '-p', '--pull',
    is_flag=True,
    help='run `git pull` on each module checkout',
)
@click.argument('module-names', required=False, nargs=-1)
def main(base, pull, module_names):
    """
    Show status of modulemd files for all CentOS modules.
    """

    if module_names:
        target_modules = {
            name: streams
            for name, streams in all_modules.items()
            if name in module_names
        }
    else:
        target_modules = all_modules

    for name, streams in target_modules.items():
        # In click 8+, the base option is forced to be a string.  Change it
        # back to a Path before attempting the "/" operation.  A better way to
        # fix this would be to set the type for the base option:
        #
        # type=click.Path(exists=True, path_type=pathlib.Path)
        #
        # However, that would mean everyone running the script needs to be on
        # click 8+, and EL8 only has click 6.
        #
        # https://click.palletsprojects.com/en/8.0.x/api/?highlight=path#click.Path
        repo_path = pathlib.Path(base) / name

        if repo_path.is_dir():
            # if the directory exists, assume it's a clone of the git repo
            repo = git.Repo(repo_path)
        else:
            # if the directory doesn't exist, clone it
            repo = git.Repo.clone_from(f'ssh://git@git.centos.org/modules/{name}.git', repo_path)

        fetch_failed = False
        if pull:
            try:
                repo.remotes.origin.fetch()
            except git.exc.GitCommandError:
                fetch_failed = True
                # TODO: do at least one retry

        for stream in streams:
            click.echo(f'{name:<22}{stream:<17}', nl=False)

            if fetch_failed:
                click.secho('(failed to fetch)', fg='yellow')
                continue
                
            for prefix in ( 'c8' , 'c8s' ):
                branch = f'{prefix}-stream-{stream}'
                try:
                    repo.git.switch(branch)
                except git.exc.GitCommandError:
                    click.secho(f'{prefix} ', fg='black', nl=False)
                    continue

                repo.git.merge(f'origin/{branch}')

                # check for a modulemd file to see if there have been commits
                # since we last transmodrified
                modulemd = repo_path / f'{name}.yaml'

                # check the tag to see if we have a bogus push
                tag = repo.git.describe(tags=True, abbrev=0)
                _, _, nvr = urllib.parse.unquote(tag).split('/')
                _, _, release = nvr.rsplit('-', maxsplit=2)

                if modulemd.exists():
                    color = 'green'
                elif release.startswith('82') or release.startswith('801') or release.startswith('802'):
                    color = 'magenta'
                else:
                    color = 'red'

                click.secho(f'{prefix} ', fg=color, nl=False)

                repo.git.switch('-')

            click.echo()


if __name__ == '__main__':
    main()
