diff -Nru xdeb-0.6.6/aptutils.py xdeb-0.6.7/aptutils.py --- xdeb-0.6.6/aptutils.py 2012-05-23 09:03:04.000000000 +0000 +++ xdeb-0.6.7/aptutils.py 2017-07-10 13:37:39.000000000 +0000 @@ -14,10 +14,7 @@ import apt import apt_pkg import aptsources.sourceslist -try: - from debian import deb822, debian_support -except ImportError: - from debian_bundle import deb822, debian_support +from debian import deb822, debian_support import utils @@ -34,20 +31,22 @@ def sources_list_path(options): return os.path.join(os.path.realpath(options.destdir), 'sources.list') + def lists_path(options): return os.path.join(os.path.realpath(options.destdir), 'lists.apt') + def pkgcache_path(options): return os.path.join(os.path.realpath(options.destdir), 'pkgcache.bin') + def srcpkgcache_path(options): return os.path.join(os.path.realpath(options.destdir), 'srcpkgcache.bin') def apt_options(options): '''Return some standard APT options in command-line format.''' - return ['--allow-unauthenticated', - '-o', 'Dir::State::Lists=%s' % lists_path(options), + return ['-o', 'Dir::State::Lists=%s' % lists_path(options), '-o', 'Dir::Cache::pkgcache=%s' % pkgcache_path(options), '-o', 'Dir::Cache::srcpkgcache=%s' % srcpkgcache_path(options)] @@ -59,12 +58,11 @@ def update_destdir(options): # We can't use this until we've stopped using apt-get to install # build-dependencies. - #cache.update(sources_list='%s.destdir' % sources_list_path(options)) + # cache.update(sources_list='%s.destdir' % sources_list_path(options)) command = ['apt-get'] command.extend(apt_options(options)) command.extend( - ['--allow-unauthenticated', - '-o', 'Dir::Etc::sourcelist=%s.destdir' % sources_list_path(options), + ['-o', 'Dir::Etc::sourcelist=%s.destdir' % sources_list_path(options), '-o', 'Dir::Etc::sourceparts=#clear', '-o', 'APT::List-Cleanup=false', '-o', 'Debug::NoLocking=true', @@ -76,23 +74,23 @@ apt_conf_written = False + def update_apt_repository(options, force_rebuild=False): global apt_conf_written apt_conf = os.path.join(options.destdir, 'apt.conf') if not apt_conf_written: - apt_conf_file = open(apt_conf, 'w') - print(''' + with open(apt_conf, 'w') as apt_conf_file: + print(''' Dir { - ArchiveDir "."; - CacheDir "."; + ArchiveDir "."; + CacheDir "."; }; BinDirectory "." { - Packages "Packages"; - BinCacheDB "pkgcache.apt"; - FileList "filelist.apt"; + Packages "Packages"; + BinCacheDB "pkgcache.apt"; + FileList "filelist.apt"; };''', file=apt_conf_file) - apt_conf_file.close() apt_conf_written = True if force_rebuild: @@ -103,11 +101,10 @@ raise filelist = os.path.join(options.destdir, 'filelist.apt') - filelist_file = open(filelist, 'w') - for name in sorted(os.listdir(options.destdir)): - if name.endswith('.deb'): - print('./%s' % name, file=filelist_file) - filelist_file.close() + with open(filelist, 'w') as filelist_file: + for name in sorted(os.listdir(options.destdir)): + if name.endswith('.deb'): + print('./%s' % name, file=filelist_file) utils.spawn(['apt-ftparchive', 'generate', 'apt.conf'], cwd=options.destdir) @@ -119,21 +116,19 @@ """Configure APT the way we like it. We need a custom sources.list.""" system_sources_list = apt_pkg.config.find_file('Dir::Etc::sourcelist') sources_list = sources_list_path(options) - sources_list_file = open('%s.destdir' % sources_list, 'w') - print(('deb file:%s ./' % os.path.realpath(options.destdir)), - file=sources_list_file) - sources_list_file.close() - sources_list_file = open(sources_list, 'w') - print(('deb file:%s ./' % os.path.realpath(options.destdir)), - file=sources_list_file) - try: - system_sources_list_file = open(system_sources_list) - shutil.copyfileobj(system_sources_list_file, sources_list_file) - system_sources_list_file.close() - except IOError as e: - if e.errno != errno.ENOENT: - raise - sources_list_file.close() + real_destdir = os.path.realpath(options.destdir) + with open('%s.destdir' % sources_list, 'w') as sources_list_file: + print(('deb [trusted=yes] file:%s ./' % real_destdir), + file=sources_list_file) + with open(sources_list, 'w') as sources_list_file: + print(('deb [trusted=yes] file:%s ./' % real_destdir), + file=sources_list_file) + try: + with open(system_sources_list) as system_sources_list_file: + shutil.copyfileobj(system_sources_list_file, sources_list_file) + except IOError as e: + if e.errno != errno.ENOENT: + raise apt_pkg.config.set('Dir::Etc::sourcelist', sources_list) system_lists = apt_pkg.config.find_file('Dir::State::Lists') @@ -156,8 +151,6 @@ apt_pkg.config.set('Dir::Cache::pkgcache', pkgcache_path(options)) apt_pkg.config.set('Dir::Cache::srcpkgcache', srcpkgcache_path(options)) - apt_pkg.config.set('APT::Get::AllowUnauthenticated', str(True)) - update_apt_repository(options) @@ -198,27 +191,24 @@ for source in sources: try: - source_file = open(os.path.join(listdir, source)) + with open(os.path.join(listdir, source)) as source_file: + tag_file = apt_pkg.TagFile(source_file) + for src_stanza in tag_file: + if ('package' not in src_stanza or + 'version' not in src_stanza or + 'binary' not in src_stanza): + continue + src = src_stanza['package'] + if (src not in srcrec or + (debian_support.Version(src_stanza['version']) > + debian_support.Version(version[src]))): + srcrec[src] = str(src_stanza) + version[src] = src_stanza['version'] + binaries[src] = src_stanza['binary'] except IOError: continue - try: - tag_file = apt_pkg.TagFile(source_file) - for src_stanza in tag_file: - if ('package' not in src_stanza or - 'version' not in src_stanza or - 'binary' not in src_stanza): - continue - src = src_stanza['package'] - if (src not in srcrec or - (debian_support.Version(src_stanza['version']) > - debian_support.Version(version[src]))): - srcrec[src] = str(src_stanza) - version[src] = src_stanza['version'] - binaries[src] = src_stanza['binary'] - finally: - source_file.close() - for src, pkgs in binaries.iteritems(): + for src, pkgs in binaries.items(): for pkg in re_comma_sep.split(pkgs): pkgsrc[pkg] = src @@ -226,8 +216,10 @@ class MultipleProvidesException(RuntimeError): pass + seen_providers = {} + def get_real_pkg(pkg): """Get the real name of binary package pkg, resolving Provides.""" if pkg in cache and cache[pkg].versions: @@ -308,6 +300,7 @@ apt_architectures = None + def apt_architecture_allowed(arch): """Check if apt can acquire packages for the host architecture.""" global apt_architectures diff -Nru xdeb-0.6.6/.bzr-builddeb/default.conf xdeb-0.6.7/.bzr-builddeb/default.conf --- xdeb-0.6.6/.bzr-builddeb/default.conf 1970-01-01 00:00:00.000000000 +0000 +++ xdeb-0.6.7/.bzr-builddeb/default.conf 2017-07-10 13:37:39.000000000 +0000 @@ -0,0 +1,2 @@ +[BUILDDEB] +native = True diff -Nru xdeb-0.6.6/checks/xdeb xdeb-0.6.7/checks/xdeb --- xdeb-0.6.6/checks/xdeb 2011-09-16 09:45:58.000000000 +0000 +++ xdeb-0.6.7/checks/xdeb 1970-01-01 00:00:00.000000000 +0000 @@ -1,167 +0,0 @@ -# xdeb -- lintian check script -*- perl -*- - -# This started as a cut-down version of the Emdebian Lintian check script. -# Its copyright notice follows: -# -# Copyright (C) 2008 Neil Williams -# -# If at all possible, this script should only use perl modules -# that lintian itself would use - or functions that can be migrated -# into such modules. -# -# This package 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 3 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, see . - -package Lintian::xdeb; -use strict; -use Lintian::Tags; -use Util; -use vars qw( %archdetecttable); - -# debug -use Data::Dumper; - -# need to make this table more accessible in Debian::DpkgCross -# and then do the comparison in that module (which can migrate into -# dpkg-dev). -%archdetecttable = ( - 'i386' => 'ELF 32-bit LSB .* 80386', - 'sparc' => 'ELF 32-bit MSB .* SPARC', - 'sparc64' => 'ELF 64-bit MSB .* SPARC', - 'alpha' => 'ELF 64-bit LSB .* Alpha', - 'm68k' => 'ELF 32-bit MSB .* 680[02]0', - 'arm' => 'ELF 32-bit LSB .* ARM', - 'armeb' => 'ELF 32-bit MSB .* ARM', - 'armel' => 'ELF 32-bit LSB .* SYSV', - 'armhf' => 'ELF 32-bit LSB .* SYSV', - 'powerpc' => 'ELF 32-bit MSB .* PowerPC', - 'powerpc64' => 'ELF 64-bit MSB .* PowerPC', - 'mips' => 'ELF 32-bit MSB .* MIPS', - 'mipsel' => 'ELF 32-bit LSB .* MIPS', - 'hppa' => 'ELF 32-bit MSB .* PA-RISC', - 's390' => 'ELF 32-bit MSB .* S.390', - 's390x' => 'ELF 64-bit MSB .* S.390', - 'ia64' => 'ELF 64-bit LSB .* IA-64', - 'm32r' => 'ELF 32-bit MSB .* M32R', - 'amd64' => 'ELF 64-bit LSB .* x86-64', - 'w32-i386' => '80386 COFF', - 'AR' => 'current ar archive'); - -# currently unused, pending changes in lintian. -sub set { - our $arch; - my $pkg = shift; - my $type = shift; - my $tdeb = 0; - my $tags = $Lintian::Tags::GLOBAL; - my $build = `dpkg-architecture -qDEB_BUILD_ARCH`; - chomp($build); - $tdeb = 1 if ($pkg =~ /locale/); - if ($type eq "source") - { - $tags->suppress ("debian-rules-missing-required-target"); - # might want to fix this one. - $tags->suppress ("debian-files-list-in-source"); - $tags->suppress ("native-package-with-dash-version"); - $tags->suppress ("build-depends-indep-without-arch-indep"); - $tags->suppress ("source-nmu-has-incorrect-version-number"); - $tags->suppress ("changelog-should-mention-nmu"); - return; - } - if ($tdeb > 0) - { - $tags->suppress ("extended-description-is-empty"); - $tags->suppress ("no-md5sums-control-file"); - $tags->suppress ("no-copyright-file"); - # need TDeb checks here. - $tags->suppress ("debian-rules-missing-required-target *"); - # might want to fix this one. - $tags->suppress ("debian-files-list-in-source"); - $tags->suppress ("native-package-with-dash-version"); - return; - } - $tags->suppress ("no-copyright-file"); - $tags->suppress ("python-script-but-no-python-dep"); - $tags->suppress ("binary-without-manpage"); - $tags->suppress ("binary-or-shlib-defines-rpath"); - $tags->suppress ("build-depends-indep-without-arch-indep"); -} - -# there are problems with some of these tests - the number of results -# is higher than the number of detections because certain tests get -# repeated for unrelated files unpacked alongside problematic files. - -sub run { - - our %RPATH; - my $pkg = shift; - my $type = shift; - my $info = shift; - my $tdeb = 0; - my $tags = $Lintian::Tags::GLOBAL; - my $build = `dpkg-architecture -qDEB_BUILD_ARCH`; - chomp($build); - $tdeb = 1 if ($pkg =~ /locale/); - my %seen=(); - my $arch = $info->field('architecture'); - if ($type eq "source") - { - $tags->suppress ("debian-rules-missing-required-target"); - # might want to fix this one. - $tags->suppress ("debian-files-list-in-source"); - $tags->suppress ("native-package-with-dash-version"); - $tags->suppress ("build-depends-indep-without-arch-indep"); - $tags->suppress ("source-nmu-has-incorrect-version-number"); - $tags->suppress ("changelog-should-mention-nmu"); - return; - } - # process all files in package - for my $file (sort keys %{$info->file_info}) - { - my $fileinfo = $info->file_info->{$file}; - $tags->suppress ("no-copyright-file"); - $tags->suppress ("python-script-but-no-python-dep"); - $tags->suppress ("binary-without-manpage"); - # binary or object file? - if ($fileinfo =~ m/^[^,]*\bELF\b/) - { - $tags->suppress ("binary-or-shlib-defines-rpath"); - $tags->suppress ("build-depends-indep-without-arch-indep"); - # rpath is mandatory when cross building. - if (exists $RPATH{$file} and - grep { !m,^/usr/lib/(games/)?\Q$pkg\E(?:/|\z), } split(/:/, $RPATH{$file})) - { - tag "binary-or-shlib-omits-rpath", "$file $RPATH{$file}"; - } - if ($arch eq "armel" or $arch eq "armhf") - { - tag "binary-is-wrong-architecture", "$file" - unless ($fileinfo =~ /ARM, version 1 \(SYSV\)/); - } - elsif ($arch eq "i386") - { - tag "binary-is-wrong-architecture", "$file" - unless ($fileinfo =~ /x86-64, version 1 \(SYSV\)/) or - ($fileinfo =~ /$archdetecttable{$arch}/); - } - else - { - tag "binary-is-wrong-architecture", "$file" - unless ($fileinfo =~ /$archdetecttable{$arch}/); - } - } - } - close (IN); -} - -1; diff -Nru xdeb-0.6.6/checks/xdeb.pm xdeb-0.6.7/checks/xdeb.pm --- xdeb-0.6.6/checks/xdeb.pm 1970-01-01 00:00:00.000000000 +0000 +++ xdeb-0.6.7/checks/xdeb.pm 2017-07-11 11:04:07.000000000 +0000 @@ -0,0 +1,168 @@ +# xdeb -- lintian check script -*- perl -*- + +# This started as a cut-down version of the Emdebian Lintian check script. +# Its copyright notice follows: +# +# Copyright (C) 2008 Neil Williams +# +# If at all possible, this script should only use perl modules +# that lintian itself would use - or functions that can be migrated +# into such modules. +# +# This package 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 3 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, see . + +package Lintian::xdeb; +use strict; +use Lintian::Tags qw(tag); +use Lintian::Util; +use vars qw( %archdetecttable); + +# debug +use Data::Dumper; + +# need to make this table more accessible in Debian::DpkgCross +# and then do the comparison in that module (which can migrate into +# dpkg-dev). +%archdetecttable = ( + 'i386' => 'ELF 32-bit LSB .* 80386', + 'sparc' => 'ELF 32-bit MSB .* SPARC', + 'sparc64' => 'ELF 64-bit MSB .* SPARC', + 'alpha' => 'ELF 64-bit LSB .* Alpha', + 'm68k' => 'ELF 32-bit MSB .* 680[02]0', + 'arm' => 'ELF 32-bit LSB .* ARM', + 'armeb' => 'ELF 32-bit MSB .* ARM', + 'armel' => 'ELF 32-bit LSB .* SYSV', + 'armhf' => 'ELF 32-bit LSB .* SYSV', + 'powerpc' => 'ELF 32-bit MSB .* PowerPC', + 'powerpc64' => 'ELF 64-bit MSB .* PowerPC', + 'mips' => 'ELF 32-bit MSB .* MIPS', + 'mipsel' => 'ELF 32-bit LSB .* MIPS', + 'hppa' => 'ELF 32-bit MSB .* PA-RISC', + 's390' => 'ELF 32-bit MSB .* S.390', + 's390x' => 'ELF 64-bit MSB .* S.390', + 'ia64' => 'ELF 64-bit LSB .* IA-64', + 'm32r' => 'ELF 32-bit MSB .* M32R', + 'amd64' => 'ELF 64-bit LSB .* x86-64', + 'w32-i386' => '80386 COFF', + 'AR' => 'current ar archive'); + +# currently unused, pending changes in lintian. +sub set { + our $arch; + my $pkg = shift; + my $type = shift; + my $tdeb = 0; + my $tags = $Lintian::Tags::GLOBAL; + my $build = `dpkg-architecture -qDEB_BUILD_ARCH`; + chomp($build); + $tdeb = 1 if ($pkg =~ /locale/); + if ($type eq "source") + { +# $tags->suppress ("debian-rules-missing-required-target"); +# # might want to fix this one. +# $tags->suppress ("debian-files-list-in-source"); +# $tags->suppress ("native-package-with-dash-version"); +# $tags->suppress ("build-depends-indep-without-arch-indep"); +# $tags->suppress ("source-nmu-has-incorrect-version-number"); +# $tags->suppress ("changelog-should-mention-nmu"); + return; + } + if ($tdeb > 0) + { +# $tags->suppress ("extended-description-is-empty"); +# $tags->suppress ("no-md5sums-control-file"); +# $tags->suppress ("no-copyright-file"); +# # need TDeb checks here. +# $tags->suppress ("debian-rules-missing-required-target *"); +# # might want to fix this one. +# $tags->suppress ("debian-files-list-in-source"); +# $tags->suppress ("native-package-with-dash-version"); + return; + } +# $tags->suppress ("no-copyright-file"); +# $tags->suppress ("python-script-but-no-python-dep"); +# $tags->suppress ("binary-without-manpage"); +# $tags->suppress ("binary-or-shlib-defines-rpath"); +# $tags->suppress ("build-depends-indep-without-arch-indep"); +} + +# there are problems with some of these tests - the number of results +# is higher than the number of detections because certain tests get +# repeated for unrelated files unpacked alongside problematic files. + +sub run { + + our %RPATH; + my $pkg = shift; + my $type = shift; + my $info = shift; + my $tdeb = 0; + my $tags = $Lintian::Tags::GLOBAL; + my $build = `dpkg-architecture -qDEB_BUILD_ARCH`; + chomp($build); + $tdeb = 1 if ($pkg =~ /locale/); + my %seen=(); + my $arch = $info->field('architecture'); + if ($type eq "source") + { +# $tags->suppress ("debian-rules-missing-required-target"); +# # might want to fix this one. +# $tags->suppress ("debian-files-list-in-source"); +# $tags->suppress ("native-package-with-dash-version"); +# $tags->suppress ("build-depends-indep-without-arch-indep"); +# $tags->suppress ("source-nmu-has-incorrect-version-number"); +# $tags->suppress ("changelog-should-mention-nmu"); + return; + } + # process all files in package + foreach my $file ($info->sorted_index) + { + my $fileinfo = $file->file_info; + next if not $file->is_file; +# $tags->suppress ("no-copyright-file"); +# $tags->suppress ("python-script-but-no-python-dep"); +# $tags->suppress ("binary-without-manpage"); + # binary or object file? + if ($fileinfo =~ m/^[^,]*\bELF\b/) + { +# $tags->suppress ("binary-or-shlib-defines-rpath"); +# $tags->suppress ("build-depends-indep-without-arch-indep"); + # rpath is mandatory when cross building. + if (exists $RPATH{$file} and + grep { !m,^/usr/lib/(games/)?\Q$pkg\E(?:/|\z), } split(/:/, $RPATH{$file})) + { + tag "binary-or-shlib-omits-rpath", "$file $RPATH{$file}"; + } + if ($arch eq "armel" or $arch eq "armhf") + { + tag "binary-is-wrong-architecture", "$file" + unless ($fileinfo =~ /ARM,( EABI5)? version 1 \(SYSV\)/); + } + elsif ($arch eq "i386") + { + tag "binary-is-wrong-architecture", "$file" + unless ($fileinfo =~ /x86-64, version 1 \(SYSV\)/) or + ($fileinfo =~ /$archdetecttable{$arch}/); + } + else + { + tag "binary-is-wrong-architecture", "$file" + unless ($fileinfo =~ /$archdetecttable{$arch}/); + } + } + } + close (IN); +} + +1; diff -Nru xdeb-0.6.6/config.py xdeb-0.6.7/config.py --- xdeb-0.6.6/config.py 2011-09-20 12:49:19.000000000 +0000 +++ xdeb-0.6.7/config.py 2017-07-10 13:37:39.000000000 +0000 @@ -12,12 +12,22 @@ # system. For the time being, given the target package set, the most economical # approach is to hardcode various special cases in a configuration file. -from cStringIO import StringIO +try: + from cStringIO import StringIO +except ImportError: + from io import StringIO -import ConfigParser import os import pprint import sys +try: + if sys.version < '3.2': + from configparser import SafeConfigParser + else: + from configparser import ConfigParser as SafeConfigParser +except ImportError: + from ConfigParser import SafeConfigParser + __pychecker__ = 'unusednames=_NATIVE_IMPORT_SOURCE_NAME' @@ -135,7 +145,7 @@ Args: config_paths: A sequence of path strings for config files to load. """ - config = ConfigParser.SafeConfigParser( + config = SafeConfigParser( {_PARENT_OPTION: '', 'architecture': self._architecture, 'variant': self._variant}) @@ -204,13 +214,13 @@ """ if option_name[0] == '+': real_name = option_name[1:] - if merged_config.has_key(real_name): + if real_name in merged_config: merged_config[real_name].update(values) else: merged_config[real_name] = set(values) elif option_name[0] == '-': real_name = option_name[1:] - if merged_config.has_key(real_name): + if real_name in merged_config: merged_config[real_name].difference_update(values) else: merged_config[option_name] = set(values) @@ -281,9 +291,7 @@ output.write('\n') # Print out each property. - class_members = self.__class__.__dict__.keys() - class_members.sort() - for prop in class_members: + for prop in sorted(self.__class__.__dict__): if isinstance(self.__class__.__dict__[prop], property): output.write('%s: %s\n' % (prop, pp.pformat(getattr(self, prop)))) diff -Nru xdeb-0.6.6/debian/changelog xdeb-0.6.7/debian/changelog --- xdeb-0.6.6/debian/changelog 2012-05-23 10:03:20.000000000 +0000 +++ xdeb-0.6.7/debian/changelog 2017-07-11 11:04:29.000000000 +0000 @@ -1,3 +1,54 @@ +xdeb (0.6.7) unstable; urgency=low + + [ Colin Watson ] + * Use next(iterator) rather than iterator.next(). + * Use "key in dict" rather than "dict.has_key(key)". + * Make code style more or less conform to PEP-8. + * Simplify utils.file_on_path. + * Use dict.items rather than dict.iteritems to simplify porting to Python + 3; the performance impact should be negligible here. + * Simplify sorting in various places by relying on the default iteration + protocol for mappings. + * Use io.StringIO if cStringIO.StringIO is not available. + * Rephrase MyPkgRelation.parse_relations using list comprehensions: + arguably clearer, and works in both Python 2 and 3. + * Adjust GraphCycleError.__str__ to work in Python 3. + * Drop support for debian_bundle from python-debian (<< 0.1.15). + * Use configparser rather than ConfigParser if available. + * Remove __pycache__ directories on clean. + * Pass universal_newlines=True to subprocess.Popen to get Unicode output + in Python 3. + * Suppress pychecker warnings from the standard library. + * Set source format to 3.0 (native). + * Canonicalise the path to the GPL text in debian/copyright. + * Set [trusted=yes] for our local repository, and enable APT + authentication otherwise (closes: #781595). + * Use context managers where appropriate. + + [ Loïc Minier ] + * More PEP8 fixes. + * pyflakes fix. + * Run pyflakes as part of testsuite if it's available. + * Run pep8 as part of testsuite if it's available. + * Fix pychecker warning in tests. + * Run pychecker as part of testsuite if it's available. + * Test that we're running pychecker on all *.py files. + * Also run pychecker on tests. + * Clean __pycache__ in Makefile rather than debian/rules. + * Bump Standards-Version to 4.0.0. + * Remove myself from uploaders. + * Bump Debhelper compat level and build-dep to 10. + * Build-depend on dh-python. + * Remove Colin Watson and Steve Langasek from Uploaders with their + agreement. + * Add .pm suffix to checks/xdeb. + * Use Lintian::Util instead of Util in Lintian check. + * Updated to latest Lintian checks API, except for tag suppression + which would need to be ported to Lintian profiles. + * Fix ARM file magic detection (allow for "EABI5"). + + -- Loïc Minier Tue, 11 Jul 2017 13:04:29 +0200 + xdeb (0.6.6) unstable; urgency=low [ Loïc Minier ] diff -Nru xdeb-0.6.6/debian/compat xdeb-0.6.7/debian/compat --- xdeb-0.6.6/debian/compat 2010-06-10 11:28:36.000000000 +0000 +++ xdeb-0.6.7/debian/compat 2017-07-10 13:41:27.000000000 +0000 @@ -1 +1 @@ -7 +10 diff -Nru xdeb-0.6.6/debian/control xdeb-0.6.7/debian/control --- xdeb-0.6.6/debian/control 2012-05-23 10:00:42.000000000 +0000 +++ xdeb-0.6.7/debian/control 2017-07-11 10:02:30.000000000 +0000 @@ -2,15 +2,14 @@ Section: devel Priority: optional Maintainer: Wookey -Uploaders: Colin Watson , Loic Minier , Steve Langasek -Standards-Version: 3.9.2 -Build-Depends: debhelper (>= 7.0.50~) -Build-Depends-Indep: python (>= 2.7), python-debian (>= 0.1.11), python-apt (>= 0.7.91) +Standards-Version: 4.0.0 +Build-Depends: debhelper (>= 10~), dh-python +Build-Depends-Indep: python (>= 2.7), python-debian (>= 0.1.15~), python-apt (>= 0.7.91) X-Python-Version: >= 2.6 Package: xdeb Architecture: all -Depends: ${misc:Depends}, ${python:Depends}, python-debian (>= 0.1.11), dpkg-dev (>= 1.15), lintian (>= 2.3.0), devscripts (>= 2.10.41), dpkg-cross (>= 2.6.3), apt-utils (>= 0.8.11), python-apt (>= 0.7.91), wget, build-essential, sudo +Depends: ${misc:Depends}, ${python:Depends}, python-debian (>= 0.1.15~), dpkg-dev (>= 1.15), lintian (>= 2.3.0), devscripts (>= 2.10.41), dpkg-cross (>= 2.6.3), apt-utils (>= 0.8.11), python-apt (>= 0.7.91), wget, build-essential, sudo Recommends: gcc, fakeroot Breaks: apt (<< 0.7.26~exp6) Description: Cross-build tool for Debian packages diff -Nru xdeb-0.6.6/debian/copyright xdeb-0.6.7/debian/copyright --- xdeb-0.6.6/debian/copyright 2010-06-10 11:28:36.000000000 +0000 +++ xdeb-0.6.7/debian/copyright 2017-07-10 13:37:39.000000000 +0000 @@ -42,5 +42,5 @@ On Debian and Ubuntu systems, the complete text of the GNU General -Public License can be found in `/usr/share/common-licenses/GPL'. +Public License can be found in `/usr/share/common-licenses/GPL-3'. diff -Nru xdeb-0.6.6/debian/source/format xdeb-0.6.7/debian/source/format --- xdeb-0.6.6/debian/source/format 1970-01-01 00:00:00.000000000 +0000 +++ xdeb-0.6.7/debian/source/format 2017-07-10 13:37:39.000000000 +0000 @@ -0,0 +1 @@ +3.0 (native) diff -Nru xdeb-0.6.6/Makefile xdeb-0.6.7/Makefile --- xdeb-0.6.6/Makefile 2012-05-23 10:01:05.000000000 +0000 +++ xdeb-0.6.7/Makefile 2017-07-10 13:37:39.000000000 +0000 @@ -1,17 +1,8 @@ clean: -find -name \*.pyc | xargs -r rm -f + -find -name __pycache__ -print0 | xargs -0r rm -rf -# pychecker can get confused if modules aren't passed in the right order. check: - if which pychecker >/dev/null 2>&1; then \ - pychecker \ - config.py \ - tsort.py \ - utils.py \ - aptutils.py \ - tree.py \ - xdeb.py; \ - fi python -m unittest discover -v install: diff -Nru xdeb-0.6.6/tests/__init__.py xdeb-0.6.7/tests/__init__.py --- xdeb-0.6.6/tests/__init__.py 2012-05-23 09:56:57.000000000 +0000 +++ xdeb-0.6.7/tests/__init__.py 2017-07-10 13:37:39.000000000 +0000 @@ -4,6 +4,7 @@ import unittest + def test_suite(): module_names = [ 'tests.test_tree', @@ -12,4 +13,3 @@ loader = unittest.TestLoader() suite = loader.loadTestsFromNames(module_names) return suite - diff -Nru xdeb-0.6.6/tests/test_pep8.py xdeb-0.6.7/tests/test_pep8.py --- xdeb-0.6.6/tests/test_pep8.py 1970-01-01 00:00:00.000000000 +0000 +++ xdeb-0.6.7/tests/test_pep8.py 2017-07-10 13:37:39.000000000 +0000 @@ -0,0 +1,22 @@ +# Copyright (c) 2012 Linaro Ltd. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import subprocess +import unittest + +import utils + + +@unittest.skipUnless(utils.file_on_path('pep8', os.environ['PATH']), + "pep8 not found") +class TestPep8(unittest.TestCase): + def test_pep8(self): + # ignore return code + proc = subprocess.Popen( + ['pep8', '--repeat', '.'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = proc.communicate() + self.assertEqual(b'', stdout) + self.assertEqual(b'', stderr) diff -Nru xdeb-0.6.6/tests/test_pychecker.py xdeb-0.6.7/tests/test_pychecker.py --- xdeb-0.6.6/tests/test_pychecker.py 1970-01-01 00:00:00.000000000 +0000 +++ xdeb-0.6.7/tests/test_pychecker.py 2017-07-10 13:37:39.000000000 +0000 @@ -0,0 +1,34 @@ +# Copyright (c) 2012 Linaro Ltd. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import glob +import os +import subprocess +import unittest + +import utils + + +@unittest.skipUnless(utils.file_on_path('pychecker', os.environ['PATH']), + "pychecker not found") +class TestPychecker(unittest.TestCase): + # pychecker can get confused if modules aren't passed in the right + # order. + order = ['config.py', 'tsort.py', 'utils.py', 'aptutils.py', 'tree.py', + 'xdeb.py', 'tests/__init__.py', 'tests/test_pep8.py', + 'tests/test_pychecker.py', 'tests/test_pyflakes.py', + 'tests/test_tree.py', 'tests/test_xdeb.py', ] + + def test_pychecker(self): + # ignore return code + proc = subprocess.Popen( + ['pychecker', '-q', '-Q'] + self.order, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = proc.communicate() + self.assertEqual(b'', stdout) + self.assertEqual(b'', stderr) + + def test_pychecker_no_missing(self): + all_files = glob.glob('*.py') + glob.glob('tests/*.py') + self.assertEqual(sorted(all_files), sorted(self.order)) diff -Nru xdeb-0.6.6/tests/test_pyflakes.py xdeb-0.6.7/tests/test_pyflakes.py --- xdeb-0.6.6/tests/test_pyflakes.py 1970-01-01 00:00:00.000000000 +0000 +++ xdeb-0.6.7/tests/test_pyflakes.py 2017-07-10 13:37:39.000000000 +0000 @@ -0,0 +1,22 @@ +# Copyright (c) 2012 Linaro Ltd. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import subprocess +import unittest + +import utils + + +@unittest.skipUnless(utils.file_on_path('pyflakes', os.environ['PATH']), + "pyflakes not found") +class TestPyflakes(unittest.TestCase): + def test_pyflakes(self): + # ignore return code + proc = subprocess.Popen( + ['pyflakes', '.'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = proc.communicate() + self.assertEqual(b'', stdout) + self.assertEqual(b'', stderr) diff -Nru xdeb-0.6.6/tests/test_tree.py xdeb-0.6.7/tests/test_tree.py --- xdeb-0.6.6/tests/test_tree.py 2011-11-08 12:25:20.000000000 +0000 +++ xdeb-0.6.7/tests/test_tree.py 2017-07-10 13:37:39.000000000 +0000 @@ -10,6 +10,7 @@ import tree import xdeb + class TestGetControlLines(unittest.TestCase): def test_regular(self): control = [ @@ -73,6 +74,7 @@ ] self.assertEqual(expected, tree.get_control_lines(control)) + def clear_cache(): tree.srcdir = None tree.dirsrc = None @@ -82,6 +84,7 @@ tree.pkgrec = None tree.provides = None + class TestScanDir(unittest.TestCase): tmpdir = None @@ -99,7 +102,7 @@ def test_empty_control(self): os.mkdir(os.path.join(self.tmpdir, 'debian')) - with open(os.path.join(self.tmpdir, 'debian', 'control'), 'w') as f: + with open(os.path.join(self.tmpdir, 'debian', 'control'), 'w'): pass self.assertFalse(tree.scan_dir(self.tmpdir)) @@ -144,8 +147,9 @@ tree.pkgrec) self.assertEqual({'provides': ['package2']}, tree.provides) + class TestBuildCache(unittest.TestCase): - options = None + options = None saved_scan_dir = None scan_dir_pathes = [] tmpdir = None @@ -166,7 +170,7 @@ def tearDown(self): if self.saved_scan_dir: - setattr(tree, 'scan_dir', self.saved_scan_dir) + tree.scan_dir = self.saved_scan_dir if self.tmpdir: shutil.rmtree(self.tmpdir) @@ -185,4 +189,3 @@ os.makedirs(d) tree.build_cache(self.options) self.assertEqual(dirs, self.scan_dir_pathes) - diff -Nru xdeb-0.6.6/tests/test_xdeb.py xdeb-0.6.7/tests/test_xdeb.py --- xdeb-0.6.6/tests/test_xdeb.py 2011-11-08 12:25:20.000000000 +0000 +++ xdeb-0.6.7/tests/test_xdeb.py 2017-07-10 13:37:39.000000000 +0000 @@ -6,10 +6,10 @@ from xdeb import parse_options, want_apt_version + class TestWantAptVersion(TestCase): def test_no_apt(self): _parser, options, _args = parse_options(args=[]) options.prefer_apt = False options.apt_source = False self.assertFalse(want_apt_version(options, None)) - diff -Nru xdeb-0.6.6/tree.py xdeb-0.6.7/tree.py --- xdeb-0.6.6/tree.py 2012-05-23 09:04:25.000000000 +0000 +++ xdeb-0.6.7/tree.py 2017-07-10 13:37:39.000000000 +0000 @@ -9,21 +9,35 @@ import os import re -import ConfigParser import shutil - +import sys try: - from debian import deb822, changelog + from configparser import NoOptionError, NoSectionError + if sys.version < '3.2': + from configparser import SafeConfigParser + else: + from configparser import ConfigParser as SafeConfigParser except ImportError: - from debian_bundle import deb822, changelog + from ConfigParser import NoOptionError, NoSectionError, SafeConfigParser + +from debian import deb822, changelog + + +__pychecker__ = 'unusednames=cls' re_dep = re.compile( - r'^\s*(?P[a-zA-Z0-9.+\-]{2,}|\${[^}]*})(\s*\(\s*(?P[>=<]+)\s*(?P[0-9a-zA-Z:\-+~.]+|\${[^}]*})\s*\))?(\s*\[(?P[\s!\w\-]+)\])?\s*$') + r''' + ^\s*(?P[a-zA-Z0-9.+\-]{2,}|\${[^}]*}) + (\s*\(\s*(?P[>=<]+)\s* + (?P[0-9a-zA-Z:\-+~.]+|\${[^}]*})\s*\))? + (\s*\[(?P[\s!\w\-]+)\])?\s*$ + ''', re.X) re_comma_sep = re.compile(r'\s*,\s*') re_pipe_sep = re.compile(r'\s*\|\s*') re_blank_sep = re.compile(r'\s*') + # This is derived from deb822.PkgRelations.parse_relations, but we want to # treat substvars in an intelligent way. We make the following assumptions: # @@ -35,8 +49,6 @@ # * Any automatically generated versions in dependencies will normally be # within the same source package, and may be safely discarded. -__pychecker__ = 'unusednames=cls' - class MyPkgRelation(deb822.PkgRelation): @classmethod def parse_relations(cls, raw): @@ -56,7 +68,7 @@ parts = match.groupdict() if parts['name'].startswith('${'): return - d = { 'name': parts['name'] } + d = {'name': parts['name']} if not (parts['relop'] is None or parts['version'] is None): if parts['version'].startswith('${'): d['version'] = None @@ -70,12 +82,12 @@ d['arch'] = parse_archs(parts['archs']) return d - tl_deps = re_comma_sep.split(raw.strip()) # top-level deps - cnf = map(re_pipe_sep.split, tl_deps) - return filter(None, - map(lambda or_deps: filter(None, - map(parse_rel, or_deps)), - cnf)) + def parse_or_deps(or_deps): + return [dep for dep in map(parse_rel, or_deps) if dep] + + tl_deps = re_comma_sep.split(raw.strip()) # top-level deps + cnf = [re_pipe_sep.split(tl_dep) for tl_dep in tl_deps] + return [deps for deps in map(parse_or_deps, cnf) if deps] deb822.PkgRelation.parse_relations = MyPkgRelation.parse_relations @@ -107,6 +119,7 @@ pkgrec = None provides = None + def init_cache(): global srcdir, dirsrc, pkgsrc, srcpkgs, srcrec, pkgrec, provides @@ -119,15 +132,16 @@ pkgrec = {} provides = {} + def scan_dir(path): init_cache() if os.path.exists('%s/xdeb.cfg' % path): - config = ConfigParser.SafeConfigParser() + config = SafeConfigParser() config.read('%s/xdeb.cfg' % path) try: path = '%s/%s' % (path, config.get('Package', 'directory')) - except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): + except (NoSectionError, NoOptionError): pass try: debian_symlink = config.get('Package', 'debian_symlink') @@ -143,19 +157,18 @@ print("Creating debian -> %s symlink in %s" % (debian_symlink, path)) os.symlink(debian_symlink, '%s/debian' % path) - except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): + except (NoSectionError, NoOptionError): pass try: - control_file = open('%s/debian/control' % path) + with open('%s/debian/control' % path) as control_file: + control_lines = get_control_lines(control_file) except IOError: return False - control_lines = get_control_lines(control_file) - control_file.close() stanzas = deb822.Deb822.iter_paragraphs(control_lines, use_apt_pkg=False) try: - src_stanza = stanzas.next() + src_stanza = next(stanzas) except StopIteration: return False if 'source' not in src_stanza: @@ -181,6 +194,7 @@ return True + def build_cache(options): if srcdir is not None: return @@ -208,6 +222,7 @@ build_cache(options) return srcdir.get(src) + def get_directory_src(options, path): build_cache(options) return dirsrc.get(path) @@ -216,6 +231,7 @@ class MultipleProvidesException(RuntimeError): pass + def get_real_pkg(options, pkg): """Get the real name of binary package pkg, resolving Provides.""" build_cache(options) @@ -261,19 +277,16 @@ def get_src_version(options, src): """Return the version of the working tree for source package src.""" + changelog_path = '%s/debian/changelog' % get_src_directory(options, src) try: - changelog_file = open('%s/debian/changelog' % - get_src_directory(options, src)) + with open(changelog_path) as changelog_file: + cl = changelog.Changelog(file=changelog_file, max_blocks=1) + if cl.get_versions(): + return str(cl.version) + else: + return None except IOError: return None - try: - cl = changelog.Changelog(file=changelog_file, max_blocks=1) - if cl.get_versions(): - return str(cl.version) - else: - return None - finally: - changelog_file.close() def get_src_binaries(options, src): @@ -286,18 +299,17 @@ def architectures(options, src): + control_path = '%s/debian/control' % get_src_directory(options, src) try: - control_file = open('%s/debian/control' % - get_src_directory(options, src)) + with open(control_path) as control_file: + control_lines = get_control_lines(control_file) except IOError: return set() - control_lines = get_control_lines(control_file) - control_file.close() architectures = set() # apt_pkg is quicker, but breaks if the control file contains comments. stanzas = deb822.Deb822.iter_paragraphs(control_lines, use_apt_pkg=False) - stanzas.next() # discard source stanza + next(stanzas) # discard source stanza for stanza in stanzas: if 'architecture' not in stanza: architectures.add('any') @@ -308,4 +320,4 @@ def all_packages(options): build_cache(options) - return sorted(set(srcdir.keys()) - set(options.exclude)) + return sorted(set(srcdir) - set(options.exclude)) diff -Nru xdeb-0.6.6/tsort.py xdeb-0.6.7/tsort.py --- xdeb-0.6.6/tsort.py 2012-05-23 09:06:07.000000000 +0000 +++ xdeb-0.6.7/tsort.py 2017-07-10 13:37:39.000000000 +0000 @@ -21,9 +21,10 @@ """Topological sorting routines.""" - from __future__ import print_function +import sys + __all__ = ["topo_sort", "TopoSorter"] @@ -42,10 +43,11 @@ # slot, so it isn't seen in __dict__ d['message'] = getattr(self, 'message', 'no message') s = self._fmt % d - # __str__() should always return a 'str' object - # never a 'unicode' object. - if isinstance(s, unicode): - return s.encode('utf8') + if sys.version < '3': + # __str__() should always return a 'str' object + # never a 'unicode' object. + if isinstance(s, unicode): + return s.encode('utf8') return s @@ -75,8 +77,8 @@ node identifiers can be any hashable object, and are typically strings. - If you have a graph like [('a', ['b']), ('a', ['c'])] this will only use - one of the two values for 'a'. + If you have a graph like [('a', ['b']), ('a', ['c'])] this will only + use one of the two values for 'a'. The graph is sorted lazily: until you iterate or sort the input is not processed other than to create an internal representation. @@ -87,7 +89,7 @@ # a dict of the graph. self._graph = dict(graph) self._visitable = set(self._graph) - ### if debugging: + # if debugging: # self._original_graph = dict(graph) # this is a stack storing the depth first search into the graph. @@ -108,15 +110,15 @@ """ return list(self.iter_topo_order()) -### Useful if fiddling with this code. -### # cross check -### sorted_names = list(self.iter_topo_order()) -### for index in range(len(sorted_names)): -### rev = sorted_names[index] -### for left_index in range(index): -### if rev in self.original_graph[sorted_names[left_index]]: -### print("revision in parent list of earlier revision") -### import pdb;pdb.set_trace() +# Useful if fiddling with this code. +# # cross check +# sorted_names = list(self.iter_topo_order()) +# for index in range(len(sorted_names)): +# rev = sorted_names[index] +# for left_index in range(index): +# if rev in self.original_graph[sorted_names[left_index]]: +# print("revision in parent list of earlier revision") +# import pdb;pdb.set_trace() def iter_topo_order(self): """Yield the nodes of the graph in a topological order. @@ -125,8 +127,8 @@ iteration. """ while self._graph: - # now pick a random node in the source graph, and transfer it to the - # top of the depth first search stack. + # now pick a random node in the source graph, and transfer it to + # the top of the depth first search stack. node_name, parents = self._graph.popitem() self._push_node(node_name, parents) while self._node_name_stack: @@ -153,15 +155,15 @@ try: parents = self._graph.pop(next_node_name) except KeyError: - # if the next node is not in the source graph it has - # already been popped from it and placed into the - # current search stack (but not completed or we would - # have hit the continue 4 lines up. - # this indicates a cycle. + # if the next node is not in the source graph it + # has already been popped from it and placed + # into the current search stack (but not + # completed or we would have hit the continue 4 + # lines up. this indicates a cycle. raise GraphCycleError(self._node_name_stack) self._push_node(next_node_name, parents) - # and do not continue processing parents until this 'call' - # has recursed. + # and do not continue processing parents until this + # 'call' has recursed. break def _push_node(self, node_name, parents): diff -Nru xdeb-0.6.6/utils.py xdeb-0.6.7/utils.py --- xdeb-0.6.6/utils.py 2012-05-23 09:04:33.000000000 +0000 +++ xdeb-0.6.7/utils.py 2017-07-10 13:37:39.000000000 +0000 @@ -15,12 +15,14 @@ class SubprocessException(RuntimeError): pass + def subprocess_setup(): # Python installs a SIGPIPE handler by default. This is bad for # non-Python subprocesses, which need SIGPIPE set to the default action # or else they won't notice if the debconffilter dies. signal.signal(signal.SIGPIPE, signal.SIG_DFL) + def spawn(args, **kwargs): """Spawn a subprocess. Raise SubprocessException if it fails.""" print(' '.join(args)) @@ -30,6 +32,7 @@ if ret != 0: raise SubprocessException(ret) + def spawn_root(args, **kwargs): """Spawn a subprocess as root. Raise SubprocessException if it fails.""" # TODO hardcoding of root escalation method @@ -39,16 +42,19 @@ args = new_args spawn(args, **kwargs) + def get_output(args, mayfail=False, **kwargs): """Get the output of a subprocess.""" subp = subprocess.Popen(args, preexec_fn=subprocess_setup, - stdout=subprocess.PIPE, **kwargs) + stdout=subprocess.PIPE, universal_newlines=True, + **kwargs) output = subp.communicate()[0] if subp.returncode != 0 and not mayfail: print(' '.join(args)) raise SubprocessException(subp.returncode) return output + def get_output_root(args, mayfail=False, **kwargs): """Get the output of a subprocess, run as root. Raise SubprocessException if it fails.""" @@ -59,12 +65,10 @@ args = new_args return get_output(args, mayfail=mayfail, **kwargs) + def file_on_path(filename, searchpath): - """ Returns true if file found on search path """ - found = 0 - paths = searchpath.split(os.pathsep) - for path in paths: - if os.path.exists(os.path.join(path, filename)): - found = 1 - break - return found + """Return true if file found on search path.""" + for path in searchpath.split(os.pathsep): + if os.path.exists(os.path.join(path, filename)): + return True + return False diff -Nru xdeb-0.6.6/xdeb.py xdeb-0.6.7/xdeb.py --- xdeb-0.6.6/xdeb.py 2012-05-23 09:02:59.000000000 +0000 +++ xdeb-0.6.7/xdeb.py 2017-07-10 13:37:39.000000000 +0000 @@ -14,10 +14,7 @@ import shutil import sys -try: - from debian import deb822, debfile, debian_support -except ImportError: - from debian_bundle import deb822, debfile, debian_support +from debian import deb822, debfile, debian_support from config import TargetConfig import utils @@ -25,9 +22,11 @@ import tree import tsort + # TODO(ajwong): Remove this global. target_config = None + # Abstractions for aptutils/tree functions. def want_apt_version(options, src): @@ -46,6 +45,7 @@ else: return False + def get_real_pkg(options, pkg): """Get the real name of binary package pkg, resolving Provides.""" if options.apt_source or options.prefer_apt: @@ -54,6 +54,7 @@ return real_pkg return tree.get_real_pkg(options, pkg) + def get_src_name(options, pkg): """Return the source package name that produces binary package pkg.""" @@ -63,6 +64,7 @@ return src return tree.get_src_name(options, pkg) + def get_src_record(options, src): """Return a parsed source package record for source package src.""" if want_apt_version(options, src): @@ -70,6 +72,7 @@ else: return tree.get_src_record(options, src) + def get_pkg_record(options, pkg): """Return a parsed binary package record for binary package pkg.""" src = get_src_name(options, pkg) @@ -78,6 +81,7 @@ else: return tree.get_pkg_record(options, pkg) + def get_src_version(options, src): """Return the current version for source package src.""" if want_apt_version(options, src): @@ -85,6 +89,7 @@ else: return tree.get_src_version(options, src) + def get_src_binaries(options, src): """Return all the binaries produced by source package src.""" if want_apt_version(options, src): @@ -95,6 +100,7 @@ dpkg_architectures = None + def dpkg_architecture_allowed(arch): """Check if dpkg can install packages for the host architecture.""" global dpkg_architectures @@ -105,14 +111,14 @@ dpkg_architectures = set() dpkg_architectures.add( utils.get_output(['dpkg', '--print-architecture']).strip()) - devnull = open('/dev/null', 'w') - dpkg_architectures.update( - utils.get_output(['dpkg', '--print-foreign-architectures'], - mayfail=True, stderr=devnull).split()) - devnull.close() + with open('/dev/null', 'w') as devnull: + dpkg_architectures.update( + utils.get_output(['dpkg', '--print-foreign-architectures'], + mayfail=True, stderr=devnull).split()) return arch in dpkg_architectures + def apt_architecture_allowed(arch): return (dpkg_architecture_allowed(arch) or aptutils.apt_architecture_allowed(arch)) @@ -134,7 +140,7 @@ return False record = get_pkg_record(options, real_pkg) if record is None: - return False + return False if 'multi-arch' in record: return record['multi-arch'] == 'foreign' @@ -152,33 +158,35 @@ 'lib64stdc++' in pkg or 'libstdc++' in pkg or 'lib64c' in pkg or 'multilib' in pkg or pkg == 'linux-libc-dev') + def is_crossable(pkg, conversion=False): """Can pkg sensibly be cross-built?""" global target_config if pkg in target_config.blacklist: - return False # manually blacklisted + return False # manually blacklisted if conversion and pkg in target_config.cross_blacklist: - return False # manually blacklisted for cross-conversion + return False # manually blacklisted for cross-conversion if pkg in target_config.whitelist: - return True # manually whitelisted + return True # manually whitelisted if (pkg.endswith('-bin') or pkg.endswith('-common') or - pkg.endswith('-data') or pkg.endswith('-dbg') or - pkg.endswith('-doc') or pkg.endswith('-i18n') or - pkg.endswith('-perl') or pkg.endswith('-pic') or - pkg.endswith('-refdbg') or pkg.endswith('-tcl') or - pkg.endswith('-util') or pkg.endswith('-utils') or - pkg.startswith('python-')): - return False # generally want build versions of these, not host + pkg.endswith('-data') or pkg.endswith('-dbg') or + pkg.endswith('-doc') or pkg.endswith('-i18n') or + pkg.endswith('-perl') or pkg.endswith('-pic') or + pkg.endswith('-refdbg') or pkg.endswith('-tcl') or + pkg.endswith('-util') or pkg.endswith('-utils') or + pkg.startswith('python-')): + return False # generally want build versions of these, not host if 'lib' in pkg: return True if 'x11proto' in pkg: return True return False + def need_loop_break(parent, pkg): """Sometimes we need to break loops manually.""" if (parent in ('python2.5', 'python2.6', 'python2.7') and - pkg == 'libbluetooth-dev'): + pkg == 'libbluetooth-dev'): # Python build-depends on several things that are optional for # building. These are only used for module builds, and not for the # core Python binary and libraries that we need to cross-convert. @@ -196,15 +204,16 @@ # set of graph edges in dependency tree dot_relationships = dict() + def print_relations(options, graph_pkg, parent, pkg, src, depth, parent_binary): if options.generate_graph: if options.generate_compact_graph: - rel = '"%s" -> "%s";' % ( parent, src) + rel = '"%s" -> "%s";' % (parent, src) dot_relationships[graph_pkg].append(rel) else: - style = '"bin-%s" [label="%s",shape=box];' % ( pkg, pkg ) - rel = '"%s" -> "bin-%s" -> "%s";' % ( parent, pkg, src) + style = '"bin-%s" [label="%s",shape=box];' % (pkg, pkg) + rel = '"%s" -> "bin-%s" -> "%s";' % (parent, pkg, src) dot_relationships[graph_pkg].append(style) dot_relationships[graph_pkg].append(rel) if options.debug: @@ -215,6 +224,7 @@ else: print("%s%s -> %s (%s)" % (' ' * depth, parent, src, pkg)) + def filter_arch(deps, arch): """Filter out (build-)dependencies that do not apply to arch.""" new_deps = [] @@ -244,6 +254,7 @@ new_deps.append(new_or_deps) return new_deps + def should_expand(options, parent, pkg): if pkg in explicit_requests: # We're going to build it anyway because it was requested on the @@ -253,6 +264,7 @@ not is_multiarch_foreign(options, pkg) and not need_loop_break(parent, pkg)) + def expand_depends(options, graph_pkg, pkg, depth, builddep_depth, parent=None, parent_binary=None): """Recursively expand (build-)dependencies of pkg.""" @@ -328,7 +340,7 @@ # what is built can be installed. However we only want to do this # for binary deps that are actually needed as build-deps if (pkg not in all_pkgs and pkg in get_src_binaries(options, src) and - is_crossable(pkg) and not is_toolchain(pkg)): + is_crossable(pkg) and not is_toolchain(pkg)): all_pkgs.add(pkg) parsed_binary = get_pkg_record(options, pkg) deps = parsed_binary.relations['pre-depends'] @@ -355,6 +367,7 @@ parent=src, parent_binary=pkg) break + def mark_needs_build(options, src, force=False): """Decide whether a package needs to be (re)built.""" if src in needs_build: @@ -380,7 +393,7 @@ if options.force_rebuild or force or newer: needs_build[src] = True - for depsrc, depset in depends.iteritems(): + for depsrc, depset in depends.items(): if src in depset: if options.debug: print("Recursing:", src, "->", depsrc) @@ -391,6 +404,7 @@ re_changes_filename = re.compile(r"(.+?)_(.+?)_(.+)\.changes$") + def all_builds(options, src=None): """Return the versions of all builds for source package src.""" for name in sorted(os.listdir(options.destdir)): @@ -403,15 +417,12 @@ if not matchobj: continue if ((src is None or matchobj.group(1) == src) and - matchobj.group(3) == options.architecture): - changes_file = open(path) - try: + matchobj.group(3) == options.architecture): + with open(path) as changes_file: changes = deb822.Changes(changes_file) if 'version' in changes: yield (matchobj.group(1), debian_support.Version(changes['version'])) - finally: - changes_file.close() build_arch = utils.get_output(['dpkg-architecture', @@ -424,11 +435,12 @@ re_deb_filename = re.compile(r"(.+?)_(.+?)_(.+)\.deb$") + def install_build_depends(options, srcs): available_builddeps = set() if options.architecture != build_arch: if ('binutils-multiarch' in aptutils.cache and - not aptutils.cache['binutils-multiarch'].is_installed): + not aptutils.cache['binutils-multiarch'].is_installed): all_builddeps.add('binutils-multiarch') available_builddeps.add('binutils-multiarch') for src in srcs: @@ -452,13 +464,13 @@ real_bd_pkg = bd_pkg all_builddeps.add(real_bd_pkg) if (real_bd_pkg in aptutils.cache and - not aptutils.cache[real_bd_pkg].is_installed): + not aptutils.cache[real_bd_pkg].is_installed): available_builddeps.add(real_bd_pkg) if is_crossable(real_bd_pkg): cross_bd_pkg = '%s-%s-cross' % (real_bd_pkg, options.architecture) if (cross_bd_pkg in aptutils.cache and - not aptutils.cache[cross_bd_pkg].is_installed): + not aptutils.cache[cross_bd_pkg].is_installed): available_builddeps.add(cross_bd_pkg) if available_builddeps: @@ -472,6 +484,7 @@ utils.spawn_root(command) aptutils.reopen_cache() + def cross_convert(options, debs, outdir='.'): crossable_debs = [] exclude_deps = set() @@ -508,6 +521,7 @@ return crossed_debs + def native_import(options, src): """Import a native build of source package src at version ver.""" src_record = aptutils.get_src_record(src) @@ -538,11 +552,11 @@ except Exception: if options.debug: print("skipping - %s" % binary) - continue # might be a udeb or not built for specified arch + continue # might be a udeb or not built for specified arch bin_stanzas = deb822.Packages.iter_paragraphs(bin_cache) while True: try: - bin_stanza = bin_stanzas.next() + bin_stanza = next(bin_stanzas) if 'version' not in bin_stanza or bin_stanza['version'] != ver: continue if 'filename' not in bin_stanza: @@ -578,9 +592,9 @@ # fake up a changes file changes = '%s_%s_%s.changes' % (src, ver_no_epoch, options.architecture) - changes_file = open(os.path.join(options.builddirs[0], changes), 'w') - print('Version: %s\nFake: yes' % ver, file=changes_file) - changes_file.close() + with open( + os.path.join(options.builddirs[0], changes), 'w') as changes_file: + print('Version: %s\nFake: yes' % ver, file=changes_file) crossed_debs = cross_convert(options, debs, options.builddirs[0]) @@ -593,9 +607,11 @@ aptutils.update_apt_repository(options, force_rebuild=previously_imported) + class BuildException(RuntimeError): pass + def build(options, src, ver): """Build source package src at version ver.""" install_build_depends(options, [src]) @@ -632,7 +648,7 @@ arches = tree.architectures(options, src) if ('any' not in arches and 'all' not in arches and - options.architecture not in arches): + options.architecture not in arches): print("%s_%s not buildable for %s" % (src, ver, options.architecture)) return @@ -660,7 +676,7 @@ if cpu_count > 1: # Rule of thumb is to spawn 1 more than the number of CPUs when # building. - buildpackage.append('-j%s' % (cpu_count + 1) ) + buildpackage.append('-j%s' % (cpu_count + 1)) if options.architecture != build_arch: buildpackage.append('-eCONFIG_SITE=/etc/dpkg-cross/cross-config.%s' % options.architecture) @@ -736,7 +752,7 @@ aptutils.reopen_cache() -def parse_options(args = sys.argv[1:]): +def parse_options(args=sys.argv[1:]): usage = '%prog [options] package ...' parser = optparse.OptionParser(usage=usage) parser.add_option('-C', '--config-files', dest='config_files', @@ -814,7 +830,7 @@ help='draw a simplified graph omitting binary package ' 'links') parser.add_option('--stage1', - dest='stage1', + dest='stage1', action='store_true', default=False, help='generate the dependencies of packages based on ' 'the Build-Depends-Stage1 field of the control ' @@ -844,7 +860,7 @@ print('Configuration is:\n%s' % target_config) # Use config file values for options if no commandline override was given. - for name, value in target_config.options.iteritems(): + for name, value in target_config.options.items(): if name in parser.defaults: if getattr(options, name) == parser.defaults[name]: if name in ('builddirs', 'exclude'): @@ -873,7 +889,7 @@ src, ver = b if src not in build_srcs or ver > build_srcs[src]: build_srcs[src] = ver - for src in sorted(build_srcs.keys()): + for src in sorted(build_srcs): print(src, build_srcs[src]) sys.exit(0) @@ -984,5 +1000,6 @@ if options.debug: print("Skipping %s (already built)" % src) + if __name__ == '__main__': main()