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