fix: add CLI and main module files
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled

This commit is contained in:
2026-02-01 08:19:10 +00:00
parent c9b31fb9b6
commit beb98d85fc

View File

@@ -1,226 +1,111 @@
import os import sys
from datetime import datetime
from pathlib import Path
from typing import Optional from typing import Optional
import click import click
from rich.console import Console from rich import print as rprint
from src.git_insights import GitInsights from git_insights import GitInsights
from src.utils.config import load_config from git_insights.formatters import DashboardFormatter, JSONFormatter, MarkdownFormatter, HTMLFormatter
console = Console()
@click.group() @click.group()
@click.option( def main():
"--repo-path",
"-p",
default=".",
help="Path to git repository",
)
@click.option(
"--days",
"-d",
default=30,
type=int,
help="Number of days to analyze",
)
@click.option(
"--config",
"-c",
default=None,
type=str,
help="Path to config file",
)
@click.pass_context
def main(
ctx: click.Context,
repo_path: str,
days: int,
config: Optional[str],
) -> None:
"""Git Insights CLI - Analyze git repositories for productivity insights.""" """Git Insights CLI - Analyze git repositories for productivity insights."""
ctx.ensure_object(dict) pass
ctx.obj["repo_path"] = repo_path
ctx.obj["days"] = days
ctx.obj["config"] = config
@main.command() @main.command()
@click.option( @click.argument("path", type=click.Path(exists=True), required=False, default=".")
"--format", @click.option("--days", type=int, default=30, help="Number of days to analyze")
"-f", @click.option("--format", type=click.Choice(["json", "markdown", "html"]), default="console", help="Output format")
type=click.Choice(["json", "markdown", "html", "console"]), @click.option("-v", "--verbose", is_flag=True, help="Enable verbose output")
default="console", def analyze(path: str, days: int, format: str, verbose: bool):
help="Output format", """Analyze a git repository for commit patterns and productivity metrics."""
)
@click.pass_context
def analyze(ctx: click.Context, format: str) -> None:
"""Analyze repository for commit patterns, code churn, and productivity metrics."""
repo_path = ctx.obj["repo_path"]
days = ctx.obj["days"]
config_path = ctx.obj["config"]
config = load_config(config_path) if config_path else None
if not os.path.isdir(repo_path):
console.print(f"[red]Error: Directory not found: {repo_path}[/red]")
return
try: try:
insights = GitInsights( insights = GitInsights(path, days=days)
repo_path=repo_path, result = insights.analyze()
days=days,
config=config,
)
results = insights.analyze()
if format == "json": if format == "json":
from src.formatters import JSONFormatter click.echo(JSONFormatter.format(result))
console.print(JSONFormatter.format(results))
elif format == "markdown": elif format == "markdown":
from src.formatters import MarkdownFormatter click.echo(MarkdownFormatter.format(result))
console.print(MarkdownFormatter.format(results))
elif format == "html": elif format == "html":
from src.formatters import HTMLFormatter click.echo(HTMLFormatter.format(result))
console.print(HTMLFormatter.format(results))
else: else:
from src.formatters import DashboardFormatter DashboardFormatter.display(result)
DashboardFormatter.display(results)
if verbose:
click.echo(f"\nAnalysis period: {days} days")
click.echo(f"Repository: {Path(path).resolve()}")
click.echo(f"Timestamp: {datetime.now().isoformat()}")
except Exception as e: except Exception as e:
console.print(f"[red]Error: {e}[/red]") rprint(f"[red]Error: {e}[/red]")
raise sys.exit(1)
@main.command() @main.command()
@click.pass_context @click.argument("path", type=click.Path(exists=True), required=False, default=".")
def dashboard(ctx: click.Context) -> None: @click.option("--days", type=int, default=30, help="Number of days to analyze")
def dashboard(path: str, days: int):
"""Display productivity metrics in an interactive dashboard.""" """Display productivity metrics in an interactive dashboard."""
repo_path = ctx.obj["repo_path"]
days = ctx.obj["days"]
config_path = ctx.obj["config"]
config = load_config(config_path) if config_path else None
if not os.path.isdir(repo_path):
console.print(f"[red]Error: Directory not found: {repo_path}[/red]")
return
try: try:
insights = GitInsights( insights = GitInsights(path, days=days)
repo_path=repo_path, result = insights.analyze()
days=days, DashboardFormatter.display(result)
config=config,
)
results = insights.analyze()
from src.formatters import DashboardFormatter
DashboardFormatter.display(results)
except Exception as e: except Exception as e:
console.print(f"[red]Error: {e}[/red]") rprint(f"[red]Error: {e}[/red]")
raise sys.exit(1)
@main.command() @main.command()
@click.option( @click.argument("path", type=click.Path(exists=True), required=False, default=".")
"--format", @click.option("--days", type=int, default=30, help="Number of days to analyze")
"-f", @click.option("--format", type=click.Choice(["json", "markdown", "html"]), default="json", help="Output format")
type=click.Choice(["json", "markdown", "html"]), @click.option("--output", type=click.Path(), help="Output file path")
default="json", def export(path: str, days: int, format: str, output: Optional[str]):
help="Output format",
)
@click.option(
"--output",
"-o",
default=None,
type=str,
help="Output file path",
)
@click.pass_context
def export(ctx: click.Context, format: str, output: Optional[str]) -> None:
"""Export analysis results to a file.""" """Export analysis results to a file."""
repo_path = ctx.obj["repo_path"]
days = ctx.obj["days"]
config_path = ctx.obj["config"]
config = load_config(config_path) if config_path else None
if not os.path.isdir(repo_path):
console.print(f"[red]Error: Directory not found: {repo_path}[/red]")
return
try: try:
insights = GitInsights( insights = GitInsights(path, days=days)
repo_path=repo_path, result = insights.analyze()
days=days,
config=config,
)
results = insights.analyze()
if format == "json": if format == "json":
from src.formatters import JSONFormatter content = JSONFormatter.format(result)
output_str = JSONFormatter.format(results)
elif format == "markdown": elif format == "markdown":
from src.formatters import MarkdownFormatter content = MarkdownFormatter.format(result)
output_str = MarkdownFormatter.format(results)
else: else:
from src.formatters import HTMLFormatter content = HTMLFormatter.format(result)
output_str = HTMLFormatter.format(results)
if output: if output:
with open(output, "w") as f: Path(output).write_text(content)
f.write(output_str) click.echo(f"Exported to {output}")
console.print(f"[green]Exported to {output}[/green]")
else: else:
console.print(output_str) click.echo(content)
except Exception as e: except Exception as e:
console.print(f"[red]Error: {e}[/red]") rprint(f"[red]Error: {e}[/red]")
raise sys.exit(1)
@main.command() @main.command()
@click.option( @click.argument("path", type=click.Path(exists=True), required=False, default=".")
"--output", @click.option("--days", type=int, default=30, help="Number of days to analyze")
"-o", @click.option("--output", type=click.Path(), help="Output file path")
default=None, def report(path: str, days: int, output: Optional[str]):
type=str,
help="Output file path",
)
@click.pass_context
def report(ctx: click.Context, output: Optional[str]) -> None:
"""Generate a comprehensive productivity report.""" """Generate a comprehensive productivity report."""
repo_path = ctx.obj["repo_path"]
days = ctx.obj["days"]
config_path = ctx.obj["config"]
config = load_config(config_path) if config_path else None
if not os.path.isdir(repo_path):
console.print(f"[red]Error: Directory not found: {repo_path}[/red]")
return
try: try:
insights = GitInsights( insights = GitInsights(path, days=days)
repo_path=repo_path, report = insights.get_productivity_report()
days=days, content = HTMLFormatter.format(report)
config=config,
)
results = insights.analyze()
from src.formatters import HTMLFormatter
report_str = HTMLFormatter.format(results)
if output: if output:
with open(output, "w") as f: Path(output).write_text(content)
f.write(report_str) click.echo(f"Report generated: {output}")
console.print(f"[green]Report generated: {output}[/green]")
else: else:
console.print(report_str) click.echo(content)
except Exception as e: except Exception as e:
console.print(f"[red]Error: {e}[/red]") rprint(f"[red]Error: {e}[/red]")
raise sys.exit(1)