/[pkg-kde]/scripts/dh_installgen
ViewVC logotype

Contents of /scripts/dh_installgen

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12925 - (show annotations) (download)
Fri Dec 12 22:44:10 2008 UTC (4 years, 5 months ago) by modax-guest
File size: 30855 byte(s)
debian/not-installed verification support
1 #!/usr/bin/perl -w
2
3 =head1 NAME
4
5 dh_install - install files into package build directories
6
7 =cut
8
9 use strict;
10 use File::Find;
11 use File::Temp ':mktemp';
12 use File::Spec;
13 use Digest::MD5;
14
15 use Debian::Debhelper::Dh_Lib;
16 use Getopt::Long;
17
18 =head1 SYNOPSIS
19
20 B<dh_install> [B<-X>I<item>] [B<--autodest>] [B<--sourcedir=>I<dir>] [B<--destdir=>I<dir>] [S<I<debhelper options>>] [S<I<file [...] dest>>]
21
22 =head1 DESCRIPTION
23
24 dh_install is a debhelper program that handles installing files into package
25 build directories. There are many dh_install* commands that handle installing
26 specific types of files such as documentation, examples, man pages, and so on,
27 and they should be used when possible as they often have extra intelligence for
28 those particular tasks. dh_install, then, is useful for installing everything
29 else, for which no particular intelligence is needed. It is a replacement for
30 the old dh_movefiles command.
31
32 Files named debian/package.install list the files to install into each
33 package and the directory they should be installed to. The format is a set
34 of lines, where each line lists a file or files to install, and at the end
35 of the line tells the directory it should be installed in. The name of the
36 files (or directories) to install should be given relative to the current
37 directory, while the installation directory is given relative to the
38 package build directory. You may use wildcards in the names of the files to
39 install (in v3 mode and above).
40
41 This program may be used in one of two ways. If you just have a file or two
42 that the upstream Makefile does not install for you, you can run dh_install
43 on them to move them into place. On the other hand, maybe you have a large
44 package that builds multiple binary packages. You can use the upstream
45 Makefile to install it all into debian/tmp, and then use dh_install to copy
46 directories and files from there into the proper package build directories.
47
48 =head1 OPTIONS
49
50 =over 4
51
52 =item B<-Xitem>, B<--exclude=item>
53
54 Exclude files that contain "item" anywhere in their filename from
55 being installed.
56
57 =item B<--autodest>
58
59 Guess as the destination directory to install things to. If this is
60 specified, you should not list destination directories in
61 debian/package.install files or on the command line. Instead, dh_install
62 will guess as follows:
63
64 Strip off debian/tmp (or the sourcedir if one is given) from the front of
65 the filename, if it is present, and install into the dirname of the
66 filename. So if the filename is debian/tmp/usr/bin, then that directory
67 will be copied to debian/package/usr/. If the filename is
68 debian/tmp/etc/passwd, it will be copied to debian/package/etc/.
69
70 Note that if you list exactly one filename or wildcard-pattern on a line by
71 itself in a
72 debian/package.install file, with no explicit destination, then dh_install
73 will automatically guess the destination even if this flag is not set.
74
75 =item B<--fail-missing>
76
77 This option is like --list-missing, except if a file was missed, it will
78 not only list the missing files, but also fail with a nonzero exit code.
79
80 =item B<--sourcedir=dir>
81
82 Makes all source files be found under dir. If this is specified, it is
83 akin to all the source filenames having "dir/" prepended to them.
84
85 To make dh_install behave like the old dh_movefiles, move your
86 package.files file to package.install and call dh_install with
87 "--sourcedir=debian/tmp" appended to the command. This will
88 approximate dh_movefiles behaviour, except it will copy files instead
89 of moving them.
90
91 =item B<--builddir=dir>
92
93 foo bar
94
95 =item I<file [...] dest>
96
97 Lists files (or directories) to install and where to install them to.
98 The files will be installed into the first package dh_install acts on.
99
100 =back
101
102 =cut
103
104 package DH::InstGen::File;
105
106 our %builddir_cache = (
107 builddir => "",
108 cache => undef,
109 );
110
111 sub build_cache($) {
112 my $builddir = shift;
113 if ($builddir_cache{'builddir'} ne $builddir) {
114 my %cache;
115 File::Find::find({ wanted => sub {
116 my $key;
117 if (m/debian$/ && -d) {
118 $File::Find::prune = 1;
119 return;
120 } elsif (-f) {
121 $key = ((stat($_))[7] / (1024*256));
122 } elsif (-l) {
123 $key = 'links';
124 } else {
125 return;
126 }
127 $cache{$key} = [] unless exists $cache{$key};
128 push @{$cache{$key}}, new DH::InstGen::File($_);
129 }, no_chdir => 1 }, $builddir);
130 $builddir_cache{'builddir'} = $builddir;
131 $builddir_cache{'cache'} = \%cache;
132 }
133 return $builddir_cache{'cache'};
134 }
135
136 sub new($$) {
137 my ($cls, $dst) = @_;
138 my $self = {
139 src => undef,
140 dst => $dst,
141 chksum => undef,
142 is_link => (-l $dst),
143 };
144 return bless($self, $cls);
145 }
146
147 sub is_link {
148 return shift()->{is_link};
149 }
150
151 sub get_path($) {
152 my $self = shift;
153
154 sub gp_internal($) {
155 my $path = shift;
156 if ($path && (-l $path)) {
157 my $first_path = $path;
158 while (-l $path) {
159 $_ = readlink($path);
160 if (m#^/#) {
161 $path = $_;
162 } else {
163 $path = main::dirname($path) . "/" . $_
164 }
165 }
166 if (! -f $path && $path =~ m#^/# ) {
167 my $old_path = $path;
168 my @parts = split /\/+/, $first_path;
169 while (! -f $path && @parts) {
170 $path = shift(@parts) . "/" . $path;
171 }
172 $path = $old_path if (! -f $path);
173 }
174 return $path;
175 } elsif ($path && -f $path) {
176 return $path;
177 }
178 return undef;
179 }
180
181 $self->{path} = gp_internal($self->{dst}) if (!exists($self->{path}));
182 return $self->{path};
183 }
184
185 sub _stripped_path($$) {
186 my ($path, $prefix) = @_;
187 if ($path) {
188 $path =~ s/^\Q$prefix\E\/?//;
189 return $path;
190 } else {
191 return undef;
192 }
193 }
194
195 sub stripped_path($$) {
196 my ($self, $prefix) = @_;
197 return _stripped_path($self->get_path(), $prefix);
198 }
199
200 sub stripped_dstpath($$) {
201 my ($self, $prefix) = @_;
202 return _stripped_path($self->{dst}, $prefix);
203 }
204
205 sub calc_checksum {
206 my $self = shift;
207 my $path = shift;
208
209 return if ($self->{is_link});
210
211 $path = $self->get_path() if (! defined $path);
212
213 if ($path) {
214 my $md5 = new Digest::MD5;
215
216 open (FILE, $path) or main::error("Unable to open '$path' for checksuming: $!");
217 binmode(FILE);
218 $md5->addfile(*FILE)->hexdigest;
219 my $sum = $md5->hexdigest;
220 close(FILE);
221
222 return $sum;
223 } else {
224 main::error("Unable to find/open file '$path'");
225 }
226 }
227
228 sub get_cache_key($) {
229 my $self = shift;
230 if ($self->{is_link}) {
231 return 'links';
232 } elsif (my $path = $self->get_path()) {
233 return ((stat($path))[7] / (1024*256));
234 }
235 }
236
237 sub locate_in_cache {
238 my ($self, $cache) = @_;
239 my $key = $self->get_cache_key();
240
241 if (exists $cache->{$key}) {
242 my $srcs = $cache->{$key};
243 foreach my $src (@$srcs) {
244 if ($self->is_the_same($src)) {
245 return $src;
246 }
247 }
248 }
249 return undef;
250 }
251
252 sub locate($$) {
253 my ($self, $builddir) = @_;
254
255 my $cache = build_cache($builddir);
256
257 if ($self->{is_link}) {
258 # Search among links first
259 if (!($self->{src} = $self->locate_in_cache($cache))) {
260 my $path = $self->get_path();
261 if (-f $path) {
262 my $new_file = new DH::InstGen::File($path);
263 $self->{src} = $new_file->locate_in_cache($cache);
264 }
265 }
266
267 main::warning("Unable to locate a source file for the link: " . $self->{dst})
268 unless($self->{src});
269 } else {
270 main::warning("Unable to locate a source file for the file: " . $self->get_path())
271 unless($self->{src} = $self->locate_in_cache($cache));
272 }
273
274 $self->{src} = $self->{src}->get_path() if (defined $self->{src});
275 return $self->{src};
276 }
277
278 sub is_the_same($$) {
279 my ($self, $other) = @_;
280
281 if ($self->{is_link} && $other->{is_link}) {
282 # print $self->{dst}, " => ", $other->{dst}, "\n";
283 # Match by basename of the link and readlink
284 return (main::basename($self->{dst}) eq main::basename($other->{dst}) &&
285 $self->get_path() eq $other->get_path());
286 } elsif (!($self->{is_link} && ($other->{is_link}))) {
287 # I.e. file
288 $self->{chksum} = $self->calc_checksum() unless ($self->{chksum});
289 $other->{chksum} = $other->calc_checksum() unless ($other->{chksum});
290
291 return ($self->{chksum} && $other->{chksum} &&
292 $self->{chksum} eq $other->{chksum});
293 } else {
294 return 0;
295 }
296 }
297
298 ###############################################################################
299 package DH::InstGen::Installed;
300
301 sub new {
302 my $cls = shift;
303 return bless({d=>{}}, $cls);
304 }
305
306 sub add {
307 my ($self, $pattern) = @_;
308
309 # Kill any extra slashes. Makes the
310 # stuff more robust.
311 $pattern =~ y:/:/:s;
312 $pattern =~ s:/+$::;
313 $pattern =~ s:^(\./)*::;
314
315 my $bn = main::basename($pattern);
316 $self->{d}->{$bn} = [] unless (exists $self->{d}->{$bn});
317 push @{$self->{d}->{$bn}}, qr{^(?:\Q$pattern\E\/.*|\Q$pattern\E)$};
318 }
319
320 sub check {
321 my ($self, $file) = @_;
322 my @parts = split /\//, $file;
323
324 my $found = $self->_check_basename(\@parts, $file);
325 while (! $found && @parts > 0 ) {
326 pop @parts;
327 $found = $self->_check_basename(\@parts, $file);
328 }
329 return $found;
330 }
331
332 sub _check_basename {
333 my ($self, $parts, $file) = @_;
334 my $bn = $parts->[scalar(@$parts) - 1];
335 if (defined $bn && exists $self->{d}->{$bn}) {
336 my $found = 0;
337 my $file = join("/", @$parts);
338 for my $f (@{$self->{d}->{$bn}}) {
339 return 1 if ($file =~ m/$f/);
340 }
341 }
342 return 0;
343 }
344
345
346 ###############################################################################
347 package DH::InstGen::Pattern::Common;
348
349 sub new {
350 my ($cls, $negated, $val) = @_;
351 return bless( { negated => $negated, value => $val }, $cls);
352 }
353
354 sub type {
355 undef;
356 }
357
358 sub _match {
359 undef;
360 }
361
362 sub match {
363 my ($self, $file) = @_;
364 my $result = $self->_match($file);
365 return ($self->{negated}) ? !$result : $result;
366 }
367
368 sub has_value {
369 return defined shift()->{value};
370 }
371
372 package DH::InstGen::Pattern::Src;
373 our @ISA = qw( DH::InstGen::Pattern::Common );
374
375 sub new {
376 my $self = DH::InstGen::Pattern::Common::new(@_);
377 if ($self->{value} && !($self->{value} =~ m/^\s*$/)) {
378 $self->{regex} = qr{$self->{value}};
379 } else {
380 $self->{value} = undef;
381 $self->{regex} = qr/.*/;
382 }
383 return $self;
384 }
385
386 sub type {
387 "src";
388 }
389
390 sub _match_filename {
391 my ($self, $filename) = @_;
392 if (defined $filename) {
393 return $filename =~ m/$self->{regex}/;
394 } else {
395 return 0;
396 }
397 }
398
399 sub _match {
400 my ($self, $file) = @_;
401 return $self->_match_filename($file->{src});
402 }
403
404 package DH::InstGen::Pattern::Dst;
405 our @ISA = qw( DH::InstGen::Pattern::Src );
406
407 sub type {
408 "dst";
409 }
410
411 sub _match {
412 my ($self, $file) = @_;
413 return $self->_match_filename($file->{dst});
414 }
415
416 package DH::InstGen::Pattern::External;
417 our @ISA = qw( DH::InstGen::Pattern::Src );
418
419 sub new {
420 my ($cls, $negated, $value, $type, $desc) = @_;
421 my $self = DH::InstGen::Pattern::Src::new(@_);
422 $self->{type} = $type;
423 $self->{desc} = $desc;
424 return $self;
425 }
426
427 sub type {
428 return shift()->{type};
429 }
430
431 sub _match {
432 my ($self, $file) = @_;
433
434 if (my $d = $self->{desc}{$file->{dst}}) {
435 return $self->_match_filename($d);
436 } else {
437 return 0;
438 }
439 }
440
441 package DH::InstGen::Pattern::Link;
442 our @ISA = qw( DH::InstGen::Pattern::Src );
443
444 sub type {
445 "link";
446 }
447
448 sub _match {
449 my ($self, $file) = @_;
450 return $file->{is_link} && (!$self->has_value() ||
451 $self->_match_filename($file->get_path()));
452 }
453
454 package DH::InstGen::Pattern::Magic;
455 our @ISA = qw( DH::InstGen::Pattern::Common );
456
457 sub new {
458 my $self = DH::InstGen::Pattern::Common::new(@_);
459 $self->{regex} = qr{^$self->{value}$};
460 return $self;
461 }
462
463 sub type {
464 return "mime";
465 }
466
467 sub get_mimetype {
468 my $filename = shift;
469 unless (open(CMD_FILE, "file --brief --mime-type '$filename'|")) {
470 main::warning ("Could not run `file'");
471 return undef;
472 }
473 $_ = <CMD_FILE>;
474 chomp;
475 close CMD_FILE;
476 return $_;
477 }
478
479 sub _match {
480 my ($self, $file) = @_;
481 if (! exists $file->{__mime__}) {
482 if (my $path = $file->get_path()) {
483 $file->{__mime__} = get_mimetype($path);
484 } else {
485 $file->{__mime__} = undef;
486 }
487 }
488 my $mime = $file->{__mime__};
489 if (defined $mime) {
490 return $mime =~ m/$self->{regex}/;
491 } else {
492 return 0;
493 }
494 return 0;
495 }
496
497 ###############################################################################
498 package DH::InstGen::Pattern;
499
500 my %externals;
501 my $externals_re;
502
503 sub new {
504 my ($cls, $pattern) = @_;
505 my $p = $pattern->[0];
506 my $action;
507
508 if ($p =~ m/^(inst|miss|stop|skip)(?:all|ing)?$/) {
509 $action = $1;
510 shift @$pattern;
511 } elsif ($p =~ m/^depends$/) {
512 # Ignore. Not interesting here
513 return bless({ action => "ignr", pats => [] }, $cls);
514 } else {
515 $action = "inst"; # default
516 }
517 my $self = bless( { action => $action, pats => [] }, $cls);
518
519 while (@$pattern > 0) {
520 my $negated = 0;
521 my $type;
522 my $value;
523
524 $p = shift @$pattern;
525 if ($p =~ m/^!$/) {
526 $negated = 1;
527 $p = shift @$pattern;
528 }
529 if ($p =~ m/^dst:(.*)$/) {
530 $self->add_pattern(new DH::InstGen::Pattern::Dst($negated,$1));
531 } elsif ($p =~ m/^src:(.*)$/) {
532 $self->add_pattern(new DH::InstGen::Pattern::Src($negated, $1));
533 } elsif ($p =~ m/^link:(.*)$/) {
534 $self->add_pattern(new DH::InstGen::Pattern::Link($negated, $1));
535 } elsif ($p =~ m/^mime:(.*)$/) {
536 $self->add_pattern(new DH::InstGen::Pattern::Magic($negated, $1));
537 } elsif ((defined $externals_re && $p =~ m/^($externals_re):(.*)$/) ||
538 ($p =~ m/^([^:]+):(.+)$/ && -f "$1.ig-external")) {
539 my ($type, $value) = ($1, $2);
540 if (! exists $externals{$type}) {
541 DH::InstGen::Pattern->load_external($type);
542 }
543 $self->add_pattern(new DH::InstGen::Pattern::External($negated, $2, $1, $externals{$1}));
544 } else {
545 # Default is src
546 $self->add_pattern(new DH::InstGen::Pattern::Src($negated, $p));
547 }
548 }
549 return $self;
550 }
551
552 sub add_pattern {
553 my ($self, $p) = @_;
554 my $type = $p->type();
555 if ($type) {
556 if (exists $self->{$type}) {
557 $self->{$type}++;
558 } else {
559 $self->{$type} = 1;
560 }
561 push @{$self->{pats}}, $p;
562 }
563 }
564
565 sub has_type {
566 my ($self, $type) = @_;
567 return exists $self->{$type};
568 }
569
570 sub match {
571 my ($self, $file) = @_;
572 my $lastpat = undef;
573 for my $pat (@{$self->{pats}}) {
574 return undef unless ($pat->match($file));
575 $lastpat = $pat;
576 }
577 return (defined $lastpat) ? $self->action() : undef;
578 }
579
580 sub action {
581 return shift()->{action};
582 }
583
584 sub load_external {
585 my ($cls, $desc) = @_;
586 my @desc = split(/:/, $desc);
587 my ($type, $file);
588 if (scalar(@desc) == 1) {
589 $type = shift @desc;
590 $file = "$type.ig-external";
591 } else {
592 ($type, $file) = @desc;
593 $file = File::Spec->catfile($file, "$type.ig-external") if (-d $file);
594 }
595
596 my %desc;
597 my $last_key;
598 open(FILE, $file) or main::error("Unable to open external '$type' file '$file' for reading");
599 while (<FILE>) {
600 chomp;
601 if (defined $last_key && m/^\s+(.*)$/) {
602 $desc{$1} = $last_key;
603 } elsif (m/^(.*):$/) {
604 $last_key = $1;
605 } else {
606 main::error("Invalid syntax of the external '$type' file '$file' at line $.");
607 }
608 }
609 close(FILE);
610 if (scalar(keys %externals)) {
611 $externals_re .= "|" . $type;
612 } else {
613 $externals_re = $type;
614 }
615 $externals{$type} = \%desc;
616 return 1;
617 }
618
619 ###############################################################################
620 package DH::InstGen::Installgen;
621
622 sub new {
623 my ($cls, $srcdir, $builddir) = @_;
624 return bless( { srcdir => $srcdir,
625 builddir => $builddir,
626 rules => [],
627 processed => {},
628 autoadd => {} }, $cls);
629 }
630
631 sub rules {
632 return @{shift()->{rules}};
633 }
634
635 sub is_package_virtual {
636 my ($self, $package) = @_;
637 return $package =~ /_virtual$/;
638 }
639
640 sub autoadd {
641 my ($self, $package) = @_;
642 return (exists $self->{autoadd}{$package}) ? $self->{autoadd}{$package} : [];
643 }
644
645 sub add_package {
646 my ($self, $package, $patterns) = @_;
647 push @{$self->{rules}}, { package => $package, patterns => $patterns };
648 }
649
650 sub parse_installgen($$) {
651 my ($self, $file) = @_;
652 my $patterns = [];
653 my $package;
654 my $is_virtual;
655 $file = "debian/installgen" unless ($file);
656
657 return undef if (! -r $file);
658
659 open(INSTALLGEN, $file) or main::error("Unable to open installgen rule file $file");
660 while (<INSTALLGEN>) {
661 if (/^\s*#/ || /^\s*$/) {
662 next; # Comment
663 } elsif (/^\s*\[\s*(.*)\s*\]\s*$/) {
664 if (defined $package && @$patterns && $package ne $1) {
665 $self->add_package($package, $patterns);
666 $patterns = [];
667 }
668 $package = $1; # new package name
669 $is_virtual = $self->is_package_virtual($package);
670 } else {
671 if (defined $package) {
672 my @patternset = split(/\s+/);
673 my $pattern = new DH::InstGen::Pattern(\@patternset);
674 if ($is_virtual && $pattern->action() eq "inst") {
675 main::error("install action is forbidden in virtual package ($package) at ${file}:$.");
676 } else {
677 push @$patterns, $pattern;
678 }
679 } else {
680 main::error("Expected package name at ${file}:$.");
681 }
682 }
683 }
684 if (defined $package && @$patterns) {
685 $self->add_package($package, $patterns);
686 }
687 close(INSTALLGEN);
688 }
689
690 sub verify_against_packagelist {
691 my $self = shift;
692
693 # Check if all packages specified in the rule file exist
694 my %packages;
695 map { $packages{$_} = 1 } @_;
696 for my $rule (@{$self->{rules}}) {
697 main::error("Package '". $rule->{package} . "' is not defined and is not virtual")
698 if (!exists $packages{$rule->{package}} &&
699 !$self->is_package_virtual($rule->{package}));
700 }
701 }
702
703 sub process_rule {
704 my ($self, $rule, $missing) = @_;
705 my ($package, $patterns) = ($rule->{package}, $rule->{patterns});
706 my @autoadd;
707
708 # Load additional package patterns from $package.installgen
709 my $gfile = "debian/$package.installgen";
710 if (! exists $self->{processed}{$package} && -r $gfile) {
711 my @patternset = Debian::Debhelper::Dh_Lib::filedoublearray($gfile);
712 for my $pattern (@patternset) {
713 push @{$patterns}, new DH::InstGen::Pattern($pattern);
714 }
715 }
716 $self->{processed}{$package} = 1;
717
718 if (@$missing && @$patterns) {
719 for my $pattern (@$patterns) {
720 # Search for the missing files in the source/build tree
721 foreach my $miss (@$missing) {
722 next if $miss->{st_found};
723 next if $miss->{st_stop};
724 next if (exists $miss->{st_skip} && $miss->{st_skip} eq $package);
725
726 if ($pattern->has_type("src") && ! defined($miss->{src})) {
727 $miss->locate($self->{builddir});
728 }
729 my $match = $pattern->match($miss);
730 if (defined $match) {
731 if ($match eq "skip") {
732 $miss->{st_skip} = $package;
733 next;
734 } elsif ($match eq "stop") {
735 $miss->{st_stop} = 1;
736 } else {
737 if ($match eq "inst") {
738 push @autoadd, $miss->stripped_dstpath($self->{srcdir});
739 } else {
740 # Otherwise the file was defined as missing on purpose
741 $miss->{st_miss} = 1;
742 }
743 $miss->{st_found} = 1;
744 }
745 }
746 }
747 }
748 }
749 push @{$self->{autoadd}{$package}}, @autoadd;
750 }
751
752 sub process {
753 my $self = shift;
754 my $missing = shift;
755 my %dopackages;
756
757 map { $dopackages{$_} = 1 } @_;
758
759 foreach my $rule (@{$self->{rules}}) {
760 if ( exists $dopackages{$rule->{package}} ||
761 $self->is_package_virtual($rule->{package}) ) {
762 $self->process_rule($rule, $missing);
763 }
764 }
765 }
766
767 ###########################################################################
768 package main;
769
770 my %autoremove;
771 my %instgen_opts;
772
773 # Parse installgen specific command line options first
774 my $prevconfig = Getopt::Long::Configure("pass_through", "no_auto_abbrev");
775 $instgen_opts{SORT} = 1;
776 $instgen_opts{MANPAGES} = 1;
777 $instgen_opts{EXTERNALS} = [];
778 exit 1 unless (GetOptions(
779 "builddir|b=s" => \$instgen_opts{BUILDDIR},
780 "validate|test|t" => \$instgen_opts{VALIDATE},
781 "sort!" => \$instgen_opts{SORT},
782 "manpages!" => \$instgen_opts{MANPAGES},
783 "external|e=s" => $instgen_opts{EXTERNALS},
784 ));
785
786 # Get global debhelper options
787 Getopt::Long::Configure($prevconfig);
788 init();
789
790 my $installed = new DH::InstGen::Installed;
791
792 my $srcdir = '.';
793 $srcdir = $dh{SOURCEDIR}."/" if defined $dh{SOURCEDIR};
794
795 my $builddir = '.';
796 $builddir = $dh{BUILDDIR} . "/" if defined $dh{BUILDDIR};
797
798 sub rewrite_install_file($\@\@) {
799 my ($file, $remove, $add) = @_;
800 my $tmpfile = "$file.tmp";
801 my $delfile = 0;
802
803 if (@$remove || @$add) {
804 my $p = shift @$remove;
805 my @lines;
806 my $again = 0;
807 my $prevline = "";
808
809 # Read. Remove non-matching patterns
810 if (-r $file) {
811 open (DH_INSTALL, "<$file") or main::error("cannot read $file: $!");
812 if ($instgen_opts{VALIDATE}) {
813 while (<DH_INSTALL>) {
814 my @set = split;
815 if (! defined $dh{AUTODEST} && @set > 1) {
816 push @lines, $_;
817 }
818 }
819 } else {
820 while ($again || ($_ = <DH_INSTALL>)) {
821 if (defined $p && !m/^#/ && m/(?:^|\s+)\Q$p\E(?:\s+|$)/) {
822 my @set = split;
823 if (! defined $dh{AUTODEST} && @set > 1) {
824 s/((?:^|\s+)\Q$p\E\s*)(?!$)/ /;
825 } else {
826 s/((?:^|\s+)\Q$p\E\s*)/ /;
827 }
828 if (@set == 1 || @set == 2) {
829 # Move on
830 $p = shift @$remove;
831 } else {
832 # Check for another match
833 $_ = chomp() . "\n";
834 $again = 1;
835 next;
836 }
837 } else {
838 push @lines, $_;
839 }
840 $again = 0;
841 $prevline = $_;
842 }
843 }
844 close(DH_INSTALL);
845 }
846
847 # Sort *.install if needed
848 if ($instgen_opts{VALIDATE} && $instgen_opts{SORT}) {
849 my $needs_sort = 0;
850 my @install_data;
851 my $prevline = "";
852
853 if (open(DH_INSTALL, "<$file")) {
854 while (<DH_INSTALL>) {
855 $needs_sort = 1 if (!$needs_sort && $prevline gt $_);
856 push @install_data, $_;
857 $prevline = $_;
858 }
859 close(DH_INSTALL);
860 }
861
862 if ($needs_sort) {
863 @install_data = sort(@install_data);
864
865 my ($fh, $sorted_file) = mkstemp("/tmp/" . basename($file) . ".XXXXXX");
866 for (@install_data) {
867 print $fh $_;
868 }
869 close($fh);
870
871 $file = $sorted_file;
872 $delfile = 1;
873 }
874 }
875
876 push @lines, map { "$_\n" } @$add if (@$add);
877 @lines = sort(@lines) if ($instgen_opts{SORT});
878
879 open (DH_INSTALL, ">$tmpfile") or main::error("cannot write to $tmpfile: $!");
880 for (@lines) {
881 print DH_INSTALL $_;
882 }
883 close(DH_INSTALL);
884 if ($dh{NO_ACT} || $instgen_opts{VALIDATE}) {
885 system("diff", "-uN", "$file", "$tmpfile");
886 system("rm", "-rf", "$file") if ($delfile);
887 } else {
888 doit("mv", "$tmpfile", "$file");
889 }
890 }
891 }
892
893 sub check_for_autoremove {
894 my ($package, $type, $fileset, $sdir) = @_;
895 $sdir = "." if (! defined $sdir);
896
897 foreach (@$fileset) {
898 my $pat = "$sdir/$_";
899 my @files = glob $pat;
900 if (@files == 1 && $files[0] eq $pat) {
901 # The pattern might have not been expanded.
902 # Check manually
903 if (! -e $pat && ! -l $pat) {
904 push @{$autoremove{$package}{$type}}, $_;
905 }
906 } elsif ( ! @files ) {
907 push @{$autoremove{$package}{$type}}, $_;
908 }
909 }
910
911 foreach my $src (map { glob "$sdir/$_" } @$fileset) {
912 next if excludefile($src);
913
914 $installed->add($src);
915 }
916 }
917
918 sub get_not_installed {
919 my $file = shift;
920 $file = "debian/not-installed" unless ($file);
921 if (-r $file) {
922 my %notinstalled;
923 open(NOTINSTALLED, $file) or main::error("Unable to $file for reading");
924 while (<NOTINSTALLED>) {
925 if (m/^\.\/(.*)$/) {
926 $notinstalled{$1} = 0;
927 }
928 }
929 close(NOTINSTALLED);
930 return \%notinstalled;
931 } else {
932 return undef;
933 }
934 }
935
936 # Initialize some data
937 foreach my $package (@{$dh{DOPACKAGES}}) {
938 $autoremove{$package} = {};
939 $autoremove{$package}{install} = [];
940 $autoremove{$package}{manpages} = [];
941 }
942
943 # Initialize externals
944 for my $external (@{$instgen_opts{EXTERNALS}}) {
945 DH::InstGen::Pattern->load_external($external);
946 }
947
948 # Read and process *.install unless dh_installgen was started in the
949 # validate mode. In that case, assume none of the files are installed.
950 if (!$instgen_opts{VALIDATE}) {
951 foreach my $package (@{$dh{DOPACKAGES}}) {
952 $autoremove{$package} = {};
953
954 # Handle *.install files
955 my $tmp=tmpdir($package);
956 my $file=pkgfile($package,"install");
957
958 my @install;
959 if ($file) {
960 @install=filedoublearray($file); # no globbing yet
961 }
962
963 if (($package eq $dh{FIRSTPACKAGE} || $dh{PARAMS_ALL}) && @ARGV) {
964 push @install, [@ARGV];
965 }
966
967 foreach my $set (@install) {
968 my $dest;
969 my $tmpdest=0;
970
971 if (! defined $dh{AUTODEST} && @$set > 1) {
972 $dest=pop @$set;
973 }
974
975 check_for_autoremove($package, "install", $set, $srcdir);
976 }
977
978 if ($instgen_opts{MANPAGES}) {
979 # Handle .manpages files
980 $file = pkgfile($package, "manpages");
981 if ($file) {
982 @install=filearray($file);
983 }
984 check_for_autoremove($package, "manpages", \@install);
985 }
986 }
987 }
988
989 # . as srcdir makes no sense, so this is a special case.
990 if ($srcdir eq '.') {
991 $srcdir='debian/tmp';
992 }
993
994 main::error("Unable to find sourcedir: '$srcdir'") unless (-d $srcdir);
995
996 my @missing = ();
997 my $found_file;
998
999 find( { wanted => sub {
1000 $found_file = 1;
1001 -f || -l || return;
1002 if (! excludefile($_) && ! $installed->check($_) ) {
1003 push @missing, new DH::InstGen::File($_);
1004 }
1005 }, no_chdir => 1 }, $srcdir);
1006
1007 main::error("Sorry, but '$srcdir' appears to be empty") unless ($found_file);
1008
1009 # Process packages with installgen
1010 my $installgen = new DH::InstGen::Installgen($srcdir, $builddir);
1011 $installgen->parse_installgen("debian/installgen");
1012
1013 if ($installgen->rules()) {
1014 $installgen->verify_against_packagelist(getpackages());
1015 $installgen->process(\@missing, @{$dh{DOPACKAGES}});
1016 }
1017
1018 if ($dh{LIST_MISSING} || $dh{FAIL_MISSING}) {
1019 my $unmatched = 0;
1020 foreach (@missing) {
1021 unless ($_->{st_found}) {
1022 $unmatched++;
1023 warning "Not installed files are listed below:" if ($unmatched == 1 && $dh{LIST_MISSING});
1024 print STDERR $_->stripped_dstpath($srcdir), "\n" if ($dh{LIST_MISSING});
1025 # warning $_->stripped_dstpath($srcdir) .
1026 # " exists in $srcdir but is not installed to anywhere" if ($dh{LIST_MISSING});
1027 }
1028 }
1029 if ($dh{FAIL_MISSING} && $unmatched) {
1030 main::error("missing files ($unmatched), aborting");
1031 }
1032 }
1033
1034 # Verify against missing on purpose files against debian/not-installed
1035 if (my $notinstalled = get_not_installed("debian/not-installed")) {
1036 my @missing_in_notinstalled;
1037 my @excess_in_notinstalled;
1038 foreach (@missing) {
1039 next unless (exists $_->{st_miss});
1040 my $filepath = $_->stripped_dstpath($srcdir);
1041 if (!exists $notinstalled->{$filepath}) {
1042 push @missing_in_notinstalled, $filepath;
1043 } else {
1044 $notinstalled->{$filepath} = 1;
1045 }
1046 }
1047 foreach (keys %$notinstalled) {
1048 push @excess_in_notinstalled, $_ if ($notinstalled->{$_} == 0);
1049 }
1050
1051 if (@missing_in_notinstalled || @excess_in_notinstalled) {
1052 warning "debian/not-installed is out of sync:";
1053 map { print STDERR "-", $_, "\n" } sort @excess_in_notinstalled;
1054 map { print STDERR "+", $_, "\n" } sort @missing_in_notinstalled;
1055
1056 if (@missing_in_notinstalled && !($instgen_opts{VALIDATE} or $dh{NO_ACT})) {
1057 main::error("Aborting, please update debian/not-installed");
1058 }
1059 }
1060 }
1061
1062 foreach my $package (@{$dh{DOPACKAGES}}) {
1063 # Handle *.install files
1064 my $file=pkgfile($package, "install");
1065 $file = "debian/$package.install" if (! -r $file);
1066
1067 rewrite_install_file($file, @{$autoremove{$package}{install}},
1068 @{$installgen->autoadd($package)});
1069
1070 # Handle *.manpages file (TODO; improve)
1071 $file=pkgfile($package, "manpages");
1072 if ($file && exists $autoremove{$package}) {
1073 my @dummy;
1074 rewrite_install_file($file, @{$autoremove{$package}{manpages}}, @dummy);
1075 }
1076 }
1077

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.5