File: | Dpkg/Dist/Files.pm |
Coverage: | 85.7% |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | # Copyright © 2014-2015 Guillem Jover <guillem@debian.org> | ||||||
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 <https://www.gnu.org/licenses/>. | ||||||
15 | |||||||
16 | =encoding utf8 | ||||||
17 | |||||||
18 - 29 | =head1 NAME Dpkg::Dist::Files - handle built artifacts to distribute =head1 DESCRIPTION This module provides a class used to parse and write the F<debian/files> file, as part of the list of built artifacts to include in an upload. B<Note>: This is a private module, its API can change at any time. =cut | ||||||
30 | |||||||
31 | package Dpkg::Dist::Files 0.01; | ||||||
32 | |||||||
33 | 3 3 3 | 10 3 52 | use strict; | ||||
34 | 3 3 3 | 7 3 87 | use warnings; | ||||
35 | |||||||
36 | 3 3 3 | 4375 16436 107 | use IO::Dir; | ||||
37 | |||||||
38 | 3 3 3 | 943 17 90 | use Dpkg::Gettext; | ||||
39 | 3 3 3 | 754 3 106 | use Dpkg::ErrorHandling; | ||||
40 | |||||||
41 | 3 3 3 | 6 2 6 | use parent qw(Dpkg::Interface::Storable); | ||||
42 | |||||||
43 | sub new { | ||||||
44 | 3 | 0 | 2 | my ($this, %opts) = @_; | |||
45 | 3 | 13 | my $class = ref($this) || $this; | ||||
46 | |||||||
47 | 3 | 4 | my $self = { | ||||
48 | options => [], | ||||||
49 | files => {}, | ||||||
50 | }; | ||||||
51 | 3 | 4 | foreach my $opt (keys %opts) { | ||||
52 | 0 | 0 | $self->{$opt} = $opts{$opt}; | ||||
53 | } | ||||||
54 | 3 | 2 | bless $self, $class; | ||||
55 | |||||||
56 | 3 | 4 | return $self; | ||||
57 | } | ||||||
58 | |||||||
59 | sub reset { | ||||||
60 | 15 | 0 | 12 | my $self = shift; | |||
61 | |||||||
62 | 15 | 67 | $self->{files} = {}; | ||||
63 | } | ||||||
64 | |||||||
65 | sub parse_filename { | ||||||
66 | 99 | 0 | 96 | my ($self, $fn) = @_; | |||
67 | |||||||
68 | 99 | 55 | my $file; | ||||
69 | |||||||
70 | 99 | 175 | if ($fn =~ m/^(([-+:.0-9a-z]+)_([^_]+)_([-\w]+)\.([a-z0-9.]+))$/) { | ||||
71 | # Artifact using the common <name>_<version>_<arch>.<type> pattern. | ||||||
72 | 54 | 42 | $file->{filename} = $1; | ||||
73 | 54 | 41 | $file->{package} = $2; | ||||
74 | 54 | 39 | $file->{version} = $3; | ||||
75 | 54 | 35 | $file->{arch} = $4; | ||||
76 | 54 | 46 | $file->{package_type} = $5; | ||||
77 | } elsif ($fn =~ m/^([-+:.,_0-9a-zA-Z~]+)$/) { | ||||||
78 | # Artifact with no common pattern, usually called byhand or raw, as | ||||||
79 | # they might require manual processing on the server side, or custom | ||||||
80 | # actions per file type. | ||||||
81 | 42 | 37 | $file->{filename} = $1; | ||||
82 | } else { | ||||||
83 | 3 | 2 | $file = undef; | ||||
84 | } | ||||||
85 | |||||||
86 | 99 | 54 | return $file; | ||||
87 | } | ||||||
88 | |||||||
89 | sub parse { | ||||||
90 | 21 | 1 | 21 | my ($self, $fh, $desc) = @_; | |||
91 | 21 | 8 | my $count = 0; | ||||
92 | |||||||
93 | 21 | 15 | local $_; | ||||
94 | 21 | 27 | binmode $fh; | ||||
95 | |||||||
96 | 21 | 92 | while (<$fh>) { | ||||
97 | 81 | 58 | chomp; | ||||
98 | |||||||
99 | 81 | 31 | my $file; | ||||
100 | |||||||
101 | 81 | 163 | if (m/^(\S+) (\S+) (\S+)((?:\s+[0-9a-z-]+=\S+)*)$/) { | ||||
102 | 81 | 49 | $file = $self->parse_filename($1); | ||||
103 | 81 | 64 | error(g_('badly formed file name in files list file, line %d'), $.) | ||||
104 | unless defined $file; | ||||||
105 | 81 | 58 | $file->{section} = $2; | ||||
106 | 81 | 56 | $file->{priority} = $3; | ||||
107 | 81 | 45 | my $attrs = $4; | ||||
108 | 81 30 | 73 49 | $file->{attrs} = { map { split /=/ } split ' ', $attrs }; | ||||
109 | } else { | ||||||
110 | 0 | 0 | error(g_('badly formed line in files list file, line %d'), $.); | ||||
111 | } | ||||||
112 | |||||||
113 | 81 | 119 | if (defined $self->{files}->{$file->{filename}}) { | ||||
114 | warning(g_('duplicate files list entry for file %s (line %d)'), | ||||||
115 | 0 | 0 | $file->{filename}, $.); | ||||
116 | } else { | ||||||
117 | 81 | 40 | $count++; | ||||
118 | 81 | 87 | $self->{files}->{$file->{filename}} = $file; | ||||
119 | } | ||||||
120 | } | ||||||
121 | |||||||
122 | 21 | 28 | return $count; | ||||
123 | } | ||||||
124 | |||||||
125 | sub load_dir { | ||||||
126 | 3 | 0 | 4 | my ($self, $dir) = @_; | |||
127 | |||||||
128 | 3 | 1 | my $count = 0; | ||||
129 | 3 | 13 | my $dh = IO::Dir->new($dir) or syserr(g_('cannot open directory %s'), $dir); | ||||
130 | |||||||
131 | 3 | 120 | while (defined(my $file = $dh->read)) { | ||||
132 | 15 | 82 | my $pathname = "$dir/$file"; | ||||
133 | 15 | 40 | next unless -f $pathname; | ||||
134 | 9 | 11 | $count += $self->load($pathname); | ||||
135 | } | ||||||
136 | |||||||
137 | 3 | 16 | return $count; | ||||
138 | } | ||||||
139 | |||||||
140 | sub get_files { | ||||||
141 | 3 | 0 | 3 | my $self = shift; | |||
142 | |||||||
143 | 3 15 3 | 2 13 6 | return map { $self->{files}->{$_} } sort keys %{$self->{files}}; | ||||
144 | } | ||||||
145 | |||||||
146 | sub get_file { | ||||||
147 | 36 | 0 | 38 | my ($self, $filename) = @_; | |||
148 | |||||||
149 | 36 | 51 | return $self->{files}->{$filename}; | ||||
150 | } | ||||||
151 | |||||||
152 | sub add_file { | ||||||
153 | 15 | 0 | 19 | my ($self, $filename, $section, $priority, %attrs) = @_; | |||
154 | |||||||
155 | 15 | 12 | my $file = $self->parse_filename($filename); | ||||
156 | 15 | 17 | error(g_('invalid filename %s'), $filename) unless defined $file; | ||||
157 | 15 | 13 | $file->{section} = $section; | ||||
158 | 15 | 9 | $file->{priority} = $priority; | ||||
159 | 15 | 13 | $file->{attrs} = \%attrs; | ||||
160 | |||||||
161 | 15 | 18 | $self->{files}->{$filename} = $file; | ||||
162 | |||||||
163 | 15 | 13 | return $file; | ||||
164 | } | ||||||
165 | |||||||
166 | sub del_file { | ||||||
167 | 3 | 0 | 4 | my ($self, $filename) = @_; | |||
168 | |||||||
169 | 3 | 4 | delete $self->{files}->{$filename}; | ||||
170 | } | ||||||
171 | |||||||
172 | sub filter { | ||||||
173 | 9 | 0 | 13 | my ($self, %opts) = @_; | |||
174 | 9 6 | 14 9 | my $remove = $opts{remove} // sub { 0 }; | ||||
175 | 9 15 | 20 18 | my $keep = $opts{keep} // sub { 1 }; | ||||
176 | |||||||
177 | 9 9 | 6 12 | foreach my $filename (keys %{$self->{files}}) { | ||||
178 | 45 | 24 | my $file = $self->{files}->{$filename}; | ||||
179 | |||||||
180 | 45 | 32 | if (not $keep->($file) or $remove->($file)) { | ||||
181 | 27 | 40 | delete $self->{files}->{$filename}; | ||||
182 | } | ||||||
183 | } | ||||||
184 | } | ||||||
185 | |||||||
186 | sub output { | ||||||
187 | 21 | 1 | 18 | my ($self, $fh) = @_; | |||
188 | 21 | 11 | my $str = ''; | ||||
189 | |||||||
190 | 21 | 19 | binmode $fh if defined $fh; | ||||
191 | |||||||
192 | 21 21 | 12 43 | foreach my $filename (sort keys %{$self->{files}}) { | ||||
193 | 78 | 37 | my $file = $self->{files}->{$filename}; | ||||
194 | 78 | 51 | my $entry = "$filename $file->{section} $file->{priority}"; | ||||
195 | |||||||
196 | 78 | 59 | if (exists $file->{attrs}) { | ||||
197 | 78 78 | 32 65 | foreach my $attr (sort keys %{$file->{attrs}}) { | ||||
198 | 27 | 22 | $entry .= " $attr=$file->{attrs}->{$attr}"; | ||||
199 | } | ||||||
200 | } | ||||||
201 | |||||||
202 | 78 | 40 | $entry .= "\n"; | ||||
203 | |||||||
204 | 78 0 | 51 0 | print { $fh } $entry if defined $fh; | ||||
205 | 78 | 55 | $str .= $entry; | ||||
206 | } | ||||||
207 | |||||||
208 | 21 | 39 | return $str; | ||||
209 | } | ||||||
210 | |||||||
211 - 217 | =head1 CHANGES =head2 Version 0.xx This is a private module. =cut | ||||||
218 | |||||||
219 | 1; |