diff --git a/app/cli.py b/app/cli.py index 941e25c..a7caaeb 100644 --- a/app/cli.py +++ b/app/cli.py @@ -9,7 +9,7 @@ from app.commands import check, download, progress, setup, verify from app.commands.repl import repl from app.commands.version import version -from app.utils.click import ClickColor, CliContextKey, warn +from app.utils.click import ClickColor, CliContextKey, handle_unexpected_error, warn from app.utils.version import Version from app.version import __version__ @@ -32,7 +32,6 @@ def invoke(self, ctx: click.Context) -> None: @click.option("--verbose", "-v", is_flag=True, help="Enable verbose output") @click.pass_context def cli(ctx: click.Context, verbose: bool) -> None: - """Git-Mastery app""" ctx.ensure_object(dict) ctx.obj[CliContextKey.VERBOSE] = verbose @@ -69,4 +68,8 @@ def start() -> None: cli.add_command(command, aliases=COMMAND_ALIASES[command.name]) else: cli.add_command(command) - cli(obj={}) + try: + cli(obj={}) + except Exception as e: + handle_unexpected_error(e) + sys.exit(1) diff --git a/app/commands/repl.py b/app/commands/repl.py index ccf879c..3bd28bf 100644 --- a/app/commands/repl.py +++ b/app/commands/repl.py @@ -14,7 +14,7 @@ from app.commands.setup_folder import setup from app.commands.verify import verify from app.commands.version import version -from app.utils.click import CliContextKey, ClickColor +from app.utils.click import CliContextKey, ClickColor, handle_unexpected_error from app.utils.version import Version from app.version import __version__ @@ -128,7 +128,7 @@ def _run_gitmastery_command(self, command_name: str, args: List[str]) -> None: except SystemExit: pass except Exception as e: - click.echo(click.style(f"Error: {e}", fg=ClickColor.BRIGHT_RED)) + handle_unexpected_error(e) finally: try: os.chdir(original_cwd) diff --git a/app/utils/click.py b/app/utils/click.py index 88a4c51..c7e9170 100644 --- a/app/utils/click.py +++ b/app/utils/click.py @@ -6,7 +6,13 @@ import click from app.configs.exercise_config import ExerciseConfig -from app.configs.gitmastery_config import GitMasteryConfig +from app.configs.gitmastery_config import ( + GITMASTERY_CONFIG_NAME, + GITMASTERY_LOG_NAME, + METADATA_FOLDER_NAME, + GitMasteryConfig, +) +from app.configs.utils import find_root logger = logging.getLogger(__name__) @@ -45,6 +51,16 @@ def error(message: str) -> NoReturn: sys.exit(1) +def handle_unexpected_error(exception: Exception) -> None: + logger.exception("Unexpected error: %s", exception) + message = f"An unexpected error occurred: {type(exception).__name__}: {exception}" + if find_root(GITMASTERY_CONFIG_NAME, folder=METADATA_FOLDER_NAME) is not None: + message += f" See {METADATA_FOLDER_NAME}/{GITMASTERY_LOG_NAME} for details." + click.echo( + f"{click.style(' ERROR ', fg=ClickColor.BLACK, bg=ClickColor.BRIGHT_RED, bold=True)} {message}" + ) + + def info(message: str) -> None: logger.info(message) click.echo(