Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Resume emerge when no resume file - continuemerge.pl
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks
View previous topic :: View next topic  
Author Message
thomasa88
Tux's lil' helper
Tux's lil' helper


Joined: 13 Apr 2005
Posts: 143
Location: Sweden

PostPosted: Wed Jun 08, 2005 11:50 am    Post subject: Resume emerge when no resume file - continuemerge.pl Reply with quote

I wrote this script because sometimes my computer just hangs when emerging and no resume-file is written, and when you do a --emptytree you dont want to start again from the beginning. Instead you want to continue from where it was before hanging. My script does that by skipping to the ebuild you want to start from. (maybe not the best gram. but the computer hung on emerge while I was writing this post the first time :S)

Comments and suggestions are welcome :)

edit.
The script has support for following namingformats (if more than one hit it will take the first)
cat-subcat/prg-ver
cat-subcat/prg
prg-ver
prg

Version 2 added (after v1, cronologhical :P)

Version 1.xx
This is the first and textbased version (with some colors :))
Code:

#!/usr/bin/perl

################################################################################
# File:      continuemerge.pl
# Version:   1.09
# By:      Thomas Axelsson 2005
# Description:   Let's you resume an emerge -e when emerge can't resume (--resume)
################################################################################

#Let the user choose which ebuild to use
sub ChooseStartFrom #($fullList)
{
   my($fullList,$startFrom)=($_[0]);
   while(true)
   {
      print "Which ebuild do you want to \e[32mstart from?\e[0m\n";
      print("1 = Show full merge list  2 = Show the last lines of emerge log\n\n");
      print "\e[36m";
      $startFrom=<STDIN>;
      chomp($startFrom);
      print "\e[0m\n\n";
      
      if($startFrom eq "1")
      {
         print $fullList;
      }
      elsif($startFrom eq "2")
      {
         system("tail -n20 /var/log/emerge.log");
      }
      else
      {   
         #done
         last;
      }
      
      print "\n\n";
   }
   return $startFrom;
}

