line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::Web::VPKBuilder; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
21386
|
use 5.014000; |
|
1
|
|
|
|
|
4
|
|
4
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
22
|
|
5
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
12
|
|
|
1
|
|
|
|
|
37
|
|
6
|
1
|
|
|
1
|
|
726
|
use parent qw/Plack::Component/; |
|
1
|
|
|
|
|
301
|
|
|
1
|
|
|
|
|
6
|
|
7
|
1
|
|
|
1
|
|
15512
|
use re '/s'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
96
|
|
8
|
|
|
|
|
|
|
our $VERSION = '0.001'; |
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
6
|
use File::Find qw/find/; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
75
|
|
11
|
1
|
|
|
1
|
|
12
|
use File::Path qw/remove_tree/; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
64
|
|
12
|
1
|
|
|
1
|
|
787
|
use File::Spec::Functions qw/abs2rel catfile rel2abs/; |
|
1
|
|
|
|
|
935
|
|
|
1
|
|
|
|
|
91
|
|
13
|
1
|
|
|
1
|
|
1129
|
use File::Temp qw/tempdir/; |
|
1
|
|
|
|
|
13953
|
|
|
1
|
|
|
|
|
67
|
|
14
|
1
|
|
|
1
|
|
6520
|
use IO::Compress::Zip qw/zip ZIP_CM_LZMA/; |
|
1
|
|
|
|
|
87852
|
|
|
1
|
|
|
|
|
103
|
|
15
|
1
|
|
|
1
|
|
903
|
use sigtrap qw/die normal-signals/; |
|
1
|
|
|
|
|
1329
|
|
|
1
|
|
|
|
|
9
|
|
16
|
|
|
|
|
|
|
|
17
|
1
|
|
|
1
|
|
887
|
use Data::Diver qw/DiveRef/; |
|
1
|
|
|
|
|
950
|
|
|
1
|
|
|
|
|
74
|
|
18
|
1
|
|
|
1
|
|
847
|
use File::Slurp qw/write_file/; |
|
1
|
|
|
|
|
13638
|
|
|
1
|
|
|
|
|
67
|
|
19
|
1
|
|
|
1
|
|
1484
|
use HTML::Element; |
|
1
|
|
|
|
|
25716
|
|
|
1
|
|
|
|
|
5
|
|
20
|
1
|
|
|
1
|
|
1286
|
use HTML::TreeBuilder; |
|
1
|
|
|
|
|
8392
|
|
|
1
|
|
|
|
|
9
|
|
21
|
1
|
|
|
1
|
|
866
|
use Hash::Merge qw/merge/; |
|
1
|
|
|
|
|
2926
|
|
|
1
|
|
|
|
|
78
|
|
22
|
1
|
|
|
1
|
|
850
|
use List::MoreUtils qw/uniq/; |
|
1
|
|
|
|
|
12433
|
|
|
1
|
|
|
|
|
9
|
|
23
|
1
|
|
|
1
|
|
1453
|
use Plack::Request; |
|
1
|
|
|
|
|
52392
|
|
|
1
|
|
|
|
|
39
|
|
24
|
1
|
|
|
1
|
|
776
|
use Sort::ByExample qw/sbe/; |
|
1
|
|
|
|
|
13418
|
|
|
1
|
|
|
|
|
7
|
|
25
|
1
|
|
|
1
|
|
961
|
use YAML qw/LoadFile/; |
|
1
|
|
|
|
|
7471
|
|
|
1
|
|
|
|
|
1555
|
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub new { |
28
|
0
|
|
|
0
|
1
|
|
my $self = shift->SUPER::new(@_); |
29
|
0
|
|
|
|
|
|
$self->{cfg} = {}; |
30
|
0
|
|
|
|
|
|
for (sort ) { |
31
|
0
|
|
|
|
|
|
my $cfg = LoadFile $_; |
32
|
0
|
|
|
|
|
|
$self->{cfg} = merge $self->{cfg}, $cfg |
33
|
|
|
|
|
|
|
} |
34
|
0
|
|
0
|
|
|
|
$self->{cfg}{vpk_extension} //= 'vpk'; |
35
|
0
|
|
|
0
|
|
|
$self->{cfg}{sort} = sbe $self->{cfg}{sort_order}, { fallback => sub { shift cmp shift } }; |
|
0
|
|
|
|
|
|
|
36
|
0
|
|
|
|
|
|
$self |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub addpkg { |
40
|
0
|
|
|
0
|
0
|
|
my ($pkg, $dir) = @_; |
41
|
0
|
0
|
|
|
|
|
return unless $pkg =~ /^[a-zA-Z0-9_-]+$/aa; |
42
|
0
|
|
|
|
|
|
my @dirs = ($dir); |
43
|
|
|
|
|
|
|
find { |
44
|
0
|
|
|
0
|
|
|
postprocess => sub { pop @dirs }, |
45
|
|
|
|
|
|
|
wanted => sub { |
46
|
0
|
|
|
0
|
|
|
my $dest = catfile @dirs, $_; |
47
|
0
|
0
|
|
|
|
|
mkdir $dest if -d; |
48
|
0
|
0
|
|
|
|
|
push @dirs, $_ if -d; |
49
|
0
|
0
|
|
|
|
|
link $_, $dest if -f; |
50
|
0
|
|
|
|
|
|
}}, catfile 'pkg', $pkg; |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub makepkg { |
54
|
0
|
|
|
0
|
0
|
|
my ($self, @pkgs) = @_; |
55
|
0
|
|
|
|
|
|
mkdir $self->{cfg}{dir}; |
56
|
0
|
|
|
|
|
|
my $dir = rel2abs tempdir 'workXXXX', DIR => $self->{cfg}{dir}; |
57
|
0
|
|
|
|
|
|
my $dest = catfile $dir, 'pkg'; |
58
|
0
|
|
|
|
|
|
mkdir $dest; |
59
|
0
|
|
|
|
|
|
@pkgs = grep { exists $self->{cfg}{pkgs}{$_} } @pkgs; |
|
0
|
|
|
|
|
|
|
60
|
0
|
|
0
|
|
|
|
push @pkgs, split /,/, ($self->{cfg}{pkgs}{$_}{deps} // '') for @pkgs; |
61
|
0
|
|
|
|
|
|
@pkgs = uniq @pkgs; |
62
|
0
|
|
|
|
|
|
addpkg $_, $dest for @pkgs; |
63
|
0
|
|
|
|
|
|
write_file catfile ($dir, 'readme.txt'), $self->{cfg}{readme}; |
64
|
0
|
|
|
|
|
|
my @zip_files = catfile $dir, 'readme.txt'; |
65
|
0
|
0
|
|
|
|
|
if ($self->{cfg}{vpk}) { |
66
|
0
|
|
|
|
|
|
system $self->{cfg}{vpk} => $dest; |
67
|
0
|
|
|
|
|
|
push @zip_files, catfile $dir, "pkg.$self->{cfg}{vpk_extension}" |
68
|
|
|
|
|
|
|
} else { |
69
|
0
|
0
|
|
0
|
|
|
find sub { push @zip_files, $File::Find::name if -f }, $dest; |
|
0
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
} |
71
|
0
|
|
|
0
|
|
|
zip \@zip_files, catfile($dir, 'pkg.zip'), FilterName => sub { $_ = abs2rel $_, $dir }, -Level => 1; |
|
0
|
|
|
|
|
|
|
72
|
0
|
0
|
|
|
|
|
open my $fh, '<', catfile $dir, 'pkg.zip' or return [500, ['Content-Type' => 'text/plain;charset=utf-8'], ['Error opening pkg.zip']]; ## no critic (RequireBriefOpen) |
73
|
0
|
|
|
|
|
|
remove_tree $dir; |
74
|
0
|
|
|
|
|
|
[200, ['Content-Type' => 'application/zip', 'Content-Disposition' => 'attachment; filename=pkg.zip'], $fh] |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub makelist { |
78
|
0
|
|
|
0
|
0
|
|
my ($self, $elem, $tree, $lvl, $key) = @_; |
79
|
0
|
|
|
|
|
|
my $name = HTML::Element->new('span', class => 'name'); |
80
|
0
|
|
|
|
|
|
$name->push_content($key); |
81
|
0
|
0
|
|
|
|
|
$elem->push_content($name) if defined $key; |
82
|
0
|
0
|
|
|
|
|
if (ref $tree eq 'ARRAY') { |
83
|
0
|
|
|
|
|
|
my $sel = HTML::Element->new('select', name => 'pkg'); |
84
|
0
|
|
|
|
|
|
my $opt = HTML::Element->new('option', value => ''); |
85
|
0
|
|
|
|
|
|
$opt->push_content('None'); |
86
|
0
|
|
|
|
|
|
$sel->push_content($opt); |
87
|
0
|
|
|
|
|
|
for my $pkg (sort { $a->{name} cmp $b->{name} } @$tree) { |
|
0
|
|
|
|
|
|
|
88
|
0
|
0
|
|
|
|
|
my $option = HTML::Element->new('option', value => $pkg->{pkg}, $pkg->{default} ? (selected => 'selected') : ()); |
89
|
0
|
|
|
|
|
|
$option->push_content($pkg->{name}); |
90
|
0
|
|
|
|
|
|
$sel->push_content($option); |
91
|
|
|
|
|
|
|
} |
92
|
0
|
|
|
|
|
|
$elem->push_content($sel); |
93
|
|
|
|
|
|
|
} else { |
94
|
0
|
|
|
|
|
|
my $ul = HTML::Element->new('ul'); |
95
|
0
|
|
|
|
|
|
for my $key ($self->{cfg}{sort}->(keys %$tree)) { |
96
|
0
|
|
|
|
|
|
my $li = HTML::Element->new('li', class => "level$lvl"); |
97
|
0
|
|
|
|
|
|
$self->makelist($li, $tree->{$key}, $lvl + 1, $key); |
98
|
0
|
|
|
|
|
|
$ul->push_content($li); |
99
|
|
|
|
|
|
|
} |
100
|
0
|
|
|
|
|
|
$elem->push_content($ul); |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub makeindex { |
105
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
106
|
0
|
|
|
|
|
|
my ($pkgs, $tree) = ($self->{cfg}{pkgs}, {}); |
107
|
0
|
|
|
|
|
|
for (keys %$pkgs) { |
108
|
0
|
|
|
|
|
|
my $ref = DiveRef ($tree, split /,/, $pkgs->{$_}{path}); |
109
|
0
|
0
|
|
|
|
|
$$ref = [] unless ref $$ref eq 'ARRAY'; |
110
|
0
|
|
|
|
|
|
push @{$$ref}, {pkg => $_, name => $pkgs->{$_}{name}, default => $pkgs->{$_}{default}}; |
|
0
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
} |
112
|
0
|
|
|
|
|
|
my $html = HTML::TreeBuilder->new_from_file('index.html'); |
113
|
0
|
|
|
|
|
|
$self->makelist(scalar $html->look_down(id => 'list'), $tree, 1); |
114
|
0
|
|
|
|
|
|
my $ret = $html->as_HTML('', ' '); |
115
|
0
|
|
|
|
|
|
utf8::encode($ret); |
116
|
0
|
|
|
|
|
|
[200, ['Content-Type' => 'text/html;charset=utf-8'], [$ret]] |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub call{ |
120
|
0
|
|
|
0
|
1
|
|
my ($self, $env) = @_; |
121
|
0
|
|
|
|
|
|
my $req = Plack::Request->new($env); |
122
|
0
|
0
|
|
|
|
|
return $self->makepkg($req->param('pkg')) if $req->path eq '/makepkg'; |
123
|
0
|
|
|
|
|
|
$self->makeindex; |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
1; |
127
|
|
|
|
|
|
|
__END__ |