File Coverage

blib/lib/Dpkg/Dist/Files.pm
Criterion Covered Total %
statement 105 109 96.3
branch 16 24 66.6
condition 8 10 80.0
subroutine 19 19 100.0
pod 2 11 18.1
total 150 173 86.7


line stmt bran cond sub pod time code
1             # Copyright © 2014-2015 Guillem Jover
2             #
3             # This program is free software; you can redistribute it and/or modify
4             # it under the terms of the GNU General Public License as published by
5             # the Free Software Foundation; either version 2 of the License, or
6             # (at your option) any later version.
7             #
8             # This program is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11             # GNU General Public License for more details.
12             #
13             # You should have received a copy of the GNU General Public License
14             # along with this program. If not, see .
15              
16             package Dpkg::Dist::Files;
17              
18 1     1   780 use strict;
  1         3  
  1         30  
19 1     1   5 use warnings;
  1         2  
  1         39  
20              
21             our $VERSION = '0.01';
22              
23 1     1   523 use IO::Dir;
  1         9401  
  1         52  
24              
25 1     1   532 use Dpkg::Gettext;
  1         2  
  1         63  
26 1     1   502 use Dpkg::ErrorHandling;
  1         3  
  1         82  
27              
28 1     1   499 use parent qw(Dpkg::Interface::Storable);
  1         302  
  1         5  
29              
30             sub new {
31 1     1 0 43 my ($this, %opts) = @_;
32 1   33     7 my $class = ref($this) || $this;
33              
34 1         3 my $self = {
35             options => [],
36             files => {},
37             };
38 1         4 foreach my $opt (keys %opts) {
39 0         0 $self->{$opt} = $opts{$opt};
40             }
41 1         2 bless $self, $class;
42              
43 1         26 return $self;
44             }
45              
46             sub reset {
47 5     5 0 9 my $self = shift;
48              
49 5         34 $self->{files} = {};
50             }
51              
52             sub parse_filename {
53 33     33 0 804 my ($self, $fn) = @_;
54              
55 33         45 my $file;
56              
57 33 100       146 if ($fn =~ m/^(([-+:.0-9a-z]+)_([^_]+)_([-\w]+)\.([a-z0-9.]+))$/) {
    100          
58             # Artifact using the common __. pattern.
59 18         53 $file->{filename} = $1;
60 18         38 $file->{package} = $2;
61 18         38 $file->{version} = $3;
62 18         34 $file->{arch} = $4;
63 18         38 $file->{package_type} = $5;
64             } elsif ($fn =~ m/^([-+:.,_0-9a-zA-Z~]+)$/) {
65             # Artifact with no common pattern, usually called byhand or raw, as
66             # they might require manual processing on the server side, or custom
67             # actions per file type.
68 14         40 $file->{filename} = $1;
69             } else {
70 1         3 $file = undef;
71             }
72              
73 33         63 return $file;
74             }
75              
76             sub parse {
77 7     7 1 16 my ($self, $fh, $desc) = @_;
78 7         12 my $count = 0;
79              
80 7         11 local $_;
81 7         21 binmode $fh;
82              
83 7         78 while (<$fh>) {
84 27         837 chomp;
85              
86 27         33 my $file;
87              
88 27 50       136 if (m/^(\S+) (\S+) (\S+)((?:\s+[0-9a-z-]+=\S+)*)$/) {
89 27         62 $file = $self->parse_filename($1);
90 27 50       53 error(g_('badly formed file name in files list file, line %d'), $.)
91             unless defined $file;
92 27         53 $file->{section} = $2;
93 27         46 $file->{priority} = $3;
94 27         38 my $attrs = $4;
95 27         91 $file->{attrs} = { map { split /=/ } split ' ', $attrs };
  10         43  
96             } else {
97 0         0 error(g_('badly formed line in files list file, line %d'), $.);
98             }
99              
100 27 50       123 if (defined $self->{files}->{$file->{filename}}) {
101             warning(g_('duplicate files list entry for file %s (line %d)'),
102 0         0 $file->{filename}, $.);
103             } else {
104 27         35 $count++;
105 27         92 $self->{files}->{$file->{filename}} = $file;
106             }
107             }
108              
109 7         249 return $count;
110             }
111              
112             sub load_dir {
113 1     1 0 3 my ($self, $dir) = @_;
114              
115 1         2 my $count = 0;
116 1 50       8 my $dh = IO::Dir->new($dir) or syserr(g_('cannot open directory %s'), $dir);
117              
118 1         123 while (defined(my $file = $dh->read)) {
119 5         92 my $pathname = "$dir/$file";
120 5 100       81 next unless -f $pathname;
121 3         16 $count += $self->load($pathname);
122             }
123              
124 1         22 return $count;
125             }
126              
127             sub get_files {
128 1     1 0 3 my $self = shift;
129              
130 1         1 return map { $self->{files}->{$_} } sort keys %{$self->{files}};
  5         10  
  1         7  
131             }
132              
133             sub get_file {
134 12     12 0 6652 my ($self, $filename) = @_;
135              
136 12         45 return $self->{files}->{$filename};
137             }
138              
139             sub add_file {
140 5     5 0 10 my ($self, $filename, $section, $priority, %attrs) = @_;
141              
142 5         11 my $file = $self->parse_filename($filename);
143 5 50       10 error(g_('invalid filename %s'), $filename) unless defined $file;
144 5         11 $file->{section} = $section;
145 5         8 $file->{priority} = $priority;
146 5         10 $file->{attrs} = \%attrs;
147              
148 5         10 $self->{files}->{$filename} = $file;
149              
150 5         10 return $file;
151             }
152              
153             sub del_file {
154 1     1 0 3 my ($self, $filename) = @_;
155              
156 1         5 delete $self->{files}->{$filename};
157             }
158              
159             sub filter {
160 3     3 0 10 my ($self, %opts) = @_;
161 3   100 2   17 my $remove = $opts{remove} // sub { 0 };
  2         14  
162 3   100 5   12 my $keep = $opts{keep} // sub { 1 };
  5         14  
163              
164 3         5 foreach my $filename (keys %{$self->{files}}) {
  3         13  
165 15         31 my $file = $self->{files}->{$filename};
166              
167 15 100 100     24 if (not $keep->($file) or $remove->($file)) {
168 9         57 delete $self->{files}->{$filename};
169             }
170             }
171             }
172              
173             sub output {
174 7     7 1 20 my ($self, $fh) = @_;
175 7         13 my $str = '';
176              
177 7 50       16 binmode $fh if defined $fh;
178              
179 7         10 foreach my $filename (sort keys %{$self->{files}}) {
  7         35  
180 26         36 my $file = $self->{files}->{$filename};
181 26         59 my $entry = "$filename $file->{section} $file->{priority}";
182              
183 26 50       44 if (exists $file->{attrs}) {
184 26         31 foreach my $attr (sort keys %{$file->{attrs}}) {
  26         56  
185 9         20 $entry .= " $attr=$file->{attrs}->{$attr}";
186             }
187             }
188              
189 26         37 $entry .= "\n";
190              
191 26 50       43 print { $fh } $entry if defined $fh;
  0         0  
192 26         55 $str .= $entry;
193             }
194              
195 7         119 return $str;
196             }
197              
198             1;