Entry.pm 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. # Copyright © 2009 Raphaël Hertzog <hertzog@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. package Dpkg::Changelog::Entry;
  16. use strict;
  17. use warnings;
  18. our $VERSION = '1.01';
  19. use Carp;
  20. use Dpkg::Gettext;
  21. use Dpkg::ErrorHandling;
  22. use Dpkg::Control::Changelog;
  23. use overload
  24. '""' => \&output,
  25. 'eq' => sub { defined($_[1]) and "$_[0]" eq "$_[1]" },
  26. fallback => 1;
  27. =encoding utf8
  28. =head1 NAME
  29. Dpkg::Changelog::Entry - represents a changelog entry
  30. =head1 DESCRIPTION
  31. This object represents a changelog entry. It is composed
  32. of a set of lines with specific purpose: an header line, changes lines, a
  33. trailer line. Blank lines can be between those kind of lines.
  34. =head1 METHODS
  35. =over 4
  36. =item $entry = Dpkg::Changelog::Entry->new()
  37. Creates a new object. It doesn't represent a real changelog entry
  38. until one has been successfully parsed or built from scratch.
  39. =cut
  40. sub new {
  41. my $this = shift;
  42. my $class = ref($this) || $this;
  43. my $self = {
  44. header => undef,
  45. changes => [],
  46. trailer => undef,
  47. blank_after_header => [],
  48. blank_after_changes => [],
  49. blank_after_trailer => [],
  50. };
  51. bless $self, $class;
  52. return $self;
  53. }
  54. =item $str = $entry->output()
  55. =item "$entry"
  56. Get a string representation of the changelog entry.
  57. =item $entry->output($fh)
  58. Print the string representation of the changelog entry to a
  59. filehandle.
  60. =cut
  61. sub _format_output_block {
  62. my $lines = shift;
  63. return join('', map { $_ . "\n" } @{$lines});
  64. }
  65. sub output {
  66. my ($self, $fh) = @_;
  67. my $str = '';
  68. $str .= $self->{header} . "\n" if defined($self->{header});
  69. $str .= _format_output_block($self->{blank_after_header});
  70. $str .= _format_output_block($self->{changes});
  71. $str .= _format_output_block($self->{blank_after_changes});
  72. $str .= $self->{trailer} . "\n" if defined($self->{trailer});
  73. $str .= _format_output_block($self->{blank_after_trailer});
  74. print { $fh } $str if defined $fh;
  75. return $str;
  76. }
  77. =item $entry->get_part($part)
  78. Return either a string (for a single line) or an array ref (for multiple
  79. lines) corresponding to the requested part. $part can be
  80. "header, "changes", "trailer", "blank_after_header",
  81. "blank_after_changes", "blank_after_trailer".
  82. =cut
  83. sub get_part {
  84. my ($self, $part) = @_;
  85. croak "invalid part of changelog entry: $part" unless exists $self->{$part};
  86. return $self->{$part};
  87. }
  88. =item $entry->set_part($part, $value)
  89. Set the value of the corresponding part. $value can be a string
  90. or an array ref.
  91. =cut
  92. sub set_part {
  93. my ($self, $part, $value) = @_;
  94. croak "invalid part of changelog entry: $part" unless exists $self->{$part};
  95. if (ref($self->{$part})) {
  96. if (ref($value)) {
  97. $self->{$part} = $value;
  98. } else {
  99. $self->{$part} = [ $value ];
  100. }
  101. } else {
  102. $self->{$part} = $value;
  103. }
  104. }
  105. =item $entry->extend_part($part, $value)
  106. Concatenate $value at the end of the part. If the part is already a
  107. multi-line value, $value is added as a new line otherwise it's
  108. concatenated at the end of the current line.
  109. =cut
  110. sub extend_part {
  111. my ($self, $part, $value, @rest) = @_;
  112. croak "invalid part of changelog entry: $part" unless exists $self->{$part};
  113. if (ref($self->{$part})) {
  114. if (ref($value)) {
  115. push @{$self->{$part}}, @$value;
  116. } else {
  117. push @{$self->{$part}}, $value;
  118. }
  119. } else {
  120. if (defined($self->{$part})) {
  121. if (ref($value)) {
  122. $self->{$part} = [ $self->{$part}, @$value ];
  123. } else {
  124. $self->{$part} .= $value;
  125. }
  126. } else {
  127. $self->{$part} = $value;
  128. }
  129. }
  130. }
  131. =item $is_empty = $entry->is_empty()
  132. Returns 1 if the changelog entry doesn't contain anything at all.
  133. Returns 0 as soon as it contains something in any of its non-blank
  134. parts.
  135. =cut
  136. sub is_empty {
  137. my $self = shift;
  138. return !(defined($self->{header}) || defined($self->{trailer}) ||
  139. scalar(@{$self->{changes}}));
  140. }
  141. =item $entry->normalize()
  142. Normalize the content. Strip whitespaces at end of lines, use a single
  143. empty line to separate each part.
  144. =cut
  145. sub normalize {
  146. my $self = shift;
  147. if (defined($self->{header})) {
  148. $self->{header} =~ s/\s+$//g;
  149. $self->{blank_after_header} = [''];
  150. } else {
  151. $self->{blank_after_header} = [];
  152. }
  153. if (scalar(@{$self->{changes}})) {
  154. s/\s+$//g foreach @{$self->{changes}};
  155. $self->{blank_after_changes} = [''];
  156. } else {
  157. $self->{blank_after_changes} = [];
  158. }
  159. if (defined($self->{trailer})) {
  160. $self->{trailer} =~ s/\s+$//g;
  161. $self->{blank_after_trailer} = [''];
  162. } else {
  163. $self->{blank_after_trailer} = [];
  164. }
  165. }
  166. =item $src = $entry->get_source()
  167. Return the name of the source package associated to the changelog entry.
  168. =cut
  169. sub get_source {
  170. return;
  171. }
  172. =item $ver = $entry->get_version()
  173. Return the version associated to the changelog entry.
  174. =cut
  175. sub get_version {
  176. return;
  177. }
  178. =item @dists = $entry->get_distributions()
  179. Return a list of target distributions for this version.
  180. =cut
  181. sub get_distributions {
  182. return;
  183. }
  184. =item $fields = $entry->get_optional_fields()
  185. Return a set of optional fields exposed by the changelog entry.
  186. It always returns a Dpkg::Control object (possibly empty though).
  187. =cut
  188. sub get_optional_fields {
  189. return Dpkg::Control::Changelog->new();
  190. }
  191. =item $urgency = $entry->get_urgency()
  192. Return the urgency of the associated upload.
  193. =cut
  194. sub get_urgency {
  195. return;
  196. }
  197. =item $maint = $entry->get_maintainer()
  198. Return the string identifying the person who signed this changelog entry.
  199. =cut
  200. sub get_maintainer {
  201. return;
  202. }
  203. =item $time = $entry->get_timestamp()
  204. Return the timestamp of the changelog entry.
  205. =cut
  206. sub get_timestamp {
  207. return;
  208. }
  209. =item $time = $entry->get_timepiece()
  210. Return the timestamp of the changelog entry as a Time::Piece object.
  211. This function might return undef if there was no timestamp.
  212. =cut
  213. sub get_timepiece {
  214. return;
  215. }
  216. =item $str = $entry->get_dpkg_changes()
  217. Returns a string that is suitable for usage in a C<Changes> field
  218. in the output format of C<dpkg-parsechangelog>.
  219. =cut
  220. sub get_dpkg_changes {
  221. my $self = shift;
  222. my $header = $self->get_part('header') // '';
  223. $header =~ s/\s+$//;
  224. return "\n$header\n\n" . join("\n", @{$self->get_part('changes')});
  225. }
  226. =back
  227. =head1 CHANGES
  228. =head2 Version 1.01 (dpkg 1.18.8)
  229. New method: $entry->get_timepiece().
  230. =head2 Version 1.00 (dpkg 1.15.6)
  231. Mark the module as public.
  232. =cut
  233. 1;