You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
2.4 KiB
Python

#!/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()