fix: add CLI and main module files
This commit is contained in:
239
src/cli.py
239
src/cli.py
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user