#!/usr/bin/env python3
"""show dirty git repos"""

from __future__ import division, print_function

from colorama import Fore
from pathlib import Path

import contextlib
import os
import re
import subprocess

import click


# TODO config file (and defaults here)
IGNORES = [
    r"\.sync",
    r"\.git/modules",  # XXX check this again
    r"\.local/share/containers/storage",
]


def git_directories(startdir) -> Path:
    for dirpath, dirnames, _ in os.walk(startdir):
        if any(re.search(ignore, dirpath) for ignore in IGNORES):
            continue
        if set(["info", "objects", "refs"]).issubset(set(dirnames)):
            yield Path(dirpath)


@contextlib.contextmanager
def working_directory(directory: Path):
    saved_cwd = os.getcwd()
    os.chdir(directory)
    yield
    os.chdir(saved_cwd)


@click.command
@click.argument(
    "topdirs", nargs=-1, type=click.Path(exists=True, file_okay=False, path_type=Path)
)
@click.option(
    "-l",
    "--list",
    "list_",
    is_flag=True,
    default=False,
    help="Just list the dirty directories",
)
def search_dirty(topdirs, list_):
    """Search for dirty git working directories in TOPDIRS"""
    if len(topdirs) == 0:
        topdirs = [Path(".")]

    for topdir in topdirs:
        for git_directory in git_directories(topdir):
            # technically, we could have a different GIT_DIR than ".git", but this script
            # assumes ".git".
            if git_directory.parts[-1] != ".git":
                continue
            work_tree_directory = git_directory.parent

            with working_directory(work_tree_directory):
                try:
                    out = subprocess.check_output(['git', 'status', '-s'], stderr=subprocess.STDOUT)
                    if len(out) > 0:
                        if not list_:
                            print(
                                f"== {work_tree_directory}\n" f"{out.decode('utf-8')}"
                            )
                        else:
                            print(work_tree_directory)
                except subprocess.CalledProcessError as e:
                    print(
                        (
                            Fore.RED + "git status is unhappy with {}" + Fore.RESET
                        ).format(work_tree_directory)
                    )
                    print(e.output)


if __name__ == "__main__":
    search_dirty()