| line | stmt | bran | cond | sub | pod | time | code | 
| 1 | 3 |  |  | 3 |  | 1245 | use strict; | 
|  | 3 |  |  |  |  | 7 |  | 
|  | 3 |  |  |  |  | 89 |  | 
| 2 | 3 |  |  | 3 |  | 15 | use warnings; | 
|  | 3 |  |  |  |  | 6 |  | 
|  | 3 |  |  |  |  | 71 |  | 
| 3 | 3 |  |  | 3 |  | 17 | use utf8; | 
|  | 3 |  |  |  |  | 14 |  | 
|  | 3 |  |  |  |  | 15 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | use Text::Xslate; | 
| 6 | 3 |  |  | 3 |  | 1732 | use File::Spec; | 
|  | 3 |  |  |  |  | 36344 |  | 
|  | 3 |  |  |  |  | 158 |  | 
| 7 | 3 |  |  | 3 |  | 23 | use File::Basename; | 
|  | 3 |  |  |  |  | 8 |  | 
|  | 3 |  |  |  |  | 58 |  | 
| 8 | 3 |  |  | 3 |  | 14 | use File::Path (); | 
|  | 3 |  |  |  |  | 6 |  | 
|  | 3 |  |  |  |  | 255 |  | 
| 9 | 3 |  |  | 3 |  | 22 | use Amon2; | 
|  | 3 |  |  |  |  | 19 |  | 
|  | 3 |  |  |  |  | 64 |  | 
| 10 | 3 |  |  | 3 |  | 1316 | use Plack::Util (); | 
|  | 3 |  |  |  |  | 8 |  | 
|  | 3 |  |  |  |  | 91 |  | 
| 11 | 3 |  |  | 3 |  | 18 | use Carp (); | 
|  | 3 |  |  |  |  | 7 |  | 
|  | 3 |  |  |  |  | 37 |  | 
| 12 | 3 |  |  | 3 |  | 14 | use Amon2::Trigger; | 
|  | 3 |  |  |  |  | 4 |  | 
|  | 3 |  |  |  |  | 58 |  | 
| 13 | 3 |  |  | 3 |  | 1164 | use mro; | 
|  | 3 |  |  |  |  | 9 |  | 
|  | 3 |  |  |  |  | 175 |  | 
| 14 | 3 |  |  | 3 |  | 19 | use File::ShareDir (); | 
|  | 3 |  |  |  |  | 6 |  | 
|  | 3 |  |  |  |  | 12 |  | 
| 15 | 3 |  |  | 3 |  | 1560 | use Module::CPANfile 0.9020; | 
|  | 3 |  |  |  |  | 77325 |  | 
|  | 3 |  |  |  |  | 106 |  | 
| 16 | 3 |  |  | 3 |  | 1355 |  | 
|  | 3 |  |  |  |  | 42458 |  | 
|  | 3 |  |  |  |  | 4590 |  | 
| 17 |  |  |  |  |  |  | my $self = shift; | 
| 18 |  |  |  |  |  |  |  | 
| 19 | 1 |  |  | 1 | 0 | 3 | my @assets = qw( | 
| 20 |  |  |  |  |  |  | jQuery Bootstrap MicroTemplateJS StrftimeJS SprintfJS | 
| 21 | 1 |  |  |  |  | 7 | MicroLocationJS MicroDispatcherJS XSRFTokenJS | 
| 22 |  |  |  |  |  |  | ); | 
| 23 |  |  |  |  |  |  | @assets; | 
| 24 |  |  |  |  |  |  | } | 
| 25 | 1 |  |  |  |  | 4 |  | 
| 26 |  |  |  |  |  |  | my $caller = do { | 
| 27 |  |  |  |  |  |  | my $x; | 
| 28 |  |  |  |  |  |  | for (1..10) { | 
| 29 | 57 |  |  | 57 | 0 | 121 | $x = caller($_); | 
| 30 | 57 |  |  |  |  | 75 | last if $x ne __PACKAGE__; | 
| 31 | 57 |  |  |  |  | 158 | } | 
| 32 | 120 |  |  |  |  | 238 | $x; | 
| 33 | 120 | 100 |  |  |  | 269 | }; | 
| 34 |  |  |  |  |  |  | $caller =~ s/^Amon2::Setup:://; | 
| 35 | 57 |  |  |  |  | 107 | print "[$caller] "; | 
| 36 |  |  |  |  |  |  | @_==1 ? print(@_) : printf(@_); | 
| 37 | 57 |  |  |  |  | 100 | print "\n"; | 
| 38 | 57 |  |  |  |  | 1884 | } | 
| 39 | 57 | 50 |  |  |  | 493 |  | 
| 40 | 57 |  |  |  |  | 366 | my $class = shift; | 
| 41 |  |  |  |  |  |  | my %args = @_ ==1 ? %{$_[0]} : @_; | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | $args{amon2_version} = $Amon2::VERSION; | 
| 44 | 1 |  |  | 1 | 0 | 1485 |  | 
| 45 | 1 | 50 |  |  |  | 8 | for (qw/module/) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 46 |  |  |  |  |  |  | die "Missing mandatory parameter $_" unless exists $args{$_}; | 
| 47 | 1 |  |  |  |  | 3 | } | 
| 48 |  |  |  |  |  |  | $args{module} =~ s!-!::!g; | 
| 49 | 1 |  |  |  |  | 22 |  | 
| 50 | 1 | 50 |  |  |  | 14 | # $module = "Foo::Bar" | 
| 51 |  |  |  |  |  |  | # $dist   = "Foo-Bar" | 
| 52 | 1 |  |  |  |  | 4 | # $path   = "Foo/Bar" | 
| 53 |  |  |  |  |  |  | my @pkg  = split /::/, $args{module}; | 
| 54 |  |  |  |  |  |  | $args{dist} = join "-", @pkg; | 
| 55 |  |  |  |  |  |  | $args{path} = join "/", @pkg; | 
| 56 |  |  |  |  |  |  | my $self = bless { %args }, $class; | 
| 57 | 1 |  |  |  |  | 5 | $self->{xslate} = $self->_build_xslate(); | 
| 58 | 1 |  |  |  |  | 5 | $self->load_assets(); | 
| 59 | 1 |  |  |  |  | 3 | $self; | 
| 60 | 1 |  |  |  |  | 5 | } | 
| 61 | 1 |  |  |  |  | 5 |  | 
| 62 | 1 |  |  |  |  | 5 | my $self = shift; | 
| 63 | 1 |  |  |  |  | 9 |  | 
| 64 |  |  |  |  |  |  | my $xslate = Text::Xslate->new( | 
| 65 |  |  |  |  |  |  | syntax => 'Kolon', | 
| 66 |  |  |  |  |  |  | type   => 'text', | 
| 67 | 1 |  |  | 1 |  | 1 | tag_start => '<%', | 
| 68 |  |  |  |  |  |  | tag_end   => '%>', | 
| 69 | 1 |  |  |  |  | 7 | line_start => '%%', | 
| 70 |  |  |  |  |  |  | path => [ File::Spec->catdir(File::ShareDir::dist_dir('Amon2'), 'flavor') ], | 
| 71 |  |  |  |  |  |  | module => [ | 
| 72 |  |  |  |  |  |  | 'Amon2::Util' => ['random_string'], | 
| 73 |  |  |  |  |  |  | ], | 
| 74 |  |  |  |  |  |  | ); | 
| 75 |  |  |  |  |  |  | $xslate; | 
| 76 |  |  |  |  |  |  | } | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | my ($self, $path) = @_; | 
| 80 | 1 |  |  |  |  | 8330 | Carp::croak("path should not be ref") if ref $path; | 
| 81 |  |  |  |  |  |  | infof("mkpath: $path"); | 
| 82 |  |  |  |  |  |  | File::Path::mkpath($path); | 
| 83 | 0 |  |  | 0 | 0 | 0 | } | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | my $self = shift; | 
| 86 | 0 |  |  | 0 | 1 | 0 | my $template = shift; | 
| 87 | 0 | 0 |  |  |  | 0 | my %args = @_==1 ? %{$_[0]} : @_; | 
| 88 | 0 |  |  |  |  | 0 | return $self->{xslate}->render_string($template, {%$self, %args}); | 
| 89 | 0 |  |  |  |  | 0 | } | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | my ($self, $dstname, $filename, $params) = @_; | 
| 92 |  |  |  |  |  |  | Carp::croak("filename should not be reference") if ref $filename; | 
| 93 | 0 |  |  | 0 | 0 | 0 | $dstname =~ s/<<([^>]+)>>/$self->{lc($1)} or die "$1 is not defined. But you want to use $1 in filename."/ge; | 
| 94 | 0 |  |  |  |  | 0 |  | 
| 95 | 0 | 0 |  |  |  | 0 | my $content = $self->{xslate}->render($filename, {%$self, $params ? %$params : () }); | 
|  | 0 |  |  |  |  | 0 |  | 
| 96 | 0 |  |  |  |  | 0 | $self->write_file_raw($dstname, $content); | 
| 97 |  |  |  |  |  |  | } | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | my ($self, $filename, $template) = (shift, shift, shift); | 
| 100 | 0 |  |  | 0 | 0 | 0 | Carp::croak("filename should not be reference") if ref $filename; | 
| 101 | 0 | 0 |  |  |  | 0 |  | 
| 102 | 0 | 0 |  |  |  | 0 | $filename =~ s/<<([^>]+)>>/$self->{lc($1)} or die "$1 is not defined. But you want to use $1 in filename."/ge; | 
|  | 0 |  |  |  |  | 0 |  | 
| 103 |  |  |  |  |  |  |  | 
| 104 | 0 | 0 |  |  |  | 0 | my $content = $self->render_string($template, @_); | 
| 105 | 0 |  |  |  |  | 0 | $self->write_file_raw($filename, $content); | 
| 106 |  |  |  |  |  |  | } | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | my ($self, $filename, $content, $input_mode) = @_; | 
| 109 | 0 |  |  | 0 | 1 | 0 | Carp::croak("filename should not be reference") if ref $filename; | 
| 110 | 0 | 0 |  |  |  | 0 | $input_mode ||= '>:encoding(utf-8)'; | 
| 111 |  |  |  |  |  |  |  | 
| 112 | 0 | 0 |  |  |  | 0 | infof("writing $filename"); | 
|  | 0 |  |  |  |  | 0 |  | 
| 113 |  |  |  |  |  |  |  | 
| 114 | 0 |  |  |  |  | 0 | my $dirname = dirname($filename); | 
| 115 | 0 |  |  |  |  | 0 | File::Path::mkpath($dirname) if $dirname; | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  | open my $ofh, $input_mode, $filename or die "Cannot open file: $filename: $!"; | 
| 118 |  |  |  |  |  |  | print {$ofh} $content; | 
| 119 | 47 |  |  | 47 | 1 | 101 | close $ofh; | 
| 120 | 47 | 50 |  |  |  | 91 | } | 
| 121 | 47 |  | 50 |  |  | 81 |  | 
| 122 |  |  |  |  |  |  | my ($self) = @_; | 
| 123 | 47 |  |  |  |  | 136 | for my $asset ($self->assets) { | 
| 124 |  |  |  |  |  |  | $self->load_asset($asset); | 
| 125 | 47 |  |  |  |  | 1477 | } | 
| 126 | 47 | 50 |  |  |  | 1837 | } | 
| 127 |  |  |  |  |  |  |  | 
| 128 | 1 | 50 |  | 1 |  | 9 | my ($self, $asset) = @_; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 9 |  | 
|  | 47 |  |  |  |  | 3306 |  | 
| 129 | 47 |  |  |  |  | 17758 | infof("Loading asset: $asset"); | 
|  | 47 |  |  |  |  | 17667 |  | 
| 130 | 47 |  |  |  |  | 1553 | my $klass = Plack::Util::load_class($asset, 'Amon2::Setup::Asset'); | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | my $require_newline = $self->{tags} ? 1 : 0; | 
| 133 |  |  |  |  |  |  | $self->{tags} .= $klass->tags; | 
| 134 | 1 |  |  | 1 | 0 | 3 | $self->{tags} .= "\n" if $require_newline && $self->{tags} !~ /\n\z/; | 
| 135 | 1 |  |  |  |  | 8 |  | 
| 136 | 8 |  |  |  |  | 26 | # $klass->run($self); | 
| 137 |  |  |  |  |  |  | } | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | my ($self, $asset, $base) = @_; | 
| 140 |  |  |  |  |  |  | $asset || die "Missing asset name"; | 
| 141 | 10 |  |  | 10 | 0 | 36 | $base ||= 'static/'; | 
| 142 | 10 |  |  |  |  | 37 |  | 
| 143 | 10 |  |  |  |  | 43 | my $klass = Plack::Util::load_class($asset, 'Amon2::Setup::Asset'); | 
| 144 |  |  |  |  |  |  | my $files = $klass->files; | 
| 145 | 10 | 100 |  |  |  | 145 | while (my ($fname, $content) = each %$files) { | 
| 146 | 10 |  |  |  |  | 161 | my $layer = $fname =~ /\.js\z/ ? '>:encoding(utf-8)' : '>:raw'; | 
| 147 | 10 | 50 | 66 |  |  | 102 | $self->write_file_raw("$base/$fname", $content, $layer); | 
| 148 |  |  |  |  |  |  | } | 
| 149 |  |  |  |  |  |  | } | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | my ($self, $dst) = @_; | 
| 152 |  |  |  |  |  |  |  | 
| 153 | 2 |  |  | 2 | 0 | 15 | for my $asset ($self->assets) { | 
| 154 | 2 | 50 |  |  |  | 8 | $self->write_asset($asset, $dst); | 
| 155 | 2 |  | 50 |  |  | 14 | } | 
| 156 |  |  |  |  |  |  | } | 
| 157 | 2 |  |  |  |  | 8 |  | 
| 158 | 2 |  |  |  |  | 47 | my ($self, $runtime_deps) = @_; | 
| 159 | 2 |  |  |  |  | 12 | $runtime_deps ||= +{}; | 
| 160 | 47 | 100 |  |  |  | 235 |  | 
| 161 | 47 |  |  |  |  | 248 | my $cpanfile = Module::CPANfile->from_prereqs( | 
| 162 |  |  |  |  |  |  | { | 
| 163 |  |  |  |  |  |  | runtime => { | 
| 164 |  |  |  |  |  |  | requires => { | 
| 165 |  |  |  |  |  |  | 'perl'              => '5.010_001', | 
| 166 | 0 |  |  | 0 | 0 |  | 'Amon2'             => $Amon2::VERSION, | 
| 167 |  |  |  |  |  |  | 'Text::Xslate'      => '2.0009', | 
| 168 | 0 |  |  |  |  |  | 'Starlet'           => '0.20', | 
| 169 | 0 |  |  |  |  |  | 'Module::Functions' => 2, | 
| 170 |  |  |  |  |  |  | %$runtime_deps, | 
| 171 |  |  |  |  |  |  | }, | 
| 172 |  |  |  |  |  |  | }, | 
| 173 |  |  |  |  |  |  | configure => { | 
| 174 | 0 |  |  | 0 | 0 |  | requires => { | 
| 175 | 0 |  | 0 |  |  |  | 'Module::Build'    => '0.38', | 
| 176 |  |  |  |  |  |  | 'Module::CPANfile' => '0.9010', | 
| 177 | 0 |  |  |  |  |  | }, | 
| 178 |  |  |  |  |  |  | }, | 
| 179 |  |  |  |  |  |  | test => { | 
| 180 |  |  |  |  |  |  | requires => { | 
| 181 |  |  |  |  |  |  | 'Test::More' => '0.98', | 
| 182 |  |  |  |  |  |  | }, | 
| 183 |  |  |  |  |  |  | }, | 
| 184 |  |  |  |  |  |  | } | 
| 185 |  |  |  |  |  |  | ); | 
| 186 |  |  |  |  |  |  | $self->write_file('cpanfile', $cpanfile->to_string()); | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  | 1; | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | =head1 NAME | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | Amon2::Setup::Flavor - Abstract base class for flavors. | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 196 |  |  |  |  |  |  |  | 
| 197 |  |  |  |  |  |  | This is an abstract base class for flavors. But you don't need to inherit this class. Amon2 uses duck typing. You should implement only C<< Class->run >> method. | 
| 198 |  |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | In Amon2, flavor means setup script. | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | =head1 METHODS | 
| 202 | 0 |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | This class provides some useful methods to write setup script. | 
| 204 |  |  |  |  |  |  |  | 
| 205 |  |  |  |  |  |  | =over 4 | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | =item C<< $flavor->init() >> | 
| 208 |  |  |  |  |  |  |  | 
| 209 |  |  |  |  |  |  | Hook point to initialize module directory. | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | =item C<< $flavor->mkpath($dir) >> | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | same as C<< `mkdir -p $dir` >>. | 
| 214 |  |  |  |  |  |  |  | 
| 215 |  |  |  |  |  |  | =item C<< $flavor->write_file($fnametmpl, $template) >> | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | C<< $fnametmpl >> will be replace with the parameters. | 
| 218 |  |  |  |  |  |  |  | 
| 219 |  |  |  |  |  |  | Generate file using L<Text::Xslate>. | 
| 220 |  |  |  |  |  |  |  | 
| 221 |  |  |  |  |  |  | For more details, read the source Luke! Or please write docs... | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  | =item C<< $flavor->write_file_raw($fname, $content) >> | 
| 224 |  |  |  |  |  |  |  | 
| 225 |  |  |  |  |  |  | Write C<< $content >> to the C<< $fname >>. | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  | =back | 
| 228 |  |  |  |  |  |  |  |