* pbuilder-dist:

- Refactor to use subprocess.popen instead of os.system (LP: #398974)
  - Catch OSErrors when creating directories (LP: #671067)
  - Set HOME so pbuilder reads .pbuilderrc
  - Add bidirectional workarounds for LP: #599695 (pbuilder uses the host
    apt keyring). Complain if the target's keyring isn't installed.
* Use dpkg-vendor in ubuntutools.misc.system_distribution(), cache result.
This commit is contained in:
Stefano Rivera 2010-12-02 11:42:51 +02:00
commit 84e2835686
3 changed files with 392 additions and 371 deletions

9
debian/changelog vendored
View File

@ -13,6 +13,13 @@ ubuntu-dev-tools (0.107) UNRELEASED; urgency=low
- Add --sort-binary-packages and --keep-first (LP: #681119) - Add --sort-binary-packages and --keep-first (LP: #681119)
* grab-merge, syncpackage: Export DEB_VENDOR=Ubuntu when unpacking source * grab-merge, syncpackage: Export DEB_VENDOR=Ubuntu when unpacking source
packages. 3.0 (quilt) has optional per-vendor patch series. packages. 3.0 (quilt) has optional per-vendor patch series.
* pbuilder-dist:
- Refactor to use subprocess.popen instead of os.system (LP: #398974)
- Catch OSErrors when creating directories (LP: #671067)
- Set HOME so pbuilder reads .pbuilderrc
- Add bidirectional workarounds for LP: #599695 (pbuilder uses the host
apt keyring). Complain if the target's keyring isn't installed.
* Use dpkg-vendor in ubuntutools.misc.system_distribution(), cache result.
[ Benjamin Drung ] [ Benjamin Drung ]
* wrap-and-sort: Remove duplicate items from sorted lists. * wrap-and-sort: Remove duplicate items from sorted lists.
@ -27,7 +34,7 @@ ubuntu-dev-tools (0.107) UNRELEASED; urgency=low
* submittodebian: Encourage sending multiple independent pieces of the * submittodebian: Encourage sending multiple independent pieces of the
Ubuntu patch in separate bug reports. Ubuntu patch in separate bug reports.
-- Daniel Holbach <daniel.holbach@ubuntu.com> Tue, 30 Nov 2010 11:55:24 +0100 -- Stefano Rivera <stefanor@ubuntu.com> Thu, 02 Dec 2010 09:36:48 +0200
ubuntu-dev-tools (0.106) experimental; urgency=low ubuntu-dev-tools (0.106) experimental; urgency=low

View File

@ -2,7 +2,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright (C) 2007-2010 Siegfried-A. Gevatter <rainct@ubuntu.com> # Copyright (C) 2007-2010 Siegfried-A. Gevatter <rainct@ubuntu.com>
# With some changes by Iain Lane <iain@orangesquash.org.uk> # With some changes by Iain Lane <iain@orangesquash.org.uk>,
# Stefano Rivera <stefanor@ubuntu.com>
# Based upon pbuilder-dist-simple by Jamin Collins and Jordan Mantha. # Based upon pbuilder-dist-simple by Jamin Collins and Jordan Mantha.
# #
# ################################################################## # ##################################################################
@ -11,13 +12,13 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# See file /usr/share/common-licenses/GPL for more details. # See file /usr/share/common-licenses/GPL-2 for more details.
# #
# ################################################################## # ##################################################################
# #
@ -28,356 +29,370 @@
# configurations. For example, a symlink called pbuilder-hardy will assume # configurations. For example, a symlink called pbuilder-hardy will assume
# that the target distribution is always meant to be Ubuntu Hardy. # that the target distribution is always meant to be Ubuntu Hardy.
import sys
import os import os
import subprocess
from sys import exit, argv, stderr
import ubuntutools.misc import ubuntutools.misc
debian_distros = ['etch', 'lenny', 'squeeze', 'sid', 'stable', \ debian_distros = ['etch', 'lenny', 'squeeze', 'sid', 'stable', 'testing',
'testing', 'unstable', 'experimental'] 'unstable', 'experimental']
class pbuilder_dist: class pbuilder_dist:
def __init__(self, builder):
def __init__(self, builder): # Base directory where pbuilder will put all the files it creates.
self.base = None
# Base directory where pbuilder will put all the files it creates.
self.base = None
# Name of the operation which pbuilder should perform.
self.operation = None
# Wheter additional components should be used or not. That is,
# 'universe' and 'multiverse' for Ubuntu chroots and 'contrib'
# and 'non-free' for Debian.
self.extra_components = True
# File where the log of the last operation will be saved.
self.logfile = None
# System architecture
self.system_architecture = None
# Build architecture
self.build_architecture = None
# System's distribution
self.system_distro = None
# Target distribution
self.target_distro = None
# This is an identificative string which will either take the form
# 'distribution' or 'distribution-architecture'.
self.chroot_string = None
# Authentication method
self.auth = 'sudo'
# Builder
self.builder = builder
# Ensure that the used builder is installed
for file in os.environ['PATH'].split(':'):
if os.path.exists(os.path.join(file, builder)):
builder = ''
break
if builder:
print 'Error: Could not find "%s".' % builder
sys.exit(1)
##############################################################
self.base = os.path.expanduser(os.environ.get('PBUILDFOLDER', '~/pbuilder/'))
if not os.path.exists(self.base): # Name of the operation which pbuilder should perform.
os.makedirs(self.base) self.operation = None
if 'PBUILDAUTH' in os.environ:
self.auth = os.environ['PBUILDAUTH']
self.system_architecture = ubuntutools.misc.host_architecture()
self.system_distro = ubuntutools.misc.system_distribution()
if not self.system_architecture or not self.system_distro:
exit(1)
self.target_distro = self.system_distro
##############################################################
def __getitem__(self, name):
return getattr(self, name)
def set_target_distro(self, distro):
""" pbuilder_dist.set_target_distro(distro) -> None
Check if the given target distribution name is correct, if it
isn't know to the system ask the user for confirmation before
proceeding, and finally either save the value into the appropiate
variable or finalize pbuilder-dist's execution.
"""
if not distro.isalpha():
print 'Error: «%s» is an invalid distribution codename.' % distro
sys.exit(1)
if not os.path.isfile(os.path.join('/usr/share/debootstrap/scripts/', distro)):
if os.path.isdir('/usr/share/debootstrap/scripts/'):
# Debian experimental doesn't have a debootstrap file but
# should work nevertheless.
if distro not in debian_distros:
answer = ask('Warning: Unknown distribution «%s». Do you ' \
'want to continue [y/N]? ' % distro)
if answer not in ('y', 'Y'):
sys.exit(0)
else:
print 'Please install package "debootstrap".'
sys.exit(1)
self.target_distro = distro
def set_operation(self, operation):
""" pbuilder_dist.set_operation -> None
Check if the given string is a valid pbuilder operation and
depending on this either save it into the appropiate variable
or finalize pbuilder-dist's execution.
"""
arguments = ('create', 'update', 'build', 'clean', 'login', 'execute')
if operation not in arguments:
if operation.endswith('.dsc'):
if os.path.isfile(operation):
self.operation = 'build'
return [operation]
else:
print 'Error: Could not find file «%s».' % operation
sys.exit(1)
else:
print 'Error: «%s» is not a recognized argument.' % operation
print 'Please use one of those: ' + ', '.join(arguments) + '.'
sys.exit(1)
else:
self.operation = operation
return []
def get_command(self, remaining_arguments = None):
""" pbuilder_dist.get_command -> string
Generate the pbuilder command which matches the given configuration
and return it as a string.
"""
if not self.build_architecture:
self.chroot_string = self.target_distro
self.build_architecture = self.system_architecture
else:
self.chroot_string = '%(target_distro)s-%(build_architecture)s' % self
prefix = os.path.join(self.base, self.chroot_string)
result = '%s_result/' % prefix
if not self.logfile and self.operation != 'login':
self.logfile = os.path.normpath('%s/last_operation.log' % result)
if not os.path.isdir(result):
# Create the results directory, if it doesn't exist.
os.makedirs(result)
if self.builder == 'pbuilder':
base = '--basetgz "%s-base.tgz"' % prefix
elif self.builder == 'cowbuilder':
base = '--basepath "%s-base.cow"' % prefix
else:
print 'Error: Unrecognized builder "%s".' % self.builder
sys.exit(1)
arguments = [
'--%s' % self.operation,
base,
'--distribution "%(target_distro)s"' % self,
'--buildresult "%s"' % result,
'--aptcache "/var/cache/apt/archives/"',
'--override-config',
]
if self.logfile: # Wheter additional components should be used or not. That is,
arguments.append('--logfile %s' % self.logfile) # 'universe' and 'multiverse' for Ubuntu chroots and 'contrib'
# and 'non-free' for Debian.
if os.path.exists('/var/cache/archive/'): self.extra_components = True
arguments.append('--bindmounts "/var/cache/archive/"')
localrepo = '/var/cache/archive/%(target_distro)s' % self # File where the log of the last operation will be saved.
if os.path.exists(localrepo): self.logfile = None
arguments.append('--othermirror ' +\
'"deb file:///var/cache/archive/ %(target_distro)s/"' % self) # System architecture
self.system_architecture = None
if self.target_distro in debian_distros:
arguments.append('--mirror "ftp://ftp.debian.org/debian"') # Build architecture
# work around bug #599695 self.build_architecture = None
arguments.append('--debootstrapopts --keyring=/usr/share/keyrings/debian-archive-keyring.gpg')
components = 'main' # System's distribution
if self.extra_components: self.system_distro = None
components += ' contrib non-free'
else: # Target distribution
if self.build_architecture in ('amd64','i386'): self.target_distro = None
arguments.append('--mirror "http://archive.ubuntu.com/ubuntu/"')
elif self.build_architecture == 'powerpc' and self.target_distro == 'dapper': # This is an identificative string which will either take the form
arguments.append('--mirror "http://archive.ubuntu.com/ubuntu/"') # 'distribution' or 'distribution-architecture'.
else: self.chroot_string = None
arguments.append('--mirror "http://ports.ubuntu.com/ubuntu-ports/"')
components = 'main restricted' # Authentication method
if self.extra_components: self.auth = 'sudo'
components += ' universe multiverse'
# Builder
self.builder = builder
# Ensure that the used builder is installed
paths = set(os.environ['PATH'].split(':'))
paths |= set(('/sbin', '/usr/sbin', '/usr/local/sbin'))
if not any(os.path.exists(os.path.join(p, builder)) for p in paths):
print >> stderr, 'Error: Could not find "%s".' % builder
exit(1)
##############################################################
self.base = os.path.expanduser(os.environ.get('PBUILDFOLDER',
'~/pbuilder/'))
if not os.path.isdir(self.base):
try:
os.makedirs(self.base)
except os.OSError:
print >> stderr, ('Error: Cannot create base directory "%s"'
% self.base)
exit(1)
if 'PBUILDAUTH' in os.environ:
self.auth = os.environ['PBUILDAUTH']
self.system_architecture = ubuntutools.misc.host_architecture()
self.system_distro = ubuntutools.misc.system_distribution()
if not self.system_architecture or not self.system_distro:
exit(1)
self.target_distro = self.system_distro
def set_target_distro(self, distro):
""" pbuilder_dist.set_target_distro(distro) -> None
Check if the given target distribution name is correct, if it
isn't know to the system ask the user for confirmation before
proceeding, and finally either save the value into the appropiate
variable or finalize pbuilder-dist's execution.
"""
if not distro.isalpha():
print >> stderr, ('Error: "%s" is an invalid distribution codename.'
% distro)
exit(1)
if not os.path.isfile(os.path.join('/usr/share/debootstrap/scripts/',
distro)):
if os.path.isdir('/usr/share/debootstrap/scripts/'):
# Debian experimental doesn't have a debootstrap file but
# should work nevertheless.
if distro not in debian_distros:
answer = ask(('Warning: Unknown distribution "%s". Do you '
'want to continue [y/N]? ') % distro)
if answer not in ('y', 'Y'):
exit(0)
else:
print >> stderr, 'Please install package "debootstrap".'
exit(1)
self.target_distro = distro
def set_operation(self, operation):
""" pbuilder_dist.set_operation -> None
Check if the given string is a valid pbuilder operation and
depending on this either save it into the appropiate variable
or finalize pbuilder-dist's execution.
"""
arguments = ('create', 'update', 'build', 'clean', 'login', 'execute')
if operation not in arguments:
if operation.endswith('.dsc'):
if os.path.isfile(operation):
self.operation = 'build'
return [operation]
else:
print >> stderr, ('Error: Could not find file "%s".'
% operation)
exit(1)
else:
print >> stderr, (
'Error: "%s" is not a recognized argument.\n'
'Please use one of these: %s.'
) % (operation, ', '.join(arguments))
exit(1)
else:
self.operation = operation
return []
def get_command(self, remaining_arguments = None):
""" pbuilder_dist.get_command -> string
Generate the pbuilder command which matches the given configuration
and return it as a string.
"""
if not self.build_architecture:
self.chroot_string = self.target_distro
self.build_architecture = self.system_architecture
else:
self.chroot_string = (self.target_distro + '-'
+ self.build_architecture)
prefix = os.path.join(self.base, self.chroot_string)
result = '%s_result/' % prefix
if not self.logfile and self.operation != 'login':
self.logfile = os.path.normpath('%s/last_operation.log' % result)
if not os.path.isdir(result):
try:
os.makedirs(result)
except os.OSError:
print >> stderr, ('Error: Cannot create results directory "%s"'
% result)
exit(1)
arguments = [
'--%s' % self.operation,
'--distribution', self.target_distro,
'--buildresult', result,
'--aptcache', '/var/cache/apt/archives/',
'--override-config',
]
if self.builder == 'pbuilder':
arguments += ['--basetgz', prefix + '-base.tgz']
elif self.builder == 'cowbuilder':
arguments += ['--basepath', prefix + '-base.cow']
else:
print >> stderr, 'Error: Unrecognized builder "%s".' % self.builder
exit(1)
if self.logfile:
arguments += ['--logfile', self.logfile]
if os.path.exists('/var/cache/archive/'):
arguments += ['--bindmounts', '/var/cache/archive/']
localrepo = '/var/cache/archive/' + self.target_distro
if os.path.exists(localrepo):
arguments += [
'--othermirror ',
'deb file:///var/cache/archive/ %s/' % self.target_distro,
]
if self.target_distro in debian_distros:
arguments += ['--mirror', 'http://ftp.debian.org/debian']
components = 'main'
if self.extra_components:
components += ' contrib non-free'
else:
if self.build_architecture in ('amd64', 'i386'):
arguments += ['--mirror', 'http://archive.ubuntu.com/ubuntu/']
elif (self.build_architecture == 'powerpc'
and self.target_distro == 'dapper'):
arguments += ['--mirror', 'http://archive.ubuntu.com/ubuntu/']
else:
arguments += ['--mirror',
'http://ports.ubuntu.com/ubuntu-ports/']
components = 'main restricted'
if self.extra_components:
components += ' universe multiverse'
# Work around LP:#599695
if (ubuntutools.misc.system_distribution() == 'Debian'
and self.target_distro not in debian_distros):
if not os.path.exists(
'/usr/share/keyrings/ubuntu-archive-keyring.gpg'):
print >> stderr, 'Error: ubuntu-keyring not installed'
exit(1)
arguments += [
'--debootstrapopts',
'--keyring=/usr/share/keyrings/ubuntu-archive-keyring.gpg',
]
elif (ubuntutools.misc.system_distribution() == 'Ubuntu'
and self.target_distro in debian_distros):
if not os.path.exists(
'/usr/share/keyrings/debian-archive-keyring.gpg'):
print >> stderr, 'Error: debian-archive-keyring not installed'
exit(1)
arguments += [
'--debootstrapopts',
'--keyring=/usr/share/keyrings/debian-archive-keyring.gpg',
]
arguments += ['--components', components]
if self.build_architecture != self.system_architecture:
arguments += ['--debootstrapopts',
'--arch=' + self.build_architecture]
apt_conf_dir = os.path.join(self.base,
'etc/%s/apt.conf' % self.target_distro)
if os.path.exists(apt_conf_dir):
arguments += ['--aptconfdir', apt_conf_dir]
# Append remaining arguments
if remaining_arguments:
arguments.extend(remaining_arguments)
# Export the distribution and architecture information to the
# environment so that it is accessible to ~/.pbuilderrc (LP: #628933).
return [
self.auth,
'HOME=' + os.path.expanduser('~'),
'ARCH=' + self.build_architecture,
'DIST=' + self.target_distro,
self.builder,
] + arguments
arguments.append('--components "%s"' % components)
if self.build_architecture != self.system_architecture:
arguments.append('--debootstrapopts --arch="%(build_architecture)s"' % self)
apt_conf_dir = os.path.join(self.base, 'etc/%(target_distro)s/apt.conf' % self)
if os.path.exists(apt_conf_dir):
arguments.append('--aptconfdir "%s"' % apt_conf_dir)
# Append remaining arguments
if remaining_arguments:
arguments.extend(remaining_arguments)
def quote(argument):
""" quote(argument) -> string
Try to guess any missing quotes around the arguments so that
their meaning doesn't get lost (see LP: #398989).
"""
if argument.startswith('--'):
if '=' in argument:
return '%s="%s"' % tuple(argument.split('=', 1))
return argument
return '"%s"' % argument
# Export the distribution and architecture information to the
# environment so that it is accessible to ~/.pbuilderrc (LP: #628933).
return '%s ARCH="%s" DIST="%s" /usr/sbin/%s %s' % (self.auth,
self.build_architecture, self.target_distro, self.builder,
' '.join(map(quote, arguments)))
def ask(question): def ask(question):
""" ask(question) -> string """ ask(question) -> string
Ask the given question and return the answer. Also catch Ask the given question and return the answer. Also catch
KeyboardInterrupt (Ctrl+C) and EOFError (Ctrl+D) exceptions and KeyboardInterrupt (Ctrl+C) and EOFError (Ctrl+D) exceptions and
immediately return None if one of those is found. immediately return None if one of those is found.
"""
""" try:
answer = raw_input(question)
try: except (KeyboardInterrupt, EOFError):
answer = raw_input(question) print
except (KeyboardInterrupt, EOFError): answer = None
print
answer = None return answer
return answer
def help(exit_code = 0): def help(exit_code = 0):
""" help() -> None """ help() -> None
Print a help message for pbuilder-dist, and exit with the given code. Print a help message for pbuilder-dist, and exit with the given code.
"""
""" print 'See man pbuilder-dist for more information.'
print 'See man pbuilder-dist for more information.' exit(exit_code)
sys.exit(exit_code)
def main(): def main():
""" main() -> None """ main() -> None
This is pbuilder-dist's main function. It creates a pbuilder_dist This is pbuilder-dist's main function. It creates a pbuilder_dist
object, modifies all necessary settings taking data from the object, modifies all necessary settings taking data from the
executable's name and command line options and finally either ends executable's name and command line options and finally either ends
the script and runs pbuilder itself or exists with an error message. the script and runs pbuilder itself or exists with an error message.
"""
""" script_name = os.path.basename(argv[0])
parts = script_name.split('-')
script_name = os.path.basename(sys.argv[0])
parts = script_name.split('-') # Copy arguments into another list for save manipulation
args = argv[1:]
# Copy arguments into another list for save manipulation
args = sys.argv[1:] if ('-' in script_name and parts[0] not in ('pbuilder', 'cowbuilder')
or len(parts) > 3):
if '-' in script_name and (parts[0] != 'pbuilder' and \ print >> stderr, ('Error: "%s" is not a valid name for a '
parts[0] != 'cowbuilder') or len(parts) > 3: '"pbuilder-dist" executable.') % script_name
print 'Error: «%s» is not a valid name for a «pbuilder-dist» executable.' % script_name exit(1)
sys.exit(1)
if len(args) < 1:
if len(args) < 1: print >> stderr, 'Insufficient number of arguments.'
print 'Insufficient number of arguments.' help(1)
help(1)
if args[0] in ('-h', '--help', 'help'):
if args[0] in ('-h', '--help', 'help'): help(0)
help(0)
app = pbuilder_dist(parts[0])
app = pbuilder_dist(parts[0])
if len(parts) > 1 and parts[1] != 'dist' and '.' not in parts[1]:
if len(parts) > 1 and parts[1] != 'dist' and '.' not in parts[1]: app.set_target_distro(parts[1])
app.set_target_distro(parts[1]) else:
else: app.set_target_distro(args.pop(0))
app.set_target_distro(args.pop(0))
if len(parts) > 2:
if len(parts) > 2: requested_arch = parts[2]
requested_arch = parts[2] elif len(args) > 0 and args[0] in (
elif len(args) > 0 and args[0] in ("alpha", "amd64", "arm", "armeb", 'alpha', 'amd64', 'arm', 'armeb', 'armel', 'i386', 'lpia', 'm68k',
"armel", "i386", "lpia", "m68k", "mips", "mipsel", "powerpc", "ppc64", 'mips', 'mipsel', 'powerpc', 'ppc64', 'sh4', 'sh4eb', 'sparc',
"sh4", "sh4eb", "sparc", "sparc64"): 'sparc64'):
requested_arch = args.pop(0) requested_arch = args.pop(0)
else: else:
requested_arch = None requested_arch = None
if requested_arch: if requested_arch:
app.build_architecture = requested_arch app.build_architecture = requested_arch
# For some foreign architectures we need to use qemu # For some foreign architectures we need to use qemu
if requested_arch != app.system_architecture and (app.system_architecture, if (requested_arch != app.system_architecture
requested_arch) not in [("amd64", "i386"), ("amd64", "lpia"), and (app.system_architecture, requested_arch) not in [
("arm", "armel"), ("armel", "arm"), ("i386", "lpia"), ("lpia", "i386"), ('amd64', 'i386'), ('amd64', 'lpia'), ('arm', 'armel'),
("powerpc", "ppc64"), ("ppc64", "powerpc"), ("sparc", "sparc64"), ('armel', 'arm'), ('i386', 'lpia'), ('lpia', 'i386'),
("sparc64", "sparc")]: ('powerpc', 'ppc64'), ('ppc64', 'powerpc'),
args.append('--debootstrap qemu-debootstrap') ('sparc', 'sparc64'), ('sparc64', 'sparc')]):
args += ['--debootstrap', 'qemu-debootstrap']
if 'mainonly' in sys.argv or '--main-only' in sys.argv:
app.extra_components = False if 'mainonly' in argv or '--main-only' in argv:
if 'mainonly' in sys.argv: app.extra_components = False
args.remove('mainonly') if 'mainonly' in argv:
else: args.remove('mainonly')
args.remove('--main-only') else:
args.remove('--main-only')
if len(args) < 1:
print 'Insufficient number of arguments.' if len(args) < 1:
help(1) print >> stderr, 'Insufficient number of arguments.'
help(1)
# Parse the operation
args = app.set_operation(args.pop(0)) + args # Parse the operation
args = app.set_operation(args.pop(0)) + args
if app.operation == 'build' and not '.dsc' in ' '.join(args):
print 'Error: You have to specify a .dsc file if you want to build.' if app.operation == 'build' and '.dsc' not in ' '.join(args):
sys.exit(1) print >> stderr, ('Error: You have to specify a .dsc file if you want '
'to build.')
# Execute the pbuilder command exit(1)
if not '--debug-echo' in args:
sys.exit(os.system(app.get_command(args))) # Execute the pbuilder command
else: if not '--debug-echo' in args:
print app.get_command((args)).replace( exit(subprocess.call(app.get_command(args)))
' --debug-echo', '') else:
print app.get_command([arg for arg in args if arg != '--debug-echo'])
if __name__ == '__main__': if __name__ == '__main__':
try:
try: main()
main() except KeyboardInterrupt:
except KeyboardInterrupt: print >> stderr, 'Manually aborted.'
print 'Manually aborted.' exit(1)
sys.exit(1)

View File

@ -10,7 +10,7 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3 # as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@ -26,71 +26,70 @@ from subprocess import Popen, PIPE
from ubuntutools.lp.udtexceptions import PocketDoesNotExistError from ubuntutools.lp.udtexceptions import PocketDoesNotExistError
_system_distribution = None
def system_distribution(): def system_distribution():
""" system_distro() -> string """ system_distro() -> string
Detect the system's distribution and return it as a string. If the Detect the system's distribution and return it as a string. If the
name of the distribution can't be determined, print an error message name of the distribution can't be determined, print an error message
and return None. and return None.
""" """
# We try to avoid calling the "lsb_release" as looking up the value global _system_distribution
# directly is faster. However, Debian doesn't have /etc/lsb-release if _system_distribution is None:
# so we need to fallback to the former there. try:
if os.path.isfile('/etc/lsb-release'): if os.path.isfile('/usr/bin/dpkg-vendor'):
for line in open('/etc/lsb-release'): p = Popen(('dpkg-vendor', '--query', 'vendor'), stdout=PIPE)
line = line.strip() else:
if line.startswith('DISTRIB_CODENAME'): p = Popen(('lsb_release', '-cs'), stdout=PIPE)
return line[17:] output = p.communicate()[0]
else: except OSError:
import commands print 'Error: Could not determine what distribution you are running.'
output = commands.getoutput('lsb_release -cs') return None
if output: if p.returncode != 0:
return output print 'Error determininng system distribution'
print 'Error: Could not determine what distribution you are running.' return None
return None _system_distribution = output.strip()
return _system_distribution
def host_architecture(): def host_architecture():
""" host_architecture -> string """ host_architecture -> string
Detect the host's architecture and return it as a string. If the Detect the host's architecture and return it as a string. If the
architecture can't be determined, print an error message and return None. architecture can't be determined, print an error message and return None.
""" """
arch = Popen(['dpkg', '--print-architecture'], stdout=PIPE, \ arch = Popen(['dpkg', '--print-architecture'], stdout=PIPE, \
stderr=PIPE).communicate()[0].split() stderr=PIPE).communicate()[0].split()
if not arch or 'not found' in arch[0]: if not arch or 'not found' in arch[0]:
print 'Error: Not running on a Debian based system; could not ' \ print 'Error: Not running on a Debian based system; could not ' \
'detect its architecture.' 'detect its architecture.'
return None return None
return arch[0] return arch[0]
def readlist(filename, uniq=True): def readlist(filename, uniq=True):
""" readlist(filename, uniq) -> list """ readlist(filename, uniq) -> list
Read a list of words from the indicated file. If 'uniq' is True, filter Read a list of words from the indicated file. If 'uniq' is True, filter
out duplicated words. out duplicated words.
""" """
if not os.path.isfile(filename): if not os.path.isfile(filename):
print 'File "%s" does not exist.' % filename print 'File "%s" does not exist.' % filename
return False return False
content = open(filename).read().replace('\n', ' ').replace(',', ' ') content = open(filename).read().replace('\n', ' ').replace(',', ' ')
if not content.strip(): if not content.strip():
print 'File "%s" is empty.' % filename print 'File "%s" is empty.' % filename
return False return False
items = [item for item in content.split() if item] items = [item for item in content.split() if item]
if uniq: if uniq:
items = list(set(items)) items = list(set(items))
return items return items
def splitReleasePocket(release): def splitReleasePocket(release):