Dpkg::Source::Package: Document method additions with an object
[dpkg.git] / scripts / Dpkg / Source / Package.pm
blob06884c330eb43341715f94d6fdd70c80b8e39b9c
1 # Copyright © 2008-2011 Raphaël Hertzog <hertzog@debian.org>
2 # Copyright © 2008-2019 Guillem Jover <guillem@debian.org>
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.
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.
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/>.
17 =encoding utf8
19 =head1 NAME
21 Dpkg::Source::Package - manipulate Debian source packages
23 =head1 DESCRIPTION
25 This module provides a class that can manipulate Debian source
26 packages. While it supports both the extraction and the creation
27 of source packages, the only API that is officially supported
28 is the one that supports the extraction of the source package.
30 =cut
32 package Dpkg::Source::Package 2.02;
34 use strict;
35 use warnings;
37 our @EXPORT_OK = qw(
38 get_default_diff_ignore_regex
39 set_default_diff_ignore_regex
40 get_default_tar_ignore_pattern
43 use Exporter qw(import);
44 use POSIX qw(:errno_h :sys_wait_h);
45 use Carp;
46 use File::Temp;
47 use File::Copy qw(cp);
48 use File::Basename;
49 use File::Spec;
51 use Dpkg::Gettext;
52 use Dpkg::ErrorHandling;
53 use Dpkg::Control;
54 use Dpkg::Checksums;
55 use Dpkg::Version;
56 use Dpkg::Compression;
57 use Dpkg::Path qw(check_files_are_the_same check_directory_traversal);
58 use Dpkg::Vendor qw(run_vendor_hook);
59 use Dpkg::Source::Format;
60 use Dpkg::OpenPGP;
61 use Dpkg::OpenPGP::ErrorCodes;
63 my $diff_ignore_default_regex = '
64 # Ignore general backup files
65 (?:^|/).*~$|
66 # Ignore emacs recovery files
67 (?:^|/)\.#.*$|
68 # Ignore vi swap files
69 (?:^|/)\..*\.sw.$|
70 # Ignore baz-style junk files or directories
71 (?:^|/),,.*(?:$|/.*$)|
72 # File-names that should be ignored (never directories)
73 (?:^|/)(?:DEADJOE|\.arch-inventory|\.(?:bzr|cvs|hg|git|mtn-)ignore)$|
74 # File or directory names that should be ignored
75 (?:^|/)(?:CVS|RCS|\.deps|\{arch\}|\.arch-ids|\.svn|
76 \.hg(?:tags|sigs)?|_darcs|\.git(?:attributes|modules|review)?|
77 \.mailmap|\.shelf|_MTN|\.be|\.bzr(?:\.backup|tags)?)(?:$|/.*$)
79 # Take out comments and newlines
80 $diff_ignore_default_regex =~ s/^#.*$//mg;
81 $diff_ignore_default_regex =~ s/\n//sg;
83 no warnings 'qw'; ## no critic (TestingAndDebugging::ProhibitNoWarnings)
84 my @tar_ignore_default_pattern = qw(
85 *.a
86 *.la
87 *.o
88 *.so
89 .*.sw?
90 */*~
91 ,,*
92 .[#~]*
93 .arch-ids
94 .arch-inventory
95 .be
96 .bzr
97 .bzr.backup
98 .bzr.tags
99 .bzrignore
100 .cvsignore
101 .deps
102 .git
103 .gitattributes
104 .gitignore
105 .gitmodules
106 .gitreview
108 .hgignore
109 .hgsigs
110 .hgtags
111 .mailmap
112 .mtn-ignore
113 .shelf
114 .svn
116 DEADJOE
118 _MTN
119 _darcs
120 {arch}
122 ## use critic
124 =head1 FUNCTIONS
126 =over 4
128 =item $string = get_default_diff_ignore_regex()
130 Returns the default diff ignore regex.
132 =cut
134 sub get_default_diff_ignore_regex {
135 return $diff_ignore_default_regex;
138 =item set_default_diff_ignore_regex($string)
140 Set a regex as the new default diff ignore regex.
142 =cut
144 sub set_default_diff_ignore_regex {
145 my $regex = shift;
147 $diff_ignore_default_regex = $regex;
150 =item @array = get_default_tar_ignore_pattern()
152 Returns the default tar ignore pattern, as an array.
154 =cut
156 sub get_default_tar_ignore_pattern {
157 return @tar_ignore_default_pattern;
160 =back
162 =head1 METHODS
164 =over 4
166 =item $p = Dpkg::Source::Package->new(%opts, options => {})
168 Creates a new object corresponding to a source package. When the key
169 B<filename> is set to a F<.dsc> file, it will be used to initialize the
170 source package with its description. Otherwise if the B<format> key is
171 set to a valid value, the object will be initialized for that format
172 (since dpkg 1.19.3).
174 The B<options> key is a hash ref which supports the following options:
176 =over 8
178 =item skip_debianization
180 If set to 1, do not apply Debian changes on the extracted source package.
182 =item skip_patches
184 If set to 1, do not apply Debian-specific patches. This options is
185 specific for source packages using format "2.0" and "3.0 (quilt)".
187 =item require_valid_signature
189 If set to 1, the check_signature() method will be stricter and will error
190 out if the signature can't be verified.
192 =item require_strong_checksums
194 If set to 1, the check_checksums() method will be stricter and will error
195 out if there is no strong checksum.
197 =item copy_orig_tarballs
199 If set to 1, the extraction will copy the upstream tarballs next the
200 target directory. This is useful if you want to be able to rebuild the
201 source package after its extraction.
203 =back
205 =cut
207 # Class methods
208 sub new {
209 my ($this, %args) = @_;
210 my $class = ref($this) || $this;
211 my $self = {
212 fields => Dpkg::Control->new(type => CTRL_DSC),
213 format => Dpkg::Source::Format->new(),
214 options => {},
215 checksums => Dpkg::Checksums->new(),
216 openpgp => Dpkg::OpenPGP->new(needs => { api => 'verify' }),
218 bless $self, $class;
219 if (exists $args{options}) {
220 $self->{options} = $args{options};
222 if (exists $args{filename}) {
223 $self->initialize($args{filename});
224 $self->init_options();
225 } elsif ($args{format}) {
226 $self->{fields}{Format} = $args{format};
227 $self->upgrade_object_type(0);
228 $self->init_options();
231 if ($self->{options}{require_valid_signature}) {
232 $self->{report_verify} = \&error;
233 } else {
234 $self->{report_verify} = \&warning;
237 return $self;
240 sub init_options {
241 my $self = shift;
242 # Use full ignore list by default
243 # note: this function is not called by V1 packages
244 $self->{options}{diff_ignore_regex} ||= $diff_ignore_default_regex;
245 $self->{options}{diff_ignore_regex} .= '|(?:^|/)debian/source/local-.*$';
246 $self->{options}{diff_ignore_regex} .= '|(?:^|/)debian/files(?:\.new)?$';
247 if (defined $self->{options}{tar_ignore}) {
248 $self->{options}{tar_ignore} = [ @tar_ignore_default_pattern ]
249 unless @{$self->{options}{tar_ignore}};
250 } else {
251 $self->{options}{tar_ignore} = [ @tar_ignore_default_pattern ];
253 push @{$self->{options}{tar_ignore}},
254 'debian/source/local-options',
255 'debian/source/local-patch-header',
256 'debian/files',
257 'debian/files.new';
258 $self->{options}{copy_orig_tarballs} //= 0;
260 # Skip debianization while specific to some formats has an impact
261 # on code common to all formats
262 $self->{options}{skip_debianization} //= 0;
263 $self->{options}{skip_patches} //= 0;
265 # Set default validation checks.
266 $self->{options}{require_valid_signature} //= 0;
267 $self->{options}{require_strong_checksums} //= 0;
269 # Set default compressor for new formats.
270 $self->{options}{compression} //= 'xz';
271 $self->{options}{comp_level} //= compression_get_level($self->{options}{compression});
272 $self->{options}{comp_ext} //= compression_get_file_extension($self->{options}{compression});
275 sub initialize {
276 my ($self, $filename) = @_;
277 my ($fn, $dir) = fileparse($filename);
278 error(g_('%s is not the name of a file'), $filename) unless $fn;
279 $self->{basedir} = $dir || './';
280 $self->{filename} = $fn;
282 # Read the fields
283 my $fields = $self->{fields};
284 $fields->load($filename);
285 $self->{is_signed} = $fields->get_option('is_pgp_signed');
287 foreach my $f (qw(Source Version Files)) {
288 unless (defined($fields->{$f})) {
289 error(g_('missing critical source control field %s'), $f);
293 $self->{checksums}->add_from_control($fields, use_files_for_md5 => 1);
295 $self->upgrade_object_type(0);
298 sub upgrade_object_type {
299 my ($self, $update_format) = @_;
300 $update_format //= 1;
302 my $format = $self->{fields}{'Format'} // '1.0';
303 my ($major, $minor, $variant) = $self->{format}->set($format);
305 my $module = "Dpkg::Source::Package::V$major";
306 $module .= '::' . ucfirst $variant if defined $variant;
307 eval qq{
308 require $module;
309 \$minor = \$${module}::CURRENT_MINOR_VERSION;
311 if ($@) {
312 error(g_("source package format '%s' is not supported: %s"),
313 $format, $@);
315 if ($update_format) {
316 $self->{format}->set_from_parts($major, $minor, $variant);
317 $self->{fields}{'Format'} = $self->{format}->get();
320 $module->prerequisites() if $module->can('prerequisites');
321 bless $self, $module;
324 =item $p->get_filename()
326 Returns the filename of the DSC file.
328 =cut
330 sub get_filename {
331 my $self = shift;
332 return File::Spec->catfile($self->{basedir}, $self->{filename});
335 =item $p->get_files()
337 Returns the list of files referenced by the source package. The filenames
338 usually do not have any path information.
340 =cut
342 sub get_files {
343 my $self = shift;
344 return $self->{checksums}->get_files();
347 =item $p->check_checksums()
349 Verify the checksums embedded in the DSC file. It requires the presence of
350 the other files constituting the source package. If any inconsistency is
351 discovered, it immediately errors out. It will make sure at least one strong
352 checksum is present.
354 If the object has been created with the "require_strong_checksums" option,
355 then any problem will result in a fatal error.
357 =cut
359 sub check_checksums {
360 my $self = shift;
361 my $checksums = $self->{checksums};
362 my $warn_on_weak = 0;
364 # add_from_file verify the checksums if they are already existing
365 foreach my $file ($checksums->get_files()) {
366 if (not $checksums->has_strong_checksums($file)) {
367 if ($self->{options}{require_strong_checksums}) {
368 error(g_('source package uses only weak checksums'));
369 } else {
370 $warn_on_weak = 1;
373 my $pathname = File::Spec->catfile($self->{basedir}, $file);
374 $checksums->add_from_file($pathname, key => $file);
377 warning(g_('source package uses only weak checksums')) if $warn_on_weak;
380 sub get_basename {
381 my ($self, $with_revision) = @_;
382 my $f = $self->{fields};
383 unless (exists $f->{'Source'} and exists $f->{'Version'}) {
384 error(g_('%s and %s fields are required to compute the source basename'),
385 'Source', 'Version');
387 my $v = Dpkg::Version->new($f->{'Version'});
388 my $vs = $v->as_string(omit_epoch => 1, omit_revision => !$with_revision);
389 return $f->{'Source'} . '_' . $vs;
392 sub find_original_tarballs {
393 my ($self, %opts) = @_;
394 $opts{extension} //= compression_get_file_extension_regex();
395 $opts{include_main} //= 1;
396 $opts{include_supplementary} //= 1;
397 my $basename = $self->get_basename();
398 my @tar;
399 foreach my $dir ('.', $self->{basedir}, $self->{options}{origtardir}) {
400 next unless defined($dir) and -d $dir;
401 opendir(my $dir_dh, $dir) or syserr(g_('cannot opendir %s'), $dir);
402 push @tar, map { File::Spec->catfile($dir, $_) } grep {
403 ($opts{include_main} and
404 /^\Q$basename\E\.orig\.tar\.$opts{extension}$/) or
405 ($opts{include_supplementary} and
406 /^\Q$basename\E\.orig-[[:alnum:]-]+\.tar\.$opts{extension}$/)
407 } readdir($dir_dh);
408 closedir($dir_dh);
410 return @tar;
413 =item $p->get_upstream_signing_key($dir)
415 Get the filename for the upstream key.
417 =cut
419 sub get_upstream_signing_key {
420 my ($self, $dir) = @_;
422 return "$dir/debian/upstream/signing-key.asc";
425 =item $p->armor_original_tarball_signature($bin, $asc)
427 Convert a signature from binary to ASCII armored form. If the signature file
428 does not exist, it is a no-op. If the signature file is already ASCII armored
429 then simply copy it, otherwise convert it from binary to ASCII armored form.
431 =cut
433 sub armor_original_tarball_signature {
434 my ($self, $bin, $asc) = @_;
436 if (-e $bin) {
437 return $self->{openpgp}->armor('SIGNATURE', $bin, $asc);
440 return;
443 =item $p->check_original_tarball_signature($dir, @asc)
445 Verify the original upstream tarball signatures @asc using the upstream
446 public keys. It requires the origin upstream tarballs, their signatures
447 and the upstream signing key, as found in an unpacked source tree $dir.
448 If any inconsistency is discovered, it immediately errors out.
450 =cut
452 sub check_original_tarball_signature {
453 my ($self, $dir, @asc) = @_;
455 my $upstream_key = $self->get_upstream_signing_key($dir);
456 if (not -e $upstream_key) {
457 warning(g_('upstream tarball signatures but no upstream signing key'));
458 return;
461 foreach my $asc (@asc) {
462 my $datafile = $asc =~ s/\.asc$//r;
464 info(g_('verifying %s'), $asc);
465 my $rc = $self->{openpgp}->verify($datafile, $asc, $upstream_key);
466 if ($rc) {
467 $self->{report_verify}->(g_('cannot verify upstream tarball signature for %s: %s'),
468 $datafile, openpgp_errorcode_to_string($rc));
473 =item $bool = $p->is_signed()
475 Returns 1 if the DSC files contains an embedded OpenPGP signature.
476 Otherwise returns 0.
478 =cut
480 sub is_signed {
481 my $self = shift;
482 return $self->{is_signed};
485 =item $p->check_signature()
487 Implement the same OpenPGP signature check that dpkg-source does.
488 In case of problems, it prints a warning or errors out.
490 If the object has been created with the "require_valid_signature" option,
491 then any problem will result in a fatal error.
493 =cut
495 sub check_signature {
496 my $self = shift;
497 my $dsc = $self->get_filename();
498 my @certs;
500 push @certs, $self->{openpgp}->get_trusted_keyrings();
502 foreach my $vendor_keyring (run_vendor_hook('package-keyrings')) {
503 if (-r $vendor_keyring) {
504 push @certs, $vendor_keyring;
508 my $rc = $self->{openpgp}->inline_verify($dsc, undef, @certs);
509 if ($rc) {
510 $self->{report_verify}->(g_('cannot verify inline signature for %s: %s'),
511 $dsc, openpgp_errorcode_to_string($rc));
515 sub describe_cmdline_options {
516 return;
519 sub parse_cmdline_options {
520 my ($self, @opts) = @_;
521 foreach my $option (@opts) {
522 if (not $self->parse_cmdline_option($option)) {
523 warning(g_('%s is not a valid option for %s'), $option, ref $self);
528 sub parse_cmdline_option {
529 return 0;
532 =item $p->extract($targetdir)
534 Extracts the source package in the target directory $targetdir. Beware
535 that if $targetdir already exists, it will be erased (as long as the
536 no_overwrite_dir option is set).
538 =cut
540 sub extract {
541 my ($self, $newdirectory) = @_;
543 my ($ok, $error) = version_check($self->{fields}{'Version'});
544 if (not $ok) {
545 if ($self->{options}{ignore_bad_version}) {
546 warning($error);
547 } else {
548 error($error);
552 # Copy orig tarballs
553 if ($self->{options}{copy_orig_tarballs}) {
554 my $basename = $self->get_basename();
555 my ($dirname, $destdir) = fileparse($newdirectory);
556 $destdir ||= './';
557 my $ext = compression_get_file_extension_regex();
558 foreach my $orig (grep { /^\Q$basename\E\.orig(-[[:alnum:]-]+)?\.tar\.$ext$/ }
559 $self->get_files())
561 my $src = File::Spec->catfile($self->{basedir}, $orig);
562 my $dst = File::Spec->catfile($destdir, $orig);
563 if (not check_files_are_the_same($src, $dst, 1)) {
564 cp($src, $dst)
565 or syserr(g_('cannot copy %s to %s'), $src, $dst);
570 # Try extract
571 $self->do_extract($newdirectory);
573 # Check for directory traversals.
574 if (not $self->{options}{skip_debianization} and not $self->{no_check}) {
575 # We need to add a trailing slash to handle the debian directory
576 # possibly being a symlink.
577 check_directory_traversal($newdirectory, "$newdirectory/debian/");
580 # Store format if non-standard so that next build keeps the same format
581 if ($self->{fields}{'Format'} and
582 $self->{fields}{'Format'} ne '1.0' and
583 not $self->{options}{skip_debianization})
585 my $srcdir = File::Spec->catdir($newdirectory, 'debian', 'source');
586 my $format_file = File::Spec->catfile($srcdir, 'format');
587 unless (-e $format_file) {
588 mkdir($srcdir) unless -e $srcdir;
589 $self->{format}->save($format_file);
593 # Make sure debian/rules is executable
594 my $rules = File::Spec->catfile($newdirectory, 'debian', 'rules');
595 my @s = lstat($rules);
596 if (not scalar(@s)) {
597 unless ($! == ENOENT) {
598 syserr(g_('cannot stat %s'), $rules);
600 warning(g_('%s does not exist'), $rules)
601 unless $self->{options}{skip_debianization};
602 } elsif (-f _) {
603 chmod($s[2] | 0111, $rules)
604 or syserr(g_('cannot make %s executable'), $rules);
605 } else {
606 warning(g_('%s is not a plain file'), $rules);
610 sub do_extract {
611 croak 'Dpkg::Source::Package does not know how to unpack a ' .
612 'source package; use one of the subclasses';
615 # Function used specifically during creation of a source package
617 sub before_build {
618 my ($self, $dir) = @_;
621 sub build {
622 my ($self, @args) = @_;
624 $self->do_build(@args);
627 sub after_build {
628 my ($self, $dir) = @_;
631 sub do_build {
632 croak 'Dpkg::Source::Package does not know how to build a ' .
633 'source package; use one of the subclasses';
636 sub can_build {
637 my ($self, $dir) = @_;
638 return (0, 'can_build() has not been overridden');
641 sub add_file {
642 my ($self, $filename) = @_;
643 my ($fn, $dir) = fileparse($filename);
644 if ($self->{checksums}->has_file($fn)) {
645 croak "tried to add file '$fn' twice";
647 $self->{checksums}->add_from_file($filename, key => $fn);
648 $self->{checksums}->export_to_control($self->{fields},
649 use_files_for_md5 => 1);
652 sub commit {
653 my ($self, @args) = @_;
655 $self->do_commit(@args);
658 sub do_commit {
659 my ($self, $dir) = @_;
660 info(g_("'%s' is not supported by the source format '%s'"),
661 'dpkg-source --commit', $self->{fields}{'Format'});
664 sub write_dsc {
665 my ($self, %opts) = @_;
666 my $fields = $self->{fields};
668 foreach my $f (keys %{$opts{override}}) {
669 $fields->{$f} = $opts{override}{$f};
672 unless ($opts{nocheck}) {
673 foreach my $f (qw(Source Version Architecture)) {
674 unless (defined($fields->{$f})) {
675 error(g_('missing information for critical output field %s'), $f);
678 foreach my $f (qw(Maintainer Standards-Version)) {
679 unless (defined($fields->{$f})) {
680 warning(g_('missing information for output field %s'), $f);
685 foreach my $f (keys %{$opts{remove}}) {
686 delete $fields->{$f};
689 my $filename = $opts{filename};
690 $filename //= $self->get_basename(1) . '.dsc';
691 open(my $dsc_fh, '>', $filename)
692 or syserr(g_('cannot write %s'), $filename);
693 $fields->apply_substvars($opts{substvars});
694 $fields->output($dsc_fh);
695 close($dsc_fh);
698 =back
700 =head1 CHANGES
702 =head2 Version 2.02 (dpkg 1.21.10)
704 New method: $p->armor_original_tarball_signature().
706 =head2 Version 2.01 (dpkg 1.20.1)
708 New method: $p->get_upstream_signing_key().
710 =head2 Version 2.00 (dpkg 1.20.0)
712 New method: $p->check_original_tarball_signature().
714 Remove variable: $diff_ignore_default_regexp.
716 Hide variable: @tar_ignore_default_pattern.
718 =head2 Version 1.03 (dpkg 1.19.3)
720 New option: format in new().
722 =head2 Version 1.02 (dpkg 1.18.7)
724 New option: require_strong_checksums in $p->check_checksums().
726 =head2 Version 1.01 (dpkg 1.17.2)
728 New functions: $p->get_default_diff_ignore_regex(),
729 $p->set_default_diff_ignore_regex(), $p->get_default_tar_ignore_pattern().
731 Deprecated variables: $diff_ignore_default_regexp, @tar_ignore_default_pattern
733 =head2 Version 1.00 (dpkg 1.16.1)
735 Mark the module as public.
737 =cut