#!/usr/lib/rads/venv/bin/python3
"""Mass MyISAM table fixer"""
# 9/19/14 Vanessa Vasile vanessav@inmotion.net
# This script does not require MySQL to be running

import glob
from pathlib import Path
import argparse
import subprocess


def iter_databases():
    """Iterate over folders in /var/lib/mysql"""
    # Generally speaking, every folder in datadir should be a database
    # if it's not, no biggie
    for entry in Path('/var/lib/mysql').iterdir():
        if entry.is_dir():
            yield entry.name


def repair_database(database: str, tmpdir: str) -> bool:
    """Runs a repair on a table"""
    Path(tmpdir).mkdir(mode=0o755, exist_ok=True, parents=True)
    # List MyISAM tables
    if tables := glob.glob(f'/var/lib/mysql/{database}/*.MYI'):
        print(f'Fixing {len(tables)} tables in database {database}')
    else:
        print('No MyISAM tables to fix in database', database)
        return True
    repaired = True
    for table in tables:
        print("    Fixing %s" % table)
        try:
            subprocess.run(
                ['myisamchk', '-r', '-q', '-t', tmpdir, table],
                check=True,
                stderr=subprocess.DEVNULL,
                stdout=subprocess.DEVNULL,
            )
        except subprocess.CalledProcessError:
            repaired = False
    return repaired


def main():
    """Default function"""
    args = parse_args()
    if args.repair_all is True:
        # Get a list of databases
        for dbname in iter_databases():
            repair_database(dbname, args.tmpdir)
    if args.database:
        repair_database(args.database, args.tmpdir)


def parse_args():
    """Defines valid command line options"""
    parser = argparse.ArgumentParser(description=__doc__)
    group = parser.add_mutually_exclusive_group(required=True)
    # fmt: off
    group.add_argument(
        '-a', '--all', dest='repair_all', action='store_true',
        help="Repair all databases",
    )
    group.add_argument(
        '-d', '--database', dest='database',
        help="The name of a specific database to repair",
    )
    parser.add_argument('-t', '--tmpdir', dest='tmpdir', default='/root/tmp')
    # fmt: on
    return parser.parse_args()


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        pass
