aboutsummaryrefslogtreecommitdiff
path: root/SBO-Lib/lib/SBO/Lib/Build.pm
diff options
context:
space:
mode:
Diffstat (limited to 'SBO-Lib/lib/SBO/Lib/Build.pm')
-rw-r--r--SBO-Lib/lib/SBO/Lib/Build.pm772
1 files changed, 0 insertions, 772 deletions
diff --git a/SBO-Lib/lib/SBO/Lib/Build.pm b/SBO-Lib/lib/SBO/Lib/Build.pm
deleted file mode 100644
index 4a86e4d..0000000
--- a/SBO-Lib/lib/SBO/Lib/Build.pm
+++ /dev/null
@@ -1,772 +0,0 @@
-package SBO::Lib::Build;
-
-use 5.016;
-use strict;
-use warnings;
-
-our $VERSION = '2.8.0';
-
-use SBO::Lib::Util qw/ :const prompt script_error get_sbo_from_loc get_arch check_multilib uniq %config in /;
-use SBO::Lib::Tree qw/ get_sbo_location /;
-use SBO::Lib::Info qw/ get_sbo_version check_x32 get_requires /;
-use SBO::Lib::Download qw/ get_sbo_downloads get_dl_fns get_filename_from_link check_distfiles /;
-
-use Exporter 'import';
-use Fcntl qw(F_SETFD F_GETFD);
-use File::Copy; # copy() and move()
-use File::Path qw/ make_path remove_tree /;
-use File::Temp qw/ tempdir tempfile /;
-use Tie::File;
-use Cwd;
-
-our @EXPORT_OK = qw{
- do_convertpkg
- do_slackbuild
- do_upgradepkg
- get_build_queue
- get_dc_regex
- get_pkg_name
- get_src_dir
- get_tmp_extfn
- make_clean
- make_distclean
- merge_queues
- perform_sbo
- process_sbos
- revert_slackbuild
- rewrite_slackbuild
- run_tee
-
- $tmpd
- $env_tmp
-};
-
-our %EXPORT_TAGS = (
- all => \@EXPORT_OK,
-);
-
-=pod
-
-=encoding UTF-8
-
-=head1 NAME
-
-SBO::Lib::Build - Routines for building slackware packages from SlackBuilds.org.
-
-=head1 SYNOPSIS
-
- use SBO::Lib::Build qw/ perform_sbo /;
-
- my ($foo, $bar, $exit) = perform_sbo(LOCATION => $location, ARCH => 'x86_64');
-
-=head1 VARIABLES
-
-=head2 $env_tmp
-
-This will reflect the C<$TMP> from the environment, being C<undef> if it is not
-set.
-
-=head2 $tmpd
-
-Will be the same as C<$TMP> if it is set, otherwise it will be C</tmp/SBo>.
-
-=cut
-
-# get $TMP from the env, if defined - we use two variables here because there
-# are times when we need to know if the environment variable is set, and other
-# times where it doesn't matter.
-our $env_tmp = $ENV{TMP};
-our $tmpd = $env_tmp ? $env_tmp : '/tmp/SBo';
-make_path($tmpd) unless -d $tmpd;
-
-=head1 SUBROUTINES
-
-=cut
-
-=head2 do_convertpkg
-
- my ($name32, $exit) = do_convertpkg($name64);
-
-C<do_convertpkg()> runs C<convertpkg> on the package in C<$name64>.
-
-It returns two values. If the second value is true, the first will contain an
-error message. Otherwise it will contain the name of the converted package.
-
-=cut
-
-# run convertpkg on a package to turn it into a -compat32 thing
-sub do_convertpkg {
- script_error('do_convertpkg requires an argument.') unless @_ == 1;
- my $pkg = shift;
- my $c32tmpd = $env_tmp // '/tmp';
-
- my ($out, $ret) = run_tee("/bin/bash -c '/usr/sbin/convertpkg-compat32 -i $pkg -d $c32tmpd'");
-
- if ($ret != 0) {
- return "convertpkg-compt32 returned non-zero exit status\n",
- _ERR_CONVERTPKG;
- }
- unlink $pkg;
- return get_pkg_name($out);
-}
-
-=head2 do_slackbuild
-
- my ($ver, $pkg, $src, $exit) = do_slackbuild(LOCATION => $location);
-
-C<do_slackbuild()> will make some checks and set up the C<perform_sbo()> call,
-if needed run C<do_convertpkg()>, and return the results.
-
-It will return a list of four values. If the fourth one is a true value, the
-first one will be an error message. Otherwise the first will be the version,
-the second will be the package, and the third will be an array reference to the
-source directories created by the build.
-
-=cut
-
-# "public interface", sort of thing.
-sub do_slackbuild {
- my %args = (
- OPTS => 0,
- JOBS => 0,
- LOCATION => '',
- COMPAT32 => 0,
- @_
- );
- $args{LOCATION} or script_error('do_slackbuild requires LOCATION.');
- my $location = $args{LOCATION};
- my $sbo = get_sbo_from_loc($location);
- my $arch = get_arch();
- my $multilib = check_multilib();
- my $version = get_sbo_version($location);
- my $x32;
- # ensure x32 stuff is set correctly, or that we're setup for it
- if ($args{COMPAT32}) {
- unless ($multilib) {
- return "compat32 requires multilib.\n", (undef) x 2,
- _ERR_NOMULTILIB;
- }
- unless (-f '/usr/sbin/convertpkg-compat32') {
- return "compat32 requires /usr/sbin/convertpkg-compat32.\n",
- (undef) x 2, _ERR_NOCONVERTPKG;
- }
- } else {
- if ($arch eq 'x86_64') {
- $x32 = check_x32 $args{LOCATION};
- if ($x32 && ! $multilib) {
- my $warn =
- "$sbo is 32-bit which requires multilib on x86_64.\n";
- return $warn, (undef) x 2, _ERR_NOMULTILIB;
- }
- }
- }
- # setup and run the .SlackBuild itself
- my ($pkg, $src, $exit) = perform_sbo(
- OPTS => $args{OPTS},
- JOBS => $args{JOBS},
- LOCATION => $location,
- ARCH => $arch,
- C32 => $args{COMPAT32},
- X32 => $x32,
- );
- return $pkg, (undef) x 2, $exit if $exit;
- if ($args{COMPAT32}) {
- ($pkg, $exit) = do_convertpkg($pkg);
- return $pkg, (undef) x 2, $exit if $exit;
- }
- return $version, $pkg, $src;
-}
-
-=head2 do_upgradepkg
-
- do_upgradepkg($pkg);
-
-C<do_upgradepkg()> runs C<upgradepkg> on C<$pkg>.
-
-There is no useful return value.
-
-=cut
-
-# run upgradepkg for a created package
-sub do_upgradepkg {
- script_error('do_upgradepkg requires an argument.') unless @_ == 1;
- system('/sbin/upgradepkg', '--reinstall', '--install-new', shift);
- return 1;
-}
-
-=head2 get_build_queue
-
- my @queue = @{ get_build_queue($sbo, my $warnings) };
-
-C<get_build_queue()> gets the prerequisites for C<$sbo>, and updates the
-C<$warnings> hash reference with any C<%README%> encountered. It returns the
-prerequisites and the C<$sbo> in the order in which they need to be built.
-
-=cut
-
-sub get_build_queue {
- script_error('get_build_queue requires two arguments.') unless @_ == 2;
- return [ _build_queue(@_) ];
-}
-
-=head2 get_dc_regex
-
- my ($rx, $initial) = get_dc_regex($line);
-
-C<get_dc_regex()> when given a line that is an untar or similar command, creates
-a regular expression which should match the filename. This is returned, together
-with the C<$initial> character which will start the filename match.
-
-=cut
-
-# given a line that looks like it's decompressing something, try to return a
-# valid filename regex
-sub get_dc_regex {
- my $line = shift;
- # get rid of initial 'tar x'whatever stuff
- $line =~ s/^.*(?<![a-z])(tar|p7zip|unzip|ar|rpm2cpio|sh)\s+[^\s]+\s+//;
- # need to know preceeding character - should be safe to assume it's either
- # a slash or a space
- my $initial = $line =~ qr|/| ? '/' : ' ';
- # get rid of initial path info
- $line =~ s|^\$[^/]+/||;
- # convert any instances of command substitution to [^-]+
- $line =~ s/\$\([^)]+\)/[^-]+/g;
- # convert any bash variables to [^-]+
- $line =~ s/\$(\{|)[A-Za-z0-9_]+(}|)/[^-]+/g;
- # get rid of anything excess at the end
- $line =~ s/\s+.*$//;
- # fix .?z* at the end
- $line =~ s/\.\?z\*/\.[a-z]z.*/;
- # return what's left as a regex
- my $regex = qr/$initial$line/;
- return $regex, $initial;
-}
-
-=head2 get_pkg_name
-
- my $name = get_pkg_name($str);
-
-C<get_pkg_name()> searches C<$str> for text matching the output of C<makepkg>
-where it outputs the filename of the package it made, and returns it.
-
-=cut
-
-# pull the created package name from the temp file we tee'd to
-sub get_pkg_name {
- my $str = shift;
-
- my ($out) = $str =~ m/^Slackware\s+package\s+([^\s]+)\s+created\.$/m;
-
- return $out;
-}
-
-=head2 get_src_dir
-
- my @dirs = @{ get_src_dir(@orig_dirs) };
-
-C<get_src_dir()> returns a list of the directories under C</tmp/SBo> or C<$TMP>
-that aren't in @orig_dirs.
-
-=cut
-
-sub get_src_dir {
- my @ls = @_;
- my @src_dirs;
- # scripts use either $TMP or /tmp/SBo
- if (opendir(my $tsbo_dh, $tmpd)) {
- FIRST: while (my $ls = readdir $tsbo_dh) {
- next FIRST if in($ls => qw/ . .. /, qr/^package-/, @ls);
- next FIRST unless -d "$tmpd/$ls";
-
- push @src_dirs, $ls;
- }
- close $tsbo_dh;
- }
- return \@src_dirs;
-}
-
-=head2 get_tmp_extfn
-
- my ($ret, $exit) = get_tmp_extfn($fh);
-
-C<get_tmp_extfn()> gets the filename in the form of C</dev/fd/X> for the C<$fh>
-passed in, setting flags on it that make it usable from other processes without
-messing things up.
-
-It returns the filename if successful, otherwise it returns C<undef>.
-
-=cut
-
-# return a filename from a temp fh for use externally
-sub get_tmp_extfn {
- script_error('get_tmp_extfn requires an argument.') unless @_ == 1;
- my $fh = shift;
- unless (fcntl($fh, F_SETFD, 0)) { return undef; }
- return '/dev/fd/'. fileno $fh;
-}
-
-=head2 make_clean
-
- make_clean(SBO => $sbo, SRC => $src, VERSION => $ver);
-
-C<make_clean()> removes source directories, package directories, and compat32
-directories that are left over from a slackbuild run.
-
-It has no useful return value.
-
-=cut
-
-# remove work directories (source and packaging dirs under /tmp/SBo or $TMP and /tmp or $OUTPUT)
-sub make_clean {
- my %args = (
- SBO => '',
- SRC => '',
- VERSION => '',
- @_
- );
- unless ($args{SBO} && $args{SRC} && $args{VERSION}) {
- script_error('make_clean requires three arguments.');
- }
- my $src = $args{SRC};
- say "Cleaning for $args{SBO}-$args{VERSION}...";
- for my $dir (@$src) {
- remove_tree("$tmpd/$dir") if -d "$tmpd/$dir";
- }
-
- my $output = $ENV{OUTPUT} // '/tmp';
- remove_tree("$output/package-$args{SBO}") if
- -d "$output/package-$args{SBO}";
-
- if ($args{SBO} =~ /^(.+)-compat32$/) {
- my $pkg_name = $1;
- remove_tree("/tmp/package-$args{SBO}") if
- not defined $env_tmp and
- -d "/tmp/package-$args{SBO}";
- remove_tree("$tmpd/package-$pkg_name") if
- -d "$tmpd/package-$pkg_name";
- }
- return 1;
-}
-
-=head2 make_distclean
-
- make_distclean(SRC => $src, VERSION => $ver, LOCATION => $loc);
-
-C<make_distclean()> does everything C<make_clean()> does, but in addition it
-also removes distribution files, such as the downloaded source tarballs.
-
-It has no useful return value.
-
-=cut
-
-# remove distfiles
-sub make_distclean {
- my %args = (
- SRC => '',
- VERSION => '',
- LOCATION => '',
- @_
- );
- unless ($args{SRC} && $args{VERSION} && $args{LOCATION}) {
- script_error('make_distclean requires four arguments.');
- }
- my $sbo = get_sbo_from_loc($args{LOCATION});
- make_clean(SBO => $sbo, SRC => $args{SRC}, VERSION => $args{VERSION});
- say "Distcleaning for $sbo-$args{VERSION}...";
- # remove any distfiles for this particular SBo.
- my $downloads = get_sbo_downloads(LOCATION => $args{LOCATION});
- for my $key (keys %$downloads) {
- my $filename = get_filename_from_link($key);
- unlink $filename if -f $filename;
- }
- return 1;
-}
-
-=head2 merge_queues
-
- my @merged = @{ merge_queues([@queue1], [@queue2]) };
-
-C<merge_queues> takes two array references and merges them with C<@queue1> in
-front, and then anything in C<@queue2> that wasn't already in C<@queue1>. This
-is then returned as an array reference.
-
-=cut
-
-sub merge_queues {
- # Usage: merge_queues(\@queue_a, \@queue_b);
- # Results in queue_b being merged into queue_a (without duplicates)
- script_error('merge_queues requires two arguments.') unless @_ == 2;
-
- return [ uniq @{$_[0]}, @{$_[1]} ];
-}
-
-=head2 perform_sbo
-
- my ($pkg, $src, $exit) = perform_sbo(LOCATION => $location, ARCH => $arch);
-
-C<perform_sbo()> preps and runs a .SlackBuild. It returns a list of three
-values, and if the third one is a true value, the first one will be an error
-message. Otherwise the first one will be the package name that was built, and
-the second one will be an array reference containing the source directories
-that were created.
-
-=cut
-
-# prep and run .SlackBuild
-sub perform_sbo {
- my %args = (
- OPTS => 0,
- JOBS => 0,
- LOCATION => '',
- ARCH => '',
- C32 => 0,
- X32 => 0,
- @_
- );
- unless ($args{LOCATION} && $args{ARCH}) {
- script_error('perform_sbo requires LOCATION and ARCH.');
- }
-
- my $location = $args{LOCATION};
- my $sbo = get_sbo_from_loc($location);
-
- # we need to get a listing of /tmp/SBo, or $TMP, if we can, before we run
- # the SlackBuild so that we can compare to a listing taken afterward.
- my @src_ls;
- if (opendir(my $tsbo_dh, $tmpd)) {
- @src_ls = grep { ! in( $_ => qw/ . .. /) } readdir $tsbo_dh;
- }
-
- my ($cmd, %changes);
- # set any changes we need to make to the .SlackBuild, setup the command
-
- $cmd = '';
-
- if ($args{ARCH} eq 'x86_64' and ($args{C32} || $args{X32})) {
- if ($args{C32}) {
- $changes{libdirsuffix} = '';
- } elsif ($args{X32}) {
- $changes{arch_out} = 'i486';
- }
- $cmd .= '. /etc/profile.d/32dev.sh &&';
- }
- if ($args{JOBS} and $args{JOBS} ne 'FALSE') {
- $changes{jobs} = 1;
- }
- $cmd .= " $args{OPTS}" if $args{OPTS};
- $cmd .= " MAKEOPTS=\"-j$args{JOBS}\"" if $changes{jobs};
-
- # set TMP/OUTPUT if set in the environment
- $cmd .= " TMP=$env_tmp" if $env_tmp;
- $cmd .= " OUTPUT=$ENV{OUTPUT}" if defined $ENV{OUTPUT};
- $cmd .= " /bin/bash $location/$sbo.SlackBuild";
-
- # attempt to rewrite the slackbuild, or exit if we can't
- my ($fail, $exit) = rewrite_slackbuild(
- SBO => $sbo,
- SLACKBUILD => "$location/$sbo.SlackBuild",
- CHANGES => \%changes,
- C32 => $args{C32},
- );
- return $fail, undef, $exit if $exit;
-
- # run the slackbuild, grab its exit status, revert our changes
- my $cwd = getcwd();
- chdir $location;
- my ($out, $ret) = run_tee($cmd);
- chdir $cwd;
-
- revert_slackbuild("$location/$sbo.SlackBuild");
- # return error now if the slackbuild didn't exit 0
- return "$sbo.SlackBuild return non-zero\n", undef, _ERR_BUILD if $ret != 0;
- my $pkg = get_pkg_name($out);
- return "$sbo.SlackBuild didn't create a package\n", undef, _ERR_BUILD if not defined $pkg;
- my $src = get_src_dir(@src_ls);
- return $pkg, $src;
-}
-
-=head2 process_sbos
-
- my ($failures, $exit) = process_sbos(TODO => [@queue]);
-
-C<process_sbos()> processes the C<@queue> of slackbuilds and returns a list of
-two values containing any failed builds in an array ref in the first value, and
-the exit status in the second.
-
-=cut
-
-# do the things with the provided sbos - whether upgrades or new installs.
-sub process_sbos {
- my %args = (
- TODO => '',
- CMDS => '',
- OPTS => '',
- JOBS => 'FALSE',
- LOCATIONS => '',
- NOINSTALL => 0,
- NOCLEAN => 'FALSE',
- DISTCLEAN => 'FALSE',
- NON_INT => 0,
- @_
- );
- my $todo = $args{TODO};
- my $cmds = $args{CMDS};
- my $opts = $args{OPTS};
- my $locs = $args{LOCATIONS};
- my $jobs = $args{JOBS} =~ /^\d+$/ ? $args{JOBS} : 0;
- @$todo >= 1 or script_error('process_sbos requires TODO.');
- my (@failures, @symlinks, $err);
- FIRST: for my $sbo (@$todo) {
- my $compat32 = $sbo =~ /-compat32$/ ? 1 : 0;
- my ($temp_syms, $exit) = check_distfiles(
- LOCATION => $$locs{$sbo}, COMPAT32 => $compat32
- );
- # if $exit is defined, prompt to proceed or return with last $exit
- if ($exit) {
- $err = $exit;
- my $fail = $temp_syms;
- push @failures, {$sbo => $fail};
- # return now if we're not interactive
- return \@failures, $exit if $args{NON_INT};
- say "Unable to download/verify source file(s) for $sbo:";
- say " $fail";
- if (prompt('Do you want to proceed?' , default => 'no')) {
- next FIRST;
- } else {
- unlink for @symlinks;
- return \@failures, $exit;
- }
- } else {
- push @symlinks, @$temp_syms;
- }
- }
- my $count = 0;
- FIRST: for my $sbo (@$todo) {
- $count++;
- my $options = $$opts{$sbo} // 0;
- my $cmds = $$cmds{$sbo} // [];
- for my $cmd (@$cmds) {
- system($cmd) == 0 or warn "\"$cmd\" exited non-zero\n";
- }
- # switch compat32 on if upgrading/installing a -compat32
- # else make sure compat32 is off
- my $compat32 = $sbo =~ /-compat32$/ ? 1 : 0;
- my ($version, $pkg, $src, $exit) = do_slackbuild(
- OPTS => $options,
- JOBS => $jobs,
- LOCATION => $$locs{$sbo},
- COMPAT32 => $compat32,
- );
- if ($exit) {
- my $fail = $version;
- push @failures, {$sbo => $fail};
- # return now if we're not interactive
- return \@failures, $exit if $args{NON_INT};
- # or if this is the last $sbo
- return \@failures, $exit if $count == @$todo;
- say "Failure encountered while building $sbo:";
- say " $fail";
- if (prompt('Do you want to proceed?', default => 'no')) {
- next FIRST;
- } else {
- unlink for @symlinks;
- return \@failures, $exit;
- }
- }
-
- do_upgradepkg($pkg) unless $args{NOINSTALL};
-
- unless ($args{DISTCLEAN}) {
- make_clean(SBO => $sbo, SRC => $src, VERSION => $version)
- unless $args{NOCLEAN};
- } else {
- make_distclean(
- SBO => $sbo,
- SRC => $src,
- VERSION => $version,
- LOCATION => $$locs{$sbo},
- );
- }
- # move package to $config{PKG_DIR} if defined
- unless ($config{PKG_DIR} eq 'FALSE') {
- my $dir = $config{PKG_DIR};
- unless (-d $dir) {
- mkdir($dir) or warn "Unable to create $dir\n";
- }
- if (-d $dir) {
- move($pkg, $dir), say "$pkg stored in $dir";
- } else {
- warn "$pkg left in $tmpd\n";
- }
- } elsif ($args{DISTCLEAN}) {
- unlink $pkg;
- }
- }
- unlink for @symlinks;
- return \@failures, $err;
-}
-
-=head2 revert_slackbuild
-
- revert_slackbuild($path);
-
-C<revert_slackbuild()> moves back a slackbuild that was rewritten by
-C<rewrite_slackbuild()>.
-
-There is no useful return value.
-
-=cut
-
-# move a backed-up .SlackBuild file back into place
-sub revert_slackbuild {
- script_error('revert_slackbuild requires an argument') unless @_ == 1;
- my $slackbuild = shift;
- if (-f "$slackbuild.orig") {
- unlink $slackbuild if -f $slackbuild;
- rename "$slackbuild.orig", $slackbuild;
- }
- return 1;
-}
-
-=head2 rewrite_slackbuild
-
- my ($ret, $exit) = rewrite_slackbuild(SLACKBUILD => $path);
-
-C<rewrite_slackbuild()> when given a path and some changes to make, will move
-and copy the C<$path> and rewrite the copy with the needed changes.
-
-It returns a list of two values. The second value is the exit status, and if it
-is true, the first value will be an error message.
-
-=cut
-
-# make a backup of the existent SlackBuild, and rewrite the original as needed
-sub rewrite_slackbuild {
- my %args = (
- SBO => '',
- SLACKBUILD => '',
- CHANGES => {},
- C32 => 0,
- @_
- );
- $args{SLACKBUILD} or script_error('rewrite_slackbuild requires SLACKBUILD.');
- my $slackbuild = $args{SLACKBUILD};
- my $changes = $args{CHANGES};
-
- # $status will be undefined if either the rename or the copy fails, otherwise it will be 1
- my $status = eval {
- rename($slackbuild, "$slackbuild.orig") or die "not ok";
- copy("$slackbuild.orig", $slackbuild) or die "not ok";
- 1;
- };
- if (not $status) {
- rename "$slackbuild.orig", $slackbuild if not -f $slackbuild;
- return "Unable to backup $slackbuild to $slackbuild.orig\n",
- _ERR_OPENFH;
- }
-
- my $libdir_regex = qr/^\s*LIBDIRSUFFIX="64"\s*$/;
- my $arch_regex = qr/\$VERSION-\$ARCH-\$BUILD/;
- my $dc_regex = qr/(?<![a-z])(tar|p7zip|unzip|ar|rpm2cpio|sh)\s+/;
- my $make_regex = qr/^\s*make\s*$/;
- # tie the slackbuild, because this is the easiest way to handle this.
- tie my @sb_file, 'Tie::File', $slackbuild;
- # if we're dealing with a compat32, we need to change the tar line(s) so
- # that the 32-bit source is untarred
- if ($args{C32}) {
- my $location = get_sbo_location($args{SBO});
- my $downloads = get_sbo_downloads(
- LOCATION => $location,
- 32 => 1,
- );
- my $fns = get_dl_fns([keys %$downloads]);
- for my $line (@sb_file) {
- if ($line =~ $dc_regex) {
- my ($regex, $initial) = get_dc_regex($line);
- for my $fn (@$fns) {
- $fn = "$initial$fn";
- $line =~ s/$regex/$fn/ if $fn =~ $regex;
- }
- }
- }
- }
- for my $line (@sb_file) {
- # then check for and apply any other %$changes
- if (exists $$changes{libdirsuffix}) {
- $line =~ s/64/$$changes{libdirsuffix}/ if $line =~ $libdir_regex;
- }
- if (exists $$changes{arch_out}) {
- $line =~ s/\$ARCH/$$changes{arch_out}/ if $line =~ $arch_regex;
- }
- if (exists $changes->{jobs}) {
- $line =~ s/make/make \$MAKEOPTS/ if $line =~ $make_regex;
- }
- }
- untie @sb_file;
- return 1;
-}
-
-=head2 run_tee
-
- my ($output, $exit) = run_tee($cmd);
-
-C<run_tee()> runs the C<$cmd >under C<tee(1)> to allow both displaying its
-output and returning it as a string. It returns a list of the output and the
-exit status (C<$?> in bash). If it can't even run the bash interpreter, the
-output will be C<undef> and the exit status will hold a true value.
-
-=cut
-
-sub run_tee {
- my $cmd = shift;
-
- my $tempdir = tempdir(CLEANUP => 1, DIR => $tmpd);
-
- my $out_fh = tempfile(DIR => $tempdir);
- my $out_fn = get_tmp_extfn($out_fh);
- return undef, _ERR_F_SETFD if not defined $out_fn;
-
- my $exit_fh = tempfile(DIR => $tempdir);
- my $exit_fn = get_tmp_extfn($exit_fh);
- return undef, _ERR_F_SETFD if not defined $exit_fn;
-
- $cmd = sprintf '( %s; echo $? > %s ) | tee %s', $cmd, $exit_fn, $out_fn;
-
- my $ret = system('/bin/bash', '-c', $cmd);
-
- return undef, $ret if $ret;
-
- seek $exit_fh, 0, 0;
- chomp($ret = readline $exit_fh);
-
- seek $out_fh, 0, 0;
- my $out = do { local $/; readline $out_fh; };
-
- return $out, $ret;
-}
-
-sub _build_queue {
- my ($sbos, $warnings) = @_;
- my @queue = @$sbos;
- my @result;
-
- while (my $sbo = shift @queue) {
- next if $sbo eq "%README%";
- my $reqs = get_requires($sbo);
- if (defined $reqs) {
- push @result, _build_queue($reqs, $warnings);
- foreach my $req (@$reqs) {
- $warnings->{$sbo}="%README%" if $req eq "%README%";
- }
- }
- else {
- $warnings->{$sbo} = "nonexistent";
- }
- push @result, $sbo;
- }
-
- return uniq @result;
-}
-
-1;