From 057affe59d66940c3933a2a50b899aa55c8d58e9 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Tue, 6 May 2025 23:12:43 +0100 Subject: [PATCH] nixos-rebuild-ng: improve error message on CalledProcessError This commit improves readability of error messages by making a Path object a string and by joining all arguments. It only changes formatting when `--verbose` or `--debug` is not being used, since those flags are supposed to be used when debugging issues so it is better to have the raw exception instead. Replaces #402997. --- .../src/nixos_rebuild/__init__.py | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py index 0e7cf61b00a4..4208fb3dc1d5 100644 --- a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py +++ b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py @@ -366,16 +366,37 @@ def main() -> None: try: execute(sys.argv) except CalledProcessError as ex: - if logger.level == logging.DEBUG: - import traceback - - traceback.print_exc() - else: - print(str(ex), file=sys.stderr) - # Exit with the error code of the process that failed - sys.exit(ex.returncode) + _handle_called_process_error(ex) except (Exception, KeyboardInterrupt) as ex: - if logger.level == logging.DEBUG: + if logger.isEnabledFor(logging.DEBUG): raise else: sys.exit(str(ex)) + + +def _handle_called_process_error(ex: CalledProcessError) -> None: + if logger.isEnabledFor(logging.DEBUG): + import traceback + + traceback.print_exception(ex) + else: + import shlex + + # If cmd is a list, stringify any Paths and join in a single string + # This will show much nicer in the error (e.g., as something that + # the user can simple copy-paste in terminal to debug) + cmd = ( + shlex.join([str(cmd) for cmd in ex.cmd]) + if isinstance(ex.cmd, list) + else ex.cmd + ) + ex = CalledProcessError( + returncode=ex.returncode, + cmd=cmd, + output=ex.output, + stderr=ex.stderr, + ) + print(str(ex), file=sys.stderr) + + # Exit with the error code of the process that failed + sys.exit(ex.returncode)