859 lines
24 KiB
Perl
Executable File
859 lines
24 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
# apk add perl-libwww perl-json
|
|
|
|
use strict;
|
|
use warnings;
|
|
use 5.016;
|
|
|
|
use LWP::UserAgent;
|
|
use LWP::ConnCache;
|
|
use CPAN::Meta;
|
|
use Module::CoreList;
|
|
use JSON;
|
|
use Text::Wrap qw(wrap $columns);
|
|
use List::Util qw (uniq);
|
|
use File::Basename qw(basename dirname);
|
|
use URI;
|
|
|
|
my $license_mappings = {
|
|
"perl_5" => "GPL-1.0-or-later OR Artistic-1.0-Perl",
|
|
"artistic_2" => "Artistic-2.0",
|
|
"gpl_2" => "GPL-2.0-only",
|
|
"gpl_3" => "GPL-3.0-only",
|
|
"mit" => "MIT",
|
|
"apache_2_0" => "Apache-2.0",
|
|
};
|
|
|
|
my $package_mappings = {
|
|
"LWP" => "perl-libwww",
|
|
"libwww-perl" => "perl-libwww",
|
|
"TermReadKey" => "perl-term-readkey",
|
|
"perl-ldap" => "perl-ldap",
|
|
"PerlIO-gzip" => "perl-io-gzip",
|
|
"ControlX10-CM11" => "perl-control-x10",
|
|
"File-RsyncP" => "perl-file-rsync",
|
|
"Perl-Critic" => "perl-critic",
|
|
"Perl-Tidy" => "perl-tidy",
|
|
"ack" => "ack",
|
|
"Mail-SpamAssassin" => "spamassassin",
|
|
};
|
|
our $packager = "";
|
|
my $template = <<'EOF';
|
|
# Automatically generated by apkbuild-cpan, template 4
|
|
[% authors %]
|
|
pkgname=[% pkgname %]
|
|
pkgver=[% pkgver %]
|
|
pkgrel=[% pkgrel %]
|
|
#_pkgreal is used by apkbuild-cpan to find modules at MetaCpan
|
|
_pkgreal=[% pkgreal %]
|
|
pkgdesc="Perl module for [% pkgreal %]"
|
|
provides="[% provides %]"
|
|
replaces="[% replaces %]"
|
|
url="https://metacpan.org/release/[% pkgreal %]/"
|
|
arch="noarch"
|
|
options="[% options %]"[% options_comment %]
|
|
license="GPL-1.0-or-later OR Artistic-1.0-Perl"
|
|
depends="perl"
|
|
makedepends=""
|
|
checkdepends=""
|
|
subpackages="$pkgname-doc"
|
|
source="[% source %]"
|
|
builddir="[% builddir %]"
|
|
|
|
build() {
|
|
:
|
|
}
|
|
|
|
check() {
|
|
:
|
|
}
|
|
|
|
package() {
|
|
:
|
|
}
|
|
|
|
EOF
|
|
|
|
our $ua = LWP::UserAgent->new();
|
|
our $json = JSON->new;
|
|
$ua->env_proxy;
|
|
$ua->conn_cache( LWP::ConnCache->new() );
|
|
|
|
sub read_file {
|
|
my ($filename) = @_;
|
|
local $/;
|
|
open my $fh, "<", $filename or die "could not open $filename: $!";
|
|
return <$fh>;
|
|
}
|
|
|
|
sub read_assignments_from_file {
|
|
my ($filename) = @_;
|
|
return () if ( !-e $filename );
|
|
my $text = read_file($filename);
|
|
my %sline = $text =~ /^(\w+)\s*=\s*([^\"\n]*)$/mg;
|
|
my %mline = $text =~ /^(\w+)\s*=\s*\"([^\"]*)\"$/mg;
|
|
my %hash = ( %sline, %mline );
|
|
|
|
return \%hash if $filename ne 'APKBUILD';
|
|
my $authors = join( "\n",
|
|
$text =~ /^# Contributor: .*$/mg,
|
|
$text =~ /^# Maintainer: .*$/mg );
|
|
$hash{'authors'} = $authors if length($authors) > 1;
|
|
|
|
my $options = $text =~ m/^options=\"(.*)\"(.*)$/mg;
|
|
$hash{'options'} = "$1" if length($options) >= 1;
|
|
$hash{'options_comment'} = "$2" if length($options) >= 1;
|
|
|
|
return \%hash;
|
|
}
|
|
|
|
sub map_cpan_to_apk {
|
|
my ($cpan_distrib) = @_;
|
|
return $package_mappings->{$cpan_distrib}
|
|
if exists $package_mappings->{$cpan_distrib};
|
|
|
|
# most packages are named according to the
|
|
# distribution name
|
|
return 'perl-' . lc $cpan_distrib;
|
|
}
|
|
|
|
sub read_apkbuild {
|
|
return read_assignments_from_file("APKBUILD");
|
|
}
|
|
|
|
sub format_line {
|
|
my $line = shift;
|
|
return "\t" . $line . "\n";
|
|
}
|
|
|
|
sub format_source {
|
|
my $srcurl = shift;
|
|
my $orig_src = shift;
|
|
|
|
$orig_src =~ s/^\n//mg;
|
|
|
|
my @sources = split (/\n/m, $orig_src);
|
|
|
|
return $srcurl if scalar @sources le 1;
|
|
|
|
my $source = format_line($srcurl);
|
|
|
|
shift @sources;
|
|
my $patches = undef;
|
|
for my $patch (@sources) {
|
|
$patch =~ s/\t//g;
|
|
next if $patch eq "";
|
|
$patches .= format_line($patch);
|
|
}
|
|
|
|
return "\n" . $source . (defined $patches ? $patches : '') . "\t";
|
|
}
|
|
|
|
sub write_apkbuild {
|
|
my ( $distdata, $apkbuild, $moddata ) = @_;
|
|
|
|
my $authors = undef;
|
|
my $replaces = undef;
|
|
my $provides = undef;
|
|
my $pkgrel = 0;
|
|
my $options = undef;
|
|
my $options_comment = undef;
|
|
my $orig_source = undef;
|
|
if ( defined $apkbuild ) {
|
|
$authors = $apkbuild->{authors};
|
|
$provides = $apkbuild->{provides};
|
|
$replaces = $apkbuild->{replaces};
|
|
$pkgrel = $apkbuild->{pkgrel};
|
|
$options = $apkbuild->{options} if defined $apkbuild->{options};
|
|
$options_comment = $apkbuild->{options_comment} if defined $apkbuild->{options_comment};
|
|
$orig_source = $apkbuild->{source};
|
|
if ( $apkbuild->{pkgver} eq $moddata->{version} ) {
|
|
$pkgrel++;
|
|
}
|
|
}
|
|
|
|
my $builddir;
|
|
|
|
my $srcurl = $moddata->{download_url};
|
|
my $filename = (URI->new($srcurl)->path_segments)[-1];
|
|
|
|
my $pkgreal = $moddata->{distribution};
|
|
my $pkgver = $moddata->{version} =~ s/^[^0-9]+//r;
|
|
if ( $filename =~ m/$pkgreal-$pkgver/ ) {
|
|
$builddir = "\$srcdir/\$_pkgreal-\$pkgver";
|
|
} elsif ( $filename =~ m/$pkgreal-v${pkgver}/ ) {
|
|
$builddir = "\$srcdir/\$_pkgreal-v\$pkgver";
|
|
} else {
|
|
$builddir = "\$srcdir/\$_pkgreal-" . $moddata->{version};
|
|
}
|
|
|
|
my %repl = (
|
|
authors => (
|
|
$authors
|
|
or "# Contributor: $packager\n# Maintainer: $packager"
|
|
),
|
|
pkgname => map_cpan_to_apk( $moddata->{distribution} ),
|
|
pkgreal => $pkgreal,
|
|
pkgver => $pkgver,
|
|
pkgrel => $pkgrel,
|
|
source => format_source($srcurl, $orig_source),
|
|
pkgdesc => $distdata->{abstract},
|
|
provides => ( $provides or '' ),
|
|
replaces => ( $replaces or '' ),
|
|
builddir => $builddir,
|
|
options => ( $options or '' ),
|
|
options_comment => ( $options_comment or '' ),
|
|
);
|
|
$repl{source} =~ s/$repl{pkgver}/\$pkgver/g;
|
|
$template =~ s/\[% (.*?) %\]/$repl{$1}/g;
|
|
|
|
open my $fh, '>', "APKBUILD" or die;
|
|
print $fh $template;
|
|
close $fh;
|
|
|
|
say "Wrote $repl{pkgname}/APKBUILD";
|
|
}
|
|
|
|
sub query_metacpan {
|
|
my ($type, $name) = @_;
|
|
|
|
my $response = $ua->get("https://fastapi.metacpan.org/$type/$name");
|
|
$response->is_success
|
|
or die $response->status_line
|
|
. " unable to find $name, verify Perl Module name in APKBUILD\n";
|
|
|
|
my $data = $json->decode( $response->decoded_content );
|
|
$data->{error}
|
|
and die "Error trying to locate $name: $data->{error}\n";
|
|
|
|
return $data;
|
|
}
|
|
|
|
sub parse_deps {
|
|
my ($reqs) = @_;
|
|
my $distfiles = {};
|
|
my $deps = "";
|
|
my $reqmodlist = "";
|
|
|
|
#Get list of unique required modules from all parameters
|
|
foreach $reqs (@_) {
|
|
for my $module ( $reqs->required_modules ) {
|
|
$reqmodlist .= "$module " unless $reqmodlist =~ m/^$module$/;
|
|
}
|
|
}
|
|
|
|
# Check add the require module to $dep if not part of core perl
|
|
foreach my $module ( split " ", $reqmodlist ) {
|
|
next if $module eq 'perl';
|
|
if ( Module::CoreList->is_core($module) ) {
|
|
my $perlver = Module::CoreList->first_release($module);
|
|
say " $module is part of core perl since $perlver.";
|
|
next;
|
|
}
|
|
|
|
# map module name to package name
|
|
my $moddata = query_metacpan( module => $module );
|
|
$distfiles->{$module} = $moddata->{distribution};
|
|
}
|
|
|
|
# map package names to alpine packages
|
|
foreach my $module ( sort keys %{$distfiles} ) {
|
|
my $pkgname = map_cpan_to_apk( $distfiles->{$module} );
|
|
$deps .= "$pkgname " unless $deps =~ m/\b$pkgname\b/;
|
|
}
|
|
$deps =~ s/\h+/ /g;
|
|
$deps =~ s/ $//;
|
|
return defined $deps ? $deps : '';
|
|
}
|
|
|
|
sub prepare_tree {
|
|
system("abuild checksum unpack prepare") == 0
|
|
or die "abuild checksum failed";
|
|
}
|
|
|
|
sub update_functions {
|
|
my $apkbuild = read_apkbuild;
|
|
my $pkgver = $apkbuild->{'pkgver'};
|
|
my $build_pl_found = glob("src/*${pkgver}/Build.PL");
|
|
my $build_func;
|
|
my $check_func;
|
|
my $package_func;
|
|
|
|
my $text = read_file "APKBUILD";
|
|
if ( $build_pl_found ) {
|
|
$build_func = <<'EOF';
|
|
build() {
|
|
export CFLAGS=$(perl -MConfig -E 'say $Config{ccflags}')
|
|
perl Build.PL \
|
|
--installdirs=vendor \
|
|
--create_packlist=0
|
|
./Build
|
|
}
|
|
EOF
|
|
$package_func = <<'EOF';
|
|
package() {
|
|
./Build install --destdir="$pkgdir"
|
|
}
|
|
EOF
|
|
$check_func = <<'EOF';
|
|
check() {
|
|
./Build test
|
|
}
|
|
EOF
|
|
}
|
|
else {
|
|
$build_func = <<'EOF';
|
|
build() {
|
|
export CFLAGS=$(perl -MConfig -E 'say $Config{ccflags}')
|
|
PERL_MM_USE_DEFAULT=1 perl -I. Makefile.PL \
|
|
INSTALLDIRS=vendor \
|
|
NO_PACKLIST=1 \
|
|
NO_PERLLOCAL=1
|
|
make
|
|
}
|
|
EOF
|
|
$package_func = <<'EOF';
|
|
package() {
|
|
make DESTDIR="$pkgdir" install
|
|
}
|
|
EOF
|
|
$check_func = <<'EOF';
|
|
check() {
|
|
export CFLAGS=$(perl -MConfig -E 'say $Config{ccflags}')
|
|
make test
|
|
}
|
|
EOF
|
|
}
|
|
|
|
if ( length(`find src/*$pkgver/lib -name '*.pod'`) ) {
|
|
$package_func .= <<'EOF';
|
|
|
|
doc() {
|
|
local file; find "$pkgdir" -name "*.pod" | while read -r file; do
|
|
amove "${file#"$pkgdir"}"
|
|
done
|
|
default_doc
|
|
}
|
|
EOF
|
|
}
|
|
|
|
$text =~ s/^build\(\) \{.*?^\}\n/$build_func/smg
|
|
or die "Can't replace build function APKBUILD";
|
|
$text =~ s/^package\(\) \{.*?^\}\n/$package_func/smg
|
|
or die "Can't replace package function APKBUILD";
|
|
$text =~ s/^check\(\) \{.*?^\}\n/$check_func/smg
|
|
or die "Can't replace check function APKBUILD";
|
|
|
|
open my $fh, '>', "APKBUILD" or die;
|
|
print $fh $text;
|
|
close $fh;
|
|
}
|
|
|
|
sub sort_pkgs_by_orig {
|
|
my $sort_order = shift;
|
|
my $list = shift;
|
|
|
|
return '' if !defined $list;
|
|
my @array_to_sort = split / /, $list;
|
|
|
|
s/[\t\n\r\f]/ /g
|
|
for $sort_order; # remove embedded new lines from sort order
|
|
s/\h+/ /g for $sort_order; # remove embedded spaces from sort order
|
|
|
|
my @sort_order = split / /, $sort_order;
|
|
|
|
#get order of order by string
|
|
my $count = 0;
|
|
my %position_of;
|
|
$position_of{$_} = $count++ for @sort_order;
|
|
|
|
my %sorted; # holds the position of array to sort
|
|
|
|
foreach (@array_to_sort) {
|
|
my $pos = $position_of{$_};
|
|
if ( !defined $pos ) {
|
|
|
|
# not found in sort order so add to the end
|
|
$sorted{$_} = $count;
|
|
$count++;
|
|
}
|
|
else {
|
|
$sorted{$_} = $pos;
|
|
}
|
|
}
|
|
|
|
my @tmp; # hold array of sorted in position order
|
|
|
|
foreach my $name ( sort { $sorted{$a} <=> $sorted{$b} } keys %sorted ) {
|
|
push @tmp, $name;
|
|
}
|
|
|
|
# remove any duplicates
|
|
uniq @tmp;
|
|
|
|
return join( " ", @tmp );
|
|
}
|
|
|
|
sub format_depends {
|
|
my $deps = shift;
|
|
|
|
return '' if !defined $deps;
|
|
$columns = 102;
|
|
|
|
$deps =~ s/ {2,}/ /g;
|
|
$deps =~ s/^\s//g;
|
|
$deps =~ s/\s$//g;
|
|
|
|
if ( length($deps) >= $columns ) {
|
|
$deps = wrap( "\t", "\t", $deps );
|
|
}
|
|
$deps =~ s/\s$//g;
|
|
|
|
if ( length($deps) >= $columns ) {
|
|
$deps = "\n" . $deps . "\n\t";
|
|
}
|
|
return $deps;
|
|
}
|
|
|
|
sub do_depends {
|
|
my $modver = shift;
|
|
my $oldapkbuild = shift;
|
|
my $apkbuild = read_apkbuild;
|
|
|
|
my $metaprefix = '';
|
|
if ( exists $apkbuild->{'_realname'} ) {
|
|
$metaprefix = "src/" . $apkbuild->{'_realname'};
|
|
}
|
|
elsif ( exists $apkbuild->{'_pkgreal'} ) {
|
|
$metaprefix = "src/" . $apkbuild->{'_pkgreal'};
|
|
}
|
|
elsif ( exists $apkbuild->{'_pkgname'} ) {
|
|
$metaprefix = "src/" . $apkbuild->{'_pkgname'};
|
|
}
|
|
elsif ( exists $apkbuild->{'_name'} ) {
|
|
$metaprefix = "src/" . $apkbuild->{'_name'};
|
|
}
|
|
elsif ( exists $apkbuild->{'_realpkgname'} ) {
|
|
$metaprefix =
|
|
"src/" . $apkbuild->{'_realpkgname'};
|
|
}
|
|
elsif ( exists $apkbuild->{'_pkg_real'} ) {
|
|
$metaprefix = "src/" . $apkbuild->{'_pkg_real'};
|
|
}
|
|
else {
|
|
die
|
|
"Unable to find meta file directory - check APKBUILD Perl Module Name";
|
|
}
|
|
|
|
$modver = defined($modver) ? $modver : $apkbuild->{'pkgver'};
|
|
$modver =~ s/v//g;
|
|
|
|
# try with partial metaprefix
|
|
my @metafiles = glob("
|
|
$metaprefix-*${modver}/*META.json
|
|
$metaprefix-*${modver}/*META.yml
|
|
");
|
|
|
|
my $build_path = glob("
|
|
src/*${modver}/Build.PL
|
|
src/*${modver}/Makefile.PL
|
|
");
|
|
|
|
if ( @metafiles ) {
|
|
$metaprefix = dirname($metafiles[0]);
|
|
} elsif ( $build_path ) {
|
|
$metaprefix = dirname($build_path);
|
|
my $build_file = basename($build_path);
|
|
system("cd $metaprefix && perl -I. $build_file");
|
|
|
|
# try again with full metaprefix
|
|
push @metafiles, glob("
|
|
$metaprefix/*META.json
|
|
$metaprefix/*META.yml
|
|
");
|
|
} else {
|
|
die "Unable to find meta, makefile, and build.pl - cannot proceed"
|
|
}
|
|
|
|
die "No meta files found after executing $build_path" unless @metafiles;
|
|
|
|
my $builddir = do {
|
|
my $pkgreal = $apkbuild->{'_pkgreal'};
|
|
my $oldbuilddir = $apkbuild->{builddir};
|
|
my $newbuilddir = $metaprefix;
|
|
|
|
$newbuilddir =~ s/src/\$srcdir/;
|
|
$newbuilddir =~ s/$pkgreal/\$_pkgreal/;
|
|
$newbuilddir =~ s/$modver/\$pkgver/;
|
|
|
|
$newbuilddir eq $oldbuilddir ? undef : $newbuilddir
|
|
};
|
|
|
|
my $meta;
|
|
|
|
foreach
|
|
my $metafile ( @metafiles )
|
|
{
|
|
if ( -e "$metafile" ) {
|
|
say "Using meta information from $metafile";
|
|
$meta = CPAN::Meta->load_file("$metafile");
|
|
last;
|
|
}
|
|
}
|
|
|
|
my $deps;
|
|
my $abstract;
|
|
my $license;
|
|
if ($meta) {
|
|
$license = join " OR ",
|
|
map { $license_mappings->{$_} or $_ } $meta->license;
|
|
say "License: $license";
|
|
|
|
$abstract = $meta->abstract;
|
|
say "Abstract: $abstract";
|
|
|
|
$deps = parse_deps(
|
|
$meta->effective_prereqs->requirements_for( 'runtime', 'requires' ) );
|
|
}
|
|
|
|
if ( defined $oldapkbuild->{'depends'} ) {
|
|
if ( defined $oldapkbuild->{'cpandepends'} ) {
|
|
$oldapkbuild->{'depends'} =~
|
|
s/\$cpandepends/$oldapkbuild->{'cpandepends'}/g;
|
|
}
|
|
my @libs = split /\s+/, $oldapkbuild->{'depends'};
|
|
if ( @libs ) {
|
|
my $libs = join ' ',
|
|
grep { not (m/perl\-\w+[-\w+]+/ or ($_ eq 'perl')) } @libs;
|
|
$deps .= " " . $libs if defined $deps;
|
|
}
|
|
$deps = sort_pkgs_by_orig( $oldapkbuild->{'depends'}, $deps );
|
|
}
|
|
|
|
if ( defined $deps && $deps eq '' ) {
|
|
if (defined $oldapkbuild->{'depends'} && ! $meta ) {
|
|
$deps = $oldapkbuild->{'depends'};
|
|
} else {
|
|
$deps = "perl";
|
|
}
|
|
}
|
|
else {
|
|
$deps = format_depends( "perl " . $deps ) if defined $deps;
|
|
}
|
|
|
|
my $makedeps = '';
|
|
if ($meta) {
|
|
say "CPAN runtime Required: $deps";
|
|
say "CPAN runtime Recommended: "
|
|
. parse_deps(
|
|
$meta->effective_prereqs->requirements_for( 'runtime', 'recommends' ) );
|
|
|
|
$makedeps = parse_deps(
|
|
$meta->effective_prereqs->requirements_for( 'configure', 'requires' ),
|
|
$meta->effective_prereqs->requirements_for( 'configure', 'recommends' ),
|
|
$meta->effective_prereqs->requirements_for( 'build', 'requires' ),
|
|
$meta->effective_prereqs->requirements_for( 'build', 'recommends' )
|
|
);
|
|
|
|
if ( -e "$metaprefix/Build.PL" ) {
|
|
$makedeps = "$makedeps perl-module-build"
|
|
unless $makedeps =~ m/^perl-module-build$/;
|
|
}
|
|
|
|
}
|
|
if ( defined $oldapkbuild->{'makedepends'} ) {
|
|
if ( defined $oldapkbuild->{'cpanmakedepends'} ) {
|
|
$oldapkbuild->{'makedepends'} =~
|
|
s/\$cpanmakedepends/$oldapkbuild->{'cpanmakedepends'}/g;
|
|
}
|
|
my @libs = split /\s+/, $oldapkbuild->{'makedepends'};
|
|
if ( @libs ) {
|
|
my $libs = join ' ', grep { not (m/perl\-\w+[-\w+]+/) } @libs;
|
|
$makedeps .= " " . $libs;
|
|
}
|
|
$makedeps =
|
|
sort_pkgs_by_orig( $oldapkbuild->{'makedepends'}, $makedeps );
|
|
}
|
|
|
|
my $has_xs = length(`find $metaprefix -name '*.xs'`);
|
|
|
|
my $perldev = $has_xs ? "perl-dev" : '';
|
|
if ( defined $makedeps && $makedeps eq '' ) {
|
|
if (defined $oldapkbuild->{'makedepends'} && ! $meta) {
|
|
$makedeps = $oldapkbuild->{'makedepends'};
|
|
my @tmp = split(" ", $makedeps);
|
|
@tmp = grep ! /$perldev/, @tmp if ! $has_xs;
|
|
$makedeps = format_depends(join(" ", @tmp));
|
|
} else {
|
|
$makedeps = $perldev;
|
|
}
|
|
}
|
|
else {
|
|
$makedeps = format_depends( $perldev . " " . $makedeps );
|
|
}
|
|
$makedeps =~ s/ +$//g;
|
|
|
|
my $checkdeps;
|
|
if ($meta) {
|
|
say "CPAN build deps: $makedeps";
|
|
say " CPAN build requires: "
|
|
. parse_deps(
|
|
$meta->effective_prereqs->requirements_for( 'configure', 'requires' ),
|
|
$meta->effective_prereqs->requirements_for( 'build', 'requires' )
|
|
);
|
|
say " CPAN build recommends: "
|
|
. parse_deps(
|
|
$meta->effective_prereqs->requirements_for( 'configure', 'recommends' ),
|
|
$meta->effective_prereqs->requirements_for( 'build', 'recommends' )
|
|
);
|
|
|
|
$checkdeps = parse_deps(
|
|
$meta->effective_prereqs->requirements_for( 'test', 'requires' ),
|
|
$meta->effective_prereqs->requirements_for( 'test', 'recommends' )
|
|
);
|
|
}
|
|
|
|
if ( defined $oldapkbuild->{'checkdepends'} ) {
|
|
if ( defined $oldapkbuild->{'cpancheckdepends'} ) {
|
|
$oldapkbuild->{'checkdepends'} =~
|
|
s/\$cpancheckdepends/$oldapkbuild->{'cpancheckdepends'}/g;
|
|
}
|
|
my @libs = split /\s+/, $oldapkbuild->{'checkdepends'};
|
|
if ( @libs ) {
|
|
my $libs = join ' ', grep { not (m/perl\-\w+[-\w+]+/) } @libs;
|
|
$checkdeps .= " " . $libs;
|
|
}
|
|
$checkdeps =
|
|
sort_pkgs_by_orig( $oldapkbuild->{'checkdepends'}, $checkdeps );
|
|
}
|
|
|
|
if ( defined $checkdeps && $checkdeps eq '' ) {
|
|
if (defined $oldapkbuild->{'checkdeps'} && ! $meta) {
|
|
$checkdeps = $oldapkbuild->{'checkdeps'};
|
|
}
|
|
} else {
|
|
$checkdeps = format_depends($checkdeps);
|
|
}
|
|
|
|
say "CPAN check deps: $checkdeps";
|
|
|
|
my $text = read_file "APKBUILD";
|
|
if ( $abstract && $abstract ne 'unknown' ) {
|
|
$abstract =~ s/"/\\"/g;
|
|
$abstract =~ s/[.\s]+$//;
|
|
|
|
$text =~ s/^pkgdesc=\"([^\"]*)\"$/pkgdesc=\"$abstract\"/mg
|
|
or die "Can't find pkgdesc line in APKBUILD";
|
|
}
|
|
|
|
if ( exists $oldapkbuild->{'arch'} ) {
|
|
# Prevent removal of empty arch variable for disabled aports
|
|
my $subst_arch = $oldapkbuild->{'arch'}
|
|
? '"' . $oldapkbuild->{'arch'} . '"'
|
|
: "";
|
|
|
|
$text =~ s/^arch=\"([^\"]*)\"$/arch=$subst_arch/mg
|
|
or die "Can't find arch line in APKBUILD";
|
|
} elsif ( $has_xs ) {
|
|
$text =~ s/^arch=\"([^\"]*)\"$/arch="all"/mg
|
|
or die "Can't find arch line in APKBUILD";
|
|
}
|
|
|
|
if ( defined $license && $license ne 'unknown' ) {
|
|
$text =~ s/^license=\"([^\"]*)\"$/license=\"$license\"/mg
|
|
or die "Can't find license line in APKBUILD";
|
|
}
|
|
$text =~ s/^depends=\"([^\"]*)\"$/depends=\"$deps\"/mg
|
|
or $text =~ s/(license=.*\n)/$1depends=\"$deps\"\n/gm
|
|
or die "Can't insert depends line in APKBUILD" if defined $deps;
|
|
|
|
$text =~ s/^makedepends=\"([^\"]*)\"$/makedepends=\"$makedeps\"/mg
|
|
or $text =~ s/(depends=.*\n)/$1makedepends=\"$makedeps\"\n/gm
|
|
or die "Can't insert makedepends line in APKBUILD" if defined $makedeps;
|
|
|
|
$text =~ s/^checkdepends=\"([^\"]*)\"$/checkdepends=\"$checkdeps\"/mg
|
|
or $text =~ s/(makedepends=.*\n)/$1checkdepends=\"$checkdeps\"\n/gm
|
|
or die "Can't insert checkdepends line in APKBUILD" if defined $checkdeps;
|
|
|
|
if (defined $builddir) {
|
|
print "\n\$builddir redefined:\n\tOLD: '", $apkbuild->{builddir},
|
|
"', NEW: '", $builddir, "'\n";
|
|
|
|
$text =~ s/^builddir=\"([^\"]*)\"/builddir="$builddir"/mg;
|
|
}
|
|
|
|
# remove empty variables
|
|
$text =~ s/.*="".{0,}\n//g;
|
|
|
|
open my $fh, '>', "APKBUILD" or die;
|
|
print $fh $text;
|
|
close $fh;
|
|
}
|
|
|
|
sub get_data {
|
|
my $apkbuild = read_apkbuild;
|
|
my $pkgreal = '';
|
|
|
|
if ( exists $apkbuild->{_realname} ) {
|
|
$pkgreal = $apkbuild->{_realname};
|
|
}
|
|
elsif ( exists $apkbuild->{_pkgreal} ) {
|
|
$pkgreal = $apkbuild->{_pkgreal};
|
|
}
|
|
elsif ( exists $apkbuild->{_pkgname} ) {
|
|
$pkgreal = $apkbuild->{_pkgname};
|
|
}
|
|
elsif ( exists $apkbuild->{_name} ) {
|
|
$pkgreal = $apkbuild->{_name};
|
|
}
|
|
elsif ( exists $apkbuild->{_realpkgname} ) {
|
|
$pkgreal = $apkbuild->{_realpkgname};
|
|
}
|
|
elsif ( exists $apkbuild->{_pkg_real} ) {
|
|
$pkgreal = $apkbuild->{_pkg_real};
|
|
}
|
|
else {
|
|
my $module = '';
|
|
my $distribution = '';
|
|
while ( ( my $key, my $value ) = each(%$apkbuild) ) {
|
|
|
|
# Do not parse any depends lines to not find incorrect module
|
|
if ( $key =~ m/.*depends.*/ ) {
|
|
next;
|
|
}
|
|
|
|
# Try to find a perl module name in APKBUILD
|
|
if ( $value =~ m/((\w+::)+\w+)/g ) {
|
|
|
|
# Match Perl Module names containing ::
|
|
$module .= "$1 " unless $module =~ m/$1/;
|
|
}
|
|
elsif ( $value =~ m/(([A-Z]\w+-)+\w+)/ ) {
|
|
|
|
# Match possible distribution names with -
|
|
$distribution .= "$1 " unless $distribution =~ m/ *$1 /;
|
|
}
|
|
elsif ( $value =~ m/.*release\/([A-Z]\w+).*/ ) {
|
|
|
|
# Match Single Word Perl Module Name after release in URL?
|
|
$distribution .= "$1 " unless $distribution =~ m/ *$1 /;
|
|
}
|
|
}
|
|
|
|
# Want to try the traditional Module::Name first
|
|
my $list = $module . $distribution;
|
|
foreach ( split / /, $list ) {
|
|
my $type = '';
|
|
if ( $_ =~ m/::/ ) {
|
|
$type = 'module';
|
|
}
|
|
else {
|
|
$type = 'release';
|
|
}
|
|
|
|
my $moddata;
|
|
eval { $moddata = query_metacpan( $type => $_ ); };
|
|
next if $@
|
|
or ref $moddata ne 'HASH'
|
|
or not $moddata->{distribution};
|
|
|
|
$pkgreal = $moddata->{distribution};
|
|
last;
|
|
}
|
|
}
|
|
|
|
$pkgreal =~ s/-\$pkgver//g;
|
|
|
|
my $distdata = query_metacpan( release => $pkgreal );
|
|
|
|
my $moddata = query_metacpan( module => $distdata->{main_module} );
|
|
|
|
return ( $apkbuild, $distdata, $moddata );
|
|
}
|
|
|
|
my $abuild_conf = read_assignments_from_file("/etc/abuild.conf");
|
|
$packager = $abuild_conf->{PACKAGER} if $abuild_conf->{PACKAGER};
|
|
|
|
my $user_abuild_conf =
|
|
read_assignments_from_file( $ENV{"HOME"} . "/.abuild/abuild.conf" );
|
|
$packager = $user_abuild_conf->{PACKAGER} if $user_abuild_conf->{PACKAGER};
|
|
|
|
my $command = $ARGV[0] // '';
|
|
|
|
if ( $command eq "create" ) {
|
|
my $module = $ARGV[1];
|
|
$module or die "Module name is a mandatory argument";
|
|
|
|
my $moddata = query_metacpan( module => $module );
|
|
|
|
my $distdata = query_metacpan( release => $moddata->{distribution} );
|
|
|
|
my $apkname = map_cpan_to_apk $distdata->{metadata}{name};
|
|
mkdir $apkname;
|
|
chdir $apkname;
|
|
write_apkbuild( $distdata, undef, $moddata );
|
|
prepare_tree;
|
|
update_functions;
|
|
do_depends $moddata->{version};
|
|
}
|
|
elsif ( $command eq "recreate" ) {
|
|
|
|
#TODO: likely should keep pkgrel the same on recreate
|
|
my ( $apkbuild, $distdata, $moddata ) = get_data;
|
|
my $pkgver = $moddata->{version} =~ s/^[^0-9]+//r;
|
|
if ( $pkgver ne $apkbuild->{pkgver} ) {
|
|
|
|
#Reset pkgrel on upgrade on recreate
|
|
say "Upgrading CPAN module from $apkbuild->{pkgver} to $pkgver";
|
|
$apkbuild->{pkgrel} = 0;
|
|
}
|
|
write_apkbuild( $distdata, $apkbuild, $moddata );
|
|
prepare_tree;
|
|
update_functions;
|
|
do_depends( $moddata->{version}, $apkbuild );
|
|
}
|
|
elsif ( $command eq "upgrade" ) {
|
|
my ( $apkbuild, $distdata, $moddata ) = get_data;
|
|
|
|
my $pkgver = $moddata->{version} =~ s/^[^0-9]+//r;
|
|
if ( $pkgver ne $apkbuild->{pkgver} ) {
|
|
say "Upgrading CPAN module from $apkbuild->{pkgver} to $pkgver";
|
|
|
|
my $text = read_file "APKBUILD";
|
|
$text =~ s/^pkgver=(.*)$/pkgver=$pkgver/mg
|
|
or die "Can't find pkgver line in APKBUILD";
|
|
$text =~ s/^pkgrel=(.*)$/pkgrel=0/mg;
|
|
|
|
#FIXME: review whether this works over time
|
|
# It deletes the blank line before the checksum
|
|
# So prepare_tree does not insert extra blank line
|
|
$text =~ s/\n^(.*sums=.*\n)/$1/mg;
|
|
open my $fh, '>', "APKBUILD" or die;
|
|
say $fh $text;
|
|
close $fh;
|
|
prepare_tree;
|
|
do_depends( $moddata->{version}, $apkbuild );
|
|
}
|
|
else {
|
|
say "Up-to-date with CPAN";
|
|
}
|
|
}
|
|
elsif ( $command eq "check" ) {
|
|
my ( $apkbuild, $distdata, $moddata ) = get_data;
|
|
my $pkgver = $moddata->{version} =~ s/^[^0-9]+//r;
|
|
say
|
|
"$apkbuild->{pkgname}: Latest version: $pkgver Packaged version: $apkbuild->{pkgver}";
|
|
if ( $pkgver ne $apkbuild->{pkgver} ) {
|
|
exit(1);
|
|
}
|
|
}
|
|
elsif ( $command eq "update" ) {
|
|
prepare_tree;
|
|
do_depends;
|
|
}
|
|
else {
|
|
say
|
|
"Usage: apkbuild-cpan [create <Module::Name> | check | recreate | update | upgrade]";
|
|
exit;
|
|
}
|