| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package DPKG::Packages::Parser; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
92675
|
use v5.40; |
|
|
1
|
|
|
|
|
3
|
|
|
4
|
1
|
|
|
1
|
|
5
|
use feature 'class'; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
154
|
|
|
5
|
1
|
|
|
1
|
|
4
|
no warnings 'experimental::class'; |
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
34
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
493
|
use Clone qw(clone); |
|
|
1
|
|
|
|
|
581
|
|
|
|
1
|
|
|
|
|
89
|
|
|
8
|
1
|
|
|
1
|
|
7
|
use Carp qw(croak); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
1047
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our $VERSION = '0.03'; |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
class DPKG::Packages::Parser { |
|
13
|
|
|
|
|
|
|
field $file :param :reader = 'Packages'; |
|
14
|
|
|
|
|
|
|
field $fh :param :reader = undef; |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
field %entries = (); |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
method parse(@fields) { |
|
19
|
|
|
|
|
|
|
if(-r $file) { |
|
20
|
|
|
|
|
|
|
open(my $f, '<', $file) or die "Cannot read $file\n"; |
|
21
|
|
|
|
|
|
|
$self->_parse_from_filehandle($f, @fields); |
|
22
|
|
|
|
|
|
|
return 1; |
|
23
|
|
|
|
|
|
|
} elsif(defined($fh)) { |
|
24
|
|
|
|
|
|
|
$self->_parse_from_filehandle($fh, @fields); |
|
25
|
|
|
|
|
|
|
return 1; |
|
26
|
|
|
|
|
|
|
} else { |
|
27
|
|
|
|
|
|
|
croak("DPKG::Packages::Parser - $file is not a readable file"); |
|
28
|
|
|
|
|
|
|
} |
|
29
|
|
|
|
|
|
|
} |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
method _parse_from_filehandle($fh, @fields) { |
|
32
|
|
|
|
|
|
|
my %f = (); |
|
33
|
|
|
|
|
|
|
my @array_fields = qw(Tag Depends Pre-Depends Replaces Provides Breaks Enhances Conflicts Recommends Suggests); |
|
34
|
|
|
|
|
|
|
if(@fields) { |
|
35
|
|
|
|
|
|
|
unshift @fields, 'Package' if ! grep { 'Packages' eq $_ } @fields; |
|
36
|
|
|
|
|
|
|
$f{$_} = 1 foreach(@fields); |
|
37
|
|
|
|
|
|
|
@array_fields = grep { $f{$_} } @array_fields; # Only keep the ones that are requested by the User |
|
38
|
|
|
|
|
|
|
} |
|
39
|
|
|
|
|
|
|
my %entry = (); |
|
40
|
|
|
|
|
|
|
my $last_key; # 'Tag' is multi-line, I don't know why this is the only field which does this... but we need to remember th^i |
|
41
|
|
|
|
|
|
|
while(<$fh>) { |
|
42
|
|
|
|
|
|
|
chomp; |
|
43
|
|
|
|
|
|
|
if(!$_) { # Empty line == post processing of entry (we've seen all its lines) |
|
44
|
|
|
|
|
|
|
# Yeah, good luck understanding this mess. We loop through the array fields to split it based on ', '. Then if we're dealing with a tag but with a list that contains package names, we have to parse each package name. There's a further edge case where there's an OR statement (signified by '|') between packages that we also deal with. |
|
45
|
|
|
|
|
|
|
map { $entry{$_} = $_ eq 'Tag' ? [ split(', ', $entry{$_}) ] : [ map { index($_,'|') >= 0 ? [ map { $self->_parse_package_str($_) } split(' \| ', $_) ] : $self->_parse_package_str($_) } split(', ', $entry{$_}) ] if defined($entry{$_}) } @array_fields; |
|
46
|
|
|
|
|
|
|
$entries{$entry{Package}} = clone(\%entry); |
|
47
|
|
|
|
|
|
|
%entry = (); |
|
48
|
|
|
|
|
|
|
} else { |
|
49
|
|
|
|
|
|
|
# if statement with side-effects: the defined() condition needs to be first because we need to set $last_key every time we match a line. |
|
50
|
|
|
|
|
|
|
# We check in the if-condition if we are interested in this line or not by extracting the field name of this line (and only that, not the value). We only extract the value if it's a line of interest. |
|
51
|
|
|
|
|
|
|
if(index($_, ' ') != 0 && (defined($f{$last_key = substr($_, 0, index($_, ':'))}) || !@fields)) { |
|
52
|
|
|
|
|
|
|
$entry{$last_key} = substr($_, index($_, ':') + 2); |
|
53
|
|
|
|
|
|
|
} elsif(!@fields || $f{$last_key}) { |
|
54
|
|
|
|
|
|
|
$entry{$last_key} .= $_ |
|
55
|
|
|
|
|
|
|
} |
|
56
|
|
|
|
|
|
|
} |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
close($fh); |
|
59
|
|
|
|
|
|
|
} |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
method _parse_package_str($s) { |
|
62
|
|
|
|
|
|
|
my @x = split(' ', $s); |
|
63
|
|
|
|
|
|
|
my ($name, $arch) = split(':', $x[0]); |
|
64
|
|
|
|
|
|
|
my $op = $x[1] ? substr($x[1], 1) : undef; |
|
65
|
|
|
|
|
|
|
chop($x[2]) if $x[2]; |
|
66
|
|
|
|
|
|
|
my $version = $x[2] ? $x[2] : undef; |
|
67
|
|
|
|
|
|
|
return {name => $name, op => $op, version => $version, arch => $arch}; |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
method get_package($name) { |
|
71
|
|
|
|
|
|
|
return defined($entries{$name}) ? $entries{$name} : undef; |
|
72
|
|
|
|
|
|
|
} |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
1; |
|
76
|
|
|
|
|
|
|
__END__ |