pfilter is a script that uses dialog (emerge dialog) to allow you to deselect some of the packages portage wants to emerge when you do something like an "emerge -up world". This is very useful if you have a full world-file you don't want to edit and use "emerge -u world" to keep your system up to date, but don't want to emerge all the things portage suggests at once. femerge is simple wrapper for emerge that will take the same options as emerge (but may die horribly if you try to use things like -C or -f yet) and lets you filter down the suggested packages repeatedly until you're happy and then emerge it.
The scripts are below - put the code in /usr/local/bin/pfilter and /usr/local/bin/femerge respectively, make them executable, and emerge dialog if you haven't got it installed.
To use pfilter by itself, do something like:
Code: Select all
# emerge -up world | pfilterCode: Select all
# emerge -up world | pfilter | xargs emerge -uCode: Select all
# femerge -u worldUpdate:femerge now passes options it doesn't recognise through to regular old emerge and exits.
Changelog:
2003-04-06: Fixed silly bug in femerge that was causing the final emerge step to break.
2003-04-06 (a little later): Fixed bug in pfilter that caused it to crash if there were no inputs (i.e. emerge -up XZY had nothing to update). Made femerge a little more aware of command line options.
2003-04-07: Decided to do it properly - the code has now been cleaned up and modularised significantly, femerge should now deal properly with --fetchonly/-f, and also handles compound options like "-uf". Also, it's possible to use another emerge wrapper (e.g. semerge) if it complies sufficiently with emerge's options by changing the variable $emerge_cmd at the top of the femerge script.
2003-04-07 (a little later): pfilter now remembers which version of a package is being emerged specifically (i.e. if you're trying to emerge a package that is not the latest non-masked one). Made femerge output prettier using the functions in /sbin/functions.sh.
2003-04-08: femerge now falls back on emerge for options it doesn't understand, meaning you can use it as a full wrapper for emerge. femerge will no longer add dependencies to the worldfile - only packages specified on the original command line, presuming they are not filtered out and --oneshot is not specified.
2003-04-23 Added -d option to pfilter that will deselect (rather than select) all packages by default. Pass -d to femerge for the same effect.
I'd be very grateful if people could test this more - it seems to work for me, and as long as you're not entirely wreckless, it should be pretty difficult to do any unintended damage with it.
pfilter 1.0:
Code: Select all
#!/bin/bash
# pfilter 1.0 by Martin Aspeli <optilude@gmx.net>
# Filter for Gentoo Linux (www.gentoo.org)'s Portage system, allowing you to
# select which packages from an emerge -p you wish to update. Takes output
# from emerge -p as its standard input, prints list of selected packages.
# Suggested use: # emerge -up world | pfilter | xargs emerge -u
# This will do an emerge -up world, then allow you to deselect any of the
# packages about to be installed (using dialog) and then do an emerge -u on
# those packages. Note that if you deselect a package which is a dependency
# of a selected package, it will still be installed.
# read from standard input and make items suitable for passing to dialog's
# checklist as checklist options.
select_packages=1
get_checklist_items () {
# Read input and break portage --pretend output into package and info
local line=""
# Read lines
while read line ; do
# ... find its parts: \1 = the status characters, \2 = name of package
# \3 = optionally version of installed package
if test "${select_packages}" = "1" ; then
echo "${line}" | grep "^\[ebuild " | \
sed 's/^\[ebuild \([^]]*\)] \([^[:space:]]*\)[[:space:]]\?\(.*\)$/\2 \"\1\3\" on/'
else
echo "${line}" | grep "^\[ebuild " | \
sed 's/^\[ebuild \([^]]*\)] \([^[:space:]]*\)[[:space:]]\?\(.*\)$/\2 \"\1\3\" off/'
fi
done
}
# display checklist (using dialog) of all the ebuilds given as command line
# options (output from get_checklist_items).
display_checklist () {
if test "${1}" = "" ; then
return 1
fi
# Display the checklist dialogue
eval "dialog --title 'Portage ebuild filter' --separate-output \
--checklist 'Select packages to install:' 0 0 0 ${@} 2>&1" || \
exit 1
}
# format ebuilds output by display_checklist by removing version info and
# double quotes.
format_ebuilds () {
for package in ${@} ; do
# print leading =
echo "=${package}"
done
}
print_help () {
echo "Usage: emerge -p [packages] | pfilter [options]"
echo
echo "Options:"
echo " -d Deselect packages by default"
echo " -h Display this message"
echo
}
init () {
select_packages=1
while getopts "d" opt ; do
case "${opt}" in
d)
select_packages=0
;;
*)
print_help && exit 1
;;
esac
done
}
init ${@}
# get the filtered packages from the checklist
packages=$(display_checklist $(get_checklist_items))
# if any selected, print them
test "${packages}" != "" && format_ebuilds ${packages} || exit 1
Code: Select all
#!/bin/bash
# femerge 1.0 by Martin Aspeli <optilude@gmx.net>
# pfilter-aware wrapper for Gentoo Linux (www.gentoo.org)'s emerge command,
# allowing you to select which packages from an emerge -p you wish to update.
# Takes the same options as emerge, but does not support things like unmerging,
# injecting or emerging only dependencies.
# An option -d is passed to pfilter, causing it to deselect packages by default.
# Suggested use: # femerge -up world
# This will do an emerge -up world, then allow you to deselect any of the
# packages about to be installed (using dialog) and then do an emerge -u on
# those packages. Note that if you deselect a package which is a dependency
# of a selected package, it will still be installed. You will be allowed to
# review what is going to be installed and make further adjustmenets or abort
# if necessary.
# Please ensure dialog and pfilter are both installed in your $PATH.
source /sbin/functions.sh
trap "error 'interrupted'" SIGINT SIGHUP SIGINT
###############################################################################
# Edit these if necessary (e.g. set final_emerge_cmd to semerge to use semerge)
emerge_cmd="emerge" # command used to get emerge -p output.
final_emerge_cmd="emerge" # command used to actually emerge the packages
pfilter_cmd="pfilter" # command used to filter the packages
world_file="/var/cache/edb/world"
###############################################################################
# Do not edit anything below this line
emerge_options="" # options to pass to emerge each time (affect
# dependencies)
final_emerge_options="" # further options to pass to emerge when actually
# emerging.
emerge_packages="" # initial list of packages/profile to emerge
pfilter_options="" # options to pass to pfilter each time
oneshot=0 # set to 1 to not touch world file
# print a message and exit
cancelled () {
ewarn "Cancelled."
echo
exit 0
}
# print an error message and exit
error () {
eend 1 "Error: ${1}"
exit 1
}
# print usage information and exit
usage () {
echo ""
echo "Usage: femerge [options] < packages >"
echo " femerge [options] < system | world >"
echo ""
echo "See emerge --help for more information."
exit 0
}
bad_option () {
eerror "Option ${1} not supported by femerge.">&2
}
# apply pfilter to the emerge-ouput passed as $1
filter_packages () {
echo "${1}" | ${pfilter_cmd} ${pfilter_options}
}
# do an emerge pretend with non-final options
preview_emerge () {
${emerge_cmd} -p ${emerge_options} ${@} || \
error "${emerge_cmd} -p ${emerge_options} ${@} failed."
}
# for all the builds passed as arguments, for the ones that were in the
# original list of packages, add them to the worldfile if necessary.
fix_worldfile () {
test "${oneshot}" = "1" && return 0
local ebuild=""
local short_ebuild=""
einfo "Amending ${world_file}"
for ebuild in ${@} ; do
short_ebuild=$(echo ${ebuild} | sed -e 's/-r[0-9]\+$//' \
-e 's/-[0-9][^-]*$//' -e 's/^=//')
if echo "${emerge_packages}" | grep -qs "${short_ebuild##*/}" && \
! grep -qs "${short_ebuild}" ${world_file} ; then
einfo " Adding: ${short_ebuild}"
echo "${short_ebuild}" >> ${world_file}
fi
done
}
# get options from command line and place in the three variables $emerge_options
# (options to pass to emerge when determining dependencies),
# $final_emerge_options (options that should only be passed to emerge when
# actually emerging) and $emerge_packages (what's being emerged)
get_options () {
local goahead=0
# Get options
while true ; do
case "${1}" in
-h|--help|--usage)
usage
;;
--columns|--nospinner|-q|--quiet)
;;
--oneshot)
oneshot=1
;;
--buildpkg|-b|--buildpkgonly|-B|--fetchonly|-f|--noconfmem|\
--oneshot|--resume|--usepkg|-k|--usepkgonly|-K)
final_emerge_options="${final_emerge_options} ${1}"
;;
--deep|-D|--emptytree|-e|--nodeps|-O|--noreplace|-n|--update|\
-u|--upgradeonly|-U)
emerge_options="${emerge_options} ${1}"
;;
-d)
pfilter_options="${pfilter_options} ${1}"
;;
--*)
bad_option ${1}
goahead=1
;;
-?)
bad_option ${1}
goahead=1
;;
-*) # Multiple one-letter options in one...
local options="${1#-}"
# Deal with -h and -q
echo ${options} | grep -qs "h" && usage
options=${options//q/}
# Deal with final options - remove anything from $options that's not
# b, B, f, k or K
local final_options=$(echo "${options}" | sed s/[^bBfkK]//g)
test "${final_options}" != "" &&
final_emerge_options="${final_emerge_options} -${final_options}"
# Do the same to $emerge_options for D, e, O, n, u or U
local normal_options=$(echo "${options}" | sed s/[^DeOnuU]//g)
test "${normal_options}" != "" &&
emerge_options="${emerge_options} -${normal_options}"
# Then do -d for pfilter
local filter_options=$(echo "${options}" | sed s/[^d]//g)
test "${filter_options}" != "" &&
pfilter_options="${pfilter_options} -${filter_options}"
local unknown_options=$(echo "${options}" | \
sed s/[${final_options}${normal_options}${filter_options}]//g)
test "${unknown_options}" != "" && \
bad_option "-${unknown_options}" && goahead=1
;;
clean|depclean|info|inject|prune|regen|search|unmerge|sync|rsync)
bad_option ${1}
goahead=1
;;
*)
test "${1}" != "" && emerge_packages="${emerge_packages} ${1}"
;;
esac
shift || break
done
return ${goahead}
}
# Main:
# Get emerge command line options and packages/profile to emerge
if ! get_options ${@} ; then
ewarn "Falling back on ${final_emerge_cmd}"
${final_emerge_cmd} ${@}
exit ${?}
fi
test "${emerge_packages}" = "" && usage
einfo "Calculating dependencies..."
emerge_output=$(preview_emerge ${emerge_packages})
packages=""
# loop until exit by abort or emerge
while true ; do
# Filter the packages we have so far"
packages=$(filter_packages "${emerge_output}")
test "${packages}" = "" && cancelled
# Preview the emerge
einfo "Calculating dependencies..."
emerge_output=$(preview_emerge ${packages})
echo "${emerge_output}"
echo
# Ask for action
choice=""
until test "${choice}" = "e" -o "${choice}" = "E" -o \
"${choice}" = "f" -o "${choice}" = "F" -o \
"${choice}" = "a" -o "${choice}" = "A" ; do
einfon "Press (e) to emerge, (f) to filter again, (a) to abort: "
read choice
echo
case "${choice}" in
a|A)
cancelled
;;
f|F)
# do nothing - allow next filtering
;;
e|E)
ebegin "Running ${final_emerge_cmd}..."
${final_emerge_cmd} --oneshot ${emerge_options} \
${final_emerge_options} ${packages} &&
fix_worldfile ${packages}
echo
exit 0
;;
*)
eerror "Invalid input."
;;
esac
done
done
Martin




