1
0
Fork 0
env/.local/bin/stignore-gen

106 lines
3.0 KiB
Python
Executable File

#!/usr/bin/env python3
from typing import Optional, Iterable
from pathlib import Path
from argparse import ArgumentParser
from os import SEEK_END
def check_line(path: Path, line: str) -> bool:
if not path.exists():
return False
elif path.is_file():
with open(path, "r") as f:
return line in f.read()
return True
def write_line(path: Path, line: str):
with open(path, "w+") as f:
f.seek(0, SEEK_END)
if f.tell() > 0:
f.seek(f.tell() - 1, 0)
last_char = f.read()
if last_char != "\n":
f.write("\n")
f.write(line + "\n")
def resolve(parent: Path, line: str) -> Iterable[str]:
if line.startswith("#") or len(line.strip()) == 0:
return
negate = line.startswith("!")
path = line.removeprefix("!").strip()
absolute = "/" in line.removesuffix("/")
prefix = ""
if negate:
prefix += "!"
else:
# gitignore lines to recursively delete
if (
"target" in path
or "generated" in path
or "output" in path
or "cache" in path
or "build" in path
or "node_modules" in path
):
prefix += "(?d)"
# gitignore lines to exclude
if "[._]" in path:
return
yield "// " + str(parent) + ": " + line.strip()
if absolute:
yield prefix + str(parent) + "/" + path.removeprefix("/")
else:
yield prefix + str(parent) + "/" + path.removeprefix("/")
yield prefix + str(parent) + "/**/" + path.removeprefix("/")
def scan(directory: Path) -> Iterable[str]:
# Useful defaults
yield "// Always included"
yield "(?d)node_modules"
# Scan .gitignore
for path in directory.rglob(".gitignore"):
parent = path.parent
if not path.is_file():
continue
with open(path, "r") as f:
for line in f:
yield from resolve(parent, line)
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument(
"-w", "--write", action="store_const", const=True, default=False
)
parser.add_argument(
"path", type=Path, nargs="*", default=[Path(".")]
)
args = parser.parse_args()
if args.write:
ignore = Path(".stignore")
ignore_gen = Path(".stignore.gen")
with open(ignore_gen, "w") as f:
for path in args.path:
for line in scan(Path(path)):
f.write(line + "\n")
ignore_line = "#include " + str(ignore_gen)
if not check_line(ignore, ignore_line):
print("WARNING: .stignore does not exist or is missing the include line")
response = input("append an include line for the generated file? (y/n) ")
if response.lower() == "y":
write_line(ignore, ignore_line)
else:
for path in args.path:
for line in scan(Path(path)):
print(line)
# vim: set et ts=4 sw=4: