1#!/bin/bash
2
3# wnpp-alert -- check for installed packages which have been orphaned
4#               or put up for adoption
5
6# This script is in the PUBLIC DOMAIN.
7# Authors:
8# Arthur Korn <arthur@korn.ch>
9
10# Arthur wrote:
11# Get a list of packages with bugnumbers. I tried with LDAP, but this
12# is _much_ faster.
13# And I (Julian) tried it with Perl's LWP, but this is _much_ faster
14# (startup time is huge).  And even Perl with wget is slower by 50%....
15
16set -e
17
18PROGNAME="${0##*/}"
19# TODO: Remove use of OLDCACHEDDIR post-Stretch
20OLDCACHEDIR=~/.devscripts_cache
21OLDCACHEDDIFF="${OLDCACHEDIR}/wnpp-diff"
22CACHEDIR=${XDG_CACHE_HOME:-~/.cache}
23CACHEDIR=${CACHEDIR%/}/devscripts
24CACHEDDIFF="${CACHEDIR}/wnpp-diff"
25CURLORWGET=""
26GETCOMMAND=""
27
28usage () { echo \
29"Usage: $PROGNAME [--help|-h|--version|-v|--diff|-d] [package ...]
30  List all installed (or listed) packages with Request for
31  Adoption (RFA), Request for Help (RHF), or Orphaned (O)
32  bugs against them, as determined from the WNPP website.
33  https://www.debian.org/devel/wnpp"
34}
35
36version () { echo \
37"This is $PROGNAME, from the Debian devscripts package, version ###VERSION###
38This script is in the PUBLIC DOMAIN.
39Authors: Arthur Korn <arthur@korn.ch>
40Modifications: Julian Gilbey <jdg@debian.org>"
41}
42
43wnppdiff () {
44    if [ -f "$OLDCACHEDDIFF" ]; then
45        mv "$OLDCACHEDDIFF" "$CACHEDDIFF"
46    fi
47    if [ ! -f "$CACHEDDIFF" ]; then
48        # First use
49        comm -12 $WNPP_PACKAGES $INSTALLED | sed -e 's/+/\\+/g' | \
50          xargs -i grep -E '^[A-Z]+ [0-9]+ {} ' $WNPP | \
51          tee $CACHEDDIFF
52    else
53        comm -12 $WNPP_PACKAGES $INSTALLED | sed -e 's/+/\\+/g' | \
54          xargs -i grep -E '^[A-Z]+ [0-9]+ {} ' $WNPP > $WNPP_DIFF
55        sort -o $CACHEDDIFF $CACHEDDIFF
56        sort -o $WNPP_DIFF $WNPP_DIFF
57        comm -3 $CACHEDDIFF $WNPP_DIFF | \
58          sed -e 's/\t/\+/g' -e 's/^\([^+]\)/-\1/g'
59        mv $WNPP_DIFF $CACHEDDIFF
60    fi
61}
62
63if [ "x$1" = "x--help" -o "x$1" = "x-h" ]; then usage; exit 0; fi
64if [ "x$1" = "x--version" -o "x$1" = "x-v" ]; then version; exit 0; fi
65
66if command -v wget >/dev/null 2>&1; then
67    CURLORWGET="wget"
68    GETCOMMAND="wget -q -O"
69elif command -v curl >/dev/null 2>&1; then
70    CURLORWGET="curl"
71    GETCOMMAND="curl -qfs -o"
72else
73    echo "$PROGNAME: need either the wget or curl package installed to run this" >&2
74    exit 1
75fi
76
77
78# Let's abandon this directory from now on, these files are so small
79# (see bug#309802)
80if [ -d "$CACHEDIR" ]; then
81    rm -f "$CACHEDIR"/orphaned "$CACHEDIR"/rfa_bypackage
82fi
83
84INSTALLED=$(mktemp --tmpdir wnppalert-installed.XXXXXX)
85WNPP=$(mktemp --tmpdir wnppalert-wnpp.XXXXXX)
86WNPPTMP=$(mktemp --tmpdir wnppalert-wnpp.XXXXXX)
87WNPP_PACKAGES=$(mktemp --tmpdir wnppalert-wnpp_packages.XXXXXX)
88trap 'rm -f "$INSTALLED" "$WNPP" "$WNPPTMP" "$WNPP_PACKAGES"' EXIT
89
90if [ "x$1" = "x--diff" ] || [ "x$1" = "x-d" ]; then
91    shift
92    WNPP_DIFF=$(mktemp --tmpdir wnppalert-wnpp_diff.XXXXXX)
93    trap 'rm -f "$INSTALLED" "$WNPP" "$WNPPTMP" "$WNPP_PACKAGES" "$WNPP_DIFF"' \
94        EXIT
95fi
96
97# Here's a really sly sed script.  Rather than first grepping for
98# matching lines and then processing them, this attempts to sed
99# every line; those which succeed execute the 'p' command, those
100# which don't skip over it to the label 'd'
101$GETCOMMAND $WNPPTMP https://www.debian.org/devel/wnpp/orphaned || \
102    { echo "$PROGNAME: $CURLORWGET https://www.debian.org/devel/wnpp/orphaned failed" >&2; exit 1; }
103sed -ne 's/.*<li><a href="https\?:\/\/bugs.debian.org\/\([0-9]*\)">\([^:<]*\)[: ]*\([^<]*\)<\/a>.*/O \1 \2 -- \3/; T d; p; : d' $WNPPTMP > $WNPP
104
105$GETCOMMAND $WNPPTMP https://www.debian.org/devel/wnpp/rfa_bypackage || \
106    { echo "$PROGNAME: $CURLORWGET https://www.debian.org/devel/wnpp/rfa_bypackage" >&2; exit 1; }
107sed -ne 's/.*<li><a href="https\?:\/\/bugs.debian.org\/\([0-9]*\)">\([^:<]*\)[: ]*\([^<]*\)<\/a>.*/RFA \1 \2 -- \3/; T d; p; : d' $WNPPTMP >> $WNPP
108
109$GETCOMMAND $WNPPTMP https://www.debian.org/devel/wnpp/help_requested || \
110    { echo "$PROGNAME: $CURLORWGET https://www.debian.org/devel/wnpp/help_requested" >&2; exit 1; }
111sed -ne 's/.*<li><a href="https\?:\/\/bugs.debian.org\/\([0-9]*\)">\([^:<]*\)[: ]*\([^<]*\)<\/a>.*/RFH \1 \2 -- \3/; T d; p; : d' $WNPPTMP >> $WNPP
112
113cut -f3 -d' ' $WNPP | sort > $WNPP_PACKAGES
114
115# A list of installed files.
116
117if [ $# -gt 0 ]; then
118    echo $* | tr ' ' '\n' | sort -u > $INSTALLED
119else
120    dpkg-query -W -f '${Package} ${Status}\n${Source} ${Status}\n' | \
121        awk '/^[^ ].*install ok installed/{print $1}' | \
122        sort -u \
123        > $INSTALLED
124fi
125
126if [ -f "$WNPP_DIFF" ]; then
127    # This may fail when run from a cronjob (c.f., #309802), so just ignore it
128    # and carry on.
129    mkdir -p "$CACHEDIR" >/dev/null 2>&1 || true
130    if [ -d "$CACHEDIR" ] || [ -d "$OLDCACHEDIR" ]; then
131        wnppdiff
132        exit 0
133    else
134        echo "$PROGNAME: Unable to create diff; displaying full output"
135    fi
136fi
137
138comm -12 $WNPP_PACKAGES $INSTALLED | sed -e 's/+/\\+/g' | \
139xargs -i grep -E '^[A-Z]+ [0-9]+ {} ' $WNPP
140