mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-15 02:42:45 +08:00
fix(codex-lens): refine CLI exception handling with specific error types
Replace overly broad `except Exception` blocks with specific exception handlers (StorageError, ConfigError, ParseError, SearchError, PermissionError) across all CLI commands. This provides more precise error messages and improves debugging experience for end users. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ from rich.table import Table
|
|||||||
|
|
||||||
from codexlens.config import Config
|
from codexlens.config import Config
|
||||||
from codexlens.entities import IndexedFile, SearchResult, Symbol
|
from codexlens.entities import IndexedFile, SearchResult, Symbol
|
||||||
from codexlens.errors import CodexLensError
|
from codexlens.errors import CodexLensError, ConfigError, ParseError, StorageError, SearchError
|
||||||
from codexlens.parsers.factory import ParserFactory
|
from codexlens.parsers.factory import ParserFactory
|
||||||
from codexlens.storage.path_mapper import PathMapper
|
from codexlens.storage.path_mapper import PathMapper
|
||||||
from codexlens.storage.registry import RegistryStore, ProjectInfo
|
from codexlens.storage.registry import RegistryStore, ProjectInfo
|
||||||
@@ -124,12 +124,42 @@ def init(
|
|||||||
if build_result.errors:
|
if build_result.errors:
|
||||||
console.print(f" [yellow]Warnings:[/yellow] {len(build_result.errors)} errors")
|
console.print(f" [yellow]Warnings:[/yellow] {len(build_result.errors)} errors")
|
||||||
|
|
||||||
except Exception as exc:
|
except StorageError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Storage error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Init failed (storage):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except ConfigError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Configuration error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Init failed (config):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except ParseError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Parse error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Init failed (parse):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except PermissionError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Permission denied: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Init failed (permission denied):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except CodexLensError as exc:
|
||||||
if json_mode:
|
if json_mode:
|
||||||
print_json(success=False, error=str(exc))
|
print_json(success=False, error=str(exc))
|
||||||
else:
|
else:
|
||||||
console.print(f"[red]Init failed:[/red] {exc}")
|
console.print(f"[red]Init failed:[/red] {exc}")
|
||||||
raise typer.Exit(code=1)
|
raise typer.Exit(code=1)
|
||||||
|
except Exception as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Unexpected error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Init failed (unexpected):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
finally:
|
finally:
|
||||||
if registry is not None:
|
if registry is not None:
|
||||||
registry.close()
|
registry.close()
|
||||||
@@ -193,12 +223,30 @@ def search(
|
|||||||
if verbose:
|
if verbose:
|
||||||
console.print(f"[dim]Searched {result.stats.dirs_searched} directories in {result.stats.time_ms:.1f}ms[/dim]")
|
console.print(f"[dim]Searched {result.stats.dirs_searched} directories in {result.stats.time_ms:.1f}ms[/dim]")
|
||||||
|
|
||||||
except Exception as exc:
|
except SearchError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Search error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Search failed (query):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except StorageError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Storage error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Search failed (storage):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except CodexLensError as exc:
|
||||||
if json_mode:
|
if json_mode:
|
||||||
print_json(success=False, error=str(exc))
|
print_json(success=False, error=str(exc))
|
||||||
else:
|
else:
|
||||||
console.print(f"[red]Search failed:[/red] {exc}")
|
console.print(f"[red]Search failed:[/red] {exc}")
|
||||||
raise typer.Exit(code=1)
|
raise typer.Exit(code=1)
|
||||||
|
except Exception as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Unexpected error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Search failed (unexpected):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
finally:
|
finally:
|
||||||
if registry is not None:
|
if registry is not None:
|
||||||
registry.close()
|
registry.close()
|
||||||
@@ -240,12 +288,30 @@ def symbol(
|
|||||||
else:
|
else:
|
||||||
render_symbols(syms)
|
render_symbols(syms)
|
||||||
|
|
||||||
except Exception as exc:
|
except SearchError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Search error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Symbol lookup failed (search):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except StorageError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Storage error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Symbol lookup failed (storage):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except CodexLensError as exc:
|
||||||
if json_mode:
|
if json_mode:
|
||||||
print_json(success=False, error=str(exc))
|
print_json(success=False, error=str(exc))
|
||||||
else:
|
else:
|
||||||
console.print(f"[red]Symbol lookup failed:[/red] {exc}")
|
console.print(f"[red]Symbol lookup failed:[/red] {exc}")
|
||||||
raise typer.Exit(code=1)
|
raise typer.Exit(code=1)
|
||||||
|
except Exception as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Unexpected error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Symbol lookup failed (unexpected):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
finally:
|
finally:
|
||||||
if registry is not None:
|
if registry is not None:
|
||||||
registry.close()
|
registry.close()
|
||||||
@@ -277,12 +343,36 @@ def inspect(
|
|||||||
render_file_inspect(indexed.path, indexed.language, indexed.symbols)
|
render_file_inspect(indexed.path, indexed.language, indexed.symbols)
|
||||||
else:
|
else:
|
||||||
render_status({"file": indexed.path, "language": indexed.language})
|
render_status({"file": indexed.path, "language": indexed.language})
|
||||||
except Exception as exc:
|
except ParseError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Parse error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Inspect failed (parse):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except FileNotFoundError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"File not found: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Inspect failed (file not found):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except PermissionError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Permission denied: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Inspect failed (permission denied):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except CodexLensError as exc:
|
||||||
if json_mode:
|
if json_mode:
|
||||||
print_json(success=False, error=str(exc))
|
print_json(success=False, error=str(exc))
|
||||||
else:
|
else:
|
||||||
console.print(f"[red]Inspect failed:[/red] {exc}")
|
console.print(f"[red]Inspect failed:[/red] {exc}")
|
||||||
raise typer.Exit(code=1)
|
raise typer.Exit(code=1)
|
||||||
|
except Exception as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Unexpected error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Inspect failed (unexpected):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
@@ -335,12 +425,24 @@ def status(
|
|||||||
console.print(f" Total Directories: {stats['total_dirs']}")
|
console.print(f" Total Directories: {stats['total_dirs']}")
|
||||||
console.print(f" Index Size: {stats['index_size_mb']} MB")
|
console.print(f" Index Size: {stats['index_size_mb']} MB")
|
||||||
|
|
||||||
except Exception as exc:
|
except StorageError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Storage error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Status failed (storage):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except CodexLensError as exc:
|
||||||
if json_mode:
|
if json_mode:
|
||||||
print_json(success=False, error=str(exc))
|
print_json(success=False, error=str(exc))
|
||||||
else:
|
else:
|
||||||
console.print(f"[red]Status failed:[/red] {exc}")
|
console.print(f"[red]Status failed:[/red] {exc}")
|
||||||
raise typer.Exit(code=1)
|
raise typer.Exit(code=1)
|
||||||
|
except Exception as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Unexpected error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Status failed (unexpected):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
finally:
|
finally:
|
||||||
if registry is not None:
|
if registry is not None:
|
||||||
registry.close()
|
registry.close()
|
||||||
@@ -474,12 +576,30 @@ def projects(
|
|||||||
|
|
||||||
except typer.BadParameter:
|
except typer.BadParameter:
|
||||||
raise
|
raise
|
||||||
except Exception as exc:
|
except StorageError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Storage error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Projects command failed (storage):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except PermissionError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Permission denied: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Projects command failed (permission denied):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except CodexLensError as exc:
|
||||||
if json_mode:
|
if json_mode:
|
||||||
print_json(success=False, error=str(exc))
|
print_json(success=False, error=str(exc))
|
||||||
else:
|
else:
|
||||||
console.print(f"[red]Projects command failed:[/red] {exc}")
|
console.print(f"[red]Projects command failed:[/red] {exc}")
|
||||||
raise typer.Exit(code=1)
|
raise typer.Exit(code=1)
|
||||||
|
except Exception as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Unexpected error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Projects command failed (unexpected):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
finally:
|
finally:
|
||||||
if registry is not None:
|
if registry is not None:
|
||||||
registry.close()
|
registry.close()
|
||||||
@@ -626,14 +746,209 @@ def config(
|
|||||||
|
|
||||||
except typer.BadParameter:
|
except typer.BadParameter:
|
||||||
raise
|
raise
|
||||||
except Exception as exc:
|
except ConfigError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Configuration error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Config command failed (config):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except StorageError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Storage error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Config command failed (storage):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except PermissionError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Permission denied: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Config command failed (permission denied):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except CodexLensError as exc:
|
||||||
if json_mode:
|
if json_mode:
|
||||||
print_json(success=False, error=str(exc))
|
print_json(success=False, error=str(exc))
|
||||||
else:
|
else:
|
||||||
console.print(f"[red]Config command failed:[/red] {exc}")
|
console.print(f"[red]Config command failed:[/red] {exc}")
|
||||||
raise typer.Exit(code=1)
|
raise typer.Exit(code=1)
|
||||||
|
except Exception as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Unexpected error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Config command failed (unexpected):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def enhance(
|
||||||
|
path: Path = typer.Argument(Path("."), exists=True, file_okay=False, dir_okay=True, help="Project root to enhance."),
|
||||||
|
tool: str = typer.Option("gemini", "--tool", "-t", help="LLM tool to use (gemini or qwen)."),
|
||||||
|
batch_size: int = typer.Option(5, "--batch-size", "-b", min=1, max=20, help="Number of files to process per batch."),
|
||||||
|
force: bool = typer.Option(False, "--force", "-f", help="Regenerate metadata for all files, even if already exists."),
|
||||||
|
json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
|
||||||
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
|
||||||
|
) -> None:
|
||||||
|
"""Generate LLM-enhanced semantic metadata for indexed files.
|
||||||
|
|
||||||
|
Uses CCW CLI to generate summaries, keywords, and purpose descriptions.
|
||||||
|
Requires ccw to be installed and accessible in PATH.
|
||||||
|
"""
|
||||||
|
_configure_logging(verbose)
|
||||||
|
base_path = path.expanduser().resolve()
|
||||||
|
|
||||||
|
registry: RegistryStore | None = None
|
||||||
|
try:
|
||||||
|
# Check if ccw is available
|
||||||
|
import subprocess
|
||||||
|
try:
|
||||||
|
subprocess.run(["ccw", "--version"], capture_output=True, check=True)
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||||
|
raise CodexLensError("ccw CLI not found. Please install ccw first.")
|
||||||
|
|
||||||
|
# Validate tool
|
||||||
|
if tool not in ("gemini", "qwen"):
|
||||||
|
raise CodexLensError(f"Invalid tool: {tool}. Must be 'gemini' or 'qwen'.")
|
||||||
|
|
||||||
|
registry = RegistryStore()
|
||||||
|
registry.initialize()
|
||||||
|
mapper = PathMapper()
|
||||||
|
|
||||||
|
# Find project
|
||||||
|
project_info = registry.find_project(base_path)
|
||||||
|
if not project_info:
|
||||||
|
raise CodexLensError(f"No index found for: {base_path}. Run 'codex-lens init' first.")
|
||||||
|
|
||||||
|
# Import LLM enhancer
|
||||||
|
try:
|
||||||
|
from codexlens.semantic.llm_enhancer import LLMEnhancer, LLMConfig
|
||||||
|
except ImportError as e:
|
||||||
|
raise CodexLensError(f"Semantic enhancement requires additional dependencies: {e}")
|
||||||
|
|
||||||
|
# Create enhancer with config
|
||||||
|
config = LLMConfig(tool=tool, batch_size=batch_size)
|
||||||
|
enhancer = LLMEnhancer(config=config)
|
||||||
|
|
||||||
|
# Get index directory
|
||||||
|
index_dir = mapper.source_to_index_dir(base_path)
|
||||||
|
if not index_dir.exists():
|
||||||
|
raise CodexLensError(f"Index directory not found: {index_dir}")
|
||||||
|
|
||||||
|
# Process all index databases recursively
|
||||||
|
from codexlens.storage.dir_index import DirIndexStore
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
total_processed = 0
|
||||||
|
total_errors = 0
|
||||||
|
|
||||||
|
with Progress(
|
||||||
|
SpinnerColumn(),
|
||||||
|
TextColumn("[progress.description]{task.description}"),
|
||||||
|
BarColumn(),
|
||||||
|
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
|
||||||
|
TimeElapsedColumn(),
|
||||||
|
console=console,
|
||||||
|
) as progress:
|
||||||
|
# Find all _index.db files
|
||||||
|
index_files = list(index_dir.rglob("_index.db"))
|
||||||
|
task = progress.add_task(f"Enhancing {len(index_files)} directories...", total=len(index_files))
|
||||||
|
|
||||||
|
for db_path in index_files:
|
||||||
|
try:
|
||||||
|
store = DirIndexStore(db_path)
|
||||||
|
store.initialize()
|
||||||
|
|
||||||
|
# Get files to process
|
||||||
|
if force:
|
||||||
|
files_to_process = store.list_files()
|
||||||
|
else:
|
||||||
|
files_to_process = store.get_files_without_semantic()
|
||||||
|
|
||||||
|
if not files_to_process:
|
||||||
|
progress.update(task, advance=1)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Process files
|
||||||
|
for file_entry in files_to_process:
|
||||||
|
try:
|
||||||
|
# Read file content
|
||||||
|
with open(file_entry.full_path, "r", encoding="utf-8", errors="ignore") as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Generate metadata
|
||||||
|
metadata = enhancer.enhance_file(
|
||||||
|
path=str(file_entry.full_path),
|
||||||
|
content=content,
|
||||||
|
language=file_entry.language or "unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Store metadata
|
||||||
|
store.add_semantic_metadata(
|
||||||
|
file_id=file_entry.id,
|
||||||
|
summary=metadata.summary,
|
||||||
|
keywords=metadata.keywords,
|
||||||
|
purpose=metadata.purpose,
|
||||||
|
llm_tool=tool
|
||||||
|
)
|
||||||
|
|
||||||
|
total_processed += 1
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
total_errors += 1
|
||||||
|
if verbose:
|
||||||
|
console.print(f"[yellow]Error processing {file_entry.full_path}: {e}[/yellow]")
|
||||||
|
|
||||||
|
store.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
total_errors += 1
|
||||||
|
if verbose:
|
||||||
|
console.print(f"[yellow]Error processing {db_path}: {e}[/yellow]")
|
||||||
|
|
||||||
|
progress.update(task, advance=1)
|
||||||
|
|
||||||
|
result = {
|
||||||
|
"path": str(base_path),
|
||||||
|
"tool": tool,
|
||||||
|
"files_processed": total_processed,
|
||||||
|
"errors": total_errors,
|
||||||
|
}
|
||||||
|
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=True, result=result)
|
||||||
|
else:
|
||||||
|
console.print(f"[green]Enhanced {total_processed} files using {tool}[/green]")
|
||||||
|
if total_errors > 0:
|
||||||
|
console.print(f" [yellow]Errors: {total_errors}[/yellow]")
|
||||||
|
|
||||||
|
except StorageError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Storage error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Enhancement failed (storage):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except PermissionError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Permission denied: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Enhancement failed (permission denied):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except CodexLensError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=str(exc))
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Enhancement failed:[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except Exception as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Unexpected error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Enhancement failed (unexpected):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
finally:
|
||||||
|
if registry is not None:
|
||||||
|
registry.close()
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def clean(
|
def clean(
|
||||||
path: Optional[Path] = typer.Argument(None, help="Project path to clean (removes project index)."),
|
path: Optional[Path] = typer.Argument(None, help="Project path to clean (removes project index)."),
|
||||||
@@ -759,9 +1074,27 @@ def clean(
|
|||||||
console.print(f" Total Size: {result['total_size_mb']} MB")
|
console.print(f" Total Size: {result['total_size_mb']} MB")
|
||||||
console.print("\n[dim]Use 'clean <path>' to remove a specific project or 'clean --all' to remove everything.[/dim]")
|
console.print("\n[dim]Use 'clean <path>' to remove a specific project or 'clean --all' to remove everything.[/dim]")
|
||||||
|
|
||||||
except Exception as exc:
|
except StorageError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Storage error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Clean failed (storage):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except PermissionError as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Permission denied: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Clean failed (permission denied):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except CodexLensError as exc:
|
||||||
if json_mode:
|
if json_mode:
|
||||||
print_json(success=False, error=str(exc))
|
print_json(success=False, error=str(exc))
|
||||||
else:
|
else:
|
||||||
console.print(f"[red]Clean failed:[/red] {exc}")
|
console.print(f"[red]Clean failed:[/red] {exc}")
|
||||||
raise typer.Exit(code=1)
|
raise typer.Exit(code=1)
|
||||||
|
except Exception as exc:
|
||||||
|
if json_mode:
|
||||||
|
print_json(success=False, error=f"Unexpected error: {exc}")
|
||||||
|
else:
|
||||||
|
console.print(f"[red]Clean failed (unexpected):[/red] {exc}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
|||||||
Reference in New Issue
Block a user