diff options
62 files changed, 874 insertions, 403 deletions
diff --git a/.travis.yml b/.travis.yml index 7cf180d..b1bd345 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: perl perl: + - "5.26" - "5.22" - "5.18" - "5.16" @@ -7,11 +8,9 @@ env: - TEST_ONLINE=1 TEST_INSTALL=1 TEST_MULTILIB=0 - TEST_ONLINE=1 TEST_INSTALL=1 TEST_MULTILIB=1 - TEST_ONLINE=1 TEST_INSTALL=1 TEST_MULTILIB=2 - - TEST_ONLINE=1 TEST_INSTALL=0 - TEST_ONLINE=0 TEST_INSTALL=1 TEST_MULTILIB=0 - TEST_ONLINE=0 TEST_INSTALL=1 TEST_MULTILIB=1 - TEST_ONLINE=0 TEST_INSTALL=1 TEST_MULTILIB=2 - - TEST_ONLINE=0 TEST_INSTALL=0 sudo: required install: - sudo bash t/travis-deps/install.sh @@ -3,14 +3,38 @@ **[sbotools](https://pink-mist.github.io/sbotools/)** provides a ports-like interface to [slackbuilds.org](http://www.slackbuilds.org/). ## Changes -* 2.1 - Unreleased +* 2.5 - 2018-02-14 + * Document download behaviour #66 + * Remake sbosnap and sboremove to have OO semantics + * Strip -compat32 from slackbuild names when looking them up #65 + * Optimise searching in sbofind + +* 2.4 - 2017-05-18 + * Rewrite sboremove from the ground up so it relies less on global state + * Fix for parsing README with useradd/groupadd commands which span lines #57 + * Add --reinstall option to sboinstall #58 + * Exit with error when sbosnap fails to sync with a repo #61 + * Add version information to sbofind output #60 + +* 2.3 - 2017-01-21 + * Bugfix for parsing .info files with \ among the separators #55 + +* 2.2 - 2017-01-17 + * Bugfix for parsing .info files with trailing whitespace after a value #54 + +* 2.1 - 2017-01-14 * Internals: - Adding internal documentation - Extract code to submodules for easier separation of concerns * New features: - Support for templates for installing things with specified options #38 + - Display other README files if the slackbuild comes with them #49 * Bugfixes - sboinstall/sboremove disagreeing about a package being installed #44 + - sbocheck and sboupgrade misinterpreting version strings #45 + - parsing .info files without leading space on second line #46 + - local git repo gets partially chowned to root #47 + - stop excluding .tar.gz files when rsyncing #53 * 2.0 - 2016-07-02 * Major new features diff --git a/SBO-Lib/Changes b/SBO-Lib/Changes index 588b0ec..60e9f54 100644 --- a/SBO-Lib/Changes +++ b/SBO-Lib/Changes @@ -1,13 +1,50 @@ -2.1 - Unreleased +2.5 - 2018-02-14 + * Document download behaviour + (https://github.com/pink-mist/sbotools/issues/66) + * Remake sbosnap and sboremove to have OO semantics + * Strip -compat32 from slackbuild names when looking them up + (https://github.com/pink-mist/sbotools/issues/65) + * Optimise searching in sbofind + +2.4 - 2017-05-18 + * Rewrite sboremove from the ground up so it relies less on global state + * Fix for parsing README with useradd/groupadd commands which span lines + (https://github.com/pink-mist/sbotools/issues/57) + * Add --reinstall option to sboinstall + (https://github.com/pink-mist/sbotools/issues/58) + * Exit with error when sbosnap fails to sync with a repo + (https://github.com/pink-mist/sbotools/issues/61) + * Add version information to sbofind output + (https://github.com/pink-mist/sbotools/issues/60) + +2.3 - 2017-01-21 + * Bugfix for parsing .info files with \ among the separators + (https://github.com/pink-mist/sbotools/issues/55) + +2.2 - 2017-01-17 + * Bugfix for parsing .info files with trailing whitespace after a value + (https://github.com/pink-mist/sbotools/issues/54) + +2.1 - 2017-01-14 * Internals: - Adding internal documentation - Extract code to submodules for easier separation of concerns * New features: - Support for templates for installing things with specified options (https://github.com/pink-mist/sbotools/issues/38) + - Display other README files if the slackbuild comes with them + (https://github.com/pink-mist/sbotools/issues/49) * Bugfixes - sboinstall/sboremove disagreeing about a package being installed (https://github.com/pink-mist/sbotools/issues/44) + - sbocheck and sboupgrade misinterpreting version strings + (https://github.com/pink-mist/sbotools/issues/45) + - parsing .info files without leading space on second line + (https://github.com/pink-mist/sbotools/issues/46) + - local git repo gets partially chowned to root + (https://github.com/pink-mist/sbotools/issues/47) + - stop excluding .tar.gz files when rsyncing + (https://github.com/pink-mist/sbotools/issues/53) 2.0 - 2016-07-02 * Major new features diff --git a/SBO-Lib/MANIFEST b/SBO-Lib/MANIFEST index ed6efe2..a00cb9d 100644 --- a/SBO-Lib/MANIFEST +++ b/SBO-Lib/MANIFEST @@ -4,6 +4,9 @@ MANIFEST README t/SBO-Lib.t t/versions.t +lib/SBO/App.pm +lib/SBO/App/Remove.pm +lib/SBO/App/Snap.pm lib/SBO/Lib.pm lib/SBO/Lib/Build.pm lib/SBO/Lib/Download.pm diff --git a/SBO-Lib/README b/SBO-Lib/README index 2fbc0af..35e157b 100644 --- a/SBO-Lib/README +++ b/SBO-Lib/README @@ -1,4 +1,4 @@ -SBO-Lib version 2.1 +SBO-Lib version 2.5 =================== SBO::Lib is a library for the sbotools scripts. diff --git a/SBO-Lib/lib/SBO/App.pm b/SBO-Lib/lib/SBO/App.pm new file mode 100644 index 0000000..c9e0fdf --- /dev/null +++ b/SBO-Lib/lib/SBO/App.pm @@ -0,0 +1,26 @@ +package SBO::App; + +# vim: ts=2:et +# +# authors: Luke Williams <xocel@iquidus.org> +# Jacob Pipkin <j@dawnrazor.net> +# Andreas Guldstrand <andreas.guldstrand@gmail.com> +# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING> + +use 5.16.0; +use strict; +use warnings FATAL => 'all'; +use File::Basename; + +our $VERSION = '2.5'; + +sub new { + my $class = shift; + + my $self = $class->_parse_opts(@_); + $self->{fname} = basename( (caller(0))[1] ); + + return bless $self, $class; +} + +1; diff --git a/SBO-Lib/lib/SBO/App/Remove.pm b/SBO-Lib/lib/SBO/App/Remove.pm new file mode 100644 index 0000000..9747a6a --- /dev/null +++ b/SBO-Lib/lib/SBO/App/Remove.pm @@ -0,0 +1,219 @@ +package SBO::App::Remove; + +# vim: ts=2:et +# +# authors: Luke Williams <xocel@iquidus.org> +# Jacob Pipkin <j@dawnrazor.net> +# Andreas Guldstrand <andreas.guldstrand@gmail.com> +# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING> + +use 5.16.0; +use strict; +use warnings FATAL => 'all'; +use SBO::Lib qw/ get_inst_names get_installed_packages get_sbo_location get_build_queue merge_queues get_requires get_readme_contents prompt show_version in /; +use Getopt::Long qw(GetOptionsFromArray :config bundling); + +use parent 'SBO::App'; + +our $VERSION = '2.5'; + +sub _parse_opts { + my $class = shift; + my @ARGS = @_; + + my ($help, $vers, $non_int, $alwaysask); + + GetOptionsFromArray( + \@ARGS, + 'help|h' => \$help, + 'version|v' => \$vers, + 'nointeractive' => \$non_int, + 'alwaysask|a' => \$alwaysask, + ); + + return { help => $help, vers => $vers, non_int => $non_int, alwaysask => $alwaysask, args => \@ARGS, }; +} + +sub run { + my $self = shift; + + if ($self->{help}) { $self->show_usage(); return 0; } + if ($self->{vers}) { $self->show_version(); return 0; } + if (!@{ $self->{args} }) { $self->show_usage(); return 1; } + + # current workflow: + # * get names of all installed SBo packages + # * compare commandline args to SBo packages as well as installed SBo packages + # * add reverse deps to list if they're not a dep of something else (which is not also already on the list) + # * confirm removal of each package on the list + # - while taking into account the options passed in such as $non_int, and $alwaysask + # - also offering to display README if %README% is passed + # * remove the confirmed packages + + my @args = @{ $self->{args} }; + + my @installed = @{ get_installed_packages('SBO') }; + my $installed = +{ map {; $_->{name}, $_->{pkg} } @installed }; + + @args = grep { check_sbo($_, $installed) } @args; + exit 1 unless @args; + my %sbos = map { $_ => 1 } @args; + + my @remove = get_full_queue($installed, @args); + + my @confirmed; + + if ($self->{non_int}) { + @confirmed = @remove; + } else { + my $required_by = get_reverse_reqs($installed); + for my $remove (@remove) { + # if $remove was on the commandline, mark it as not needed, + # otherwise check if it is needed by something else. + my @required_by = get_required_by($remove->{name}, [map { $_->{name} } @confirmed], $required_by); + my $needed = $sbos{$remove->{name}} ? 0 : @required_by; + + next if $needed and not $self->{alwaysask}; + + push @confirmed, $remove if confirm($remove, $needed ? @required_by : ()); + } + } + + if (@confirmed) { + $self->remove(@confirmed); + } else { + say "Nothing to remove."; + } + + return 0; +} + +sub show_usage { + my $self = shift; + my $fname = $self->{fname}; + + print <<"EOF"; +Usage: $fname [options] sbo + +Options (defaults shown first where applicable): + -h|--help: + this screen. + -v|--version: + version information. + -a|--alwaysask: + always ask to remove, even if required by other packages on system. + +Note: optional dependencies need to be removed separately. + +EOF + return 1; +} + +sub check_sbo { + my ($sbo, $installed) = @_; + + if (not get_sbo_location($sbo)) { + say "Unable to locate $sbo in the SlackBuilds.org tree."; + return 0; + } + + if (not exists $installed->{$sbo}) { + say "$sbo is not installed from SlackBuilds.org."; + return 0; + } + + return 1; +} + +sub get_full_queue { + my ($installed, @sbos) = @_; + + my $remove_queue = []; + my %warnings; + for my $sbo (@sbos) { + my $queue = get_build_queue([$sbo], \%warnings); + @$queue = reverse @$queue; + $remove_queue = merge_queues($remove_queue, $queue); + } + + return map {; +{ + name => $_, + pkg => $installed->{$_}, + defined $warnings{$_} ? (warning => $warnings{$_}) : () + } } + grep { exists $installed->{$_} } + @$remove_queue; +} + +sub get_reverse_reqs { + my $installed = shift; + my %required_by; + + for my $inst (keys %$installed) { + for my $req (@{ get_requires($inst) }) { + $required_by{$req}{$inst} = 1 if exists $installed->{$req}; + } + } + + return \%required_by; +} + +sub get_required_by { + my ($sbo, $confirmed, $required_by) = @_; + my @dep_of; + + if ( $required_by->{$sbo} ) { + for my $req_by (keys %{$required_by->{$sbo}}) { + push @dep_of, $req_by unless in($req_by => @$confirmed); + } + } + return @dep_of; +} + +sub confirm { + my ($remove, @required_by) = @_; + + if (@required_by) { + say sprintf "%s : required by %s", $remove->{name}, join ' ', @required_by; + } else { + say $remove->{name}; + } + + if ($remove->{warning}) { + say "It is recommended that you view the README before continuing."; + if (prompt("Display README now?", default => 'yes')) { + my $readme = get_readme_contents(get_sbo_location($remove->{name})); + if (not defined $readme) { + warn "Unable to open README for $remove->{name}.\n"; + } else { + print "\n" . $readme; + } + } + } + + if (prompt("Remove $remove->{name}?", default => @required_by ? 'no' : 'yes')) { + say " * Added to remove queue\n"; + return 1; + } + say " * Ignoring\n"; + return 0; +} + +sub remove { + my $self = shift; + my $non_int = $self->{non_int}; + my @confirmed = @_; + + say sprintf "Removing %d package(s)", scalar @confirmed; + say join " ", map { $_->{name} } @confirmed; + + if (!$non_int and !prompt("\nAre you sure you want to continue?", default => 'no')) { + return say 'Exiting.'; + } + + system("/sbin/removepkg", $_->{pkg}) for @confirmed; + + say "All operations have completed successfully."; +} + +1; diff --git a/SBO-Lib/lib/SBO/App/Snap.pm b/SBO-Lib/lib/SBO/App/Snap.pm new file mode 100644 index 0000000..bfa80b4 --- /dev/null +++ b/SBO-Lib/lib/SBO/App/Snap.pm @@ -0,0 +1,81 @@ +package SBO::App::Snap; + +# vim: ts=2:et +# +# sbosnap +# script to pull down / update a local copy of the slackbuilds.org tree. +# +# authors: Jacob Pipkin <j@dawnrazor.net> +# Luke Williams <xocel@iquidus.org> +# Andreas Guldstrand <andreas.guldstrand@gmail.com> +# license: WTFPL <http://sam.zoy.org/wtfpl/COPYING> + +use 5.16.0; +use strict; +use warnings FATAL => 'all'; +use SBO::Lib qw/ fetch_tree update_tree %config show_version /; +use Getopt::Long qw/ GetOptionsFromArray /; + +use parent 'SBO::App'; + +our $VERSION = '2.5'; + +sub _parse_opts { + my $class = shift; + my @ARGS = @_; + + my ($help, $vers); + + GetOptionsFromArray( + \@ARGS, + 'help|h' => \$help, + 'version|v' => \$vers, + ); + + return { help => $help, vers => $vers, args => \@ARGS, }; +} + +sub show_usage { + my $self = shift; + my $fname = $self->{fname}; + print <<"EOF"; +Usage: $fname [options|command] + +Options: + -h|--help: + this screen. + -v|--version: + version information. + +Commands: + fetch: initialize a local copy of the slackbuilds.org tree. + update: update an existing local copy of the slackbuilds.org tree. + (generally, you may prefer "sbocheck" over "$fname update") + +EOF + return 1; +} + +sub run { + my $self = shift; + my @args = @{ $self->{args} }; + + if ($self->{help}) { $self->show_usage(); return 0 } + if ($self->{vers}) { $self->show_version(); return 0 } + + # check for a command and, if found, execute it + $args[0] //= ''; + + if ($args[0] eq 'fetch') { + fetch_tree() + } elsif ($args[0] eq 'update') { + update_tree() + } else { + $self->show_usage(); + return 1; + } + + return 0; +} + +1; diff --git a/SBO-Lib/lib/SBO/Lib.pm b/SBO-Lib/lib/SBO/Lib.pm index 25f39a3..42eb313 100644 --- a/SBO-Lib/lib/SBO/Lib.pm +++ b/SBO-Lib/lib/SBO/Lib.pm @@ -15,7 +15,7 @@ use strict; use warnings FATAL => 'all'; package SBO::Lib; -our $VERSION = '2.1'; +our $VERSION = '2.5'; =pod @@ -109,7 +109,7 @@ Guldstrand <andreas.guldstrand@gmail.com>. The sbotools are licensed under the WTFPL <http://sam.zoy.org/wtfpl/COPYING>. -Copyright (C) 2012-2016, Jacob Pipkin, Luke Williams, Andreas Guldstrand. +Copyright (C) 2012-2017, Jacob Pipkin, Luke Williams, Andreas Guldstrand. =cut diff --git a/SBO-Lib/lib/SBO/Lib/Build.pm b/SBO-Lib/lib/SBO/Lib/Build.pm index 9323f16..f6911a9 100644 --- a/SBO-Lib/lib/SBO/Lib/Build.pm +++ b/SBO-Lib/lib/SBO/Lib/Build.pm @@ -4,7 +4,7 @@ use 5.016; use strict; use warnings; -our $VERSION = '2.1'; +our $VERSION = '2.5'; 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 /; @@ -241,7 +241,7 @@ sub get_dc_regex { # convert any instances of command substitution to [^-]+ $line =~ s/\$\([^)]+\)/[^-]+/g; # convert any bash variables to [^-]+ - $line =~ s/\$({|)[A-Za-z0-9_]+(}|)/[^-]+/g; + $line =~ s/\$(\{|)[A-Za-z0-9_]+(}|)/[^-]+/g; # get rid of anything excess at the end $line =~ s/\s+.*$//; # fix .?z* at the end @@ -762,7 +762,7 @@ Guldstrand <andreas.guldstrand@gmail.com>. The sbotools are licensed under the WTFPL <http://sam.zoy.org/wtfpl/COPYING>. -Copyright (C) 2012-2016, Jacob Pipkin, Luke Williams, Andreas Guldstrand. +Copyright (C) 2012-2017, Jacob Pipkin, Luke Williams, Andreas Guldstrand. =cut diff --git a/SBO-Lib/lib/SBO/Lib/Download.pm b/SBO-Lib/lib/SBO/Lib/Download.pm index 0f6d40a..264067a 100644 --- a/SBO-Lib/lib/SBO/Lib/Download.pm +++ b/SBO-Lib/lib/SBO/Lib/Download.pm @@ -4,7 +4,7 @@ use 5.016; use strict; use warnings; -our $VERSION = '2.1'; +our $VERSION = '2.5'; use SBO::Lib::Util qw/ :const script_error get_sbo_from_loc open_read get_arch /; use SBO::Lib::Repo qw/ $distfiles /; @@ -161,7 +161,7 @@ sub get_distfile { # if wget $link && verify, return # else wget sbosrcarch && verify - if (system('wget', '--no-check-certificate', $link) != 0) { + if (system('wget', '--no-check-certificate', '--tries=5', $link) != 0) { $fail->{msg} = "Unable to wget $link.\n"; $fail->{err} = _ERR_DOWNLOAD; } @@ -179,7 +179,7 @@ sub get_distfile { substr($info_md5, 0, 1), substr($info_md5, 1, 1), $info_md5, _get_fname($link)); return 1 if - system('wget', '--no-check-certificate', $sbosrcarch) == 0 and + system('wget', '--no-check-certificate', '--tries=5', $sbosrcarch) == 0 and verify_distfile(@_); return $fail->{msg}, $fail->{err}; @@ -296,7 +296,7 @@ Guldstrand <andreas.guldstrand@gmail.com>. The sbotools are licensed under the WTFPL <http://sam.zoy.org/wtfpl/COPYING>. -Copyright (C) 2012-2016, Jacob Pipkin, Luke Williams, Andreas Guldstrand. +Copyright (C) 2012-2017, Jacob Pipkin, Luke Williams, Andreas Guldstrand. =cut diff --git a/SBO-Lib/lib/SBO/Lib/Info.pm b/SBO-Lib/lib/SBO/Lib/Info.pm index 3f20497..b79c7fd 100644 --- a/SBO-Lib/lib/SBO/Lib/Info.pm +++ b/SBO-Lib/lib/SBO/Lib/Info.pm @@ -4,7 +4,7 @@ use 5.016; use strict; use warnings; -our $VERSION = '2.1'; +our $VERSION = '2.5'; use SBO::Lib::Util qw/ get_arch get_sbo_from_loc open_read script_error slurp usage_error /; use SBO::Lib::Tree qw/ get_orig_location get_sbo_location is_local /; @@ -18,6 +18,7 @@ our @EXPORT_OK = qw{ get_orig_version get_requires get_sbo_version + parse_info }; our %EXPORT_TAGS = ( @@ -132,18 +133,13 @@ sub get_from_info { usage_error("get_from_info: could not read $args{LOCATION}/$sbo.info.") unless defined $contents; - $contents =~ s/("|\\\n)//g; - my $last_key = ''; + my %parse = parse_info($contents); + script_error("error when parsing $sbo.info file.") unless %parse; + $store = {}; $store->{LOCATION} = [$args{LOCATION}]; - foreach my $line (split /\n/, $contents) { - my ($key, $val) = $last_key; - if ($line =~ /^([^=\s]+)=(.*)$/) { $key = $1; $val = $2; } - elsif ($line =~ /^\s+([^\s].+)$/) { $val = $1; } - else { script_error("error when parsing $sbo.info file. Line: $line") } - push @{ $store->{$key} }, ($val ? split(' ', $val) : $val); - $last_key = $key; - } + foreach my $k (keys %parse) { $store->{$k} = $parse{$k}; } + # allow local overrides to get away with not having quite all the fields if (is_local($sbo)) { for my $key (qw/DOWNLOAD_x86_64 MD5SUM_x86_64 REQUIRES/) { @@ -184,7 +180,7 @@ C<get_requires()> returns the requirements for a given C<$sbo>. # wrapper to pull the list of requirements for a given sbo sub get_requires { my $location = get_sbo_location(shift); - return() unless $location; + return [] unless $location; my $info = get_from_info(LOCATION => $location, GET => 'REQUIRES'); return $info; } @@ -205,6 +201,36 @@ sub get_sbo_version { return $version->[0]; } +=head2 parse_info + + my %parse = parse_info($str); + +C<parse_info()> parses the contents of an .info file from C<$str> and returns +a key-value list of it. + +=cut + +sub parse_info { + script_error('parse_info requires an argument.') unless @_ == 1; + my $info_str = shift; + my $pos = 0; + my %ret; + + while ($info_str =~ /\G([A-Za-z0-9_]+)="([^"]*)"\s*(?:\n|\z)/g) { + my ($key, $val) = ($1, $2); + $val =~ s/\\[ \t]*$/ /mg; + my @val = split " ", $val; + @val = '' unless @val; + $ret{$key} = \@val; + $pos = pos($info_str); + } + + return if $pos != length($info_str); + + return %ret; + +} + =head1 AUTHORS SBO::Lib was originally written by Jacob Pipkin <j@dawnrazor.net> with @@ -215,7 +241,7 @@ Guldstrand <andreas.guldstrand@gmail.com>. The sbotools are licensed under the WTFPL <http://sam.zoy.org/wtfpl/COPYING>. -Copyright (C) 2012-2016, Jacob Pipkin, Luke Williams, Andreas Guldstrand. +Copyright (C) 2012-2017, Jacob Pipkin, Luke Williams, Andreas Guldstrand. =cut diff --git a/SBO-Lib/lib/SBO/Lib/Pkgs.pm b/SBO-Lib/lib/SBO/Lib/Pkgs.pm index 6975a7f..be3507e 100644 --- a/SBO-Lib/lib/SBO/Lib/Pkgs.pm +++ b/SBO-Lib/lib/SBO/Lib/Pkgs.pm @@ -4,7 +4,7 @@ use 5.016; use strict; use warnings; -our $VERSION = '2.1'; +our $VERSION = '2.5'; use SBO::Lib::Util qw/ %config script_error open_read version_cmp /; use SBO::Lib::Tree qw/ get_sbo_location get_sbo_locations is_local /; @@ -128,8 +128,8 @@ C<get_installed_packages()> returns an array reference to a list of packages in C</var/log/packages> that match the specified C<$type>. The available types are C<STD> for non-SBo packages, C<SBO> for SBo packages, and C<ALL> for both. -The returned array reference will hold a list of hashes representing both names -and versions of the returned packages. +The returned array reference will hold a list of hash references representing +both names, versions, and full installed package name of the returned packages. =cut @@ -205,7 +205,7 @@ Guldstrand <andreas.guldstrand@gmail.com>. The sbotools are licensed under the WTFPL <http://sam.zoy.org/wtfpl/COPYING>. -Copyright (C) 2012-2016, Jacob Pipkin, Luke Williams, Andreas Guldstrand. +Copyright (C) 2012-2017, Jacob Pipkin, Luke Williams, Andreas Guldstrand. =cut diff --git a/SBO-Lib/lib/SBO/Lib/Readme.pm b/SBO-Lib/lib/SBO/Lib/Readme.pm index b29558b..e46c557 100644 --- a/SBO-Lib/lib/SBO/Lib/Readme.pm +++ b/SBO-Lib/lib/SBO/Lib/Readme.pm @@ -4,7 +4,7 @@ use 5.016; use strict; use warnings; -our $VERSION = '2.1'; +our $VERSION = '2.5'; use SBO::Lib::Util qw/ prompt script_error slurp open_read _ERR_OPENFH usage_error /; use SBO::Lib::Tree qw/ is_local /; @@ -13,6 +13,7 @@ use Exporter 'import'; our @EXPORT_OK = qw{ ask_opts + ask_other_readmes ask_user_group get_opts get_readme_contents @@ -77,6 +78,31 @@ sub ask_opts { return(); } +=head2 ask_other_readmes + + ask_other_readmes($sbo, $location); + +C<ask_other_readmes()> checks if there are other readmes for the C<$sbo> in +C<$location>, and if so, asks the user if they should be displayed, and then +displays them if the user didn't decline. + +=cut + +sub ask_other_readmes { + my ($sbo, $location) = @_; + my @readmes = sort grep { ! m!/README$! } glob "$location/README*"; + + return unless @readmes; + + return unless prompt("\nIt looks like $sbo has additional README files. Would you like to see those too?", default => 'yes'); + + for my $fn (@readmes) { + my ($display_fn) = $fn =~ m!/(README.*)$!; + say "\n$display_fn:"; + say slurp $fn; + } +} + =head2 ask_user_group my $bool = ask_user_group($cmds, $readme); @@ -144,7 +170,7 @@ C<groupadd> commands, and returns them in an array reference. sub get_user_group { script_error('get_user_group requires an argument') unless @_ == 1; my $readme = shift; - my @cmds = $readme =~ /^\s*#*\s*(useradd.*|groupadd.*)/mg; + my @cmds = $readme =~ /^\s*#*\s*(useradd.*?|groupadd.*?)(?<!\\)\n/msg; return \@cmds; } @@ -183,6 +209,7 @@ sub user_prompt { my $opts = 0; $opts = ask_opts($sbo, $readme) if get_opts($readme); print "\n". $readme unless $opts; + ask_other_readmes($sbo, $location); # we have to return something substantial if the user says no so that we # can check the value of $cmds on the calling side. we should be able to # assume that 'N' will never be a valid command to run. @@ -200,7 +227,7 @@ Guldstrand <andreas.guldstrand@gmail.com>. The sbotools are licensed under the WTFPL <http://sam.zoy.org/wtfpl/COPYING>. -Copyright (C) 2012-2016, Jacob Pipkin, Luke Williams, Andreas Guldstrand. +Copyright (C) 2012-2017, Jacob Pipkin, Luke Williams, Andreas Guldstrand. =cut diff --git a/SBO-Lib/lib/SBO/Lib/Repo.pm b/SBO-Lib/lib/SBO/Lib/Repo.pm index e920b6b..e2c5bae 100644 --- a/SBO-Lib/lib/SBO/Lib/Repo.pm +++ b/SBO-Lib/lib/SBO/Lib/Repo.pm @@ -4,9 +4,9 @@ use 5.016; use strict; use warnings; -our $VERSION = '2.1'; +our $VERSION = '2.5'; -use SBO::Lib::Util qw/ %config prompt usage_error get_slack_version script_error open_fh open_read in /; +use SBO::Lib::Util qw/ %config prompt usage_error get_slack_version script_error open_fh open_read in _ERR_DOWNLOAD /; use Cwd; use File::Copy; @@ -242,7 +242,7 @@ sub git_sbo_tree { } else { chdir $config{SBO_HOME} or return 0; remove_tree($repo_path) if -d $repo_path; - $res = system(qw/ git clone /, $url, $repo_path) == 0; + $res = system(qw/ git clone --no-local /, $url, $repo_path) == 0; } _race::cond '$cwd could be deleted here'; return 1 if chdir $cwd and $res; @@ -300,6 +300,8 @@ sub pull_sbo_tree { $res = git_sbo_tree($url); } + if ($res == 0) { warn "Could not sync from $url.\n"; exit _ERR_DOWNLOAD; } + my $wanted = sub { chown 0, 0, $File::Find::name; }; find($wanted, $repo_path) if -d $repo_path; if ($res and not chk_slackbuilds_txt()) { @@ -324,7 +326,7 @@ sub rsync_sbo_tree { my @info; # only slackware versions above 14.1 have an rsync that supports --info=progress2 if (versioncmp(get_slack_version(), '14.1') == 1) { @info = ('--info=progress2'); } - my @args = ('rsync', @info, '-a', '--exclude=*.tar.gz', '--exclude=*.tar.gz.asc', '--delete', $url); + my @args = ('rsync', @info, '-a', '--delete', $url); return system(@args, $repo_path) == 0; } @@ -378,7 +380,7 @@ Guldstrand <andreas.guldstrand@gmail.com>. The sbotools are licensed under the WTFPL <http://sam.zoy.org/wtfpl/COPYING>. -Copyright (C) 2012-2016, Jacob Pipkin, Luke Williams, Andreas Guldstrand. +Copyright (C) 2012-2017, Jacob Pipkin, Luke Williams, Andreas Guldstrand. =cut diff --git a/SBO-Lib/lib/SBO/Lib/Tree.pm b/SBO-Lib/lib/SBO/Lib/Tree.pm index e8d17fb..2e75de0 100644 --- a/SBO-Lib/lib/SBO/Lib/Tree.pm +++ b/SBO-Lib/lib/SBO/Lib/Tree.pm @@ -4,7 +4,7 @@ use 5.016; use strict; use warnings; -our $VERSION = '2.1'; +our $VERSION = '2.5'; use SBO::Lib::Util qw/ script_error open_read idx %config /; use SBO::Lib::Repo qw/ $repo_path $slackbuilds_txt /; @@ -76,7 +76,7 @@ filesystem once when searching, and populating the internal cache. =cut sub get_sbo_location { - my @sbos = defined $_[0] && ref $_[0] eq 'ARRAY' ? @{ $_[0] } : @_; + my @sbos = map { s/-compat32$//r } defined $_[0] && ref $_[0] eq 'ARRAY' ? @{ $_[0] } : @_; script_error('get_sbo_location requires an argument.') unless @sbos; # if we already have the location, return it now. @@ -95,7 +95,7 @@ package name to its location. =cut sub get_sbo_locations { - my @sbos = defined $_[0] && ref $_[0] eq 'ARRAY' ? @{ $_[0] } : @_; + my @sbos = map { s/-compat32$//r } defined $_[0] && ref $_[0] eq 'ARRAY' ? @{ $_[0] } : @_; script_error('get_sbo_locations requires an argument.') unless @_; my %locations; @@ -168,7 +168,7 @@ Guldstrand <andreas.guldstrand@gmail.com>. The sbotools are licensed under the WTFPL <http://sam.zoy.org/wtfpl/COPYING>. -Copyright (C) 2012-2016, Jacob Pipkin, Luke Williams, Andreas Guldstrand. +Copyright (C) 2012-2017, Jacob Pipkin, Luke Williams, Andreas Guldstrand. =cut diff --git a/SBO-Lib/lib/SBO/Lib/Util.pm b/SBO-Lib/lib/SBO/Lib/Util.pm index c4128af..52f622a 100644 --- a/SBO-Lib/lib/SBO/Lib/Util.pm +++ b/SBO-Lib/lib/SBO/Lib/Util.pm @@ -4,7 +4,7 @@ use 5.016; use strict; use warnings; -our $VERSION = '2.1'; +our $VERSION = '2.5'; use Exporter 'import'; use Sort::Versions; @@ -350,7 +350,7 @@ sub print_failures { exit unless prompt "Should we continue?", default => "yes"; -C<prompt()> prompts the user for an answer, optinally specifying a default of +C<prompt()> prompts the user for an answer, optionally specifying a default of C<yes> or C<no>. If the default has been specified it returns a true value in case 'yes' was selected, and a false value if 'no' was selected. Otherwise it returns whatever the user answered. @@ -506,20 +506,32 @@ sub usage_error { C<version_cmp()> will compare C<$ver1> with C<$ver2> to try to determine which is bigger than the other, and returns 1 if C<$ver1> is bigger, -1 if C<$ver2> is bigger, and 0 if they are just as big. Before making the comparison, it will -strip off the version of your running kernel if it happens to be appended to -the version string being compared. +strip off the version of your running kernel as well as any locale information +if it happens to be appended to the version string being compared. =cut # wrapper around versioncmp for checking if versions have kernel version -# appended to them +# or locale info appended to them sub version_cmp { my ($v1, $v2) = @_; my $kv = get_kernel_version(); + # strip off kernel version if ($v1 =~ /(.+)_\Q$kv\E$/) { $v1 = $1 } if ($v2 =~ /(.+)_\Q$kv\E$/) { $v2 = $1 } + # if $v2 doesn't end in the same thing, strip off locale info from $v1 + if ($v1 =~ /(.*)_([a-z]{2})_([A-Z]{2})$/) { + my $v = $1; + if ($v2 !~ /_$2_$3$/) { $v1 = $v; } + } + # and vice versa... + if ($v2 =~ /(.*)_([a-z]{2})_([A-Z]{2})$/) { + my $v = $1; + if ($v1 !~ /_$2_$3$/) { $v2 = $v; } + } + versioncmp($v1, $v2); } @@ -537,7 +549,7 @@ Guldstrand <andreas.guldstrand@gmail.com>. The sbotools are licensed under the WTFPL <http://sam.zoy.org/wtfpl/COPYING>. -Copyright (C) 2012-2016, Jacob Pipkin, Luke Williams, Andreas Guldstrand. +Copyright (C) 2012-2017, Jacob Pipkin, Luke Williams, Andreas Guldstrand. =cut diff --git a/man1/sbocheck.1 b/man1/sbocheck.1 index 6a6c268..bbb4ba7 100644 --- a/man1/sbocheck.1 +++ b/man1/sbocheck.1 @@ -1,4 +1,4 @@ -.TH sbocheck 1 "Pungenday, Confusion 37, 3182 YOLD" "sbotools 2.0" dawnrazor.net +.TH sbocheck 1 "Setting Orange, Chaos 45, 3184 YOLD" "sbotools 2.5" dawnrazor.net .SH NAME .P sbocheck - update a local slackbuilds.org tree and check for updates. diff --git a/man1/sboclean.1 b/man1/sboclean.1 index 2e3bf2f..af3144e 100644 --- a/man1/sboclean.1 +++ b/man1/sboclean.1 @@ -1,4 +1,4 @@ -.TH sboclean 1 "Pungenday, Confusion 37, 3182 YOLD" "sbotools 2.0" dawnrazor.net +.TH sboclean 1 "Setting Orange, Chaos 45, 3184 YOLD" "sbotools 2.5" dawnrazor.net .SH NAME .P sboclean - clean files left around by sbotools. diff --git a/man1/sboconfig.1 b/man1/sboconfig.1 index cb6d346..ad225a2 100644 --- a/man1/sboconfig.1 +++ b/man1/sboconfig.1 @@ -1,4 +1,4 @@ -.TH sboconfig 1 "Pungenday, Confusion 37, 3182 YOLD" "sbotools 2.0" dawnrazor.net +.TH sboconfig 1 "Setting Orange, Chaos 45, 3184 YOLD" "sbotools 2.5" dawnrazor.net .SH NAME .P sboconfig - set sbotools configuration options. diff --git a/man1/sbofind.1 b/man1/sbofind.1 index a21fc79..606d4ef 100644 --- a/man1/sbofind.1 +++ b/man1/sbofind.1 @@ -1,4 +1,4 @@ -.TH sbofind 1 "Pungenday, Confusion 37, 3182 YOLD" "sbotools 2.0" dawnrazor.net +.TH sbofind 1 "Setting Orange, Chaos 45, 3184 YOLD" "sbotools 2.5" dawnrazor.net .SH NAME .P sbofind - search slackbuilds.org tree for a given name diff --git a/man1/sboinstall.1 b/man1/sboinstall.1 index bee6b0f..8d4eb33 100644 --- a/man1/sboinstall.1 +++ b/man1/sboinstall.1 @@ -1,4 +1,4 @@ -.TH sboinstall 1 "Pungenday, Confusion 37, 3182 YOLD" "sbotools 2.0" dawnrazor.net +.TH sboinstall 1 "Setting Orange, Chaos 45, 3184 YOLD" "sbotools 2.5" dawnrazor.net .SH NAME .P sboinstall - install slackbuilds @@ -9,6 +9,8 @@ sboinstall [-h|-v] [-d TRUE|FALSE] [-j #|FALSE] [-c TRUE|FALSE] [-NRip] --use-te .SH DESCRIPTION .P sboinstall is used to install SBos. If the -r flag is NOT specified, sboinstall will pull the list of requirements from the .info file for any specified slackbuild. If such a list exists, sboinstall will look to see whether or not those requirements are already installed, and if not, it will ask whether or not it should attempt to install them first. This is recursive, so that ordering happens correctly. sboinstall will refuse to handle circular requirements. sboinstall will attempt to note groupadd and useradd commands in README files and offer to run those first. If the README appears to document options of the KEY=value form, sboinstall will offer the opportunity to set options. +.P +sboinstall will attempt to download the sources from the DOWNLOAD or DOWNLOAD_x86_64 variables in the .info file. If such a download fails or the file can't be verified, it'll attempt to download the file from ftp://slackware.uk/sbosrcarch/ instead. .SH OPTIONS .P -h|--help @@ -56,6 +58,11 @@ Skip viewing of the README and the yes or no question which accompanies it. Anyt This option causes sboinstall to skip requirement handling, but still show the README and prompt the user to proceed. .RE .P +--reinstall +.RS +This option asks if we should reinstall anything among the requirements that is already installed. +.RE +.P --create-template (FILE) .RS Create a template for the SlackBuilds including any optional commands or build options that you wish to set and store this in the specified FILE. diff --git a/man1/sboremove.1 b/man1/sboremove.1 index 55c7a86..159e778 100644 --- a/man1/sboremove.1 +++ b/man1/sboremove.1 @@ -1,4 +1,4 @@ -.TH sboremove 1 "Pungenday, Confusion 37, 3182 YOLD" "sbotools 2.0" dawnrazor.net +.TH sboremove 1 "Setting Orange, Chaos 45, 3184 YOLD" "sbotools 2.5" dawnrazor.net .SH NAME .P sboremove - remove packages installed from slackbuilds diff --git a/man1/sbosnap.1 b/man1/sbosnap.1 index 0145f32..f317ffb 100644 --- a/man1/sbosnap.1 +++ b/man1/sbosnap.1 @@ -1,4 +1,4 @@ -.TH sbosnap 1 "Pungenday, Confusion 37, 3182 YOLD" "sbotools 2.0" dawnrazor.net +.TH sbosnap 1 "Setting Orange, Chaos 45, 3184 YOLD" "sbotools 2.5" dawnrazor.net .SH NAME .P sbosnap - slackbuilds.org tree fetch and update command. @@ -40,6 +40,9 @@ sbosnap can exit with the following codes: .RS 1: a usage error occurred, such as running sbosnap with no command. .RE +.RS +5: error downloading from the repository. +.RE .SH BUGS .P None known, but there may be some. Please report any found to https://github.com/pink-mist/sbotools/issues ; patches are always welcome. diff --git a/man1/sboupgrade.1 b/man1/sboupgrade.1 index 9c19d83..6cac0d1 100644 --- a/man1/sboupgrade.1 +++ b/man1/sboupgrade.1 @@ -1,4 +1,4 @@ -.TH sboupgrade 1 "Pungenday, Confusion 37, 3182 YOLD" "sbotools 2.0" dawnrazor.net +.TH sboupgrade 1 "Setting Orange, Chaos 45, 3184 YOLD" "sbotools 2.5" dawnrazor.net .SH NAME .P sboupgrade - install or upgrade slackbuilds @@ -8,6 +8,8 @@ sboupgrade [-h|-v] [-c TRUE|FALSE] [-d TRUE|FALSE] [-j #|FALSE] [-fNrRiz] --all| .SH DESCRIPTION .P sboupgrade is used to upgrade packages installed from slackbuilds. If the -r flag is NOT specified, sboupgrade will pull the list of requirements from the .info file for any specified slackbuild. If such a list exists, sboupgrade will look to see whether or not those requirements are already installed, and if not, it will ask whether or not it should attempt to install them first. This is recursive, so that ordering happens correctly. sboupgrade will refuse to handle circular requirements. sboupgrade will also note groupadd and useradd commands in README files and offer to run those first. If the README documents options of the KEY=value form, sboupgrade will offer the opportunity to set options. If --all is supplied it will try to upgrade everything that sbocheck(1) reports. +.P +sboupgrade will attempt to download the sources from the DOWNLOAD or DOWNLOAD_x86_64 variables in the .info file. If such a download fails or the file can't be verified, it'll attempt to download the file from ftp://slackware.uk/sbosrcarch/ instead. .SH OPTIONS .P -h|--help diff --git a/man5/sbotools.conf.5 b/man5/sbotools.conf.5 index d428e7b..469f99e 100644 --- a/man5/sbotools.conf.5 +++ b/man5/sbotools.conf.5 @@ -1,4 +1,4 @@ -.TH sbotools.conf 5 "Pungenday, Confusion 37, 3182 YOLD" "sbotools 2.0" dawnrazor.net +.TH sbotools.conf 5 "Setting Orange, Chaos 45, 3184 YOLD" "sbotools 2.5" dawnrazor.net .SH NAME .P sbotools.conf - configuration file for sbotools commands. @@ -27,9 +27,12 @@ sub show_usage { Usage: $self [options] [arguments] Options: - -h: this screen. - -v: version information. - -l: show current options. + -h|--help: + this screen. + -v|--version: + version information. + -l|--list: + show current options. Config options (defaults shown): -c|--clean FALSE: @@ -13,7 +13,7 @@ use 5.16.0; use strict; use warnings FATAL => 'all'; -use SBO::Lib qw/ slackbuilds_or_fetch slurp script_error open_read get_build_queue %config $slackbuilds_txt $repo_path show_version in indent /; +use SBO::Lib qw/ slackbuilds_or_fetch slurp script_error open_read get_build_queue %config $slackbuilds_txt $repo_path show_version in indent get_from_info /; use File::Basename; use Getopt::Long qw(:config bundling); @@ -97,28 +97,37 @@ sub perform_search { } my (%local, @findings); FIRST: while (my $line = <$fh>) { - next FIRST unless $line =~ /NAME:/; + if ($line =~ /NAME:\s+(.*)$/) { + my $name = $1; - # Try to match either the search string or any of the names from the TAGS.txt - foreach my $search ($search_name_re, map { quotemeta } @names) { - if (my ($name) = $line =~ /NAME:\s+($search)$/i) { + # Try to match either one of the names from TAGS.txt or the search string - # If the name matches a local override, use its location - if ($config{LOCAL_OVERRIDES} ne 'FALSE' and -d "$config{LOCAL_OVERRIDES}/$name") { - push @findings, {name => $name, location => "$config{LOCAL_OVERRIDES}/$name", local => 1 }; - $local{$name} = 1; - next FIRST; - } + my $names = @names; + # Whenever we find an element equal to $name, throw it away (and + # replace with last element rather than shifting stuff around) + for (reverse @names) { $_ = pop @names if $_ eq $name; } + + # next if $name didn't match either one of @names or $search_name_re + if ($names == @names and $name !~ /$search_name_re/i) { next FIRST; } + + # We only reach this point if $name matched one of @names, or if + # $search_name_re matched - # Otherwise the location should be in the next line - LOCATION: { - my $loc_line = <$fh>; - if (my ($location) = $loc_line =~ $loc_regex) { - push @findings, {name => $name, location => $repo_path . $location}; - next FIRST; - } else { - redo LOCATION; # But if it isn't, we try again... - } + # If the name matches a local override, use its location + if ($config{LOCAL_OVERRIDES} ne 'FALSE' and -d "$config{LOCAL_OVERRIDES}/$name") { + push @findings, {name => $name, location => "$config{LOCAL_OVERRIDES}/$name", local => 1 }; + $local{$name} = 1; + next FIRST; + } + + # Otherwise the location should be in the next line + LOCATION: { + my $loc_line = <$fh>; + if (my ($location) = $loc_line =~ $loc_regex) { + push @findings, {name => $name, location => $repo_path . $location}; + next FIRST; + } else { + redo LOCATION; # But if it isn't, we try again... } } } @@ -159,8 +168,9 @@ if (exists $$findings[0]) { for my $hash (@$findings) { my $name = $hash->{name}; my $location = $hash->{location}; + my $version = get_from_info(LOCATION => $location, GET => 'VERSION')->[0]; my $sbo = "SBo: "; $sbo = "Local: " if $hash->{local}; - say "$sbo $name"; + say "$sbo $name $version"; say "Path: $location"; say "info: ". get_file_contents("$location/$name.info") if $show_info; say "README: ". get_file_contents("$location/README") if $show_readme; @@ -44,6 +44,8 @@ Options (defaults shown first where applicable): non-interactive; skips README and all prompts. -R|--norequirements: view the README but do not parse requirements, commands, or options. + --reinstall: + Ask to reinstall any already-installed packages in the requirement list. --create-template (FILE): create a template with specified requirements, commands, and options. --use-template (FILE): @@ -57,7 +59,7 @@ EOF my $noclean = $config{NOCLEAN}; my $distclean = $config{DISTCLEAN}; my $jobs = $config{JOBS}; -my ($help, $vers, $no_install, $non_int, $no_reqs, $compat32, $ctemp, $utemp); +my ($help, $vers, $no_install, $non_int, $no_reqs, $compat32, $ctemp, $utemp, $reinstall); GetOptions( 'help|h' => \$help, @@ -69,6 +71,7 @@ GetOptions( 'compat32|p' => \$compat32, 'nointeractive|r' => \$non_int, 'norequirements|R' => \$no_reqs, + 'reinstall' => \$reinstall, 'create-template=s' => \$ctemp, 'use-template=s' => \$utemp, ); @@ -150,8 +153,13 @@ FIRST: for my $sbo (@$build_queue) { my $name = $compat32 ? "$sbo-compat32" : $sbo; if ($inst_names{$name}) { - say sprintf "%s (%s) is already installed.", $name, $inst_names{$name}{pkg}; - next FIRST; + my $inst_msg = sprintf "%s (%s) is already installed.", $name, $inst_names{$name}{pkg}; + if ($reinstall and not $non_int) { + next FIRST unless prompt("$inst_msg Do you want to reinstall from SBo?", default => 'no'); + } else { + say $inst_msg; + next FIRST; + } } else { if ($sbo =~ /^perl-/) { my $pm_name = $sbo; @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# vim: ts=4:noet +# vim: ts=2:et # # sboremove # script to remove an installed SlackBuild @@ -13,179 +13,8 @@ use 5.16.0; use strict; use warnings FATAL => 'all'; -use SBO::Lib qw/ get_inst_names get_installed_packages get_sbo_location get_build_queue merge_queues get_requires get_readme_contents prompt show_version in /; -use Getopt::Long qw(:config bundling); -use File::Basename; +use SBO::App::Remove; -my $self = basename ($0); +my $app = SBO::App::Remove->new(@ARGV); -sub show_usage { - print <<"EOF"; -Usage: $self [options] sbo - -Options (defaults shown first where applicable): - -h|--help: - this screen. - -v|--version: - version information. - -a|--alwaysask: - always ask to remove, even if required by other packages on system. - -Note: optional dependencies need to be removed separately. - -EOF - return 1; -} - -my ($help, $vers, $non_int, $alwaysask, @excluded); - -GetOptions( - 'help|h' => \$help, - 'version|v' => \$vers, - 'nointeractive' => \$non_int, - 'alwaysask|a' => \$alwaysask, -); - -if ($help) { show_usage(); exit 0 } -if ($vers) { show_version(); exit 0 } - -if (!@ARGV) { show_usage(); exit 1 } - -# ensure that all provided arguments are valid sbos -my @sbos; -my $inst_names = get_inst_names(get_installed_packages 'SBO'); -my %inst_names; -$inst_names{$_} = 1 for @$inst_names; -for my $sbo (@ARGV) { - if (get_sbo_location($sbo)) { - $inst_names{$sbo} ? push @sbos, $sbo - : say "$sbo is not installed from SlackBuilds.org."; - } else { - say "Unable to locate $sbo in the SlackBuilds.org tree." - } -} -exit 1 unless @sbos; - -# Create full queue. -my ($remove_queue, %warnings); -for my $sbo (@sbos) { - my $queue = get_build_queue([$sbo], \%warnings); - @$queue = reverse(@$queue); - $remove_queue = merge_queues($remove_queue, $queue); -} - -# Determine required by for all installed sbo's -my (%required_by, @confirmed); - -# populates the required_by hash -sub get_reverse_reqs { - my $installed = shift; - INST: for my $inst (@$installed) { - my $require = get_requires($inst); - REQ: for my $req (@$require) { - next REQ if $req eq '%README%'; - push @{ $required_by{$req} }, $inst if in($req => @$installed); - } - } - return 1; -} -get_reverse_reqs($inst_names); - -# returns a list of installed sbo's that list the given sbo as a requirement, -# excluding any installed sbo's that have already been confirmed for removal -sub get_required_by { - my $sbo = shift; - my @dep_of; - if ( $required_by{$sbo} ) { - for my $req_by (@{$required_by{$sbo}}) { - push @dep_of, $req_by unless in($req_by => @confirmed); - } - } - return @dep_of ? \@dep_of : undef; -} - -sub confirm_remove { - my $sbo = shift; - push @confirmed, $sbo unless in($sbo => @confirmed); - return 1; -} - -# Check if packages in queue are actually installed on system -my @temp; -for my $sbo (@$remove_queue) { - push @temp, $sbo if $inst_names{$sbo}; -} -$remove_queue = \@temp; - -# Confirm all and skip prompts if noninteractive -if ($non_int) { - confirm_remove($_) for @$remove_queue; - goto CONFIRMED; -} - -# Begin prompts -FIRST: for my $remove (@$remove_queue) { - # Determine whether $remove is still needed on system. - my $required_by = get_required_by $remove; - my $needed = 0; - my %sbos; - $sbos{$_} = 1 for @sbos; - for my $rq (@$required_by) { - $needed = 1 unless $sbos{$remove}; - # still needed, unless required_by is already confirmed for removal or - # the sbo in question was cli-specified. - } - if ( $needed ) { - next FIRST unless $alwaysask; #ignore sbo and skip prompt - print "$remove : required by " . join(' ', @$required_by) . "\n"; - } else { - say "$remove"; - } - - # Check for %README% value and inform user. - if ( $warnings{$remove} ) { - say "It is recommended that you view the README before continuing."; - if (prompt("Display README now?", default => 'yes')) { - my $readme = get_readme_contents(get_sbo_location($remove)); - if (not defined $readme) { - warn "Unable to open README for $remove.\n"; - } else { - print "\n" . $readme; - } - } - } - - # Determine default behavior for prompt using $needed - # Ask user to confirm removal - if (prompt("Remove $remove?", default => $needed ? 'no' : 'yes')) { - confirm_remove($remove); - say " * Added to remove queue\n"; - } else { - say " * Ignoring\n"; - } -} - -CONFIRMED: -# Show remove queue -my $remove_count = @confirmed; -if ($remove_count) { - say "Removing $remove_count package(s)"; - print join(' ', @confirmed) . "\n"; -} else { - say 'Nothing to remove.'; - exit 0; -} - -# Final confirmation -unless ($non_int) { - unless (prompt("\nAre you sure you want to continue?", default => 'no')) { - say 'Exiting.'; - exit 0; - } -} - -system("/sbin/removepkg", $_) for @confirmed; - -say "All operations have completed successfully."; - -exit 0; +exit $app->run(); @@ -13,49 +13,8 @@ use 5.16.0; use strict; use warnings FATAL => 'all'; -use SBO::Lib qw/ fetch_tree update_tree %config show_version /; -use File::Basename; -use Getopt::Long; +use SBO::App::Snap; -my $sbo_home = $config{SBO_HOME}; -my $self = basename($0); +my $app = SBO::App::Snap->new(@ARGV); -sub show_usage { - print <<"EOF"; -Usage: $self [options|command] - -Options: - -h|--help: - this screen. - -v|--version: - version information. - -Commands: - fetch: initialize a local copy of the slackbuilds.org tree. - update: update an existing local copy of the slackbuilds.org tree. - (generally, you may prefer "sbocheck" over "$self update") - -EOF - return 1; -} - -my ($help, $vers); - -GetOptions('help|h' => \$help, 'version|v' => \$vers); - -if ($help) { show_usage(); exit 0 } -if ($vers) { show_version(); exit 0 } - -# check for a command and, if found, execute it -$ARGV[0] //= ''; - -if ($ARGV[0] eq 'fetch') { - fetch_tree() -} elsif ($ARGV[0] eq 'update') { - update_tree() -} else { - show_usage(); - exit 1; -} - -exit 0; +exit $app->run(); diff --git a/slackbuild/sbotools/sbotools.SlackBuild b/slackbuild/sbotools/sbotools.SlackBuild index d151953..63102f7 100644 --- a/slackbuild/sbotools/sbotools.SlackBuild +++ b/slackbuild/sbotools/sbotools.SlackBuild @@ -5,7 +5,7 @@ # Licensed under the WTFPL <http://sam.zoy.org/wtfpl/COPYING> PRGNAM=sbotools -VERSION=${VERSION:-2.1} +VERSION=${VERSION:-2.5} BUILD=${BUILD:-1} TAG=${TAG:-_SBo} diff --git a/slackbuild/sbotools/sbotools.info b/slackbuild/sbotools/sbotools.info index 1b22f7c..4335de2 100644 --- a/slackbuild/sbotools/sbotools.info +++ b/slackbuild/sbotools/sbotools.info @@ -1,5 +1,5 @@ PRGNAM="sbotools" -VERSION="2.1" +VERSION="2.5" HOMEPAGE="http://pink-mist.github.io/sbotools/" DOWNLOAD="http://pink-mist.github.io/sbotools/downloads/@FILENAME@" MD5SUM="@MD5@" diff --git a/t/01-unit.t b/t/01-unit.t index 13d6e8e..f1aabb0 100755 --- a/t/01-unit.t +++ b/t/01-unit.t @@ -11,7 +11,7 @@ use Capture::Tiny qw/ capture_merged /; use File::Temp 'tempdir'; use Cwd; -plan tests => 60; +plan tests => 61; # 1-2: test script_error(); { @@ -196,12 +196,6 @@ SKIP: { is (SBO::Lib::generate_slackbuilds_txt(), 1, 'generate_slackbuilds_txt() returned 1'); system(qw! rm -r /usr/sbo/repo !) if -d '/usr/sbo/repo'; - - local $config{REPO} = ''; - capture_merged { SBO::Lib::pull_sbo_tree(); }; - ok (!-e '/usr/sbo/repo/SLACKBUILDS.TXT', 'SLACKBUILDS.TXT was not generated by pull_sbo_tree()'); - - system(qw! rm -r /usr/sbo/repo !) if -d '/usr/sbo/repo'; system(qw! mv /usr/sbo/backup /usr/sbo/repo !) if -d '/usr/sbo/backup'; my $sbohome = '/usr/sbo'; @@ -218,7 +212,7 @@ SKIP: { system('mv', "$sbohome.bak", $sbohome); } -# 38: test get_installed_packages(); +# 37: test get_installed_packages(); { system(qw!mv /var/log/packages /var/log/packages.backup!); system(qw!mkdir -p /var/log/packages!); @@ -228,7 +222,7 @@ SKIP: { system(qw!mv /var/log/packages.backup /var/log/packages!); } -# 39-41: test get_sbo_location() and get_sbo_locations(); +# 38-40: test get_sbo_location() and get_sbo_locations(); { my $exit; my $out = capture_merged { $exit = exit_code { get_sbo_location([]); }; }; @@ -245,18 +239,18 @@ SKIP: { } } -# 42: test get_local_outdated_versions(); +# 41: test get_local_outdated_versions(); { local $config{LOCAL_OVERRIDES} = 'FALSE'; is(scalar get_local_outdated_versions(), 0, 'get_local_outdated_versions() returned an empty list'); } -# 43: test get_filename_from_link(); +# 42: test get_filename_from_link(); { is (SBO::Lib::get_filename_from_link('/'), undef, "get_filename_from_link() returned undef"); } -# 44-47: test revert_slackbuild(); +# 43-46: test revert_slackbuild(); { my $tmp = tempdir(CLEANUP => 1); is (SBO::Lib::revert_slackbuild("$tmp/foo"), 1, "revert_slackbuild() returned 1"); @@ -267,7 +261,7 @@ SKIP: { ok (!-f "$tmp/foo.orig", 'foo.orig is no more'); } -# 48: test get_src_dir(); +# 47: test get_src_dir(); SKIP: { skip 'Test invalid if /foo-bar exists.', 1 if -e '/foo-bar'; my $scalar = ''; @@ -277,13 +271,13 @@ SKIP: { is (scalar @{ SBO::Lib::get_src_dir($fh) }, 0, "get_src_dir() returned an empty array ref"); } -# 49: test get_readme_contents(); +# 48: test get_readme_contents(); { my @ret = get_readme_contents(undef); is ($ret[0], undef, "get_readme_contents() returned undef"); } -# 50-51: test user_prompt(); +# 49-50: test user_prompt(); { my $exit; my $out = capture_merged { $exit = exit_code { user_prompt('foo', undef); }; }; @@ -292,7 +286,7 @@ SKIP: { is ($out, "Unable to locate foo in the SlackBuilds.org tree.\n", 'user_prompt() gave correct output'); } -# 52-54: test perform_sbo(); +# 51-53: test perform_sbo(); SKIP: { skip 'Tests invalid if /foo exists.', 3 if -e "/foo"; @@ -303,7 +297,7 @@ SKIP: { is ($res[2], 6, 'perform_sbo returned correct exit'); } -# 55-59: test version_cmp(); +# 54-60: test version_cmp(); { chomp(my $kv = `uname -r`); $kv =~ s/-/_/g; @@ -319,9 +313,12 @@ SKIP: { local *SBO::Lib::Util::get_kernel_version = sub { "foo_bar" }; is (SBO::Lib::version_cmp('1.0', '1.0_foo_bar'), 0, "version_cmp(1.0, 1.0_foo_bar) returned 0"); + + is (SBO::Lib::version_cmp('1.0_en_US', '1.0'), 0, "version_cmp(1.0_en_US, 1.0) returned 0"); + is (SBO::Lib::version_cmp('1.0', '1.0_en_US'), 0, "version_cmp(1.0, 1.0_en_US) returned 0"); } -# 60: test check_multilib(); +# 61: test check_multilib(); { my $file = "/etc/profile.d/32dev.sh"; diff --git a/t/03-travis.t b/t/03-travis.t index d5bd2d1..4b77313 100755 --- a/t/03-travis.t +++ b/t/03-travis.t @@ -26,7 +26,7 @@ SKIP: { skip 'Not doing online tests without TEST_ONLINE=1', 2 if $ENV{TEST_ONLINE} ne '1'; sbosnap 'fetch', { expected => qr/\APulling SlackBuilds tree\.\.\.\n/ }; - sbofind 'sbotools', { expected => "SBo: sbotools\nPath: /usr/sbo/repo/system/sbotools\n\n" }; + sbofind 'sbotools', { expected => "SBo: sbotools 1.9\nPath: /usr/sbo/repo/system/sbotools\n\n" }; } # 4-10: Test alternative REPO @@ -39,7 +39,7 @@ SKIP: { sbosnap 'fetch', { expected => qr!Pulling SlackBuilds tree.*Cloning into '/usr/sbo/repo'!s }; ok (-e "/usr/sbo/repo/SLACKBUILDS.TXT", "SLACKBUILDS.TXT exists (REPO)"); ok (! -e "/usr/sbo/repo/SLACKBUILDS.TXT.gz", "SLACKBUILDS.TXT.gz doesn't exist (REPO)"); - sbofind 'sbotools', { expected => "SBo: sbotools\nPath: /usr/sbo/repo/system/sbotools\n\n" }; + sbofind 'sbotools', { expected => qr"SBo: sbotools .*\nPath: /usr/sbo/repo/system/sbotools\n\n" }; } # 11-17: Test local overrides @@ -50,30 +50,30 @@ SKIP: { skip "Online testing disabled (TEST_ONLINE!=1) and could not create dummy SLACKBUILDS.TXT", 9 if $skip; sbofind 'nonexistentslackbuild', { expected => sub { -m!\QLocal: nonexistentslackbuild6 +m!\QLocal: nonexistentslackbuild6 1.0 Path: $RealBin/LO/nonexistentslackbuild6! and -m!\QLocal: nonexistentslackbuild5 +m!\QLocal: nonexistentslackbuild5 1.0 Path: $RealBin/LO/nonexistentslackbuild5! and -m!\QLocal: nonexistentslackbuild4 +m!\QLocal: nonexistentslackbuild4 1.0 Path: $RealBin/LO/nonexistentslackbuild4! and -m!\QLocal: nonexistentslackbuild2 +m!\QLocal: nonexistentslackbuild2 1.0 Path: $RealBin/LO/nonexistentslackbuild2! and -m!\QLocal: nonexistentslackbuild7 +m!\QLocal: nonexistentslackbuild7 1.0 Path: $RealBin/LO/nonexistentslackbuild7! and -m!\QLocal: nonexistentslackbuild +m!\QLocal: nonexistentslackbuild 1.0 Path: $RealBin/LO/nonexistentslackbuild! and -m!\QLocal: nonexistentslackbuild8 +m!\QLocal: nonexistentslackbuild8 1.0 Path: $RealBin/LO/nonexistentslackbuild8! } }; sboinstall qw/ -r nonexistentslackbuild /, - { expected => qr/nonexistentslackbuild added to install queue[.].*perf[.]dummy' saved.*Cleaning for nonexistentslackbuild-1[.]0/s }; + { expected => qr/nonexistentslackbuild added to install queue[.].*perf[.]dummy.* saved.*Cleaning for nonexistentslackbuild-1[.]0/s }; sboremove qw/ --nointeractive nonexistentslackbuild /, { expected => qr/Removing 1 package\(s\).*nonexistentslackbuild.*All operations have completed/s }; is (system(qw!/sbin/installpkg nonexistentslackbuild-0.9-noarch-1_SBo.tgz!), 0, 'Old version fake installed'); sbocheck { expected => qr/Updating SlackBuilds tree.*Checking for updated SlackBuilds.*nonexistentslackbuild 0[.]9.*needs updating/s }; diff --git a/t/04-install.t b/t/04-install.t index ea7b07c..f1f922f 100755 --- a/t/04-install.t +++ b/t/04-install.t @@ -10,7 +10,7 @@ use lib $RealBin; use Test::Sbotools qw/ make_slackbuilds_txt set_lo sboinstall sboremove restore_perf_dummy /; if ($ENV{TEST_INSTALL}) { - plan tests => 20; + plan tests => 22; } else { plan skip_all => 'Only run these tests if TEST_INSTALL=1'; } @@ -112,6 +112,10 @@ sboinstall 'perl-nonexistentcpan', { input => "n", expected => qr/Proceed with p sboinstall '-p', 'foo', { expected => "compat32 only works on x86_64.\n", exit => 1 }; } +# 21-22: check --reinstall option +sboinstall '--reinstall', 'nonexistentslackbuild', { input => "n", expected => qr/\Qnonexistentslackbuild (nonexistentslackbuild-1.0-noarch-1_SBo) is already installed. Do you want to reinstall from SBo? [n]\E/ }; +sboinstall '--reinstall', 'nonexistentslackbuild', { input => "y\ny\ny", expected => qr/nonexistentslackbuild .* is already installed[.] Do you want to reinstall.*Install queue: nonexistentslackbuild/s }; + # Cleanup END { cleanup(); diff --git a/t/05-upgrade.t b/t/05-upgrade.t index b7e1e29..44037c6 100755 --- a/t/05-upgrade.t +++ b/t/05-upgrade.t @@ -11,7 +11,7 @@ use Test::Sbotools qw/ make_slackbuilds_txt set_lo sboconfig sboinstall sboupgra use File::Temp 'tempdir'; if ($ENV{TEST_INSTALL}) { - plan tests => 20; + plan tests => 21; } else { plan skip_all => 'Only run these tests if TEST_INSTALL=1'; } @@ -25,12 +25,14 @@ sub cleanup { system(qw!/sbin/removepkg nonexistentslackbuild5!); system(qw!/sbin/removepkg nonexistentslackbuild6!); system(qw!/sbin/removepkg weird-versionsbo!); + system(qw!/sbin/removepkg locale-versionsbo!); unlink "$RealBin/LO/nonexistentslackbuild/perf.dummy"; unlink "$RealBin/LO/nonexistentslackbuild2/perf.dummy"; unlink "$RealBin/LO/nonexistentslackbuild4/perf.dummy"; unlink "$RealBin/LO/nonexistentslackbuild5/perf.dummy"; unlink "$RealBin/LO/nonexistentslackbuild6/perf.dummy"; unlink "$RealBin/LO/weird-versionsbo/perf.dummy"; + unlink "$RealBin/LO/locale-versionsbo/perf.dummy"; unlink "$RealBin/LO2/nonexistentslackbuild/perf.dummy"; unlink "$RealBin/LO2/nonexistentslackbuild2/perf.dummy"; unlink "$RealBin/LO2/nonexistentslackbuild4/perf.dummy"; @@ -50,6 +52,7 @@ sub cleanup { system(qw!rm -rf /tmp/SBo/nonexistentslackbuild5-1.0!); system(qw!rm -rf /tmp/SBo/nonexistentslackbuild6-1.0!); system(qw!rm -rf /tmp/SBo/weird-versionsbo-1.0!); + system(qw!rm -rf /tmp/SBo/locale-versionsbo-1.0!); system(qw!rm -rf /tmp/SBo/nonexistentslackbuild-1.1!); system(qw!rm -rf /tmp/SBo/nonexistentslackbuild2-1.1!); system(qw!rm -rf /tmp/SBo/nonexistentslackbuild4-1.1!); @@ -61,6 +64,7 @@ sub cleanup { system(qw!rm -rf /tmp/package-nonexistentslackbuild5!); system(qw!rm -rf /tmp/package-nonexistentslackbuild6!); system(qw!rm -rf /tmp/package-weird-versionsbo!); + system(qw!rm -rf /tmp/package-locale-versionsbo!); }; } @@ -112,13 +116,13 @@ sboupgrade 'nonexistentslackbuild4', { input => "y\ny", expected => qr/Proceed w install( 'LO3', 'nonexistentslackbuild5', 'nonexistentslackbuild4' ); sboupgrade qw/ -f nonexistentslackbuild4 /, { input => "y\ny\ny", expected => qr/Proceed with nonexistentslackbuild5\b.*Proceed with nonexistentslackbuild4\b.*Upgrade queue: nonexistentslackbuild5 nonexistentslackbuild4\n/s }; -# 13-15: sboupgrade --all +# 13-16: sbosnap + sboupgrade --all my $temp = tempdir(CLEANUP => 1); set_repo("file://$temp"); capture_merged { system <<"END"; }; cd $temp; git init; END -sbosnap 'fetch', { test => 0 }; +sbosnap 'fetch', { expected => qr/Pulling SlackBuilds tree[.][.][.]/ }; install( 'LO2', 'nonexistentslackbuild' ); my @sbos = glob("/var/log/packages/*_SBo"); sboupgrade '--all', { input => ("n\n" x (@sbos+1)), expected => qr/Proceed with nonexistentslackbuild\b/ }; @@ -129,19 +133,19 @@ sboupgrade '--all', { expected => "Checking for updated SlackBuilds...\nNothing cleanup(); -# 16: sboupgrade --all shouldn't pick up weird-versionsbo -install('LO', 'weird-versionsbo'); -sboupgrade '--all', { input => ("n\n" x (@sbos+1)), expected => sub { not /weird-versionsbo/ } }; +# 17: sboupgrade --all shouldn't pick up weird-versionsbo or locale-versionsbo +install('LO', 'weird-versionsbo', 'locale-versionsbo'); +sboupgrade '--all', { input => ("n\n" x (@sbos+1)), expected => sub { not /weird-versionsbo/ and not /locale-versionsbo/ } }; -# 17-18: sboupgrade -r -f both something installed and something not installed +# 18-19: sboupgrade -r -f both something installed and something not installed install('LO', 'nonexistentslackbuild'); sboupgrade qw/ -r -f nonexistentslackbuild /, { expected => qr/^Upgrade queue: nonexistentslackbuild$/m }; sboupgrade qw/ -r -f nonexistentslackbuild2 /, { expected => "" }; -# 19: sboupgrade -r on something already up to date +# 20: sboupgrade -r on something already up to date sboupgrade qw/ -r nonexistentslackbuild /, { expected => "" }; -# 20: sboupgrade and answer weirdly and use a default and then answer no twice +# 21: sboupgrade and answer weirdly and use a default and then answer no twice install('LO2', 'nonexistentslackbuild', 'nonexistentslackbuild5'); sboupgrade qw/nonexistentslackbuild nonexistentslackbuild5/, { input => "foo\n\nn\nn\n", expected => qr/Proceed with nonexistentslackbuild\?.*Proceed with nonexistentslackbuild\?.*Proceed with nonexistentslackbuild5\?.*Upgrade queue: nonexistentslackbuild$/sm }; diff --git a/t/07-fail.t b/t/07-fail.t index a7d2a45..6798446 100755 --- a/t/07-fail.t +++ b/t/07-fail.t @@ -126,7 +126,7 @@ sboinstall 'malformed-noinfo', { expected => "get_from_info: could not read $Rea # 11-13: Malformed slackbuild - malformed .info sboinstall 'malformed-info', { input => "y\ny\nn", expected => qr!Failures:\n malformed-info: Unable to get download info from $RealBin/LO-fail/malformed-info/malformed-info[.]info\n!, exit => 7 }; sboinstall 'malformed-info2', { input => "y\ny\nn", expected => qr!Failures:\n malformed-info2: Unable to get download info from $RealBin/LO-fail/malformed-info2/malformed-info2[.]info\n!, exit => 7 }; -sboinstall 'malformed-info3', { exit => 2, expected => "A fatal script error has occurred:\nerror when parsing malformed-info3.info file. Line: FAIL\nExiting.\n" }; +sboinstall 'malformed-info3', { exit => 2, expected => "A fatal script error has occurred:\nerror when parsing malformed-info3.info file.\nExiting.\n" }; # 14-15: Malformed slackbuild - no readme sboinstall 'malformed-readme', { expected => "Unable to open README for malformed-readme.\n", exit => 6 }; diff --git a/t/09-multilib.t b/t/09-multilib.t index 470b0a9..22306c0 100755 --- a/t/09-multilib.t +++ b/t/09-multilib.t @@ -7,12 +7,12 @@ use Test::More; use Capture::Tiny qw/ capture_merged /; use FindBin '$RealBin'; use lib $RealBin; -use Test::Sbotools qw/ make_slackbuilds_txt set_lo sboinstall sboclean restore_perf_dummy /; +use Test::Sbotools qw/ make_slackbuilds_txt set_lo sboinstall sboclean sboremove restore_perf_dummy /; use File::Temp 'tempdir'; $ENV{TEST_MULTILIB} //= 0; if ($ENV{TEST_INSTALL} and ($ENV{TEST_MULTILIB} == 2)) { - plan tests => 10; + plan tests => 11; } else { plan skip_all => 'Only run these tests if TEST_INSTALL=1 and TEST_MULTILIB=2'; } @@ -77,6 +77,10 @@ sboinstall qw/ -p multilibsbo /, { input => "n", expected => qr/Proceed with mul # 10: multilibsbo with command in readme sboinstall qw/ -p multilibsbowithcommandinreadme /, { input => "y\ny\nn\nn\nn", expected => qr/It looks like.*Shall I run.*Proceed.*It looks like.*Shall I run.*Proceed.*Are you sure/s }; +# 11: sboremove multilibsbo +sboinstall qw/ -p multilibsbo /, { input => "y\ny\ny", test => 0 }; +sboremove qw/ multilibsbo /, { input => "y\ny\ny", expected => qr/Remove multilibsbo\b.*Removing 1 package\(s\)/s }; + # Cleanup END { cleanup(); @@ -10,14 +10,18 @@ use lib $RealBin; use Test::Sbotools qw/ set_repo sbosnap /; if ($ENV{TEST_INSTALL}) { - plan tests => 3; + plan tests => 5; } else { plan skip_all => 'Only run these tests if TEST_INSTALL=1'; } sub cleanup { capture_merged { - system(qw!rm -rf !, "$RealBin/gitrepo"); + system(qw!rm -rf !, "$RealBin/gitrepo"); + if (defined $ENV{TRAVIS} and $ENV{TRAVIS} eq 'true') { + system(qw!userdel test!); + system(qw!groupdel test!); + } }; } @@ -40,20 +44,39 @@ git checkout -b b1; echo 'echo "Hello World."' > test; git commit -am 'branch co git checkout master; echo 'echo "Hello World"' > test; git commit -am 'master commit'; END -set_repo("file://$RealBin/gitrepo/"); +if (defined $ENV{TRAVIS} and $ENV{TRAVIS} eq 'true') { +capture_merged { system(<<"END"); }; +groupadd -g 199 test +useradd -u 199 -g 199 -d /tmp test +chown -R 199:199 $RealBin/gitrepo +END +} + +set_repo("$RealBin/gitrepo/"); # 1: sbosnap get initial repo sbosnap 'fetch', { expected => qr!Pulling SlackBuilds tree.*Cloning into '/usr/sbo/repo'!s }; +# 2-3: check ownership of repodir if under TRAVIS +SKIP: { + skip "Only run under Travis CI", 2 unless defined $ENV{TRAVIS} and $ENV{TRAVIS} eq 'true'; + + my @fnames = glob "$RealBin/gitrepo/.git/objects/*/*"; + + my @stat = stat shift @fnames; + is ($stat[4], 199, "Correct owner uid for $RealBin/gitrepo"); + is ($stat[5], 199, "Correct owner gid for $RealBin/gitrepo"); +} + # make a conflict capture_merged { system(<<"END"); }; cd "$RealBin"; cd gitrepo; git reset --hard b1 END -# 2: sbosnap update through merge conflict +# 4: sbosnap update through merge conflict sbosnap 'update', { expected => qr!Updating SlackBuilds tree.*master.*->.*origin/master.*forced update.*HEAD is now at!s }; -# 3: make sure test repo is merged correctly +# 5: make sure test repo is merged correctly is (slurp('/usr/sbo/repo/test'), <<"END", 'repo test file updated correctly'); echo "Hello World." END diff --git a/t/12-readme.t b/t/12-readme.t index ff69ac2..d95c7cf 100755 --- a/t/12-readme.t +++ b/t/12-readme.t @@ -10,7 +10,7 @@ use lib $RealBin; use Test::Sbotools qw/ make_slackbuilds_txt set_lo sboinstall sboremove restore_perf_dummy /; if ($ENV{TEST_INSTALL}) { - plan tests => 10; + plan tests => 11; } else { plan skip_all => 'Only run these tests if TEST_INSTALL=1'; } @@ -19,12 +19,16 @@ sub cleanup { capture_merged { system(qw!/sbin/removepkg envsettingtest!); system(qw!/sbin/removepkg envsettingtest2!); + system(qw!/sbin/removepkg otherreadmes!); unlink "$RealBin/LO-readme/envsettingtest/perf.dummy"; unlink "$RealBin/LO-readme/envsettingtest2/perf.dummy"; + unlink "$RealBin/LO-readme/otherreadmes/perf.dummy"; system(qw!rm -rf /tmp/SBo/envsettingtest-1.0!); system(qw!rm -rf /tmp/SBo/envsettingtest2-1.0!); + system(qw!rm -rf /tmp/SBo/otherreadmes-1.0!); system(qw!rm -rf /tmp/package-envsettingtest!); system(qw!rm -rf /tmp/package-envsettingtest2!); + system(qw!rm -rf /tmp/package-otherreadmes!); }; } @@ -62,7 +66,7 @@ SKIP: { skip "Only run useradd/groupadd commands under Travis CI", 2 unless (defined $ENV{TRAVIS} and $ENV{TRAVIS} eq 'true'); skip "Only run useradd/groupadd commands if there is no test user/group", 2, if (defined getgrnam('test') or defined getpwnam('test')); - sboinstall 'commandinreadme', { input => "y\ny\ny", expected => qr{It looks like this slackbuild requires the following command\(s\) to be run first:.*groupadd -g 200 test.*useradd -u 200 -g 200 -d /tmp test.*Shall I run them prior to building.*}s }; + sboinstall 'commandinreadme', { input => "y\ny\ny", expected => qr{It looks like this slackbuild requires the following command\(s\) to be run first:.*groupadd -g 199 test.*useradd -u 199 -g 199 -d /tmp test.*Shall I run them prior to building.*}s }; sboremove 'commandinreadme', { input => "y\ny", test => 0 }; sboinstall 'commandinreadme', { input => "y\ny\ny", expected => qr/groupadd.*exited non-zero/ }; @@ -70,6 +74,9 @@ SKIP: { capture_merged { system(qw/ userdel test /); system(qw/ groupdel test /); }; } +# 11: sboinstall otherreadmes +sboinstall 'otherreadmes', { input => "y\ny\ny", expected => qr/It looks like.*Would you like to see.*README.*SlackBuilds[.]org.*SLACKWARE/s }; + # Cleanup END { cleanup(); diff --git a/t/15-usage.t b/t/15-usage.t index 4a9b61c..f14ef84 100755 --- a/t/15-usage.t +++ b/t/15-usage.t @@ -50,9 +50,12 @@ my $sboconfig = <<'SBOCONFIG'; Usage: sboconfig [options] [arguments] Options: - -h: this screen. - -v: version information. - -l: show current options. + -h|--help: + this screen. + -v|--version: + version information. + -l|--list: + show current options. Config options (defaults shown): -c|--clean FALSE: @@ -127,6 +130,8 @@ Options (defaults shown first where applicable): non-interactive; skips README and all prompts. -R|--norequirements: view the README but do not parse requirements, commands, or options. + --reinstall: + Ask to reinstall any already-installed packages in the requirement list. --create-template (FILE): create a template with specified requirements, commands, and options. --use-template (FILE): diff --git a/t/17-find.t b/t/17-find.t index 5ea3e74..2be2a56 100755 --- a/t/17-find.t +++ b/t/17-find.t @@ -16,14 +16,14 @@ make_slackbuilds_txt(); set_lo("$RealBin/LO"); # 1: basic sbofind testing -sbofind 'nonexistentslackbuild4', { expected => qr!Local:\s+nonexistentslackbuild4\nPath:\s+\Q$RealBin/LO/nonexistentslackbuild4! }; +sbofind 'nonexistentslackbuild4', { expected => qr!Local:\s+nonexistentslackbuild4 .*\nPath:\s+\Q$RealBin/LO/nonexistentslackbuild4! }; # 2: basic sbofind testing - nothing found sbofind 'nonexistentslackbuild3', { expected => "Nothing found for search term: nonexistentslackbuild3\n" }; # 3: find something using a tag replace_tags_txt("nonexistentslackbuild2: testingtag\n"); -sbofind 'testingtag', { expected => qr!Local:\s+nonexistentslackbuild2\nPath:\s+\Q$RealBin/LO/nonexistentslackbuild2! }; +sbofind 'testingtag', { expected => qr!Local:\s+nonexistentslackbuild2 .*\nPath:\s+\Q$RealBin/LO/nonexistentslackbuild2! }; # 4: show build queue sbofind '-q', 'nonexistentslackbuild2', { expected => qr/Queue:\s+nonexistentslackbuild3 nonexistentslackbuild2/ }; diff --git a/t/28-race-sboremove.t b/t/28-race-sboremove.t index ebc707f..3c7e026 100755 --- a/t/28-race-sboremove.t +++ b/t/28-race-sboremove.t @@ -52,4 +52,4 @@ tie *STDIN, 'STDINTIE'; my $res = load('sboremove', argv => ['nonexistentslackbuild8']); like ($res->{out}, qr/Unable to open README for nonexistentslackbuild8\./, 'sboremove output with race condition correct'); -is ($res->{exit}, 0, 'sboremove exited with 0'); +is ($res->{exit}, 0, 'sboremove did not exit in error'); diff --git a/t/29-unit-sboremove.t b/t/29-unit-sboremove.t deleted file mode 100755 index a968dc7..0000000 --- a/t/29-unit-sboremove.t +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env perl - -use strict; -use warnings; -use Test::More; -use Test::Exit; -use FindBin '$RealBin'; -use lib $RealBin; -use Test::Sbotools qw/ load /; -use Capture::Tiny qw/ capture_merged /; -use File::Temp 'tempdir'; -use Cwd; - -plan tests => 1; - -# 1: sboremove unit test... -{ - load('sboremove'); - - no warnings 'redefine', 'once'; - - my $sentinel = 0; - local *main::in = sub { - my $find = shift; - my @ret = grep { $find eq $_ } @_; - $sentinel++ if @ret; - return 1 if @ret; - return 0; - }; - - main::confirm_remove('foo'); - main::confirm_remove('foo'); - - is ($sentinel, 1, "confirm_remove() checks for duplicates."); -} diff --git a/t/31-template.t b/t/31-template.t index 982c08f..250e2f6 100755 --- a/t/31-template.t +++ b/t/31-template.t @@ -11,7 +11,7 @@ use Test::Sbotools qw/ make_slackbuilds_txt set_lo sboinstall sboremove restore_ use File::Temp qw/ tempdir /; if ($ENV{TEST_INSTALL}) { - plan tests => 26; + plan tests => 29; } else { plan skip_all => 'Only run these tests if TEST_INSTALL=1'; } @@ -20,12 +20,20 @@ sub cleanup { capture_merged { system(qw!/sbin/removepkg envsettingtest!); system(qw!/sbin/removepkg envsettingtest2!); + system(qw!/sbin/removepkg commandinreadme!); + system(qw!/sbin/removepkg commandinreadmespanslines!); unlink "$RealBin/LO-readme/envsettingtest/perf.dummy"; unlink "$RealBin/LO-readme/envsettingtest2/perf.dummy"; + unlink "$RealBin/LO-readme/commandinreadme/perf.dummy"; + unlink "$RealBin/LO-readme/commandinreadmespanslines/perf.dummy"; system(qw!rm -rf /tmp/SBo/envsettingtest-1.0!); system(qw!rm -rf /tmp/SBo/envsettingtest2-1.0!); + system(qw!rm -rf /tmp/SBo/commandinreadme-1.0!); + system(qw!rm -rf /tmp/SBo/commandinreadmespanslines-1.0!); system(qw!rm -rf /tmp/package-envsettingtest!); system(qw!rm -rf /tmp/package-envsettingtest2!); + system(qw!rm -rf /tmp/package-commandinreadme!); + system(qw!rm -rf /tmp/package-commandinreadmespanslines!); }; } @@ -143,8 +151,8 @@ SKIP: { ], "commands" : { "commandinreadme" : [ - "groupadd -g 200 test", - "useradd -u 200 -g 200 -d /tmp test" + "groupadd -g 199 test", + "useradd -u 199 -g 199 -d /tmp test" ] }, "options" : { @@ -173,6 +181,35 @@ sboinstall '--use-template', '', { expected => qr/Usage/, exit => 1 }; sboinstall '--use-template', '', '', { expected => qr/Usage/, exit => 1 }; sboinstall '--create-template', '', '', { expected => qr/Usage/, exit => 1 }; +# 27-29: sboinstall commandinreadmespanslines +SKIP: { + skip "Only run useradd/groupadd commands under Travis CI", 3 unless (defined $ENV{TRAVIS} and $ENV{TRAVIS} eq 'true'); + skip "Only run useradd/groupadd commands if there is no test user/group", 3 if (defined getgrnam('test') or defined getpwnam('test')); + + sboinstall '-i', '--create-template', "$tempdir/10.temp", 'commandinreadmespanslines', { input => "y\ny\ny", expected => qr!Template \Q$tempdir/10.temp saved.\E\n! }; + capture_merged { system(qw/ userdel test /); system(qw/ groupdel test /); }; + is (scalar capture_merged { system cat => "$tempdir/10.temp" }, <<'TEMP10', "10.temp is correct"); +{ + "build_queue" : [ + "commandinreadmespanslines" + ], + "commands" : { + "commandinreadmespanslines" : [ + "groupadd -g 199 test", + "useradd -u 199 -g 199 -d /tmp \\\n -s /bin/sh test" + ] + }, + "options" : { + "commandinreadmespanslines" : 0 + } +} +TEMP10 + sboinstall '--use-template', "$tempdir/10.temp", { expected => sub { ! m/exited non-zero/ } }; + sboremove 'commandinreadmespanslines', { input => "y\ny", test => 0 }; + + capture_merged { system(qw/ userdel test /); system(qw/ groupdel test /); }; +} + # Cleanup END { cleanup(); diff --git a/t/32-info.t b/t/32-info.t new file mode 100644 index 0000000..0f5e4bd --- /dev/null +++ b/t/32-info.t @@ -0,0 +1,55 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Test::More; + +use FindBin '$RealBin'; +use lib "$RealBin/../SBO-Lib/lib"; +use SBO::Lib 'parse_info'; + +plan tests => 23; + +my %parse = parse_info(<<"END"); +FOO="bar" +BAR="foo bar +baz" +BAZ="barf foof + bazf" +QUUX="finf" +FLAR_f="trailing whitespace" +FLINGLE="\ +glorg \ +glorg \ +and\ +a\ + gloob\ +blorx\ +" +END + +is ($parse{FOO}[0], 'bar', 'bar value gotten from FOO key'); +is ($parse{FOO}[1], undef, 'FOO key has correct length'); +is ($parse{BAR}[0], 'foo', 'foo value gotten from BAR key'); +is ($parse{BAR}[1], 'bar', 'bar value gotten from BAR key'); +is ($parse{BAR}[2], 'baz', 'baz value gotten from BAR key'); +is ($parse{BAR}[3], undef, 'BAR key has correct length'); +is ($parse{BAZ}[0], 'barf', 'barf value gotten from BAZ key'); +is ($parse{BAZ}[1], 'foof', 'foof value gotten from BAZ key'); +is ($parse{BAZ}[2], 'bazf', 'bazf value gotten from BAZ key'); +is ($parse{BAZ}[3], undef, 'BAZ key has correct length'); +is ($parse{QUUX}[0], 'finf', 'finf value gotten from QUUX key'); +is ($parse{QUUX}[1], undef, 'QUUX key has correct length'); +is ($parse{FLAR_f}[0], 'trailing', 'trailing value gotten from FLAR_f key'); +is ($parse{FLAR_f}[1], 'whitespace', 'whitespace value gotten from FLAR_f key'); +is ($parse{FLAR_f}[2], undef, 'FLAR_f key has correct length'); +is ($parse{FLINGLE}[0], 'glorg', 'glorg value gotten from FLINGLE key'); +is ($parse{FLINGLE}[1], 'glorg', 'glorg value gotten from FLINGLE key'); +is ($parse{FLINGLE}[2], 'and', 'and value gotten from FLINGLE key'); +is ($parse{FLINGLE}[3], 'a', 'a value gotten from FLINGLE key'); +is ($parse{FLINGLE}[4], 'gloob', 'gloob value gotten from FLINGLE key'); +is ($parse{FLINGLE}[5], 'blorx', 'blorx value gotten from FLINGLE key'); +is ($parse{FLINGLE}[6], undef, 'FLINGLE key has correct length'); +delete @parse{qw/ FOO BAR BAZ QUUX FLAR_f FLINGLE /}; +is (scalar %parse, 0, 'no additional keys were parsed'); diff --git a/t/LO-multilib/multilibsbowithcommandinreadme/README b/t/LO-multilib/multilibsbowithcommandinreadme/README index 6e51784..db5d140 100644 --- a/t/LO-multilib/multilibsbowithcommandinreadme/README +++ b/t/LO-multilib/multilibsbowithcommandinreadme/README @@ -1,4 +1,4 @@ This doesn't exist! - groupadd -g 200 test - useradd -u 200 -g 200 -d /tmp test + groupadd -g 199 test + useradd -u 199 -g 199 -d /tmp test diff --git a/t/LO-readme/commandinreadme/README b/t/LO-readme/commandinreadme/README index 6e51784..db5d140 100644 --- a/t/LO-readme/commandinreadme/README +++ b/t/LO-readme/commandinreadme/README @@ -1,4 +1,4 @@ This doesn't exist! - groupadd -g 200 test - useradd -u 200 -g 200 -d /tmp test + groupadd -g 199 test + useradd -u 199 -g 199 -d /tmp test diff --git a/t/LO-readme/commandinreadmespanslines/README b/t/LO-readme/commandinreadmespanslines/README new file mode 100644 index 0000000..696c2fe --- /dev/null +++ b/t/LO-readme/commandinreadmespanslines/README @@ -0,0 +1,5 @@ +This doesn't exist! + + groupadd -g 199 test + useradd -u 199 -g 199 -d /tmp \ + -s /bin/sh test diff --git a/t/LO-readme/commandinreadmespanslines/commandinreadmespanslines.SlackBuild b/t/LO-readme/commandinreadmespanslines/commandinreadmespanslines.SlackBuild new file mode 100644 index 0000000..0ff4195 --- /dev/null +++ b/t/LO-readme/commandinreadmespanslines/commandinreadmespanslines.SlackBuild @@ -0,0 +1,20 @@ +#!/bin/bash +PRGNAM="commandinreadmespanslines" +VERSION=${VERSION:-1.0} +BUILD=${BUILD:-1} +TAG=${TAG:-_SBo} +TMP=${TMP:-/tmp/SBo} +OUTPUT=${OUTPUT:-/tmp} + +if ! getent passwd "test"; then + echo "test user doesn't exist!" + exit 1 +fi + +mkdir -p $TMP/$PRGNAM-$VERSION +cp README $TMP/$PRGNAM-$VERSION +mkdir -p $OUTPUT/package-$PRGNAM/usr/doc/$PRGNAM-$VERSION +cp README $OUTPUT/package-$PRGNAM/usr/doc/$PRGNAM-$VERSION +cd $OUTPUT/package-$PRGNAM + +/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-noarch-$BUILD$TAG.tgz diff --git a/t/LO-readme/commandinreadmespanslines/commandinreadmespanslines.info b/t/LO-readme/commandinreadmespanslines/commandinreadmespanslines.info new file mode 100644 index 0000000..e6f71b6 --- /dev/null +++ b/t/LO-readme/commandinreadmespanslines/commandinreadmespanslines.info @@ -0,0 +1,10 @@ +PRGNAM="commandinreadmespanslines" +VERSION="1.0" +HOMEPAGE="http://www.example.com" +DOWNLOAD="http://pink-mist.github.io/sbotools/testing/perf.dummy" +MD5SUM="9cba6c70fb57a22a155073d54748b614" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +REQUIRES="" +MAINTAINER="Andreas Guldstrand" +EMAIL="doesnt@matter.org" diff --git a/t/LO-readme/otherreadmes/README b/t/LO-readme/otherreadmes/README new file mode 100644 index 0000000..6d388bb --- /dev/null +++ b/t/LO-readme/otherreadmes/README @@ -0,0 +1 @@ +This doesn't exist! diff --git a/t/LO-readme/otherreadmes/README.SBo b/t/LO-readme/otherreadmes/README.SBo new file mode 100644 index 0000000..7ff669b --- /dev/null +++ b/t/LO-readme/otherreadmes/README.SBo @@ -0,0 +1 @@ +this is the README for SlackBuilds.org diff --git a/t/LO-readme/otherreadmes/README.SLACKWARE b/t/LO-readme/otherreadmes/README.SLACKWARE new file mode 100644 index 0000000..9539839 --- /dev/null +++ b/t/LO-readme/otherreadmes/README.SLACKWARE @@ -0,0 +1 @@ +this is the README for SLACKWARE! diff --git a/t/LO-readme/otherreadmes/otherreadmes.SlackBuild b/t/LO-readme/otherreadmes/otherreadmes.SlackBuild new file mode 100644 index 0000000..4466ded --- /dev/null +++ b/t/LO-readme/otherreadmes/otherreadmes.SlackBuild @@ -0,0 +1,15 @@ +#!/bin/bash +PRGNAM="otherreadmes" +VERSION=${VERSION:-1.0} +BUILD=${BUILD:-1} +TAG=${TAG:-_SBo} +TMP=${TMP:-/tmp/SBo} +OUTPUT=${OUTPUT:-/tmp} + +mkdir -p $TMP/$PRGNAM-$VERSION +cp README $TMP/$PRGNAM-$VERSION +mkdir -p $OUTPUT/package-$PRGNAM/usr/doc/$PRGNAM-$VERSION +cp README $OUTPUT/package-$PRGNAM/usr/doc/$PRGNAM-$VERSION +cd $OUTPUT/package-$PRGNAM + +/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-noarch-$BUILD$TAG.tgz diff --git a/t/LO-readme/otherreadmes/otherreadmes.info b/t/LO-readme/otherreadmes/otherreadmes.info new file mode 100644 index 0000000..3dcaf67 --- /dev/null +++ b/t/LO-readme/otherreadmes/otherreadmes.info @@ -0,0 +1,10 @@ +PRGNAM="otherreadmes" +VERSION="1.0" +HOMEPAGE="http://www.example.com" +DOWNLOAD="http://pink-mist.github.io/sbotools/testing/perf.dummy" +MD5SUM="9cba6c70fb57a22a155073d54748b614" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +REQUIRES="" +MAINTAINER="Andreas Guldstrand" +EMAIL="doesnt@matter.org" diff --git a/t/LO/locale-versionsbo/README b/t/LO/locale-versionsbo/README new file mode 100644 index 0000000..6d388bb --- /dev/null +++ b/t/LO/locale-versionsbo/README @@ -0,0 +1 @@ +This doesn't exist! diff --git a/t/LO/locale-versionsbo/locale-versionsbo.SlackBuild b/t/LO/locale-versionsbo/locale-versionsbo.SlackBuild new file mode 100644 index 0000000..f146a92 --- /dev/null +++ b/t/LO/locale-versionsbo/locale-versionsbo.SlackBuild @@ -0,0 +1,16 @@ +#!/bin/bash +PRGNAM="locale-versionsbo" +VERSION=${VERSION:-1.0} +BUILD=${BUILD:-1} +TAG=${TAG:-_SBo} +TMP=${TMP:-/tmp/SBo} +OUTPUT=${OUTPUT:-/tmp} +KERNEL=$(uname -r) + +mkdir -p $TMP/$PRGNAM-$VERSION +cp README $TMP/$PRGNAM-$VERSION +mkdir -p $OUTPUT/package-$PRGNAM/usr/doc/$PRGNAM-$VERSION +cp README $OUTPUT/package-$PRGNAM/usr/doc/$PRGNAM-$VERSION +cd $OUTPUT/package-$PRGNAM + +/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION\_en_US-noarch-$BUILD$TAG.tgz diff --git a/t/LO/locale-versionsbo/locale-versionsbo.info b/t/LO/locale-versionsbo/locale-versionsbo.info new file mode 100644 index 0000000..787a2ef --- /dev/null +++ b/t/LO/locale-versionsbo/locale-versionsbo.info @@ -0,0 +1,10 @@ +PRGNAM="locale-versionsbo" +VERSION="1.0" +HOMEPAGE="http://www.example.com" +DOWNLOAD="http://pink-mist.github.io/sbotools/testing/perf.dummy" +MD5SUM="9cba6c70fb57a22a155073d54748b614" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +REQUIRES="" +MAINTAINER="Andreas Guldstrand" +EMAIL="doesnt@matter.org" diff --git a/tools/htmlgen.sh b/tools/htmlgen.sh index b623928..3953490 100755 --- a/tools/htmlgen.sh +++ b/tools/htmlgen.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -if [[ "$1" == "" ]]; then +if [ "$1" == "" -o "$1" == "-h" ]; then echo "usage: $(basename $0) destdir" exit 1 fi diff --git a/tools/update_versions.sh b/tools/update_versions.sh index 8c7f49f..188ed35 100755 --- a/tools/update_versions.sh +++ b/tools/update_versions.sh @@ -38,6 +38,9 @@ update_perl=" SBO-Lib/lib/SBO/Lib/Info.pm SBO-Lib/lib/SBO/Lib/Download.pm SBO-Lib/lib/SBO/Lib/Build.pm + SBO-Lib/lib/SBO/App.pm + SBO-Lib/lib/SBO/App/Remove.pm + SBO-Lib/lib/SBO/App/Snap.pm " update_other=" SBO-Lib/README |