| 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 |