| File: | Dpkg/ErrorHandling.pm |
| Coverage: | 55.3% |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | # This program is free software; you can redistribute it and/or modify | ||||||
| 2 | # it under the terms of the GNU General Public License as published by | ||||||
| 3 | # the Free Software Foundation; either version 2 of the License, or | ||||||
| 4 | # (at your option) any later version. | ||||||
| 5 | # | ||||||
| 6 | # This program is distributed in the hope that it will be useful, | ||||||
| 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
| 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
| 9 | # GNU General Public License for more details. | ||||||
| 10 | # | ||||||
| 11 | # You should have received a copy of the GNU General Public License | ||||||
| 12 | # along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 13 | |||||||
| 14 | =encoding utf8 | ||||||
| 15 | |||||||
| 16 - 26 | =head1 NAME Dpkg::ErrorHandling - handle error conditions =head1 DESCRIPTION This module provides functions to handle all reporting and error handling. B<Note>: This is a private module, its API can change at any time. =cut | ||||||
| 27 | |||||||
| 28 | package Dpkg::ErrorHandling 0.02; | ||||||
| 29 | |||||||
| 30 | 2013 2013 2013 | 4858 843 28825 | use strict; | ||||
| 31 | 2013 2013 2013 | 3269 2342 48767 | use warnings; | ||||
| 32 | 2013 2013 2013 | 3045 1942 147038 | use feature qw(state); | ||||
| 33 | |||||||
| 34 | our @EXPORT_OK = qw( | ||||||
| 35 | REPORT_PROGNAME | ||||||
| 36 | REPORT_COMMAND | ||||||
| 37 | REPORT_STATUS | ||||||
| 38 | REPORT_DEBUG | ||||||
| 39 | REPORT_INFO | ||||||
| 40 | REPORT_NOTICE | ||||||
| 41 | REPORT_WARN | ||||||
| 42 | REPORT_ERROR | ||||||
| 43 | report_pretty | ||||||
| 44 | report_color | ||||||
| 45 | report | ||||||
| 46 | ); | ||||||
| 47 | our @EXPORT = qw( | ||||||
| 48 | report_options | ||||||
| 49 | debug | ||||||
| 50 | info | ||||||
| 51 | notice | ||||||
| 52 | warning | ||||||
| 53 | error | ||||||
| 54 | errormsg | ||||||
| 55 | syserr | ||||||
| 56 | printcmd | ||||||
| 57 | subprocerr | ||||||
| 58 | usageerr | ||||||
| 59 | ); | ||||||
| 60 | |||||||
| 61 | 2013 2013 2013 | 4082 1295 29465 | use Exporter qw(import); | ||||
| 62 | |||||||
| 63 | 2013 2013 2013 | 233177 1464 23126 | use Dpkg (); | ||||
| 64 | 2013 2013 2013 | 224058 2446 215595 | use Dpkg::Gettext; | ||||
| 65 | |||||||
| 66 | my $quiet_warnings = 0; | ||||||
| 67 | my $debug_level = 0; | ||||||
| 68 | my $info_fh = \*STDOUT; | ||||||
| 69 | |||||||
| 70 | sub setup_color | ||||||
| 71 | { | ||||||
| 72 | 72 | 0 | 241 | my $mode = $ENV{'DPKG_COLORS'} // 'auto'; | |||
| 73 | 72 | 78 | my $use_color; | ||||
| 74 | |||||||
| 75 | 72 | 207 | if ($mode eq 'auto') { | ||||
| 76 | ## no critic (InputOutput::ProhibitInteractiveTest) | ||||||
| 77 | 0 | 0 | $use_color = 1 if -t *STDOUT or -t *STDERR; | ||||
| 78 | } elsif ($mode eq 'always') { | ||||||
| 79 | 0 | 0 | $use_color = 1; | ||||
| 80 | } else { | ||||||
| 81 | 72 | 89 | $use_color = 0; | ||||
| 82 | } | ||||||
| 83 | |||||||
| 84 | 72 | 161 | require Term::ANSIColor if $use_color; | ||||
| 85 | } | ||||||
| 86 | |||||||
| 87 | use constant { | ||||||
| 88 | 2013 | 1226650 | REPORT_PROGNAME => 1, | ||||
| 89 | REPORT_COMMAND => 2, | ||||||
| 90 | REPORT_STATUS => 3, | ||||||
| 91 | REPORT_INFO => 4, | ||||||
| 92 | REPORT_NOTICE => 5, | ||||||
| 93 | REPORT_WARN => 6, | ||||||
| 94 | REPORT_ERROR => 7, | ||||||
| 95 | REPORT_DEBUG => 8, | ||||||
| 96 | 2013 2013 | 6779 1989 | }; | ||||
| 97 | |||||||
| 98 | my %report_mode = ( | ||||||
| 99 | REPORT_PROGNAME() => { | ||||||
| 100 | color => 'bold', | ||||||
| 101 | }, | ||||||
| 102 | REPORT_COMMAND() => { | ||||||
| 103 | color => 'bold magenta', | ||||||
| 104 | }, | ||||||
| 105 | REPORT_STATUS() => { | ||||||
| 106 | color => 'clear', | ||||||
| 107 | # We do not translate this name because the untranslated output is | ||||||
| 108 | # part of the interface. | ||||||
| 109 | name => 'status', | ||||||
| 110 | }, | ||||||
| 111 | REPORT_DEBUG() => { | ||||||
| 112 | color => 'clear', | ||||||
| 113 | # We do not translate this name because it is a developer interface | ||||||
| 114 | # and all debug messages are untranslated anyway. | ||||||
| 115 | name => 'debug', | ||||||
| 116 | }, | ||||||
| 117 | REPORT_INFO() => { | ||||||
| 118 | color => 'green', | ||||||
| 119 | name => g_('info'), | ||||||
| 120 | }, | ||||||
| 121 | REPORT_NOTICE() => { | ||||||
| 122 | color => 'yellow', | ||||||
| 123 | name => g_('notice'), | ||||||
| 124 | }, | ||||||
| 125 | REPORT_WARN() => { | ||||||
| 126 | color => 'bold yellow', | ||||||
| 127 | name => g_('warning'), | ||||||
| 128 | }, | ||||||
| 129 | REPORT_ERROR() => { | ||||||
| 130 | color => 'bold red', | ||||||
| 131 | name => g_('error'), | ||||||
| 132 | }, | ||||||
| 133 | ); | ||||||
| 134 | |||||||
| 135 | sub report_options | ||||||
| 136 | { | ||||||
| 137 | 1770 | 0 | 5157 | my (%options) = @_; | |||
| 138 | |||||||
| 139 | 1770 | 4070 | if (exists $options{quiet_warnings}) { | ||||
| 140 | 1770 | 2874 | $quiet_warnings = $options{quiet_warnings}; | ||||
| 141 | } | ||||||
| 142 | 1770 | 4570 | if (exists $options{debug_level}) { | ||||
| 143 | 0 | 0 | $debug_level = $options{debug_level}; | ||||
| 144 | } | ||||||
| 145 | 1770 | 4275 | if (exists $options{info_fh}) { | ||||
| 146 | 0 | 0 | $info_fh = $options{info_fh}; | ||||
| 147 | } | ||||||
| 148 | } | ||||||
| 149 | |||||||
| 150 | sub report_name | ||||||
| 151 | { | ||||||
| 152 | 252 | 0 | 213 | my $type = shift; | |||
| 153 | |||||||
| 154 | 252 | 515 | return $report_mode{$type}{name} // ''; | ||||
| 155 | } | ||||||
| 156 | |||||||
| 157 | sub report_color | ||||||
| 158 | { | ||||||
| 159 | 504 | 0 | 391 | my $type = shift; | |||
| 160 | |||||||
| 161 | 504 | 1094 | return $report_mode{$type}{color} // 'clear'; | ||||
| 162 | } | ||||||
| 163 | |||||||
| 164 | sub report_pretty | ||||||
| 165 | { | ||||||
| 166 | 504 | 0 | 488 | my ($msg, $color) = @_; | |||
| 167 | |||||||
| 168 | 504 | 450 | state $use_color = setup_color(); | ||||
| 169 | |||||||
| 170 | 504 | 493 | if ($use_color) { | ||||
| 171 | 0 | 0 | return Term::ANSIColor::colored($msg, $color); | ||||
| 172 | } else { | ||||||
| 173 | 504 | 621 | return $msg; | ||||
| 174 | } | ||||||
| 175 | } | ||||||
| 176 | |||||||
| 177 | sub _progname_prefix | ||||||
| 178 | { | ||||||
| 179 | 252 | 524 | return report_pretty("$Dpkg::PROGNAME: ", report_color(REPORT_PROGNAME)); | ||||
| 180 | } | ||||||
| 181 | |||||||
| 182 | sub _typename_prefix | ||||||
| 183 | { | ||||||
| 184 | 252 | 200 | my $type = shift; | ||||
| 185 | |||||||
| 186 | 252 | 315 | return report_pretty(report_name($type), report_color($type)); | ||||
| 187 | } | ||||||
| 188 | |||||||
| 189 | sub report(@) | ||||||
| 190 | { | ||||||
| 191 | 252 | 0 | 395 | my ($type, $msg, @args) = @_; | |||
| 192 | |||||||
| 193 | 252 | 756 | $msg = sprintf $msg, @args if @args; | ||||
| 194 | |||||||
| 195 | 252 | 396 | my $progname = _progname_prefix(); | ||||
| 196 | 252 | 368 | my $typename = _typename_prefix($type); | ||||
| 197 | |||||||
| 198 | 252 | 2221 | return "$progname$typename: $msg\n"; | ||||
| 199 | } | ||||||
| 200 | |||||||
| 201 | sub debug | ||||||
| 202 | { | ||||||
| 203 | 0 | 0 | 0 | my ($level, @args) = @_; | |||
| 204 | |||||||
| 205 | 0 | 0 | print report(REPORT_DEBUG, @args) if $level <= $debug_level; | ||||
| 206 | } | ||||||
| 207 | |||||||
| 208 | sub info($;@) | ||||||
| 209 | { | ||||||
| 210 | 0 | 0 | 0 | my @args = @_; | |||
| 211 | |||||||
| 212 | 0 0 | 0 0 | print { $info_fh } report(REPORT_INFO, @args) if not $quiet_warnings; | ||||
| 213 | } | ||||||
| 214 | |||||||
| 215 | sub notice | ||||||
| 216 | { | ||||||
| 217 | 0 | 0 | 0 | my @args = @_; | |||
| 218 | |||||||
| 219 | 0 | 0 | warn report(REPORT_NOTICE, @args) if not $quiet_warnings; | ||||
| 220 | } | ||||||
| 221 | |||||||
| 222 | sub warning($;@) | ||||||
| 223 | { | ||||||
| 224 | 67278 | 0 | 181655 | my @args = @_; | |||
| 225 | |||||||
| 226 | 67278 | 136124 | warn report(REPORT_WARN, @args) if not $quiet_warnings; | ||||
| 227 | } | ||||||
| 228 | |||||||
| 229 | sub syserr($;@) | ||||||
| 230 | { | ||||||
| 231 | 6 | 0 | 12 | my ($msg, @args) = @_; | |||
| 232 | |||||||
| 233 | 6 | 37 | die report(REPORT_ERROR, "$msg: $!", @args); | ||||
| 234 | } | ||||||
| 235 | |||||||
| 236 | sub error($;@) | ||||||
| 237 | { | ||||||
| 238 | 186 | 0 | 314 | my @args = @_; | |||
| 239 | |||||||
| 240 | 186 | 348 | die report(REPORT_ERROR, @args); | ||||
| 241 | } | ||||||
| 242 | |||||||
| 243 | sub errormsg($;@) | ||||||
| 244 | { | ||||||
| 245 | 0 | 0 | 0 | my @args = @_; | |||
| 246 | |||||||
| 247 | 0 0 | 0 0 | print { *STDERR } report(REPORT_ERROR, @args); | ||||
| 248 | } | ||||||
| 249 | |||||||
| 250 | sub printcmd | ||||||
| 251 | { | ||||||
| 252 | 0 | 0 | 0 | my (@cmd) = @_; | |||
| 253 | |||||||
| 254 | 0 0 | 0 0 | print { *STDERR } report_pretty(" @cmd\n", report_color(REPORT_COMMAND)); | ||||
| 255 | } | ||||||
| 256 | |||||||
| 257 | sub subprocerr(@) | ||||||
| 258 | { | ||||||
| 259 | 3 | 0 | 5 | my ($p, @args) = @_; | |||
| 260 | |||||||
| 261 | 3 | 10 | $p = sprintf $p, @args if @args; | ||||
| 262 | |||||||
| 263 | 3 | 23 | require POSIX; | ||||
| 264 | |||||||
| 265 | 3 | 13 | if (POSIX::WIFEXITED($?)) { | ||||
| 266 | 3 | 5 | my $ret = POSIX::WEXITSTATUS($?); | ||||
| 267 | 3 | 14 | error(g_('%s subprocess returned exit status %d'), $p, $ret); | ||||
| 268 | } elsif (POSIX::WIFSIGNALED($?)) { | ||||||
| 269 | 0 | my $sig = POSIX::WTERMSIG($?); | |||||
| 270 | 0 | error(g_('%s subprocess was killed by signal %d'), $p, $sig); | |||||
| 271 | } else { | ||||||
| 272 | 0 | error(g_('%s subprocess failed with unknown status code %d'), $p, $?); | |||||
| 273 | } | ||||||
| 274 | } | ||||||
| 275 | |||||||
| 276 | sub usageerr(@) | ||||||
| 277 | { | ||||||
| 278 | 0 | 0 | my ($msg, @args) = @_; | ||||
| 279 | |||||||
| 280 | 0 | state $printforhelp = g_('Use --help for program usage information.'); | |||||
| 281 | |||||||
| 282 | 0 | $msg = sprintf $msg, @args if @args; | |||||
| 283 | 0 | warn report(REPORT_ERROR, $msg); | |||||
| 284 | 0 | warn "\n$printforhelp\n"; | |||||
| 285 | 0 | exit(2); | |||||
| 286 | } | ||||||
| 287 | |||||||
| 288 - 294 | =head1 CHANGES =head2 Version 0.xx This is a private module. =cut | ||||||
| 295 | |||||||
| 296 | 1; | ||||||