# vim:set fileencoding=utf-8 et ts=4 sts=4 sw=4:
#
# apt-listchanges - Show changelog entries between the installed versions
# of a set of packages and the versions contained in
# corresponding .deb files
#
# Copyright (C) 2000-2006 Matt Zimmerman <mdz@debian.org>
# Copyright (C) 2006 Pierre Habouzit <madcoder@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
#
import configparser
import getopt
import sys, os
import ALCLog
from ALChacks import _
class ALCConfig:
def __init__(self):
### Command line only options
self.apt_mode = False # "--apt" option
self.dump_seen = False
self.profile = None
### Options that can be set in the config file
self.frontend = 'pager'
self.email_address = None
self.email_format = 'text'
self.verbose = False
self.show_all = False
self.confirm = False
self.headers = False
self.debug = False
self.save_seen = None
self.which = 'both'
self.since = None
self.latest = None
self.reverse = False
self.no_network = False
self.select_frontend = False
self.ignore_apt_assume = False
self.ignore_debian_frontend = False
self.titled = True
self.log = '/var/log/apt/listchanges.log'
self.filter = None
### Internal options for managing the config file options
# - options that can be also used for command line parameters
# (after replacing '_' with '-', and adding trailing '=' if needed)
self._bool_opts = [
'confirm',
'debug',
'show_all',
'headers',
'verbose',
'reverse',
'dump_seen',
'select_frontend',
'no_network',
'ignore_apt_assume',
'ignore_debian_frontend',
'titled',
]
self._value_opts = [
'frontend',
'email_address',
'email_format',
'latest',
'log',
'filter',
'save_seen',
'since',
'which',
]
# - options that can be given only in the config file
self._cfgfile_only_opts = [
'browser',
'pager',
'xterm',
]
### Other options
self.quiet = 0
self.frontend_from_env = False
self._allowed_email_formats = ('text', 'html')
self._allowed_which = ('both', 'news', 'changelogs')
def read(self, file):
self.parser = configparser.ConfigParser()
self.parser.read(file)
def expose(self):
if self.parser.has_section(self.profile):
for option in self.parser.options(self.profile):
value = None
if self.parser.has_option(self.profile, option):
if option in self._bool_opts:
value = self.parser.getboolean(self.profile, option)
elif option in self._value_opts or option in self._cfgfile_only_opts:
value = self.parser.get(self.profile, option)
else:
ALCLog.warning(_("Unknown configuration file option: %s") % option)
continue
setattr(self, option, value)
def get(self, option, defvalue=None):
return getattr(self, option, defvalue)
def usage(self, exitcode):
if exitcode == 0:
fh = sys.stdout
else:
fh = sys.stderr
fh.write(_("Usage: apt-listchanges [options] {--apt | filename.deb ...}\n"))
sys.exit(exitcode)
def _check_allowed(self, arg, opt, allowed):
if arg in allowed:
return arg
ALCLog.error((_('Unknown argument %(arg)s for option %(opt)s. Allowed are: %(allowed)s.') %
{'arg': arg, 'opt': opt, 'allowed': ', '.join(allowed)}))
sys.exit(1)
def _check_debs(self, debs):
if self.apt_mode or self.dump_seen:
return
if not debs:
self.usage(1)
for deb in debs:
ext = os.path.splitext(deb)[1]
if ext != ".deb":
ALCLog.error(_("%(deb)s does not have '.deb' extension") % {'deb': deb})
sys.exit(1)
if not os.path.isfile(deb):
ALCLog.error(_('%(deb)s does not exist or is not a file') % {'deb': deb})
sys.exit(1)
if not os.access(deb, os.R_OK):
ALCLog.error(_('%(deb)s is not readable') % {'deb' : deb})
sys.exit(1)
def getopt(self, argv):
try:
(optlist, args) = getopt.getopt(argv[1:], 'vf:s:cah', [
# command line only
"apt", "profile=", "help",
# deprecated options for backward compatibility
"all", "save_seen=" ]
# boolean options
+ [ x.replace('_', '-') for x in self._bool_opts ]
# with value options
+ [ x.replace('_', '-')+'=' for x in self._value_opts ]
)
except getopt.GetoptError as err:
ALCLog.error(str(err))
sys.exit(1)
# Determine mode and profile before processing other options
for opt, arg in optlist:
if opt == '--profile':
self.profile = arg
elif opt == '--apt':
self.apt_mode = True
# Provide a default profile if none has been specified
if self.profile is None:
if self.apt_mode:
self.profile = 'apt'
else:
self.profile = 'cmdline'
# Expose defaults from config file
self.expose()
# Environment variables override config file
if 'APT_LISTCHANGES_FRONTEND' in os.environ:
self.frontend = os.getenv('APT_LISTCHANGES_FRONTEND')
self.frontend_from_env = True
# Prefer APT_LISTCHANGES_FRONTEND over DEBIAN_FRONTEND
self.ignore_debian_frontend = True
(since, latest, show_all) = (None, None, False)
# Command-line options override environment and config file
for opt, arg in optlist:
if opt == '--help':
self.usage(0)
elif opt in ('-v', '--verbose'):
self.verbose = True
elif opt in ('-f', '--frontend'):
self.frontend = arg
elif opt == '--email-address':
self.email_address = arg
elif opt == '--email-format':
self.email_format = self._check_allowed(arg, opt, self._allowed_email_formats)
elif opt in ('-c', '--confirm'):
self.confirm = True
elif opt in ('--since'):
since = arg
elif opt in ('--latest'):
latest = arg
elif opt in ('-a', '--show-all', '--all'):
show_all = True
elif opt in ('-h', '--headers'):
self.headers = True
elif opt in ('--save-seen', '--save_seen'):
self.save_seen = arg
elif opt == '--dump-seen':
self.dump_seen = True
elif opt == '--which':
self.which = self._check_allowed(arg, opt, self._allowed_which)
elif opt == '--debug':
self.debug = True
elif opt == '--reverse':
self.reverse = True
elif opt in ('-n', '--no-network'):
self.no_network = True
elif opt == '--select-frontend':
self.select_frontend = True
elif opt == '--ignore-apt-assume':
self.ignore_apt_assume = True
elif opt == '--ignore-debian-frontend':
self.ignore_debian_frontend = True
elif opt == '--titled':
self.titled = True
elif opt == '--untitled':
self.titled = False
elif opt in ('--log'):
self.log = arg
elif opt in ('--filter'):
self.filter = arg
if self.email_address == 'none':
self.email_address = None
if self.save_seen == 'none':
self.save_seen = None
if ((self.since is not None and self.show_all)
or (since is not None and show_all)):
ALCLog.error(_('--since=<version> and --show-all are mutually exclusive'))
sys.exit(1)
elif since is not None or show_all:
self.since = since
self.show_all = show_all
if self.since is not None:
if len(args) != 1:
ALCLog.error(_('--since=<version> expects a path to exactly one .deb archive'))
sys.exit(1)
self.save_seen = None
if ((self.latest is not None and self.show_all) or
(latest is not None and show_all)):
ALCLog.error(_('--latest=<N> and --show-all are mutually exclusive'))
sys.exit(1)
elif latest is not None or show_all:
self.latest = latest
self.show_all = show_all
if (self.apt_mode and not self.ignore_debian_frontend and
os.getenv('DEBIAN_FRONTEND', '') == 'noninteractive'):
# Force non-interactive usage
self.quiet = 1
self.confirm = False
self._check_debs(args)
return args
__all__ = [ 'ALCConfig' ]
|