diff --git a/git_context/__init__.py b/git_context/__init__.py index 92e2b81..da61cca 100755 --- a/git_context/__init__.py +++ b/git_context/__init__.py @@ -4,7 +4,7 @@ Dump project structure, git log, file contents, and branch topology in one optimized prompt-ready block. -Usage: git context [--depth N] [--files] [--log N] [--output file] [--dir ] +Usage: git context [--depth N] [--files] [--log N] [--output file] [--dir ] [--json] """ import argparse @@ -12,6 +12,7 @@ import subprocess import sys import fnmatch +import json from pathlib import Path from datetime import datetime @@ -128,6 +129,7 @@ def main(): p.add_argument('--log', type=int, default=20, help='Number of recent commits (default: 20, 0=skip)') p.add_argument('--output', '-o', help='Write to file instead of stdout') p.add_argument('--dir', default=os.getcwd(), help='Target directory (default: cwd)') + p.add_argument('--json', action='store_true', help='Output in JSON format') args = p.parse_args() target = os.path.abspath(args.dir) @@ -136,54 +138,74 @@ def main(): sys.exit(1) repo_name = os.path.basename(target) - sections = [] - sections.append(f"# git-context: {repo_name}") - sections.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") - sections.append(f"Path: {target}") - sections.append("") - - # Git info - branch = run(["git", "rev-parse", "--abbrev-ref", "HEAD"], target) - remote = run(["git", "remote", "get-url", "origin"], target) - sections.append(f"## Git Info\n- Branch: `{branch}`") - sections.append(f"- Remote: {remote}") + + # Collect data + git_info = { + "branch": run(["git", "rev-parse", "--abbrev-ref", "HEAD"], target), + "remote": run(["git", "remote", "get-url", "origin"], target), + } has_unstaged = run(["git", "diff", "--stat"], target) has_staged = run(["git", "diff", "--cached", "--stat"], target) - status = "" - if has_unstaged: status += f"\n- Unstaged changes: {has_unstaged.split(chr(10))[-1]}" - if has_staged: status += f"\n- Staged changes: {has_staged.split(chr(10))[-1]}" + status_msg = "" + if has_unstaged: status_msg += f"Unstaged changes: {has_unstaged.split(chr(10))[-1]} " + if has_staged: status_msg += f"Staged changes: {has_staged.split(chr(10))[-1]} " if not has_unstaged and not has_staged: - status += "\n- Working tree: clean" - sections.append(status) - - # Recent commits + status_msg = "Working tree: clean" + + git_info["status"] = status_msg.strip() + + log_data = [] if args.log > 0: - log = run(["git", "log", f"--max-count={args.log}", "--oneline", "--graph", - "--pretty=format:%h %d %s (%an, %ar)"], target) - if log: - sections.append(f"\n## Recent Commits (last {args.log})") - sections.append(f"```\n{log}\n```") - - # Branch topology - branches = run(["git", "branch", "-a"], target) - if branches: - sections.append("\n## Branches") - sections.append(f"```\n{branches}\n```") - - # Directory tree + raw_log = run(["git", "log", f"--max-count={args.log}", "--oneline", "--graph", + "--pretty=format:%h %d %s (%an, %ar)"], target) + if raw_log: + log_data = raw_log.splitlines() + + branches_data = run(["git", "branch", "-a"], target) + tree_out = tree(target, ignored=DEFAULT_IGNORE, depth=args.depth) - sections.append(f"\n## Project Structure (depth={args.depth})") - sections.append(f"```\n{tree_out}\n```") - - # File contents + + contents_data = "" if args.files: - contents = file_contents(target) - if contents: + contents_data = file_contents(target) + + # Output logic + if args.json: + data = { + "repo_name": repo_name, + "generated_at": datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + "path": target, + "git_info": git_info, + "recent_commits": log_data, + "branches": branches_data, + "project_structure": tree_out, + "file_contents": contents_data + } + output = json.dumps(data, indent=2) + else: + sections = [ + f"# git-context: {repo_name}", + f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", + f"Path: {target}", + "", + f"## Git Info\n- Branch: `{git_info['branch']}`", + f"- Remote: {git_info['remote']}", + f"Status: {git_info['status']}", + "", + ] + if log_data: + sections.append(f"## Recent Commits (last {args.log})") + sections.append(f"```\n{''.join(log_data)}\n```") + if branches_data: + sections.append(f"\n## Branches") + sections.append(f"```\n{branches_data}\n```") + sections.append(f"\n## Project Structure (depth={args.depth})") + sections.append(f"```\n{tree_out}\n```") + if contents_data: sections.append("\n## File Contents") - sections.append(contents) - - output = "\n".join(sections) + sections.append(contents_data) + output = "\n".join(sections) if args.output: Path(args.output).write_text(output)