diff --git a/app/src/promptforge/cli/commands/version.py b/app/src/promptforge/cli/commands/version.py new file mode 100644 index 0000000..2e1cd26 --- /dev/null +++ b/app/src/promptforge/cli/commands/version.py @@ -0,0 +1,147 @@ +import click + +from promptforge.core.git_manager import GitManager + + +@click.group() +def version(): + """Manage prompt versions.""" + pass + + +@version.command("history") +@click.argument("prompt_name", required=False) +@click.pass_obj +def history(ctx, prompt_name: str): + """Show version history.""" + prompts_dir = ctx["prompts_dir"] + git_manager = GitManager(prompts_dir) + + if not (prompts_dir / ".git").exists(): + click.echo("Git not initialized. Run 'pf init' first.", err=True) + raise click.Abort() + + try: + commits = git_manager.log() + + if prompt_name: + file_history = git_manager.get_file_history( + f"{prompt_name.lower().replace(' ', '_')}.yaml" + ) + for commit in file_history: + click.echo(f"{commit['sha'][:7]} - {commit['message']}") + click.echo(f" {commit['date']} by {commit['author']}") + else: + for commit in commits: + hexsha = commit.hexsha + if isinstance(hexsha, bytes): + hexsha = hexsha.decode('utf-8') + message = commit.message + if isinstance(message, bytes): + message = message.decode('utf-8') + click.echo(f"{hexsha[:7]} - {message.strip()}") + click.echo(f" {commit.author.name} - {commit.committed_datetime.isoformat()}") + except Exception as e: + click.echo(f"Error: {e}", err=True) + raise click.Abort() + + +@version.command("create") +@click.argument("message") +@click.option("--author", help="Commit author") +@click.pass_obj +def create(ctx, message: str, author: str): + """Create a version commit.""" + prompts_dir = ctx["prompts_dir"] + git_manager = GitManager(prompts_dir) + + if not (prompts_dir / ".git").exists(): + git_manager.init() + + try: + git_manager.commit(message, author=author) + click.echo(f"Created version: {message}") + except Exception as e: + click.echo(f"Error: {e}", err=True) + raise click.Abort() + + +@version.command("branch") +@click.argument("branch_name") +@click.pass_obj +def branch(ctx, branch_name: str): + """Create a branch for prompt variations.""" + prompts_dir = ctx["prompts_dir"] + git_manager = GitManager(prompts_dir) + + try: + git_manager.create_branch(branch_name) + click.echo(f"Created branch: {branch_name}") + except Exception as e: + click.echo(f"Error: {e}", err=True) + raise click.Abort() + + +@version.command("switch") +@click.argument("branch_name") +@click.pass_obj +def switch(ctx, branch_name: str): + """Switch to a branch.""" + prompts_dir = ctx["prompts_dir"] + git_manager = GitManager(prompts_dir) + + try: + git_manager.switch_branch(branch_name) + click.echo(f"Switched to branch: {branch_name}") + except Exception as e: + click.echo(f"Error: {e}", err=True) + raise click.Abort() + + +@version.command("list") +@click.pass_obj +def list_branches(ctx): + """List all branches.""" + prompts_dir = ctx["prompts_dir"] + git_manager = GitManager(prompts_dir) + + try: + branches = git_manager.list_branches() + for branch in branches: + click.echo(f"* {branch}") + except Exception as e: + click.echo(f"Error: {e}", err=True) + raise click.Abort() + + +@version.command("diff") +@click.pass_obj +def diff(ctx): + """Show uncommitted changes.""" + prompts_dir = ctx["prompts_dir"] + git_manager = GitManager(prompts_dir) + + try: + changes = git_manager.diff() + if changes: + click.echo(changes) + else: + click.echo("No uncommitted changes") + except Exception as e: + click.echo(f"Error: {e}", err=True) + raise click.Abort() + + +@version.command("status") +@click.pass_obj +def status(ctx): + """Show git status.""" + prompts_dir = ctx["prompts_dir"] + git_manager = GitManager(prompts_dir) + + try: + status_output = git_manager.status() + click.echo(status_output) + except Exception as e: + click.echo(f"Error: {e}", err=True) + raise click.Abort()