OLD | NEW |
(Empty) | |
| 1 # Copyright © 2006-2009,2012 Guillem Jover <guillem@debian.org> |
| 2 # Copyright © 2007-2010 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 package Dpkg::Substvars; |
| 18 |
| 19 use strict; |
| 20 use warnings; |
| 21 |
| 22 our $VERSION = '1.02'; |
| 23 |
| 24 use Dpkg (); |
| 25 use Dpkg::Arch qw(get_host_arch); |
| 26 use Dpkg::ErrorHandling; |
| 27 use Dpkg::Gettext; |
| 28 |
| 29 use Carp; |
| 30 use POSIX qw(:errno_h); |
| 31 |
| 32 use parent qw(Dpkg::Interface::Storable); |
| 33 |
| 34 my $maxsubsts = 50; |
| 35 |
| 36 =encoding utf8 |
| 37 |
| 38 =head1 NAME |
| 39 |
| 40 Dpkg::Substvars - handle variable substitution in strings |
| 41 |
| 42 =head1 DESCRIPTION |
| 43 |
| 44 It provides some an object which is able to substitute variables in |
| 45 strings. |
| 46 |
| 47 =head1 METHODS |
| 48 |
| 49 =over 8 |
| 50 |
| 51 =item my $s = Dpkg::Substvars->new($file) |
| 52 |
| 53 Create a new object that can do substitutions. By default it contains |
| 54 generic substitutions like ${Newline}, ${Space}, ${Tab}, ${dpkg:Version} |
| 55 and ${dpkg:Upstream-Version}. |
| 56 |
| 57 Additional substitutions will be read from the $file passed as parameter. |
| 58 |
| 59 It keeps track of which substitutions were actually used (only counting |
| 60 substvars(), not get()), and warns about unused substvars when asked to. The |
| 61 substitutions that are always present are not included in these warnings. |
| 62 |
| 63 =cut |
| 64 |
| 65 sub new { |
| 66 my ($this, $arg) = @_; |
| 67 my $class = ref($this) || $this; |
| 68 my $self = { |
| 69 vars => { |
| 70 'Newline' => "\n", |
| 71 'Space' => ' ', |
| 72 'Tab' => "\t", |
| 73 'dpkg:Version' => $Dpkg::PROGVERSION, |
| 74 'dpkg:Upstream-Version' => $Dpkg::PROGVERSION, |
| 75 }, |
| 76 used => {}, |
| 77 msg_prefix => '', |
| 78 }; |
| 79 $self->{vars}{'dpkg:Upstream-Version'} =~ s/-[^-]+$//; |
| 80 bless $self, $class; |
| 81 $self->mark_as_used($_) foreach keys %{$self->{vars}}; |
| 82 if ($arg) { |
| 83 $self->load($arg) if -e $arg; |
| 84 } |
| 85 return $self; |
| 86 } |
| 87 |
| 88 =item $s->set($key, $value) |
| 89 |
| 90 Add/replace a substitution. |
| 91 |
| 92 =cut |
| 93 |
| 94 sub set { |
| 95 my ($self, $key, $value) = @_; |
| 96 $self->{vars}{$key} = $value; |
| 97 } |
| 98 |
| 99 =item $s->set_as_used($key, $value) |
| 100 |
| 101 Add/replace a substitution and mark it as used (no warnings will be produced |
| 102 even if unused). |
| 103 |
| 104 =cut |
| 105 |
| 106 sub set_as_used { |
| 107 my ($self, $key, $value) = @_; |
| 108 $self->set($key, $value); |
| 109 $self->mark_as_used($key); |
| 110 } |
| 111 |
| 112 =item $s->get($key) |
| 113 |
| 114 Get the value of a given substitution. |
| 115 |
| 116 =cut |
| 117 |
| 118 sub get { |
| 119 my ($self, $key) = @_; |
| 120 return $self->{vars}{$key}; |
| 121 } |
| 122 |
| 123 =item $s->delete($key) |
| 124 |
| 125 Remove a given substitution. |
| 126 |
| 127 =cut |
| 128 |
| 129 sub delete { |
| 130 my ($self, $key) = @_; |
| 131 delete $self->{used}{$key}; |
| 132 return delete $self->{vars}{$key}; |
| 133 } |
| 134 |
| 135 =item $s->mark_as_used($key) |
| 136 |
| 137 Prevents warnings about a unused substitution, for example if it is provided by |
| 138 default. |
| 139 |
| 140 =cut |
| 141 |
| 142 sub mark_as_used { |
| 143 my ($self, $key) = @_; |
| 144 $self->{used}{$key}++; |
| 145 } |
| 146 |
| 147 =item $s->no_warn($key) |
| 148 |
| 149 Obsolete function, use mark_as_used() instead. |
| 150 |
| 151 =cut |
| 152 |
| 153 sub no_warn { |
| 154 my ($self, $key) = @_; |
| 155 carp 'obsolete no_warn() function, use mark_as_used() instead'; |
| 156 $self->mark_as_used($key); |
| 157 } |
| 158 |
| 159 =item $s->load($file) |
| 160 |
| 161 Add new substitutions read from $file. |
| 162 |
| 163 =item $s->parse($fh, $desc) |
| 164 |
| 165 Add new substitutions read from the filehandle. $desc is used to identify |
| 166 the filehandle in error messages. |
| 167 |
| 168 =cut |
| 169 |
| 170 sub parse { |
| 171 my ($self, $fh, $varlistfile) = @_; |
| 172 binmode($fh); |
| 173 while (<$fh>) { |
| 174 next if m/^\s*\#/ || !m/\S/; |
| 175 s/\s*\n$//; |
| 176 if (! m/^(\w[-:0-9A-Za-z]*)\=(.*)$/) { |
| 177 error(_g('bad line in substvars file %s at line %d'), |
| 178 $varlistfile, $.); |
| 179 } |
| 180 $self->{vars}{$1} = $2; |
| 181 } |
| 182 } |
| 183 |
| 184 =item $s->set_version_substvars($sourceversion, $binaryversion) |
| 185 |
| 186 Defines ${binary:Version}, ${source:Version} and |
| 187 ${source:Upstream-Version} based on the given version strings. |
| 188 |
| 189 These will never be warned about when unused. |
| 190 |
| 191 =cut |
| 192 |
| 193 sub set_version_substvars { |
| 194 my ($self, $sourceversion, $binaryversion) = @_; |
| 195 |
| 196 # Handle old function signature taking only one argument. |
| 197 $binaryversion ||= $sourceversion; |
| 198 |
| 199 # For backwards compatibility on binNMUs that do not use the Binary-Only |
| 200 # field on the changelog, always fix up the source version. |
| 201 $sourceversion =~ s/\+b[0-9]+$//; |
| 202 |
| 203 $self->{vars}{'binary:Version'} = $binaryversion; |
| 204 $self->{vars}{'source:Version'} = $sourceversion; |
| 205 $self->{vars}{'source:Upstream-Version'} = $sourceversion; |
| 206 $self->{vars}{'source:Upstream-Version'} =~ s/-[^-]*$//; |
| 207 |
| 208 # XXX: Source-Version is now deprecated, remove in the future. |
| 209 $self->{vars}{'Source-Version'} = $binaryversion; |
| 210 |
| 211 $self->mark_as_used($_) foreach qw/binary:Version source:Version source:Upst
ream-Version Source-Version/; |
| 212 } |
| 213 |
| 214 =item $s->set_arch_substvars() |
| 215 |
| 216 Defines architecture variables: ${Arch}. |
| 217 |
| 218 This will never be warned about when unused. |
| 219 |
| 220 =cut |
| 221 |
| 222 sub set_arch_substvars { |
| 223 my ($self) = @_; |
| 224 |
| 225 $self->set_as_used('Arch', get_host_arch()); |
| 226 } |
| 227 |
| 228 =item $newstring = $s->substvars($string) |
| 229 |
| 230 Substitutes variables in $string and return the result in $newstring. |
| 231 |
| 232 =cut |
| 233 |
| 234 sub substvars { |
| 235 my ($self, $v, %opts) = @_; |
| 236 my $lhs; |
| 237 my $vn; |
| 238 my $rhs = ''; |
| 239 my $count = 0; |
| 240 $opts{msg_prefix} = $self->{msg_prefix} unless exists $opts{msg_prefix}; |
| 241 $opts{no_warn} = 0 unless exists $opts{no_warn}; |
| 242 |
| 243 while ($v =~ m/^(.*?)\$\{([-:0-9a-z]+)\}(.*)$/si) { |
| 244 # If we have consumed more from the leftover data, then |
| 245 # reset the recursive counter. |
| 246 $count = 0 if (length($3) < length($rhs)); |
| 247 |
| 248 if ($count >= $maxsubsts) { |
| 249 error($opts{msg_prefix} . |
| 250 _g("too many substitutions - recursive ? - in \`%s'"), $v); |
| 251 } |
| 252 $lhs = $1; $vn = $2; $rhs = $3; |
| 253 if (defined($self->{vars}{$vn})) { |
| 254 $v = $lhs . $self->{vars}{$vn} . $rhs; |
| 255 $self->mark_as_used($vn); |
| 256 $count++; |
| 257 } else { |
| 258 warning($opts{msg_prefix} . _g('unknown substitution variable ${%s}'
), |
| 259 $vn) unless $opts{no_warn}; |
| 260 $v = $lhs . $rhs; |
| 261 } |
| 262 } |
| 263 return $v; |
| 264 } |
| 265 |
| 266 =item $s->warn_about_unused() |
| 267 |
| 268 Issues warning about any variables that were set, but not used |
| 269 |
| 270 =cut |
| 271 |
| 272 sub warn_about_unused { |
| 273 my ($self, %opts) = @_; |
| 274 $opts{msg_prefix} = $self->{msg_prefix} unless exists $opts{msg_prefix}; |
| 275 |
| 276 foreach my $vn (keys %{$self->{vars}}) { |
| 277 next if $self->{used}{$vn}; |
| 278 # Empty substitutions variables are ignored on the basis |
| 279 # that they are not required in the current situation |
| 280 # (example: debhelper's misc:Depends in many cases) |
| 281 next if $self->{vars}{$vn} eq ''; |
| 282 warning($opts{msg_prefix} . _g('unused substitution variable ${%s}'), |
| 283 $vn); |
| 284 } |
| 285 } |
| 286 |
| 287 =item $s->set_msg_prefix($prefix) |
| 288 |
| 289 Define a prefix displayed before all warnings/error messages output |
| 290 by the module. |
| 291 |
| 292 =cut |
| 293 |
| 294 sub set_msg_prefix { |
| 295 my ($self, $prefix) = @_; |
| 296 $self->{msg_prefix} = $prefix; |
| 297 } |
| 298 |
| 299 =item $s->save($file) |
| 300 |
| 301 Store all substitutions variables except the automatic ones in the |
| 302 indicated file. |
| 303 |
| 304 =item "$s" |
| 305 |
| 306 Return a string representation of all substitutions variables except the |
| 307 automatic ones. |
| 308 |
| 309 =item $str = $s->output($fh) |
| 310 |
| 311 Print all substitutions variables except the automatic ones in the |
| 312 filehandle and return the content written. |
| 313 |
| 314 =cut |
| 315 |
| 316 sub output { |
| 317 my ($self, $fh) = @_; |
| 318 my $str = ''; |
| 319 # Store all non-automatic substitutions only |
| 320 foreach my $vn (sort keys %{$self->{vars}}) { |
| 321 next if /^(?:(?:dpkg|source|binary):(?:Source-)?Version|Space|Tab|Newlin
e|Arch|Source-Version|F:.+)$/; |
| 322 my $line = "$vn=" . $self->{vars}{$vn} . "\n"; |
| 323 print { $fh } $line if defined $fh; |
| 324 $str .= $line; |
| 325 } |
| 326 return $str; |
| 327 } |
| 328 |
| 329 =back |
| 330 |
| 331 =head1 AUTHOR |
| 332 |
| 333 Raphaël Hertzog <hertzog@debian.org>. |
| 334 |
| 335 =cut |
| 336 |
| 337 1; |
OLD | NEW |