App-cpan2arch

 view release on metacpan or  search on metacpan

lib/App/cpan2arch/WritePkgbuild.pm  view on Meta::CPAN

use v5.42.0;

use strict;
use warnings;
no source::encoding;  # Avoid dying on v5.42.0 (non-ASCII char in POD).

use Object::Pad 0.825;

package App::cpan2arch::WritePkgbuild;  # For toolchain compatibility.
role App::cpan2arch::WritePkgbuild;

use open qw< :std :encoding(UTF-8) >;

use File::Basename qw< basename >;
use Scalar::Util   qw< looks_like_number >;
use List::Util     qw<
    any
    first
    reduce
    uniq
>;

$|++;  # Disable STDOUT buffering.

our $VERSION = 'v1.1.2';

field $_install_license;
field %_generated_meta;
field %_pkgbuild :reader :writer;

# Generate the PKGBUILD bash script.
#
# References:
#   https://wiki.archlinux.org/title/Perl_package_guidelines
method generate_pkgbuild ()
{
    $self->_psub;

    $self->_get_pkgbuild_vars;

    my %opts = $self->opts;
    my %meta = $self->meta;
    my $mb   = false;

    # build()
    my $build;
    {
        my %arch_prereqs = $self->arch_prereqs;
        my @has_mb;

        # Set the builder to use in PKGBUILD
        # (Prefer M::B or M::B::T and use EU::MM as fallback)

        if ( !$meta{has_module_install} ) {
            @has_mb = grep { /\Aperl-module-build(?> -tiny)? (?> [<>=] | \z )/x } $arch_prereqs{makedepends}->@*;
            $mb     = true if scalar @has_mb;
        }

        $build = $mb
          ? <<~'END'
              unset PERL_MB_OPT PERL5LIB PERL_LOCAL_LIB_ROOT
              export PERL_MM_USE_DEFAULT=1 MODULEBUILDRC=/dev/null

              /usr/bin/perl Build.PL --create_packlist=0
              ./Build
          END
          : <<~'END';
              unset PERL_MM_OPT PERL5LIB PERL_LOCAL_LIB_ROOT
              export PERL_MM_USE_DEFAULT=1

              /usr/bin/perl Makefile.PL NO_PACKLIST=1 NO_PERLLOCAL=1
              make
          END

        # Do not auto-install prereqs with Module::Install.

lib/App/cpan2arch/WritePkgbuild.pm  view on Meta::CPAN

                    pkgdesc
                    url
                    install
                    changelog
                >
            );
            my @NEEDED_VARS = (
                qw<
                    pkgbase
                    pkgver
                    pkgrel
                >
            );

            # References:
            #   https://wiki.archlinux.org/title/.SRCINFO
            #   https://man.archlinux.org/man/SRCINFO.5
            #   https://man.archlinux.org/man/alpm-pkgver.7
            #   https://man.archlinux.org/man/alpm-pkgrel.7
            foreach my $line (@srcinfo) {
                next if $line eq '';

                my ( $key, $val ) = split / = /, $line;
                next unless defined $val;
                $key =~ s{\A\t}{};

                if ( any { $key eq $_ } @VARS ) {
                    $srcinfo_meta{$key} = $val;
                    next;
                }

                push $srcinfo_meta{$key}->@*, $val;
            }

            $self->_pdump( '%srcinfo_meta', \%srcinfo_meta, "\n" );

            foreach my ($var) (@NEEDED_VARS) {
                if ( !exists $srcinfo_meta{$var} ) {
                    warn "$prog: $var is not declared in $FILES{metadata}\n";
                    return 1;
                }
            }

            if ( $pkgname ne $srcinfo_meta{pkgbase} ) {
                warn "$prog: $FILES{metadata} package ($srcinfo_meta{pkgbase}) is different than $pkgname\n";
                return 1;
            }
        }

        # .SRCINFO pkgver must not be newer than generated PKGBUILD pkgver.
        {
            my $ret = $self->_comp_vers( $_pkgbuild{pkgver}, $srcinfo_meta{pkgver}, '<' );
            return 1 if defined $ret && $ret == 1;

            if ( defined $ret && $ret == 0 ) {
                warn "$prog: $FILES{metadata} version ($srcinfo_meta{pkgver}) is newer than $_pkgbuild{pkgver}\n";
                return 1;
            }
        }

        if ( !looks_like_number( $srcinfo_meta{pkgrel} ) ) {
            warn "$prog: pkgrel $srcinfo_meta{pkgrel} is not a number\n";
            return 1;
        }

        # Add epoch if newer version breaks pacman's version comparison logic.
        #
        # References:
        #   https://wiki.archlinux.org/title/PKGBUILD#epoch
        #   https://man.archlinux.org/man/core/pacman/PKGBUILD.5.en#:~:text=epoch
        #   https://man.archlinux.org/man/alpm-epoch.7
        #   https://man.archlinux.org/man/vercmp.8
        #   https://gitlab.archlinux.org/pacman/pacman/-/blob/master/lib/libalpm/version.c
        my $has_epoch = false;
        {
            my $ret = $self->_comp_vers( $_pkgbuild{pkgver}, $srcinfo_meta{pkgver}, '>' );
            return 1 if defined $ret && $ret == 1;

            if ( defined $ret && $ret == 0 ) {
                require Devel::CheckBin;
                Devel::CheckBin->VERSION('0.04');

                my $cmd_path = Devel::CheckBin::can_run('vercmp');
                $self->_pdump( '$cmd_path', \$cmd_path, '' );

                if ( defined $cmd_path ) {
                    require Capture::Tiny;
                    Capture::Tiny->VERSION('0.50');

                    my ( $stdout, $stderr, $exit ) = Capture::Tiny::capture(
                        sub { system( $cmd_path, $_pkgbuild{pkgver}, $srcinfo_meta{pkgver} ) }
                    );

                    $self->_pdump( '$stdout', \$stdout, '' );
                    $self->_pdump( '$stderr', \$stderr, '' );
                    $self->_pdump( '$exit',   \$exit,   '' );

                    if ( $exit != 0 ) {
                        warn $stderr;
                        warn "$prog: failed to run vercmp\n";

                        return 1;
                    }

                    # New version breaks vercmp logic.
                    if ( $stdout < 0 ) {
                        my $epoch = $srcinfo_meta{epoch} // 1;

                        if ( exists $srcinfo_meta{epoch} ) {
                            ++$epoch;
                            $self->_pdbg("bump epoch to $epoch\n");
                        }

                        if ( $gen_output =~ s{^pkgrel=[^\n]+\n\K}{epoch=$epoch\n}m ) {
                            $has_epoch = true;
                            $self->_pdbg("add epoch\n");
                        }
                    }

                    $self->_pdbg("\n");
                }



( run in 0.833 second using v1.01-cache-2.11-cpan-6aa56a78535 )