abuild/apkbuild-cpan.in
Natanael Copa 122bcd7cb2 apkbuild-cpan: remove prepare function from APKBUILD
the generation of Makefile is comparable with running configure, which
we normally do in the build() function, not in prepare.

also fix some whitespace damamge.
2019-03-21 11:34:06 +01:00

379 lines
11 KiB
Perl

#!/usr/bin/perl
# apk add perl-libwww perl-json
use strict;
use warnings;
use 5.016;
use feature "switch";
no if $] >= 5.018, warnings => "experimental::smartmatch";
use LWP::UserAgent;
use LWP::ConnCache;
use CPAN::Meta;
use Module::CoreList;
use JSON;
my $license_mappings = {
"perl_5" => "GPL PerlArtistic",
"artistic_2" => "Artistic-2",
};
my $package_mappings = {
"LWP" => "perl-libwww",
"TermReadKey" => "perl-term-readkey",
};
our $packager = "";
my $template = <<'EOF';
# Automatically generated by apkbuild-cpan, template 2
[% authors %]
pkgname=[% pkgname %]
_pkgreal=[% pkgreal %]
pkgver=[% pkgver %]
pkgrel=0
pkgdesc="Perl module for [% pkgreal %]"
url="https://metacpan.org/release/[% pkgreal %]/"
arch="noarch"
license="GPL PerlArtistic"
cpandepends=""
cpanmakedepends=""
cpancheckdepends=""
depends="$cpandepends"
makedepends="perl-dev $cpanmakedepends"
checkdepends="$cpancheckdepends"
subpackages="$pkgname-doc"
source="[% source %]"
builddir="$srcdir/$_pkgreal-$pkgver"
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 );
my $authors = join("\n", $text =~ /^# Contributor: .*$/mg, $text =~ /^# Maintainer: .*$/mg);
$hash{'authors'} = $authors if length($authors) > 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 write_apkbuild {
my ($distdata, $authors, $moddata) = @_;
my $cpanid = $distdata->{id};
$cpanid = substr($cpanid, 0, 1) . "/" . substr($cpanid, 0, 2) . "/$cpanid";
my %repl = (
authors => ($authors or "# Contributor: $packager\n# Maintainer: $packager"),
pkgname => map_cpan_to_apk($moddata->{distribution}),
pkgreal => $moddata->{distribution},
pkgver => $moddata->{version},
source => $moddata->{download_url},
);
$template =~ s/\[% (.*?) %\]/$repl{$1}/g;
open my $fh, '>', "APKBUILD" or die;
print $fh $template;
close $fh;
say "Wrote $repl{pkgname}/APKBUILD";
}
sub parse_deps {
my ($reqs) = @_;
my $distfiles = {};
my $response;
my $deps = "";
for my $module ($reqs->required_modules) {
if (my $perlver = Module::CoreList->first_release($module)) {
say "$module is part of core perl since $perlver.";
next;
}
next if $module eq 'perl';
# map module name to package name
$response = $ua->get("https://fastapi.metacpan.org/module/$module");
$response->is_success or die $response->status_line;
my $moddata = $json->decode($response->decoded_content);
$moddata->{error} and die "Error trying to locate $module: $moddata->{error}\n";
$distfiles->{$moddata->{distribution}} = $moddata;
}
# map package names to alpine packages
foreach ( keys %{ $distfiles } ) {
$response = $ua->get("https://fastapi.metacpan.org/release/$_");
$response->is_success or die $response->status_line;
my $distdata = $json->decode($response->decoded_content);
$distdata->{error} and die "Error trying to locate $_: $distdata->{error}\n";
my $pkgname = map_cpan_to_apk($distdata->{name});
$deps .= "$pkgname ";
}
$deps =~ s/\h+/ /g;
$deps =~ s/ $//;
return $deps;
}
sub prepare_tree {
system("abuild checksum unpack prepare") == 0 or
die "abuild checksum failed";
}
sub update_functions {
my $apkbuild = read_apkbuild;
my $metaprefix = "src/" . $apkbuild->{'_pkgreal'} . "-" . $apkbuild->{'pkgver'} . "/";
my $build_func;
my $check_func;
my $package_func;
my $text = read_file "APKBUILD";
if (-e "$metaprefix/Build.PL" ) {
$build_func = <<'EOF';
build() {
cd "$builddir"
export CFLAGS=$(perl -MConfig -E 'say $Config{ccflags}')
perl Build.PL installdirs=vendor
./Build
}
EOF
$package_func = <<'EOF';
package() {
cd "$builddir"
./Build install destdir="$pkgdir"
find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
}
EOF
$check_func = <<'EOF';
check() {
cd "$builddir"
./Build test
}
EOF
} else {
$build_func = <<'EOF';
build() {
cd "$builddir"
export CFLAGS=$(perl -MConfig -E 'say $Config{ccflags}')
PERL_MM_USE_DEFAULT=1 perl -I. Makefile.PL INSTALLDIRS=vendor
make
}
EOF
$package_func = <<'EOF';
package() {
cd "$builddir"
make DESTDIR="$pkgdir" install
find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
}
EOF
$check_func = <<'EOF';
check() {
cd "$builddir"
export CFLAGS=$(perl -MConfig -E 'say $Config{ccflags}')
make test
}
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 do_depends {
my $apkbuild = read_apkbuild;
my $metaprefix = "src/" . $apkbuild->{'_pkgreal'} . "-" . $apkbuild->{'pkgver'} . "/";
my $meta;
foreach my $metafile ("MYMETA.json", "META.json", "MYMETA.yml", "META.yml") {
if (-e "$metaprefix$metafile") {
say "Using meta information from $metafile";
$meta = CPAN::Meta->load_file("$metaprefix$metafile");
last;
}
}
die "No dependency meta file found" unless $meta;
my $abstract = $meta->abstract;
say "Abstract: $abstract";
my $license = join " ", map {$license_mappings->{$_} or $_} $meta->license;
say "License: $license";
my $deps = parse_deps $meta->effective_prereqs->requirements_for('runtime', 'requires');
say "CPAN deps: $deps";
say "Recommend: " . parse_deps $meta->effective_prereqs->requirements_for('runtime', 'recommends');
my $makedeps = parse_deps($meta->effective_prereqs->requirements_for('build', 'requires'), $meta->effective_prereqs->requirements_for('build', 'recommends'));
say "CPAN build deps: $makedeps";
say "CPAN requires: " . parse_deps($meta->effective_prereqs->requirements_for('build', 'requires'));
say "CPAN recommds: " . parse_deps($meta->effective_prereqs->requirements_for('build', 'recommends'));
my $checkdeps = parse_deps($meta->effective_prereqs->requirements_for('test', 'requires'), $meta->effective_prereqs->requirements_for('test', 'recommends'));
say "CPAN check deps: $makedeps";
my $text = read_file "APKBUILD";
if ($abstract) {
$text =~ s/^pkgdesc=\"([^\"]*)\"$/pkgdesc=\"$abstract\"/mg or
die "Can't find cpandepends line in APKBUILD";
}
if (length(`find $metaprefix -name '*.xs'`)) {
$text =~ s/^arch=\"([^\"]*)\"$/arch="all"/mg or
die "Can't find arch line in APKBUILD";
}
if ($license ne 'unknown') {
$text =~ s/^license=\"([^\"]*)\"$/license=\"$license\"/mg or
die "Can't find license line in APKBUILD";
}
$text =~ s/^cpandepends=\"([^\"]*)\"$/cpandepends=\"$deps\"/mg or
die "Can't find cpandepends line in APKBUILD";
$text =~ s/^cpanmakedepends=\"([^\"]*)\"$/cpanmakedepends=\"$makedeps\"/mg or
die "Can't find cpanmakedepends line in APKBUILD";
$text =~ s/^cpancheckdepends=\"([^\"]*)\"$/cpancheckdepends=\"$checkdeps\"/mg or
die "Can't find cpancheckdepends line in APKBUILD";
open my $fh, '>', "APKBUILD" or die;
print $fh $text;
close $fh;
}
sub get_data {
my $apkbuild = read_apkbuild;
$apkbuild->{_pkgreal} or die "Not apkbuild-cpan generated APKBUILD";
my $response = $ua->get("https://fastapi.metacpan.org/release/$apkbuild->{_pkgreal}");
$response->is_success or die $response->status_line;
my $distdata = $json->decode($response->decoded_content);
$distdata->{error} and die "Error trying to locate $apkbuild->{_pkgreal}: $distdata->{error}\n";
$response = $ua->get("https://fastapi.metacpan.org/module/$distdata->{main_module}");
$response->is_success or die $response->status_line;
my $moddata = $json->decode($response->decoded_content);
$moddata->{error} and die "Error trying to locate $distdata->{main_module}: $moddata->{error}\n";
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};
given ( $ARGV[0] ) {
when ("create") {
my $module = $ARGV[1];
my $response;
$module or die "Module name is a mandatory argument";
$response = $ua->get("https://fastapi.metacpan.org/module/$module");
$response->is_success or die $response->status_line;
my $moddata = $json->decode($response->decoded_content);
$moddata->{error} and die "Error trying to locate $module: $moddata->{error}\n";
$response = $ua->get("https://fastapi.metacpan.org/release/$moddata->{distribution}");
$response->is_success or die $response->status_line;
my $distdata = $json->decode($response->decoded_content);
$distdata->{error} and die "Error trying to locate $module: $distdata->{error}\n";
my $apkname = map_cpan_to_apk $distdata->{metadata}{name};
mkdir $apkname;
chdir $apkname;
write_apkbuild($distdata, undef, $moddata);
prepare_tree;
update_functions;
do_depends;
}
when ("recreate") {
my ($apkbuild, $distdata, $moddata) = get_data;
write_apkbuild($distdata, $apkbuild->{authors}, $moddata);
prepare_tree;
update_functions;
do_depends;
}
when ("upgrade") {
my ($apkbuild, $distdata, $moddata) = get_data;
my $pkgver = $moddata->{version};
if ($pkgver != $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;
open my $fh, '>', "APKBUILD" or die;
say $fh $text;
close $fh;
prepare_tree;
do_depends;
} else {
say "Up-to-data with CPAN";
}
}
when ('check') {
my ($apkbuild, $distdata, $moddata) = get_data;
my $pkgver = $moddata->{version};
say "$apkbuild->{pkgname}: Latest version: $pkgver Packaged version: $apkbuild->{pkgver}";
if ($pkgver ne $apkbuild->{pkgver}) {
exit(1);
}
}
when ("update") {
prepare_tree;
do_depends;
}
default {
say "Usage: apkbuild-cpan [create <Module::Name> | check | recreate | update | upgrade]";
exit;
}
}