File Coverage

blib/lib/CPAN/Reporter/Config.pm
Criterion Covered Total %
statement 178 215 82.7
branch 63 90 70.0
condition 23 37 62.1
subroutine 34 35 97.1
pod n/a
total 298 377 79.0


line stmt bran cond sub pod time code
1 60     60   5630 use strict;
  60         110  
  60         1951  
2             package CPAN::Reporter::Config;
3              
4             our $VERSION = '1.2017';
5              
6 59     59   13141 use Config::Tiny 2.08 ();
  59         22713  
  59         929  
7 59     59   389 use File::Glob ();
  59         102  
  59         796  
8 57     57   306 use File::HomeDir 0.58 ();
  57         542  
  57         897  
9 54     54   284 use File::Path qw/mkpath/;
  54         419  
  54         1783  
10 53     53   294 use File::Spec 3.19 ();
  53         451  
  53         757  
11 53     53   21274 use IPC::Cmd 0.76 ();
  53         1066502  
  53         1030  
12 44     44   270 use IO::File ();
  44         58  
  44         662  
13 39     39   118 use CPAN 1.9301 (); # for printing warnings
  39         432  
  39         81480  
14              
15             #--------------------------------------------------------------------------#
16             # Back-compatibility checks -- just once per load
17             #--------------------------------------------------------------------------#
18              
19             # 0.28_51 changed Mac OS X config file location -- if old directory is found,
20             # move it to the new location
21             if ( $^O eq 'darwin' ) {
22                 my $old = File::Spec->catdir(File::HomeDir->my_documents,".cpanreporter");
23                 my $new = File::Spec->catdir(File::HomeDir->my_home,".cpanreporter");
24                 if ( ( -d $old ) && (! -d $new ) ) {
25                     $CPAN::Frontend->mywarn( << "HERE");
26             CPAN::Reporter: since CPAN::Reporter 0.28_51, the Mac OSX config directory
27             has changed.
28            
29             Old: $old
30             New: $new
31            
32             Your existing configuration file will be moved automatically.
33             HERE
34                     mkpath($new);
35                     my $OLD_CONFIG = IO::File->new(
36                         File::Spec->catfile($old, "config.ini"), "<"
37                     ) or die $!;
38                     my $NEW_CONFIG = IO::File->new(
39                         File::Spec->catfile($new, "config.ini"), ">"
40                     ) or die $!;
41                     $NEW_CONFIG->print( do { local $/; <$OLD_CONFIG> } );
42                     $OLD_CONFIG->close;
43                     $NEW_CONFIG->close;
44                     unlink File::Spec->catfile($old, "config.ini") or die $!;
45                     rmdir($old) or die $!;
46                 }
47             }
48              
49             #--------------------------------------------------------------------------#
50             # Public
51             #--------------------------------------------------------------------------#
52              
53             sub _configure {
54 2     2   5     my $config_dir = _get_config_dir();
55 2         3     my $config_file = _get_config_file();
56              
57 2 50       22     mkpath $config_dir if ! -d $config_dir;
58 2 50       17     if ( ! -d $config_dir ) {
59 0         0         $CPAN::Frontend->myprint(
60                         "\nCPAN::Reporter: couldn't create configuration directory '$config_dir': $!"
61                     );
62 0         0         return;
63                 }
64              
65 2         3     my $config;
66                 my $existing_options;
67              
68             # explain grade:action pairs
69 2         4     $CPAN::Frontend->myprint( _grade_action_prompt() );
70              
71             # read or create
72 2 100       102     if ( -f $config_file ) {
73 1         5         $CPAN::Frontend->myprint(
74                         "\nCPAN::Reporter: found your CPAN::Reporter config file at:\n$config_file\n"
75                     );
76 1         9         $config = _open_config_file();
77             # if we can't read it, bail out
78 1 50       4         if ( ! $config ) {
79 0         0             $CPAN::Frontend->mywarn("\n
80             CPAN::Reporter: configuration will not be changed\n");
81 0         0             return;
82                     }
83             # clone what's in the config file
84 1 50       3         $existing_options = { %{$config->{_}} } if $config;
  1         4  
85 1         4         $CPAN::Frontend->myprint(
86                         "\nCPAN::Reporter: Updating your CPAN::Reporter configuration settings:\n"
87                     );
88                 }
89                 else {
90 1         3         $CPAN::Frontend->myprint(
91                         "\nCPAN::Reporter: no config file found; creating a new one.\n"
92                     );
93 1         13         $config = Config::Tiny->new();
94                 }
95              
96 2         17     my %spec = _config_spec();
97              
98 2         6     for my $k ( _config_order() ) {
99 8         10         my $option_data = $spec{$k};
100 8         26         $CPAN::Frontend->myprint( "\n" . $option_data->{info}. "\n");
101             # options with defaults are mandatory
102 8 50       67         if ( defined $option_data->{default} ) {
103             # if we have a default, always show as a sane recommendation
104 8 100       15             if ( length $option_data->{default} ) {
105 6         14                 $CPAN::Frontend->myprint(
106                                 "(Recommended: '$option_data->{default}')\n\n"
107                             );
108                         }
109             # repeat until validated
110                         PROMPT:
111 8   66     62             while ( defined (
112                             my $answer = CPAN::Shell::colorable_makemaker_prompt(
113                                 "$k?",
114                                 $existing_options->{$k} || $option_data->{default}
115                             )
116                         )) {
117 8 50 66     221                 if ( ! $option_data->{validate} ||
118                                     $option_data->{validate}->($k, $answer, $config->{_})
119                                 ) {
120 8         17                     $config->{_}{$k} = $answer;
121 8         10                     last PROMPT;
122                             }
123                         }
124                     }
125                     else {
126             # only initialize options without default if
127             # answer matches non white space and validates,
128             # otherwise reset it
129                         my $answer = CPAN::Shell::colorable_makemaker_prompt(
130                             "$k?",
131 0   0     0                 $existing_options->{$k} || q{}
132                         );
133 0 0       0             if ( $answer =~ /\S/ ) {
134 0         0                 $config->{_}{$k} = $answer;
135                         }
136                         else {
137 0         0                 delete $config->{_}{$k};
138                         }
139                     }
140             # delete existing as we proceed so we know what's left
141 8         16         delete $existing_options->{$k};
142                 }
143              
144             # initialize remaining existing options
145                 $CPAN::Frontend->myprint(
146 2 100       9         "\nYour CPAN::Reporter config file also contains these advanced " .
147                       "options:\n\n") if keys %$existing_options;
148 2         14     for my $k ( keys %$existing_options ) {
149                     $config->{_}{$k} = CPAN::Shell::colorable_makemaker_prompt(
150 2         29             "$k?", $existing_options->{$k}
151                     );
152                 }
153              
154                 $CPAN::Frontend->myprint(
155 2         27         "\nCPAN::Reporter: writing config file to '$config_file'.\n"
156                 );
157 2 50       21     if ( $config->write( $config_file ) ) {
158 2         257         return $config->{_};
159                 }
160                 else {
161 0         0         $CPAN::Frontend->mywarn( "\nCPAN::Reporter: error writing config file to '$config_file':\n"
162                         . Config::Tiny->errstr(). "\n");
163 0         0         return;
164                 }
165             }
166              
167             #--------------------------------------------------------------------------#
168             # Private
169             #--------------------------------------------------------------------------#
170              
171             #--------------------------------------------------------------------------#
172             # _config_order -- determines order of interactive config. Only items
173             # in interactive config will be written to a starter config file
174             #--------------------------------------------------------------------------#
175              
176             sub _config_order {
177 2     2   5     return qw(
178             email_from
179             edit_report
180             send_report
181             transport
182             );
183             }
184              
185             #--------------------------------------------------------------------------#
186             # _config_spec -- returns configuration options information
187             #
188             # Keys include
189             # default -- recommended value, used in prompts and as a fallback
190             # if an options is not set; mandatory if defined
191             # prompt -- short prompt for EU::MM prompting
192             # info -- long description shown before prompting
193             # validate -- CODE ref; return normalized option or undef if invalid
194             #--------------------------------------------------------------------------#
195              
196             my %option_specs = (
197                 email_from => {
198                     default => '',
199                     prompt => 'What email address will be used to reference your reports?',
200                     info => <<'HERE',
201             CPAN::Reporter requires a valid email address to identify senders
202             in the body of a test report. Please use a standard email format
203             like: "John Doe" <jdoe@example.com>
204             HERE
205                 },
206                 smtp_server => {
207                     default => undef, # (deprecated)
208                     prompt => "[DEPRECATED] It's safe to remove this from your config file.",
209                 },
210                 edit_report => {
211                     default => 'default:ask/no pass/na:no',
212                     prompt => "Do you want to review or edit the test report?",
213                     validate => \&_validate_grade_action_pair,
214                     info => <<'HERE',
215             Before test reports are sent, you may want to review or edit the test
216             report and add additional comments about the result or about your system
217             or Perl configuration. By default, CPAN::Reporter will ask after
218             each report is generated whether or not you would like to edit the
219             report. This option takes "grade:action" pairs.
220             HERE
221                 },
222                 send_report => {
223                     default => 'default:ask/yes pass/na:yes',
224                     prompt => "Do you want to send the report?",
225                     validate => \&_validate_grade_action_pair,
226                     info => <<'HERE',
227             By default, CPAN::Reporter will prompt you for confirmation that
228             the test report should be sent before actually doing it. This
229             gives the opportunity to skip sending particular reports if
230             you need to (e.g. if you caused the failure). This option takes
231             "grade:action" pairs.
232             HERE
233                 },
234                 transport => {
235                     default => 'Metabase uri https://metabase.cpantesters.org/api/v1/ id_file metabase_id.json',
236                     prompt => 'Which transport system will be used to transmit the reports?',
237                     validate => \&_validate_transport,
238                     info => <<'HERE',
239             CPAN::Reporter sends your reports over HTTPS using Metabase. This option lets
240             you set a different uri, transport mechanism and metabase profile path. If you
241             are receiving HTTPS errors, you may change the uri to use plain HTTP, though
242             this is not recommended. Unless you know what you're doing, just accept
243             the default value.
244             HERE
245                 },
246                 send_duplicates => {
247                     default => 'default:no',
248                     prompt => "This report is identical to a previous one. Send it anyway?",
249                     validate => \&_validate_grade_action_pair,
250                     info => <<'HERE',
251             CPAN::Reporter records tests grades for each distribution, version and
252             platform. By default, duplicates of previous results will not be sent at
253             all, regardless of the value of the "send_report" option. This option takes
254             "grade:action" pairs.
255             HERE
256                 },
257                 send_PL_report => {
258                     prompt => "Do you want to send the PL report?",
259                     default => undef,
260                     validate => \&_validate_grade_action_pair,
261                 },
262                 send_make_report => {
263                     prompt => "Do you want to send the make/Build report?",
264                     default => undef,
265                     validate => \&_validate_grade_action_pair,
266                 },
267                 send_test_report => {
268                     prompt => "Do you want to send the test report?",
269                     default => undef,
270                     validate => \&_validate_grade_action_pair,
271                 },
272                 send_skipfile => {
273                     prompt => "What file has patterns for things that shouldn't be reported?",
274                     default => undef,
275                     validate => \&_validate_skipfile,
276                 },
277                 cc_skipfile => {
278                     prompt => "What file has patterns for things that shouldn't CC to authors?",
279                     default => undef,
280                     validate => \&_validate_skipfile,
281                 },
282                 command_timeout => {
283                     prompt => "If no timeout is set by CPAN, halt system commands after how many seconds?",
284                     default => undef,
285                     validate => \&_validate_seconds,
286                 },
287                 email_to => {
288                     default => undef,
289                 },
290                 editor => {
291                     default => undef,
292                 },
293                 debug => {
294                     default => undef,
295                 },
296                 retry_submission => {
297                     default => undef,
298                 },
299                 '_store_problems_in_dir' => { #experimental
300                     default => undef,
301                 },
302                 '_problem_log' => { #experimental
303                     default => undef,
304                 },
305             );
306              
307 635     635   8070 sub _config_spec { return %option_specs }
308              
309             #--------------------------------------------------------------------------#
310             # _generate_profile
311             #
312             # Run 'metabase-profile' in the .cpanreporter directory
313             #--------------------------------------------------------------------------#
314              
315             sub _generate_profile {
316 0     0   0     my ($id_file, $config) = @_;
317              
318 0         0     my $cmd = IPC::Cmd::can_run('metabase-profile');
319 0 0       0     return unless $cmd;
320              
321             # XXX this is an evil assumption about email addresses, but
322             # might do for simple cases that users might actually provide
323              
324 0         0     my @opts = ("--output" => $id_file);
325 0         0     my $email = $config->{email_from};
326              
327 0 0       0     if ($email =~ /\A(.+)\s+<([^>]+)>\z/ ) {
328 0         0         push @opts, "--email" => $2;
329 0         0         my $name = $1;
330 0         0         $name =~ s/\A["'](.*)["']\z/$1/;
331 0 0       0         push ( @opts, "--name" => $1)
332                         if length $name;
333                 }
334                 else {
335 0         0         push @opts, "--email" => $email;
336                 }
337              
338             # XXX profile 'secret' is really just a generated API key, so we
339             # can create something fairly random for the user and use that
340 0         0     push @opts, "--secret" => sprintf("%08x", rand(2**31));
341              
342 0         0     return scalar IPC::Cmd::run(
343                     command => [ $cmd, @opts ],
344                     verbose => 1,
345                 );
346             }
347              
348             #--------------------------------------------------------------------------#
349             # _get_config_dir
350             #--------------------------------------------------------------------------#
351              
352             sub _get_config_dir {
353 1371 100 66 1371   6663     if ( defined $ENV{PERL_CPAN_REPORTER_DIR} &&
354                      length $ENV{PERL_CPAN_REPORTER_DIR}
355                 ) {
356 3         18         return $ENV{PERL_CPAN_REPORTER_DIR};
357                 }
358              
359 1368         6896     my $conf_dir = File::Spec->catdir(File::HomeDir->my_home, ".cpanreporter");
360              
361 1368 50       13330     if ($^O eq 'MSWin32') {
362 0         0       my $alt_dir = File::Spec->catdir(File::HomeDir->my_documents, ".cpanreporter");
363 0 0 0     0       $conf_dir = $alt_dir if -d $alt_dir && ! -d $conf_dir;
364                 }
365              
366 1368         10685     return $conf_dir;
367             }
368              
369             #--------------------------------------------------------------------------#
370             # _get_config_file
371             #--------------------------------------------------------------------------#
372              
373             sub _get_config_file {
374 498 100 66 498   2416     if ( defined $ENV{PERL_CPAN_REPORTER_CONFIG} &&
375                       length $ENV{PERL_CPAN_REPORTER_CONFIG}
376                 ) {
377 2         6         return $ENV{PERL_CPAN_REPORTER_CONFIG};
378                 }
379                 else {
380 496         1234         return File::Spec->catdir( _get_config_dir, "config.ini" );
381                 }
382             }
383              
384             #--------------------------------------------------------------------------#
385             # _get_config_options
386             #--------------------------------------------------------------------------#
387              
388             sub _get_config_options {
389 305     305   21038     my $config = shift;
390             # extract and return valid options, with fallback to defaults
391 305         862     my %spec = CPAN::Reporter::Config::_config_spec();
392 305         730     my %active;
393 305         1241     OPTION: for my $option ( keys %spec ) {
394 5490 100       6342         if ( exists $config->{_}{$option} ) {
395 1576         1869             my $val = $config->{_}{$option};
396 1576 100 100     5486             if ( $spec{$option}{validate} &&
397                                 ! $spec{$option}{validate}->($option, $val)
398                             ) {
399 5         26                     $CPAN::Frontend->mywarn( "\nCPAN::Reporter: invalid option '$val' in '$option'. Using default instead.\n\n" );
400 5         117                     $active{$option} = $spec{$option}{default};
401 5         14                     next OPTION;
402                         }
403 1571         2950             $active{$option} = $val;
404                     }
405                     else {
406                         $active{$option} = $spec{$option}{default}
407 3914 100       7315                 if defined $spec{$option}{default};
408                     }
409                 }
410 305         1545     return \%active;
411             }
412              
413              
414             #--------------------------------------------------------------------------#
415             # _grade_action_prompt -- describes grade action pairs
416             #--------------------------------------------------------------------------#
417              
418             sub _grade_action_prompt {
419 2     2   11     return << 'HERE';
420            
421             Some of the following configuration options require one or more "grade:action"
422             pairs that determine what grade-specific action to take for that option.
423             These pairs should be space-separated and are processed left-to-right. See
424             CPAN::Reporter documentation for more details.
425            
426             GRADE : ACTION ======> EXAMPLES
427             ------- ------- --------
428             pass yes default:no
429             fail no default:yes pass:no
430             unknown ask/no default:ask/no pass:yes fail:no
431             na ask/yes
432             default
433            
434             HERE
435             }
436              
437             #--------------------------------------------------------------------------#
438             # _is_valid_action
439             #--------------------------------------------------------------------------#
440              
441             my @valid_actions = qw{ yes no ask/yes ask/no ask };
442             sub _is_valid_action {
443 1449     1449   1347     my $action = shift;
444 1449         1645     return grep { $action eq $_ } @valid_actions;
  7245         8373  
445             }
446              
447             #--------------------------------------------------------------------------#
448             # _is_valid_grade
449             #--------------------------------------------------------------------------#
450              
451             my @valid_grades = qw{ pass fail unknown na default };
452             sub _is_valid_grade {
453 765     765   657     my $grade = shift;
454 765         690     return grep { $grade eq $_ } @valid_grades;
  3825         4741  
455             }
456              
457              
458             #--------------------------------------------------------------------------#
459             # _normalize_id_file
460             #--------------------------------------------------------------------------#
461              
462             sub _normalize_id_file {
463 422     422   2213     my ($id_file) = @_;
464              
465             # Windows does not use ~ to signify a home directory
466 422 50 33     2386     if ( $^O eq 'MSWin32' && $id_file =~ m{^~/(.*)} ) {
    100          
467 0         0         $id_file = File::Spec->catdir(File::HomeDir->my_home, $1);
468                 }
469                 elsif ( $id_file =~ /~/ ) {
470 1         57         $id_file = File::Spec->canonpath(File::Glob::bsd_glob( $id_file ));
471                 }
472 422 100       3994     unless ( File::Spec->file_name_is_absolute( $id_file ) ) {
473 419         830         $id_file = File::Spec->catfile(
474                         CPAN::Reporter::Config::_get_config_dir(), $id_file
475                     );
476                 }
477 422         1167     return $id_file;
478             }
479              
480             #--------------------------------------------------------------------------#
481             # _open_config_file
482             #--------------------------------------------------------------------------#
483              
484             sub _open_config_file {
485 305     305   2265     my $config_file = _get_config_file();
486 305 100       3615     my $config = Config::Tiny->read( $config_file )
487                     or $CPAN::Frontend->mywarn("CPAN::Reporter: couldn't read configuration file " .
488                             "'$config_file': \n" . Config::Tiny->errstr() . "\n");
489 305         50392     return $config;
490             }
491              
492             #--------------------------------------------------------------------------#
493             # _validate
494             #
495             # anything is OK if there is no validation subroutine
496             #--------------------------------------------------------------------------#
497              
498             sub _validate {
499 8     8   2716     my ($name, $value) = @_;
500 8 50       21     return 1 if ! exists $option_specs{$name}{validate};
501 8         15     return $option_specs{$name}{validate}->($name, $value);
502             }
503              
504             #--------------------------------------------------------------------------#
505             # _validate_grade_action
506             # returns hash of grade => action
507             # returns undef
508             #--------------------------------------------------------------------------#
509              
510             sub _validate_grade_action_pair {
511 973     973   22149     my ($name, $option) = @_;
512 973   100     1584     $option ||= "no";
513              
514 973         889     my %ga_map; # grade => action
515              
516 973         2376     PAIR: for my $grade_action ( split q{ }, $option ) {
517 1448         1134         my ($grade_list,$action);
518              
519 1448 100       4188         if ( $grade_action =~ m{.:.} ) {
    100          
    100          
    100          
520             # parse pair for later check
521 632         2057             ($grade_list, $action) = $grade_action =~ m{\A([^:]+):(.+)\z};
522                     }
523                     elsif ( _is_valid_action($grade_action) ) {
524             # action by itself
525 813         1561             $ga_map{default} = $grade_action;
526 813         1573             next PAIR;
527                     }
528                     elsif ( _is_valid_grade($grade_action) ) {
529             # grade by itself
530 1         2             $ga_map{$grade_action} = "yes";
531 1         3             next PAIR;
532                     }
533                     elsif( $grade_action =~ m{./.} ) {
534             # gradelist by itself, so setup for later check
535 1         2             $grade_list = $grade_action;
536 1         1             $action = "yes";
537                     }
538                     else {
539             # something weird, so warn and skip
540 1         25             $CPAN::Frontend->mywarn(
541                             "\nCPAN::Reporter: ignoring invalid grade:action '$grade_action' for '$name'.\n\n"
542                         );
543 1         38             next PAIR;
544                     }
545              
546             # check gradelist
547 633         1082         my %grades = map { ($_,1) } split( "/", $grade_list);
  762         1912  
548 633         1081         for my $g ( keys %grades ) {
549 762 100       1001             if ( ! _is_valid_grade($g) ) {
550 1         8                 $CPAN::Frontend->mywarn(
551                                 "\nCPAN::Reporter: ignoring invalid grade '$g' in '$grade_action' for '$name'.\n\n"
552                             );
553 1         24                 delete $grades{$g};
554                         }
555                     }
556              
557             # check action
558 633 100       841         if ( ! _is_valid_action($action) ) {
559 2         12             $CPAN::Frontend->mywarn(
560                             "\nCPAN::Reporter: ignoring invalid action '$action' in '$grade_action' for '$name'.\n\n"
561                         );
562 2         31             next PAIR;
563                     }
564              
565             # otherwise, it all must be OK
566 631         2012         $ga_map{$_} = $action for keys %grades;
567                 }
568              
569 973 100       4039     return scalar(keys %ga_map) ? \%ga_map : undef;
570             }
571              
572             sub _validate_transport {
573 307     307   567     my ($name, $option, $config) = @_;
574 307         656     my $transport = '';
575              
576 307 50       1817     if ( $option =~ /^(\w+(?:::\w+)*)\s?/ ) {
577 307         563         $transport = $1;
578 307         664         my $full_class = "Test::Reporter::Transport::$transport";
579 307     22   31509         eval "use $full_class ()";
  22     22   161  
  22     21   38  
  22     21   250  
  22     20   196  
  22     20   34  
  22     20   312  
  21     20   228  
  21     14   62  
  21         253  
  21         220  
  21         50  
  21         262  
  20         450  
  19         55  
  19         250  
  20         522  
  19         48  
  19         239  
  20         416  
  19         52  
  19         234  
  20         390  
  19         40  
  19         232  
  14         144  
  14         39  
  14         183  
580 307 100       1076         if ($@) {
581 4         54             $CPAN::Frontend->mywarn(
582                             "\nCPAN::Reporter: error loading $full_class. Please install the missing module or choose a different transport mechanism.\n\n"
583                         );
584                     }
585                 }
586                 else {
587 0         0         $CPAN::Frontend->mywarn(
588                         "\nCPAN::Reporter: Please provide a transport mechanism.\n\n"
589                     );
590 0         0         return;
591                 }
592              
593             # we do extra validation for Metabase and offer to create the profile
594 307 100       960     if ( $transport eq 'Metabase' ) {
595 303 100       2047         unless ( $option =~ /\buri\s+\S+/ ) {
596 2         36             $CPAN::Frontend->mywarn(
597                             "\nCPAN::Reporter: Please provide a target uri.\n\n"
598                         );
599 2         42             return;
600                     }
601              
602 301 50       1846         unless ( $option =~ /\bid_file\s+(\S.+?)\s*$/ ) {
603 0         0             $CPAN::Frontend->mywarn(
604                             "\nCPAN::Reporter: Please specify an id_file path.\n\n"
605                         );
606 0         0             return;
607                     }
608              
609 301         886         my $id_file = _normalize_id_file($1);
610              
611             # Offer to create if it doesn't exist
612 301 50 33     7990         if ( ! -e $id_file ) {
    50          
613 0         0             my $answer = CPAN::Shell::colorable_makemaker_prompt(
614                             "\nWould you like to run 'metabase-profile' now to create '$id_file'?", "y"
615                         );
616 0 0       0             if ( $answer =~ /^y/i ) {
617 0         0                 return _generate_profile( $id_file, $config );
618                         }
619                         else {
620 0         0                 $CPAN::Frontend->mywarn( <<"END_ID_FILE" );
621             You can create a Metabase profile by typing 'metabase-profile' in your
622             command prompt and moving the resulting file to the location you specified.
623             If you did not specify an absolute path, put it in your .cpanreporter
624             directory. You will need to do this before continuing.
625             END_ID_FILE
626 0         0                 return;
627                         }
628                     }
629             # Warn and fail validation if there but not readable
630                     elsif (
631                         not ( -r $id_file
632                                 or -r File::Spec->catdir(_get_config_dir(), $id_file)
633                             )
634                     ) {
635 0         0             $CPAN::Frontend->mywarn(
636                             "CPAN::Reporter: '$id_file' was not readable.\n\n"
637                         );
638 0         0             return;
639                     }
640                 } # end Metabase
641              
642 305         1337     return 1;
643             }
644              
645             sub _validate_seconds {
646 22     22   39     my ($name, $option) = @_;
647 22 100 100     242     return unless defined($option) && length($option)
      100        
      66        
648                     && ($option =~ /^\d/) && $option >= 0;
649 18         51     return $option;
650             }
651              
652             sub _validate_skipfile {
653 16     16   25     my ($name, $option) = @_;
654 16 50       32     return unless $option;
655 16 100       130     my $skipfile = File::Spec->file_name_is_absolute( $option )
656                              ? $option : File::Spec->catfile( _get_config_dir(), $option );
657 16 100       241     return -r $skipfile ? $skipfile : undef;
658             }
659              
660             1;
661              
662             # ABSTRACT: Config file options for CPAN::Reporter
663              
664             =pod
665            
666             =encoding UTF-8
667            
668             =head1 NAME
669            
670             CPAN::Reporter::Config - Config file options for CPAN::Reporter
671            
672             =head1 VERSION
673            
674             version 1.2017
675            
676             =head1 SYNOPSIS
677            
678             From the CPAN shell:
679            
680             cpan> o conf init test_report
681            
682             =head1 DESCRIPTION
683            
684             Default options for CPAN::Reporter are read from a configuration file
685             C<<< .cpanreporter/config.ini >>> in the user's home directory. (On Win32 platforms,
686             the directory will be located in the user's "Documents" directory.)
687             The location of the configuration directory or file may be specified
688             using environment variables instead.
689            
690             The configuration file is in "ini" format, with the option name and value
691             separated by an "=" sign
692            
693             email_from = "John Doe" <johndoe@nowhere.org>
694             edit_report = no
695            
696             Interactive configuration of email address and common
697             action prompts may be repeated at any time from the CPAN shell.
698            
699             cpan> o conf init test_report
700            
701             If a configuration file does not exist, it will be created the first
702             time interactive configuration is performed.
703            
704             Subsequent interactive configuration will also include any advanced
705             options that have been added manually to the configuration file.
706            
707             =head1 INTERACTIVE CONFIGURATION OPTIONS
708            
709             =head2 Email Address (required)
710            
711             email_from = <email address>
712            
713             CPAN::Reporter requires users to provide an email address that will be used
714             in the header of the report.
715            
716             The email address provided should be a valid address format, e.g.:
717            
718             email_from = user@domain
719             email_from = John Doe <user@domain>
720             email_from = "John Q. Public" <user@domain>
721            
722             =head2 Transport (required)
723            
724             transport = <transport class> [transport args]
725            
726             This sets the transport mechanism passed to the C<<< transport() >>> method of
727             L<Test::Reporter>. Normally, CPAN::Reporter uses 'Metabase' for transport class
728             (i.e. L<Test::Reporter::Transport::Metabase>) and will provide a default set of
729             transport arguments.
730            
731             Metabase transport arguments are two space-separated keyE<sol>value pairs:
732            
733             =over
734            
735             =item *
736            
737             C<<< uri >>> -- URI for the Metabase API. Defaults to
738             C<<< https://metabase.cpantesters.org/api/v1/ >>>
739            
740             =item *
741            
742             C<<< id_file >>> -- path to the user's Metabase profile file.
743             Defaults to C<<< metabase_id.json >>>. (Assumed to be in the C<<< .cpanreporter >>>
744             directory).
745            
746             =back
747            
748             Prior to sending reports, a user must have a valid profile file at the path
749             specified. For Metabase transport, CPAN::Reporter will automatically rewrite a
750             relative C<<< id_file >>> path as an absolute path located in the C<<< .cpanreporter >>>
751             directory.
752            
753             If the specified profile file does not exist, CPAN::Reporter will offer
754             to run C<<< metabase-profile >>> to create it.
755            
756             For other transport types, see the documentation that comes with your choice of
757             Test::Reporter::Transport subclass for the proper way to set the C<<< transport >>>
758             configuration option.
759            
760             =head2 Action Prompts
761            
762             Several steps in the generation of a test report are optional. Configuration
763             options control whether an action should be taken automatically or whether
764             CPAN::Reporter should prompt the user for the action to take. The action to
765             take may be different for each report grade. For example, users may wish to
766             customize for which grades they wish to manually review a report before sending
767             it.
768            
769             Most users should just accept the default settings until they have some
770             experience as CPAN Testers.
771            
772             Valid actions, and their associated meaning, are as follows:
773            
774             =over
775            
776             =item *
777            
778             C<<< yes >>> -- automatic yes
779            
780             =item *
781            
782             C<<< no >>> -- automatic no
783            
784             =item *
785            
786             C<<< ask/no >>> or just C<<< ask >>> -- ask each time, but default to no
787            
788             =item *
789            
790             C<<< ask/yes >>> -- ask each time, but default to yes
791            
792             =back
793            
794             For "ask" prompts, the default will be used if return is pressed immediately at
795             the prompt or if the C<<< PERL_MM_USE_DEFAULT >>> environment variable is set to a
796             true value.
797            
798             Action prompt options take one or more space-separated "grade:action" pairs,
799             which are processed left to right.
800            
801             edit_report = fail:ask/yes pass:no
802            
803             An action by itself is taken as a default to be used for any grade which does
804             not have a grade-specific action. A default action may also be set by using
805             the word "default" in place of a grade.
806            
807             edit_report = ask/no
808             edit_report = default:ask/no
809            
810             A grade by itself is taken to have the action "yes" for that grade.
811            
812             edit_report = default:no fail
813            
814             Multiple grades may be specified together by separating them with a slash.
815            
816             edit_report = pass:no fail/na/unknown:ask/yes
817            
818             The action prompt options included in interactive configuration are:
819            
820             =over
821            
822             =item *
823            
824             C<<< edit_report = <grade:action> ... >>> -- edit the test report before sending?
825             (default:askE<sol>no passE<sol>na:no)
826            
827             =item *
828            
829             C<<< send_report = <grade:action> ... >>> -- should test reports be sent at all?
830             (default:askE<sol>yes passE<sol>na:yes)
831            
832             =back
833            
834             Note that if C<<< send_report >>> is set to "no", CPAN::Reporter will still go through
835             the motions of preparing a report, but will discard it rather than send it.
836            
837             A better way to disable CPAN::Reporter temporarily is with the CPAN option
838             C<<< test_report >>>:
839            
840             cpan> o conf test_report 0
841            
842             =head2 Mail Server (DEPRECATED)
843            
844             CPAN::Reporter used to send mail directly to perl.org mail servers. The
845             C<<< smtp_server >>> option is now deprecated and will be ignored if it exists.
846            
847             =head1 ADVANCED CONFIGURATION OPTIONS
848            
849             These additional options are only necessary in special cases, for example if
850             the default editor cannot be found or if reports shouldn't be sent in
851             certain situations or for automated testing, and so on.
852            
853             =over
854            
855             =item *
856            
857             C<<< command_timeout >>> -- if greater than zero and the CPAN config is
858             C<<< inactivity_timeout >>> is not set, then any commands executed by CPAN::Reporter
859             will be halted after this many seconds; useful for unattended smoke testing
860             to stop after some amount of time; generally, this should be large --
861             900 seconds or more -- as some distributions' tests take quite a long time to
862             run. On MSWin32, L<Win32::Job> is a needed and trying to kill a process may
863             actually deadlock in some situations -- so use at your own risk.
864            
865             =item *
866            
867             C<<< editor = <editor> >>> -- editor to use to edit the test report; if not set,
868             Test::Reporter will use environment variables C<<< VISUAL >>>, C<<< EDITOR >>> or C<<< EDIT >>>
869             (in that order) to find an editor
870            
871             =item *
872            
873             C<<< retry_submission >>> -- if greater than zero, CPAN::Reporter will try to
874             resend the report after a few seconds in case the first attempt fails.
875            
876             =item *
877            
878             C<<< send_duplicates = <grade:action> ... >>> -- should duplicates of previous
879             reports be sent, regardless of C<<< send_report >>>? (default:no)
880            
881             =item *
882            
883             C<<< send_PL_report = <grade:action> ... >>> -- if defined, used in place of
884             C<<< send_report >>> during the PL phase
885            
886             =item *
887            
888             C<<< send_make_report = <grade:action> ... >>> -- if defined, used in place of
889             C<<< send_report >>> during the make phase
890            
891             =item *
892            
893             C<<< send_test_report = <grade:action> ... >>> -- if defined, used in place of
894             C<<< send_report >>> during the test phase
895            
896             =item *
897            
898             C<<< send_skipfile = <skipfile> >>> -- filename containing regular expressions (one
899             per line) to match against the distribution ID (e.g.
900             'AUTHORE<sol>Dist-Name-0.01.tar.gz'); the report will not be sent if a match is
901             found; non-absolute filename must be in the .cpanreporter config directory;
902            
903             =back
904            
905             If these options are manually added to the configuration file, they will
906             be included (and preserved) in subsequent interactive configuration.
907            
908             =head2 Skipfile regular expressions
909            
910             Skip files are expected to have one regular expression per line and will be
911             matched against the distribution ID, composed of the author's CPAN ID and the
912             distribution tarball name.
913            
914             DAGOLDEN/CPAN-Reporter-1.00.tar.gz
915            
916             Lines that begin with a sharp (#) are considered comments and will not be
917             matched. All regular expressions will be matched case insensitive and will
918             not be anchored unless you provide one.
919            
920             As the format of a distribution ID is "AUTHORE<sol>tarball", anchoring at the
921             start of the line with a caret (^) will match the author and with a slash (E<sol>)
922             will match the distribution.
923            
924             # any distributions by JOHNDOE
925             ^JOHNDOE
926             # any distributions starting with Win32
927             /Win32
928             # a particular very specific distribution
929             ^JOHNDOE/Foo-Bar-3.14
930            
931             =head1 CONFIGURATION OPTIONS FOR DEBUGGING
932            
933             These options are useful for debugging only:
934            
935             =over
936            
937             =item *
938            
939             C<<< debug = <boolean> >>> -- turns debugging onE<sol>off
940            
941             =back
942            
943             =head1 ENVIRONMENT
944            
945             The following environment variables may be set to alter the default locations
946             for CPAN::Reporter files:
947            
948             =over
949            
950             =item *
951            
952             C<<< PERL_CPAN_REPORTER_DIR >>> -- if set, this directory is used in place of
953             the default C<<< .cpanreporter >>> directory; this will affect not only the location
954             of the default C<<< config.ini >>>, but also the location of the
955             L<CPAN::Reporter::History> database and any other files that live in that
956             directory
957            
958             =item *
959            
960             C<<< PERL_CPAN_REPORTER_CONFIG >>> -- if set, this file is used in place of
961             the default C<<< config.ini >>> file; it may be in any directory, regardless of the
962             choice of configuration directory
963            
964             =back
965            
966             =head1 SEE ALSO
967            
968             =over
969            
970             =item *
971            
972             L<CPAN::Reporter>
973            
974             =item *
975            
976             L<CPAN::Reporter::History>
977            
978             =item *
979            
980             L<CPAN::Reporter::FAQ>
981            
982             =back
983            
984             =head1 AUTHOR
985            
986             David Golden <dagolden@cpan.org>
987            
988             =head1 COPYRIGHT AND LICENSE
989            
990             This software is Copyright (c) 2006 by David Golden.
991            
992             This is free software, licensed under:
993            
994             The Apache License, Version 2.0, January 2004
995            
996             =cut
997              
998             __END__
999            
1000            
1001             # vim: ts=4 sts=4 sw=4 et:
1002