#!/usr/bin/perl -w

=head1 NAME

dh_installs6 - install s6-rc unit files

=cut

use strict;
use warnings;
use Debian::Debhelper::Dh_Lib;
use File::Find;
use Cwd qw(getcwd abs_path);

our $VERSION = DH_BUILTIN_VERSION;

=head1 SYNOPSIS

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

=head1 DESCRIPTION

B<dh_installs6> is a debhelper program that is responsible for
installing package maintainer supplied s6-rc unit folders.

Generates F<preinst>, F<postinst>, and F<prerm> code blocks for enabling,
disabling and restarting the corresponding s6-rc services, when the package
is installed, updated, or removed. These snippets are added to the maintainer
scripts by L<dh_installdeb(1)>.

B<dh_installs6> automatically processes unit folders containing the file
F<producer-for> (services). For changing the generated blocks behaviour use
file hints (e.g. B<.noenable>) for specific unit folders.

To enable this addon in your source package use B<Build-Depends: dh-sequence-s6>
or set `--with s6` in your debian/rules file.

=head1 FILES

=over 4

=item F<debian/I<package>.s6-rc/*/>

If any of those folders exists, they are installed into
F<usr/lib/s6-rc/sources/> in the package build directory.

=item F<debian/I<package>.s6-rc/*/.noenable>

Disable the service(s) on purge, but do not enable them on install.

B<Note> that this option also affects whether the services are
started/restarted. If a service is enabled or was running it will be
started/restarted. Use file B<.norestart> to mitigate that.

=item F<debian/I<package>.s6-rc/*/.norestart>

Do not restart the service after upgrades or start after initial installation.

B<Note> that this option does not affect whether the services are
enabled. Please remember to also use file B<.noenable> if the services
should not be enabled.

=back

=head1 NOTES

This command is not idempotent. L<dh_prep(1)> should be called between
invocations of this command (with the same arguments). Otherwise, it
may cause multiple instances of the same text to be added to maintainer
scripts.

=cut

init(options => {});

sub quote {
	# Add single quotes around the argument.
	return '\'' . $_[0] . '\'';
}

sub uniq {
	my %seen;
	return grep { !$seen{$_}++ } @_;
}

sub list_installed_service_units {
	my ($tmpdir) = @_;

	my @installed;

	foreach my $unitdir (glob("$tmpdir/usr/lib/s6-rc/sources/*")) {
		next unless -d $unitdir;
		next if -f "$unitdir/consumer-for"; # only service units (not log units)
		push @installed, basename($unitdir);
	}

	return @installed;
}

# Install package maintainer supplied unit folders
foreach my $package (@{$dh{DOPACKAGES}}) {
	my $tmpdir = tmpdir($package);

	# Install all unit folders in the debian/ directory in the
	# form $package.s6-rc/$name.
	my $basedir = "debian/$package.s6-rc";
	my $targetdir = "$tmpdir/usr/lib/s6-rc/sources";

	next unless -d $basedir;

	install_dir($targetdir);
	foreach my $namepath (glob("$basedir/*")) {
		doit("cp", '--reflink=auto', "-r", "-a", $namepath, $targetdir);
	}
}

# Add postinst, prerm, and postrm code blocks to handle activation,
# deactivation, start and stopping of services when the package is
# installed, upgraded or removed.
foreach my $package (@{$dh{DOPACKAGES}}) {
	my $tmpdir = tmpdir($package);
	my (@args, @enable_units, @restart_units);

	my @service_units = list_installed_service_units($tmpdir);

	# find service units that should not be enabled or restarted
	for my $unit (@service_units) {
		my $path = "${tmpdir}/usr/lib/s6-rc/sources/${unit}";
		push @enable_units, $unit unless (-f "$path/.noenable");
		push @restart_units, $unit unless (-f "$path/.norestart");
	}

	# remove .noenable and .noinstall files
	for my $unit (@service_units) {
		doit("rm", "-f", "${tmpdir}/usr/lib/s6-rc/sources/$unit/.noenable");
		doit("rm", "-f", "${tmpdir}/usr/lib/s6-rc/sources/$unit/.norestart");
	}

	# quote and sort to be used in autoscript template
	@service_units = map { quote($_) } uniq sort @service_units;
	@enable_units = map { quote($_) } uniq sort @enable_units;
	@restart_units = map { quote($_) } uniq sort @restart_units;

	if (@enable_units) {
		autoscript($package, 'postinst', 'postinst-s6-enable', {'UNITFILES' => join(' ', @enable_units) });
	} else {
		autoscript($package, 'postinst', 'postinst-s6-compile');
	}

	if (@service_units) {
		autoscript($package, 'postrm', 'postrm-s6-compile');
		autoscript($package, 'prerm', 'prerm-s6-stop', { 'UNITFILES' => join(' ', @service_units) })
	}

	if (@restart_units) {
		autoscript($package, 'postinst', 'postinst-s6-restart', { 'UNITFILES' => join(' ', @restart_units) });
	}
}

=head1 SEE ALSO

L<debhelper(7)>

=head1 AUTHORS

info@automatic-server.com

=cut
