File Coverage

blib/lib/App/CISetup/Role/ConfigFile.pm
Criterion Covered Total %
statement 70 71 98.5
branch 6 8 75.0
condition 2 3 66.6
subroutine 15 16 93.7
pod 0 2 0.0
total 93 100 93.0


line stmt bran cond sub pod time code
1             package App::CISetup::Role::ConfigFile;
2              
3 1     1   879 use strict;
  1         3  
  1         37  
4 1     1   7 use warnings;
  1         3  
  1         39  
5 1     1   5 use namespace::autoclean;
  1         2  
  1         14  
6 1     1   92 use autodie qw( :all );
  1         4  
  1         9  
7              
8             our $VERSION = '0.19';
9              
10 1     1   6279 use App::CISetup::Types qw( Path );
  1         11  
  1         20  
11 1     1   3254 use Try::Tiny;
  1         2  
  1         72  
12 1     1   663 use YAML qw( Dump LoadFile );
  1         7480  
  1         92  
13              
14 1     1   11 use Moose::Role;
  1         1  
  1         17  
15              
16             requires qw(
17             _cisetup_flags
18             _create_config
19             _fix_up_yaml
20             _update_config
21             );
22              
23             has file => (
24             is => 'ro',
25             isa => Path,
26             coerce => 1,
27             required => 1,
28             );
29              
30             sub create_file {
31 6     6 0 16 my $self = shift;
32              
33 6         221 $self->file->spew( $self->_config_to_yaml( $self->_create_config ) );
34              
35 6         3260 return;
36             }
37              
38             sub update_file {
39 8     8 0 21 my $self = shift;
40              
41 8         304 my $file = $self->file;
42 8         46 my $orig = $file->slurp;
43              
44             my $content = try {
45 8     8   504 LoadFile($file);
46             }
47             catch {
48 0     0   0 die "YAML parsing error: $_\n";
49 8         1807 };
50              
51 8 50       60499 return 0 unless $content;
52              
53 8         68 my $config = $self->_update_config($content);
54 8         49 my $yaml = $self->_config_to_yaml($config);
55              
56 8 100       81 return 0 if $yaml eq $orig;
57              
58 5         35 $file->spew($yaml);
59              
60 5         2910 return 1;
61             }
62              
63             sub _config_to_yaml {
64 14     14   37 my $self = shift;
65 14         26 my $config = shift;
66              
67             ## no critic (TestingAndDebugging::ProhibitNoWarnings, Variables::ProhibitPackageVars)
68 1     1   6564 no warnings 'once';
  1         3  
  1         553  
69              
70             # If Perl versions aren't quotes then Travis displays 5.10 as "5.1"
71 14         32 local $YAML::QuoteNumericStrings = 1;
72 14         73 my $yaml = Dump($config);
73 14         142418 $yaml = $self->_fix_up_yaml($yaml);
74              
75 14         65 return $self->_fix_up_yaml($yaml) . $self->_cisetup_flags_as_comment;
76             }
77              
78             sub _cisetup_flags_as_comment {
79 14     14   36 my $self = shift;
80              
81 14         66 my $yaml = Dump( $self->_cisetup_flags );
82 14         14942 $yaml =~ s/^/# /gm;
83              
84             # Yes, this is YAML embedded in YAML as a comment. Yes, this is dumb. Yes,
85             # this is necessary. Unfortunately, AppVeyor chokes on random keys in its
86             # config file, so we have no choice but to use a comment. We could use
87             # Data::Dumper but we're already using YAML, and I don't really love doing
88             # an "eval" when trying to read this data.
89 14         158 return sprintf( <<'EOF', $yaml );
90             ### __app_cisetup__
91             %s
92             ### __app_cisetup__
93             EOF
94             }
95              
96             ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
97             sub _reorder_yaml_blocks {
98 28     28   58 my $self = shift;
99 28         51 my $yaml = shift;
100 28         47 my $blocks_order = shift;
101              
102 28         107 my $re = qr/^
103             (
104             ([a-z_]+): # key:
105             (?:
106             (?:$)\n.+?
107             |
108             \ .+?\n
109             )
110             )
111             (?=^[a-z]|\z)
112             /xms;
113              
114 28         51 my %blocks;
115 28         432 while ( $yaml =~ /$re/g ) {
116 192         2865 $blocks{$2} = $1;
117             }
118              
119 28         124 for my $name ( keys %blocks ) {
120 192         412 my $method = '_reorder_' . $name . '_block';
121 192 100       736 next unless $self->can($method);
122 20         88 $blocks{$name} = $self->$method( $blocks{$name} );
123             }
124              
125 28         73 my %known_blocks = map { $_ => 1 } @{$blocks_order};
  652         1403  
  28         81  
126 28         121 for my $block ( keys %blocks ) {
127             die "Unknown block $block in " . $self->file
128 192 50       385 unless $known_blocks{$block};
129             }
130              
131 28   66     63 return "---\n" . join q{}, map { $blocks{$_} // () } @{$blocks_order};
  652         1812  
  28         54  
132             }
133             ## use critic
134              
135             1;