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   935 use strict;
  1         4  
  1         37  
4 1     1   8 use warnings;
  1         2  
  1         34  
5 1     1   6 use namespace::autoclean;
  1         2  
  1         12  
6 1     1   81 use autodie qw( :all );
  1         3  
  1         9  
7              
8             our $VERSION = '0.18';
9              
10 1     1   5964 use App::CISetup::Types qw( Path );
  1         2  
  1         16  
11 1     1   3240 use Try::Tiny;
  1         3  
  1         72  
12 1     1   557 use YAML qw( Dump LoadFile );
  1         7373  
  1         96  
13              
14 1     1   9 use Moose::Role;
  1         3  
  1         11  
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         225 $self->file->spew( $self->_config_to_yaml( $self->_create_config ) );
34              
35 6         3076 return;
36             }
37              
38             sub update_file {
39 8     8 0 26 my $self = shift;
40              
41 8         297 my $file = $self->file;
42 8         35 my $orig = $file->slurp;
43              
44             my $content = try {
45 8     8   460 LoadFile($file);
46             }
47             catch {
48 0     0   0 die "YAML parsing error: $_\n";
49 8         1641 };
50              
51 8 50       59243 return 0 unless $content;
52              
53 8         63 my $config = $self->_update_config($content);
54 8         35 my $yaml = $self->_config_to_yaml($config);
55              
56 8 100       67 return 0 if $yaml eq $orig;
57              
58 5         32 $file->spew($yaml);
59              
60 5         2351 return 1;
61             }
62              
63             sub _config_to_yaml {
64 14     14   38 my $self = shift;
65 14         27 my $config = shift;
66              
67             ## no critic (TestingAndDebugging::ProhibitNoWarnings, Variables::ProhibitPackageVars)
68 1     1   6349 no warnings 'once';
  1         3  
  1         517  
69              
70             # If Perl versions aren't quotes then Travis displays 5.10 as "5.1"
71 14         36 local $YAML::QuoteNumericStrings = 1;
72 14         54 my $yaml = Dump($config);
73 14         139219 $yaml = $self->_fix_up_yaml($yaml);
74              
75 14         64 return $self->_fix_up_yaml($yaml) . $self->_cisetup_flags_as_comment;
76             }
77              
78             sub _cisetup_flags_as_comment {
79 14     14   44 my $self = shift;
80              
81 14         58 my $yaml = Dump( $self->_cisetup_flags );
82 14         14823 $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         210 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   53 my $self = shift;
99 28         48 my $yaml = shift;
100 28         55 my $blocks_order = shift;
101              
102 28         93 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         408 while ( $yaml =~ /$re/g ) {
116 192         2738 $blocks{$2} = $1;
117             }
118              
119 28         125 for my $name ( keys %blocks ) {
120 192         375 my $method = '_reorder_' . $name . '_block';
121 192 100       706 next unless $self->can($method);
122 20         85 $blocks{$name} = $self->$method( $blocks{$name} );
123             }
124              
125 28         68 my %known_blocks = map { $_ => 1 } @{$blocks_order};
  652         1367  
  28         74  
126 28         123 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     64 return "---\n" . join q{}, map { $blocks{$_} // () } @{$blocks_order};
  652         1736  
  28         53  
132             }
133             ## use critic
134              
135             1;