OLD | NEW |
| (Empty) |
1 # Copyright © 2005, 2007 Frank Lichtenheld <frank@lichtenheld.de> | |
2 # Copyright © 2009 Raphaël Hertzog <hertzog@debian.org> | |
3 # | |
4 # This program is free software; you can redistribute it and/or modify | |
5 # it under the terms of the GNU General Public License as published by | |
6 # the Free Software Foundation; either version 2 of the License, or | |
7 # (at your option) any later version. | |
8 # | |
9 # This program is distributed in the hope that it will be useful, | |
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 # GNU General Public License for more details. | |
13 # | |
14 # You should have received a copy of the GNU General Public License | |
15 # along with this program. If not, see <https://www.gnu.org/licenses/>. | |
16 | |
17 =encoding utf8 | |
18 | |
19 =head1 NAME | |
20 | |
21 Dpkg::Changelog::Parse - generic changelog parser for dpkg-parsechangelog | |
22 | |
23 =head1 DESCRIPTION | |
24 | |
25 This module provides a single function changelog_parse() which reproduces | |
26 all the features of dpkg-parsechangelog. | |
27 | |
28 =head2 FUNCTIONS | |
29 | |
30 =cut | |
31 | |
32 package Dpkg::Changelog::Parse; | |
33 | |
34 use strict; | |
35 use warnings; | |
36 | |
37 our $VERSION = '1.00'; | |
38 | |
39 use Dpkg (); | |
40 use Dpkg::Gettext; | |
41 use Dpkg::ErrorHandling; | |
42 use Dpkg::Control::Changelog; | |
43 | |
44 use Exporter qw(import); | |
45 our @EXPORT = qw(changelog_parse); | |
46 | |
47 =over 4 | |
48 | |
49 =item my $fields = changelog_parse(%opt) | |
50 | |
51 This function will parse a changelog. In list context, it return as many | |
52 Dpkg::Control object as the parser did output. In scalar context, it will | |
53 return only the first one. If the parser didn't return any data, it will | |
54 return an empty in list context or undef on scalar context. If the parser | |
55 failed, it will die. | |
56 | |
57 The parsing itself is done by an external program (searched in the | |
58 following list of directories: $opt{libdir}, | |
59 F</usr/local/lib/dpkg/parsechangelog>, F</usr/lib/dpkg/parsechangelog>) That | |
60 program is named according to the format that it's able to parse. By | |
61 default it's either "debian" or the format name lookep up in the 40 last | |
62 lines of the changelog itself (extracted with this perl regular expression | |
63 "\schangelog-format:\s+([0-9a-z]+)\W"). But it can be overridden | |
64 with $opt{changelogformat}. The program expects the content of the | |
65 changelog file on its standard input. | |
66 | |
67 The changelog file that is parsed is F<debian/changelog> by default but it | |
68 can be overridden with $opt{file}. | |
69 | |
70 All the other keys in %opt are forwarded as parameter to the external | |
71 parser. If the key starts with "-", it's passed as is. If not, it's passed | |
72 as "--<key>". If the value of the corresponding hash entry is defined, then | |
73 it's passed as the parameter that follows. | |
74 | |
75 =cut | |
76 | |
77 sub changelog_parse { | |
78 my (%options) = @_; | |
79 my @parserpath = ('/usr/local/lib/dpkg/parsechangelog', | |
80 "$Dpkg::LIBDIR/parsechangelog", | |
81 '/usr/lib/dpkg/parsechangelog'); | |
82 my $format = 'debian'; | |
83 my $force = 0; | |
84 | |
85 # Extract and remove options that do not concern the changelog parser | |
86 # itself (and that we shouldn't forward) | |
87 if (exists $options{libdir}) { | |
88 unshift @parserpath, $options{libdir}; | |
89 delete $options{libdir}; | |
90 } | |
91 if (exists $options{changelogformat}) { | |
92 $format = $options{changelogformat}; | |
93 delete $options{changelogformat}; | |
94 $force = 1; | |
95 } | |
96 | |
97 # Set a default filename | |
98 if (not exists $options{file}) { | |
99 $options{file} = 'debian/changelog'; | |
100 } | |
101 my $changelogfile = $options{file}; | |
102 | |
103 # Extract the format from the changelog file if possible | |
104 unless($force or ($changelogfile eq '-')) { | |
105 open(my $format_fh, '-|', 'tail', '-n', '40', $changelogfile) | |
106 or syserr(_g('cannot create pipe for %s'), 'tail'); | |
107 while (<$format_fh>) { | |
108 $format = $1 if m/\schangelog-format:\s+([0-9a-z]+)\W/; | |
109 } | |
110 close($format_fh) or subprocerr(_g('tail of %s'), $changelogfile); | |
111 } | |
112 | |
113 # Find the right changelog parser | |
114 my $parser; | |
115 foreach my $dir (@parserpath) { | |
116 my $candidate = "$dir/$format"; | |
117 next if not -e $candidate; | |
118 if (-x _) { | |
119 $parser = $candidate; | |
120 last; | |
121 } else { | |
122 warning(_g('format parser %s not executable'), $candidate); | |
123 } | |
124 } | |
125 error(_g('changelog format %s is unknown'), $format) if not defined $parser; | |
126 | |
127 # Create the arguments for the changelog parser | |
128 my @exec = ($parser, "-l$changelogfile"); | |
129 foreach (keys %options) { | |
130 if (m/^-/) { | |
131 # Options passed untouched | |
132 push @exec, $_; | |
133 } else { | |
134 # Non-options are mapped to long options | |
135 push @exec, "--$_"; | |
136 } | |
137 push @exec, $options{$_} if defined($options{$_}); | |
138 } | |
139 | |
140 # Fork and call the parser | |
141 my $pid = open(my $parser_fh, '-|'); | |
142 syserr(_g('cannot fork for %s'), $parser) unless defined $pid; | |
143 if (not $pid) { | |
144 exec(@exec) or syserr(_g('cannot exec format parser: %s'), $parser); | |
145 } | |
146 | |
147 # Get the output into several Dpkg::Control objects | |
148 my (@res, $fields); | |
149 while (1) { | |
150 $fields = Dpkg::Control::Changelog->new(); | |
151 last unless $fields->parse($parser_fh, _g('output of changelog parser'))
; | |
152 push @res, $fields; | |
153 } | |
154 close($parser_fh) or subprocerr(_g('changelog parser %s'), $parser); | |
155 if (wantarray) { | |
156 return @res; | |
157 } else { | |
158 return $res[0] if (@res); | |
159 return; | |
160 } | |
161 } | |
162 | |
163 =back | |
164 | |
165 =cut | |
166 | |
167 1; | |
OLD | NEW |