aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SBO-Lib/lib/SBO/Lib.pm123
-rwxr-xr-xsbocheck51
-rwxr-xr-xsboclean9
-rwxr-xr-xsboconfig45
-rwxr-xr-xsbofind40
-rwxr-xr-xsboinstall4
-rwxr-xr-xsbosnap7
-rwxr-xr-xsboupgrade121
-rw-r--r--t/SBO/Lib.pm686
-rwxr-xr-xt/prep.pl47
-rwxr-xr-xt/test.t262
11 files changed, 483 insertions, 912 deletions
diff --git a/SBO-Lib/lib/SBO/Lib.pm b/SBO-Lib/lib/SBO/Lib.pm
index 3f75d80..959fe22 100644
--- a/SBO-Lib/lib/SBO/Lib.pm
+++ b/SBO-Lib/lib/SBO/Lib.pm
@@ -10,8 +10,8 @@
# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING>
use 5.12.3;
-use warnings FATAL => 'all';
use strict;
+use warnings FATAL => 'all';
package SBO::Lib 0.7;
my $version = "0.7";
@@ -35,7 +35,10 @@ our @EXPORT = qw(
get_sbo_location
get_from_info
get_tmp_extfn
- get_tmp_perlfn
+ $tempdir
+ $conf_dir
+ $conf_file
+ %config
);
$< == 0 or die "This script requires root privileges.\n";
@@ -46,7 +49,6 @@ use Digest::MD5;
use File::Copy;
use File::Path qw(make_path remove_tree);
use Fcntl;
-use File::Find;
use File::Temp qw(tempdir tempfile);
use Fcntl qw(F_SETFD F_GETFD);
@@ -55,12 +57,12 @@ our $tempdir = tempdir (CLEANUP => 1);
# subroutine for throwing internal script errors
sub script_error (;$) {
exists $_[0] ? die "A fatal script error has occurred:\n$_[0]\nExiting.\n"
- : die "A fatal script error has occurred: Exiting.\n";
+ : die "A fatal script error has occurred. Exiting.\n";
}
# sub for opening files, second arg is like '<','>', etc
-sub open_fh {
- exists $_[1] or script_error ('open_fh requires two arguments');
+sub open_fh ($$) {
+ exists $_[1] or script_error 'open_fh requires two arguments';
unless ($_[1] eq '>') {
-f $_[0] or script_error 'open_fh first argument not a file';
}
@@ -73,7 +75,7 @@ sub open_read ($) {
return open_fh shift, '<';
}
-# pull in configuration, set sane defaults, etc.
+# global config variables
our $conf_dir = '/etc/sbotools';
our $conf_file = "$conf_dir/sbotools.conf";
our %config = (
@@ -84,20 +86,23 @@ our %config = (
SBO_HOME => 'FALSE',
);
-# if the conf file exists, pull all the $key=$value pairs into a hash
-my %conf_values;
-if (-f $conf_file) {
- my $fh = open_read ($conf_file);
- my $text = do {local $/; <$fh>};
- %conf_values = $text =~ /^(\w+)=(.*)$/mg;
- close $fh;
+# subroutine to suck in config in order to facilitate unit testing
+sub read_config () {
+ my %conf_values;
+ if (-f $conf_file) {
+ my $fh = open_read $conf_file;
+ my $text = do {local $/; <$fh>};
+ %conf_values = $text =~ /^(\w+)=(.*)$/mg;
+ close $fh;
+ }
+ for my $key (keys %config) {
+ $config{$key} = $conf_values{$key} if exists $conf_values{$key};
+ }
+ $config{JOBS} = 'FALSE' unless $config{JOBS} =~ /^\d+$/;
+ $config{SBO_HOME} = '/usr/sbo' if $config{SBO_HOME} eq 'FALSE';
}
-for my $key (keys %config) {
- $config{$key} = $conf_values{$key} if exists $conf_values{$key};
-}
-$config{JOBS} = 'FALSE' unless $config{JOBS} =~ /^\d+$/;
-$config{SBO_HOME} = '/usr/sbo' if $config{SBO_HOME} eq 'FALSE';
+read_config;
# some stuff we'll need later.
my $distfiles = "$config{SBO_HOME}/distfiles";
@@ -106,8 +111,8 @@ my $name_regex = '\ASLACKBUILD\s+NAME:\s+';
sub show_version () {
say "sbotools version $version";
- say "licensed under the WTFPL";
- say "<http://sam.zoy.org/wtfpl/COPYING>";
+ say 'licensed under the WTFPL';
+ say '<http://sam.zoy.org/wtfpl/COPYING>';
}
# %supported maps what's in /etc/slackware-version to what's at SBo
@@ -127,7 +132,7 @@ sub get_slack_version () {
# does the SLACKBUILDS.TXT file exist in the sbo tree?
sub chk_slackbuilds_txt () {
- return -f $slackbuilds_txt ? 1 : 0;
+ return -f $slackbuilds_txt ? 1 : undef;
}
# check for the validity of new $config{SBO_HOME}
@@ -140,8 +145,9 @@ sub check_home () {
die "$sbo_home exists and is not empty. Exiting.\n";
}
} else {
- make_path ($sbo_home) or die "Unable to create $sbo_home.\n";
+ make_path ($sbo_home) or die "Unable to create $sbo_home.\n";
}
+ return 1;
}
# rsync the sbo tree from slackbuilds.org to $config{SBO_HOME}
@@ -150,19 +156,19 @@ sub rsync_sbo_tree () {
my @arg = ('rsync', '-a', '--exclude=*.tar.gz', '--exclude=*.tar.gz.asc');
push @arg, "rsync://slackbuilds.org/slackbuilds/$slk_version/*";
my $out = system @arg, $config{SBO_HOME};
- say "Finished." and return $out;
+ say 'Finished.' and return $out;
}
# wrappers for differing checks and output
sub fetch_tree () {
check_home;
- say "Pulling SlackBuilds tree...";
+ say 'Pulling SlackBuilds tree...';
rsync_sbo_tree, return 1;
}
sub update_tree () {
fetch_tree, return unless chk_slackbuilds_txt;
- say "Updating SlackBuilds tree...";
+ say 'Updating SlackBuilds tree...';
rsync_sbo_tree, return 1;
}
@@ -171,8 +177,8 @@ sub update_tree () {
sub slackbuilds_or_fetch () {
unless (chk_slackbuilds_txt) {
say 'It looks like you haven\'t run "sbosnap fetch" yet.';
- print "Would you like me to do this now? [y] ";
- <STDIN> =~ /^[Yy\n]/ ? fetch_tree () :
+ print 'Would you like me to do this now? [y] ';
+ <STDIN> =~ /^[Yy\n]/ ? fetch_tree :
die "Please run \"sbosnap fetch\"\n";
}
return 1;
@@ -240,14 +246,14 @@ sub get_from_info (%) {
$$vars{$key} = [$$vars{$key}];
}
}
- return exists $$vars{$args{GET}} ? $$vars{$args{GET}} : 0;
+ return exists $$vars{$args{GET}} ? $$vars{$args{GET}} : undef;
}
# find the version in the tree for a given sbo (provided a location)
sub get_sbo_version ($) {
- exists $_[0] or script_error 'get_sbo_version requires an arguments';
+ exists $_[0] or script_error 'get_sbo_version requires an argument.';
my $version = get_from_info (LOCATION => shift, GET => 'VERSION');
- return $$version[0] ? $$version[0] : 0;
+ return $$version[0] ? $$version[0] : undef;
}
# for each installed sbo, find out whether or not the version in the tree is
@@ -287,9 +293,9 @@ sub get_download_info (%) {
if ($args{X64}) {
my $nothing;
if (! $$downs[0]) {
- $nothing = 1;
+ $nothing++;
} elsif ($$downs[0] =~ qr/^UN(SUPPOR|TES)TED$/) {
- $nothing = 1;
+ $nothing++;
}
if ($nothing) {
$args{X64} = 0;
@@ -336,7 +342,9 @@ sub get_sbo_downloads (%) {
# given a link, grab the filename from the end of it
sub get_filename_from_link ($) {
exists $_[0] or script_error 'get_filename_from_link requires an argument';
- return "$distfiles/". (shift =~ qr#/([^/]+)$#)[0];
+ my $fn = shift;
+ my $regex = qr#/([^/]+)$#;
+ return $fn =~ $regex ? $distfiles .'/'. ($fn =~ $regex)[0] : undef;
}
# for a given file, computer its md5sum
@@ -353,7 +361,7 @@ sub compute_md5sum ($) {
sub compare_md5s ($$) {
exists $_[1] or script_error 'compare_md5s requires two arguments.';
my ($first, $second) = @_;
- return $first eq $second ? 1 : 0;
+ return $first eq $second ? 1 : undef;
}
# for a given distfile, see whether or not it exists, and if so, if its md5sum
@@ -384,7 +392,7 @@ sub get_distfile ($$) {
return 1;
}
-# for a given distfile, what will be the full path of the symlink?
+# for a given distfile, figure out what the full path to its symlink will be
sub get_symlink_from_filename ($$) {
exists $_[1] or script_error
'get_symlink_from_filename requires two arguments';
@@ -398,12 +406,12 @@ sub get_symlink_from_filename ($$) {
sub check_x32 ($) {
exists $_[0] or script_error 'check_x32 requires an argument.';
my $dl = get_from_info (LOCATION => shift, GET => 'DOWNLOAD_x86_64');
- return $$dl[0] =~ /UN(SUPPOR|TES)TED/ ? 1 : 0;
+ return $$dl[0] =~ /UN(SUPPOR|TES)TED/ ? 1 : undef;
}
# can't do 32-bit on x86_64 without this file, so we'll use it as the test to
# to determine whether or not an x86_64 system is setup for multilib
-sub check_multilib {
+sub check_multilib () {
return 1 if -f '/etc/profile.d/32dev.sh';
return;
}
@@ -419,7 +427,7 @@ sub rewrite_slackbuild ($$%) {
my $libdir_regex = qr/^\s*LIBDIRSUFFIX="64"\s*$/;
my $make_regex = qr/^\s*make(| \Q||\E exit 1)$/;
my $arch_regex = qr/\$VERSION-\$ARCH-\$BUILD/;
- # tie the slackbuilds, because this is the easiest way to handle this.
+ # tie the slackbuild, because this is the easiest way to handle this.
tie my @sb_file, 'Tie::File', $slackbuild;
for my $line (@sb_file) {
# get the output of the tar and makepkg commands. hope like hell that v
@@ -427,7 +435,7 @@ sub rewrite_slackbuild ($$%) {
if ($line =~ $tar_regex || $line =~ $makepkg_regex) {
$line = "$line | tee -a $tempfn";
}
- # then check for and apply any %changes
+ # then check for and apply any other %changes
if (exists $changes{libdirsuffix}) {
$line =~ s/64/$changes{libdirsuffix}/ if $line =~ $libdir_regex;
}
@@ -460,9 +468,7 @@ sub check_distfiles (%) {
my %dists = @_;
for my $link (keys %dists) {
my $md5sum = $dists{$link};
- unless (verify_distfile $link, $md5sum) {
- die unless get_distfile $link, $md5sum;
- }
+ get_distfile $link, $md5sum unless verify_distfile $link, $md5sum;
}
return 1;
}
@@ -518,28 +524,14 @@ sub get_pkg_name ($) {
REGEX => qr/^Slackware\s+package\s+([^\s]+)\s+created\.$/);
}
-# clear the close-on-exec bit from a temp file handle
-sub clear_coe_bit ($) {
- exists $_[0] or script_error 'clear_coe_bit requires an argument';
- my $fh = shift;
- fcntl ($fh, F_SETFD, 0) or die "no unset exec-close thingy\n";
- return $fh;
-}
-
# return a filename from a temp fh for use externally
sub get_tmp_extfn ($) {
exists $_[0] or script_error 'get_tmp_extfn requires an argument.';
- my $fh = clear_coe_bit shift;
+ my $fh = shift;
+ fcntl ($fh, F_SETFD, 0) or die "Can't unset exec-on-close bit\n";
return '/dev/fd/'. fileno $fh;
}
-# return a filename from a temp fh for use internally
-sub get_tmp_perlfn ($) {
- exists $_[0] or script_error 'get_tmp_perlfn requires an argument.';
- my $fh = clear_coe_bit shift;
- return '+<=&'. fileno $fh;
-}
-
# prep and run .SlackBuild
sub perform_sbo (%) {
my %args = (
@@ -557,7 +549,7 @@ sub perform_sbo (%) {
my $location = $args{LOCATION};
my $sbo = get_sbo_from_loc $location;
my ($cmd, %changes);
- # figure out any changes we need to make to the .SlackBuild
+ # set any changes we need to make to the .SlackBuild, setup the command
$changes{make} = "-j $args{JOBS}" if $args{JOBS};
if ($args{ARCH} eq 'x86_64' and ($args{C32} || $args{X32})) {
if ($args{C32}) {
@@ -574,7 +566,7 @@ sub perform_sbo (%) {
rewrite_slackbuild "$location/$sbo.SlackBuild", $fn, %changes;
chdir $location, my $out = system $cmd;
revert_slackbuild "$location/$sbo.SlackBuild";
- die unless $out == 0;
+ die "$sbo.SlackBuild returned non-zero ext status\n" unless $out == 0;
my $pkg = get_pkg_name $tempfh;
my $src = get_src_dir $tempfh;
return $pkg, $src;
@@ -587,7 +579,8 @@ sub do_convertpkg ($) {
my $tempfh = tempfile (DIR => $tempdir);
my $fn = get_tmp_extfn $tempfh;
my $cmd = "/usr/sbin/convertpkg-compat32 -i $pkg -d /tmp | tee $fn";
- system ($cmd) == 0 or die;
+ system ($cmd) == 0 or
+ die "convertpkg-compt32 returned non-zero exit status\n";
unlink $pkg;
return get_pkg_name $tempfh;
}
@@ -645,7 +638,7 @@ sub do_slackbuild (%) {
# remove work directories (source and packaging dirs under /tmp/SBo)
sub make_clean ($$$) {
- exists $_[1] or script_error 'make_clean requires two arguments.';
+ exists $_[2] or script_error 'make_clean requires three arguments.';
my ($sbo, $src, $version) = @_;
say "Cleaning for $sbo-$version...";
my $tmpsbo = "/tmp/SBo";
@@ -667,8 +660,8 @@ sub make_distclean (%) {
}
my $sbo = get_sbo_from_loc $args{LOCATION};
make_clean $sbo, $args{SRC}, $args{VERSION};
- say "Distcleaning for $sbo-$version...";
- # remove any distfiles for this particular SBo
+ 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;
diff --git a/sbocheck b/sbocheck
index 18c3e7c..f8d89c2 100755
--- a/sbocheck
+++ b/sbocheck
@@ -10,15 +10,11 @@
# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING>
use 5.12.3;
+use strict;
+use warnings FATAL => 'all';
use SBO::Lib;
-use File::Basename;
use Getopt::Std;
use Text::Tabulate;
-use warnings FATAL => 'all';
-use strict;
-
-my %config = %SBO::Lib::config;
-my $self = basename ($0);
my %options;
getopts ('v',\%options);
@@ -27,24 +23,35 @@ show_version && exit 0 if exists $options{v};
update_tree;
-say "Checking for updated SlackBuilds...";
-my $updates = get_available_updates;
-
-# pretty formatting.
-my @listing;
-for my $up (@$updates) {
- my $string = "$$up{name}-$$up{installed}";
- $string .= " < needs updating (SBo has $$up{update})\n";
- push @listing, $string;
+# retrieve and format list of available updates
+sub get_update_list () {
+ print "Checking for updated SlackBuilds...\n";
+ my $updates = get_available_updates;
+ # pretty formatting.
+ my @listing;
+ for my $update (@$updates) {
+ my $string = "$$update{name}-$$update{installed}";
+ $string .= " < needs updating (SBo has $$update{update})\n";
+ push @listing, $string;
+ }
+ return \@listing;
}
-if (exists $listing[0]) {
- my $tab = new Text::Tabulate ();
- $tab->configure (tab => '\s');
- my $output = $tab->format (@listing);
- say "\n". $output;
-} else {
- say "\nNo updates available.";
+# Text::Tabulate and print list of updates
+sub print_output ($) {
+ exists $_[0] or script_error 'print_output requires an argument';
+ my $listing = shift;
+ if (exists $$listing[0]) {
+ my $tab = new Text::Tabulate ();
+ $tab->configure (tab => '\s');
+ my $output = $tab->format (@$listing);
+ say "\n". $output;
+ } else {
+ say "\nNo updates available.";
+ }
}
+my $output = get_update_list;
+print_output $output;
+
exit 0;
diff --git a/sboclean b/sboclean
index 61d0ce6..fef857f 100755
--- a/sboclean
+++ b/sboclean
@@ -10,14 +10,13 @@
# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING>
use 5.12.3;
+use strict;
+use warnings FATAL => 'all';
use SBO::Lib;
use File::Basename;
use Getopt::Std;
use File::Path qw(remove_tree);
-use strict;
-use warnings FATAL => 'all';
-my %config = %SBO::Lib::config;
my $self = basename ($0);
sub show_usage () {
@@ -64,7 +63,7 @@ sub remove_stuff ($) {
}
}
-remove_stuff ($config{SBO_HOME} . '/distfiles') if $clean_dist;
-remove_stuff ('/tmp/SBo') if $clean_work;
+remove_stuff $config{SBO_HOME} . '/distfiles' if $clean_dist;
+remove_stuff '/tmp/SBo' if $clean_work;
exit 0;
diff --git a/sboconfig b/sboconfig
index 1dfa74f..a3a3096 100755
--- a/sboconfig
+++ b/sboconfig
@@ -19,7 +19,6 @@ use File::Copy;
use File::Path qw(make_path);
use File::Temp qw(tempfile);;
-my %config = %SBO::Lib::config;
my $self = basename ($0);
sub show_usage () {
@@ -80,48 +79,50 @@ if (exists $changes{JOBS}) {
($changes{JOBS} =~ /^\d+$/ || $changes{JOBS} eq 'FALSE');
}
-my $conf_dir = $SBO::Lib::conf_dir;;
-my $conf_file = $SBO::Lib::conf_file;
-
-# safely modify our conf file; copy to a temp location, edit the temp file,
-# move the edited file into place
+# safely modify our conf file; write its contents to a temp file, modify the
+# temp file, write the contents of the temp file back to the conf file
sub config_write ($$) {
exists $_[1] or script_error 'config_write requires two arguments.';
my ($key, $val) = @_;
if (! -d $conf_dir) {
- mkdir ($conf_dir) or die "Unable to create $conf_dir. Exiting.\n";
+ mkdir $conf_dir or die "Unable to create $conf_dir. Exiting.\n";
}
if (-f $conf_file) {
- my $tempfh = tempfile (DIR => $SBO::Lib::tempdir);
- my $tempfn = get_tmp_perlfn $tempfh;
- copy ($conf_file, $tempfn);
- # tie the file so that if $key is already there, we just change that
- # line and untie it
- tie my @temp, 'Tie::File', $tempfn;
- my $has = 0;
+ my $tempfh = tempfile (DIR => $tempdir);
+ my $conffh = open_read $conf_file;
+ my $conftents = do {local $/; <$conffh>};
+ print {$tempfh} $conftents;
+ # tie the temp file so that if $key is already there, we just change
+ # that line and untie it
+ tie my @temp, 'Tie::File', $tempfh;
+ my $has;
my $regex = qr/\A\Q$key\E=/;
FIRST: for my $tmpline (@temp) {
$has++, $tmpline = "$key=$val", last FIRST if $tmpline =~ $regex;
}
untie @temp;
# otherwise, append our new $key=$value pair
- unless ($has) {
- my $fh = open_fh ($tempfn, '>>');
- print {$fh} "$key=$val\n";
- close $fh;
- }
- move ($tempfn, $conf_file);
+ print {$tempfh} "$key=$val\n" unless $has;
+ # then over write the conf file with the contents of the temp file
+ seek $tempfh, 0, 0;
+ my $contents = do {local $/; <$tempfh>};
+ close $conffh;
+ eval { $conffh = open_fh $conf_file, '>' };
+ warn "Cannot write configuration: $@\n" and return if $@;
+ print {$conffh} $contents or return;
+ close $conffh, close $tempfh;
} else {
# no config file, easiest case of all.
- my $fh = open_fh $conf_file, '>';
+ my $fh = open_fh $conf_file, '>' or return;
print {$fh} "$key=$val\n";
close $fh;
}
+ return 1;
}
while (my ($key, $value) = each %changes) {
say "Setting $key to $value...";
- config_write $key, $value;
+ config_write $key, $value or warn "Unable to write to $conf_file\n";
}
exit 0;
diff --git a/sbofind b/sbofind
index 055ce9b..d977072 100755
--- a/sbofind
+++ b/sbofind
@@ -10,13 +10,12 @@
# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING>
use 5.12.3;
+use strict;
+use warnings FATAL => 'all';
use SBO::Lib;
use File::Basename;
use Getopt::Std;
-use strict;
-use warnings FATAL => 'all';
-my %config = %SBO::Lib::config;
my $self = basename ($0);
sub show_usage () {
@@ -51,26 +50,31 @@ my $search = $ARGV[0];
slackbuilds_or_fetch;
# find anything with $search in its name
-my ($findings, $name);
-my $found = 0;
-my $name_regex = qr/NAME:\s+(.*\Q$search\E.*)$/i;
-my $loc_regex = qr/LOCATION:\s+(.*)$/;
-my $fh = open_read "$config{SBO_HOME}/SLACKBUILDS.TXT";
-FIRST: while (my $line = <$fh>) {
- unless ($found) {
- $found++, next FIRST if $name = ($line =~ $name_regex)[0];
- } else {
- if (my ($location) = ($line =~ $loc_regex)[0]) {
- $found = 0;
- $location =~ s#^\.##;
- push @$findings, {$name => $config{SBO_HOME} . $location};
+sub perform_search ($) {
+ exists $_[0] or script_error 'perform_search requires an argument.';
+ my $search = shift;
+ my (@findings, $name, $found);
+ my $name_regex = qr/NAME:\s+(.*\Q$search\E.*)$/i;
+ my $loc_regex = qr/LOCATION:\s+(.*)$/;
+ my $fh = open_read "$config{SBO_HOME}/SLACKBUILDS.TXT";
+ FIRST: while (my $line = <$fh>) {
+ unless ($found) {
+ $found++, next FIRST if $name = ($line =~ $name_regex)[0];
+ } else {
+ if (my ($location) = ($line =~ $loc_regex)[0]) {
+ $found = 0;
+ $location =~ s#^\.##;
+ push @findings, {$name => $config{SBO_HOME} . $location};
+ }
}
}
+ return \@findings;
}
+# pull the contents of a file into a variable and format it for output
sub get_file_contents ($) {
exists $_[0] or script_error 'get_file_contents requires an argument';
- -f $_[0] or script_error 'get_file_contents argument is not a file';
+ -f $_[0] or return "$_[0] doesn't exist.\n";
my $fh = open_read shift;
my $contents = do {local $/; <$fh>};
$contents =~ s/\n/\n /g;
@@ -78,6 +82,8 @@ sub get_file_contents ($) {
return $contents;
}
+perform_search $search;
+
# pretty formatting
if (exists $$findings[0]) {
my @listing = ("\n");
diff --git a/sboinstall b/sboinstall
index f54a758..5216345 100755
--- a/sboinstall
+++ b/sboinstall
@@ -10,11 +10,11 @@
# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING>
use 5.12.3;
+use strict;
+use warnings FATAL => 'all';
use SBO::Lib;
use Getopt::Std;
use File::Basename;
-use strict;
-use warnings FATAL => 'all';
my $self = basename ($0);
diff --git a/sbosnap b/sbosnap
index 7628474..b3e0dff 100755
--- a/sbosnap
+++ b/sbosnap
@@ -9,17 +9,14 @@
# author: Jacob Pipkin <j@dawnrazor.net>
# date: Setting Orange, the 37th day of Discord in the YOLD 3178
# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING>
-# changelog:
-# .01: initial creation.
use 5.12.3;
+use strict;
+use warnings FATAL => 'all';
use SBO::Lib;
use File::Basename;
use Getopt::Std;
-use warnings FATAL => 'all';
-use strict;
-my %config = %SBO::Lib::config;
my $sbo_home = $config{SBO_HOME};
my $self = basename ($0);
diff --git a/sboupgrade b/sboupgrade
index 6d92d1c..7b7b46d 100755
--- a/sboupgrade
+++ b/sboupgrade
@@ -10,14 +10,13 @@
# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING>
use 5.12.3;
+use strict;
+use warnings FATAL => 'all';
use SBO::Lib;
use File::Basename;
use Getopt::Std;
use File::Copy;
-use strict;
-use warnings FATAL => 'all';
-my %config = %SBO::Lib::config;
my $self = basename ($0);
sub show_usage () {
@@ -96,8 +95,8 @@ sub get_inst_names ($) {
}
# this subroutine may be getting a little out of hand.
-sub grok_requirements ($$) {
- exists $_[1] or script_error 'grok_requirements requires two arguments';
+sub get_requires ($$) {
+ exists $_[1] or script_error 'get_requires requires two arguments';
return if $no_reqs;
my ($sbo, $readme) = @_;
my $readme_orig = $readme;
@@ -133,58 +132,68 @@ sub grok_requirements ($$) {
splice @deps, $rem, 1;
$_-- for @remove;
}
- return unless exists $deps[0];
- FIRST: for my $need (@deps) {
- # compare against installed slackbuilds
- my $tempname = $compat32 eq 'TRUE' ? "$need-compat32" : $need;
+ return \@deps;
+
+# ask to install any requirements found
+sub ask_requires ($$$) {
+ exists $_[2] or script_error 'ask_requires requires three arguments.';
+ my ($requires, $readme, $sbo) = shift;
+ FIRST: for my $req (@$requires) {
+ my $name = $compat32 ? "$req-compat32" : $req;
my $inst = get_installed_sbos;
my $inst_names = get_inst_names $inst;
- next FIRST if $tempname ~~ @$inst_names;
- print "\n". $readme_orig;
- print "\nIt looks like this slackbuild requires $tempname; shall I";
+ next FIRST if $name ~~ @$inst_names;
+ say $readme;
+ print "\nIt looks like this slackbuild requires $name; shall I";
print " attempt to install it first? [y] ";
if (<STDIN> =~ /^[Yy\n]/) {
- my @args = ("/usr/sbin/sboupgrade", '-oN');
+ my @args = ('/usr/sbin/sboupgrade', '-oN');
# populate args so that they carry over correctly
- push @args, "-c" if exists $options{c};
- push @args, "-d" if exists $options{d};
+ for my $arg (qw(c d p)) {
+ push @args, "-$arg" if exists $options{$arg};
+ }
push @args, "-j $options{j}" if exists $options{j};
- push @args, "-p" if $compat32;
- push @args, $need;
- system (@args) == 0 or
- die "Requirement failure, unable to proceed.\n";
+ system (@args, $req) == 0 or die "$name failed to install.\n";
}
}
return;
}
# look for any (user|group)add commands in the README
-sub grok_user_group ($) {
- exists $_[0] or script_error 'grok_user_group requires an argument';
+sub get_user_group ($) {
+ exists $_[0] or script_error 'get_user_group requires an argument';
my $readme = shift;
- my $readme_array = [split /\n/, $readme];
- my $cmd_regex = qr/^\s*#\s+((user|group)add.*)/;
- my @cmds;
- push @cmds, ($_ =~ $cmd_regex)[0] for @$readme_array;
- return unless exists $cmds[0];
+ my @cmds = $readme =~ /^\s*#*\s*(useradd.*|groupadd.*)/mg;
+ return \@cmds;
+}
+
+# offer to run any user/group add commands
+sub ask_user_group ($$) {
+ exists $_[1] or script_error 'ask_user_group requires two arguments';
+ my ($cmds, $readme) = shift;
say "\n". $readme;
- print "\nIt looks like this slackbuild requires the following command(s)";
- say ' to be run first:';
- say " # $_" for @cmds;
+ print "\nIt looks like this slackbuild requires the following";
+ say " command(s) to be run first:";
+ say " # $_" for @$cmds;
print "Shall I run it/them now? [y] ";
if (<STDIN> =~ /^[Yy\n]/) {
- for my $cmd (@cmds) {
- system ($cmd == 0) or warn "\"$cmd\" exited non-zero\n";
+ for my $cmd (@$cmds) {
+ system ($cmd) == 0 or warn "\"$cmd\" exited non-zero\n";
}
}
- return 1;
}
# see if the README mentions any options
-sub grok_options ($) {
- exists $_[0] or script_error 'grok_options requires an argument';
+sub get_opts ($) {
+ exists $_[0] or script_error 'get_opts requires an argument';
+ my $readme = shift;
+ return $readme =~ /[A-Z]+=[^\s]/ ? 1 : undef;
+}
+
+# provide an opportunity to set options
+sub ask_opts ($) {
+ exists $_[0] or script_error 'ask_opts requires an argument';
my $readme = shift;
- return unless $readme =~ /[A-Z]+=[^\s]/;
say "\n". $readme;
print "\nIt looks this slackbuilds has options; would you like to set any";
print " when the slackbuild is run? [n] ";
@@ -196,10 +205,10 @@ sub grok_options ($) {
return $opts;
};
my $kv_regex = qr/[A-Z]+=[^\s]+(|\s([A-Z]+=[^\s]+){0,})/;
- my $opts = &$ask ();
+ my $opts = &$ask;
FIRST: while ($opts !~ $kv_regex) {
warn "Invalid input received.\n";
- $opts = &$ask ();
+ $opts = &$ask;
}
return $opts;
}
@@ -213,10 +222,15 @@ sub readme_prompt ($) {
my $fh = open_read (get_readme_path $sbo);
my $readme = do {local $/; <$fh>};
close $fh;
- # check for requirements, useradd/groupadd, options
- grok_requirements $sbo, $readme;
- grok_user_group $readme;
- my $opts = grok_options $readme;
+ # check for requirements, offer to install any found
+ my $requires = get_requires $sbo, $readme;
+ ask_requires $requires, $readme, $sbo if ref $requires eq 'ARRAY';
+ # check for user/group add commands, offer to run any found
+ my $user_group = get_user_group $readme;
+ ask_user_group $user_group, $readme if ref $user_group eq 'ARRAY';
+ # check for options mentioned in the README
+ my $opts;
+ $opts = ask_opts $readme if get_opts $readme;
print "\n". $readme unless $opts;
# present the name as -compat32 if appropriate
my $name = $compat32 ? "$sbo-compat32" : $sbo;
@@ -229,7 +243,7 @@ sub readme_prompt ($) {
sub process_sbos ($) {
exists $_[0] or script_error 'process_sbos requires an argument.';
my $todo = shift;
- my @failures;
+ my %failures;
FIRST: for my $sbo (@$todo) {
my $opts = 0;
$opts = readme_prompt $sbo unless $no_readme;
@@ -243,7 +257,7 @@ sub process_sbos ($) {
COMPAT32 => $compat32,
); };
if ($@) {
- push @failures, $sbo;
+ $failures{$sbo} = $@;
} else {
unless ($distclean eq 'TRUE') {
make_clean $sbo, $src, $version unless $noclean eq 'TRUE';
@@ -272,13 +286,16 @@ sub process_sbos ($) {
}
}
}
- return @failures;
+ return %failures;
}
-sub print_failures (;@) {
+sub print_failures (;%) {
if (exists $_[0]) {
+ my %failures = @_;
say "Failures:";
- say " $_" for @_;
+ while (my ($key, $val) = each %failures) {
+ say " $key: $val";
+ }
exit 1;
}
}
@@ -306,20 +323,20 @@ unless ($force) {
push @$todo_upgrade, $sbo if $sbo ~~ @$inst_names;
}
}
-my @failures = process_sbos $todo_upgrade if exists $$todo_upgrade[0];
-print_failures @failures;
+my %failures = process_sbos $todo_upgrade if exists $$todo_upgrade[0];
+print_failures %failures;
INSTALL_NEW:
exit 0 unless $install_new;
my $todo_install;
FIRST: for my $sbo (@ARGV) {
my $name = $compat32 ? "$sbo-compat32" : $sbo;
- my $inst = get_installed_sbos;
+ my $inst = get_installed_sbos;
my $inst_names = get_inst_names $inst;;
warn "$name already installed\n", next FIRST if $name ~~ @$inst_names;
# if compat32 is TRUE, we need to see if the non-compat version exists.
if ($compat32) {
- my $inst = get_installed_sbos;
+ my $inst = get_installed_sbos;
my $inst_names = get_inst_names $inst;
unless ($sbo ~~ @$inst_names) {
print "\nYou are attempting to install $name, however, $sbo is not";
@@ -334,7 +351,7 @@ FIRST: for my $sbo (@ARGV) {
}
push @$todo_install, $sbo;
}
-@failures = process_sbos $todo_install if exists $$todo_install[0];
-print_failures @failures;
+%failures = process_sbos $todo_install if exists $$todo_install[0];
+print_failures %failures;
exit 0;
diff --git a/t/SBO/Lib.pm b/t/SBO/Lib.pm
deleted file mode 100644
index 20be10b..0000000
--- a/t/SBO/Lib.pm
+++ /dev/null
@@ -1,686 +0,0 @@
-#!/usr/bin/env perl
-#
-# vim: set ts=4:noet
-#
-# Lib.pm
-# shared functions for the sbo_ scripts.
-#
-# author: Jacob Pipkin <j@dawnrazor.net>
-# date: Setting Orange, the 37th day of Discord in the YOLD 3178
-# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING>
-
-use 5.12.3;
-use warnings FATAL => 'all';
-use strict;
-
-package SBO::Lib 0.7;
-my $version = "0.7";
-
-require Exporter;
-our @ISA = qw(Exporter);
-our @EXPORT = qw(get_slack_version chk_slackbuilds_txt check_home rsync_sbo_tree get_sbo_from_loc get_sbo_version get_download_info get_arch get_sbo_downloads get_filename_from_link compute_md5sum compare_md5s verify_distfile get_distfile get_symlink_from_filename check_x32 check_multilib rewrite_slackbuild revert_slackbuild check_distfiles create_symlinks grok_temp_file get_src_dir get_pkg_name clear_coe_bit perform_sbo do_convertpkg
- script_error
- open_fh
- open_read
- show_version
- slackbuilds_or_fetch
- fetch_tree
- update_tree
- get_installed_sbos
- get_available_updates
- do_slackbuild
- make_clean
- make_distclean
- do_upgradepkg
- get_sbo_location
- get_from_info
- get_tmp_extfn
- get_tmp_perlfn
-);
-
-#$< == 0 or die "This script requires root privileges.\n";
-
-use Tie::File;
-use Sort::Versions;
-use Digest::MD5;
-use File::Copy;
-use File::Path qw(make_path remove_tree);
-use Fcntl;
-use File::Find;
-use File::Temp qw(tempdir tempfile);
-use Fcntl qw(F_SETFD F_GETFD);
-
-our $tempdir = tempdir (CLEANUP => 1);
-
-# subroutine for throwing internal script errors
-sub script_error (;$) {
- exists $_[0] ? die "A fatal script error has occurred:\n$_[0]\nExiting.\n"
- : die "A fatal script error has occurred: Exiting.\n";
-}
-
-# sub for opening files, second arg is like '<','>', etc
-sub open_fh {
- exists $_[1] or script_error ('open_fh requires two arguments');
- unless ($_[1] eq '>') {
- -f $_[0] or script_error 'open_fh first argument not a file';
- }
- my ($file, $op) = @_;
- open my $fh, $op, $file or die "Unable to open $file.\n";
- return $fh;
-}
-
-sub open_read ($) {
- return open_fh shift, '<';
-}
-
-# pull in configuration, set sane defaults, etc.
-our $conf_dir = '/etc/sbotools';
-our $conf_file = "$conf_dir/sbotools.conf";
-our %config = (
- NOCLEAN => 'FALSE',
- DISTCLEAN => 'FALSE',
- JOBS => 'FALSE',
- PKG_DIR => 'FALSE',
- SBO_HOME => 'FALSE',
-);
-
-# if the conf file exists, pull all the $key=$value pairs into a hash
-my %conf_values;
-if (-f $conf_file) {
- my $fh = open_read ($conf_file);
- my $text = do {local $/; <$fh>};
- %conf_values = $text =~ /^(\w+)=(.*)$/mg;
- close $fh;
-}
-
-for my $key (keys %config) {
- $config{$key} = $conf_values{$key} if exists $conf_values{$key};
-}
-$config{JOBS} = 'FALSE' unless $config{JOBS} =~ /^\d+$/;
-$config{SBO_HOME} = '/usr/sbo' if $config{SBO_HOME} eq 'FALSE';
-
-# some stuff we'll need later.
-my $distfiles = "$config{SBO_HOME}/distfiles";
-my $slackbuilds_txt = "$config{SBO_HOME}/SLACKBUILDS.TXT";
-my $name_regex = '\ASLACKBUILD\s+NAME:\s+';
-
-sub show_version () {
- say "sbotools version $version";
- say "licensed under the WTFPL";
- say "<http://sam.zoy.org/wtfpl/COPYING>";
-}
-
-# %supported maps what's in /etc/slackware-version to what's at SBo
-sub get_slack_version () {
- my %supported = (
- '13.37.0' => '13.37',
- '14.0' => '13.37',
- );
- my $fh = open_read '/etc/slackware-version';
- chomp (my $line = <$fh>);
- close $fh;
- my $version = ($line =~ /\s+(\d+[^\s]+)$/)[0];
- die "Unsupported Slackware version: $version\n"
- unless $version ~~ %supported;
- return $supported{$version};
-}
-
-# does the SLACKBUILDS.TXT file exist in the sbo tree?
-sub chk_slackbuilds_txt () {
- return -f $slackbuilds_txt ? 1 : 0;
-}
-
-# check for the validity of new $config{SBO_HOME}
-sub check_home () {
- my $sbo_home = $config{SBO_HOME};
- if (-d $sbo_home) {
- opendir (my $home_handle, $sbo_home);
- FIRST: while (readdir $home_handle) {
- next FIRST if /^\.[\.]{0,1}$/;
- die "$sbo_home exists and is not empty. Exiting.\n";
- }
- } else {
- make_path ($sbo_home) or die "Unable to create $sbo_home.\n";
- }
-}
-
-# rsync the sbo tree from slackbuilds.org to $config{SBO_HOME}
-sub rsync_sbo_tree () {
- my $slk_version = get_slack_version;
- my @arg = ('rsync', '-a', '--exclude=*.tar.gz', '--exclude=*.tar.gz.asc');
- push @arg, "rsync://slackbuilds.org/slackbuilds/$slk_version/*";
- my $out = system @arg, $config{SBO_HOME};
- say "Finished." and return $out;
-}
-
-# wrappers for differing checks and output
-sub fetch_tree () {
- check_home;
- say "Pulling SlackBuilds tree...";
- rsync_sbo_tree, return 1;
-}
-
-sub update_tree () {
- fetch_tree, return unless chk_slackbuilds_txt;
- say "Updating SlackBuilds tree...";
- rsync_sbo_tree, return 1;
-}
-
-# if the SLACKBUILDS.TXT is not in $config{SBO_HOME}, we assume the tree has
-# not been populated there; prompt the user to automagickally pull the tree.
-sub slackbuilds_or_fetch () {
- unless (chk_slackbuilds_txt) {
- say 'It looks like you haven\'t run "sbosnap fetch" yet.';
- print "Would you like me to do this now? [y] ";
- <STDIN> =~ /^[Yy\n]/ ? fetch_tree () :
- die "Please run \"sbosnap fetch\"\n";
- }
- return 1;
-}
-
-# pull an array of hashes, each hash containing the name and version of an sbo
-# currently installed.
-sub get_installed_sbos () {
- my @installed;
- # $1 == name, $2 == version
- my $regex = qr#/([^/]+)-([^-]+)-[^-]+-[^-]+$#;
- for my $path (</var/log/packages/*_SBo>) {
- my ($name, $version) = ($path =~ $regex)[0,1];
- push @installed, {name => $name, version => $version};
- }
- return \@installed;
-}
-
-# search the SLACKBUILDS.TXT for a given sbo's directory
-sub get_sbo_location ($) {
- exists $_[0] or script_error 'get_sbo_location requires an argument.';
- my $sbo = shift;
- my $regex = qr#LOCATION:\s+\.(/[^/]+/$sbo)$#;
- my $fh = open_read $slackbuilds_txt;
- while (my $line = <$fh>) {
- if (my $loc = ($line =~ $regex)[0]) {
- return "$config{SBO_HOME}$loc";
- }
- }
- return;
-}
-
-# pull the sbo name from a $location: $config{SBO_HOME}/system/wine, etc.
-sub get_sbo_from_loc ($) {
- exists $_[0] or script_error 'get_sbo_from_loc requires an argument.';
- return (shift =~ qr#/([^/]+)$#)[0];
-}
-
-# pull piece(s) of data, GET, from the $sbo.info file under LOCATION.
-sub get_from_info (%) {
- my %args = (
- LOCATION => '',
- GET => '',
- @_
- );
- unless ($args{LOCATION} && $args{GET}) {
- script_error 'get_from_info requires LOCATION and GET.';
- }
- state $vars = {PRGNAM => ['']};
- my $sbo = get_sbo_from_loc $args{LOCATION};
- return $$vars{$args{GET}} if $$vars{PRGNAM}[0] eq $sbo;
- # if we're here, we haven't read in the .info file yet.
- my $fh = open_read "$args{LOCATION}/$sbo.info";
- # suck it all in, clean it all up, stuff it all in $vars.
- my $contents = do {local $/; <$fh>};
- $contents =~ s/("|\\\n)//g;
- $vars = {$contents =~ /^(\w+)=(.*)$/mg};
- # fill the hash with array refs - even for single values,
- # since consistency here is a lot easier than sorting it out later
- for my $key (keys %$vars) {
- if ($$vars{$key} =~ /\s/) {
- my @array = split ' ', $$vars{$key};
- $$vars{$key} = \@array;
- } else {
- $$vars{$key} = [$$vars{$key}];
- }
- }
- return exists $$vars{$args{GET}} ? $$vars{$args{GET}} : 0;
-}
-
-# find the version in the tree for a given sbo (provided a location)
-sub get_sbo_version ($) {
- exists $_[0] or script_error 'get_sbo_version requires an arguments';
- my $version = get_from_info (LOCATION => shift, GET => 'VERSION');
- return $$version[0] ? $$version[0] : 0;
-}
-
-# for each installed sbo, find out whether or not the version in the tree is
-# newer, and compile an array of hashes containing those which are
-sub get_available_updates () {
- my @updates;
- my $pkg_list = get_installed_sbos;
- FIRST: for my $key (keys @$pkg_list) {
- my $location = get_sbo_location $$pkg_list[$key]{name};
- # if we can't find a location, assume invalid and skip
- next FIRST unless defined $location;
- my $version = get_sbo_version $location;
- if (versioncmp ($version, $$pkg_list[$key]{version}) == 1) {
- push @updates, {
- name => $$pkg_list[$key]{name},
- installed => $$pkg_list[$key]{version},
- update => $version
- };
- }
- }
- return \@updates;
-}
-
-# get downloads and md5sums from an sbo's .info file, first
-# checking for x86_64-specific info if we are told to
-sub get_download_info (%) {
- my %args = (
- LOCATION => 0,
- X64 => 1,
- @_
- );
- $args{LOCATION} or script_error 'get_download_info requires LOCATION.';
- my ($get, $downs, $md5s, %return);
- $get = ($args{X64} ? 'DOWNLOAD_x86_64' : 'DOWNLOAD');
- $downs = get_from_info (LOCATION => $args{LOCATION}, GET => $get);
- # did we get nothing back, or UNSUPPORTED/UNTESTED?
- if ($args{X64}) {
- my $nothing;
- if (! $$downs[0]) {
- $nothing = 1;
- } elsif ($$downs[0] =~ qr/^UN(SUPPOR|TES)TED$/) {
- $nothing = 1;
- }
- if ($nothing) {
- $args{X64} = 0;
- $downs = get_from_info (LOCATION => $args{LOCATION},
- GET => 'DOWNLOAD');
- }
- }
- # if we still don't have any links, something is really wrong.
- return unless $$downs[0];
- # grab the md5s and build a hash
- $get = $args{X64} ? 'MD5SUM_x86_64' : 'MD5SUM';
- $md5s = get_from_info (LOCATION => $args{LOCATION}, GET => $get);
- return unless $$md5s[0];
- $return{$$downs[$_]} = $$md5s[$_] for (keys @$downs);
- return %return;
-}
-
-sub get_arch () {
- chomp (my $arch = `uname -m`);
- return $arch;
-}
-
-# TODO: should probably combine this with get_download_info
-sub get_sbo_downloads (%) {
- my %args = (
- LOCATION => '',
- 32 => 0,
- @_
- );
- $args{LOCATION} or script_error 'get_sbo_downloads requires LOCATION.';
- my $location = $args{LOCATION};
- -d $location or script_error 'get_sbo_downloads given a non-directory.';
- my $arch = get_arch;
- my %dl_info;
- if ($arch eq 'x86_64') {
- %dl_info = get_download_info (LOCATION => $location) unless $args{32};
- }
- unless (keys %dl_info > 0) {
- %dl_info = get_download_info (LOCATION => $location, X64 => 0);
- }
- return %dl_info;
-}
-
-# given a link, grab the filename from the end of it
-sub get_filename_from_link ($) {
- exists $_[0] or script_error 'get_filename_from_link requires an argument';
- return "$distfiles/". (shift =~ qr#/([^/]+)$#)[0];
-}
-
-# for a given file, computer its md5sum
-sub compute_md5sum ($) {
- -f $_[0] or script_error 'compute_md5sum requires a file argument.';
- my $fh = open_read shift;
- my $md5 = Digest::MD5->new;
- $md5->addfile ($fh);
- my $md5sum = $md5->hexdigest;
- close $fh;
- return $md5sum;
-}
-
-sub compare_md5s ($$) {
- exists $_[1] or script_error 'compare_md5s requires two arguments.';
- my ($first, $second) = @_;
- return $first eq $second ? 1 : 0;
-}
-
-# for a given distfile, see whether or not it exists, and if so, if its md5sum
-# matches the sbo's .info file
-sub verify_distfile ($$) {
- exists $_[1] or script_error 'check_distfile requires two arguments.';
- my ($link, $info_md5sum) = @_;
- my $filename = get_filename_from_link $link;
- return unless -d $distfiles;
- return unless -f $filename;
- my $md5sum = compute_md5sum $filename;
- return compare_md5s $info_md5sum, $md5sum;
-}
-
-# for a given distfile, attempt to retrieve it and, if successful, check its
-# md5sum against that in the sbo's .info file
-sub get_distfile ($$) {
- exists $_[1] or script_error 'get_distfile requires an argument';
- my ($link, $exp_md5) = @_;
- my $filename = get_filename_from_link $link;
- mkdir $distfiles unless -d $distfiles;
- chdir $distfiles;
- system ("wget --no-check-certificate $link") == 0 or
- die "Unable to wget $link\n";
- my $md5sum = compute_md5sum $filename;
- # can't do anything if the link in the .info doesn't lead to a good d/l
- compare_md5s $md5sum, $exp_md5 or die "md5sum failure for $filename.\n";
- return 1;
-}
-
-# for a given distfile, what will be the full path of the symlink?
-sub get_symlink_from_filename ($$) {
- exists $_[1] or script_error
- 'get_symlink_from_filename requires two arguments';
- -f $_[0] or script_error
- 'get_symlink_from_filename first argument is not a file';
- my ($filename, $location) = @_;
- return "$location/". ($filename =~ qr#/([^/]+)$#)[0];
-}
-
-# determine whether or not a given sbo is 32-bit only
-sub check_x32 ($) {
- exists $_[0] or script_error 'check_x32 requires an argument.';
- my $dl = get_from_info (LOCATION => shift, GET => 'DOWNLOAD_x86_64');
- return $$dl[0] =~ /UN(SUPPOR|TES)TED/ ? 1 : 0;
-}
-
-# can't do 32-bit on x86_64 without this file, so we'll use it as the test to
-# to determine whether or not an x86_64 system is setup for multilib
-sub check_multilib {
- return 1 if -f '/etc/profile.d/32dev.sh';
- return;
-}
-
-# make a backup of the existent SlackBuild, and rewrite the original as needed
-sub rewrite_slackbuild ($$%) {
- exists $_[1] or script_error 'rewrite_slackbuild requires two arguments.';
- my ($slackbuild, $tempfn, %changes) = @_;
- copy ($slackbuild, "$slackbuild.orig") or
- die "Unable to backup $slackbuild to $slackbuild.orig\n";
- my $tar_regex = qr/(un|)tar .*$/;
- my $makepkg_regex = qr/makepkg/;
- my $libdir_regex = qr/^\s*LIBDIRSUFFIX="64"\s*$/;
- my $make_regex = qr/^\s*make(| \Q||\E exit 1)$/;
- my $arch_regex = qr/\$VERSION-\$ARCH-\$BUILD/;
- # tie the slackbuilds, because this is the easiest way to handle this.
- tie my @sb_file, 'Tie::File', $slackbuild;
- for my $line (@sb_file) {
- # get the output of the tar and makepkg commands. hope like hell that v
- # is specified among tar's arguments
- if ($line =~ $tar_regex || $line =~ $makepkg_regex) {
- $line = "$line | tee -a $tempfn";
- }
- # then check for and apply any %changes
- if (exists $changes{libdirsuffix}) {
- $line =~ s/64/$changes{libdirsuffix}/ if $line =~ $libdir_regex;
- }
- if (exists $changes{make}) {
- $line =~ s/make/make $changes{make}/ if $line =~ $make_regex;
- }
- if (exists $changes{arch_out}) {
- $line =~ s/\$ARCH/$changes{arch_out}/ if $line =~ $arch_regex;
- }
- }
- untie @sb_file;
- return 1;
-}
-
-# move a backed-up .SlackBuild file back into place
-sub revert_slackbuild ($) {
- exists $_[0] or script_error 'revert_slackbuild requires an argument';
- my $slackbuild = shift;
- if (-f "$slackbuild.orig") {
- unlink $slackbuild if -f $slackbuild;
- rename "$slackbuild.orig", $slackbuild;
- }
- return 1;
-}
-
-# for each $download, see if we have it, and if the copy we have is good,
-# otherwise download a new copy
-sub check_distfiles (%) {
- exists $_[0] or script_error 'check_distfiles requires an argument.';
- my %dists = @_;
- for my $link (keys %dists) {
- my $md5sum = $dists{$link};
- unless (verify_distfile $link, $md5sum) {
- die unless get_distfile $link, $md5sum;
- }
- }
- return 1;
-}
-
-# given a location and a list of download links, assemble a list of symlinks,
-# and create them.
-sub create_symlinks ($%) {
- exists $_[1] or script_error 'create_symlinks requires two arguments.';
- my ($location, %downloads) = @_;
- my @symlinks;
- for my $link (keys %downloads) {
- my $filename = get_filename_from_link $link;
- my $symlink = get_symlink_from_filename $filename, $location;
- push @symlinks, $symlink;
- symlink $filename, $symlink;
- }
- return @symlinks;
-}
-
-# pull the untarred source directory or created package name from the temp
-# file (the one we tee'd to)
-sub grok_temp_file (%) {
- my %args = (
- FH => '',
- REGEX => '',
- CAPTURE => 0,
- @_
- );
- unless ($args{FH} && $args{REGEX}) {
- script_error 'grok_temp_file requires two arguments';
- }
- my $fh = $args{FH};
- seek $fh, 0, 0;
- my $out;
- FIRST: while (my $line = <$fh>) {
- if ($line =~ $args{REGEX}) {
- $out = ($line =~ $args{REGEX})[$args{CAPTURE}];
- last FIRST;
- }
- }
- return $out;
-}
-
-# wrappers around grok_temp_file
-sub get_src_dir ($) {
- exists $_[0] or script_error 'get_src_dir requires an argument';
- return grok_temp_file (FH => shift, REGEX => qr#^([^/]+)/#);
-}
-
-sub get_pkg_name ($) {
- exists $_[0] or script_error 'get_pkg_name requires an argument';
- return grok_temp_file (FH => shift,
- REGEX => qr/^Slackware\s+package\s+([^\s]+)\s+created\.$/);
-}
-
-# clear the close-on-exec bit from a temp file handle
-sub clear_coe_bit ($) {
- exists $_[0] or script_error 'clear_coe_bit requires an argument';
- my $fh = shift;
- fcntl ($fh, F_SETFD, 0) or die "no unset exec-close thingy\n";
- return $fh;
-}
-
-# return a filename from a temp fh for use externally
-sub get_tmp_extfn ($) {
- exists $_[0] or script_error 'get_tmp_extfn requires an argument.';
- my $fh = clear_coe_bit shift;
- return '/dev/fd/'. fileno $fh;
-}
-
-# return a filename from a temp fh for use internally
-sub get_tmp_perlfn ($) {
- exists $_[0] or script_error 'get_tmp_perlfn requires an argument.';
- my $fh = clear_coe_bit shift;
- return '+<=&'. fileno $fh;
-}
-
-# 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;
- my ($cmd, %changes);
- # figure out any changes we need to make to the .SlackBuild
- $changes{make} = "-j $args{JOBS}" if $args{JOBS};
- 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 &&";
- }
- $cmd .= "/bin/sh $location/$sbo.SlackBuild";
- $cmd = "$args{OPTS} $cmd" if $args{OPTS};
- my $tempfh = tempfile (DIR => $tempdir);
- my $fn = get_tmp_extfn $tempfh;
- rewrite_slackbuild "$location/$sbo.SlackBuild", $fn, %changes;
- chdir $location, my $out = system $cmd;
- revert_slackbuild "$location/$sbo.SlackBuild";
- die unless $out == 0;
- my $pkg = get_pkg_name $tempfh;
- my $src = get_src_dir $tempfh;
- return $pkg, $src;
-}
-
-# run convertpkg on a package to turn it into a -compat32 thing
-sub do_convertpkg ($) {
- exists $_[0] or script_error 'do_convertpkg requires an argument.';
- my $pkg = shift;
- my $tempfh = tempfile (DIR => $tempdir);
- my $fn = get_tmp_extfn $tempfh;
- my $cmd = "/usr/sbin/convertpkg-compat32 -i $pkg -d /tmp | tee $fn";
- system ($cmd) == 0 or die;
- unlink $pkg;
- return get_pkg_name $tempfh;
-}
-
-# "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 $multi = 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}) {
- die "compat32 only works on x86_64.\n" unless $arch eq 'x86_64';
- die "compat32 requires multilib.\n" unless $multi;
- die "compat32 requires /usr/sbin/convertpkg-compat32.\n"
- unless -f '/usr/sbin/convertpkg-compat32';
- } else {
- if ($arch eq 'x86_64') {
- $x32 = check_x32 $args{LOCATION};
- if ($x32 && ! $multi) {
- die "$sbo is 32-bit which requires multilib on x86_64.\n";
- }
- }
- }
- # get a hash of downloads and md5sums, ensure we have 'em, symlink 'em
- my %downloads = get_sbo_downloads (
- LOCATION => $location,
- 32 => $args{COMPAT32}
- );
- check_distfiles %downloads;
- my @symlinks = create_symlinks $args{LOCATION}, %downloads;
- # setup and run the .SlackBuild itself
- my ($pkg, $src) = perform_sbo (
- OPTS => $args{OPTS},
- JOBS => $args{JOBS},
- LOCATION => $location,
- ARCH => $arch,
- C32 => $args{COMPAT32},
- X32 => $x32,
- );
- do_convertpkg $pkg if $args{COMPAT32};
- unlink $_ for @symlinks;
- return $version, $pkg, $src;
-}
-
-# remove work directories (source and packaging dirs under /tmp/SBo)
-sub make_clean ($$$) {
- exists $_[1] or script_error 'make_clean requires two arguments.';
- my ($sbo, $src, $version) = @_;
- say "Cleaning for $sbo-$version...";
- my $tmpsbo = "/tmp/SBo";
- remove_tree ("$tmpsbo/$src") if -d "$tmpsbo/$src";
- remove_tree ("$tmpsbo/package-$sbo") if -d "$tmpsbo/package-$sbo";
- return 1;
-}
-
-# 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, $args{SRC}, $args{VERSION};
- say "Distcleaning for $sbo-$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;
-}
-
-# run upgradepkg for a created package
-sub do_upgradepkg ($) {
- exists $_[0] or script_error 'do_upgradepkg requires an argument.';
- system ('/sbin/upgradepkg', '--reinstall', '--install-new', shift);
- return 1;
-}
-
diff --git a/t/prep.pl b/t/prep.pl
index e2fe9bf..c51a200 100755
--- a/t/prep.pl
+++ b/t/prep.pl
@@ -1,5 +1,6 @@
#!/usr/bin/perl
+use 5.16.0;
use strict;
use warnings FATAL => 'all';
use File::Copy;
@@ -8,6 +9,52 @@ use Tie::File;
chomp (my $pwd = `pwd`);
mkdir "$pwd/SBO" unless -d "$pwd/SBO";
copy ('/home/d4wnr4z0r/projects/sbotools/SBO-Lib/lib/SBO/Lib.pm', "$pwd/SBO");
+
+open my $write, '>>', "$pwd/SBO/Lib.pm";
+
+sub pr ($) {
+ my $thing = shift;
+ print {$write} "our \$$thing = 1;\n";
+}
+
+for my $thing (qw(interactive compat32 no_readme jobs distclean noclean no_install no_reqs)) {
+ pr $thing;
+}
+
+print {$write} "my \%locations;\n";
+print {$write} "my \%options = (nothing => 'to see here');\n";
+
+sub get_subs ($) {
+ my $read = shift;
+ my $begin_regex = qr/^sub\s+[a-z0-9_]+/;
+ my $usage_regex = qr/^sub\s+show_usage/;
+ my $end_regex = qr/^}$/;
+ my $begin = 0;
+ my $end = 0;
+ while (my $line = <$read>) {
+ if (! $begin) {
+ if ($line =~ $begin_regex) {
+ if ($line !~ $usage_regex) {
+ $end = 0, $begin++, print {$write} $line;
+ }
+ }
+ } elsif (! $end) {
+ if ($line =~ $end_regex) {
+ $begin = 0, $end++, print {$write} $line;
+ } else {
+ print {$write} $line;
+ }
+ }
+ }
+}
+
+for my $file (qw(sbocheck sboclean sboconfig sbofind sboupgrade)) {
+ open my $read, '<', "../$file";
+ get_subs $read;
+ close $read;
+}
+close $write;
+
my @subs;
open my $file_h, '<', "$pwd/SBO/Lib.pm";
my $regex = qr/^sub\s+([^\s]+)\s+/;
diff --git a/t/test.t b/t/test.t
index 059958c..cdc5701 100755
--- a/t/test.t
+++ b/t/test.t
@@ -1,31 +1,49 @@
-#!/usr/bin/perl -I/home/d4wnr4z0r/projects/sbotools/t
+#!/usr/bin/env perl
use 5.16.0;
use strict;
use warnings FATAL => 'all';
use File::Temp qw(tempdir tempfile);
-use Test::More tests => 39;
+use Test::More tests => 87;
+use File::Copy;
+use Text::Diff;
+use lib ".";
use SBO::Lib;
-ok (defined $SBO::Lib::tempdir, '$tempdir is defined');
+my $sbo_home = '/home/d4wnr4z0r/sbo.git/slackbuilds';
-my $fh = open_read ('/home/d4wnr4z0r/projects/sbotools/t/test.t');
-ok (ref ($fh) eq 'GLOB', 'open_read works');
+# 1, open_read, open_fh tests
+my $fh = open_read ('./test.t');
+is (ref $fh, 'GLOB', 'open_read works');
close $fh;
-ok ($SBO::Lib::config{DISTCLEAN} eq 'FALSE', 'config{DISTCLEAN} is good');
-ok ($SBO::Lib::config{JOBS} == 2, 'config{JOBS} is good');
-ok ($SBO::Lib::config{NOCLEAN} eq 'TRUE', 'config{NOCLEAN} is good');
-ok ($SBO::Lib::config{PKG_DIR} eq 'FALSE', 'config{PKG_DIR} is good');
-ok ($SBO::Lib::config{SBO_HOME} eq '/usr/sbo', 'config{SBO_HOME} is good');
+# 2-7, config settings tests;
+ok (defined $SBO::Lib::tempdir, '$tempdir is defined');
+is ($SBO::Lib::config{DISTCLEAN}, 'FALSE', 'config{DISTCLEAN} is good');
+is ($SBO::Lib::config{JOBS}, 2, 'config{JOBS} is good');
+is ($SBO::Lib::config{NOCLEAN}, 'FALSE', 'config{NOCLEAN} is good');
+is ($SBO::Lib::config{PKG_DIR}, 'FALSE', 'config{PKG_DIR} is good');
+is ($SBO::Lib::config{SBO_HOME}, "$sbo_home", 'config{SBO_HOME} is good');
+
+# 8, show_version test
+is (show_version, 1, 'show_version is good');
+
+# 9, get_slack_version test
+is (get_slack_version, '14.0', 'get_slack_version is good');
+
+# 10-11, chk_slackbuilds_txt tests
+is (chk_slackbuilds_txt, 1, 'chk_slackbuilds_txt is good');
+move ("$sbo_home/SLACKBUILDS.TXT", "$sbo_home/SLACKBUILDS.TXT.moved");
+is (chk_slackbuilds_txt, undef, 'chk_slackbuilds_txt returns false with no SLACKBUILDS.TXT');
+move ("$sbo_home/SLACKBUILDS.TXT.moved", "$sbo_home/SLACKBUILDS.TXT");
-ok (show_version == 1, 'show_version is good');
-ok (get_slack_version eq '13.37', 'get_slack_version is good');
-ok (chk_slackbuilds_txt == 1, 'check_slackbuilds_txt is good');
#ok (rsync_sbo_tree == 1, 'rsync_sbo_tree is good');
#ok (update_tree == 1, 'update_tree is good');
-ok (slackbuilds_or_fetch == 1, 'slackbuilds_or_fetch is good');
+# 12, slackbuilds_or_fetch test
+is (slackbuilds_or_fetch, 1, 'slackbuilds_or_fetch is good');
+
+# 13-18, get_installed_sbos test
print "pseudo-random sampling of get_installed_sbos output...\n";
my $installed = get_installed_sbos;
for my $key (keys @$installed) {
@@ -38,48 +56,67 @@ for my $key (keys @$installed) {
}
print "completed pseudo-random testing of get_installed_sbos \n";
-is (get_sbo_location 'nginx', '/usr/sbo/network/nginx', 'get_sbo_location is good');
+# 19-20, get_sbo_location tests
+is (get_sbo_location 'nginx', "$sbo_home/network/nginx", 'get_sbo_location is good');
+is (get_sbo_location 'omgwtfbbq', undef, 'get_sbo_location returns false with not-an-sbo input');
+# 21-22, get_available_updates tests
my $updates = get_available_updates;
for my $key (keys @$updates) {
is ($$updates[$key]{installed}, '1.15', '$$updates[$key]{installed} good for mutagen') if $$updates[$key]{name} eq 'mutagen';
is ($$updates[$key]{update}, '1.20', '$$updates[$key]{update} good for mutagen') if $$updates[$key]{name} eq 'mutagen';
}
-ok (get_arch eq 'x86_64', 'get_arch is good');
+# 23, get_arch test
+is (get_arch, 'x86_64', 'get_arch is good');
-my %dl_info = get_download_info (LOCATION => '/usr/sbo/system/wine', X64 => 0);
+# 24-25, get_download_info tests
+my %dl_info = get_download_info (LOCATION => "$sbo_home/system/wine", X64 => 0);
my $link = 'http://downloads.sf.net/wine/source/1.4/wine-1.4.1.tar.bz2';
is ($dl_info{$link}, '0c28702ed478df7a1c097f3a9c4cabd6', 'get_download_info test 01 good.');
$link = 'http://www.unrealize.co.uk/source/dibeng-max-2010-11-12.zip';
is ($dl_info{$link}, '97159d77631da13952fe87e846cf1f3b', 'get_download_info test 02 good.');
-%dl_info = get_sbo_downloads (LOCATION => '/usr/sbo/system/wine');
+# 26-28, get_sbo_downloads tests
+%dl_info = get_sbo_downloads (LOCATION => "$sbo_home/system/wine");
$link = 'http://downloads.sf.net/wine/source/1.4/wine-1.4.1.tar.bz2';
is ($dl_info{$link}, '0c28702ed478df7a1c097f3a9c4cabd6', 'get_sbo_downloads test 01 good.');
$link = 'http://www.unrealize.co.uk/source/dibeng-max-2010-11-12.zip';
is ($dl_info{$link}, '97159d77631da13952fe87e846cf1f3b', 'get_sbo_downloads test 02 good.');
-
-my %downloads = get_sbo_downloads (LOCATION => '/usr/sbo/system/ifuse');
+my %downloads = get_sbo_downloads (LOCATION => "$sbo_home/system/ifuse");
$link = 'http://www.libimobiledevice.org/downloads/ifuse-1.1.1.tar.bz2';
is ($downloads{$link}, '8d528a79de024b91f12f8ac67965c37c', 'get_sbo_downloads test 03 good.');
-is (get_filename_from_link 'http://www.libimobiledevice.org/downloads/ifuse-1.1.1.tar.bz2', '/usr/sbo/distfiles/ifuse-1.1.1.tar.bz2', 'get_file_from_link good');
-is (compute_md5sum '/usr/sbo/distfiles//laptop-mode-tools_1.61.tar.gz', '6685af5dbb34c3d51ca27933b58f484e', 'compute_md5sum good');
-is ((verify_distfile '/usr/sbo/distfiles/laptop-mode-tools_1.61.tar.gz', '6685af5dbb34c3d51ca27933b58f484e'), 1, 'verify_distfile good');
-is (get_sbo_version '/usr/sbo/system/wine', '1.4.1', 'get_sbo_version good');
-is ((get_symlink_from_filename '/usr/sbo/distfiles/laptop-mode-tools_1.61.tar.gz', '/usr/sbo/system/laptop-mode-tools'), '/usr/sbo/system/laptop-mode-tools/laptop-mode-tools_1.61.tar.gz', 'get_symlink_from_filename good');
-ok (check_x32 '/usr/sbo/system/wine', 'check_x32 true for 32-bit only wine');
-ok (!(check_x32 '/usr/sbo/system/ifuse'), 'check_x32 false for not-32-bit-only ifuse');
-ok (check_multilib, 'check_multilib good');
+# 29, get_filename_from_link test
+is (get_filename_from_link 'http://www.libimobiledevice.org/downloads/ifuse-1.1.1.tar.bz2', "$sbo_home/distfiles/ifuse-1.1.1.tar.bz2", 'get_file_from_link good');
+is (get_filename_from_link 'adf;lkajsdfaksjdfalsdjfalsdkfjdsfj', undef, 'get_filename_from_link good with invalid input');
+
+# 31, compute_md5sum test
+is (compute_md5sum "$sbo_home/distfiles/laptop-mode-tools_1.61.tar.gz", '6685af5dbb34c3d51ca27933b58f484e', 'compute_md5sum good');
-# TODO: find a way to write a test for rewrite_slackbuild, revert_slackbuild.
+# 32, verify_distfile test
+is ((verify_distfile "$sbo_home/distfiles/laptop-mode-tools_1.61.tar.gz", '6685af5dbb34c3d51ca27933b58f484e'), 1, 'verify_distfile good');
-%downloads = get_sbo_downloads (LOCATION => '/usr/sbo/system/wine', 32 => 1);
-my @symlinks = create_symlinks '/usr/sbo/system/wine', %downloads;
-is ($symlinks[0], '/usr/sbo/system/wine/wine-1.4.1.tar.bz2', '$symlinks[0] good for create_symlinks');
-is ($symlinks[1], '/usr/sbo/system/wine/dibeng-max-2010-11-12.zip', '$symlinks[1] good for create_symlinks');
+# 33, get_sbo_version test
+is (get_sbo_version "$sbo_home/system/wine", '1.4.1', 'get_sbo_version good');
+# 34, get_symlink_from_filename test
+is ((get_symlink_from_filename "$sbo_home/distfiles/laptop-mode-tools_1.61.tar.gz", "$sbo_home/system/laptop-mode-tools"), "$sbo_home/system/laptop-mode-tools/laptop-mode-tools_1.61.tar.gz", 'get_symlink_from_filename good');
+
+# 35-36, check_x32 tests
+ok (check_x32 "$sbo_home/system/wine", 'check_x32 true for 32-bit only wine');
+ok (!(check_x32 "$sbo_home/system/ifuse"), 'check_x32 false for not-32-bit-only ifuse');
+
+# 37, check_multilib tests
+ok (check_multilib, 'check_multilib good');
+
+# 38-39, create_symlinks tests
+%downloads = get_sbo_downloads (LOCATION => "$sbo_home/system/wine", 32 => 1);
+my @symlinks = create_symlinks "$sbo_home/system/wine", %downloads;
+is ($symlinks[0], "$sbo_home/system/wine/wine-1.4.1.tar.bz2", '$symlinks[0] good for create_symlinks');
+is ($symlinks[1], "$sbo_home/system/wine/dibeng-max-2010-11-12.zip", '$symlinks[1] good for create_symlinks');
+
+# 40-41, grok_temp_file, get_src_dir/get_pkg_name tests
my $tempdir = tempdir (CLEANUP => 1);
my $tempfh = tempfile (DIR => $tempdir);
my $lmt = 'laptop-mode-tools_1.60';
@@ -87,9 +124,162 @@ print {$tempfh} "$lmt/COPYING\n";
print {$tempfh} "$lmt/Documentation/\n";
print {$tempfh} "$lmt/README\n";
print {$tempfh} "Slackware package skype-2.2.0.35-i486-1_SBo.tgz created.\n";
-#close $tempfh;
is (get_src_dir $tempfh, 'laptop-mode-tools_1.60', 'get_src_dir good');
is (get_pkg_name $tempfh, 'skype-2.2.0.35-i486-1_SBo.tgz', 'get_pkg_name good');
-%downloads = get_sbo_downloads (LOCATION => '/usr/sbo/system/wine', 32 => 1);
+close $tempfh;
+
+# 42, check_distfiles test
+%downloads = get_sbo_downloads (LOCATION => "$sbo_home/system/wine", 32 => 1);
is ((check_distfiles %downloads), 1, 'check_distfiles good');
-#is (do_convertpkg ($package), "$package-compat32", 'do_convertpkg good');
+
+# 43-45, check_home tests
+system ('sudo /usr/sbin/sboconfig -s /home/d4wnr4z0r/opt_sbo') == 0 or die "unable to set sboconfig -s\n";
+read_config;
+ok (check_home, 'check_home returns true with new non-existent directory');
+ok (-d '/home/d4wnr4z0r/opt_sbo', 'check_home creates $config{SBO_HOME}');
+ok (check_home, 'check_home returns true with new existent empty directory');
+system ("sudo /usr/sbin/sboconfig -s $sbo_home") == 0 or die "unable to reset sboconfig -s\n";
+read_config;
+rmdir "/home/d4wnr4z0r/opt_sbo";
+
+# 46-47 get_sbo_from_loc tests
+is (get_sbo_from_loc '/home/d4wnr4z0r/sbo.git/system/ifuse', 'ifuse', 'get_sbo_from_loc returns correctly with valid input');
+ok (! get_sbo_from_loc 'omg_wtf_bbq', 'get_sbo_from_loc returns false with invalid input');
+
+# 48-49, compare_md5s tests
+is (compare_md5s ('omgwtf123456789', 'omgwtf123456789'), 1, 'compare_md5s returns true for matching parameters');
+is (compare_md5s ('omgwtf123456788', 'somethingelsebbq'), undef, 'compare_md5s returns false for not-matching parameters');
+
+# 50, get_distfile tests
+my $distfile = "$sbo_home/distfiles/Sort-Versions-1.5.tar.gz";
+unlink $distfile if -f $distfile;
+is (get_distfile ('http://search.cpan.org/CPAN/authors/id/E/ED/EDAVIS/Sort-Versions-1.5.tar.gz', '5434f948fdea6406851c77bebbd0ed19'), 1, 'get_distfile is good');
+unlink $distfile;
+
+# 51-58, rewrite_slackbuilds/revert_slackbuild tests
+my $rewrite_dir = tempdir (CLEANUP => 1);
+copy ("$sbo_home/system/ifuse/ifuse.SlackBuild", $rewrite_dir);
+my $slackbuild = "$rewrite_dir/ifuse.SlackBuild";
+$tempfh = tempfile (DIR => $rewrite_dir);
+my $tempfn = get_tmp_extfn $tempfh;
+my %changes;
+is (rewrite_slackbuild ($slackbuild, $tempfn, %changes), 1, 'rewrite_slackbuild with no %changes good');
+ok (-f "$slackbuild.orig", 'rewrite_slackbuild backing up original is good.');
+my $expected_out = "67c67
+< tar xvf \$CWD/\$PRGNAM-\$VERSION.tar.bz2
+---
+> tar xvf \$CWD/\$PRGNAM-\$VERSION.tar.bz2 | tee -a $tempfn
+103c103
+< /sbin/makepkg -l y -c n \$OUTPUT/\$PRGNAM-\$VERSION-\$ARCH-\$BUILD\$TAG.\${PKGTYPE:-tgz}
+---
+> /sbin/makepkg -l y -c n \$OUTPUT/\$PRGNAM-\$VERSION-\$ARCH-\$BUILD\$TAG.\${PKGTYPE:-tgz} | tee -a $tempfn
+";
+is (diff ("$slackbuild.orig", $slackbuild, {STYLE => 'OldStyle'}), $expected_out, 'tar line rewritten correctly');
+is (revert_slackbuild $slackbuild, 1, 'revert_slackbuild is good');
+$changes{libdirsuffix} = '';
+$changes{make} = '-j 5';
+$changes{arch_out} = 'i486';
+is (rewrite_slackbuild ($slackbuild, $tempfn, %changes), 1, 'rewrite_slackbuild with all %changes good');
+ok (-f "$slackbuild.orig", 'rewrite_slackbuild backing up original is good.');
+$expected_out = "55c55
+< LIBDIRSUFFIX=\"64\"
+---
+> LIBDIRSUFFIX=\"\"
+67c67
+< tar xvf \$CWD/\$PRGNAM-\$VERSION.tar.bz2
+---
+> tar xvf \$CWD/\$PRGNAM-\$VERSION.tar.bz2 | tee -a $tempfn
+87c87
+< make
+---
+> make -j 5
+103c103
+< /sbin/makepkg -l y -c n \$OUTPUT/\$PRGNAM-\$VERSION-\$ARCH-\$BUILD\$TAG.\${PKGTYPE:-tgz}
+---
+> /sbin/makepkg -l y -c n \$OUTPUT/\$PRGNAM-\$VERSION-i486-\$BUILD\$TAG.\${PKGTYPE:-tgz} | tee -a $tempfn
+";
+is (diff ("$slackbuild.orig", $slackbuild, {STYLE => 'OldStyle'}), $expected_out, 'all changed lines rewritten correctly');
+is (revert_slackbuild $slackbuild, 1, 'revert_slackbuild is good again');
+
+# 59-61, get_from_info tests
+my $test_loc = "$sbo_home/system/ifuse";
+my %params = (LOCATION => $test_loc);
+my $info = get_from_info (%params, GET => 'VERSION');
+is ($$info[0], '1.1.1', 'get_from_info GET => VERSION is good');
+$info = get_from_info (%params, GET => 'HOMEPAGE');
+is ($$info[0], 'http://www.libimobiledevice.org', 'get_from_info GET => HOMEPAGE is good');
+$info = get_from_info (%params, GET => 'DOWNLOAD_x86_64');
+is ($$info[0], "", 'get_from_info GET => DOWNLOAD_x86_64 is good');
+
+# 62-64, get_update_list tests
+my $listing = get_update_list;
+s/\s//g for @$listing;
+for my $item (@$listing) {
+ is ($item, 'zdoom-2.5.0<needsupdating(SBohas2.6.0)', 'get_update_list output good for zdoom') if $item =~ /^zdoom/;
+ is ($item, 'ffmpeg-0.8.7<needsupdating(SBohas0.11.1)', 'get_update_list output good for ffmpeg') if $item =~ /^ffmpeg/;
+ is ($item, 'atkmm-2.22.4<needsupdating(SBohas2.22.6)', 'get_update_list output good for atkmm') if $item =~ /^atkmm/;
+}
+
+# 65, remove_stuff test - can only really test for invalid input
+is (remove_stuff '/omg/wtf/bbq', 1, 'remove_stuff good for invalid input');
+
+# 66, config_write test
+is (config_write ('OMG', 'WTF'), undef, 'config_write returned undef correctly');
+
+# 67-74, perform_search tests
+my $findings = perform_search 'desktop';
+for my $found (@$findings) {
+ for my $key (keys %$found) {
+ my $section = 'desktop';;
+ if ($key eq 'libdesktop-agnostic') {
+ $section = 'libraries';
+ } elsif ($key eq 'mendeleydesktop') {
+ $section = 'academic';
+ } elsif ($key eq 'gtk-recordmydesktop' || $key eq 'huludesktop') {
+ $section = 'multimedia';
+ } elsif ($key eq 'gnome-python-desktop') {
+ $section = 'python';
+ }
+ is ($$found{$key}, "$sbo_home/$section/$key", 'perform_search good for $search eq desktop');
+ }
+}
+
+# 75, get_inst_names test
+$installed = get_installed_sbos;
+my $inst_names = get_inst_names $installed;
+ok ('zdoom' ~~ @$inst_names, 'get_inst_names is good');
+
+# 76-81, get_reqs tests
+$SBO::Lib::no_reqs = 0;
+ok (! (get_requires 'stops', "$sbo_home/audio/stops"), 'get_requires good for circular requirements');
+ok (! (get_requires 'smc', "$sbo_home/games/smc"), 'get_requires good for REQUIRES="%README%"');
+ok (! (get_requires 'krb5', "$sbo_home/network/krb5"), 'get_requires good for REQUIRES=""');
+my $reqs = get_requires 'matchbox-desktop', "$sbo_home/desktop/matchbox-desktop";
+my $say = 'get_requires good for normal req list';
+is ($$reqs[0], 'libmatchbox', $say);
+is ($$reqs[1], 'matchbox-window-manager', $say);
+is ($$reqs[2], 'matchbox-common', $say);
+
+# 82-85, get_user_group tests
+$fh = open_read "$sbo_home/network/nagios/README";
+my $readme = do {local $/; <$fh>};
+close $fh;
+my $cmds = get_user_group $readme;
+is ($$cmds[0], 'groupadd -g 213 nagios', 'get_user_group good for # groupadd');
+is ($$cmds[1], 'useradd -u 213 -d /dev/null -s /bin/false -g nagios nagios', 'get_user_group for # useradd');
+$fh = open_read "$sbo_home/network/havp/README";
+$readme = do {local $/; <$fh>};
+close $fh;
+$cmds = get_user_group $readme;
+is ($$cmds[0], 'groupadd -g 210 clamav', 'get_user_group good for groupadd');
+is ($$cmds[1], 'useradd -u 256 -d /dev/null -s /bin/false -g clamav havp', 'get_user_group good for useradd');
+
+# 86-87, get_opts test
+$fh = open_read "$sbo_home/games/vbam/README";
+$readme = do {local $/; <$fh>};
+close $fh;
+ok (get_opts $readme, 'get_opts good where README defines opts');
+$fh = open_read "$sbo_home/libraries/libmatchbox/README";
+$readme = do {local $/; <$fh>};
+close $fh;
+ok (! (get_opts $readme), 'get_opts good where README does not define opts');