diff -Nru update-notifier-0.119ubuntu1/aclocal.m4 update-notifier-0.119ubuntu2/aclocal.m4 --- update-notifier-0.119ubuntu1/aclocal.m4 2012-03-11 09:29:37.000000000 +0000 +++ update-notifier-0.119ubuntu2/aclocal.m4 2012-04-06 15:46:21.000000000 +0000 @@ -457,62 +457,6 @@ fi]) -# gnome-common.m4 -# -# serial 3 -# - -dnl GNOME_COMMON_INIT - -AU_DEFUN([GNOME_COMMON_INIT], -[ - dnl this macro should come after AC_CONFIG_MACRO_DIR - AC_BEFORE([AC_CONFIG_MACRO_DIR], [$0]) - - dnl ensure that when the Automake generated makefile calls aclocal, - dnl it honours the $ACLOCAL_FLAGS environment variable - ACLOCAL_AMFLAGS="\${ACLOCAL_FLAGS}" - if test -n "$ac_macro_dir"; then - ACLOCAL_AMFLAGS="-I $ac_macro_dir $ACLOCAL_AMFLAGS" - fi - - AC_SUBST([ACLOCAL_AMFLAGS]) -], -[[$0: This macro is deprecated. You should set put "ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}" -in your top-level Makefile.am, instead, where "m4" is the macro directory set -with AC_CONFIG_MACRO_DIR() in your configure.ac]]) - -AC_DEFUN([GNOME_DEBUG_CHECK], -[ - AC_ARG_ENABLE([debug], - AC_HELP_STRING([--enable-debug], - [turn on debugging]),, - [enable_debug=no]) - - if test x$enable_debug = xyes ; then - AC_DEFINE(GNOME_ENABLE_DEBUG, 1, - [Enable additional debugging at the expense of performance and size]) - fi -]) - -dnl GNOME_MAINTAINER_MODE_DEFINES () -dnl define DISABLE_DEPRECATED -dnl -AC_DEFUN([GNOME_MAINTAINER_MODE_DEFINES], -[ - AC_REQUIRE([AM_MAINTAINER_MODE]) - - DISABLE_DEPRECATED="" - if test $USE_MAINTAINER_MODE = yes; then - DOMAINS="G ATK PANGO GDK GDK_PIXBUF GTK GCONF BONOBO BONOBO_UI GNOME LIBGLADE VTE GNOME_VFS WNCK LIBSOUP" - for DOMAIN in $DOMAINS; do - DISABLE_DEPRECATED="$DISABLE_DEPRECATED -D${DOMAIN}_DISABLE_DEPRECATED -D${DOMAIN}_DISABLE_SINGLE_INCLUDES" - done - fi - - AC_SUBST(DISABLE_DEPRECATED) -]) - dnl GLIB_GSETTINGS dnl Defines GSETTINGS_SCHEMAS_INSTALL which controls whether dnl the schema should be compiled diff -Nru update-notifier-0.119ubuntu1/configure update-notifier-0.119ubuntu2/configure --- update-notifier-0.119ubuntu1/configure 2012-03-11 09:29:39.000000000 +0000 +++ update-notifier-0.119ubuntu2/configure 2012-04-06 15:46:22.000000000 +0000 @@ -665,7 +665,6 @@ PKG_CONFIG_PATH PKG_CONFIG GSETTINGS_DISABLE_SCHEMAS_COMPILE -ACLOCAL_AMFLAGS EGREP GREP CPP @@ -5497,16 +5496,7 @@ fi - - - - ACLOCAL_AMFLAGS="\${ACLOCAL_FLAGS}" - if test -n "$ac_macro_dir"; then - ACLOCAL_AMFLAGS="-I $ac_macro_dir $ACLOCAL_AMFLAGS" - fi - - - +GNOME_COMMON_INIT # Check whether --enable-schemas-compile was given. diff -Nru update-notifier-0.119ubuntu1/data/Makefile.am update-notifier-0.119ubuntu2/data/Makefile.am --- update-notifier-0.119ubuntu1/data/Makefile.am 2011-09-12 08:26:27.000000000 +0000 +++ update-notifier-0.119ubuntu2/data/Makefile.am 2012-03-23 21:06:38.000000000 +0000 @@ -12,14 +12,27 @@ dist_convert_DATA = update-notifier.convert helperdir = $(libdir)/update-notifier -helper_SCRIPTS = apt_check.py apt-cdrom-check cddistupgrader update-motd-reboot-required update-motd-updates-available update-motd-fsck-at-reboot backend_helper.py +helper_SCRIPTS = apt_check.py apt-cdrom-check cddistupgrader update-motd-reboot-required update-motd-updates-available update-motd-fsck-at-reboot backend_helper.py package-data-downloader notifydir = $(datadir)/update-notifier notify_SCRIPTS = notify-reboot-required +notify_in_files = package-data-downloads-failed.in package-data-downloads-failed-permanently.in +notify_DATA = $(notify_in_files:.in=) EXTRA_DIST= $(helper_SCRIPTS) \ $(desktop_in_files) \ + $(notify_in_files) \ $(gsettings_SCHEMAS:.xml=.xml.in) CLEANFILES = \ $(gsettings_SCHEMAS) + +package-data-downloads-failed: package-data-downloads-failed.in + $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) + $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -r -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@ + sed -i -e's/^_//' $@ + +package-data-downloads-failed-permanently: package-data-downloads-failed-permanently.in + $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) + $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -r -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@ + sed -i -e's/^_//' $@ diff -Nru update-notifier-0.119ubuntu1/data/Makefile.in update-notifier-0.119ubuntu2/data/Makefile.in --- update-notifier-0.119ubuntu1/data/Makefile.in 2012-03-11 09:29:41.000000000 +0000 +++ update-notifier-0.119ubuntu2/data/Makefile.in 2012-04-06 15:46:23.000000000 +0000 @@ -72,14 +72,14 @@ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(helperdir)" "$(DESTDIR)$(notifydir)" \ - "$(DESTDIR)$(desktopdir)" "$(DESTDIR)$(convertdir)" + "$(DESTDIR)$(desktopdir)" "$(DESTDIR)$(convertdir)" \ + "$(DESTDIR)$(notifydir)" SCRIPTS = $(helper_SCRIPTS) $(notify_SCRIPTS) SOURCES = DIST_SOURCES = -DATA = $(desktop_DATA) $(dist_convert_DATA) +DATA = $(desktop_DATA) $(dist_convert_DATA) $(notify_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ @@ -213,11 +213,14 @@ convertdir = $(datadir)/GConf/gsettings dist_convert_DATA = update-notifier.convert helperdir = $(libdir)/update-notifier -helper_SCRIPTS = apt_check.py apt-cdrom-check cddistupgrader update-motd-reboot-required update-motd-updates-available update-motd-fsck-at-reboot backend_helper.py +helper_SCRIPTS = apt_check.py apt-cdrom-check cddistupgrader update-motd-reboot-required update-motd-updates-available update-motd-fsck-at-reboot backend_helper.py package-data-downloader notifydir = $(datadir)/update-notifier notify_SCRIPTS = notify-reboot-required +notify_in_files = package-data-downloads-failed.in package-data-downloads-failed-permanently.in +notify_DATA = $(notify_in_files:.in=) EXTRA_DIST = $(helper_SCRIPTS) \ $(desktop_in_files) \ + $(notify_in_files) \ $(gsettings_SCHEMAS:.xml=.xml.in) CLEANFILES = \ @@ -356,6 +359,24 @@ @list='$(dist_convert_DATA)'; test -n "$(convertdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(convertdir)'; $(am__uninstall_files_from_dir) +install-notifyDATA: $(notify_DATA) + @$(NORMAL_INSTALL) + test -z "$(notifydir)" || $(MKDIR_P) "$(DESTDIR)$(notifydir)" + @list='$(notify_DATA)'; test -n "$(notifydir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(notifydir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(notifydir)" || exit $$?; \ + done + +uninstall-notifyDATA: + @$(NORMAL_UNINSTALL) + @list='$(notify_DATA)'; test -n "$(notifydir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(notifydir)'; $(am__uninstall_files_from_dir) tags: TAGS TAGS: @@ -397,7 +418,7 @@ check: check-am all-am: Makefile $(SCRIPTS) $(DATA) installdirs: - for dir in "$(DESTDIR)$(helperdir)" "$(DESTDIR)$(notifydir)" "$(DESTDIR)$(desktopdir)" "$(DESTDIR)$(convertdir)"; do \ + for dir in "$(DESTDIR)$(helperdir)" "$(DESTDIR)$(notifydir)" "$(DESTDIR)$(desktopdir)" "$(DESTDIR)$(convertdir)" "$(DESTDIR)$(notifydir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -452,7 +473,7 @@ info-am: install-data-am: install-desktopDATA install-dist_convertDATA \ - install-helperSCRIPTS install-notifySCRIPTS + install-helperSCRIPTS install-notifyDATA install-notifySCRIPTS install-dvi: install-dvi-am @@ -497,7 +518,8 @@ ps-am: uninstall-am: uninstall-desktopDATA uninstall-dist_convertDATA \ - uninstall-helperSCRIPTS uninstall-notifySCRIPTS + uninstall-helperSCRIPTS uninstall-notifyDATA \ + uninstall-notifySCRIPTS .MAKE: install-am install-strip @@ -507,19 +529,30 @@ install-desktopDATA install-dist_convertDATA install-dvi \ install-dvi-am install-exec install-exec-am \ install-helperSCRIPTS install-html install-html-am \ - install-info install-info-am install-man install-notifySCRIPTS \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \ - uninstall-desktopDATA uninstall-dist_convertDATA \ - uninstall-helperSCRIPTS uninstall-notifySCRIPTS + install-info install-info-am install-man install-notifyDATA \ + install-notifySCRIPTS install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ + uninstall-am uninstall-desktopDATA uninstall-dist_convertDATA \ + uninstall-helperSCRIPTS uninstall-notifyDATA \ + uninstall-notifySCRIPTS @INTLTOOL_DESKTOP_RULE@ @INTLTOOL_XML_NOMERGE_RULE@ @GSETTINGS_RULES@ +package-data-downloads-failed: package-data-downloads-failed.in + $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) + $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -r -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@ + sed -i -e's/^_//' $@ + +package-data-downloads-failed-permanently: package-data-downloads-failed-permanently.in + $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) + $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -r -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@ + sed -i -e's/^_//' $@ + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff -Nru update-notifier-0.119ubuntu1/data/package-data-downloader update-notifier-0.119ubuntu2/data/package-data-downloader --- update-notifier-0.119ubuntu1/data/package-data-downloader 1970-01-01 00:00:00.000000000 +0000 +++ update-notifier-0.119ubuntu2/data/package-data-downloader 2012-04-06 05:00:22.000000000 +0000 @@ -0,0 +1,281 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""Process new requests to download per-package data""" +# Copyright (C) 2012 Canonical Ltd +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 3 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import glob +import os +import sys +import subprocess +import re +import traceback +import urllib +import debian.deb822 +import string +import apt +from datetime import timedelta + +DATADIR = "/usr/share/package-data-downloads/" +STAMPDIR = "/var/lib/update-notifier/package-data-downloads/" +NOTIFIER_SOURCE_FILE = "/usr/share/update-notifier/package-data-downloads-failed" +NOTIFIER_FILE = "/var/lib/update-notifier/user.d/data-downloads-failed" +NOTIFIER_PERMANENT_SOURCE_FILE = NOTIFIER_SOURCE_FILE + '-permanently' +NOTIFIER_PERMANENT_FILE = NOTIFIER_FILE + '-permanently' + +failures = [] +permanent_failures = [] + +def create_or_update_stampfile(file): + """Create or update the indicated stampfile, and remove failure flags""" + + try: + with open(file, 'w'): + pass + # Ignore errors + except Exception: + traceback.print_exc(file=sys.stderr) + + os.utime(file, None) + + for ext in ('.failed', '.permanent-failure'): + if os.path.exists(file + ext): + os.unlink(file + ext) + + +def mark_hook_failed(hook_name, permanent=False): + """Create a stampfile recording that a hook failed + + We create separate stampfiles for failed hooks so we can + keep track of how long the hook has been failing and if the failure + should be considered permanent.""" + + if permanent: + filename = hook_name + '.permanent-failure' + else: + filename = hook_name + '.failed' + + failure_file = os.path.join(STAMPDIR, filename) + try: + with open(failure_file, 'w'): + pass + + # Ignore errors + except Exception: + traceback.print_exc(file=sys.stderr) + + for ext in ('', '.failed', '.permanent-failure'): + stampfile = hook_name + ext + if filename != stampfile \ + and os.path.exists(os.path.join(STAMPDIR, stampfile)): + os.unlink(os.path.join(STAMPDIR, stampfile)) + + +def hook_is_permanently_failed(hook_name): + """Check if this hook has been marked as permanently failing. + + If so, don't raise any more errors about it.""" + + failure_file = os.path.join(STAMPDIR, hook_name + '.permanent-failure') + return os.path.exists(failure_file) + + +def hook_aged_out(hook_name): + """Check if this hook has been failing consistently for >= 3 days""" + + failure_file = os.path.join(STAMPDIR, hook_name + '.failed') + try: + hook_date = os.stat(failure_file).st_ctime + cur_time = os.times()[4] + d = timedelta(microseconds=cur_time-hook_date) + if d.days >= 3: + return True + except OSError: + pass + except Exception: + traceback.print_exc(file=sys.stderr) + return False + + +def record_failure(hook): + """Record that the named hook has failed""" + if hook_aged_out(hook): + permanent_failures.append(hook) + else: + failures.append(hook) + + +def existing_permanent_failures(): + """Return the list of all previously recorded permanent failures""" + + files = glob.glob(os.path.join(STAMPDIR, "*.permanent-failure")) + return [os.path.splitext(os.path.basename(path))[0] for path in files] + + +def trigger_update_notifier(failures, permanent=False): + """Tell update-notifier that there were failed packages""" + + try: + if permanent: + with open(NOTIFIER_PERMANENT_SOURCE_FILE, 'r') as f: + input = f.read() + output_file = open(NOTIFIER_PERMANENT_FILE, 'w') + else: + with open(NOTIFIER_SOURCE_FILE, 'r') as f: + input = f.read() + output_file = open(NOTIFIER_FILE, 'w') + except Exception: + # Things failed and we can't even notify about it. Break the + # trigger so that there's some error propagation, even if not + # the most pleasant sort. + traceback.print_exc(file=sys.stderr) + sys.exit(1) + + packages = [os.path.basename(failure) for failure in failures] + output_file.write( + string.Template(input).substitute( + {'packages' : ", ".join(packages)})) + output_file.close() + +def get_hook_file_names(): + res = [] + for relfile in os.listdir(DATADIR): + # ignore files ending in .dpkg-* + if (os.path.splitext(relfile)[1] and + os.path.splitext(relfile)[1].startswith(".dpkg")): + continue + res.append(relfile) + return res + +def process_download_requests(): + """Process requests to download package data files + + Iterate over /usr/share/package-data-downloads and download any + package data specified in the contained file, then hand off to + the indicated handler for further processing. + + Successful downloads are recorded in + /var/lib/update-notifier/package-data-downloads to avoid unnecessary + repeat handling. + + Failed downloads are reported to the user via the + update-notifier interface.""" + + # Get our proxy settings from apt + proxies = {} + try: + for proto in ('http','https','ftp'): + proxies[proto] = apt.apt_pkg.config.get("Acquire::"+proto+"::Proxy") + if not proxies[proto]: + proxies.pop(proto) + + if proxies: + urllib._urlopener = urllib.URLopener(proxies) + except Exception: + pass + + # Iterate through all the available hooks. If we get a failure + # processing any of them (download failure, checksum failure, or + # failure to run the hook script), record it but continue processing + # the rest of the hooks since some of them may succeed. + for relfile in get_hook_file_names(): + + stampfile = os.path.join(STAMPDIR, relfile) + file = os.path.join(DATADIR, relfile) + try: + hook_date = os.stat(file).st_mtime + stamp_date = os.stat(stampfile).st_mtime + if hook_date < stamp_date: + continue + except Exception as e: + if not isinstance(e, OSError): + traceback.print_exc(file=sys.stderr) + + hook = debian.deb822.Deb822() + files = [] + sums = [] + for para in hook.iter_paragraphs(open(file)): + if para.has_key('script'): + if not files: + record_failure(relfile) + break + command = [para['script']] + + # Download each file and verify the sum + try: + for i in range(len(files)): + print files[i] + dest_file = urllib.urlretrieve(files[i])[0] + output = subprocess.check_output(["sha256sum", dest_file]) + output = output.split(' ')[0] + if output == sums[i]: + command.append(dest_file) + else: + record_failure(relfile) + break + if relfile in failures: + break + + result = subprocess.call(command) + if result: + # There's no sense redownloading if the script fails + permanent_failures.append(relfile) + else: + create_or_update_stampfile(stampfile) + break + except Exception: + traceback.print_exc(file=sys.stderr) + + record_failure(relfile) + # The 'script' is always the last stanza + break + + # Not in a 'script' stanza, so we should have some urls + try: + files.append(para['url']) + sums.append(para['sha256']) + except Exception as e: + if not isinstance(e, KeyError): + traceback.print_exc(file=sys.stderr) + record_failure(relfile) + break + + previous_failures = existing_permanent_failures() + + # We only report about "permanent" failures when there are new ones, + # but we want the whole list of permanently-failing hooks so when + # we clobber the update-notifier file we don't lose information the + # user may not have seen yet + if permanent_failures: + new_failures = False + for failure in permanent_failures: + if failure not in previous_failures: + mark_hook_failed(failure, permanent=True) + previous_failures.append(failure) + new_failures = True + if new_failures: + trigger_update_notifier(previous_failures, permanent=True) + + # Filter out new failure reports for permanently-failed packages + our_failures = [x for x in failures if x not in previous_failures] + + if our_failures: + for failure in our_failures: + mark_hook_failed(failure) + trigger_update_notifier(our_failures) + + +if __name__ == "__main__": + process_download_requests() diff -Nru update-notifier-0.119ubuntu1/data/package_data_downloader.py update-notifier-0.119ubuntu2/data/package_data_downloader.py --- update-notifier-0.119ubuntu1/data/package_data_downloader.py 1970-01-01 00:00:00.000000000 +0000 +++ update-notifier-0.119ubuntu2/data/package_data_downloader.py 2012-04-06 05:00:22.000000000 +0000 @@ -0,0 +1,281 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""Process new requests to download per-package data""" +# Copyright (C) 2012 Canonical Ltd +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 3 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import glob +import os +import sys +import subprocess +import re +import traceback +import urllib +import debian.deb822 +import string +import apt +from datetime import timedelta + +DATADIR = "/usr/share/package-data-downloads/" +STAMPDIR = "/var/lib/update-notifier/package-data-downloads/" +NOTIFIER_SOURCE_FILE = "/usr/share/update-notifier/package-data-downloads-failed" +NOTIFIER_FILE = "/var/lib/update-notifier/user.d/data-downloads-failed" +NOTIFIER_PERMANENT_SOURCE_FILE = NOTIFIER_SOURCE_FILE + '-permanently' +NOTIFIER_PERMANENT_FILE = NOTIFIER_FILE + '-permanently' + +failures = [] +permanent_failures = [] + +def create_or_update_stampfile(file): + """Create or update the indicated stampfile, and remove failure flags""" + + try: + with open(file, 'w'): + pass + # Ignore errors + except Exception: + traceback.print_exc(file=sys.stderr) + + os.utime(file, None) + + for ext in ('.failed', '.permanent-failure'): + if os.path.exists(file + ext): + os.unlink(file + ext) + + +def mark_hook_failed(hook_name, permanent=False): + """Create a stampfile recording that a hook failed + + We create separate stampfiles for failed hooks so we can + keep track of how long the hook has been failing and if the failure + should be considered permanent.""" + + if permanent: + filename = hook_name + '.permanent-failure' + else: + filename = hook_name + '.failed' + + failure_file = os.path.join(STAMPDIR, filename) + try: + with open(failure_file, 'w'): + pass + + # Ignore errors + except Exception: + traceback.print_exc(file=sys.stderr) + + for ext in ('', '.failed', '.permanent-failure'): + stampfile = hook_name + ext + if filename != stampfile \ + and os.path.exists(os.path.join(STAMPDIR, stampfile)): + os.unlink(os.path.join(STAMPDIR, stampfile)) + + +def hook_is_permanently_failed(hook_name): + """Check if this hook has been marked as permanently failing. + + If so, don't raise any more errors about it.""" + + failure_file = os.path.join(STAMPDIR, hook_name + '.permanent-failure') + return os.path.exists(failure_file) + + +def hook_aged_out(hook_name): + """Check if this hook has been failing consistently for >= 3 days""" + + failure_file = os.path.join(STAMPDIR, hook_name + '.failed') + try: + hook_date = os.stat(failure_file).st_ctime + cur_time = os.times()[4] + d = timedelta(microseconds=cur_time-hook_date) + if d.days >= 3: + return True + except OSError: + pass + except Exception: + traceback.print_exc(file=sys.stderr) + return False + + +def record_failure(hook): + """Record that the named hook has failed""" + if hook_aged_out(hook): + permanent_failures.append(hook) + else: + failures.append(hook) + + +def existing_permanent_failures(): + """Return the list of all previously recorded permanent failures""" + + files = glob.glob(os.path.join(STAMPDIR, "*.permanent-failure")) + return [os.path.splitext(os.path.basename(path))[0] for path in files] + + +def trigger_update_notifier(failures, permanent=False): + """Tell update-notifier that there were failed packages""" + + try: + if permanent: + with open(NOTIFIER_PERMANENT_SOURCE_FILE, 'r') as f: + input = f.read() + output_file = open(NOTIFIER_PERMANENT_FILE, 'w') + else: + with open(NOTIFIER_SOURCE_FILE, 'r') as f: + input = f.read() + output_file = open(NOTIFIER_FILE, 'w') + except Exception: + # Things failed and we can't even notify about it. Break the + # trigger so that there's some error propagation, even if not + # the most pleasant sort. + traceback.print_exc(file=sys.stderr) + sys.exit(1) + + packages = [os.path.basename(failure) for failure in failures] + output_file.write( + string.Template(input).substitute( + {'packages' : ", ".join(packages)})) + output_file.close() + +def get_hook_file_names(): + res = [] + for relfile in os.listdir(DATADIR): + # ignore files ending in .dpkg-* + if (os.path.splitext(relfile)[1] and + os.path.splitext(relfile)[1].startswith(".dpkg")): + continue + res.append(relfile) + return res + +def process_download_requests(): + """Process requests to download package data files + + Iterate over /usr/share/package-data-downloads and download any + package data specified in the contained file, then hand off to + the indicated handler for further processing. + + Successful downloads are recorded in + /var/lib/update-notifier/package-data-downloads to avoid unnecessary + repeat handling. + + Failed downloads are reported to the user via the + update-notifier interface.""" + + # Get our proxy settings from apt + proxies = {} + try: + for proto in ('http','https','ftp'): + proxies[proto] = apt.apt_pkg.config.get("Acquire::"+proto+"::Proxy") + if not proxies[proto]: + proxies.pop(proto) + + if proxies: + urllib._urlopener = urllib.URLopener(proxies) + except Exception: + pass + + # Iterate through all the available hooks. If we get a failure + # processing any of them (download failure, checksum failure, or + # failure to run the hook script), record it but continue processing + # the rest of the hooks since some of them may succeed. + for relfile in get_hook_file_names(): + + stampfile = os.path.join(STAMPDIR, relfile) + file = os.path.join(DATADIR, relfile) + try: + hook_date = os.stat(file).st_mtime + stamp_date = os.stat(stampfile).st_mtime + if hook_date < stamp_date: + continue + except Exception as e: + if not isinstance(e, OSError): + traceback.print_exc(file=sys.stderr) + + hook = debian.deb822.Deb822() + files = [] + sums = [] + for para in hook.iter_paragraphs(open(file)): + if para.has_key('script'): + if not files: + record_failure(relfile) + break + command = [para['script']] + + # Download each file and verify the sum + try: + for i in range(len(files)): + print files[i] + dest_file = urllib.urlretrieve(files[i])[0] + output = subprocess.check_output(["sha256sum", dest_file]) + output = output.split(' ')[0] + if output == sums[i]: + command.append(dest_file) + else: + record_failure(relfile) + break + if relfile in failures: + break + + result = subprocess.call(command) + if result: + # There's no sense redownloading if the script fails + permanent_failures.append(relfile) + else: + create_or_update_stampfile(stampfile) + break + except Exception: + traceback.print_exc(file=sys.stderr) + + record_failure(relfile) + # The 'script' is always the last stanza + break + + # Not in a 'script' stanza, so we should have some urls + try: + files.append(para['url']) + sums.append(para['sha256']) + except Exception as e: + if not isinstance(e, KeyError): + traceback.print_exc(file=sys.stderr) + record_failure(relfile) + break + + previous_failures = existing_permanent_failures() + + # We only report about "permanent" failures when there are new ones, + # but we want the whole list of permanently-failing hooks so when + # we clobber the update-notifier file we don't lose information the + # user may not have seen yet + if permanent_failures: + new_failures = False + for failure in permanent_failures: + if failure not in previous_failures: + mark_hook_failed(failure, permanent=True) + previous_failures.append(failure) + new_failures = True + if new_failures: + trigger_update_notifier(previous_failures, permanent=True) + + # Filter out new failure reports for permanently-failed packages + our_failures = [x for x in failures if x not in previous_failures] + + if our_failures: + for failure in our_failures: + mark_hook_failed(failure) + trigger_update_notifier(our_failures) + + +if __name__ == "__main__": + process_download_requests() diff -Nru update-notifier-0.119ubuntu1/data/package-data-downloads-failed.in update-notifier-0.119ubuntu2/data/package-data-downloads-failed.in --- update-notifier-0.119ubuntu1/data/package-data-downloads-failed.in 1970-01-01 00:00:00.000000000 +0000 +++ update-notifier-0.119ubuntu2/data/package-data-downloads-failed.in 2012-03-23 21:06:38.000000000 +0000 @@ -0,0 +1,15 @@ +_Name: Failure to download extra data files +Priority: High +Terminal: True +Command: /usr/lib/update-notifier/package-data-downloader +_Description: + The following packages requested additional data downloads after package + installation, but the data could not be downloaded or could not be + processed. + . + . + $packages + . + . + The download will be attempted again later, or you can try the download + again now. Running this command requires an active Internet connection. diff -Nru update-notifier-0.119ubuntu1/data/package-data-downloads-failed-permanently.in update-notifier-0.119ubuntu2/data/package-data-downloads-failed-permanently.in --- update-notifier-0.119ubuntu1/data/package-data-downloads-failed-permanently.in 1970-01-01 00:00:00.000000000 +0000 +++ update-notifier-0.119ubuntu2/data/package-data-downloads-failed-permanently.in 2012-03-23 21:06:38.000000000 +0000 @@ -0,0 +1,14 @@ +_Name: Data files for some packages could not be downloaded +Priority: High +_Description: + The following packages requested additional data downloads after package + installation, but the data could not be downloaded or could not be + processed. + . + . + $packages + . + . + This is a permanent failure that leaves these packages unusable on your + system. You may need to fix your Internet connection, then remove and + reinstall the packages to fix this problem. diff -Nru update-notifier-0.119ubuntu1/debian/changelog update-notifier-0.119ubuntu2/debian/changelog --- update-notifier-0.119ubuntu1/debian/changelog 2012-03-11 09:29:28.000000000 +0000 +++ update-notifier-0.119ubuntu2/debian/changelog 2012-04-06 05:04:06.000000000 +0000 @@ -1,3 +1,19 @@ +update-notifier (0.119ubuntu2) precise; urgency=low + + * data/package-data-downloader, data/package-data-downloads-failed.in, + data/package-data-downloads-failed-permanently.in, + debian/update-notifier-common.{postinst,triggers}: add a new handler and + dpkg trigger to let packages queue data for download after package + install, so that network connectivity problems don't make installs + and upgrades unreliable. LP: #876298. + * debian/update-notifier-common.cron.daily: add a cronjob to periodically + retry any failed downloads. + * src/update-notifier.c: when there are new hooks, check them whether or + not dpkg has run; this allows other packages to send us notifications + by ways other than running a package maintainer script. + + -- Steve Langasek Thu, 05 Apr 2012 22:04:05 -0700 + update-notifier (0.119ubuntu1) precise; urgency=low * src/update-notifier.c: Consider both the "sudo" and "admin" groups as diff -Nru update-notifier-0.119ubuntu1/debian/control update-notifier-0.119ubuntu2/debian/control --- update-notifier-0.119ubuntu1/debian/control 2011-12-06 17:01:25.000000000 +0000 +++ update-notifier-0.119ubuntu2/debian/control 2012-03-23 21:06:38.000000000 +0000 @@ -41,7 +41,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, python, - python-apt (>= 0.6.12) + python-apt (>= 0.6.12), python-debian Recommends: libpam-modules (>= 1.0.1-9ubuntu3) Description: Files shared between update-notifier and other packages Apt setup files and reboot notification scripts shared between diff -Nru update-notifier-0.119ubuntu1/debian/update-notifier-common.cron.daily update-notifier-0.119ubuntu2/debian/update-notifier-common.cron.daily --- update-notifier-0.119ubuntu1/debian/update-notifier-common.cron.daily 1970-01-01 00:00:00.000000000 +0000 +++ update-notifier-0.119ubuntu2/debian/update-notifier-common.cron.daily 2012-03-23 21:06:38.000000000 +0000 @@ -0,0 +1,6 @@ +#!/bin/sh + +set -e + +# Try to rerun any package data downloads that failed at package install time. +/usr/lib/update-notifier/package-data-downloader diff -Nru update-notifier-0.119ubuntu1/debian/update-notifier-common.dirs update-notifier-0.119ubuntu2/debian/update-notifier-common.dirs --- update-notifier-0.119ubuntu1/debian/update-notifier-common.dirs 2012-03-10 16:00:37.000000000 +0000 +++ update-notifier-0.119ubuntu2/debian/update-notifier-common.dirs 2012-03-23 21:06:38.000000000 +0000 @@ -2,6 +2,8 @@ etc/update-notifier var/lib/update-notifier var/lib/update-notifier/user.d +var/lib/update-notifier/package-data-downloads etc/update-motd.d usr/share/update-notifier/plugins/cache-changed usr/share/update-notifier/upgrader-patches +usr/share/package-data-downloads diff -Nru update-notifier-0.119ubuntu1/debian/update-notifier-common.install update-notifier-0.119ubuntu2/debian/update-notifier-common.install --- update-notifier-0.119ubuntu1/debian/update-notifier-common.install 2012-03-10 16:00:37.000000000 +0000 +++ update-notifier-0.119ubuntu2/debian/update-notifier-common.install 2012-03-23 21:06:38.000000000 +0000 @@ -6,6 +6,8 @@ debian/98-reboot-required etc/update-motd.d debian/98-fsck-at-reboot etc/update-motd.d usr/share/update-notifier/notify-reboot-required +usr/share/update-notifier/package-data-downloads-failed +usr/share/update-notifier/package-data-downloads-failed-permanently usr/lib/update-notifier/ usr/share/locale debian/update-manager-downloader-fix2.diff usr/share/update-notifier/upgrader-patches diff -Nru update-notifier-0.119ubuntu1/debian/update-notifier-common.postinst update-notifier-0.119ubuntu2/debian/update-notifier-common.postinst --- update-notifier-0.119ubuntu1/debian/update-notifier-common.postinst 2011-06-08 05:33:04.000000000 +0000 +++ update-notifier-0.119ubuntu2/debian/update-notifier-common.postinst 2012-03-23 21:06:38.000000000 +0000 @@ -14,4 +14,15 @@ rm -f /etc/update-motd.d/20-cpu-checker fi +if [ "$1" = triggered ]; then + for trigger in $2; do + case $trigger in + /usr/share/package-data-downloads) + /usr/lib/update-notifier/package-data-downloader + ;; + esac + done + exit 0 +fi + #DEBHELPER# diff -Nru update-notifier-0.119ubuntu1/debian/update-notifier-common.triggers update-notifier-0.119ubuntu2/debian/update-notifier-common.triggers --- update-notifier-0.119ubuntu1/debian/update-notifier-common.triggers 1970-01-01 00:00:00.000000000 +0000 +++ update-notifier-0.119ubuntu2/debian/update-notifier-common.triggers 2012-03-23 21:06:38.000000000 +0000 @@ -0,0 +1 @@ +interest /usr/share/package-data-downloads diff -Nru update-notifier-0.119ubuntu1/Makefile.in update-notifier-0.119ubuntu2/Makefile.in --- update-notifier-0.119ubuntu1/Makefile.in 2012-03-11 09:29:42.000000000 +0000 +++ update-notifier-0.119ubuntu2/Makefile.in 2012-04-06 15:46:23.000000000 +0000 @@ -104,7 +104,6 @@ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ -ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ diff -Nru update-notifier-0.119ubuntu1/pixmaps/16x16/Makefile.in update-notifier-0.119ubuntu2/pixmaps/16x16/Makefile.in --- update-notifier-0.119ubuntu1/pixmaps/16x16/Makefile.in 2012-03-11 09:29:41.000000000 +0000 +++ update-notifier-0.119ubuntu2/pixmaps/16x16/Makefile.in 2012-04-06 15:46:23.000000000 +0000 @@ -75,7 +75,6 @@ DATA = $(icon_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ diff -Nru update-notifier-0.119ubuntu1/pixmaps/22x22/Makefile.in update-notifier-0.119ubuntu2/pixmaps/22x22/Makefile.in --- update-notifier-0.119ubuntu1/pixmaps/22x22/Makefile.in 2012-03-11 09:29:41.000000000 +0000 +++ update-notifier-0.119ubuntu2/pixmaps/22x22/Makefile.in 2012-04-06 15:46:23.000000000 +0000 @@ -75,7 +75,6 @@ DATA = $(icon_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ diff -Nru update-notifier-0.119ubuntu1/pixmaps/24x24/Makefile.in update-notifier-0.119ubuntu2/pixmaps/24x24/Makefile.in --- update-notifier-0.119ubuntu1/pixmaps/24x24/Makefile.in 2012-03-11 09:29:41.000000000 +0000 +++ update-notifier-0.119ubuntu2/pixmaps/24x24/Makefile.in 2012-04-06 15:46:23.000000000 +0000 @@ -75,7 +75,6 @@ DATA = $(icon_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ diff -Nru update-notifier-0.119ubuntu1/pixmaps/48x48/Makefile.in update-notifier-0.119ubuntu2/pixmaps/48x48/Makefile.in --- update-notifier-0.119ubuntu1/pixmaps/48x48/Makefile.in 2012-03-11 09:29:41.000000000 +0000 +++ update-notifier-0.119ubuntu2/pixmaps/48x48/Makefile.in 2012-04-06 15:46:23.000000000 +0000 @@ -75,7 +75,6 @@ DATA = $(appicon_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ diff -Nru update-notifier-0.119ubuntu1/pixmaps/Makefile.in update-notifier-0.119ubuntu2/pixmaps/Makefile.in --- update-notifier-0.119ubuntu1/pixmaps/Makefile.in 2012-03-11 09:29:41.000000000 +0000 +++ update-notifier-0.119ubuntu2/pixmaps/Makefile.in 2012-04-06 15:46:23.000000000 +0000 @@ -85,7 +85,6 @@ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ -ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ diff -Nru update-notifier-0.119ubuntu1/po/POTFILES.in update-notifier-0.119ubuntu2/po/POTFILES.in --- update-notifier-0.119ubuntu1/po/POTFILES.in 2011-09-12 08:26:27.000000000 +0000 +++ update-notifier-0.119ubuntu2/po/POTFILES.in 2012-03-23 21:06:38.000000000 +0000 @@ -17,3 +17,5 @@ [type: gettext/glade]ui/reboot-dialog.ui data/com.ubuntu.update-notifier.gschema.xml.in data/update-notifier.desktop.in +[type: gettext/rfc822deb] data/package-data-downloads-failed.in +[type: gettext/rfc822deb] data/package-data-downloads-failed-permanently.in diff -Nru update-notifier-0.119ubuntu1/po/update-notifier.pot update-notifier-0.119ubuntu2/po/update-notifier.pot --- update-notifier-0.119ubuntu1/po/update-notifier.pot 2012-03-11 09:29:44.000000000 +0000 +++ update-notifier-0.119ubuntu2/po/update-notifier.pot 2012-04-06 15:46:25.000000000 +0000 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-11 10:29+0100\n" +"POT-Creation-Date: 2012-04-06 15:46+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -273,24 +273,24 @@ msgid "A problem occurred when checking for the updates." msgstr "" -#: ../src/update-notifier.c:402 +#: ../src/update-notifier.c:403 msgid "Internal error" msgstr "" -#: ../src/update-notifier.c:582 +#: ../src/update-notifier.c:583 msgid "- inform about updates" msgstr "" -#: ../src/update-notifier.c:584 +#: ../src/update-notifier.c:585 #, c-format msgid "Failed to init the UI: %s\n" msgstr "" -#: ../src/update-notifier.c:585 +#: ../src/update-notifier.c:586 msgid "unknown error" msgstr "" -#: ../src/update-notifier.c:608 +#: ../src/update-notifier.c:609 msgid "update-notifier" msgstr "" @@ -323,3 +323,42 @@ #: ../data/update-notifier.desktop.in.h:2 msgid "Check for available updates automatically" msgstr "" + +#. Name +#: ../data/package-data-downloads-failed.in:1 +msgid "Failure to download extra data files" +msgstr "" + +#. Description +#: ../data/package-data-downloads-failed.in:5 +#: ../data/package-data-downloads-failed-permanently.in:3 +msgid "" +"The following packages requested additional data downloads after package " +"installation, but the data could not be downloaded or could not be processed." +msgstr "" + +#. Description +#: ../data/package-data-downloads-failed.in:5 +#: ../data/package-data-downloads-failed-permanently.in:3 +msgid " $packages" +msgstr "" + +#. Description +#: ../data/package-data-downloads-failed.in:5 +msgid "" +"The download will be attempted again later, or you can try the download " +"again now. Running this command requires an active Internet connection." +msgstr "" + +#. Name +#: ../data/package-data-downloads-failed-permanently.in:1 +msgid "Data files for some packages could not be downloaded" +msgstr "" + +#. Description +#: ../data/package-data-downloads-failed-permanently.in:3 +msgid "" +"This is a permanent failure that leaves these packages unusable on your " +"system. You may need to fix your Internet connection, then remove and " +"reinstall the packages to fix this problem." +msgstr "" diff -Nru update-notifier-0.119ubuntu1/src/Makefile.in update-notifier-0.119ubuntu2/src/Makefile.in --- update-notifier-0.119ubuntu1/src/Makefile.in 2012-03-11 09:29:41.000000000 +0000 +++ update-notifier-0.119ubuntu2/src/Makefile.in 2012-04-06 15:46:23.000000000 +0000 @@ -70,7 +70,6 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ diff -Nru update-notifier-0.119ubuntu1/src/update-notifier.c update-notifier-0.119ubuntu2/src/update-notifier.c --- update-notifier-0.119ubuntu1/src/update-notifier.c 2012-03-11 09:24:12.000000000 +0000 +++ update-notifier-0.119ubuntu2/src/update-notifier.c 2012-03-23 21:06:38.000000000 +0000 @@ -328,12 +328,6 @@ if(un->update_finished_timer > 0) g_source_remove(un->update_finished_timer); - // show pending hooks/reboots - if(un->hook_pending) { - //g_print("checking hooks now\n"); - check_update_hooks(un->hook); - un->hook_pending = FALSE; - } if(un->reboot_pending) { //g_print("checking reboot now\n"); reboot_check (un->reboot); @@ -350,6 +344,13 @@ un->last_apt_action = 0; } + // show pending hooks + if(un->hook_pending) { + //g_print("checking hooks now\n"); + check_update_hooks(un->hook); + un->hook_pending = FALSE; + } + // apt-get update/install or dpkg is runing (and updates files in // it's list/cache dir) or in /var/lib/dpkg/status if(un->apt_get_runing) diff -Nru update-notifier-0.119ubuntu1/tests/test_package-data-downloader.py update-notifier-0.119ubuntu2/tests/test_package-data-downloader.py --- update-notifier-0.119ubuntu1/tests/test_package-data-downloader.py 1970-01-01 00:00:00.000000000 +0000 +++ update-notifier-0.119ubuntu2/tests/test_package-data-downloader.py 2012-03-27 06:02:03.000000000 +0000 @@ -0,0 +1,106 @@ +#!/usr/bin/python + +import os +import shutil +import sys +import tempfile +import unittest + +sys.path.insert(0, "../data") +import package_data_downloader + +class PackageDataDownloaderTestCase(unittest.TestCase): + + def setUp(self): + self.tmpdir = tempfile.mkdtemp() + # stampdir + stampdir = os.path.join(self.tmpdir, "stampdir") + os.makedirs(stampdir) + package_data_downloader.STAMPDIR = stampdir + # datadir + datadir = os.path.join(self.tmpdir, "datadir") + os.makedirs(datadir) + package_data_downloader.DATADIR = datadir + + def tearDown(self): + shutil.rmtree(self.tmpdir) + + def test_permanently_failed(self): + # create a bunch of files using the provided mechanism + test_files = ["foo.permanent-failure", "bar.failure", "baz"] + for f in test_files: + package_data_downloader.create_or_update_stampfile( + os.path.join(package_data_downloader.STAMPDIR, f)) + self.assertEqual( + sorted(os.listdir(package_data_downloader.STAMPDIR)), + sorted(test_files)) + # test hook_is_permanently_failed() + self.assertTrue( + package_data_downloader.hook_is_permanently_failed("foo")) + self.assertFalse( + package_data_downloader.hook_is_permanently_failed("bar")) + self.assertFalse( + package_data_downloader.hook_is_permanently_failed("baz")) + # existing_permanent_failures() + self.assertEqual( + package_data_downloader.existing_permanent_failures(), + ["foo"]) + + def test_mark_hook_failed(self): + # prepare + package_data_downloader.create_or_update_stampfile( + os.path.join(package_data_downloader.STAMPDIR, "foo")) + # temp failure + package_data_downloader.mark_hook_failed("foo") + self.assertEqual(os.listdir(package_data_downloader.STAMPDIR), + ["foo.failed"]) + self.assertFalse( + package_data_downloader.hook_is_permanently_failed("foo")) + # permanent + package_data_downloader.mark_hook_failed("foo", permanent=True) + self.assertEqual(os.listdir(package_data_downloader.STAMPDIR), + ["foo.permanent-failure"]) + self.assertTrue( + package_data_downloader.hook_is_permanently_failed("foo")) + + def test_get_hook_file_names(self): + # test that .dpkg-* is ignored + test_datadir_files = ["foo.dpkg-new", "bar"] + for name in test_datadir_files: + with open(os.path.join(package_data_downloader.DATADIR, name), "w"): + pass + self.assertEqual(package_data_downloader.get_hook_file_names(), + ["bar"]) + + def test_trigger_update_notifier(self): + # write to tmpdir + package_data_downloader.NOTIFIER_FILE = os.path.join( + self.tmpdir, "data-downloads-failed") + # point to local repo file + package_data_downloader.NOTIFIER_SOURCE_FILE = \ + "../data/package-data-downloads-failed.in" + package_data_downloader.trigger_update_notifier( + failures=["foo", "bar"], permanent=False) + data = open(package_data_downloader.NOTIFIER_FILE).read() + self.assertEqual(data, """_Name: Failure to download extra data files +Priority: High +Terminal: True +Command: /usr/lib/update-notifier/package-data-downloader +_Description: + The following packages requested additional data downloads after package + installation, but the data could not be downloaded or could not be + processed. + . + . + foo, bar + . + . + The download will be attempted again later, or you can try the download + again now. Running this command requires an active Internet connection. +""") + + + + +if __name__ == "__main__": + unittest.main() diff -Nru update-notifier-0.119ubuntu1/ui/Makefile.in update-notifier-0.119ubuntu2/ui/Makefile.in --- update-notifier-0.119ubuntu1/ui/Makefile.in 2012-03-11 09:29:41.000000000 +0000 +++ update-notifier-0.119ubuntu2/ui/Makefile.in 2012-04-06 15:46:23.000000000 +0000 @@ -75,7 +75,6 @@ DATA = $(ui_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@