# SPDX-FileCopyrightText: 2013, 2016, 2018 Michael Pyne # # SPDX-License-Identifier: GPL-2.0-or-later package ksb::BuildException 0.20; # A class to wrap 'exception' messages for the script, allowing them to be # dispatch based on type and automatically stringified. use ksb; use Carp; use overload '""' => \&to_string; use Exporter qw(import); our @EXPORT = qw(croak_runtime croak_internal had_an_exception make_exception); sub new { my ($class, $type, $msg) = @_; return bless({ 'exception_type' => $type, 'message' => $msg, }, $class); } sub to_string { my $exception = shift; return $exception->{exception_type} . " Error: " . $exception->{message}; } sub message { my $self = shift; return $self->{message}; } sub setMessage { my ($self, $newMessage) = @_; $self->{message} = $newMessage; } # # Exported utility functions # # Returns a Perl exception object to pass to 'die' function # The returned reference will be an instance of ksb::BuildException. # # First parameter: Exception type, 'Exception' if undef # Second parameter: Message to show to user sub make_exception { my $exception_type = shift // 'Exception'; my $message = shift; my $levels = shift // 0; # Allow for more levels to be removed from bt # Remove this subroutine from the backtrace local $Carp::CarpLevel = 1 + $levels; $message = Carp::cluck($message) if $exception_type eq 'Internal'; return ksb::BuildException->new($exception_type, $message); } # Helper function to return $@ if $@ is a ksb::BuildException. # # This function assumes that an eval block had just been used in order to set # or clear $@ as appropriate. sub had_an_exception { if ($@ && ref $@ && $@->isa('ksb::BuildException')) { return $@; } return; } # Should be used for "runtime errors" (i.e. unrecoverable runtime problems that # don't indicate a bug in the program itself). sub croak_runtime { die (make_exception('Runtime', $_[0], 1)); } # Should be used for "logic errors" (i.e. impossibilities in program state, things # that shouldn't be possible no matter what input is fed at runtime) sub croak_internal { die (make_exception('Internal', $_[0], 1)); } # # A small subclass to hold the option name that caused a config exception to # be thrown. # # Typically this will be caught by config-reading code in ksb::Application, # which will add filename and line number information to the message. # package ksb::BuildException::Config 0.10 { use parent qw(ksb::BuildException); use Scalar::Util qw(blessed); sub new { my ($class, $bad_option_name, $msg) = @_; my $self = ksb::BuildException->new('Config', $msg); $self->{'config_invalid_option_name'} = $bad_option_name; return $self; } sub problematicOptionName { my $self = shift; return $self->{'config_invalid_option_name'}; } # Should return a lengthy explanation of how to use a given option for use in # error messages, or undef if no explanation is unavailable. sub optionUsageExplanation { my $optionName = shift; my $result; if (blessed($optionName)) { # Should only happen if called as method: ie. $optionName == $self $optionName = $optionName->problematicOptionName(); } if ($optionName eq 'git-repository-base') { $result = <<"EOF"; The y[git-repository-base] option requires a repository name and URL. e.g. git-repository base y[b[kde-sdk] g[b[https://invent.kde.org/sdk/] Use this in a "module-set" group: e.g. module-set kdesdk-set repository y[b[kde-sdk] use-modules kdesrc-build kde-dev-scripts clazy end module-set EOF } return $result; } 1; }; 1;