Hello,
Inspired by my recent love affair with dialog (http://forums.gentoo.org/viewtopic.php?t=45827, which I now use almost every day), I decided to make another tool I've been missing: pbrowser is an ebuild browser that by default looks in your portage and portage overlay directories, and lets you browse through all the packages there. You can select and deselect packages until you're happy with them, and the selected packages will be printed to the screen when you press "Done". Here are some places where this may be useful:
- To simply see what packaes are in portage, browsing through portage directories and viewing the description of each package, run:
Code: Select all
$ pbrowser - To do the same thing, but only view installed packages, and their versions, run:
Code: Select all
$ pbrowser -i - To select some packages to emerge and then emerge then, run: (note the use of backticks!)
Code: Select all
# emerge `pbrowser` - To have more control, combine this with my femerge script (http://forums.gentoo.org/viewtopic.php?t=45827), which will let you deselect packages you don't wish to emerge after all: (note the use of backticks!)
Code: Select all
# femerge `pbrowser` - If you don't want to use femerge, but want the chance to cancel before installing, use the bemerge script below: (any options to bemerge are passed straight through to emerge, with the exception of -i and -s which is passed to pbrowser, so you'll have to use --inject instead of -i and search instead of -s with bemerge)
Code: Select all
# bemerge --upgradeonly - To select some installed packages and unmerge them, run: (note the use of backticks!)
Code: Select all
# emerge unmerge `pbrowser -i` - Or, more concicely:
Code: Select all
# bemerge -i unmerge - To create a custom world file containing only packages you wish to keep track of when doing an emerge -u world, run: Make sure the file new_world is what you want, and replace /var/cache/edb/world with it (it would be a good idea to do a backup of /var/cache/edb/world first!)
Code: Select all
# pbrowser -s > new_world - To do the same thing, but only consider currently installed packages, run: (the -i option normally lists packages as they exist in /var/db/pkg, that is with version numbers and revisions appended - the -s option strips the version and revision information from the output).
Code: Select all
# pbrowser -is > new_world
Changelog:
2003-04-21: Changed name from ebb to pbrowser to avoid possible naming conflict.
2003-04-29: pbrowser now displays installed versions of packages when not using the -i option. Pass -d to pbrowser or bemerge to override. New "Try emerge" option: Select a package and see the output of "emerge -p <package>".
2003-05-27: Er.... I tried to use pbrowser today and for some obscure reason it'd stopped working. I traced the problem to dialog not outputting "HELP" when you press the Done button (which is really just a disguised help button) - and I SWEAR it used to do that! Anyway, it now uses the return error code from dialog, which should be safer anyhow... Sorry about that!
2003-06-13: Fixed minor bug whereby output would be muddled if a directory was empty.
Known bugs:
* If you enter a directory, select or deselect some packages and then use using the "Try emerge" option, your changes are lost. As far as I can tell, this is a bug in dialog (there is no way to find out what the user had selected in a dialog --checklist if HELP is pressed).
* Some ebuilds have DESCRIPTION variables that reference other variables (e.g. $PV for current version). These will not be displayed correctly by pbrowser.
Place the two scripts below in /usr/local/bin/pbrowser and /usr/local/bin/bemerge respectively, and make sure you have dialog installed (emerge dialog).
pbrowser 1.2:
Code: Select all
#!/bin/bash
# pbrowser (portage browser) 1.2 by Martin Aspeli <optilude@gmx.net>
# Selector for Gentoo Linux (www.gentoo.org)'s portage system. Iterates
# through all packages in your portage directory (/usr/portage) and your portage
# overlay directory (/usr/local/portage) as defined in /etc/make.globals and
# /etc/make.conf, if applicable, and allows you to select and de-select packages
# from all directories in the portage hierarchy. When you finally select Done,
# the selected packages are printed to the standard output, one per line.
# Suggested use: # pbrowser | xargs emerge
# or: # emerge `pbrowser`
# This will let you select packages to emerge interactively, and then emerge
# them. pbrowser can also be used to generate a new world file to replace the one
# in /var/cache/edb/world:
# Suggested use: # pbrowser > new_world
# Then examine new_world and replace /var/cache/edb/world with it if you wish.
# Please be careful with replacing a world file you don't want to lose!
# You can also use pbrowser to browse installed packages only instead of all
# packages in portage, by supplying the -i option. This will let you browse all
# versions of all installed packages. By default, version information is printed
# for selected packages. Supply -s option to suppress version numbers.
# Normally, pbrowser will show the installed versions of any packages when
# browsing the portage tree (without -i). To suppress this, pass the -d option.
source /sbin/functions.sh
make_globals="/etc/make.globals" # The make.globals file
make_conf="/etc/make.conf" # The make.conf file
pkg_db="/var/db/pkg" # Hierarchy of installed packages
################################################################################
view_installed_versions=1 # Whether to view installed versions
tmpfile=/tmp/${$} # Temporary file
################################################################################
# buld input suitable for a dialog --menu of the directories in portage
build_directories_menu () {
if test -n "${overlay_dir}" ; then
find ${portage_dir} ${overlay_dir} \
-type d -name "*-*" -maxdepth 1 -mindepth 1 2>/dev/null | \
sed -e "s#${portage_dir}\(.\+\)\$#\1 \"-->\"#" \
-e "s#${overlay_dir}\(.\+\)\$#\1 \"-->\"#" | sort | uniq
else
find ${portage_dir} -type d -name "*-*" -maxdepth 1 -mindepth 1 | \
sed -e "s#${portage_dir}\(.\+\)\$#\1 \"-->\"#" | sort | uniq
fi
}
# find the description for the package given as an argument, use the newest
# .ebuild if several exist
find_description () {
local ebuild_glob="${portage_dir}${1}/*.ebuild"
test -n "${overlay_dir}" && \
ebuild_glob="${ebuild_glob} ${overlay_dir}${1}/*.ebuild"
local ebuild=$(ls ${ebuild_glob} --sort=time 2>/dev/null | head -n 1)
local desc=""
if test -z "${ebuild}" ; then
echo "(No ebuilds found)"
elif test -r "${ebuild}" ; then
desc=$(grep "DESCRIPTION=" "${ebuild}" | sed 's/DESCRIPTION="\(.\+\)"/\1/')
test -n "${desc}" && echo "${desc}" || echo "(Description not found)"
else
echo "(Description not found)"
fi
}
# Find all installed versions of package $1/$2 ($1 = directory, $2 = package,
# without version).
find_installed_versions () {
directory="${pkg_db%/}/${1}"
find ${directory} -mindepth 1 -maxdepth 1 \
-regex "${directory}/${2}-[0-9].*" | \
grep -oe '-[[:digit:]].*$' | sed 's/^-//'
}
# build input suitable for a dialog --checklist of the packages in the
# directory specified as first argument; second argument is string of
# currently selected packages.
build_packages_checklist () {
local package=""
for package in $(find ${portage_dir}${1}/ ${overlay_dir}${1}/ \
-type d -maxdepth 1 -mindepth 1 2>/dev/null | sort | uniq) ; do
package=${package##*/}
local description=$(find_description "${1}/${package}")
description=${description//\'/}
local version_str=""
# If we're not viewing installed packages, get string of installed
# versions.
if test "${view_installed_versions}" = "1" ; then
local version=""
for version in $(find_installed_versions ${1} ${package}) ; do
version_str="${version_str}${version}, "
done
test "${version_str}" != "" &&
version_str="[${version_str%, }] " ||
version_str="[n/i] "
fi
# find out if we should mark this package as selected
local onoff="off"
echo "${2}" | grep -qs "${1}/${package}" && onoff="on"
echo "${package} '${version_str}${description}' ${onoff} '${package}: ${description}'"
done
}
# display select dialog --menu with directories specified as arguments; print
# DONE if user selected Done, nothing if user selected cancel, or the selected
# directory, if user selected OK; first argument is directory to select by
# default
display_directories_select () {
default_item=${1}
shift
# We're cheating - calling the help item for done and fixing the output...
eval "dialog --title 'pbrowser: ebuild Browser' \
--help-button --help-label 'Done' \
--default-item \"${default_item}\" \
--menu 'Directories:' 0 0 0 ${@} 2>&1"
return ${?}
}
# display package-selecting dialog --checklist; first argument is name of
# directory, subsequent options are --checklist items.
display_packages_select () {
local directory=${1}
shift
if test -z "${1}" ; then
dialog --title 'pbrowser: Portage Browser' \
--msgbox "No packages found." 0 0
else
eval "dialog --title 'pbrowser: Portage Browser' \
--help-button --help-label 'Try emerge' \
--separate-output \
--item-help \
--checklist \"Packages in ${directory}:\" 0 0 0 ${@} 2>&1"
return ${?}
fi
}
update_selection () {
local all="${1}"
local directory="${2}"
# prepend $directory to each part of $3 and call in $new
local new=""
for package in ${3} ; do
test -n "${new}" &&
new="${new} ${directory}/${package}" ||
new="${directory}/${package}"
done
# remove all packages in same directory that were not selected
for package in $(echo "${all}" | \
grep -o "${directory}/[^[:space:]]\+"); do
echo "${new}" | grep -qs "${package}" || all=${all//${package}/}
done
# add each newly selected package to $all if necessary
for package in ${new} ; do
echo "${all}" | grep -qs "${package}" || all="${all} ${package}"
done
echo "${all}"
}
# Try emerge -p for a package ($1 = directory, $2 = package name)
try_emerge () {
local directory="${1}"
local package="${2}"
local emerge=""
# strip version number
package=$(echo "${package}" | sed -e 's/-r[0-9]\+$//' -e 's/-[0-9][^-]*$//')
emerge -p ${directory}/${package} > ${tmpfile}
dialog --backtitle "Running emerge -p ${directory}/${package}..." \
--textbox "${tmpfile}" 15 76
rm -rf ${tmpfile} 2>/dev/null
}
# print all the selected packages (arguments), one on each line
print_all_selected () {
local package=""
for package in ${@} ; do
if test "${strip_versions}" = "1" ; then
echo "${package}" | sed -e 's/-r[0-9]\+$//' -e 's/-[0-9][^-]*$//'
else
echo ${package}
fi
done
}
print_help () {
echo "Usage: pbrowser [options]"
echo
echo "Options:"
echo " -i Browse installed packages"
echo " -s Strip version numbers when printing installed packages"
echo " -d Don't view installed versions of packages"
echo " -h Display this message"
echo
}
init () {
# Get configuration files
source ${make_globals}
source ${make_conf}
view_installed_versions="1"
# Parse command line options
while getopts "hisd" opt ; do
case "${opt}" in
h)
print_help
exit 0
;;
i)
portage_dir="${pkg_db%/}/"
overlay_dir=""
view_installed_versions="0"
;;
s)
strip_versions=1
;;
d)
view_installed_versions="0"
;;
*)
print_help && exit 1
;;
esac
done
# default to PORTDIR
if test -z "${portage_dir}" ; then
portage_dir="${PORTDIR%/}/"
test -d "${PORTDIR_OVERLAY}" && overlay_dir="${PORTDIR_OVERLAY%/}/"
fi
# make sure it exists
if ! test -d "${portage_dir}" ; then
echo "Portage directory ${portage_dir} not found!"
exit 1
fi
}
portage_dir=""
overlay_dir=""
all_selected=""
strip_versions=0
init ${@}
directories_menu=$(build_directories_menu)
directory=""
package=""
value=""
while true ; do
directory=$(display_directories_select "${directory}" ${directories_menu})
value="${?}"
test "${value}" = "1" && exit 0
if test "${value}" = "2" ; then
print_all_selected ${all_selected} | sort | uniq
exit 0
fi
packages=$(build_packages_checklist "${directory}" "${all_selected}")
while true ; do
selected=$(display_packages_select "${directory}" ${packages})
value="${?}"
test "${value}" = "1" && break
if echo "${selected}" | grep -qs "^HELP" ; then
package="${selected#HELP }"
package="${package%%:*}"
try_emerge "${directory}" "${package}"
else
all_selected=$(update_selection "${all_selected}" \
"${directory}" "${selected}")
break
fi
done
done
Code: Select all
#!/bin/bash
# bemerge 1.1 by Martin Aspeli <optilude@gmx.net>
# Simple wrapper for emerge that lets you chooce packages using pbrowser.
# -i or -s options are passed to pbrowser if supplied, all other options are
# passed straight to emerge. The output of emerge -p will be displayed and you
# may cancel before running emerge for real.
# Suggested use: # bemerge -U
# # bemerge -i unmerge
# The first will let you choose packages to emerge using pbrowser, and then
# upgrade those packages if possible. The second will let you choose among
# installed packages and unmerge those.
# Please ensure dialog and pbrowser are both installed and in your $PATH
source /sbin/functions.sh
pbrowser_options=""
emerge_options=""
# Get options: Let -i and -d pass to pbrowser, all other to emerge
while true ; do
case "${1}" in
-d|-i|-di|-id)
pbrowser_options="${pbrowser_options} ${1}"
;;
-p|--pretend) # ignore - we pass -p to emerge when necessary
;;
*)
emerge_options="${emerge_options} ${1}"
;;
esac
shift || break;
done
builds=$(pbrowser ${pbrowser_options})
test -n "${builds}" || exit 0 # cancelled
emerge -p ${emerge_options} ${builds} || exit 1
choice=""
until test "${choice}" = "e" -o "${choice}" = "E" -o \
"${choice}" = "a" -o "${choice}" = "A" ; do
einfon "Press (e) to emerge, (a) to abort: "
read choice
case "${choice}" in
a|A)
;;
e|E)
emerge ${emerge_options} ${builds}
exit ${?}
;;
*)
eerror "Invalid input."
;;
esac
done
Martin



