diff options
author | Justin Davis <jrcd83@gmail.com> | 2011-08-14 21:15:27 +0200 |
---|---|---|
committer | Justin Davis <jrcd83@gmail.com> | 2011-08-14 21:15:27 +0200 |
commit | 01da7f81b3d6924d5a9a25d804a3905c6fd616ed (patch) | |
tree | 5483bc3d6dca6a45addae0710ce82d1410a343c4 | |
download | genpkg-01da7f81b3d6924d5a9a25d804a3905c6fd616ed.tar.gz genpkg-01da7f81b3d6924d5a9a25d804a3905c6fd616ed.tar.xz |
Initial commit.
-rw-r--r-- | .gitignore | 1 | ||||
-rwxr-xr-x | bin/macros/perl-cpan | 42 | ||||
-rwxr-xr-x | bin/macros/perl-dist | 552 | ||||
-rwxr-xr-x | bin/pbj | 58 | ||||
-rwxr-xr-x | bin/pbjparse.awk | 119 | ||||
-rwxr-xr-x | bin/templ/perl-pkg | 145 | ||||
-rw-r--r-- | pbj/perl-moose.pbj | 4 |
7 files changed, 921 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b25c15b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/bin/macros/perl-cpan b/bin/macros/perl-cpan new file mode 100755 index 0000000..810ad8d --- /dev/null +++ b/bin/macros/perl-cpan @@ -0,0 +1,42 @@ +#!/Users/juster/perl5/perlbrew/perls/perl-5.14.1/bin/perl + +use warnings 'FATAL' => 'all'; +use strict; + +use LWP::UserAgent; +use IO::Handle; # for autoflush + +my $dist = shift or die "Usage: $0 [CPAN dist name]\n"; +my $url = "http://search.cpan.org/dist/$dist"; +my $ua = LWP::UserAgent->new(); +my $resp = $ua->get($url); + +die "$0: GET $url failed: ", $resp->status_line, "\n" + unless $resp->is_success; + +$resp = $resp->content; +my ($href) = $resp =~ m{\[<a href="([^"]+)">Download</a>\]} + or die "$0: no download link found at $url\n"; + +unless (-d 'src') { + mkdir 'src' or die "$0: mkdir src: $!" +} + +my $file = $href; +$file =~ s{\A.*/}{}; +$href = "http://search.cpan.org" . $href; + +STDERR->autoflush(1); +print STDERR "Downloading $file... "; +$resp = $ua->get($href, ':content_file' => "src/$file"); +die "$0: download of $file failed: ", $resp->status_line + unless $resp->is_success; +print STDERR "OK\n"; + +print "+ url $url\n"; +print "+ source $href\n"; +system "perl-dist src/$file"; +if ($? != 0) { + printf STDERR "$0: failed to run perl-dist%s\n", ($! ? " ($!)" : q{}); + exit 1; +} diff --git a/bin/macros/perl-dist b/bin/macros/perl-dist new file mode 100755 index 0000000..dc62ec8 --- /dev/null +++ b/bin/macros/perl-dist @@ -0,0 +1,552 @@ +#!/Users/juster/perl5/perlbrew/perls/perl-5.14.1/bin/perl + +use warnings 'FATAL' => 'all'; +use strict; + +package Convert; + +use Module::CoreList; +use LWP::UserAgent qw(); +use YAML::XS qw(); +use version qw(); + +sub dist2pkg +{ + my ($name, $ver) = @_; + return dist_pkgname($name), dist_pkgver($ver); +} + +# Copied from CPANPLUS::Dist::Arch +sub dist_pkgname +{ + my ($distname) = @_; + + # Package names should be lowercase and consist of alphanumeric + # characters only (and hyphens!)... + $distname = lc $distname; + $distname =~ tr/_+/--/; + $distname =~ tr/-a-z0-9//cd; # Delete all other chars + $distname =~ tr/-/-/s; + + # Delete leading or trailing hyphens... + $distname =~ s/\A-//; + $distname =~ s/-\z//; + + die qq{Dist name '$distname' completely violates packaging standards} + if length $distname == 0; + + # Don't prefix the package with perl- if it IS perl... + $distname = "perl-$distname" unless $distname eq 'perl'; + + return $distname; +} + +sub dist_pkgver +{ + my ($version) = @_; + + # Package versions should be numbers and decimal points only... + $version =~ tr/-/./; + $version =~ tr/_0-9.//cd; + + # Remove developer versions because pacman has no special logic + # to handle comparing them to regular versions like perl does. + $version =~ s/_\d+\z//; + + $version =~ tr/././s; + $version =~ s/^[.]|[.]$//g; + + return $version; +} + +#---HELPER FUNCTION--- +# Decide if the dist. is named after the module. +sub _ismainmod +{ + my ($mod_name, $dist_name) = @_; + + $mod_name =~ tr/:/-/s; + return (lc $mod_name) eq (lc $dist_name); +} + +#---HELPER FUNCTION--- +# Merges the right-hand deps into the left-hand deps. +sub _merge +{ + my ($left_deps, $right_deps) = @_; + + MERGE_LOOP: + while ( my ($pkg, $ver) = each %$right_deps ) { + if ( $left_deps->{$pkg} ) { + my $leftver = version->parse($left_deps->{$pkg}); + my $rightver = version->parse($ver); + next MERGE_LOOP if $leftver > $rightver; + } + $left_deps->{$pkg} = $ver; + } + + return; +} + +#---HELPER FUNCTION--- +# Merge duplicate deps into $left always storing the greatest version there. +sub _mergedups +{ + my ($left, $right) = @_; + + for my $name (keys %$left) { + my $rver = $right->{$name} or next; + my $lver = $left->{$name}; + my $lvo = ($lver ? version->parse($lver) : 0); + my $rvo = ($rver ? version->parse($rver) : 0); + $left->{$name} = ($lvo > $rvo ? $lvo : $rvo); + } + + return; +} + +#---HELPER FUNCTION--- +sub _yankcheckers +{ + my ($deps_ref) = @_; + my %checkdeps; + + for my $testdep (grep { /perl-test-/ } keys %$deps_ref) { + my $val = delete $deps_ref->{$testdep}; + $checkdeps{$testdep} = $val if $val; + } + + # Also extract Pod::Coverage module into checkdepends + for my $dep ( qw/ perl-pod-coverage / ) { + my $val = delete $deps_ref->{$dep}; + $checkdeps{$dep} = $val if $val; + } + + return \%checkdeps; +} + +#---HELPER FUNCTION--- +# Converts a decimal perl version (like $]) into the dotted decimal +# form that the official ArchLinux perl package uses. +sub _perldepver +{ + my ($perlver) = @_; + + # Fix perl-style vstrings which have a leading "v". + return $perlver if $perlver =~ s/\Av//; + return $perlver unless $perlver =~ /\A(\d+)[.](\d{3})(\d{1,3})\z/; + + # Re-apply the missing trailing zeroes. + my $patch = $3; + $patch .= q{0} x (3 - length($patch)); + return sprintf '%d.%d.%d', $1, $2, $patch; +} + +#---PUBLIC FUNCNTION--- +# Translates CPAN module dependencies into ArchLinux package dependencies. +sub _reqs2deps +{ + my ($prereqs) = @_; + + my %pkgdeps; + + CPAN_DEP_LOOP: + while (my ($name, $ver) = each %$prereqs) { + # Sometimes a perl version is given as a prerequisite + if ($name eq 'perl') { + $pkgdeps{'perl'} = _perldepver($ver); + next CPAN_DEP_LOOP; + } + +# Ideally we could take advantage of the perl package's provides list +# and add dependencies for core modules. + +# This is more robust and handles the problem of packages built +# with a different version of perl than the perl that is present +# when the package is installed. + +# The problem is that the perl package provides list still needs work. +# While I was trying to generate a provides list I noticed the +# Module::CoreList module had some incorrect version numbers +# as well. So until I get around to reporting these bugs I will +# just go back to not depending on packages provided by perl. + + # 0+$] is needed to force the perl version into number-dom + # otherwise trailing zeros cause problems + my $bundled_version = $Module::CoreList::version{ 0 + $] }->{$name}; + if ($bundled_version) { + # Avoid parsing an empty string (causes an error) or 0. + next CPAN_DEP_LOOP unless $ver; + + # Avoid parsing a bundled version of 0. Is this possible? + my $bundle_vobj = version->parse($bundled_version); + my $dep_vobj = version->parse($ver); + next CPAN_DEP_LOOP if $bundle_vobj >= $dep_vobj; + } + + my $dist = _distofmod($name); + my $pkgname = dist_pkgname($dist); + + # If the module is not named after the distribution, ignore its + # version which might not match the distribution. + undef $ver unless _ismainmod($name, $dist); + + # If two module prereqs are in the same CPAN distribution then + # the version required for the main module will override. + # (because versions specified for other modules in the dist + # are 0) + $pkgdeps{$pkgname} ||= ($ver ? dist_pkgver($ver) : 0); + } + + return \%pkgdeps; +} + +sub prereqs +{ + my ($pkgname, $prereqs) = @_; + + # maps perl names for different dependencies to ArchLinux's names + my %namemap = ('configure' => 'makedepends', + 'build' => 'makedepends', + 'testing' => 'checkdepends', + 'runtime' => 'depends'); + + my %pkgdeps; + while (my ($perl, $arch) = each %namemap) { + $pkgdeps{$arch} ||= {}; + my $reqs = $prereqs->{$perl}{'requires'}; + my $deps = _reqs2deps($reqs) if $reqs; + _merge($pkgdeps{$arch}, $deps) if $deps; + } + + # ArchLinux now has a separate array for dependencies that we only + # need for checking (aka "testing"). Older perl METAs do not + # have this separated. Force any test modules to be checkdepends. + if (!$pkgdeps{'checkdepends'} && $pkgname !~ /\Aperl-test-/) { + my $checkdeps; + my $makedeps = $pkgdeps{'makedepends'}; + _merge($checkdeps, _yankcheckers($makedeps)); + $pkgdeps{'checkdepends'} = $checkdeps; + } + + # We at least require perl, if nothing else. + unless (grep { scalar keys %$_ > 0 } values %pkgdeps) { + $pkgdeps{'depends'}{'perl'} = 0; + } + + _mergedups(@pkgdeps{qw/makedepends checkdepends/}); + _mergedups(@pkgdeps{qw/depends makedepends/}); + + # Convert all deps into arrays of strings. + for my $deptype (keys %pkgdeps) { + $pkgdeps{$deptype} = _stringify($pkgdeps{$deptype}); + } + + return \%pkgdeps; +} + +#---HELPER FUNCTION--- +sub _stringify +{ + my ($deps) = @_; + + my @depstrs; + for my $pkg (sort keys %$deps) { + my $ver = $deps->{$pkg}; + my $str = ($ver eq '0' ? $pkg : "$pkg>=$ver"); + push @depstrs, $str; + } + + return \@depstrs; +} + +my $UA; +sub _distofmod +{ + my ($mod) = @_; + + my $UA ||= LWP::UserAgent->new(); + my $url = "http://cpanmetadb.appspot.com/v1.0/package/$mod"; + my $resp = $UA->get($url); + die "failed to lookup dist for $mod: " . $resp->status_line + unless $resp->is_success; + + $resp = YAML::XS::Load($resp->content); + my $file = $resp->{'distfile'}; + $file =~ s{.*/}{}; + $file =~ s{-[^-]+\z}{}; + + return $file; +} + +#----------------------------------------------------------------------------- + +package main; + +use File::Basename qw(basename dirname); +use File::Spec::Functions qw(catfile); +use File::Find qw(find); + +use JSON::XS qw(decode_json); # parse META.{json,yml} files +use YAML::XS qw(); +use Pod::Select qw(); # search POD for description + +use Digest::MD5 qw(); # for md5sums & sha512sums +use Digest::SHA qw(); + +# Override a package's name to conform to packaging guidelines. +# Copied entries from CPANPLUS::Dist::Pacman and alot more +# from searching for packages with perl in their name in +# [extra] and [community] +my $NAME_OVERRIDES = +{ map { split /[\s=]+/ } split /\s*\n+\s*/, <<'END_OVERRIDES' }; + +libwww-perl = perl-libwww +aceperl = perl-ace +mod_perl = mod_perl + +glade-perl-two = perl-glade-two +Gnome2-GConf = gconf-perl +Gtk2-GladeXML = glade-perl +Glib = glib-perl +Gnome2 = gnome-perl +Gnome2-VFS = gnome-vfs-perl +Gnome2-Canvas = gnomecanvas-perl +Gnome2-GConf = gconf-perl +Gtk2 = gtk2-perl +Cairo = cairo-perl +Pango = pango-perl + +SDL_Perl = sdl_perl +Perl-Critic = perl-critic +Perl-Tidy = perl-tidy +App-Ack = ack +TermReadKey = perl-term-readkey + +END_OVERRIDES + +sub main +{ + my $distpath = shift or die "Usage: $0 [path to cpan dist file]\n"; + my $dir = dirname($distpath); + my $file = basename($distpath); + my $info = distinfo($file); + + chdir $dir or die "chdir $dir: $!"; + $dir = extractdist($file); + + my $meta = loadmeta($dir); + my $desc = $meta->{'abstract'}; + if (!$desc || $desc eq '~') { + $meta->{'abstract'} = distdesc($dir, $info->{'mod'}); + } + + my ($name, $ver) = Convert::dist2pkg(@{$info}{'name', 'ver'}); + my $deps = Convert::prereqs($name, $meta->{'prereqs'}); + + my %pbvars = + ('pkgname' => $name, + 'pkgver' => $ver, + 'pkgdesc' => $meta->{'abstract'}, + + 'arch' => (xsdist($dir) ? ['i686', 'x86_64'] : 'any'), + 'md5sums' => md5sums($file), + 'sha512sums' => sha512sums($file), + 'distdir' => $dir, + %$deps, + ); + + # Since this is a perl distribution, use the perl-pkg template. + printf "| perl-pkg %s\n", (-f "$dir/Build.PL" ? "MB" : "MM"); + + printjam(\%pbvars); +} + +sub envvar +{ + my ($name) = @_; + my $val = $ENV{uc $name}; + ($name => [ split /\s+/, $name ]); +} + +sub distinfo +{ + my ($distfile) = @_; + + my @c = split /-/, $distfile; + my $ver = pop @c; + my $name = join q{-}, @c; + my $mod = $name; + $mod =~ s/-/::/g; + return { 'name' => $name, 'ver' => $ver, 'mod' => $mod }; +} + +sub extractdist +{ + my ($file) = @_; + + system "bsdtar -xf $file"; + die "$0: bsdtar failed to extract $file\n" unless $? == 0; + + opendir my $srcdir, '.' or die "opendir: $!"; + my @dirs = grep { -d $_ && !/\A[.]/ } readdir $srcdir; + closedir $srcdir; + + die "$0: many dirs (@dirs) inside the tarball $file\n" + if @dirs > 1; + die "$0: no dirs found in tarball $file\n" if @dirs == 0; + return $dirs[0]; +} + +sub printjam +{ + my ($pbvars) = @_; + while (my ($name, $val) = each %$pbvars) { + if (! defined $val || $val eq q{}) { + warn "$0: warning: $name is undefined\n"; + $val = q{}; + } + print "+ $name $_\n" for (ref $val ? @$val : $val); + } +} + +sub loadmeta +{ + my ($distdir) = @_; + + for my $metaext (qw/json yml/) { + my $path = "$distdir/META.$metaext"; + next unless -f $path; + + open my $metafh, '<', $path or die "open: $!"; + my $meta = do { local $/; <$metafh> }; + close $metafh; + + $meta = ($metaext eq 'json' ? decode_json($meta) : + $metaext eq 'yml' ? YAML::XS::Load($meta) : + die "internal error: unknown \$metaext: $metaext"); + + upgrademeta($meta); + return $meta; + } + + return undef; +} + +sub upgrademeta +{ + my ($meta) = @_; + + return if exists $meta->{'prereqs'}; + + my $prereqs; + $prereqs->{'configure'}{'requires'} = delete $meta->{'configure_requires'}; + $prereqs->{'build' }{'requires'} = delete $meta->{'build_requires'}; + $prereqs->{'runtime' }{'requires'} = delete $meta->{'requires'}; + + $meta->{'prereqs'} = $prereqs; + return; +} + +sub xsdist +{ + my ($dir) = @_; + my $isxs; + find({ 'wanted' => sub { $isxs = 1 if /[.]xs$/ }, 'no_chdir' => 1 }, $dir); + return $isxs; +} + +#----------------------------------------------------------------------------- + +sub distdesc +{ + my ($dir, $modname) = @_; + return _poddesc($dir, $modname) || _readmedesc($dir, $modname); +} + +sub _poddesc +{ + my ($dir, $modname) = @_; + + my $podselect = Pod::Select->new; + $podselect->select('NAME'); + + my $modpath = $modname; $modpath =~ s{::}{/}g; + my $moddir = dirname($modpath); + my $modfile = basename($modpath); + + # First check under lib/ for a "properly" pathed module, with + # nested directories. Then search desperately for a .pm file that + # matches the module's last name component. + + my @possible = glob "$dir/{lib/,}{moddir/,}$modfile.{pod,pm}"; + + PODSEARCH: + for my $podpath ( @possible ) { + next PODSEARCH unless -f $podpath; + + # Read the NAME section of the POD into a scalar. + my $namesect = q{}; + open my $podfile, '<', $podpath or next PODSEARCH; + open my $podout, '>', \$namesect or die "open: $!"; + + $podselect->parse_from_filehandle($podfile, $podout); + + close $podfile; + close $podout or die "close: $!"; + + next PODSEARCH unless $namesect; + + # Remove formatting codes. + $namesect =~ s{ [IBCLEFSXZ] <(.*?)> }{$1}gxms; + $namesect =~ s{ [IBCLEFSXZ] <<(.*?)>> }{$1}gxms; + + # The short desc is on a line beginning with 'Module::Name - ' + if ( $namesect =~ / ^ \s* $modname [ -]+ ([^\n]+) /xms ) { + print STDERR qq{Found description "$1" in POD}; + return $1; + } + } + + return undef; +} + +#---HELPER FUNCTION--- +sub _readmedesc +{ + my ($dir, $modname) = @_; + + my $path = catfile($dir, 'README'); + return undef unless -f $path; + open my $fh, '<', $path or die "open: $!"; + + while (<$fh>) { + chomp; + next unless /\ANAME/ ... /\A[A-Z]+/ + and / \A \s* ${modname} [\s\-]+ (.+) \z /x; + print STDERR qq{Found description "$1" in README}; + return $1; + } + + close $fh; + return undef; +} + +#----------------------------------------------------------------------------- + +sub md5sums +{ + return [ map { + open my $fh, '<', $_ or die "open: $!"; + my $md5 = Digest::MD5->new()->addfile($fh)->hexdigest; + } @_ ] +} + +sub sha512sums +{ + return [ map { + my $sha = Digest::SHA->new()->addfile($_)->hexdigest; + } @_ ] +} + +main(@ARGV); @@ -0,0 +1,58 @@ +#!/bin/sh + +VERSION=0.01 + +die() { + echo "error: $1" + exit 1 +} + +if [ -z "$1" ] ; then + die "Usage: $0 [package name]" +fi + +if [ "$PBJROOT" ] ; then + cd "$PBJROOT" +fi + +bindir="$(pwd)/bin" +if [ ! -d "$bindir" ] ; then + die "$bindir does not exist" +fi +PATH="$PATH:$bindir" + +pkgroot="$(pwd)/pkg" +if [ ! -d "$pkgroot" ] ; then + die "$pkgroot does not exist" +fi + +jamdir="$(pwd)/pbj" +if [ ! -d "$jamdir" ] ; then + die "$jamdir does not exist" +fi + +jamfile="$jamdir/$1.pbj" +if [ ! -f "$jamfile" ] ; then + die "$jamfile is missing" +fi + +pkg=$1 +rm -rf "$pkgroot/$pkg" +mkdir "$pkgroot/$pkg" +cd "$pkgroot/$pkg" + +export PATH="$PATH:$bindir/macros:$bindir/templ" + +# Provide values for things macros won't be able to. +printf "+ pbjver $VERSION\n+ pkgrel ${PKGREL:-1}\n" \ + | cat - "$jamfile" \ + | awk -v packager="$PACKAGER" -f "$bindir/pbjparse.awk" \ + > PKGBUILD + +if [ $? -ne 0 ] ; then + echo "Failed to write $pkgroot/$pkg/PKGBUILD" + exit $? +fi + +echo "Wrote $pkgroot/$pkg/PKGBUILD." +exit 0 diff --git a/bin/pbjparse.awk b/bin/pbjparse.awk new file mode 100755 index 0000000..d5e89ff --- /dev/null +++ b/bin/pbjparse.awk @@ -0,0 +1,119 @@ +# pbjparse.awk +## +# Parse a PBJ data file and print a PBDATA datafile to STDOUT. +# Justin Davis <jrcd83@gmail.com> + +BEGIN { + templcount = 0 # number of templates that will be in the templates array + PROG = "pbjparse" +} + +{ parsepbj() } + +END { + tcmd = "" + if (templcount > 0) { + tcmd = templates[1] + for (i=2; i<=templcount; i++) tcmd = "|" templates[i] + } + else tcmd = "cat" + + for (key in pbvars) { + split(key, keys, SUBSEP) + + if (keys[2] != "len") continue + name = keys[1] + len = pbvars[key] + + print name | tcmd + for (i=1; i<=len; i++) print pbvars[name,i] | tcmd + print "" | tcmd + } + + if (optdepcount > 0) { + print "optdepends" | tcmd + for (name in optdeps) print optdeps[name] + print "" | tcmd + } + + if (!seenpkgr) print "packager\n" packager "\n\n" | tcmd +} + +function parsepbj ( cmd) +{ + # Ignore comments. + sub(/#.*/, "") + + # Optdeps are special. In an annoying way. + if ($1 == "+") { + if ($2 == "optdepends") { + msg = $3 + for (i=4; i<=NF; i++) msg = msg " " $i + + ++optdepcount + name = optdepname($3) + optdeps[name] = msg + + remdep("depends", name) + remdep("makedeps", name) + } + else { + # We print the default packager if none was seen. + if ($2 == "packager") seenpkgr = 1 + + val = $3 + for (i=4; i<=NF; i++) val = val " " $i + pbvars[$2, ++pbvars[$2,"len"]] = val + } + } + else if ($1 == "-") { + if ($2 == "optdepends") + die("cannot delete an optdep once it is created.") + remdep($2, $3) + } + else if ($1 == "!") { + cmd = $2 + for (i=3; i<=NF; i++) cmd = cmd " " $i + + while ((ret = cmd | getline) > 0) parsepbj() + if (ret == -1) die("failed to run $cmd") + close(cmd) + } + else if ($1 == "|") { + tcmd = $2 + for (i=3; i<=NF; i++) tcmd = tcmd " " $i + templates[++templcount] = tcmd + } + else if ($1 == "") ; # ignore blank lines + else { + print "ignoring line " FNR ": " $0 | "cat 1>&2" + } +} + +function die (msg) +{ + printf "%s:%s.%d:%s\n", PROG, FILENAME, FNR, msg | "cat 1>&2" + exit 1 +} + +function remdep (name, prefix) +{ + len = pbvars[name, "len"] + if (len == 0) return + + for (i=1; i<=len; i++) + if (pbvars[name, i] ~ "^" prefix) break + + if (i > len) die("could not find " prefix " in " name) + + while (i < len) { pbvars[name, i] = pbvars[name, i+1]; i++ } + delete pbvars[name, i] + pbvars[name, "len"]-- +} + +function optdepname (msgbeg) +{ + if (! match(msgbeg, "^[a-z_-]+:")) + die("failed to extract name from optdept") + return substr(msgbeg, 1, RLENGTH-1) +} diff --git a/bin/templ/perl-pkg b/bin/templ/perl-pkg new file mode 100755 index 0000000..92dd43a --- /dev/null +++ b/bin/templ/perl-pkg @@ -0,0 +1,145 @@ +#!/Users/juster/perl5/perlbrew/perls/perl-5.14.1/bin/perl + +use warnings 'FATAL' => 'all'; +use strict; + +use Text::Wrap qw(wrap); + +my %ACTIONS_OF = ('MM', + { 'build' => [ q{/usr/bin/perl Makefile.PL}, q{make} ], + 'check' => [ q{make test} ], + 'package' => [ q{make DESTDIR="$pkgdir" install} ] + }, + 'MB', + { 'build' => [ q{/usr/bin/perl Build.PL}, q{./Build} ], + 'check' => [ q{./Build test} ], + 'package' => [ q{./Build install} ] + } ); + +my $PBBEG = <<'END_BEG'; +# Maintainer : {: packager :} +# Generator : pbjam {: pbjver :} + +pkgname={: pkgname :} +pkgver={: pkgver :} +pkgrel={: pkgrel :} +pkgdesc={: pkgdesc :} +arch=({: arch :}) +license=(PerlArtistic GPL) +options=('!emptydirs') +depends=({: depends :}) +makedepends=({: makedepends :}) +url={: url :} +source=({: source :}) +md5sums=({: md5sums :}) +sha512sums=({: sha512sums :}) +_distdir="${srcdir}/{: distdir :}" +END_BEG + +my %FUNCFMTS; +$FUNCFMTS{'build'} = <<'END_FMT'; +build() { + ( export PERL_MM_USE_DEFAULT=1 PERL5LIB="" \ + PERL_AUTOINSTALL=--skipdeps \ + PERL_MM_OPT="INSTALLDIRS=vendor DESTDIR='$pkgdir'" \ + PERL_MB_OPT="--installdirs vendor --destdir '$pkgdir'" \ + MODULEBUILDRC=/dev/null + + cd "$_distdir" +%s + ) +} +END_FMT + +$FUNCFMTS{'check'} = <<'END_FMT'; +check() { + ( export PERL_MM_USE_DEFAULT=1 PERL5LIB="" + cd "$_distdir" +%s + ) +} +END_FMT + +$FUNCFMTS{'package'} = <<'END_FMT'; +package() { + cd "$_distdir" +%s + find "$pkgdir" -name .packlist -o -name perllocal.pod -delete +} +END_FMT + +my $PBEND = <<'END_END'; +# Local Variables: +# mode: shell-script +# sh-basic-offset: 2 +# End: +# vim:set ts=2 sw=2 et: +END_END + +# Expands one variable into its bash string representation. +sub expandvar +{ + my ($pbvars, $name) = @_; + + my $val = $pbvars->{$1}; + if ($name eq 'pkgdesc') { + $val->[0] =~ s/([\$\"\`])/\\$1/g; + return qq{"$val->[0]"}; + } + elsif ($name =~ /depends$/) { + my @deps = map { qq{'$_'} } @$val; + return wrap(q{}, q{ } x (length($name) + 2), @deps); + } + return ($val ? join q{ }, @$val : q{}); +} + +# Expand variables used in the template text. +sub expandvars +{ + my ($tmpl, $pbvars) = @_; + + my $txt = $tmpl; + $txt =~ s/ {: \s* (\w+) \s* :} /expandvar($pbvars, $1)/gex; + return $txt; +} + +# Convert actions array into lines of bash to insert into template. +sub bashify +{ + my (@lines) = @_; +# use Data::Dump qw(dump); +# print STDERR dump($lines), "\n"; + my $txt = join qq{\n}, map { s/^/ /gm; $_ } @lines; + return $txt +} + +sub printpb +{ + my ($btype, $pbvars) = @_; + my $acts = $ACTIONS_OF{$btype} + or die "$0: unknown build type ($btype)\n"; + + print expandvars($PBBEG, $pbvars), "\n"; + for my $func (qw/build check package/) { + printf $FUNCFMTS{$func}, bashify(@{$acts->{$func}}); + print "\n"; + } + print $PBEND; +} + +sub readvars +{ + my %pbvars; + my $name; + local $/ = ""; # split records on empty lines + while (<STDIN>) { + my ($name, @vals) = split /\n/; + $pbvars{$name} = \@vals; + } + + return \%pbvars; +} + +my $type = shift or die qq{$0: please provide "MM" or "MB" as argument\n}; +my $vars = readvars(); +printpb($type, $vars); diff --git a/pbj/perl-moose.pbj b/pbj/perl-moose.pbj new file mode 100644 index 0000000..cb2509e --- /dev/null +++ b/pbj/perl-moose.pbj @@ -0,0 +1,4 @@ +# A prototype, by Justin "juster" Davis +! perl-cpan Moose ++ replaces perl-class-mop ++ conflicts perl-class-mop |