All pastes #460914 Raw Edit

Upd-world 1.8 w/ TE

public shellscript v1 · immutable
#460914 ·published 2007-04-27 11:24 UTC
rendered paste body
#!/bin/bash# update-world 1.8# count_zero 2007# Licensed under the GPLv2# Modified by Michal Gorny, added 'genlop -p' support for estimating build time## update-world is a bash script that forces an emerge -uD world to continue, even# in the face of (inevitable) compile failures.  Failed builds are added to a list,# and the script jumps to the next package in the queue.## just run update-world --prepare (or --empty) followed by update-world --install.## Release Notes:# v1.8: Cleaned and modularized code.  Added ability to utilize revdep-rebuild if wished.  Can now pipe other#       emerges into update-world.  Sources /etc/make.conf.  Added interfacing with elog.  Some bugfixes.# v1.7  broken.# v1.6.1: Bugfixes, added utf-8 support# v1.6: Script preserves colored output.  Fixed version numbering in help output.# v1.5: now handles 'fetch restriction' properly# v1.4: uses '--newuse' for emerges to respect new use flags# v1.3: uses '--oneshot' for emerges so they don't get added to the world file.# v1.2: Script now detects log directly instead of accepting only /var/log/portage# v1.1: minor bugfix to allow package without version to be added to 'emergelist'# v1.0: Release###### Help ##### Help informationdisplayhelp (){echo "update-world 1.8count_zero 2007licensed under the GPLv2http://www.fsf.org/licensing/licenses/gpl.txtDescription:This is a bash script to automate the 'emerge -uD world' process.The default program directory is ~/.update-world.Error logs are filed in ~/.update-world/<date>/log.Ebuild notices (elogs) are filed in ~/.update-world/<date>/notice.Usage:update-world [ --help | -h ]	Display this help file and exit.update-world [ --prepare | -p ]	Prepares a list of packages produced by 'emerge -puvD world'	and outputs them to the file 'emergelist' in the current directory.	Add, remove, or change the version of any of the packages listed	in this file with your favorite editor before continuing.update-world [ --empty | -e ]	Same as --prepare except it performs 'emerge -ev world' to recompile	all packages on a system.update-world [ --install | -i ]	Begins the emerge process based upon the 'emergelist' file created 	from running 'update-world --prepare'.  Once finished, failed builds	will be saved in the file 'failedlist' in the program directory.update-world [ --revdep | -r ]	Run revdep-rebuild to prepare the emergelist.  Can be used alone	or in conjunction with --install.emerge -p <package> | update-world	Let portage produce an emergelist determined by a package.  This can be	useful for large packages with lots of dependencies (kde, gnome, xorg, etc.).	Once complete, run update-world --install.update-world [ --log | -l ]	View the ebuild notices (elogs) of packages installed by update-world,	sorted by date."}#### end help ##### Set the program directory and important variablessource /etc/make.confexport EMERGE_DEFAULT_OPTS=""homedir=~/.update-worldworkdir="$homedir/`date +%F`"logdir="$workdir/log"noticedir="$workdir/notice"mkdir -p $logdirmkdir -p $noticedirtouch $homedir/failedlistemergelist=$homedir/emergelistemergetemp=$workdir/emergetempfailedlist=$homedir/failedlistparameter="-puvD --newuse"#### error-check ##### make sure there are no errors in the emerge process.errorcheck (){cat $emergelist | xargs emerge -p > $emergetempif [[ -n `cat $emergetemp | grep '\[blocks'` ]]	then echo "WARNING: You have a blocking package.  Fix this before continuing."; exit 1	exit 1	elif grep -q "masked by:" $emergetemp	then echo "WARNING: You may need to unmask some packages before continuing."; exit 1	elif grep -q "emerge: there are no ebuilds to satisfy" $emergetemp	then echo "WARNING: One of the specified packages doesn't exist"; exit 1	elif [[ -n `cat $emergetemp | sed -n 's/^\[ebuild[[:upper:][:lower:] ]*F[[:upper:][:lower:] ]*\].*/&/p'` ]]	then fetchrestricted=`cat $emergetemp | sed -n 's/^\[ebuild[[:upper:][:lower:] ]*F[[:upper:][:lower:] ]*\].*/&/p' | sed -n 's/^\[ebuild[[:upper:][:lower:] ]*\]\ \([[:lower:][:upper:]0-9._+\/-]*\).*/\1/p'`	echo -e "\nWARNING: The following packages have Fetch Restriction turned on:\n$fetchrestricted"	for each in $fetchrestricted	do emerge =$each	done	exit 1	else :fi}#### end error-check ######## empty ##### parameter for '--empty' to emerge -e worldempty (){parameter='-pev'}#### end empty#### prepare ##### Prepare the list of packages to emerge into emerglistprepare (){if [[ -e "$emergelist" ]]	then echo -en "The file 'emergelist' already exists and will be overwritten.\nContinue anyway? (Y/n) "	read continue	if [[ "$continue" = 'y' || "$continue" = 'yes' || "$continue" = 'Y' || "$continue" = 'Yes' || "$continue" = 'YES' || "$continue" = '' ]]		then :		else echo exiting.		exit 0	fi	else :fiemerge $parameter world > $emergelisterrorcheckemerge $parameter worldif which genlop >/dev/null 2>&1; then	cat $emergelist | genlop -p | grep ^Estimatedfiecho -e "\nThese are the packages that will be installed.  If you want to alter this list,\njust edit the file 'emergelist' in $homedir. When finished,\nrun 'update-world --install'"cat $emergelist | sed -n 's/^\[ebuild[[:upper:][:lower:] ]*\]\ \([[:lower:][:upper:]0-9._+\/-]*\).*/\1/p' | sed 's/.*/=&/' | sort -d > $emergetempcp $emergetemp $emergelistrm -f $failedlist}#### end prepare ######## installworld ##### Install the packages listed in emergelistinstallworld (){# Make sure there's an emergelistif [[ -s "$emergelist" ]]	then :	else echo "WARNING: no 'emergelist' exists.  Did you run 'update-world --prepare' first?"; exit 1fierrorcheckcondition=false# set begin timebefore_time="${before_time:=`date +%s`}"# Until loop to make portage continue until finisheduntil [[ $condition = true ]]do	cat $emergelist | xargs emerge -1	# Detect which packages have been successfully emerged and remove from the queue	installed=`tac /var/log/emerge.log | sed '/Started\ emerge/,$d' | grep "completed emerge" | sed 's/^.*)\ //' | sed 's/\ to.*//'`	for each in `cat "$emergelist" | sed 's/^=//'`	do		if [[ -n `echo "$installed" | grep "$each"` ]]			then			# Checking emerge logs for any ebuild notices			einfo=""			notice="$noticedir/${each/\//:}-notice.log"			elog="${PORT_LOGDIR}/elog/`ls -lt $PORT_LOGDIR/elog | grep ${each/\//:} | sed '2,$ d' | sed 's/.*\ //'`"			if [[ -n "$PORTAGE_ELOG_SYSTEM" ]] && [[ -n "${einfo:=`cat $elog | sed '/^$/d' | sed '/^[ ]*$/d' | sed 's/.*/ * &/'`}" ]]				then 				echo ------------------------ > $notice				echo -e "$each \n" >> $notice				echo "$einfo" >> $notice				echo ------------------------ >> $notice				else :			fi			# Removing successful emerges 			each=`echo ${each//\//\\/} | sed 's/\-[0-9].*//'`			cat $emergelist | sed "/${each//\//\\/}/d" > $emergetemp			mv $emergetemp $emergelist		fi	done	# See if all packages have been emerged.  If so, exit function "installworld"	if [[ -z `cat "$emergelist"` ]]		then condition=true		break		else :	fi	## If there are remaining packages, find why the emerge stopped	errorlog=`ls -t $PORT_LOGDIR | sed '2,$d'`	# if user-initiated "control-c" just exit.	if [[ -n `cat $PORT_LOGDIR/$errorlog | grep 'signal 2'` ]]		then echo -e "\n*** User hit 'Control-C' ... exiting.\n"		exit 1		else :	fi	# if package failed, give user chance to stop update-world	sleep 5	echo	echo "*** Hit Control-C to exit, or just wait to continue with emerge."	echo	sleep 10	echo "*** Continuing with emerge."	# Detect failed emerge and add to failedlist, remove failed package from emergelist	failedpkg=`tac /var/log/emerge.log | sed '1d' | sed '/terminating/,$d' | sed '/completed\ emerge/,$d' | grep ">>>" | sed 's/.*)\ //' | sed 's/\ to.*//'`	#### uh-oh, stop if something's really wrong to prevent infinite emerge (tried to emerge same package again)	if [[ -n `tail -n 1 $failedlist | grep $failedpkg` ]]		then echo "The failed package $failedpkg could not be merged and must be successfully installed before continuing."		exit 1		else :	fi		echo $failedpkg >> $failedlist	# if package added to emergelist manually doesn't have a version, make sure it's still removed if it fails	if [[ -z `cat "$emergelist" | grep "$failedpkg"` ]]		then failedpkg2=`equery which =$failedpkg | sed 's/\/[^/]*$//' | sed -n 's/.*\/\([^/]*\/[^/]*\)/\1/p'`		cat $emergelist | sed "/^${failedpkg2//\//\\/}/d" > $emergetemp		else cat $emergelist | sed "/${failedpkg//\//\\/}/d" > $emergetemp	fi	mv $emergetemp $emergelist	# link to the log file of the failed package	ln -s $PORT_LOGDIR/$errorlog $logdir/${errorlog}_error-log	echo	echo	echo "*** $failedpkg compile failed, skipping."	# Is there a package in 'emergelist' that REQUIRES the failed package as a dep? If so, remove it too.	failedpkgdeps=`equery which =$failedpkg | sed 's/\/[^/]*$//' | sed -n 's/.*\/\([^/]*\/[^/]*\)/\1/p'`	deps=`equery depends $failedpkgdeps | sed '/^\[/d' | sed 's/.*/=&/'`	for each in `echo $deps`	do		if [[ -n `cat $emergelist | grep "$each"` ]]			then			if [[ -n `emerge -p $each | grep "$failedpkg"` ]]				then				each2=`cat $emergelist | grep $each | sed 's/\=//'`				echo "$each2 (depends on $failedpkg)" >> $failedlist				cat $emergelist | sed "/${each//\//\\/}/d" > $emergetemp				mv $emergetemp $emergelist				echo "*** $each depends on $failedpkg, skipping."				else :			fi			else :		fi	done	if [[ -z `cat "$emergelist"` ]]		then condition=true		break		else :	fi	echo "*** Continuing with emerge world"done}#### end installworld ######## revdep-rebuild ##### this script can call revdep-rebuild and get it's emergelist from there.# useful to run in conjunction with update-world --install, it will automatically# run revdep-rebuild after the emerge -uD world is completerevdep (){rm /root/.revdep-rebuild*.?_*revdep-rebuild --package-names --pretend | tee $emergelistcat $emergelist | sed -n 's/^\[ebuild[[:upper:][:lower:] ]*\]\ \([[:lower:][:upper:]0-9._+\/-]*\).*/\1/p' | sed 's/.*/=&/' > $emergetempmv $emergetemp $emergelist}#### end revdep-rebuild ######## piped ##### emergelist is piped from another emerge (i.e., emerge kde | update-world)piped (){echo "$piped" > $emergelisterrorcheckcat $emergelist | sed -n 's/^\[ebuild[[:upper:][:lower:] ]*\]\ \([[:lower:][:upper:]0-9._+\/-]*\).*/\1/p' | sed 's/.*/=&/' > $emergetempmv $emergetemp $emergelistcat $emergelist | xargs emerge -pecho -e "\nThese are the packages that will be installed.  If you want to alter this list,\njust edit the file 'emergelist' in $homedir. When finished, run\n'update-world --install'"}#### end piped ######## finished ##### Display closing messagesfinished (){echo -e "\n\nCongratulations!  'update-world' complete."elapsed_timeecho# All done! display the failed packages, if anyif [[ -z `cat $failedlist` ]]	then echo "All packages emerged successfully"	else echo "These packages couldn't be merged due to compile errors:"	echo	cat $failedlist	echo	echo -e "Look in $logdir/ for the portage log files of the failed builds.\nCheck bugs.gentoo.org or the Gentoo Forums for help."fiif [[ -n "$PORTAGE_ELOG_SYSTEM" ]]	then echo -e "\n * To review portage elog notices, type \"update-world --log\"\n"	else echo " * To enable portage notice viewing with elog, check out http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=3&chap=1#doc_chap4."fi}#### end finished ######## elapsed_time ##### just for fun let's see how long the process takes...elapsed_time (){after_time=`date +%s`time=$(( after_time - before_time ))days=$(( time / 86400 ))time=$(( time - ( days * 86400 ) ))hours=$(( time / 3600 ))time=$(( time - ( hours * 3600 ) ))minutes=$(( time / 60 ))time=$(( time - ( minutes * 60 ) ))seconds=$timeif [[ "$days" -eq 0 ]]	then days=""elif [[ "$days" -eq 1 ]]	then days="$days day, "elif [[ "$days" -gt 1 ]]	then days="$days days, "fiif [[ "$hours" -eq 0 ]]	then hours=""elif [[ "$hours" -eq 1 ]]	then hours="$hours hour, "elif [[ "$hours" -gt 1 ]]	then hours="$hours hours, "fiif [[ "$minutes" -eq 0 ]]	then minutes=""elif [[ "$minutes" -eq 1 ]]	then minutes="$minutes minute, and "elif [[ "$minutes" -gt 1 ]]	then minutes="$minutes minutes, and "fiseconds="$seconds seconds"echo -e "Total compiling time: $days$hours$minutes$seconds.\n"}#### end elapsed_time ######## What should the script do when invoked? ##### I have nine functions: displayhelp, empty, prepare, errorcheck, installworld, revdep, piped, elapsed_time, and finishedarguments="$@"# update-world --helpif [[ -n `echo "$arguments" | sed -n 's/-h/&/p'` || -n `echo "$arguments" | sed -n 's/--help/&/p'` ]]	then	displayhelp	exit 0	else :fi# update-world --emptyif [[ -n `echo -e \\t "$arguments" | sed -n 's/-e/&/p'` || -n `echo "$arguments" | sed -n 's/--empty/&/p'` ]]	then echo Preparing list of packages...	empty	prepare	exit 0	else :fi# update-world --prepareif [[ -n `echo "$arguments" | sed -n 's/-p/&/p'` || -n `echo "$arguments" | sed -n 's/--prepare/&/p'` ]]	then echo Preparing list of packages...	prepare	exit 0	else :fi# update-world --installif [[ -n `echo "$arguments" | sed -n 's/-[[:lower:]]*i/&/p'` || -n `echo "$arguments" | sed -n 's/--install/&/p'` ]]	then	installworld	check=true	else :fi# update-world --revdepif [[ -n `echo "$arguments" | sed -n 's/-[[:lower:]]*r/&/p'` || -n `echo "$arguments" | sed -n 's/--revdep/&/p'` ]]	then	revdep	if [[ -s "$emergelist" ]]		then installworld		else :	fi	check=true	else :fi# emerge -p <package> | update-world# piped command MUST include --pretend !!!if [[ "$arguments" = "" ]]	then echo "No arguments supplied.  If you're piping from the emerge command (emerge -p <package> | update-world), this is fine.  Otherwise, cancel and type 'update-world --help' for usage information."	until [[ `echo "$piped" | wc -l` -eq 10 ]] && [[ -z `echo "$piped" | grep 'Calculating dependencies'` ]] || [[ -z `echo "${piped:-1}" | tail -n 4` ]]	do read line	piped="${piped}$line"	done	else :fiif [[ -n `echo "$piped" | sed -n 's/Calculating\ dependencies/&/p'` ]]	then	piped	exit 0	else :fi# update-world --logif [[ -n `echo "$arguments" | sed -n 's/-l/&/p'` || -n `echo "$arguments" | sed -n 's/--log/&/p'` ]]then echo "Choose a date: "select directory in `ls -Al | grep ^d | sed 's/.*\ //'`do 	if [[ -n "$directory" ]]		then date=$directory		break		else echo "invalid selection"	fidonerm -f $homedir/$date/notice/logfor each in `ls $homedir/$date/notice/`do cat $homedir/$date/notice/$each >> $homedir/$date/notice/logdoneless $homedir/$date/notice/logcheck=trueexit 0else :fi# Check if arguments were validif [[ ${check:-false} == false ]]	then echo -e "Error: Invalid Command.\nRun 'update-world --help' for usage."	exit 1	else :fi# done! Display closing textfinishedexit 0