Import portgen.
OK many
This commit is contained in:
parent
e2fa1576ef
commit
affd2dee1b
120
infrastructure/lib/OpenBSD/PortGen/Dependency.pm
Normal file
120
infrastructure/lib/OpenBSD/PortGen/Dependency.pm
Normal file
@ -0,0 +1,120 @@
|
||||
# $OpenBSD: Dependency.pm,v 1.1.1.1 2016/01/18 18:08:19 tsg Exp $
|
||||
#
|
||||
# Copyright (c) 2015 Giannis Tsaraias <tsg@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package OpenBSD::PortGen::Dependency;
|
||||
|
||||
use 5.012;
|
||||
use warnings;
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift;
|
||||
my $self = bless {}, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub add_build
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
$self->_add_dep( 'build', @_ );
|
||||
}
|
||||
|
||||
sub add_run
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
$self->_add_dep( 'run', @_ );
|
||||
}
|
||||
|
||||
sub add_test
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
$self->_add_dep( 'test', @_ );
|
||||
}
|
||||
|
||||
sub _add_dep
|
||||
{
|
||||
my ( $self, $type, $port, $reqs ) = @_;
|
||||
|
||||
# '>=0' is redundant, remove it
|
||||
if ( defined $reqs and $reqs eq '>=0' ) {
|
||||
$reqs = '';
|
||||
}
|
||||
|
||||
$self->{deps}{$type}{$port} = $reqs;
|
||||
}
|
||||
|
||||
# from perlfaq4
|
||||
sub _arr_equal
|
||||
{
|
||||
my ( $self, $fst, $snd ) = @_;
|
||||
no warnings;
|
||||
|
||||
return 0 unless @$fst and @$snd;
|
||||
return 0 unless @$fst == @$snd;
|
||||
|
||||
for ( my $i = 0 ; $i < @$fst ; $i++ ) {
|
||||
return 0 if $fst->[$i] ne $snd->[$i];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub format
|
||||
{
|
||||
my $self = shift;
|
||||
my %fmt;
|
||||
|
||||
return unless $self->{deps};
|
||||
|
||||
for my $type (qw/ build run test/) {
|
||||
|
||||
# might not have dependencies of this type
|
||||
next unless exists $self->{deps}{$type};
|
||||
|
||||
my @deps;
|
||||
while ( my ( $name, $ver_reqs ) =
|
||||
each %{ $self->{deps}{$type} } )
|
||||
{
|
||||
push @deps, $ver_reqs ? $name . $ver_reqs : $name;
|
||||
}
|
||||
|
||||
@{ $fmt{$type} } = sort @deps;
|
||||
}
|
||||
|
||||
my ( $build_ref, $run_ref, $test_ref ) =
|
||||
( \@{ $fmt{'build'} }, \@{ $fmt{'run'} }, \@{ $fmt{'test'} } );
|
||||
|
||||
if ( $self->_arr_equal( $build_ref, $run_ref ) ) {
|
||||
@{ $fmt{'run'} } = '${BUILD_DEPENDS}';
|
||||
}
|
||||
|
||||
if ( $self->_arr_equal( $test_ref, $build_ref ) ) {
|
||||
@{ $fmt{'test'} } = '${BUILD_DEPENDS}';
|
||||
} elsif ( $self->_arr_equal( $test_ref, $run_ref ) ) {
|
||||
@{ $fmt{'test'} } = '${RUN_DEPENDS}';
|
||||
}
|
||||
|
||||
for my $type ( keys %fmt ) {
|
||||
$fmt{$type} = ( join " \\\n\t\t\t", @{ $fmt{$type} } ) || undef;
|
||||
}
|
||||
|
||||
return \%fmt;
|
||||
}
|
||||
|
||||
1;
|
83
infrastructure/lib/OpenBSD/PortGen/License.pm
Normal file
83
infrastructure/lib/OpenBSD/PortGen/License.pm
Normal file
@ -0,0 +1,83 @@
|
||||
# $OpenBSD: License.pm,v 1.1.1.1 2016/01/18 18:08:19 tsg Exp $
|
||||
#
|
||||
# Copyright (c) 2015 Giannis Tsaraias <tsg@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package OpenBSD::PortGen::License;
|
||||
|
||||
use 5.012;
|
||||
use warnings;
|
||||
|
||||
use parent qw( Exporter );
|
||||
|
||||
our @EXPORT_OK = qw(
|
||||
is_good
|
||||
pretty_license
|
||||
);
|
||||
|
||||
# Add licenses not recognized here.
|
||||
# Lowercase of what API returns as the key
|
||||
# and printable string as the value.
|
||||
my %good_licenses = (
|
||||
agpl_3 => 'AGPL 3',
|
||||
apache_1_1 => 'Apache 1.1',
|
||||
apache_2_0 => 'Apache 2.0',
|
||||
artistic_1 => 'Artistic 1.0',
|
||||
artistic_2 => 'Artistic 2.0',
|
||||
bsd => 'BSD',
|
||||
freebsd => 'FreeBSD',
|
||||
gpl_2 => 'GPLv2',
|
||||
gpl_2_0 => 'GPLv2',
|
||||
gpl_3 => 'GPLv3',
|
||||
lgpl => 'LGPL',
|
||||
lgpl_2_1 => 'LGPL v2.1',
|
||||
'lgpl_2_1+' => 'LGPL v2.1',
|
||||
mit => 'MIT',
|
||||
perl_5 => 'Perl',
|
||||
ruby => 'Ruby',
|
||||
qpl_1_0 => 'QPLv1',
|
||||
zlib => 'zlib',
|
||||
);
|
||||
|
||||
sub is_good
|
||||
{
|
||||
my $license = shift;
|
||||
|
||||
return unless $license;
|
||||
return defined $good_licenses{ _munge($license) };
|
||||
}
|
||||
|
||||
sub pretty_license
|
||||
{
|
||||
my $raw = shift;
|
||||
|
||||
return "license field not set, consider bugging module's author"
|
||||
if !$raw or $raw eq 'UNKNOWN';
|
||||
return $good_licenses{ _munge($raw) } || "unknown license -> '$raw'";
|
||||
}
|
||||
|
||||
sub _munge
|
||||
{
|
||||
my $license = shift;
|
||||
|
||||
$license = lc $license;
|
||||
$license =~ s/[,-\.\s]/_/g;
|
||||
$license =~ s/_license//;
|
||||
$license =~ s/_version//;
|
||||
$license =~ s/_{2,}/_/g;
|
||||
|
||||
return $license;
|
||||
}
|
||||
|
||||
1;
|
415
infrastructure/lib/OpenBSD/PortGen/Port.pm
Normal file
415
infrastructure/lib/OpenBSD/PortGen/Port.pm
Normal file
@ -0,0 +1,415 @@
|
||||
# $OpenBSD: Port.pm,v 1.1.1.1 2016/01/18 18:08:19 tsg Exp $
|
||||
#
|
||||
# Copyright (c) 2015 Giannis Tsaraias <tsg@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package OpenBSD::PortGen::Port;
|
||||
|
||||
use 5.012;
|
||||
use warnings;
|
||||
|
||||
use Cwd;
|
||||
use File::Path qw( make_path );
|
||||
use JSON::PP;
|
||||
use Text::Wrap;
|
||||
|
||||
use OpenBSD::PortGen::License qw( is_good pretty_license );
|
||||
use OpenBSD::PortGen::Utils qw( add_to_new_ports base_dir fetch ports_dir );
|
||||
|
||||
sub new
|
||||
{
|
||||
my ( $class, %args ) = @_;
|
||||
my $self = bless {%args}, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub get
|
||||
{
|
||||
return fetch( shift->base_url() . shift );
|
||||
}
|
||||
|
||||
sub get_json
|
||||
{
|
||||
return decode_json( shift->get(shift) );
|
||||
}
|
||||
|
||||
sub get_json_file
|
||||
{
|
||||
my ( $self, $file ) = @_;
|
||||
|
||||
open my $h, '<', $file or die $!;
|
||||
my $data = do { local $/ = undef; <$h> };
|
||||
return decode_json $data;
|
||||
}
|
||||
|
||||
sub set_descr
|
||||
{
|
||||
my ( $self, $text ) = @_;
|
||||
|
||||
$self->{descr} = $self->_format_descr($text);
|
||||
}
|
||||
|
||||
sub write_descr
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
my $text = $self->{descr};
|
||||
|
||||
if ( not -d 'pkg' ) {
|
||||
mkdir 'pkg' or die $!;
|
||||
}
|
||||
|
||||
open my $descr, '>', 'pkg/DESCR'
|
||||
or die $!;
|
||||
|
||||
say $descr $text;
|
||||
}
|
||||
|
||||
sub _format_descr
|
||||
{
|
||||
my ( $self, $text ) = @_;
|
||||
|
||||
return 'No description available for this module.'
|
||||
if not $text or $text =~ /^\s*$/;
|
||||
|
||||
$text =~ s/^ *//mg;
|
||||
$text =~ s/^\s*|\s*$//g;
|
||||
|
||||
my $lines = split /\n/, $text;
|
||||
|
||||
if ( $lines > 5 ) {
|
||||
my @paragraphs = split /\n\n/, $text;
|
||||
$text = $paragraphs[0];
|
||||
}
|
||||
|
||||
local $Text::Wrap::columns = 80;
|
||||
return Text::Wrap::wrap( '', '', $text );
|
||||
}
|
||||
|
||||
sub set_comment
|
||||
{
|
||||
my ( $self, $comment ) = @_;
|
||||
|
||||
unless ($comment) {
|
||||
$self->{COMMENT} = 'no comment available';
|
||||
return;
|
||||
}
|
||||
|
||||
$comment =~ s/\n/ /g;
|
||||
$self->{full_comment} = $comment if length $comment > 60;
|
||||
$self->{COMMENT} = $self->_format_comment($comment);
|
||||
}
|
||||
|
||||
sub set_distname
|
||||
{
|
||||
my ( $self, $distname ) = @_;
|
||||
|
||||
my $prefix = $self->ecosystem_prefix();
|
||||
|
||||
# use foo-bar instead of foo-foo-bar as PKGNAME
|
||||
if ( $distname =~ /^$prefix/ ) {
|
||||
$self->{PKGNAME} = ( $distname =~ s/^$prefix//r );
|
||||
$self->{DISTNAME} = $prefix . '${PKGNAME}';
|
||||
} else {
|
||||
$self->{DISTNAME} = $distname;
|
||||
}
|
||||
}
|
||||
|
||||
sub set_license
|
||||
{
|
||||
my ( $self, $license ) = @_;
|
||||
|
||||
if ( is_good($license) ) {
|
||||
$self->{PERMIT_PACKAGE_CDROM} = 'Yes';
|
||||
} else {
|
||||
$self->{PERMIT_PACKAGE_CDROM} = 'unknown license';
|
||||
$self->{PERMIT_PACKAGE_FTP} = 'unknown license';
|
||||
$self->{PERMIT_DISTFILES_FTP} = 'unknown license';
|
||||
}
|
||||
|
||||
$self->{license} = pretty_license($license);
|
||||
}
|
||||
|
||||
sub set_modules
|
||||
{
|
||||
my ( $self, $modules ) = @_;
|
||||
|
||||
$self->{MODULES} = $modules;
|
||||
}
|
||||
|
||||
sub set_categories
|
||||
{
|
||||
my ( $self, $categories ) = @_;
|
||||
|
||||
$self->{CATEGORIES} = $categories;
|
||||
}
|
||||
|
||||
sub set_build_deps
|
||||
{
|
||||
my ( $self, $build_deps ) = @_;
|
||||
|
||||
# Makefile.template is missing a tab for BUILD_DEPENDS
|
||||
# and we want the port to be pretty, so add one
|
||||
$self->{BUILD_DEPENDS} = "\t" . $build_deps if $build_deps;
|
||||
}
|
||||
|
||||
sub set_run_deps
|
||||
{
|
||||
my ( $self, $run_deps ) = @_;
|
||||
|
||||
$self->{RUN_DEPENDS} = $run_deps;
|
||||
}
|
||||
|
||||
sub set_test_deps
|
||||
{
|
||||
my ( $self, $test_deps ) = @_;
|
||||
|
||||
$self->{TEST_DEPENDS} = $test_deps;
|
||||
}
|
||||
|
||||
sub set_other
|
||||
{
|
||||
my ( $self, $var, $value ) = @_;
|
||||
|
||||
$self->{$var} = $value;
|
||||
}
|
||||
|
||||
sub get_other
|
||||
{
|
||||
my ( $self, $var ) = @_;
|
||||
|
||||
return $self->{$var};
|
||||
}
|
||||
|
||||
sub write_makefile
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
open my $tmpl, '<',
|
||||
ports_dir() . '/infrastructure/templates/Makefile.template'
|
||||
or die $!;
|
||||
open my $mk, '>', 'Makefile' or die $!;
|
||||
|
||||
my $output = '# $OpenBSD: Port.pm,v 1.1.1.1 2016/01/18 18:08:19 tsg Exp $' . "\n";
|
||||
my %vars_found;
|
||||
|
||||
# such a mess, should fix
|
||||
while ( defined( my $line = <$tmpl> ) ) {
|
||||
my ( $value, $other_stuff );
|
||||
|
||||
# copy MAINTAINER line as is
|
||||
if ( $line =~ /^MAINTAINER/ ) {
|
||||
$output .= $line and next;
|
||||
}
|
||||
|
||||
if ( $line =~ /(^#?([A-Z_]+)\s+\??=\s+)/ ) {
|
||||
next unless defined $self->{$2};
|
||||
$vars_found{$2} = 1;
|
||||
|
||||
( $value, $other_stuff ) = ( $self->{$2}, $1 );
|
||||
|
||||
$other_stuff =~ s/^#//;
|
||||
$other_stuff =~ s/(\?\?\?|$)/$value\n/;
|
||||
|
||||
if ( $other_stuff =~ /^PERMIT_PACKAGE_CDROM/ ) {
|
||||
$output .= "# $self->{license}\n";
|
||||
} elsif ( $other_stuff =~ /_DEPENDS/ ) {
|
||||
$other_stuff = "\n" . $other_stuff;
|
||||
} elsif ( $other_stuff =~ /^COMMENT/ ) {
|
||||
$output .= "# original: $self->{full_comment}\n"
|
||||
if $self->{full_comment};
|
||||
}
|
||||
|
||||
$output .= $other_stuff;
|
||||
}
|
||||
|
||||
$output .= $line if $line =~ /^\s+$/;
|
||||
}
|
||||
|
||||
# also write variables not found in the template
|
||||
my @unwritten_vars;
|
||||
|
||||
for my $var ( keys %{$self} ) {
|
||||
next unless $self->{$var};
|
||||
next unless $var eq uc $var;
|
||||
push @unwritten_vars, $var unless $vars_found{$var};
|
||||
}
|
||||
|
||||
# the ordering should be consistent between runs
|
||||
@unwritten_vars = sort @unwritten_vars;
|
||||
|
||||
for my $var (@unwritten_vars) {
|
||||
|
||||
# temp fix, should make saner
|
||||
my $tabs = length $var > 11 ? "\t" : "\t\t";
|
||||
$output .= "\n$var =$tabs$self->{$var}\n";
|
||||
}
|
||||
|
||||
$output .= "\n.include <bsd.port.mk>\n";
|
||||
$output =~ s/\n{2,}/\n\n/g;
|
||||
|
||||
print $mk $output;
|
||||
}
|
||||
|
||||
sub _format_comment
|
||||
{
|
||||
my ( $self, $text ) = @_;
|
||||
|
||||
return unless $text;
|
||||
|
||||
$text =~ s/^(a|an) //i;
|
||||
$text =~ s/\n/ /g;
|
||||
$text =~ s/\.$//;
|
||||
$text =~ s/\s+$//;
|
||||
|
||||
# Max comment length is 60. Try to cut it, but print full
|
||||
# version in Makefile for the porter to edit as needed.
|
||||
$text =~ s/ \S+$// while length $text > 60;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
sub _make
|
||||
{
|
||||
my $self = shift;
|
||||
system( 'make', @_ );
|
||||
return $? >> 8;
|
||||
}
|
||||
|
||||
sub make_clean
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->_make('clean');
|
||||
}
|
||||
|
||||
sub make_fetch
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->_make('fetch-all');
|
||||
}
|
||||
|
||||
sub make_makesum
|
||||
{
|
||||
shift->_make('makesum');
|
||||
}
|
||||
|
||||
sub make_checksum
|
||||
{
|
||||
shift->_make('checksum');
|
||||
}
|
||||
|
||||
sub make_extract
|
||||
{
|
||||
shift->_make('extract');
|
||||
}
|
||||
|
||||
sub make_configure
|
||||
{
|
||||
shift->_make('configure');
|
||||
}
|
||||
|
||||
sub make_fake
|
||||
{
|
||||
shift->_make('fake');
|
||||
}
|
||||
|
||||
sub make_plist
|
||||
{
|
||||
shift->_make('plist');
|
||||
}
|
||||
|
||||
sub make_show
|
||||
{
|
||||
my ( $self, $var ) = @_;
|
||||
chomp( my $output = qx{ make show=$var } );
|
||||
return $output;
|
||||
}
|
||||
|
||||
sub make_portdir
|
||||
{
|
||||
my ( $self, $name ) = @_;
|
||||
|
||||
my $portdir = base_dir() . "/$name";
|
||||
make_path($portdir) unless -e $portdir;
|
||||
|
||||
return $portdir;
|
||||
}
|
||||
|
||||
sub make_port
|
||||
{
|
||||
my ( $self, $di, $vi ) = @_;
|
||||
|
||||
my $old_cwd = getcwd();
|
||||
my $portname = $self->name_new_port($di);
|
||||
my $portdir = $self->make_portdir($portname);
|
||||
chdir $portdir or die "couldn't chdir to $portdir: $!";
|
||||
|
||||
$self->fill_in_makefile( $di, $vi );
|
||||
$self->write_makefile();
|
||||
|
||||
$self->make_fetch();
|
||||
$self->make_makesum();
|
||||
$self->make_checksum();
|
||||
$self->make_extract();
|
||||
my $wrksrc = $self->make_show('WRKSRC');
|
||||
|
||||
# children can override this to set any variables
|
||||
# that require extracted distfiles
|
||||
$self->postextract( $di, $wrksrc );
|
||||
|
||||
$self->set_other( 'CONFIGURE_STYLE',
|
||||
$self->get_config_style( $di, $wrksrc ) );
|
||||
$self->write_makefile();
|
||||
|
||||
$self->make_configure();
|
||||
|
||||
my $deps = $self->get_deps( $di, $wrksrc );
|
||||
$self->set_build_deps( $deps->{build} );
|
||||
$self->set_run_deps( $deps->{run} );
|
||||
$self->set_test_deps( $deps->{test} );
|
||||
$self->write_makefile();
|
||||
|
||||
# sometimes a make_fake() is not enough, need to run it more than
|
||||
# once to figure out which CONFIGURE_STYLE actually works
|
||||
$self->try_building();
|
||||
|
||||
$self->make_plist();
|
||||
$self->write_descr();
|
||||
chdir $old_cwd or die "couldn't chdir to $old_cwd: $!";
|
||||
|
||||
return add_to_new_ports($portdir);
|
||||
}
|
||||
|
||||
sub port
|
||||
{
|
||||
my ( $self, $module ) = @_;
|
||||
|
||||
my $di = eval { $self->get_dist_info($module) };
|
||||
|
||||
unless ($di) {
|
||||
warn "couldn't find dist for $module";
|
||||
return;
|
||||
}
|
||||
|
||||
my $vi = eval { $self->get_ver_info($module) };
|
||||
|
||||
unless ($vi) {
|
||||
warn "couldn't get version info for $module";
|
||||
return;
|
||||
}
|
||||
|
||||
return $self->make_port( $di, $vi );
|
||||
}
|
||||
|
||||
1;
|
271
infrastructure/lib/OpenBSD/PortGen/Port/CPAN.pm
Normal file
271
infrastructure/lib/OpenBSD/PortGen/Port/CPAN.pm
Normal file
@ -0,0 +1,271 @@
|
||||
# $OpenBSD: CPAN.pm,v 1.1.1.1 2016/01/18 18:08:20 tsg Exp $
|
||||
#
|
||||
# Copyright (c) 2015 Giannis Tsaraias <tsg@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package OpenBSD::PortGen::Port::CPAN;
|
||||
|
||||
use 5.012;
|
||||
use warnings;
|
||||
|
||||
use parent 'OpenBSD::PortGen::Port';
|
||||
|
||||
use File::Find qw( find );
|
||||
use OpenBSD::PortGen::Dependency;
|
||||
use OpenBSD::PortGen::Utils qw( fetch module_in_ports );
|
||||
|
||||
sub ecosystem_prefix
|
||||
{
|
||||
my $self = shift;
|
||||
return 'p5-';
|
||||
}
|
||||
|
||||
sub base_url
|
||||
{
|
||||
my $self = shift;
|
||||
return 'https://api.metacpan.org/v0/';
|
||||
}
|
||||
|
||||
sub get_dist_info
|
||||
{
|
||||
my ( $self, $module ) = @_;
|
||||
|
||||
my $dist = $self->get_dist_for_module($module);
|
||||
|
||||
return $self->get_json("release/$dist");
|
||||
}
|
||||
|
||||
sub get_ver_info
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub get_dist_for_module
|
||||
{
|
||||
my ( $self, $module ) = @_;
|
||||
|
||||
return $self->get_json("module/$module?fields=distribution")
|
||||
->{distribution};
|
||||
}
|
||||
|
||||
sub name_new_port
|
||||
{
|
||||
my ( $self, $di ) = @_;
|
||||
|
||||
my $name = ref $di ? $di->{metadata}->{name} : $di;
|
||||
$name = "p5-$name";
|
||||
$name =~ s/::/-/g;
|
||||
|
||||
return "cpan/$name";
|
||||
}
|
||||
|
||||
sub needs_author
|
||||
{
|
||||
my ( $self, $di ) = @_;
|
||||
|
||||
my $mirror = 'http://www.cpan.org';
|
||||
|
||||
# one module used 'src/foo.tar.gz', we only need foo.tar.gz
|
||||
my ($file) = $di->{archive} =~ /([^\/]+)$/;
|
||||
|
||||
$file = "$1/$file" if $file =~ /^(\w+)-/;
|
||||
|
||||
return !fetch("$mirror/modules/by-module/$file");
|
||||
}
|
||||
|
||||
sub get_config_style
|
||||
{
|
||||
my ( $self, $di, $wrksrc ) = @_;
|
||||
|
||||
if ( $di->{metadata}->{generated_by} =~ /Module::Install/
|
||||
|| -e "$wrksrc/inc/Module/Install.pm" )
|
||||
{
|
||||
return 'modinst';
|
||||
}
|
||||
|
||||
for my $dep ( @{ $di->{dependency} } ) {
|
||||
if ( $dep->{module} eq 'Module::Build' )
|
||||
{
|
||||
return 'modbuild';
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub get_deps
|
||||
{
|
||||
my ( $self, $di, $wrksrc ) = @_;
|
||||
my $deps = OpenBSD::PortGen::Dependency->new();
|
||||
|
||||
if ( -e "$wrksrc/MYMETA.json" ) {
|
||||
my $meta = $self->get_json_file("$wrksrc/MYMETA.json");
|
||||
$di = $meta if defined $meta;
|
||||
} else {
|
||||
$di = $di->{metadata};
|
||||
}
|
||||
|
||||
for my $phase (qw/ build runtime configure test /) {
|
||||
next unless $di->{prereqs}{$phase};
|
||||
|
||||
for my $relation (qw/ requires recommends /) {
|
||||
next if $relation eq 'recommends' and $phase ne 'test';
|
||||
|
||||
while ( my ( $module, $req ) =
|
||||
each %{ $di->{prereqs}{$phase}{$relation} } )
|
||||
{
|
||||
next if $self->is_in_base($module);
|
||||
|
||||
my $dist = $self->get_dist_for_module($module);
|
||||
my $port = module_in_ports( $dist, 'p5-' )
|
||||
|| $self->name_new_port($dist);
|
||||
|
||||
$req =~ s/^v//;
|
||||
$req =~ s/0+$/0/;
|
||||
|
||||
if ( $phase eq 'configure'
|
||||
|| $phase eq 'build' )
|
||||
{
|
||||
$deps->add_build( $port, ">=$req" );
|
||||
} elsif ( $phase eq 'runtime' ) {
|
||||
$deps->add_run( $port, ">=$req" );
|
||||
} elsif ( $phase eq 'test' ) {
|
||||
$deps->add_test( $port, ">=$req" );
|
||||
}
|
||||
|
||||
# don't have it in tree, port it
|
||||
if ( $port =~ m{^cpan/} ) {
|
||||
my $o =
|
||||
OpenBSD::PortGen::Port::CPAN->new();
|
||||
$o->port($module);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $deps->format();
|
||||
}
|
||||
|
||||
sub read_descr
|
||||
{
|
||||
my ( $self, $path ) = @_;
|
||||
|
||||
open my $readme, '<', "$path/README" or return;
|
||||
my $descr = do { local $/ = undef; <$readme> };
|
||||
|
||||
if ( $descr =~ /^DESCRIPTION\n(.+?)^[A-Z]+/ms ) {
|
||||
return $1 unless $1 =~ /^\s+$/;
|
||||
}
|
||||
|
||||
if ( $descr =~ /^SYNOPSIS\n(.+?)^[A-Z]+/ms ) {
|
||||
return $1 unless $1 =~ /^\s+$/;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub fill_in_makefile
|
||||
{
|
||||
my ( $self, $di, $vi ) = @_;
|
||||
|
||||
$self->set_comment( $di->{abstract} );
|
||||
$self->set_distname( $di->{name} );
|
||||
$self->set_license(
|
||||
$di->{metadata}->{license}[0] eq 'unknown'
|
||||
? ''
|
||||
: $di->{metadata}->{license}[0]
|
||||
);
|
||||
$self->set_modules('cpan');
|
||||
$self->set_categories('cpan');
|
||||
|
||||
$self->set_other( 'CPAN_AUTHOR', $di->{author} )
|
||||
if $self->needs_author($di);
|
||||
|
||||
my ($sufx) = $di->{archive} =~ /(\.[\.A-Za-z]+)$/;
|
||||
|
||||
if ( defined $sufx and $sufx ne '.tar.gz' ) {
|
||||
$self->set_other( 'EXTRACT_SUFX', $sufx );
|
||||
}
|
||||
}
|
||||
|
||||
sub postextract
|
||||
{
|
||||
my ( $self, $di, $wrksrc ) = @_;
|
||||
|
||||
$self->set_descr( $self->read_descr($wrksrc) || $di->{abstract} );
|
||||
$self->_find_hidden_test_deps($wrksrc);
|
||||
}
|
||||
|
||||
sub try_building
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
if ( $self->make_fake() and $self->get_other('CONFIGURE_STYLE') ) {
|
||||
warn
|
||||
"* * * Warning: failed to build with CONFIGURE_STYLE, trying without * * *";
|
||||
$self->set_other( 'CONFIGURE_STYLE', undef );
|
||||
$self->write_makefile();
|
||||
$self->make_clean();
|
||||
!$self->make_fake() or die 'cannot build port';
|
||||
}
|
||||
}
|
||||
|
||||
sub is_in_base
|
||||
{
|
||||
my ( $self, $module ) = @_;
|
||||
|
||||
return 1 if $module eq 'perl';
|
||||
|
||||
$module .= '.pm';
|
||||
$module =~ s{::}{/}g;
|
||||
|
||||
for (@INC) {
|
||||
next unless m{/usr/libdata/};
|
||||
return 1 if -e "$_/$module";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
# Some testfiles skip tests because the required modules are not
|
||||
# available. Those modules are not always listed as dependencies, so
|
||||
# manually check if there are testfiles skipping tests and warn the
|
||||
# porter about them.
|
||||
sub _find_hidden_test_deps
|
||||
{
|
||||
my ( $self, $path ) = @_;
|
||||
|
||||
return unless -d "$path/t";
|
||||
|
||||
find( sub { $self->_test_skips($File::Find::name) }, "$path/t" );
|
||||
}
|
||||
|
||||
sub _test_skips
|
||||
{
|
||||
my ( $self, $file ) = @_;
|
||||
|
||||
# not a testfile
|
||||
return unless $file =~ /\.t$/;
|
||||
|
||||
open my $fh, '<', $file or die $!;
|
||||
|
||||
while (<$fh>) {
|
||||
if (/plan skip_all/) {
|
||||
warn "Possible hidden test dependency in: $file\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
103
infrastructure/lib/OpenBSD/PortGen/Port/PyPI.pm
Normal file
103
infrastructure/lib/OpenBSD/PortGen/Port/PyPI.pm
Normal file
@ -0,0 +1,103 @@
|
||||
# $OpenBSD: PyPI.pm,v 1.1.1.1 2016/01/18 18:08:20 tsg Exp $
|
||||
#
|
||||
# Copyright (c) 2015 Giannis Tsaraias <tsg@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package OpenBSD::PortGen::Port::PyPI;
|
||||
|
||||
use 5.012;
|
||||
use warnings;
|
||||
|
||||
use parent 'OpenBSD::PortGen::Port';
|
||||
|
||||
use OpenBSD::PortGen::Dependency;
|
||||
|
||||
sub ecosystem_prefix
|
||||
{
|
||||
my $self = shift;
|
||||
return 'py-';
|
||||
}
|
||||
|
||||
sub base_url
|
||||
{
|
||||
my $self = shift;
|
||||
return 'https://pypi.python.org/pypi/';
|
||||
}
|
||||
|
||||
sub get_dist_info
|
||||
{
|
||||
my ( $self, $module ) = @_;
|
||||
|
||||
return $self->get_json( $module . '/json' );
|
||||
}
|
||||
|
||||
sub get_ver_info
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub name_new_port
|
||||
{
|
||||
my ( $self, $di ) = @_;
|
||||
|
||||
my $name = $di->{info}{name};
|
||||
$name = "py-$name" unless $name =~ /^py-/;
|
||||
|
||||
return "pypi/$name";
|
||||
}
|
||||
|
||||
sub fill_in_makefile
|
||||
{
|
||||
my ( $self, $di, $vi ) = @_;
|
||||
|
||||
$self->set_other( 'MODPY_PI', 'Yes' );
|
||||
$self->set_other( 'MODPY_SETUPTOOLS', 'Yes' );
|
||||
$self->set_comment( $di->{info}{summary} );
|
||||
$self->set_other( 'MODPY_EGG_VERSION', $di->{info}{version} );
|
||||
$self->set_distname( "$di->{info}{name}" . '-${MODPY_EGG_VERSION}' );
|
||||
$self->set_other( 'PKGNAME', 'py-${DISTNAME}' );
|
||||
$self->set_modules('lang/python');
|
||||
$self->set_categories('pypi');
|
||||
$self->set_other( 'HOMEPAGE', $di->{info}{home_page} );
|
||||
$self->set_license( $di->{info}{license} );
|
||||
$self->set_descr( $di->{info}{summary} );
|
||||
|
||||
for ( @{ $di->{info}{classifiers} } ) {
|
||||
if (/^Programming Language :: Python :: 3/) {
|
||||
$self->set_other( 'FLAVORS', 'python3' );
|
||||
$self->set_other( 'FLAVOR', '' );
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub try_building
|
||||
{
|
||||
my $self = shift;
|
||||
$self->make_fake();
|
||||
}
|
||||
|
||||
sub postextract
|
||||
{
|
||||
}
|
||||
|
||||
sub get_deps
|
||||
{
|
||||
}
|
||||
|
||||
sub get_config_style
|
||||
{
|
||||
}
|
||||
|
||||
1;
|
146
infrastructure/lib/OpenBSD/PortGen/Port/Ruby.pm
Normal file
146
infrastructure/lib/OpenBSD/PortGen/Port/Ruby.pm
Normal file
@ -0,0 +1,146 @@
|
||||
# $OpenBSD: Ruby.pm,v 1.1.1.1 2016/01/18 18:08:20 tsg Exp $
|
||||
#
|
||||
# Copyright (c) 2015 Giannis Tsaraias <tsg@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package OpenBSD::PortGen::Port::Ruby;
|
||||
|
||||
use 5.012;
|
||||
use warnings;
|
||||
|
||||
use parent 'OpenBSD::PortGen::Port';
|
||||
|
||||
use OpenBSD::PortGen::Dependency;
|
||||
use OpenBSD::PortGen::Utils qw( module_in_ports );
|
||||
|
||||
sub ecosystem_prefix
|
||||
{
|
||||
my $self = shift;
|
||||
return 'ruby-';
|
||||
}
|
||||
|
||||
sub postextract
|
||||
{
|
||||
}
|
||||
|
||||
sub base_url
|
||||
{
|
||||
my $self = shift;
|
||||
return 'https://rubygems.org/api/v1/';
|
||||
}
|
||||
|
||||
sub get_dist_info
|
||||
{
|
||||
my ( $self, $module ) = @_;
|
||||
return $self->get_json("gems/$module.json");
|
||||
}
|
||||
|
||||
sub get_ver_info
|
||||
{
|
||||
my ( $self, $module ) = @_;
|
||||
|
||||
return @{ $self->get_json("versions/$module.json") }[0];
|
||||
}
|
||||
|
||||
sub name_new_port
|
||||
{
|
||||
my ( $self, $di ) = @_;
|
||||
|
||||
my $name = ref $di ? $di->{name} : $di;
|
||||
$name = "ruby-$name" unless $name =~ /^ruby-/;
|
||||
|
||||
return "ruby/$name";
|
||||
}
|
||||
|
||||
sub fill_in_makefile
|
||||
{
|
||||
my ( $self, $di, $vi ) = @_;
|
||||
|
||||
$self->set_comment( $vi->{summary} );
|
||||
$self->set_distname("$di->{name}-$di->{version}");
|
||||
$self->set_modules('lang/ruby');
|
||||
$self->set_categories('ruby');
|
||||
$self->set_other( 'HOMEPAGE', $di->{homepage_uri} );
|
||||
$self->set_license( @{ $vi->{licenses} }[0] );
|
||||
$self->set_other( 'CONFIGURE_STYLE', "ruby gem" );
|
||||
$self->set_descr( $di->{info} || $vi->{summary} );
|
||||
}
|
||||
|
||||
sub try_building
|
||||
{
|
||||
my $self = shift;
|
||||
$self->make_fake();
|
||||
}
|
||||
|
||||
sub get_deps
|
||||
{
|
||||
my ( $self, $di ) = @_;
|
||||
my $deps = OpenBSD::PortGen::Dependency->new();
|
||||
|
||||
return unless $di->{dependencies};
|
||||
|
||||
for my $dep ( @{ $di->{dependencies}->{runtime} } ) {
|
||||
my ( $name, $req ) = ( $dep->{name}, $dep->{requirements} );
|
||||
|
||||
next if $self->is_standard_module($name);
|
||||
|
||||
my $port = module_in_ports( $name, 'ruby-' )
|
||||
|| $self->name_new_port($name);
|
||||
|
||||
$req =~ s/ //g;
|
||||
|
||||
# support pessimistic version requirement:
|
||||
# turn ~> 3.0.3 into >=3.0.3,<3.1.0
|
||||
# and ~> 1.1 into >=1.1,<2.0
|
||||
if ( $req =~ /~>([\d\.]+)/ ) {
|
||||
my $ver = $1;
|
||||
$req =~ s/~>/>=/;
|
||||
$ver =~ s/(\d)\.\d$/($1+1).".0"/e;
|
||||
$req .= ",<$ver";
|
||||
}
|
||||
|
||||
$deps->add_run( $port . ',${MODRUBY_FLAVOR}', $req );
|
||||
|
||||
# gems only understand runtime and development deps
|
||||
$deps->add_build('${RUN_DEPENDS}');
|
||||
|
||||
# don't have this one, port it
|
||||
if ( $port =~ m{^ruby/} ) {
|
||||
my $o = OpenBSD::PortGen::Port::Ruby->new();
|
||||
$o->port($name);
|
||||
}
|
||||
}
|
||||
|
||||
return $deps->format();
|
||||
}
|
||||
|
||||
sub is_standard_module
|
||||
{
|
||||
my ( $self, $module, $ruby_ver ) = @_;
|
||||
$ruby_ver //= '2.2';
|
||||
|
||||
return -e "/usr/local/lib/ruby/$ruby_ver/$module.rb";
|
||||
}
|
||||
|
||||
sub get_config_style
|
||||
{
|
||||
my ( $self, $di, $wrksrc ) = @_;
|
||||
|
||||
if ( -d "$wrksrc/ext" ) {
|
||||
return "ruby gem ext";
|
||||
}
|
||||
return "ruby gem";
|
||||
}
|
||||
|
||||
1;
|
112
infrastructure/lib/OpenBSD/PortGen/Utils.pm
Normal file
112
infrastructure/lib/OpenBSD/PortGen/Utils.pm
Normal file
@ -0,0 +1,112 @@
|
||||
# $OpenBSD: Utils.pm,v 1.1.1.1 2016/01/18 18:08:19 tsg Exp $
|
||||
#
|
||||
# Copyright (c) 2015 Giannis Tsaraias <tsg@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package OpenBSD::PortGen::Utils;
|
||||
|
||||
use 5.012;
|
||||
use warnings;
|
||||
|
||||
use DBI;
|
||||
|
||||
use parent qw( Exporter );
|
||||
|
||||
our @EXPORT_OK = qw(
|
||||
add_to_new_ports
|
||||
base_dir
|
||||
fetch
|
||||
module_in_ports
|
||||
ports_dir
|
||||
);
|
||||
|
||||
sub _fetch_cmd { qw( ftp -V -o- ) }
|
||||
|
||||
sub fetch
|
||||
{
|
||||
my $url = shift;
|
||||
|
||||
for ( 0 .. 1 ) {
|
||||
open my $fh, '-|', _fetch_cmd(), $url or die $!;
|
||||
my $content = do { local $/ = undef; <$fh> };
|
||||
return $content if $content;
|
||||
sleep 2 * $_;
|
||||
}
|
||||
}
|
||||
|
||||
sub ports_dir { $ENV{PORTSDIR} || '/usr/ports' }
|
||||
|
||||
sub base_dir { ports_dir() . '/mystuff' }
|
||||
|
||||
sub module_in_ports
|
||||
{
|
||||
my ( $module, $prefix ) = @_;
|
||||
|
||||
return unless $module and $prefix;
|
||||
|
||||
my $dbpath = '/usr/local/share';
|
||||
my $dbfile;
|
||||
|
||||
if ( -e "$dbpath/sqlports-compact" ) {
|
||||
$dbfile = 'sqlports-compact';
|
||||
} elsif ( -e "$dbpath/sqlports" ) {
|
||||
$dbfile = 'sqlports';
|
||||
} else {
|
||||
die "install databases/sqlports-compact or databases/sqlports";
|
||||
}
|
||||
|
||||
my $dbh = DBI->connect( "dbi:SQLite:dbname=$dbpath/$dbfile", "", "" )
|
||||
or die "failed to connect to database: $DBI::errstr";
|
||||
|
||||
my $stmt;
|
||||
$stmt =
|
||||
$dbfile =~ /compact/
|
||||
? "SELECT FULLPKGPATH FROM Paths WHERE ID IN ( SELECT FULLPKGPATH FROM Ports WHERE DISTNAME LIKE '$module%' )"
|
||||
: "SELECT FULLPKGPATH FROM Ports WHERE DISTNAME LIKE '$module%'";
|
||||
|
||||
my $pr = $dbh->prepare($stmt);
|
||||
$pr->execute();
|
||||
|
||||
my @results;
|
||||
while ( my @pkgpaths = $pr->fetchrow_array ) {
|
||||
push @results, $pkgpaths[0];
|
||||
}
|
||||
|
||||
$dbh->disconnect();
|
||||
|
||||
# don't need flavors, should find a cleaner way to do this
|
||||
s/,\w+$// for @results;
|
||||
|
||||
# just returning the shortest one that's a module of the same ecosystem
|
||||
# this should be improved
|
||||
@results = sort { length $a <=> length $b } @results;
|
||||
|
||||
# this works well enough in practice, but can't rely on it
|
||||
# see devel/perltidy
|
||||
for (@results) {
|
||||
return $_ if /\/$prefix/;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
# i know, i know...
|
||||
sub add_to_new_ports
|
||||
{
|
||||
state @new_ports;
|
||||
push @new_ports, shift;
|
||||
return @new_ports;
|
||||
}
|
||||
|
||||
1;
|
Loading…
x
Reference in New Issue
Block a user