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   815 use strict;
  1         2  
  1         36  
4 1     1   6 use warnings;
  1         2  
  1         31  
5 1     1   6 use namespace::autoclean;
  1         2  
  1         10  
6 1     1   81 use autodie qw( :all );
  1         3  
  1         9  
7              
8             our $VERSION = '0.17';
9              
10 1     1   6097 use App::CISetup::Types qw( Path );
  1         4  
  1         13  
11 1     1   3132 use Try::Tiny;
  1         2  
  1         139  
12 1     1   554 use YAML qw( Dump LoadFile );
  1         7340  
  1         148  
13              
14 1     1   10 use Moose::Role;
  1         2  
  1         12  
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 17 my $self = shift;
32              
33 6         215 $self->file->spew( $self->_config_to_yaml( $self->_create_config ) );
34              
35 6         3382 return;
36             }
37              
38             sub update_file {
39 8     8 0 24 my $self = shift;
40              
41 8         294 my $file = $self->file;
42 8         40 my $orig = $file->slurp;
43              
44             my $content = try {
45 8     8   516 LoadFile($file);
46             }
47             catch {
48 0     0   0 die "YAML parsing error: $_\n";
49 8         1653 };
50              
51 8 50       59488 return 0 unless $content;
52              
53 8         56 my $config = $self->_update_config($content);
54 8         53 my $yaml = $self->_config_to_yaml($config);
55              
56 8 100       65 return 0 if $yaml eq $orig;
57              
58 5         31 $file->spew($yaml);
59              
60 5         2602 return 1;
61             }
62              
63             sub _config_to_yaml {
64 14     14   37 my $self = shift;
65 14         30 my $config = shift;
66              
67             ## no critic (TestingAndDebugging::ProhibitNoWarnings, Variables::ProhibitPackageVars)
68 1     1   6207 no warnings 'once';
  1         3  
  1         504  
69              
70             # If Perl versions aren't quotes then Travis displays 5.10 as "5.1"
71 14         30 local $YAML::QuoteNumericStrings = 1;
72 14         61 my $yaml = Dump($config);
73 14         139565 $yaml = $self->_fix_up_yaml($yaml);
74              
75 14         51 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         52 my $yaml = Dump( $self->_cisetup_flags );
82 14         15121 $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         160 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   64 my $self = shift;
99 28         47 my $yaml = shift;
100 28         51 my $blocks_order = shift;
101              
102 28         125 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         54 my %blocks;
115 28         450 while ( $yaml =~ /$re/g ) {
116 192         2779 $blocks{$2} = $1;
117             }
118              
119 28         139 for my $name ( keys %blocks ) {
120 192         369 my $method = '_reorder_' . $name . '_block';
121 192 100       724 next unless $self->can($method);
122 20         86 $blocks{$name} = $self->$method( $blocks{$name} );
123             }
124              
125 28         59 my %known_blocks = map { $_ => 1 } @{$blocks_order};
  652         1311  
  28         81  
126 28         120 for my $block ( keys %blocks ) {
127             die "Unknown block $block in " . $self->file
128 192 50       405 unless $known_blocks{$block};
129             }
130              
131 28   66     70 return "---\n" . join q{}, map { $blocks{$_} // () } @{$blocks_order};
  652         1726  
  28         58  
132             }
133             ## use critic
134              
135             1;