#!/usr/bin/perl

=head1 NAME

dh_cruft - install cruft files into package build directories

=cut

use strict;
use warnings;
use Debian::Debhelper::Dh_Lib;

our $VERSION = DH_CRUFT_VERSION;

=head1 SYNOPSIS

B<dh_cruft> [S<I<debhelper options>>]

=head1 DESCRIPTION

B<dh_cruft> is a debhelper program that is responsible for installing
information files used by cruft(-ng) into package build directories.

=head1 FILES

=over 4

=item debian/I<package>.cruft

Installed into usr/share/cruft/rules/I<package> in the package
build directory. This file is used to register runtime files
as belonging to this package. For clarity, directories
should end with a B<'/'>.

=item debian/I<package>.purge

Appended to usr/share/cruft/rules/I<package> in the package
build directory. This file is used to register runtime files
as belonging to this package. For claririty, directories
should end with a B<'/'>.

Also, a snippet is appended to F<postrm>
with the needed I<rm -rf> commands
to remove these files on I<purge> phase.

Some basic templating is implemented: the B<#VERSION#> tag
will be replaced by the basic upstream version.

=item debian/I<package>.explain

This should be a POSIX shell script that dynamically
generate a list of files owned by this package.

This script is installed as usr/libexec/cruft/pkg/I<package>
in the package build directory.

These script should not be used for simplistic cases
that can be handler by .cruft files.

The output of the scripts can contain three kind of records:
 * /I<PATH> : the files matched (mandatory)
 * B<@>/I<PATH>: this allow indirect ownership lookup,
   i.e. the following files belong to the package owning this one file
 * I<package>: all following files belongs to I<package>

=back

=cut

init();

# PROMISE: DH NOOP WITHOUT cruft purge cli-options()

foreach my $package (@{$dh{DOPACKAGES}}) {
	next if is_udeb($package);
	my $tmp = tmpdir($package);

	my $explain = pkgfile($package, "explain");
	if ($explain) {
		install_dir("$tmp/usr/libexec/cruft/pkg/");
		install_prog($explain, "$tmp/usr/libexec/cruft/pkg/".pkgfilename($package));
	}

	# get package basic upstream version for templating
	isnative($package);
	my $version = $dh{VERSION};
	$version = (split('-', $version))[0];
	$version = (split('~', $version))[0];

	# the sum of .purge and .cruft lines
	my @lines;

	# TODO: lines about tmpfs (/run, /var/run, /var/lock)
	#       should be forbidden in $cruft as cruft-ng will never peek inside tmpfs by design
	#       but some packages really wants to clean those in postrm,
	#       so they should be accepted in $purge but not leak in @lines

	my $purge = pkgfile($package, "purge");
	if ($purge ne '') {
		my $IN;
		open (IN, $purge) or error("Failed to read ${purge}: $!");
		@lines = <IN>;
		close IN;
		my $var_games = 0;
		my @purgelines = ();
		foreach my $line (@lines)
		{
			chomp $line;
			# rtrim
			$line =~ s/\s+$//;
			if ($line =~ /^#/) {} # comment
			elsif ($line =~ /^$/) {} # empty
			elsif ($line =~ /^\//) {

				$line =~ s/#VERSION#/$version/g;

				if ($line =~ /^[a-zA-Z0-9_:~\-\/\.\?\*]*$/ ) {
					if ($line =~ /\*\*$/ ) {
						chop $line;
						chop $line;
					}
					push @purgelines, "    rm -rf \${DPKG_ROOT:-}${line}";
					if ($line =~ /^\/var\/games/ ) { $var_games = 1; }
				} else {
					my $badchar = $line;
					$badchar =~ tr/[a-zA-Z0-9_:~\-\/\.\?\*]//d;
					error("[${package}] unexpected characters in line: ${line}: [${badchar}]");
				}
			}
			# TODO: accept virtual package name override here too
			else {error("[${package}] bad .purge line: [${line}]")};
		}
		if ($var_games) {
			push @purgelines, "    if test -d \${DPKG_ROOT:-}/var/games/";
			push @purgelines, "    then";
			push @purgelines, "        rmdir --ignore-fail-on-non-empty \${DPKG_ROOT:-}/var/games/";
			push @purgelines, "    fi";

		}
		autoscript($package, "postrm", "postrm-cruft", { 'PURGE' => join("\n", @purgelines)});
	}

	my $cruft = pkgfile($package, "cruft");
	if ($cruft ne '') {
		open (IN, $cruft) or error("Failed to read ${cruft}: $!");
		foreach my $line (<IN>)
		{
			chomp $line;
			$line =~ s/#VERSION#/$version/g;
			push @lines, $line;
		}
		close IN;
	}
	
	if (@lines) {
		my $cruft_dir = "$tmp/usr/share/cruft/rules/";
		install_dir($cruft_dir);
		my $OUT;
		open(OUT, ">", "$cruft_dir/$package") or error("Failed to write to ${cruft_dir}/${package}: $!");
		foreach my $line (@lines)
		{
			if (substr($line, -1) eq "/") {
				print OUT $line . "**\n";
				chop $line;
			}
			print OUT $line . "\n";
		}
		close OUT or error("Failed to close ${OUT}: $!");
	}
}

=head1 SEE ALSO

L<debhelper(1)>

This program is a part of debhelper.

L<cruft(8)>

=head1 AUTHOR

Alexandre Detiste <alexandre.detiste@gmail.com>

=cut
