mirror of
https://gitlab.alpinelinux.org/alpine/abuild.git
synced 2025-03-31 23:59:12 +00:00
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.
This commit is contained in:
parent
7f122b77e8
commit
f670c88e53
2
Makefile
2
Makefile
@ -12,7 +12,7 @@ LUA_SHAREDIR ?= $(prefix)/share/lua/$(LUA_VERSION)/
|
||||
|
||||
SCRIPTS := abuild devbuild buildrepo abuild-keygen \
|
||||
abuild-sign newapkbuild abump apkgrel ap buildlab \
|
||||
newapkbuild-cpan
|
||||
apkbuild-cpan
|
||||
USR_BIN_FILES := $(SCRIPTS) abuild-tar
|
||||
SAMPLES := sample.APKBUILD sample.initd sample.confd \
|
||||
sample.pre-install sample.post-install
|
||||
|
336
apkbuild-cpan.in
Executable file
336
apkbuild-cpan.in
Executable file
@ -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;
|
||||
}
|
||||
}
|
@ -1,196 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# script to generate a new APKBUILD
|
||||
# Copyright (c) 2009 Natanael Copa <natanael.copa@gmail.com>
|
||||
#
|
||||
# Distributed under GPL-2
|
||||
#
|
||||
# Depends on: busybox utilities, fakeroot,
|
||||
#
|
||||
|
||||
version=@VERSION@
|
||||
sysconfdir=@sysconfdir@
|
||||
datadir=@datadir@
|
||||
|
||||
prog=${0##*/}
|
||||
|
||||
# source $PACKAGER
|
||||
for i in $sysconfdir/abuild.conf $HOME/.abuild/abuild.conf; do
|
||||
if [ -f "$i" ]; then
|
||||
. $i
|
||||
fi
|
||||
done
|
||||
|
||||
error() {
|
||||
echo "$@" >&2
|
||||
}
|
||||
|
||||
is_url() {
|
||||
case "$1" in
|
||||
http://*|ftp://*) return 0;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
get_cpan_source() {
|
||||
local mod="$1"
|
||||
wget -q -O - http://search.cpan.org/dist/$mod/ \
|
||||
| grep "href.*$mod-[0-9].*Download" \
|
||||
| sed "s|.*href=\"\(.*\)\".*|http://search.cpan.org\1|"
|
||||
}
|
||||
|
||||
# create new aport from templates
|
||||
newaport() {
|
||||
local newname= pv= source= pn= mod=
|
||||
|
||||
if is_url "$1"; then
|
||||
source="$1"
|
||||
newname="${1##*/}"
|
||||
mod=$(echo $pn | sed 's/-/::/g')
|
||||
else
|
||||
if echo $1 | grep -q '::'; then
|
||||
mod=$1
|
||||
pn=$(echo $mod | sed 's/::/-/g')
|
||||
else
|
||||
pn=$1
|
||||
mod=$(echo $pn | sed 's/-/::/g')
|
||||
fi
|
||||
source=$(get_cpan_source $pn)
|
||||
newname="${source##*/}"
|
||||
fi
|
||||
if [ -z "$source" ]; then
|
||||
error "source not found"
|
||||
exit 1
|
||||
fi
|
||||
pn=${newname%-[0-9]*}
|
||||
pv=${newname#$pn-}
|
||||
|
||||
if [ "$pn" != "$newname" ]; then
|
||||
pv=${newname#$pn-}
|
||||
pv=${pv%.t*} #strip .tar.gz .tgz .tar.bz2 etc
|
||||
fi
|
||||
pkgname=perl-$(echo $pn | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz')
|
||||
|
||||
if [ -e "$pkgname"/APKBUILD ] && [ -z "$force" ]; then
|
||||
error "$pkgname/APKBUILD already exist"
|
||||
return 1
|
||||
fi
|
||||
mkdir -p "$pkgname"
|
||||
cd "$pkgname"
|
||||
|
||||
# replace pkgver in $source
|
||||
if [ -n "$source" ]; then
|
||||
source=$(echo "$source" | sed "s/$pv/\$pkgver/g")
|
||||
fi
|
||||
|
||||
if [ -z "$url" ]; then
|
||||
url="http://search.cpan.org/dist/$pn/"
|
||||
fi
|
||||
|
||||
if [ -z "$license" ]; then
|
||||
license="GPLv2 or Artistic"
|
||||
fi
|
||||
|
||||
if [ -z "$pkgdesc" ]; then
|
||||
pkgdesc="$mod perl module"
|
||||
fi
|
||||
|
||||
# generate header with standard variables
|
||||
cat >APKBUILD<<__EOF__
|
||||
# Contributor:${PACKAGER:+" "}${PACKAGER}
|
||||
# Maintainer:${MAINTAINER:+" "}${MAINTAINER}
|
||||
pkgname=$pkgname
|
||||
pkgver=$pv
|
||||
pkgrel=0
|
||||
pkgdesc="$pkgdesc"
|
||||
url="$url"
|
||||
arch="noarch"
|
||||
license="$license"
|
||||
depends="perl"
|
||||
makedepends="perl-dev"
|
||||
install="$install"
|
||||
subpackages="\$pkgname-doc"
|
||||
source="$source"
|
||||
|
||||
__EOF__
|
||||
|
||||
abuild -f fetch unpack
|
||||
# figure out the _builddir
|
||||
for i in src/*; do
|
||||
if [ -d "$i" ]; then
|
||||
sdir=$i
|
||||
_builddir=$(echo ${i#*/} | sed "s/$pv/\$pkgver/g")
|
||||
_builddir="\"\$srcdir\"/$_builddir"
|
||||
fi
|
||||
done
|
||||
echo "_builddir=$_builddir" >> APKBUILD
|
||||
|
||||
# create the prepare() template
|
||||
cat >>APKBUILD<<__EOF__
|
||||
prepare() {
|
||||
local i
|
||||
cd "\$_builddir"
|
||||
for i in \$source; do
|
||||
case \$i in
|
||||
*.patch) msg \$i; patch -p1 -i "\$srcdir"/\$i || return 1;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
__EOF__
|
||||
|
||||
# create build()
|
||||
cat >>APKBUILD<<__EOF__
|
||||
build() {
|
||||
cd "\$_builddir"
|
||||
PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
|
||||
make && make test || return 1
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "\$_builddir"
|
||||
make DESTDIR="\$pkgdir" install || return 1
|
||||
find "\$pkgdir" \\( -name perllocal.pod -o -name .packlist \\) -delete
|
||||
}
|
||||
|
||||
__EOF__
|
||||
abuild -r checksum all
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "$prog $version"
|
||||
echo "usage: $prog [-cfh] [-d DESC] [-l LICENSE] [-u URL] PKGNAME[-PKGVER]"
|
||||
echo "Options:"
|
||||
echo " -a Create autotools (use ./configure ...)"
|
||||
echo " -c Copy a sample init.d, conf.d and install script to new directory"
|
||||
echo " -d Set package description (pkgdesc) to DESC"
|
||||
echo " -f Force even if directory already exist"
|
||||
echo " -h Show this help"
|
||||
echo " -l Set package license to LICENSE"
|
||||
echo " -p Create perl package (Assume Makefile.PL is there)"
|
||||
echo " -u Set package URL"
|
||||
echo " -s Use sourceforge source url"
|
||||
echo ""
|
||||
exit 0
|
||||
}
|
||||
|
||||
while getopts "acd:fhl:pu:s" opt; do
|
||||
case $opt in
|
||||
'a') buildtype="autotools";;
|
||||
'c') cpinitd=1;;
|
||||
'd') pkgdesc="$OPTARG";;
|
||||
'f') force=1;;
|
||||
'h') usage;;
|
||||
'l') license="$OPTARG";;
|
||||
'p') buildtype="perl";;
|
||||
'u') url="$OPTARG";;
|
||||
's') sourceforge=1;;
|
||||
esac
|
||||
done
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
(newaport $1) || exit 1
|
||||
shift
|
||||
done
|
||||
|
Loading…
Reference in New Issue
Block a user