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   801 use strict;
  1         2  
  1         29  
19 1     1   7 use warnings;
  1         1  
  1         40  
20              
21             our $VERSION = '0.01';
22              
23 1     1   513 use IO::Dir;
  1         9063  
  1         91  
24              
25 1     1   495 use Dpkg::Gettext;
  1         3  
  1         60  
26 1     1   467 use Dpkg::ErrorHandling;
  1         3  
  1         82  
27              
28 1     1   463 use parent qw(Dpkg::Interface::Storable);
  1         282  
  1         5  
29              
30             sub new {
31 1     1 0 45 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         23 return $self;
44             }
45              
46             sub reset {
47 5     5 0 8 my $self = shift;
48              
49 5         37 $self->{files} = {};
50             }
51              
52             sub parse_filename {
53 33     33 0 787 my ($self, $fn) = @_;
54              
55 33         49 my $file;
56              
57 33 100       139 if ($fn =~ m/^(([-+:.0-9a-z]+)_([^_]+)_([-\w]+)\.([a-z0-9.]+))$/) {
    100          
58             # Artifact using the common __. pattern.
59 18         55 $file->{filename} = $1;
60 18         34 $file->{package} = $2;
61 18         35 $file->{version} = $3;
62 18         30 $file->{arch} = $4;
63 18         35 $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         5 $file = undef;
71             }
72              
73 33         55 return $file;
74             }
75              
76             sub parse {
77 7     7 1 17 my ($self, $fh, $desc) = @_;
78 7         9 my $count = 0;
79              
80 7         11 local $_;
81 7         19 binmode $fh;
82              
83 7         114 while (<$fh>) {
84 27         794 chomp;
85              
86 27         34 my $file;
87              
88 27 50       132 if (m/^(\S+) (\S+) (\S+)((?:\s+[0-9a-z-]+=\S+)*)$/) {
89 27         60 $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         51 $file->{section} = $2;
93 27         42 $file->{priority} = $3;
94 27         41 my $attrs = $4;
95 27         88 $file->{attrs} = { map { split /=/ } split ' ', $attrs };
  10         47  
96             } else {
97 0         0 error(g_('badly formed line in files list file, line %d'), $.);
98             }
99              
100 27 50       103 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         45 $count++;
105 27         88 $self->{files}->{$file->{filename}} = $file;
106             }
107             }
108              
109 7         241 return $count;
110             }
111              
112             sub load_dir {
113 1     1 0 3 my ($self, $dir) = @_;
114              
115 1         3 my $count = 0;
116 1 50       9 my $dh = IO::Dir->new($dir) or syserr(g_('cannot open directory %s'), $dir);
117              
118 1         116 while (defined(my $file = $dh->read)) {
119 5         89 my $pathname = "$dir/$file";
120 5 100       81 next unless -f $pathname;
121 3         15 $count += $self->load($pathname);
122             }
123              
124 1         26 return $count;
125             }
126              
127             sub get_files {
128 1     1 0 2 my $self = shift;
129              
130 1         2 return map { $self->{files}->{$_} } sort keys %{$self->{files}};
  5         10  
  1         6  
131             }
132              
133             sub get_file {
134 12     12 0 6490 my ($self, $filename) = @_;
135              
136 12         58 return $self->{files}->{$filename};
137             }
138              
139             sub add_file {
140 5     5 0 14 my ($self, $filename, $section, $priority, %attrs) = @_;
141              
142 5         9 my $file = $self->parse_filename($filename);
143 5 50       13 error(g_('invalid filename %s'), $filename) unless defined $file;
144 5         9 $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         11 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   11 my $keep = $opts{keep} // sub { 1 };
  5         12  
163              
164 3         6 foreach my $filename (keys %{$self->{files}}) {
  3         12  
165 15         40 my $file = $self->{files}->{$filename};
166              
167 15 100 100     28 if (not $keep->($file) or $remove->($file)) {
168 9         55 delete $self->{files}->{$filename};
169             }
170             }
171             }
172              
173             sub output {
174 7     7 1 21 my ($self, $fh) = @_;
175 7         12 my $str = '';
176              
177 7 50       14 binmode $fh if defined $fh;
178              
179 7         10 foreach my $filename (sort keys %{$self->{files}}) {
  7         37  
180 26         38 my $file = $self->{files}->{$filename};
181 26         54 my $entry = "$filename $file->{section} $file->{priority}";
182              
183 26 50       50 if (exists $file->{attrs}) {
184 26         31 foreach my $attr (sort keys %{$file->{attrs}}) {
  26         57  
185 9         19 $entry .= " $attr=$file->{attrs}->{$attr}";
186             }
187             }
188              
189 26         36 $entry .= "\n";
190              
191 26 50       43 print { $fh } $entry if defined $fh;
  0         0  
192 26         47 $str .= $entry;
193             }
194              
195 7         154 return $str;
196             }
197              
198             1;