Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 9ac03fe2e1
Fetching contributors…

Cannot retrieve contributors at this time

197 lines (175 sloc) 6.022 kb
# The `rpg-list` program compares installed packages to packages available
# in the remote repository. It's useful for determining the versions of
# packages and how they relate to same named packages available in the
# repository.
# This is somewhere between a plumbing and porcelain command. It's useful
# for building other programs and provides options for generating easily
# parseable output. However, it's also useful to humans and the default
# output is optimize for human consumption.
set -e
. rpg-sh-setup
USAGE '${PROGNAME} [-u] [-a] [-p|-s] [<glob>...]
List installed and/or available packages.
Passing one or more <glob>s filters the list to matching packages.
-a Include packages available but not installed
-l Long list format: show package status and version fields
-p Generate easily parseable output
-u Sync the package index with remote repository first'
while getopts alpus opt
case $opt in
a) all=true
l) long=true;;
u) sync=true;;
p) long=true;
?) helpthem;
exit 2;;
shift $(( $OPTIND - 1 ))
# Sync the package index. Force the sync right now if we were given
# the `-u` arg; otherwise, maybe update it based on the configured stale
# time.
if $sync
then rpg-sync
else rpg-sync -s
# Parsey Mode
# -----------
# The `-p` argument causes the output to be varied slightly. These variables
# control how output lines are formatted and what symbols they use. In
# parsey mode, simple alpha characters are used since those are a bit easier
# to `grep` / `sed` without escaping.
if $parsey
then st_outdate="o"
st_format="%s %s %s %s\n"
st_up2date=" "
st_format="%1s %-35s %-12s %-12s\n"
# Package Selection / Glob Filter
# -------------------------------
# Default to matching all installed packages -- or all available packages
# when `-a` was given -- if no `<glob>`s were given.
[ "$*" ] || set -- '*'
# Build glob BREs for filtering the remote package list. The local package
# list is filtered by `rpg-package-index` so we don't need to worry about that
# side.
# If there's only one glob and it's `*`, don't do any `grep` nonsense,
# just throw a `cat` in there.
if [ "$*" = '*' ]
then remotefilter="cat"
else remotefilter="grep"
for glob in "$@"
do glob=$(
echo "$glob" |
sed -e 's@\*@[^ ]*@g' -e 's/\?/[^ ]/g'
remotefilter="$remotefilter -e '^$glob ' -e ' $glob\$'"
# Main Pipeline
# -------------
# Kick off a pipeline by listing installed packages. The output from
# `rpg-package-index` looks something like this:
# RedCloth 4.2.3
# abstract 1.0.0
# actionmailer 2.3.5
# actionpack 2.3.5
# activerecord 2.3.5
# activeresource 2.3.5
# activesupport 2.3.5
# ansi 1.1.0
# builder 2.1.2
# classifier 1.3.1
# coffee-script 0.3.2
# ...
# So we have the `<package> <version>` pairs separated by whitespace,
# basically.
rpg-package-index -x "$@" |
# Okay ...
# This is going to blow your mind.
# Use `join(1)` to perform a relational join between the installed
# package list and the recent release list from the index. The recent
# release list looks nearly identical, format-wise, to the installed
# list.
# There's a few things needed for this to work properly. First, both
# files need to be sorted (as with `sort -b`) on the join field. Here,
# the join field is the `<package>` -- we don't need to specify it
# explicitly on the command line because it's the first field in both
# files.
# The stream text that comes out of `join(1)` looks like:
# <package> <installed-version> <available-version>
# Without any other options, `join(1)` performs an "inner join",
# excluding unpaired lines from output entirely. Which is great because
# that's exactly what we need to determine which packages are out of
# date.
# This is a really insanely fast operation because it need only take a
# single pass over each file. It simply walks through each file line by
# line and, because both files are sorted, knows immediately whether the
# lines intersect or are unpairable.
# Additional, we selectively enable some of `join(1)`'s other options (`-a`
# and `-e`) for achieving "outer joins" and "full joins" when querying
# against all remote packages.
join -a 1 $joiner \
-o 1.1,1.2,2.2,2.1 \
-e '-' \
- "$RPGINDEX/release-recent" |
# Grep out remote packages based on our globs. See the *Glob Filter* section
# above for more information.
/bin/sh -c "exec $remotefilter" |
# Grep out lines that don't match a package. Also, the regular expression
# is amazing.
grep -v '. - - .' |
# All that's left is to read the output from `join` and apply some light
# formatting.
if ! $long
if $all
then awk '$4 != "-" { print $4, $3; }'
else awk '$2 != "-" { print $1, $2; }'
while read package curvers recvers pdup
test "$package" = '-' &&
if test "$recvers" = '-'
then sig="$st_missing"
elif test "$curvers" = "-"
then sig="$st_missing"
elif test "$curvers" = "$recvers"
then sig="$st_up2date"
else sig="$st_outdate"
printf "$st_format" "$sig" "$package" "$curvers" "$recvers"
Jump to Line
Something went wrong with that request. Please try again.