diff options
-rwxr-xr-x | sboremove | 254 |
1 files changed, 133 insertions, 121 deletions
@@ -1,6 +1,6 @@ #!/usr/bin/perl # -# vim: ts=4:noet +# vim: ts=2:et # # sboremove # script to remove an installed SlackBuild @@ -37,7 +37,7 @@ EOF return 1; } -my ($help, $vers, $non_int, $alwaysask, @excluded); +my ($help, $vers, $non_int, $alwaysask); GetOptions( 'help|h' => \$help, @@ -51,141 +51,153 @@ 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; +# 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 -# 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); -} +sub main { + my ($non_int, $alwaysask, @args) = @_; -# Determine required by for all installed sbo's -my (%required_by, @confirmed); + my @installed = @{ get_installed_packages('SBO') }; + my $installed = +{ map {; $_->{name}, $_->{pkg} } @installed }; -# 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); + @args = grep { check_sbo($_, $installed) } @args; + exit 1 unless @args; + my %sbos = map { $_ => 1 } @args; -# 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; -} + my @remove = get_full_queue($installed, @args); -sub confirm_remove { - my $sbo = shift; - push @confirmed, $sbo unless in($sbo => @confirmed); - return 1; + my @confirmed; + + if ($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 $alwaysask; + + push @confirmed, $remove if confirm($remove, $needed ? @required_by : ()); + } + } + + return say "Nothing to remove." unless @confirmed; + + remove($non_int, @confirmed); } -# Check if packages in queue are actually installed on system -my @temp; -for my $sbo (@$remove_queue) { - push @temp, $sbo if $inst_names{$sbo}; +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; } -$remove_queue = \@temp; -# Confirm all and skip prompts if noninteractive -if ($non_int) { - confirm_remove($_) for @$remove_queue; - goto CONFIRMED; +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; } -# 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"; - } +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; } -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; +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; } -# Final confirmation -unless ($non_int) { - unless (prompt("\nAre you sure you want to continue?", default => 'no')) { - say 'Exiting.'; - exit 0; - } +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)); + if (not defined $readme) { + warn "Unable to open README for $remove.\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; } -system("/sbin/removepkg", $_) for @confirmed; +sub remove { + my ($non_int, @confirmed) = @_; + + say sprintf "Removing %d package(s)", scalar @confirmed; + say join " ", map { $_->{name} } @confirmed; -say "All operations have completed successfully."; + 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."; +} -exit 0; +main($non_int, $alwaysask, @ARGV); |