Parse.pm 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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 <http://www.gnu.org/licenses/>.
  16. =head1 NAME
  17. Dpkg::Changelog::Parse - generic changelog parser for dpkg-parsechangelog
  18. =head1 DESCRIPTION
  19. This module provides a single function changelog_parse() which reproduces
  20. all the features of dpkg-parsechangelog.
  21. =head2 Functions
  22. =cut
  23. package Dpkg::Changelog::Parse;
  24. use strict;
  25. use warnings;
  26. use Dpkg; # for $dpkglibdir
  27. use Dpkg::Gettext;
  28. use Dpkg::ErrorHandling;
  29. use Dpkg::Control::Changelog;
  30. use base qw(Exporter);
  31. our @EXPORT = qw(changelog_parse);
  32. =head3 my $fields = changelog_parse(%opt)
  33. This function will parse a changelog. In list context, it return as many
  34. Dpkg::Control object as the parser did output. In scalar context, it will
  35. return only the first one. If the parser didn't return any data, it will
  36. return an empty in list context or undef on scalar context. If the parser
  37. failed, it will die.
  38. The parsing itself is done by an external program (searched in the
  39. following list of directories: $opt{libdir},
  40. /usr/local/lib/dpkg/parsechangelog, /usr/lib/dpkg/parsechangelog) That
  41. program is named according to the format that it's able to parse. By
  42. default it's either "debian" or the format name lookep up in the 40 last
  43. lines of the changelog itself (extracted with this perl regular expression
  44. "\schangelog-format:\s+([0-9a-z]+)\W"). But it can be overriden
  45. with $opt{changelogformat}. The program expects the content of the
  46. changelog file on its standard input.
  47. The changelog file that is parsed is debian/changelog by default but it
  48. can be overriden with $opt{file}.
  49. All the other keys in %opt are forwarded as parameter to the external
  50. parser. If the key starts with "-", it's passed as is. If not, it's passed
  51. as "--<key>". If the value of the corresponding hash entry is defined, then
  52. it's passed as the parameter that follows.
  53. =cut
  54. sub changelog_parse {
  55. my (%options) = @_;
  56. my @parserpath = ("/usr/local/lib/dpkg/parsechangelog",
  57. "$dpkglibdir/parsechangelog",
  58. "/usr/lib/dpkg/parsechangelog");
  59. my $format = "debian";
  60. my $changelogfile = "debian/changelog";
  61. my $force = 0;
  62. # Extract and remove options that do not concern the changelog parser
  63. # itself (and that we shouldn't forward)
  64. if (exists $options{"libdir"}) {
  65. unshift @parserpath, $options{"libdir"};
  66. delete $options{"libdir"};
  67. }
  68. if (exists $options{"file"}) {
  69. $changelogfile = $options{"file"};
  70. delete $options{"file"};
  71. }
  72. if (exists $options{"changelogformat"}) {
  73. $format = $options{"changelogformat"};
  74. delete $options{"changelogformat"};
  75. $force = 1;
  76. }
  77. # Extract the format from the changelog file if possible
  78. unless($force or ($changelogfile eq "-")) {
  79. open(P, "-|", "tail", "-n", "40", $changelogfile);
  80. while(<P>) {
  81. $format = $1 if m/\schangelog-format:\s+([0-9a-z]+)\W/;
  82. }
  83. close(P) or subprocerr(_g("tail of %s"), $changelogfile);
  84. }
  85. # Find the right changelog parser
  86. my $parser;
  87. foreach my $dir (@parserpath) {
  88. my $candidate = "$dir/$format";
  89. next if not -e $candidate;
  90. if (-x _) {
  91. $parser = $candidate;
  92. last;
  93. } else {
  94. warning(_g("format parser %s not executable"), $candidate);
  95. }
  96. }
  97. error(_g("changelog format %s is unknown"), $format) if not defined $parser;
  98. # Create the arguments for the changelog parser
  99. my @exec = ($parser, "-l$changelogfile");
  100. foreach (keys %options) {
  101. if (m/^-/) {
  102. # Options passed untouched
  103. push @exec, $_;
  104. } else {
  105. # Non-options are mapped to long options
  106. push @exec, "--$_";
  107. }
  108. push @exec, $options{$_} if defined($options{$_});
  109. }
  110. # Fork and call the parser
  111. my $pid = open(P, "-|");
  112. syserr(_g("fork for %s"), $parser) unless defined $pid;
  113. if (not $pid) {
  114. if ($changelogfile ne "-") {
  115. open(STDIN, "<", $changelogfile) or
  116. syserr(_g("cannot open %s"), $changelogfile);
  117. }
  118. exec(@exec) || syserr(_g("cannot exec format parser: %s"), $parser);
  119. }
  120. # Get the output into several Dpkg::Control objects
  121. my (@res, $fields);
  122. while (1) {
  123. $fields = Dpkg::Control::Changelog->new();
  124. last unless $fields->parse_fh(\*P, _g("output of changelog parser"));
  125. push @res, $fields;
  126. }
  127. close(P) or subprocerr(_g("changelog parser %s"), $parser);
  128. if (wantarray) {
  129. return @res;
  130. } else {
  131. return $res[0] if (@res);
  132. return undef;
  133. }
  134. }
  135. 1;