#!/usr/bin/perl -w


use v5.10.1;
use strict;
use Debian::Debhelper::Dh_Lib;
use File::Find;
use File::stat;
use feature 'signatures';
no warnings 'experimental';

sub parse_options($opts) {
    my $conf = { enable => 1 };
    for my $opt (split(/,/, $opts)) {
        given($opt) {
            when (/^disable$/)     { $conf->{enable} = 0; };
            when (/^name=(.*)$/)   { $conf->{name} = $1; };
            when (/^logscript$/)   { $conf->{logscript} = 1};
            when (/^defaults$/)    { "do nothing"; };
            default                { error("unknown option `$opt'"); }
        }
    }
    return $conf;
}

sub ensure_executable($directory) {
    for my $f ('run', 'finish', 'log/run', 'log/finish') {
        my $file = "$directory/$f";
        doit('chmod', '+x', $file) if (-e $file);
    }
}

sub runit_autoscript($pkg, $script, $sed) {
    autoscript($pkg, $script, "$script-runit", $sed);
}

init();

PKG: foreach my $pkg (@{$dh{DOPACKAGES}}) {
    next if is_udeb($pkg);

    my @entries = ();
    if (my $pkgfile = pkgfile($pkg, 'runit')) {
        @entries = filedoublearray($pkgfile);
    }
    while (@ARGV) {
        (my $path, my $opts) = splice(@ARGV, 0, 2);
        push @entries, [$path, $opts];
    }

    my $tmp = tmpdir($pkg);
    my $sv_dir = "$tmp/etc/sv";

    install_dir($sv_dir);

    for (@entries) {
        (my $path, my $opts) = @$_;
        error("can't read `$path'") unless -r $path;

        my $conf = parse_options($opts);
        my $name = $conf->{name} || basename($path);

        if ( -f $path) {
            install_dir("$sv_dir/$name");
            install_prog($path, "$sv_dir/$name/run");
        } elsif ( -d $path) {
            doit('cp', '-r', $path, "$sv_dir/$name");
            # Unfortunately, dh_fixperms does not handle executable bit here.
            ensure_executable("$sv_dir/$name");
        }
        make_symlink("/etc/sv/$name/supervise",
                     "/var/lib/runit/supervise/$name", $tmp);
        install_dir("$tmp/var/lib/runit/supervise/$name");

        if ($conf->{enable}) {
            make_symlink("/etc/runit/runsvdir/default/$name",
                         "/etc/sv/$name", $tmp);
        }
        runit_autoscript($pkg, 'postrm', "s/#NAME#/$name/");
        if ($conf->{logscript}) {
            my $logdir = "/var/log/runit/$name";

            install_dir("$sv_dir/$name/log");
            install_dir($tmp . $logdir);

            my $run_log = "$sv_dir/$name/log/run";
            my $log_user = "_log-". $name;
            open(RUN_LOG, ">$run_log") || die $!;
            print RUN_LOG << "HERE";
#!/bin/sh
chown -R '$log_user' '$logdir'
exec chpst -u '$log_user' svlogd -tt '$logdir'
HERE
            close(RUN_LOG);
            chmod(0755, $run_log);
            doit('dh_sysuser', '-p', $pkg, $log_user, 'defaults');
            make_symlink("/etc/sv/$name/log/supervise",
                         "/var/lib/runit/log/supervise/$name", $tmp);
            install_dir("$tmp/var/lib/runit/log/supervise/$name");
        }
    }
    addsubstvar($pkg, 'misc:Depends', 'runit', '>= 2.1.2-7');
    addsubstvar($pkg, 'misc:Depends', 'runit-helper');
}

# PROMISE: DH NOOP WITHOUT runit

=head1 NAME

dh_runit - install/enable runit runscripts

=head1 SYNOPSIS

B<dh_runit> [S<I<debhelper options>>] [I<path> I<options>] ...

=head1 DESCRIPTION

B<dh_runit> is a debhelper program that is responsible for
installing and enabling I<runit> runscripts. If file named
F<debian/I<package>.runit> exists, then different actions
are performed, depending on its format.

For runit, every unit of supervision, simply speaking program, is
represented by directory under F</etc/sv>, containing at least F<run>
executable file. Every enabled program is represented by symbolic link
under F</etc/services> (which itself is symbolic link to
F</etc/runit/runsvdir/default>) pointing to some directory under
F</etc/sv>.

B<dh_runit> reads it's arguments from command line and
F<debian/I<package>.runit> by two, with first one being an
file/directory and second one is options. If first argument is file,
it is considered 'run' script, and it is installed under
F</etc/sv/*/run>, executable bit is added. If first argument is
directory, it is copied as whole under F</etc/sv>.

Options are comma-separated, like to mount. Unsupported option
is error, following are supported:

=over

=item I<disable>

    With this option, runscript is installed, but not enabled by
    default. It means that corresponding service will not be started.
    System administrator can always do it manually or via
    update-service(8).

=item I<name>=preferred-name

    By default, name of directory under F</etc/sv> for given runscript
    is basename of first argument of pair. This option allows you to
    be explicit about it.

=item I<logscript>

    Install standard F<log/run> script, which invokes svlogd(8) with
    rights of dedicated user. It is error, if first argument in pair
    is directory, which already contains F</log/run> script.

=item I<defaults>

    If you need no other options, put this one.

=back

=head1 EXAMPLES

This section contains several example snippets from F<I<package>.runit>

  # In this case file is installed as 'run' script. Directory name under
  # /etc/sv is derived from file basename
  path/to/file/to/be/installed/as/run/script defaults

  # Same, but install directory as whole. It is your responsibility
  # to ensure is contains everything required.
  path/to/directory defaults

  # Same as above, but do not create symlink under /etc/service
  path/to/directory disable

  # You can explicitly specify name of directory under /etc/sv.
  # Standard log/run script will be created.
  path/to/directory name=my-preferred-name,logscript

=cut
