diff options
Diffstat (limited to 'archived/projt-launcher/tools')
| -rwxr-xr-x | archived/projt-launcher/tools/generate_todo_report.py | 194 | ||||
| -rw-r--r-- | archived/projt-launcher/tools/get_commits.py | 37 |
2 files changed, 231 insertions, 0 deletions
diff --git a/archived/projt-launcher/tools/generate_todo_report.py b/archived/projt-launcher/tools/generate_todo_report.py new file mode 100755 index 0000000000..6fc6f04b94 --- /dev/null +++ b/archived/projt-launcher/tools/generate_todo_report.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python3 +""" +Scan repository for TODO/FIXME comments and generate a Markdown report. + +Usage: python tools/generate_todo_report.py [--exclude-dir dir1,dir2] [--no-default-excludes] +Produces: docs/TODO_FIXME_REPORT.md +""" +import argparse +import os +import re +import sys +from pathlib import Path + +SCRIPT_DIR = Path(__file__).resolve().parent +ROOT = None + +DEFAULT_EXCLUDED_DIRS = { + '.git', + 'build', + 'qt', + 'toolchain', + 'ptinstaller', + 'docs', + 'tools', + 'gamemode', + 'libpng', + 'zlib', + 'quazip', + 'node_modules', + 'tomlplusplus', + 'json', + 'libqrencode', + 'extra-cmake-modules', + '.gitignore', + '.github', + 'cmark', + 'flatpak', + 'bzip2', + 'ci', +} + +PATTERN = re.compile(r"\b(TODO|FIXME)\b", re.IGNORECASE) + +def is_text_file(path: Path) -> bool: + try: + with open(path, 'rb') as f: + chunk = f.read(4096) + if b"\0" in chunk: + return False + except Exception: + return False + return True + +def classify(text: str) -> str: + t = text.lower() + hints_complex = [ + 'design', 'refactor', 'race', 'concurrent', 'abort', 'retry', 'performance', + 'memory', 'security', 'validate', 'schema', 'generic', 'nuke', 'inefficient', + 'algorithm', 'thread', 'blocking', 'async', 'validate', 'jwt', 'schema', 'hack' + ] + hints_trivial = ['typo', 'wrap', 'link', 'format', 'docs', 'documentation', 'spell', 'grammar', 'rename', 'cleanup', 'whitespace'] + if any(h in t for h in hints_trivial): + return 'trivial' + if any(h in t for h in hints_complex): + return 'complex' + # Context-sensitive keyword matching for implementable items + implementable_keywords = ['should', 'maybe', 'add', 'implement', 'todo:', 'need', 'missing', 'want', 'consider', 'allow', 'support', 'fixme', 'refactor', 'update', 'remove', 'bug'] + if any(k in t for k in implementable_keywords): + return 'implementable' + return 'unknown' + +def scan(root: Path, excluded_dirs): + results = [] + + for p in root.rglob('*'): + # Skip if any parent directory is in the excluded list + if any(part in excluded_dirs for part in p.parts): + continue + + if p.is_dir(): + continue + + if p.suffix in {'.patch', '.diff'}: + continue + + if not is_text_file(p): + continue + + try: + text = p.read_text(encoding='utf-8') + except Exception: + try: + text = p.read_text(encoding='latin-1') + except Exception: + continue + + lines = text.splitlines() + for i, line in enumerate(lines, start=1): + if PATTERN.search(line): + before = '\n'.join(lines[max(0, i-3):i-1]) + after = '\n'.join(lines[i:i+2]) + whole = '\n'.join(lines[max(0, i-3):min(len(lines), i+2)]) + tag = PATTERN.search(line).group(1) + cls = classify(line + ' ' + whole) + results.append({ + 'path': str(p.relative_to(root)), + 'line': i, + 'tag': tag, + 'text': line.strip(), + 'context': whole, + 'classification': cls, + }) + return results + +def generate_md(results, out_path: Path): + out_path.parent.mkdir(parents=True, exist_ok=True) + by_class = {} + for r in results: + by_class.setdefault(r['classification'], []).append(r) + + with open(out_path, 'w', encoding='utf-8') as f: + f.write('# TODO/FIXME Report\n\n') + f.write('Generated by `tools/generate_todo_report.py`.\n\n') + f.write('Summary:\n\n') + for k in sorted(by_class.keys()): + f.write(f'- **{k}**: {len(by_class[k])} items\n') + f.write('\n---\n\n') + + for k in sorted(by_class.keys()): + f.write(f'## {k.capitalize()} ({len(by_class[k])})\n\n') + for item in by_class[k]: + f.write(f'- **{item["tag"]}** in `{item["path"]}`:{item["line"]} — {item["text"]}\n') + f.write('```\n') + f.write(item['context'] + '\n') + f.write('```\n\n') + + f.write('\n---\n\n') + f.write('Notes:\n') + f.write('- `trivial`: likely simple fixes (typos, docs).\n') + f.write('- `implementable`: small code changes may resolve.\n') + f.write('- `complex`: needs design review or larger refactor.\n') + f.write('- `unknown`: manual review recommended.\n') + + print(f'Wrote report to {out_path}') + +def parse_excludes(exclude_args): + excludes = set() + for item in exclude_args or []: + for part in item.split(','): + part = part.strip() + if part: + excludes.add(part) + return excludes + +def main(): + parser = argparse.ArgumentParser(description="Generate TODO/FIXME report for the repository.") + parser.add_argument( + "--exclude-dir", + action="append", + default=[], + help="Directory name(s) to exclude. Repeat or provide comma-separated values.", + ) + parser.add_argument( + "--no-default-excludes", + action="store_true", + help="Do not use the built-in excluded directory list.", + ) + parser.add_argument( + "--root", + default=None, + help="Root directory to scan (defaults to $PWD).", + ) + parser.add_argument( + "--output", + default=None, + help="Output markdown path (defaults to <root>/docs/TODO_FIXME_REPORT.md).", + ) + args = parser.parse_args() + + # Use PWD to match user's shell location (avoids resolving symlinks to Trash/cloud storage) + root_path_str = args.root or os.getenv('PWD') or os.getcwd() + root = Path(root_path_str) + out_path = Path(args.output) if args.output else root / "docs" / "TODO_FIXME_REPORT.md" + + excludes = set() + if not args.no_default_excludes: + excludes.update(DEFAULT_EXCLUDED_DIRS) + excludes.update(parse_excludes(args.exclude_dir)) + + results = scan(root, excludes) + generate_md(results, out_path) + +if __name__ == '__main__': + main() diff --git a/archived/projt-launcher/tools/get_commits.py b/archived/projt-launcher/tools/get_commits.py new file mode 100644 index 0000000000..0d4b403e47 --- /dev/null +++ b/archived/projt-launcher/tools/get_commits.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +import requests +from bs4 import BeautifulSoup +import re + +URL = "https://sourceware.org/git/bzip2.git/log/?ofs=0" + +HEADERS = { + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " + "(KHTML, like Gecko) Chrome/120.0 Safari/537.36", + "Accept": "text/html", +} + +r = requests.get(URL, headers=HEADERS, timeout=30) +r.raise_for_status() + +soup = BeautifulSoup(r.text, "html.parser") + +commits = [] +seen = set() + +for a in soup.select('a[href*="commit/?id="]'): + href = a.get("href", "") + commit = href.split("commit/?id=")[-1] + if re.fullmatch(r"[0-9a-f]{7,40}", commit): + if commit not in seen: + commits.append(commit) + seen.add(commit) + +# newest → oldest geliyor +commits.reverse() + +if not commits: + raise RuntimeError("Commit bulunamadı — sourceware HTML hâlâ filtreliyor") + +for c in commits: + print(c)
\ No newline at end of file |
