=head1 NAME

Doit::Deb - commands for dealing with the Debian package system

=head1 SYNOPSIS

    use Doit;
    my $doit = Doit->init;
    $doit->add_component('deb');

    $doit->deb_install_packages(qw(zsh wget aptitude));

    my @missing_packages = $doit->deb_missing_packages(qw(zsh wget aptitude));

    my @upgradeable_packages = $doit->deb_upgradeable_packages();

    $doit->deb_install_key(
        url => 'http://deb.example.org/key/deb.example.org.key',
        key => '0123456789ABCDEF0123456789ABCDEF01234567',
    );

=head1 DESCRIPTION

B<Doit::Deb> is a L<Doit> component providing commands for dealing
with debian packages. It has to be added to a script using L<Doit's
add_component|Doit/add_component>:

    $doit->add_component('deb');

=head2 DOIT COMMANDS

The following commands are added to the Doit runner object:

=head3 deb_install_packages

    $doit->deb_install_packages(@packages);

Make sure that the listed debian packages are installed (currently
using L<apt-get(8)>). Return a list of the packages which were
actually installed during the execution of this command (or the number
of packages in scalar context).

=head3 deb_missing_packages

    my @missing_packages = $doit->deb_missing_packages(@packages);

Return the packages out of I<@packages> which are not yet installed.
This is an "informational" command and runs even in dry-run mode.

=head3 deb_upgradeable_packages

    my @upgradeable_packages = $doit->deb_upgradeable_packages();

Return a list of packages which have upgrades available. Uses C<apt-get
-s upgrade> to determine which packages can be upgraded. This is an
"informational" command and runs even in dry-run mode.

This function is useful for making decisions about whether to run an
upgrade:

    if ($doit->deb_upgradeable_packages) {
        $doit->system(qw(apt-get upgrade));
    }

=head3 deb_install_key

    $doit->deb_install_key(
        file => "/etc/apt/keyrings/$name.gpg",
        url  => $url,
        key  => $key,
    );
    $doit->deb_install_key(
        keyserver => $keyserver,
        key       => $key,
        file      => "/etc/apt/keyrings/$name.gpg",
    );

Make sure that the given key is installed in the specified C<file>
(newer Debian/Ubuntu) or in the default apt keyring (older
Debian/Ubuntu). The key is downloaded from the given I<$url>
(L<curl(1)> or L<wget(1)> are needed to download the key) and
installed with the help of L<gpg(1)>. The caller is responsible to
make sure that the needed packages are already installed, e.g. by
calling

    $doit->deb_install_packages(qw(curl gnupg));

before. The I<$key> parameter with the fingerprint of the key is
optional but recommended; if specified then Doit can detect if the key
is already installed and avoid downloads.

On older Debians I<$keyserver> and I<$key> may be specified instead of
I<$url> (in which case L<apt-key(8)> is used to download and install
the key).

Return 1 if the key was actually installed, otherwise 0.

=head3 deb_add_repository

    $doit->deb_add_repository($name, $sources_contents, update => $bool);

Add a repository by creating a file F<<
/etc/apt/sources.list.d/I<$name>.sources >> (newer Debians/Ubuntus) or
F<</etc/apt/sources.list.d/I<$name>.list >> (older Debians/Ubuntus).
The contents of C<$sources_contents> must be written in the new
Deb822-based C<.sources> format. For example:

     Types: deb deb-src
     URIs: http://deb.debian.org/debian
     Suites: stable
     Components: main
     Architectures: amd64 arm64
     Signed-By: /etc/apt/keyrings/foo.gpg

On older releases this content is converted automatically into the
legacy C<.list> format. The above example would be rendered as:

   deb [arch=amd64,arm64 signed-by=/etc/apt/keyrings/foo.gpg] http://deb.debian.org/debian stable main
   deb-src [arch=amd64,arm64 signed-by=/etc/apt/keyrings/foo.gpg] http://deb.debian.org/debian stable main

If C<update =E<gt> 1> is given, then C<apt-get update> will be run,
but only if the repository file was created or modified.

Return 1 if a change to the repository file occurred, otherwise 0.

=head2 NOTES

=head3 Add to sources.list

To add a Debian repository to F</etc/apt/sources.list.d> the following
approach may be used:

    use Doit::Util qw(get_os_release);
    my $codename = get_os_release()->{VERSION_CODENAME}; # for older Linux distributions (for example debian:jessie) use instead the chomped output of `lsb_release -cs`
    if ($doit->write_binary("/etc/apt/sources.list.d", "deb http://debs.example.org $codename main\n")) {
        $doit->system(qw(apt-get update));
    }

=head1 AUTHOR

Slaven Rezic <srezic@cpan.org>

=head1 COPYRIGHT

Copyright (c) 2017,2018,2020,2025 Slaven Rezic. All rights reserved.
This module is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=head1 SEE ALSO

L<Doit>, L<apt-get(8)>, L<dpkg-query(1)>, L<apt-key(8)>.

=cut
