summaryrefslogtreecommitdiffstats
path: root/apkbuild-cpan.in
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2011-06-02 11:55:00 +0300
committerTimo Teräs <timo.teras@iki.fi>2011-06-02 11:55:00 +0300
commitf670c88e530965eeb0b7c3bae5640cab69344883 (patch)
tree699bdb7d95e509debe604414ed28f53cf419bdaa /apkbuild-cpan.in
parent7f122b77e87fd69ec26afba2b022f2a1d4b33e7c (diff)
downloadabuild-f670c88e530965eeb0b7c3bae5640cab69344883.tar.bz2
abuild-f670c88e530965eeb0b7c3bae5640cab69344883.tar.xz
apkbuild-cpan: new tool superceding newapkbuild-cpan tool
Based on Aerdan's original work, this is a perl utility that interacts with CPAN which can create and update APKBUILDs with proper metadata info.
Diffstat (limited to 'apkbuild-cpan.in')
-rwxr-xr-xapkbuild-cpan.in336
1 files changed, 336 insertions, 0 deletions
diff --git a/apkbuild-cpan.in b/apkbuild-cpan.in
new file mode 100755
index 0000000..75e7dd0
--- /dev/null
+++ b/apkbuild-cpan.in
@@ -0,0 +1,336 @@
+#!/usr/bin/perl
+# apk add perl-libwww perl-json
+
+use strict;
+use warnings;
+use feature qw(:5.10);
+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 1
+# Contributor: [% packager %]
+# Maintainer: [% packager %]
+pkgname=[% pkgname %]
+_pkgreal=[% pkgreal %]
+pkgver=[% pkgver %]
+pkgrel=0
+pkgdesc="Perl module for [% pkgreal %]"
+url="http://search.cpan.org/dist/[% pkgreal %]/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="[% source %]"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ if [ -e Build.PL ]; then
+ perl Build.PL installdirs=vendor || return 1
+ else
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ fi
+}
+
+build() {
+ :
+}
+
+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) = @_;
+ 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;
+}
+
+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) = @_;
+
+ my $cpanid = $distdata->{releases}[0]->{cpanid};
+ $cpanid = substr($cpanid, 0, 1) . "/" . substr($cpanid, 0, 2) . "/$cpanid";
+ my %repl = (
+ packager => $packager,
+ pkgname => map_cpan_to_apk($distdata->{name}),
+ pkgreal => $distdata->{name},
+ pkgver => $distdata->{releases}[0]->{version},
+ source => "http://search.cpan.org/CPAN/authors/id/$cpanid/\$_pkgreal-\$pkgver.tar.gz",
+ );
+ $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("http://search.cpan.org/api/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->{distvname}} = $moddata;
+ }
+
+ # map package names to alpine packages
+ foreach ( keys $distfiles ) {
+ $response = $ua->get("http://search.cpan.org/api/dist/$_");
+ $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/\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 $prepare_func;
+ my $build_func;
+ my $package_func;
+
+ my $text = read_file "APKBUILD";
+ if (-e "$metaprefix/Build.PL" ) {
+ $prepare_func = <<'EOF';
+prepare() {
+ cd "$_builddir"
+ perl Build.PL installdirs=vendor || return 1
+}
+EOF
+ $build_func = <<'EOF';
+build() {
+ cd "$_builddir"
+ ./Build && ./Build test
+}
+EOF
+ $package_func = <<'EOF';
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+EOF
+ } else {
+ $prepare_func = <<'EOF';
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+EOF
+ $build_func = <<'EOF';
+build() {
+ cd "$_builddir"
+ make && make test
+}
+EOF
+ $package_func = <<'EOF';
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+EOF
+ }
+
+ $text =~ s/^prepare\(\) \{.*?^\}\n/$prepare_func/smg or
+ die "Can't replace prepare function APKBUILD";
+ $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";
+
+ 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";
+
+ my $makedeps = parse_deps $meta->effective_prereqs->requirements_for('build', 'requires');
+ say "CPAN build deps: $makedeps";
+
+ my $text = read_file "APKBUILD";
+ if ($abstract) {
+ $text =~ s/^pkgdesc=\"([^\"]*)\"$/pkgdesc=\"$abstract\"/mg or
+ die "Can't find cpandepends line in APKBUILD";
+ }
+ $text =~ s/^license=\"([^\"]*)\"$/license=\"$license\"/mg or
+ die "Can't find cpandepends 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";
+
+ open my $fh, '>', "APKBUILD" or die;
+ print $fh $text;
+ close $fh;
+}
+
+my $abuild_conf = read_assignments_from_file("/etc/abuild.conf");
+$packager = $abuild_conf->{PACKAGER} if $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("http://search.cpan.org/api/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("http://search.cpan.org/api/dist/$moddata->{distvname}");
+ $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->{name};
+ mkdir $apkname;
+ chdir $apkname;
+ write_apkbuild($distdata);
+ prepare_tree;
+ update_functions;
+ do_depends;
+ }
+ when ("recreate") {
+ my $apkbuild = read_apkbuild;
+ my $response = $ua->get("http://search.cpan.org/api/dist/$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";
+
+ write_apkbuild($distdata);
+ prepare_tree;
+ update_functions;
+ do_depends;
+ }
+ when ("upgrade") {
+ my $apkbuild = read_apkbuild;
+ my $response = $ua->get("http://search.cpan.org/api/dist/$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";
+
+ my $pkgver = $distdata->{releases}[0]->{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 ("update") {
+ prepare_tree;
+ do_depends;
+ }
+ default {
+ say "Usage: apkbuild-cpan [create <Module::Name> | recreate | upgrade | update]";
+ exit;
+ }
+}