#Generate $fullList (to show user, instead of running emerge -p everytime) and $buildList (to pass to emerge)
sub GenList #($cmd)
{
   my($cmd,$buildList,$fullList)=($_[0]);
   
   #Get output from emerge -p
   print "Generating lists with emerge...";
   $fullList=`$cmd`;
   print "Done.\n\n";

   print "Parsing lists...";
   #Remove anything that isn't an ebuild
   $fullList=~s/^[^[].*$//mg;
   $fullList=~s/\n{2,}/\n/g;

   #We gonna do a list to show the user ($fullList) and when to pass to emerge ($buildList)
   $buildList=$fullList;
   #Fancy colors
   $fullList=~s/\[ebuild.{7}\] //g;
   $fullList=~s|^(.*?/)(.*?)(-[0-9])|\e[35m$1\e[32m$2\e[0m$3|mg;
   
   #Make a list we can pass to emerge
   $buildList=~s/\[ebuild.{7}\] /=/g;
   $buildList=~s/\n/ /g;
   $buildList=~s/ {2,}/ /g;

   print "Done.\n\n";

   return ($fullList,$buildList);
}

sub CheckPerms
{
   #Is user root?
   my($user)=`whoami`;
   chomp($user);
   if($user ne 'root')
   {
      #No. Then we have to exit
      print "\e[31mError\e[0m: You must be \e[32mroot\e[0m to emerge!\n\n";
      exit;
   }
}

#Separate the output from what is written before
print "\n\n";

#Check if the user is root
CheckPerms;

#The main loop
while(true)
{
   my($cmd,$startFrom,$fullList,$buildList,$correct);
   
   #Ask the user what command he want to resume
   print "What \e[32mcommand\e[0m did you run?\n";
   print "\e[36memerge ";
   $cmd=<STDIN>;
   chomp($cmd);
   
   #We don't want verbose output
   $cmd=~s/-v( |$)|v([^ ])|(-[^ ]+)v/$1$2$3/g;
   
   $cmd="emerge -p $cmd";
   print "\e[0m\n\n";

   #Get ebuild-lists from user input
   ($fullList,$buildList)=GenList($cmd);
   
   #Loop until the user choose an existing ebuild
   while(true)
   {
      #Ask the user where to start from
      $startFrom=ChooseStartFrom($fullList);
      
      print "Excluding packages before \e[32m$startFrom\e[0m...";
      #Check if the ebuild is in the list
      if($buildList!~m|[=/]$startFrom[- ]|)
      {
         #Ebuild doesnt exist, inform the user
         print "\e[31mError\e[0m: ";
         print "The package you have specified could not be found in the list\nWrite \e[32m1\e[0m to show the \e[32mpackages you can choose from\e[0m.\n\n";
         #Let the user fill in the name again
         redo;
      }
      #Remove all ebuilds before the one specified
      $buildList=~s/(.* )(.*?${startFrom}.*? )//;
      $buildList="$2$buildList";
      #print "\e[31m$1\e[0m";
      #print "\e[32m$buildList\e[0m";
      print "Done.\n\n";
      
      #Stop the loop when the user has chosen an existing ebuild
      last;
   }
   
   #Output what will happen if the generated list gets emerged
   print "These packages will be emerged:\n\n";
   system("emerge -p $buildList");
   
   #Ask the user if this is correct
   print "\n\nIs this \e[32mcorrect\e[0m?[y] ";
   $correct=<STDIN>;
   chomp($correct);
   
   #Check the answer from the user
   if($correct eq "y" || $correct eq "Y" || $correct eq "")
   {
      #Do the emerge and stop the script
      print "\n\nEmerging...\n\n";
      system("emerge $buildList");
      last;
   }
   else
   {
      #Insert some new lines and return to the beginning
      print "\n\n\n\n";
   }
}


edit.

1.09 - Replace die with exit, added check for verbose (emerge -v)
1.08 - Added whoami-check
1.07 - Replaced local with my

edit.

Version 2.xx
This is the second version, it uses dialog to show and get information.

2.01 - added -q when getting list from emerge
Code:

#!/usr/bin/perl

################################################################################
# File:      continuemerge2.pl
# Version:   2.01
# By:      Thomas Axelsson 2005
# Description:   Let's you resume an emerge when emerge can't resume (--resume)
################################################################################

sub MenuChooseStartFrom #(@fullList)
{
#    my(@fullList,@fullListInfo,$startFrom,$defaultItem)=(@_);
   
   #Try to figure out where the user want to start (this isnt good on memory if the file is big..)
   #Lets make a block with a private array
   {
      #Read and reverse the emerge log
      open(LOG,"</var/log/emerge.log");
      my @emergeLog=reverse <LOG>;
      close(LOG);
      
      #Read every line until we find an ebuild in our list
      LOGLOOP: foreach $line(@emergeLog)
      {
         
         #Sample: 1118255374:  ::: completed emerge (37 of 40) net-misc/openssh-3.9_p1-r2 to /
         if($line=~/[0-9]+:  ::: completed emerge \([0-9]+ of [0-9]+\) (.+?\/.+?) to .*/)
         {
            #< is intended, we don't want to check the latest and try to add info to the next one
            for($i=0;$i<$#fullList;$i++)
            {
               if($fullList[$i] eq $1)
               {
                  $defaultItem=$fullList[$i+1];
                  $fullListInfo[$i+1]="<--- Guess";
                  last LOGLOOP;
               }
            }
         }
      }
   }
   
   for($i=0;$i<=$#fullList;$i++)
   {
      $fullList[$i]="\"$fullList[$i]\" \"$fullListInfo[$i]\"";
   }
   
   $fullList=join(" ",@fullList);

   $startFrom=`dialog --stdout --ok-label Choose --cancel-label Exit --default-item "$defaultItem" --menu "Which ebuild do you want to start from?" 0 0 0 $fullList`;
}

#Generate @fullList (to show user, instead of running emerge -p everytime) and @buildList (to pass to emerge)
sub GenListArrays #($cmd)
{
#    my($cmd,$buildList,@fullList)=($_[0]);
   
   system("dialog --infobox \"Generating lists with emerge...\" 0 0");
   #Get output from emerge -p
   @fullList=`$cmd`;

   system("dialog --infobox \"Parsing lists...\" 0 0");
   #Remove anything that isn't an ebuild
   @fullList=grep{
         $_!~/^[^[].*$/;
         } @fullList;
   
   #Remove traling \n and \s
   @fullList=map{
         chomp($_);
          $_=~s/\s+$//g;
         $_;
          } @fullList;

   #We gonna do a list to show the user (@fullList) and when to pass to emerge (@buildList)
   @buildList=@fullList;
   
   #Remove unnecessary info
   @fullList=map{
         $_=~s/\[ebuild.{7}\] //;
         $_;
         } @fullList;
   
   #Make a list we can pass to emerge
   @buildList=map{
         $_=~s/\[ebuild.{7}\] /=/;
         $_;
         } @buildList;

#    return (@fullList,@buildList);
}

sub CheckPerms
{
   #Is user root?
   my($user)=`whoami`;
   chomp($user);
   if($user ne 'root')
   {
      #No. Then we have to exit
      system("dialog --msgbox \"You must be root to run emerge!\" 0 0");
      exit;
   }
}

#Check if the user is root
CheckPerms;

#The main loop
while(true)
{
#    my($cmd,$startFrom,@fullList,@buildList,$correct);
   
   #Ask the user what command he want to resume
   $cmd=`dialog --stdout --inputbox "What command did you run?" 0 0`;

   #We don't want verbose output
   $cmd=~s/-v( |$)|v([^ ])|(-[^ ]+)v/$1$2$3/g;
   #Add "emerge"?
   if($cmd!~/^\s*emerge/)
   {
      $cmd="emerge $cmd";
   }
   #Add --pretend and --quite
   $cmd.=" -pq";

   #Get ebuild-lists from user input
   #($fullList,$buildList)=GenList($cmd);
   GenListArrays($cmd);
   
   #Ask the user where to start from
   $startFrom=MenuChooseStartFrom(@fullList);
   
   if($startFrom eq "")
   {
      last;
   }
   
   system("dialog --info \"Excluding packages before $startFrom...\" 0 0 ");
   
   #Check if the ebuild is in the list
   if((grep {$_=~$startFrom} @buildList)!=1)
   {
      #Ebuild doesnt exist, inform the user
      system("dialog --msgbox \"Error: The package you have specified could not be found in the list :S\" 0 0");
      exit;
   }
   
   #Remove all ebuilds before the one specified
   {
      my $keep=0;

      @buildList=grep{
               if(!$keep && $_=~/$startFrom/)
               {
                  $keep=1;
               }
               if($keep)
               {
                  1;
               }
               else
               {
                  0;
               }
            } @buildList;
   }
   my $buildList='"'.join('" "" "',@buildList).'" ""';
   
   #Output what will happen if the generated list gets emerged
   #and ask if the list is correct
   $correct=`dialog --stdout --ok-label Yes --cancel-label No --menu "This is the new merge list. Is it correct?" 0 0 0 $buildList`;
   
   #Check the answer from the user
   if($correct)
   {
      #Do the emerge and stop the script
      print "\n\nEmerging...\n\n";
      #system("emerge $buildList");
      last;
   }
   else
   {
      #Let the loop rerun
   }
}



_________________
- thomasa88


Last edited by thomasa88 on Sun Feb 05, 2006 1:24 pm; edited 3 times in total
Back to top
View user's profile Send private message
JoshFed
n00b
n00b


Joined: 21 Jul 2003
Posts: 44
Location: Tacoma, WA USA

PostPosted: Thu Jun 09, 2005 3:52 am    Post subject: Reply with quote

Good thinkin. I don't know much about Perl, yet, but I'll check it out.

I try to do a "emerge --fetchonly X" first, then "emerge X." Especially for large ebuilds that have a lot of packages.
Back to top
View user's profile Send private message
thomasa88
Tux's lil' helper
Tux's lil' helper


Joined: 13 Apr 2005
Posts: 143
Location: Sweden

PostPosted: Wed Jun 22, 2005 11:35 am    Post subject: Reply with quote

Added V2 beta
_________________
- thomasa88
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum