diff --git a/README.md b/README.md index bd19ede..68980f5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ urpmex ====== -*urpmex* is a (small) suite of tools making Mageia system administration a bit more comfortable, +*urpmex* is a (small) suite of tools aiming to make Mageia system administration a bit more comfortable, especially when no graphical environment are available (i.e. remote terminals and so on). Currently it provides three scripts: diff --git a/cuterepos.pl b/cuterepos.pl index 57ecef5..7ed75ad 100755 --- a/cuterepos.pl +++ b/cuterepos.pl @@ -19,7 +19,6 @@ use warnings; use diagnostics; use Curses::UI; -use Data::Dumper; use Getopt::Long; use urpmex::Urpmex; diff --git a/kir.pl b/kir.pl index 8202bc4..004a4b2 100644 --- a/kir.pl +++ b/kir.pl @@ -18,7 +18,6 @@ use warnings; use diagnostics; use Getopt::Long; -#use Data::Dumper; my $PKG_REMOVER="/usr/sbin/urpme"; my $KRNLTOKEEP=3; my $force=0; diff --git a/repos.pl b/repos.pl index 5f3ae46..042888b 100644 --- a/repos.pl +++ b/repos.pl @@ -19,7 +19,6 @@ use diagnostics; use Term::ANSIColor qw(:constants); use Getopt::Long; use urpmex::Urpmex; -#use Data::Dumper; my $HFILE = undef; @@ -35,14 +34,93 @@ my $input = undef; my $active = undef; my $count = undef; my $use_wget = 0; # false +# params used speed mode +my $e_repolist = undef; +my $d_repolist = undef; +my $repolist = undef; +my $useBackports = undef; +my $useTesting = undef; +my $useDebug = undef; + +my $result = GetOptions ("wget" => \$use_wget, + "enable=s" => \$e_repolist, + "disable=s" => \$d_repolist, + "backports!" => \$useBackports, + "testing!" => \$useTesting, + "debug!" => \$useDebug); + +die("You cannot specify --enable and --disable at the same time\n") if grep($_, $e_repolist, $d_repolist) > 1; + +my $toggleValue = undef; # contains the value for toggle_repo routine, see doc header +if(defined($e_repolist)){ + $repolist = $e_repolist; + $toggleValue = 0; +}elsif(defined($d_repolist)){ + $repolist = $d_repolist; + $toggleValue = 1; +} +if(defined($repolist)){ + chomp $repolist; + my $filter = "Updates|Release"; + if($useBackports){ + $filter .= "|Backports"; + } + if($useTesting){ + $filter .= "|Updates Testing|Release Testing"; + if($useBackports){ + $filter .= "|Backports Testing"; + } + } + if($useDebug){ + $filter .= "|Updates Debug|Release Debug"; + if($useTesting){ + $filter .= "|Updates Testing Debug|Release Testing Debug"; + } + if($useBackports){ + $filter .= "|Backports Debug"; + if($useTesting){ + $filter .= "|Backports Testing Debug"; + } + } + } + + my @choices = split(',',$repolist); + my @repolist = retrieve_medias_array(); + my @selected_medias = (); + if(check_no_medias(@repolist)){ + die("No medias found"); + } + # rte = repo to enable + for my $media(@repolist){ + $media = urpmex::Shared::trim($media); + if($media eq ""){ + print "An empty media found?!\n"; + } + for my $rte(@choices){ + $rte = ucfirst($rte); + if($media =~ /^${rte}\s+($filter)$/g){ + push @selected_medias, $media; + } + } + } -my $result = GetOptions ("wget" => \$use_wget); + my @active_medias = active_medias(); + my @medias = (); + @medias = find_medias_to_enable(\@selected_medias, \@active_medias) if($toggleValue == 0); + @medias = r_strip_occurrences(\@selected_medias, \@active_medias) if($toggleValue == 1); + for(@medias){ + print "Enabling repo $_ ...\n" if($toggleValue == 0); + print "Disabling repo $_ ...\n" if($toggleValue == 1); + toggle_repo($_,$toggleValue); + } + exit(0); +} #------------------------ formats ----------------------------------------------- format HEAD= -Elenco dei media disponibili -Attivi: @##### +List of available media +Actives: @##### $count --------------------------------------------------------------------------------------------------------------------------- . @@ -69,15 +147,8 @@ sub main { # retrieve all medias @list = retrieve_medias_array(); - if(scalar(@list) le 0){ - print "No available medias.\n Do I have to add all the default medias? (Y/n)\n"; - $input=<STDIN>; - chomp $input; - if (lc($input) eq "y"){ - return add_medias(); - }else{ - return 0; - } + if(check_no_medias(@list)){ + die("No medias found"); } # active medias @actives = active_medias(); @@ -128,6 +199,24 @@ sub main { return 1; } +# ---------------------------------------------------------------------- +# check if there's no media and ask the user to add them eventually +# ---------------------------------------------------------------------- +sub check_no_medias { + my @list = @_; + my $input; + if(scalar(@list) le 0){ + print "No available medias.\n Do I have to add all the default medias? (Y/n)\n"; + $input=<STDIN>; + chomp $input; + if (lc($input) eq "y"){ + return add_medias(); + }else{ + return 0; + } + } +} + sub show_help { system('clear'); print BRIGHT_BLUE, "Digit the media correspondent number then press ",BOLD,"[Enter]",RESET,BRIGHT_BLUE," to toggle the repo active/inactive\n", RESET; diff --git a/urpm-downloader.pl b/urpm-downloader.pl index 762d46d..826537b 100644 --- a/urpm-downloader.pl +++ b/urpm-downloader.pl @@ -19,7 +19,6 @@ use diagnostics; use Term::ANSIColor qw(:constants); use Getopt::Long qw(:config permute); use urpmex::Urpmex; -#use Data::Dumper; my $PKG_QUERYMAKER = "urpmq"; diff --git a/urpmex/RPM.pm b/urpmex/RPM.pm new file mode 100644 index 0000000..a0aaf76 --- /dev/null +++ b/urpmex/RPM.pm @@ -0,0 +1,112 @@ +package urpmex::RPM; + +use strict; +use warnings; +use diagnostics; +require Exporter; +use base qw(Exporter); +use urpmex::Shared; +use RPM4; + +our @EXPORT = qw(compare_packages + rpm_name + rpm_version + rpm_release + rpm_epoch + rpm_fullname); + +sub compare_packages { + my $a = shift(); + my $b = shift(); + # example rpmdev-vercmp 0:1.1-1.mga2 0:1.1-2.mga2 + # 0:1.1-1.mga2 < 0:1.1-2.mga2 + # return 12 + # pk1 --> local + # pk2 --> remote + my $pk1; + my $pk2; + my $ret; + if(rpm_epoch($a) eq "(none)"){ + $pk1 = rpm_version($a,1)."-".rpm_release($a,1); + $pk2 = rpm_version($b,0)."-".rpm_release($b,0); + return undef if($pk1 eq $pk2); + $ret = rpmvercmp($pk1, $pk2); + print "RPMVERCMP($pk1, $pk2)\n"; + }else{ + $pk1 = rpm_epoch($a,1).":".rpm_version($a,1)."-".rpm_release($a,1); + $pk2 = rpm_epoch($b,0).":".rpm_version($b,0)."-".rpm_release($b,0); + return undef if($pk1 eq $pk2); + $ret = RPM4::compare_evr($pk1,$pk2); + print "COMPAREEVR($pk1, $pk2)\n"; + } + return $ret; +} + +sub rpm_name { + my $pkg = shift(); + my $is_installed = shift(); + my $name = undef; + if($is_installed){ + # query local db + #print "$RPM_COMMAND $RPM_QUERY $RPM_QUERY_ALL $RPM_QUERY_FMT \"%{NAME}\\n\" $pkg 2>/dev/null\n"; + $name = `$RPM_COMMAND $RPM_QUERY $RPM_QUERY_ALL $RPM_QUERY_FMT "%{NAME}\n" $pkg 2>/dev/null`; + }else{ + # query remote db / urpmq + my @data = split(':',`$PKG_QUERYMAKER $QUERY_PKG_INFORMATIONS $pkg 2>/dev/null | grep Name | uniq`); + $name = trim($data[1]); + } + chomp $name; + return $name; +} + +sub rpm_version { + my $pkg = shift(); + my $is_installed = shift(); + my $version = undef; + if($is_installed){ + # query local db + $version = `$RPM_COMMAND $RPM_QUERY $RPM_QUERY_ALL $RPM_QUERY_FMT "%{VERSION}\n" $pkg 2>/dev/null`; + }else{ + # query remote db / urpmq + my @data = split(':',`$PKG_QUERYMAKER $QUERY_PKG_INFORMATIONS $pkg 2>/dev/null | grep Name | uniq`); + $version = trim($data[1]); + } + chomp $version; + return $version; +} + +sub rpm_release { + my $pkg = shift(); + my $is_installed = shift(); + my $release = undef; + if($is_installed){ + # query local db + $release = `$RPM_COMMAND $RPM_QUERY $RPM_QUERY_ALL $RPM_QUERY_FMT "%{RELEASE}\n" $pkg 2>/dev/null`; + }else{ + # query remote db / urpmq + my @data = split(':',`$PKG_QUERYMAKER $QUERY_PKG_INFORMATIONS $pkg 2>/dev/null | grep Name | uniq`); + $release = trim($data[1]); + } + chomp $release; + return $release; +} + +sub rpm_epoch { + my $pkg = shift(); + my $is_installed = shift(); + my $epoch = undef; + $epoch = `$RPM_COMMAND $RPM_QUERY $RPM_QUERY_ALL $RPM_QUERY_FMT "%{EPOCH}\n" $pkg 2>/dev/null`; + chomp $epoch; + return $epoch; +} + +sub rpm_fullname { + my $name = shift(); + my $full = undef; + # query local db + $full = `$RPM_COMMAND $RPM_QUERY $RPM_QUERY_ALL $name 2>/dev/null`; + chomp $full; + return $full; +} + +1; diff --git a/urpmex/Shared.pm b/urpmex/Shared.pm new file mode 100644 index 0000000..58cff9d --- /dev/null +++ b/urpmex/Shared.pm @@ -0,0 +1,84 @@ +package urpmex::Shared; + +require Exporter; +use base qw(Exporter); + +our @EXPORT = qw($PKG_QUERYMAKER + $RPM_COMMAND + $RPM_VERCMP + $RPM_QUERY + $RPM_QUERY_ALL + $RPM_QUERY_FMT + $QUERY_LIST_AVAILABLE_PACKAGES + $QUERY_LISTMEDIA_PARM + $QUERY_LISTURL_PARM + $QUERY_LIST_UPDATES_ONLY + $QUERY_LOOKFORSRPM_PARM + $QUERY_PKG_FULL + $QUERY_PKG_RELEASE + $QUERY_PKG_GROUP + $QUERY_PKG_INFORMATIONS + $DLDER + $REPO_ADDMEDIA + $REPO_ADDMEDIA_PARAM_DISTRIB + $REPO_ADDMEDIA_PARAM_MIRRORLIST + $REPO_RMMEDIA + $REPO_RMMEDIA_ALL + $REPO_ENABLER + $REPO_PARAM_ACTIVATE + $REPO_PARAM_DEACTIVATE + $WITH_GROUP + $WITHOUT_GROUP + $UPDATES_ONLY + $RPM_QUERY_NAMEONLY + $RPM_QUERY_NAME_VERSION_RELEASE + indexArray + trim); + + +our $PKG_QUERYMAKER = "urpmq"; +our $RPM_COMMAND = "rpm"; +our $RPM_QUERY = "-q"; +our $RPM_QUERY_ALL = "-a"; +our $RPM_QUERY_FMT = "--qf"; +our $QUERY_LIST_AVAILABLE_PACKAGES = "--list"; +our $QUERY_LISTMEDIA_PARM = "--list-media"; +our $QUERY_LISTURL_PARM = "--list-url"; +our $QUERY_LIST_UPDATES_ONLY = "--update"; +our $QUERY_LOOKFORSRPM_PARM = "--sourcerpm"; +our $QUERY_PKG_FULL = "-f"; +our $QUERY_PKG_RELEASE = "-r"; +our $QUERY_PKG_GROUP = "-g"; +our $QUERY_PKG_INFORMATIONS = "-i"; +our $DLDER = "--wget"; +# rpmdev-vercmp provided by rpmdevtools +our $RPM_VERCMP = "rpmdev-vercmp"; + +our $REPO_ADDMEDIA = "urpmi.addmedia"; +our $REPO_ADDMEDIA_PARAM_DISTRIB = "--distrib"; +our $REPO_ADDMEDIA_PARAM_MIRRORLIST = "--mirrorlist"; +our $REPO_RMMEDIA = "urpmi.removemedia"; +our $REPO_RMMEDIA_ALL = "-a"; +our $REPO_ENABLER = "urpmi.update"; +our $REPO_PARAM_ACTIVATE = "--no-ignore"; +our $REPO_PARAM_DEACTIVATE = "--ignore"; + +# constants +our $WITH_GROUP = 1; +our $WITHOUT_GROUP = 0; +our $UPDATES_ONLY = 1; +our $RPM_QUERY_NAMEONLY = 1; +our $RPM_QUERY_NAME_VERSION_RELEASE = 2; + +# http://www.perlmonks.org/?node_id=66003 +sub indexArray{ + 1 while $_[0] ne pop; + @_-1; +} + +sub trim { + my $st = shift(); + $st =~s/^\s*//g; + $st =~s/\s*$//g; + return $st; +} diff --git a/urpmex/Urpmex.pm b/urpmex/Urpmex.pm index faec3cc..6914087 100644 --- a/urpmex/Urpmex.pm +++ b/urpmex/Urpmex.pm @@ -22,9 +22,11 @@ use base qw(Exporter); use strict; use warnings; use diagnostics; -use Data::Dumper; use List::Compare; use List::Util qw(first); +use urpmex::Shared; +use urpmex::RPM; +use POSIX; our @EXPORT = qw(retrieve_available_updates retrieve_available_packages_full @@ -41,64 +43,81 @@ our @EXPORT = qw(retrieve_available_updates add_medias remove_medias update_repos + find_medias_to_enable + find_medias_to_disable + r_strip_occurrences compute_changes enumerate_symm_diff - $WITH_GROUP - $WITHOUT_GROUP - $UPDATES_ONLY ); -my $PKG_QUERYMAKER = "urpmq"; -my $RPM_COMMAND = "rpm"; -my $RPM_QUERY = "-q"; -my $RPM_QUERY_ALL = "-a"; -my $RPM_QUERY_FMT = "--qf"; -my $QUERY_LIST_AVAILABLE_PACKAGES = "--list"; -my $QUERY_LISTMEDIA_PARM = "--list-media"; -my $QUERY_LISTURL_PARM = "--list-url"; -my $QUERY_LIST_UPDATES_ONLY = "--update"; -my $QUERY_LOOKFORSRPM_PARM = "--sourcerpm"; -my $QUERY_PKG_FULL = "-f"; -my $QUERY_PKG_RELEASE = "-r"; -my $QUERY_PKG_GROUP = "-g"; -my $DLDER = "--wget"; - -my $REPO_ADDMEDIA = "urpmi.addmedia"; -my $REPO_ADDMEDIA_PARAM_DISTRIB = "--distrib"; -my $REPO_ADDMEDIA_PARAM_MIRRORLIST = "--mirrorlist"; -my $REPO_RMMEDIA = "urpmi.removemedia"; -my $REPO_RMMEDIA_ALL = "-a"; -my $REPO_ENABLER = "urpmi.update"; -my $REPO_PARAM_ACTIVATE = "--no-ignore"; -my $REPO_PARAM_DEACTIVATE = "--ignore"; - -# constants -our $WITH_GROUP = 1; -our $WITHOUT_GROUP = 0; -our $UPDATES_ONLY = 1; -our $RPM_QUERY_NAMEONLY = 1; +# ---------------------------------------------------------------------- +# compare two package names and return true if 2nd arg is newer than 1st +# otherwise return false - bool +# ---------------------------------------------------------------------- +sub newer { + my $installed = shift(); + my $possible = shift(); + # return 0 before comparing_packages if package names are identical + my $result = compare_packages($installed,$possible); + return 0 if($result == 1); + return 1 if($result == -1); +} + +# ---------------------------------------------------------------------- +# compare installed pkgs with available pkgs to find updates - array +# ---------------------------------------------------------------------- +sub check_for_updates { + my $possibleUpdates = shift(); + my $installedPkgs = shift(); + my @update_candidate = (); + for my $installed (@$installedPkgs){ + my $i_name = rpm_name($installed, 1); + print "RESTANTI: ".scalar(@$possibleUpdates)."\n"; + last if(scalar(@$possibleUpdates)<=0); + my @matching = grep { $_ =~ /${i_name}/ } @$possibleUpdates; + next if(scalar(@matching)<=0); + my $possible = first { rpm_name($_,0) eq $i_name } @matching; + #if(!defined($possible) || ($possible eq "")){ + # for(@matching){ + # splice(@$possibleUpdates, indexArray($_,@$possibleUpdates), 1); + # } + # next; + #} + next if(!defined($possible) || ($possible eq "")); + splice(@$possibleUpdates, indexArray($possible,@$possibleUpdates), 1); + my $p_name = rpm_name($possible,0); + next if($p_name eq ""); + if(newer($i_name,$p_name)){ + print ">>> PUSHED <<<\n"; + print "$possible\n"; + push @update_candidate, $possible; + } + } + return @update_candidate; +} # ---------------------------------------------------------------------- # find available updates - array # ---------------------------------------------------------------------- sub retrieve_available_updates { + use Data::Dumper; + my @available_updates = retrieve_available_packages_release($WITHOUT_GROUP,$UPDATES_ONLY); my @installed = retrieve_installed_packages($RPM_QUERY_NAMEONLY); - my @availables = retrieve_available_packages_release($WITHOUT_GROUP,$UPDATES_ONLY); - my @intermediate = enumerate_symm_diff(\@installed, \@availables); - print "INTERMEDIATE\n"; - print Dumper(@intermediate); - print "INSTALLED\n"; - print Dumper(@installed); - my @updates = enumerate_intersection(\@installed, \@intermediate); + #my @intermediate = enumerate_similar_items(\@installed, \@available_updates); + #my @installed_full = retrieve_installed_packages($RPM_QUERY_NAME_VERSION_RELEASE); + my @updates = check_for_updates(\@available_updates, \@installed); + print Dumper(@updates); return @updates; } sub wrap_retrieve_installed_packages { - my $nameonly = shift(); + my $filter = shift(); my @args; my $command = "$RPM_COMMAND $RPM_QUERY $RPM_QUERY_ALL"; - if(defined($nameonly) && ($nameonly == $RPM_QUERY_NAMEONLY)){ + if(defined($filter) && ($filter == $RPM_QUERY_NAMEONLY)){ push @args, "$RPM_QUERY_FMT \"%{NAME}\n\""; + }elsif(defined($filter) && ($filter == $RPM_QUERY_NAME_VERSION_RELEASE)){ + push @args, "$RPM_QUERY_FMT \"%{NAME}-%{VERSION}-%{RELEASE}\n\""; } $command = $command . " " . join(" ", @args); return $command; @@ -108,8 +127,8 @@ sub wrap_retrieve_installed_packages { # retrieve installed packages - array # ---------------------------------------------------------------------- sub retrieve_installed_packages { - my $nameonly = shift(); - my $command = wrap_retrieve_installed_packages($nameonly); + my $filter = shift(); + my $command = wrap_retrieve_installed_packages($filter); my @list = `$command`; chomp @list; return @list; @@ -352,6 +371,63 @@ sub remove_medias { } # ---------------------------------------------------------------------- +# reverse of strip_occurrences (a available from b) +# ---------------------------------------------------------------------- +sub r_strip_occurrences { + my $a = shift(); + my $b = shift(); + my @medias = (); + for my $media(@$b){ + my $res = undef; + if(isdigit($media)){ + $res = first { $_ == $media } @$a; + }else{ + $res = first { $_ eq $media } @$a; + } + push(@medias, $media) if(defined($res)); + } + return @medias; +} + +# ---------------------------------------------------------------------- +# return an array of the occurrences of a not available from b +# ---------------------------------------------------------------------- +sub strip_occurrences { + my $a = shift(); + my $b = shift(); + my @medias = (); + for my $media(@$a){ + my $res = undef; + if(isdigit($media)){ + $res = first { $_ == $media } @$b; + }else{ + $res = first { $_ eq $media } @$b; + } + next if(defined($res)); + push(@medias, $media); + } + return @medias; +} + +# ---------------------------------------------------------------------- +# find medias to disable from a mixed list +# ---------------------------------------------------------------------- +sub find_medias_to_disable { + my $unselected = shift(); + my $inactive = shift(); + return strip_occurrences(\@$unselected,\@$inactive); +} + +# ---------------------------------------------------------------------- +# find medias to enable from a mixed list +# ---------------------------------------------------------------------- +sub find_medias_to_enable { + my $selection = shift(); + my $active = shift(); + return strip_occurrences(\@$selection,\@$active); +} + +# ---------------------------------------------------------------------- # medias activation/deactivation based on previous and current selections # ---------------------------------------------------------------------- sub compute_changes { @@ -377,23 +453,13 @@ sub compute_changes { my $res = undef; my $fA=0; - for my $media(@currSelection){ - # looking for medias that WERE NOT active - # the user want to activate them right now - $res = first { $_ == $media } @ids_of_active_repos; - next if(defined($res)); # it was already active, go on - push(@MEDIASTOENABLE, $media); - $fA=1; - } + @MEDIASTOENABLE = find_medias_to_enable(\@currSelection,\@ids_of_active_repos); + $fA=1 if(scalar(@MEDIASTOENABLE) > 0); $res = undef; my $fB=0; - for my $media(@currentlyUnselected){ - $res = first { $_ == $media } @ids_of_inactive_repos; - next if(defined($res)); - push(@MEDIASTODISABLE, $media); - $fB=1; - } + @MEDIASTODISABLE = find_medias_to_disable(\@currentlyUnselected, \@ids_of_inactive_repos); + $fB=1 if(scalar(@MEDIASTODISABLE) > 0); return (undef, undef) if(($fA == 0)&&($fB == 0)); return (\@MEDIASTOENABLE, \@MEDIASTODISABLE); @@ -430,15 +496,33 @@ sub enumerate_union { sub enumerate_intersection { my $first_set = shift(); my $second_set = shift(); -=comment my $intersection = List::Compare->new('--unsorted',\@$first_set,\@$second_set); my @enumeration = $intersection->get_intersection(); -=cut + return @enumeration; +} + +# ---------------------------------------------------------------------- +# returns a list of item matching the given regex - array +# ---------------------------------------------------------------------- +sub enumerate_similar_items { + my $first_set = shift(); + my $second_set = shift(); my @enumeration; for my $pattern(@$first_set){ - push @enumeration, grep { $_ =~ /${pattern}\-/g } @$second_set; + push @enumeration, grep { $_ =~ /${pattern}/g } @$second_set; } return @enumeration; } +# ---------------------------------------------------------------------- +# returns the intersection of two lists - array +# ---------------------------------------------------------------------- +sub enumerate_complement { + my $first_list = shift(); + my $second_list = shift(); + my $complement = List::Compare->new('--unsorted',\@$first_list,\@$second_list); + my @enumeration = $complement->get_complement(); + return @enumeration; +} + 1;