1#!/bin/sh -e
2#
3#    updates_available: calculate and cache the number of updates available
4#
5#    Copyright (C) 2008 Canonical Ltd.
6#    Copyright (C) 2011-2014 Dustin Kirkland
7#
8#    Authors: Dustin Kirkland <kirkland@byobu.org>
9#
10#    This program is free software: you can redistribute it and/or modify
11#    it under the terms of the GNU General Public License as published by
12#    the Free Software Foundation, version 3 of the License.
13#
14#    This program is distributed in the hope that it will be useful,
15#    but WITHOUT ANY WARRANTY; without even the implied warranty of
16#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17#    GNU General Public License for more details.
18#
19#    You should have received a copy of the GNU General Public License
20#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22___print_updates() {
23	local u= s=
24	read u s < "$1"
25	if [ -n "$u" ]; then
26		if [ "$u" -gt 0 ]; then
27			color b r W; printf "%d" "$u"; color -; color r W
28			if [ -n "$s" ] && [ "$s" -gt 0 ]; then
29				printf "$ICON_SECURITY"
30			else
31				printf "$ICON_UPDATES"
32			fi
33			color --
34		elif [ "$u" = "0" ] && [ -e "$BYOBU_RUN_DIR/status.$BYOBU_BACKEND/updates_available" ]; then
35			# Clear out byobu's status cache
36			rm -f "$BYOBU_RUN_DIR/status.$BYOBU_BACKEND/updates_available"*
37		fi
38	fi
39}
40
41___update_cache() {
42	local mycache=$1 flock="$1.lock"
43	# Now we actually have to do hard computational work to calculate updates.
44	# Let's try to be "nice" about it:
45	renice 10 $$ >/dev/null 2>&1 || true
46	ionice -c3 -p $$ >/dev/null 2>&1 || true
47	# These are very computationally intensive processes.
48	# Background this work, have it write to the cache files,
49	# and let the next cache check pick up the results.
50	# Ensure that no more than one of these run at a given time
51	if [ -x /usr/lib/update-notifier/apt-check ]; then
52		# If apt-check binary exists, use it
53		flock -xn "$flock" sh -c "(/usr/lib/update-notifier/apt-check 2>&1 | awk '-F;' 'END { print \$1, \$2 }' >\"${mycache}-x\" 2>/dev/null ; mv \"${mycache}-x\" \"$mycache\")" &
54	elif eval $BYOBU_TEST apt-get >/dev/null; then
55		# If apt-get exists, use it
56		flock -xn "$flock" apt-get -s -o Debug::NoLocking=true upgrade | grep -c ^Inst >$mycache 2>/dev/null &
57	elif eval $BYOBU_TEST pkcon >/dev/null; then
58		# use packagekit to show list of packages
59		LC_ALL=C flock -xn "$flock" pkcon get-updates -p | awk '/^Results:$/ { start=NR }; /^Security/ { security++ }; END { if (!/There are no updates available at this time./) { print NR-start, security }}' > "$mycache" 2>/dev/null &
60	elif eval $BYOBU_TEST zypper >/dev/null; then
61		# If zypper exists, use it
62		flock -xn "$flock" zypper --no-refresh lu --best-effort | grep -c 'v |' >$mycache 2>/dev/null &
63	elif eval $BYOBU_TEST yum >/dev/null; then
64		# If yum exists, use it
65		# TODO: We need a better way of counting updates available from a RH expert
66		flock -xn "$flock" yum list updates -q | grep -vc "Updated Packages" >$mycache 2>/dev/null &
67	elif eval $BYOBU_TEST pacman >/dev/null; then
68		# If pacman (Archlinux) exists, use it
69		LC_ALL=C flock -xn "$flock" pacman -Sup | grep -vc "^\(::\| \)" >$mycache 2>/dev/null &
70	elif eval $BYOBU_TEST opkg >/dev/null; then
71		# If opkg (OpenWrt) exists, use it, also background if flock exists
72		if eval $BYOBU_TEST flock >/dev/null; then
73			flock -xn "$flock" opkg list-upgradable | wc -l >$mycache 2>/dev/null &
74		else
75			opkg list-upgradable | wc -l >$mycache &
76		fi
77	elif eval $BYOBU_TEST brew >/dev/null; then
78		# If homebrew (Mac OSX) exists, use it, also background if flock exists
79		if eval $BYOBU_TEST flock >/dev/null; then
80			flock -xn "$flock" brew outdated | wc -l >$mycache 2>/dev/null &
81		else
82			brew outdated | wc -l >$mycache &
83		fi
84	fi
85}
86
87___update_needed() {
88	# Checks if we need to update the cache.
89	# TODO: add more distro
90	local mycache=$1
91	# The cache doesn't exist: create it
92	[ ! -e "$mycache" ] && return 0
93	if eval $BYOBU_TEST apt-get >/dev/null; then
94		# Debian/ubuntu
95		d0=$(($(stat -c %Y $mycache 2>/dev/null)-5))
96		d1=$(stat -c %Y /var/lib/apt)
97		d2=$(stat -c %Y /var/lib/apt/lists)
98		d3=$(stat -c %Y /var/log/dpkg.log)
99		now=$(date +%s)
100		delta=$(($now-$d0))
101		if [ $d0 -lt 0 ] || [ $d0 -lt $d1 ] || [ $d0 -lt $d2 ] || [ $d0 -lt $d3 ] || [ 3605 -lt $delta ] ; then
102			return 0
103		else
104			return 1
105		fi
106	elif [ -e "/var/lib/PackageKit/transactions.db" ]; then
107		[ "/var/lib/PackageKit/transactions.db" -nt "$mycache" ]
108		return $?
109	elif eval $BYOBU_TEST pacman >/dev/null; then
110		# Archlinux
111		local db
112		for db in /var/lib/pacman/sync/*.db; do
113			[ "$db" -nt "$mycache" ] && return 0
114		done
115		return 1
116	elif eval $BYOBU_TEST opkg >/dev/null; then
117		# OpenWrt
118		[ ! -e /var/lock/opkg.lock ] || return 1
119		if [ -d /var/opkg-lists ]; then
120			[ /var/opkg-lists -nt "$mycache" ]
121			return $?
122		else
123			local u s
124			read u s < "$mycache"
125			[ "$u" -gt 0 ]
126			return $?
127		fi
128	elif eval $BYOBU_TEST brew >/dev/null; then
129		# Mac OSX
130		# check if any new versions have been installed since
131		# we last cached. this may not recognize formulae
132		# installed with HEAD
133		for f in $(brew --prefix)/Cellar/*; do
134			[ "$f" -nt "$mycache" ] && return 0
135		done
136		# nothing new has been installed, so check wether the
137		# formulae database was updated
138		[ "$(brew --prefix)/Library/Formula" -nt "$mycache" ]
139		return $?
140	fi
141	return 1
142}
143
144__updates_available_detail() {
145	if eval $BYOBU_TEST apt-get >/dev/null; then
146		local detail=`apt-get -s -o Debug::NoLocking=true upgrade`
147		if [ "$1" = "--detail" ]; then
148			printf "$detail"
149		else
150			local short=`printf "%s" "$detail" | grep -c ^Inst`
151			printf "$short"
152		fi
153	fi
154}
155
156__updates_available() {
157	local mycache="$BYOBU_RUN_DIR/cache.$BYOBU_BACKEND/updates-available"
158	# If mycache is present, use it
159	[ -r $mycache ] && ___print_updates "$mycache"
160	# If we really need to do so (mycache doesn't exist, or the package database has changed),
161	# background an update now
162	___update_needed "$mycache" && ___update_cache "$mycache"
163}
164
165# vi: syntax=sh ts=4 noexpandtab
166