diff -Nru ubuntu-dev-tools-0.164/404main ubuntu-dev-tools-0.187~bpo18.04.1/404main --- ubuntu-dev-tools-0.164/404main 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/404main 1970-01-01 00:00:00.000000000 +0000 @@ -1,182 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright 2006-2007 (C) Pete Savage -# Copyright 2007 (C) Siegfried-A. Gevatter -# Copyright 2009 (C) Canonical Ltd. (by Colin Watson ) -# -# ################################################################## -# -# 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. -# -# See file /usr/share/common-licenses/GPL for more details. -# -# ################################################################## -# -# This script is used to check if a package and all its build -# dependencies are in main or not. - -import sys - -import apt_pkg -import apt - -from ubuntutools import subprocess - - -def process_deps(cache, deps): - """Takes a list of (build) dependencies and processes it.""" - - for basedep in [d.or_dependencies[0] for d in deps]: - if basedep.name not in packages and basedep.name != '': - # Check the (build) dependencies recursively - find_main(cache, basedep.name) - - -def get_package_version(cache, distro, pack): - if pack not in cache: - return None - for version in (cache[pack].candidate, cache[pack].installed): - if not version: - continue - for origin in version.origins: - if origin.archive == distro: - return version - return None - - -# Cache::CompTypeDeb isn't exposed via python-apt -def comp_type_deb(op): - ops = ("", "<=", ">=", "<<", ">>", "=", "!=") - if (op & 15) < 7: - return ops[op & 15] - return "" - - -def find_main(cache, pack): - """Searches the dependencies and build dependencies of a package recursively - to determine if they are all in the 'main' component or not.""" - - global packages - - if pack in packages: - return - - # Retrieve information about the package - version = get_package_version(cache, distro, pack) - - if not version: - packages[pack] = False - return - elif [origin for origin in version.origins if origin.component == 'main']: - packages[pack] = True - return - else: - if pack not in packages: - packages[pack] = False - - # Retrieve package dependencies - process_deps(cache, version.dependencies) - - # Retrieve package build dependencies. There's no handy - # attribute on version for this, so unfortunately we have to - # do a lot of messing about with apt. - deps = [] - src_records = apt_pkg.SourceRecords() - got_src = False - while src_records.lookup(version.source_name): - if pack in src_records.binaries: - got_src = True - break - if got_src: - # pylint: disable=E1101 - for _, all_deps in src_records.build_depends.iteritems(): - # pylint: enable=E1101 - for or_deps in all_deps: - base_deps = [] - for (name, ver, op) in or_deps: - # pylint: disable=too-many-function-args - base_deps.append(apt.package.BaseDependency(name, op, - ver, False)) - # pylint: enable=too-many-function-args - # pylint: disable=no-value-for-parameter - deps.append(apt.package.Dependency(base_deps)) - # pylint: enable=no-value-for-parameter - - process_deps(cache, deps) - - -def usage(exit_code): - print 'Usage: %s []' % sys.argv[0] - sys.exit(exit_code) - - -def main(): - - global packages, distro - - # Check if the amount of arguments is correct - if len(sys.argv) > 1 and sys.argv[1] in ('help', '-h', '--help'): - usage(0) - - if len(sys.argv) < 2 or len(sys.argv) > 3: - usage(1) - - cache = apt.cache.Cache() - - if len(sys.argv) == 3 and sys.argv[2]: - distro = sys.argv[2] - if not get_package_version(cache, distro, 'bash'): - print u'«%s» is not a valid distribution.' % distro - print('Remember that for 404main to work with a certain distribution ' - 'it must be in your /etc/apt/sources.list file.') - sys.exit(1) - else: - cmd = ['lsb_release', '-cs'] - process = subprocess.Popen(cmd, stdout=subprocess.PIPE) - distro = process.stdout.read().strip('\n') - - if not get_package_version(cache, distro, sys.argv[1]): - print(u"Can't find package «%s» in distribution «%s»." % (sys.argv[1], distro)) - sys.exit(1) - - print(u'Checking package «%s» in distribution «%s»...' % (sys.argv[1], distro)) - - find_main(cache, sys.argv[1]) - - # True if everything checked until the point is in main - all_in_main = True - - for package in packages: - if not packages[package]: - if all_in_main: - print 'The following packages aren\'t in main:' - all_in_main = False - print ' ', package - - if all_in_main: - print((u'Package «%s» and all its dependencies and build dependencies are in main.') % - sys.argv[1]) - - -if __name__ == '__main__': - - # Global variable to hold the status of all packages - packages = {} - - # Global variable to hold the target distribution - distro = '' - - try: - main() - except KeyboardInterrupt: - print 'Aborted.' - sys.exit(1) diff -Nru ubuntu-dev-tools-0.164/backportpackage ubuntu-dev-tools-0.187~bpo18.04.1/backportpackage --- ubuntu-dev-tools-0.164/backportpackage 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/backportpackage 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # -*- coding: utf-8 -*- # ################################################################## # @@ -22,24 +22,28 @@ import optparse import os import shutil +import subprocess import sys import tempfile +from urllib.parse import quote import lsb_release from httplib2 import Http, HttpLib2Error +from distro_info import DebianDistroInfo, UbuntuDistroInfo -from ubuntutools.archive import (SourcePackage, DebianSourcePackage, +from ubuntutools.archive import (DebianSourcePackage, UbuntuSourcePackage, DownloadError) from ubuntutools.config import UDTConfig, ubu_email from ubuntutools.builder import get_builder from ubuntutools.lp.lpapicache import (Launchpad, Distribution, SeriesNotFoundException, PackageNotFoundException) -from ubuntutools.logger import Logger from ubuntutools.misc import (system_distribution, vendor_to_distroinfo, codename_to_distribution) from ubuntutools.question import YesNoQuestion -from ubuntutools import subprocess + +from ubuntutools import getLogger +Logger = getLogger() def error(msg): @@ -48,22 +52,12 @@ def check_call(cmd, *args, **kwargs): - Logger.command(cmd) + Logger.debug(' '.join(cmd)) ret = subprocess.call(cmd, *args, **kwargs) if ret != 0: error('%s returned %d.' % (cmd[0], ret)) -def check_program_exists(name, package=None): - paths = set(os.environ['PATH'].split(':')) - paths |= set(('/sbin', '/usr/sbin', '/usr/local/sbin')) - if not any(os.path.exists(os.path.join(p, name)) for p in paths): - Logger.error('Could not find "%s". Please install the package "%s" ' - 'to use this functionality.', - name, package or name) - sys.exit(1) - - def parse(args): usage = 'Usage: %prog [options] ' parser = optparse.OptionParser(usage) @@ -83,6 +77,11 @@ metavar='SUFFIX', help='Suffix to append to version number ' '(default: ~ppa1 when uploading to a PPA)') + parser.add_option('-e', '--message', + metavar='MESSAGE', + default="No-change", + help='Changelog message to use instead of "No-change" ' + '(default: No-change backport to DEST.)') parser.add_option('-b', '--build', default=False, action='store_true', @@ -158,8 +157,6 @@ parser.error('Please specify either a working dir or an upload target!') if opts.upload and opts.upload.startswith('ppa:'): opts.release_pocket = True - if opts.upload: - check_program_exists('dput') return opts, args, config @@ -205,8 +202,12 @@ def find_package(mirror, workdir, package, version, source_release, config): "Returns the SourcePackage" if package.endswith('.dsc'): - return SourcePackage(version=version, dscfile=package, - workdir=workdir, mirrors=(mirror,)) + # Here we are using UbuntuSourcePackage just because we don't have any + # "general" class that is safely instantiable (as SourcePackage is an + # abstract class). None of the distribution-specific details within + # UbuntuSourcePackage is relevant for this use case. + return UbuntuSourcePackage(version=version, dscfile=package, + workdir=workdir, mirrors=(mirror,)) if not source_release and not version: info = vendor_to_distroinfo(system_distribution()) @@ -225,10 +226,25 @@ distribution = codename_to_distribution(release) if not distribution: error('Unknown release codename %s' % release) - series = Distribution(distribution.lower()).\ - getSeries(name_or_version=release) + if distribution == 'Debian': + debian_distro_info = DebianDistroInfo() + debian_codenames = debian_distro_info.supported() + if release in debian_codenames: + release_version = debian_distro_info.version(release) + if not release_version: + error(f"Can't find the release version for {release}") + backport_version = "{}~bpo{}+1".format( + version, release_version + ) + else: + error(f"{release} is not a supported release ({debian_codenames})") + elif distribution == 'Ubuntu': + series = Distribution(distribution.lower()).\ + getSeries(name_or_version=release) - backport_version = version + ('~%s%s.1' % (distribution.lower(), series.version)) + backport_version = version + ('~bpo%s.1' % (series.version)) + else: + error('Unknown distribution «%s» for release «%s»' % (distribution, release)) if suffix is not None: backport_version += suffix elif upload and upload.startswith('ppa:'): @@ -294,21 +310,23 @@ h = Http() for filename in glob.glob(os.path.join(workdir, '%s_%s.orig*' % (pkg.source, version))): - url = ('https://launchpad.net/~%s/+archive/%s/+files/%s' - % (user, ppa, filename)) + url = ('https://launchpad.net/~%s/+archive/%s/+sourcefiles/%s/%s/%s' + % (quote(user), quote(ppa), quote(pkg.source), + quote(pkg.version.full_version), + quote(os.path.basename(filename)))) try: headers, body = h.request(url, 'HEAD') if (headers.status != 200 or not headers['content-location'].startswith('https://launchpadlibrarian.net')): return True except HttpLib2Error as e: - Logger.info(e) + Logger.debug(e) return True return False -def do_backport(workdir, pkg, suffix, close, release, release_pocket, build, - builder, update, upload, keyid, prompt): +def do_backport(workdir, pkg, suffix, message, close, release, release_pocket, + build, builder, update, upload, keyid, prompt): dirname = '%s-%s' % (pkg.source, release) srcdir = os.path.join(workdir, dirname) @@ -325,7 +343,7 @@ old_version = get_old_version(pkg.source, release) bp_dist = get_backport_dist(release, release_pocket) - changelog = 'No-change backport to %s' % (release,) + changelog = '%s backport to %s.' % (message, release,) if close: changelog += ' (LP: #%s)' % (close,) check_call(['dch', @@ -380,9 +398,15 @@ if not opts.dest_releases: distinfo = lsb_release.get_distro_information() try: - opts.dest_releases = [distinfo['CODENAME']] + current_distro = distinfo['ID'] except KeyError: error('No destination release specified and unable to guess yours.') + if current_distro == "Ubuntu": + opts.dest_releases = [UbuntuDistroInfo().lts()] + if current_distro == "Debian": + opts.dest_releases = [DebianDistroInfo().stable()] + else: + error(f"Unknown distribution {current_distro}, can't guess target release") if opts.workdir: workdir = os.path.expanduser(opts.workdir) @@ -405,6 +429,7 @@ do_backport(workdir, pkg, opts.suffix, + opts.message, opts.close, release, opts.release_pocket, diff -Nru ubuntu-dev-tools-0.164/bitesize ubuntu-dev-tools-0.187~bpo18.04.1/bitesize --- ubuntu-dev-tools-0.164/bitesize 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/bitesize 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 """Add 'bitesize' tag to bugs and add a comment.""" # Copyright (c) 2011 Canonical Ltd. @@ -28,7 +28,9 @@ from launchpadlib.errors import HTTPError from ubuntutools.config import UDTConfig -from ubuntutools.logger import Logger + +from ubuntutools import getLogger +Logger = getLogger() def error_out(msg): @@ -39,7 +41,7 @@ def save_entry(entry): try: entry.lp_save() - except HTTPError, error: + except HTTPError as error: error_out(error.content) @@ -73,7 +75,7 @@ # check that the new main bug isn't a duplicate try: bug = launchpad.bugs[args[0]] - except HTTPError, error: + except HTTPError as error: if error.response.status == 401: error_out("Don't have enough permissions to access bug %s. %s" % (args[0], error.content)) diff -Nru ubuntu-dev-tools-0.164/check-mir ubuntu-dev-tools-0.187~bpo18.04.1/check-mir --- ubuntu-dev-tools-0.164/check-mir 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/check-mir 2019-09-10 12:14:20.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # # Check components of build dependencies and warn about universe/multiverse # ones, for a package destined for main/restricted @@ -21,8 +21,6 @@ # this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -from __future__ import print_function - import sys import optparse import os.path @@ -103,7 +101,7 @@ print('\nChecking support status of binary dependencies...') while True: try: - control.next() + next(control) except StopIteration: break @@ -141,7 +139,7 @@ # get build dependencies from debian/control control = apt.apt_pkg.TagFile(open('debian/control')) - control.next() + next(control) unsupported_build_deps = check_build_dependencies(apt_cache, control) unsupported_binary_deps = check_binary_dependencies(apt_cache, control) diff -Nru ubuntu-dev-tools-0.164/debian/changelog ubuntu-dev-tools-0.187~bpo18.04.1/debian/changelog --- ubuntu-dev-tools-0.164/debian/changelog 2018-04-24 11:24:43.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/debian/changelog 2021-12-09 16:54:27.000000000 +0000 @@ -1,3 +1,468 @@ +ubuntu-dev-tools (0.187~bpo18.04.1) bionic-backports; urgency=medium + + * Rebuild for bionic-backports. + * archive.py: + + Support Python 3.6 by calling functools.lru_cache() as a function, and + avoid using @functools.cached_property (both new in Python 3.8). + + -- Mattia Rizzolo Thu, 09 Dec 2021 17:54:27 +0100 + +ubuntu-dev-tools (0.187) unstable; urgency=medium + + [ Paride Legovini ] + * mk-sbuild: + + Add support for zfs-snapshot schroots. LP: #1945349 + + [ Mattia Rizzolo ] + * mk-sbuild: + + Apply patch from Peter Pentchev to avoid a broken log message. + Closes: #968316 + * backportpackage: + + Support backporting to Debian releases. Closes: #776442; LP: #974132 + + Fix the guessing algorithm for the target release: + - for Debian: pick the current stable release. + - for Ubuntu: pick the current LTS release. + + [ Unit 193 ] + * backportpackage: + + Change the generated Ubuntu version following the new policy from the + Backporters team. + + [ Dan Streetman ] + * misc: + + Refactor download progress bar code. + + Save files that have Content-Encoding correctly, + such as the changes file from upload queue packages. + * pullpkg: + + Extract source packages pulled from upload queue. + * hugdaylist: + + Remove long unused and non-working script. + + -- Mattia Rizzolo Sun, 05 Dec 2021 15:58:15 +0100 + +ubuntu-dev-tools (0.186) unstable; urgency=medium + + * Replace nose with pytest (see: #997758). + + -- Stefano Rivera Sun, 24 Oct 2021 16:10:44 -0700 + +ubuntu-dev-tools (0.185) unstable; urgency=medium + + [ Alex Murray ] + * ubuntutools/archive.py: + + Fix crash due to PersonalPackageArchiveSourcePackage() returning the + wrong object when requesting a download url. LP: #1938659 + + [ Krytarik Raido ] + * merge-changelog: Fix setting of newlines. + + [ Dan Streetman ] + * misc: download to tmp file, to avoid leftover 0-size file on error + * misc: handle ConnectionError as NotFoundError + * archive: use proper component source packages sometimes have different + component than their bpphs, so use the correct component when downloading + binaries (LP: #1943819) + * misc: fix flake8 complaints + + [ Stefano Rivera ] + * Bump Standards-Version to 4.6.0, no changes needed. + + -- Stefano Rivera Fri, 17 Sep 2021 15:53:02 -0700 + +ubuntu-dev-tools (0.184) experimental; urgency=medium + + [ Dan Streetman ] + * Drop never packaged ubuntu-archive-assistant. + * Add support for downloading from private PPAs: + + ubuntutools/misc: + - Refactor to use Pathlib and f-strings. + - Refactor to use requests instead of urllib (for the earier auth) + + ubuntutools/archive: + - Refactor to use Pathlib. + - Add support for the special URLs of private PPAs. + * Don't use existing file without verifying their checksum. + * tests: recreate the test package files on demand. + * Remove no longer used dependencies on python3-termcolor and python3-yaml + + [ Mattia Rizzolo ] + * pbuilder-dist: use shutil.which instead of + distutils.spawn.find_executable() to save a dependency. LP: #1936697 + * d/control: + + Drop redundant Recommends that are already in Depends. + + Bump debhelper compat level to 13. + + [ Marco Trevisan (Treviño) ] + * mk-sbuild: + + Enable debugging in the finish.sh script if --debug is used. + + Add support to configure ccache for each schroot. + + -- Mattia Rizzolo Sat, 17 Jul 2021 17:31:19 +0200 + +ubuntu-dev-tools (0.183) unstable; urgency=medium + + [ Dan Streetman ] + * pbuilder-dist: include missing import + + -- Stefano Rivera Tue, 08 Jun 2021 10:09:11 -0400 + +ubuntu-dev-tools (0.182) unstable; urgency=medium + + [ Dan Streetman ] + * syncpackage, ubuntutools/archive.py: + Don't save dsc file to disk until requested with pull() + (LP: #1928946) + * syncpackage: + Don't login to LP if using --simulate + * d/t/control: Add minimum flake8 version + The --extend-exclude parameter is first available in flake8 3.8.0 + * ubuntutools/archive.py: Fix flake8 test failure + * d/rules, d/control: Override build tests to use flake8 and nosetests3 + + [ Stefano Rivera ] + * Respect nocheck in DEB_BUILD_OPTIONS, again. + + -- Stefano Rivera Sun, 06 Jun 2021 19:52:18 -0400 + +ubuntu-dev-tools (0.181) unstable; urgency=medium + + [ Logan Rosen ] + * Fix a couple of remaining issues from the py2→py3 move. + + [ Krytarik Raido ] + * Fix typo in the logging configuration. + + [ Dan Streetman ] + * pbuilder: Handle debian change from /updates to -security. LP: #1916633 + Starting in bullseye, the security suite is -security instead of /updates. + * backportpackage: Don't use SourcePackage() directly. Closes: #983854 + As the warning from 2010 says, don't use this class directly. + + [ Balint Reczey ] + * mk-sbuild: + + Use eatmydata only with the dpkg command. + Eatmydata wrapping the build as well could break tests. + Thanks to Julian Andres Klode for suggesting this solution + + Use eatmydata by default. + Since only the dpkg is wrapped in eatmydata it should be the safe and + fast default. Eatmydata is widely used around apt thus it should be a + serious bug if a package can't be installed with eatmydata in use. + + [ Marco Trevisan (Treviño) ] + * doc/mk-sbuild.1: Add documentation for --debootstrap-proxy and + DEBOOTSTRAP_PROXY. LP: #1926166 + + -- Mattia Rizzolo Sun, 02 May 2021 19:56:48 +0200 + +ubuntu-dev-tools (0.180) unstable; urgency=medium + + * Drop coverage in the autopkgtest, as python3-nose-cov is not in Debian. + + -- Mattia Rizzolo Fri, 19 Feb 2021 12:12:33 +0100 + +ubuntu-dev-tools (0.179) unstable; urgency=medium + + [ Stefano Rivera ] + * archive.py: Evaluate the filter() fixing Debian source history queries + LP: #1913330 + + [ Dan Streetman ] + * allow running tests using tox + * add autopkgtests to run tests + * simplify/combine archive download functions + * add support for private ppa by logging into lp + * improve support for pull-uca-* + * fix logging/printing output to stdout/stderr + + -- Dan Streetman Mon, 01 Feb 2021 11:59:03 -0500 + +ubuntu-dev-tools (0.178) unstable; urgency=medium + + [ Dan Streetman ] + * pullpkg: also catch and deal with InvalidPullValueError. LP: #1908770 + + [ Mattia Rizzolo ] + * d/control: Bump Standards-Version to 4.5.1, no changes needed. + * ubuntu-archive-assistant/mir: Fix a SyntaxWarning. + * backportpackage: + + Add a -e/--message option to change the default "No-change" + in "No-change backport to DIST". + Thanks to Unit 193 for the initial patch. + + [ You-Sheng Yang ] + * Add a dependency on tzdata, used by mk-sbuild. + + [ Logan Rosen ] + * import-bug-from-debian: + + Limit bug description length to 50k chars to support Launchpad's limits. + LP: #1193941 + + [ Dimitri John Ledkov ] + * pullpkg.py: fix --mirror option parsing. + * config.py: add UBUNTU_INTERNAL_MIRROR option, for launchpad internal + mirror. + * archive.py: use Regular, Ports, and Internal mirrors by default. Thus + enabling pull-lp-debs to work with ports architectures, and inside + launchpad builds too. + + [ Michael R. Crusoe ] + * pbuilder-dist: + + Use `arch-test` to determine whether the current system can run binaries + of the requested architecture, instead of hardcoding an ever-growing + list of whether something requires qemu or not. Add the "arch-test" + package to Recommends to that effect. + + -- Dimitri John Ledkov Mon, 25 Jan 2021 23:28:24 +0000 + +ubuntu-dev-tools (0.177) unstable; urgency=medium + + [ Dan Streetman ] + * Verify checksums for downloaded binary files + * pullpkg: support pulling from Ubuntu upload queues + + [ Mattia Rizzolo ] + * ubuntu-build: + + Add support for riscv64. + * syncpackge: + + Fix the new flake8 E741. Closes: #963310 + + [ Bryce Harrington ] + * update-maintainer: + + Try to recurse upwards to find a valid debian directory. LP: #1885233 + + -- Mattia Rizzolo Sun, 28 Jun 2020 15:52:27 +0200 + +ubuntu-dev-tools (0.176) unstable; urgency=medium + + [ Debian Janitor ] + * Fix day-of-week for changelog entry 0.66. + + [ Mattia Rizzolo ] + * pbuilder-dist: + + Add support for riscv64. LP: #1859277 + * d/control: Bump Standards-Version to 4.5.0, no changes needed. + + [ Colin Watson ] + * Use +sourcefiles URLs where possible. LP: #1860456 + + [ Dan Streetman ] + * submittodebian: + + Open file in binary mode before writing utf-8 encoded bytes. LP: #1863119 + * ubuntu-upload-permission: + + Explicitly sort packagesets by name. LP: #1862372 + * pullpkg: + + For "-p list", show bpph arch for files built for 'all' arch. + * archive.py: + + If using local file, avoid error trying to copy file to itself. + + Allow pull_binaries() to accept arch=None. + * lpapicache: + + Remove SPPH _have_all_binaries flag, as there are cases where it yield + unexpected results. + + Remove fallback_arch from getBinaries. + + Allow getBinaries(arch=None) to get all archs. LP: #1862286 + + -- Mattia Rizzolo Sun, 23 Feb 2020 13:03:21 +0100 + +ubuntu-dev-tools (0.175) unstable; urgency=medium + + [ Mattia Rizzolo ] + * Trust the installed debian-keyring when checking validity of dsc + signatures. + * requestbackport: + + Error out nicely when a tracking project doesn't exist. LP: #1852901 + * d/control: Bump Standards-Version to 4.4.1, no changes needed. + + [ Stefano Rivera ] + * merge-changelog: rewrite the changelog handling to use python3-debian. + + [ Dan Streetman ] + * tests/pylint.conf: use jobs=0 to speed up tests. + * submittodebian: use a context manager while opening a file. + * d/control: add dependency on python3-lazr.restfulclient. + * Big refactor/rewrite of the whole archive.py module, together with a + restracturing of all the pull-pkg-* commands. + * Unify the logging using the standard python logging module, and remove the + local ubuntutools.logger module. + + -- Mattia Rizzolo Sun, 01 Dec 2019 19:36:23 +0100 + +ubuntu-dev-tools (0.174) unstable; urgency=medium + + [ Stefano Rivera ] + * reverse-depends: + + Support reverse test dependencies as well. LP: #1843614 + * ubuntutools.misc: + + Replace Popen() calls with check_output(). Closes: #940040 + + Use a context manager to open file, to be sure to close them. + + [ Dan Streetman ] + * Update setup.py to also use python3. + * reverse-depends: + + Move from optparse to argparse. + + Rename the typoed --recursive-deph to --recursive-depth. + + Use list comprehensions to simplify del-during-iteration functions. + * import-bug-from-debian: + + Migrate to argparge. + + Add --verbose option. + + Actually make --dry-run do a dry run. + + Handle multiple bug numbers in the command line. + + Correctly get the bug summary. + + -- Mattia Rizzolo Thu, 26 Sep 2019 11:05:53 +0200 + +ubuntu-dev-tools (0.173) unstable; urgency=medium + + [ Stefano Rivera ] + * pull-debian-debdiff: + + Don't unpack the older source package, it will often use the same + directory as the newer one, and break. + * merge-changelog: + + Use ubuntutools.version.Version, to support Python 3. + * Drop 404main, it's been totally broken for years. + * Port all the Python scripts to Python 3, and remove Python 2 support. + Closes: #938740, LP: #1099537 + + [ Dan Streetman ] + * pull-pkg: + + Use ubuntutools.version.Version which has strip_epoch() instead + of debian.debian_support.Version. + * Have ubuntu-dev-tools depend on the matching version of python3-ubuntutools. + + [ Scott Kitterman ] + * Update requestsync to python3. Closes: #927147 + + [ Mattia Rizzolo ] + * Explicitly require Python3 >= 3.6. + + -- Mattia Rizzolo Tue, 10 Sep 2019 15:35:06 +0200 + +ubuntu-dev-tools (0.172) unstable; urgency=medium + + [ Mattia Rizzolo ] + * autopkgtest: Add a allow-stderr restriction, as things log to stderr. + + [ Stefano Rivera ] + * Build-Depend on pylint (>= 2, the Python 3 version), it replaced pylint3. + * Explicitly declare python dependencies in the python library modules (the + setup.py doesn't provide these) and ubuntu-dev-tools itself. + * dh_python2 doesn't generate a python dependency in ubuntu-dev-tools, now + that it's scripts-only, so manually declare one. + * Install pull-debian-source as python 3. It was ported, and doesn't work + under python 2 any more. LP: #1841127 + * Use dh_install to split the build into multiple binary packages. + + -- Mattia Rizzolo Wed, 04 Sep 2019 08:44:51 +0200 + +ubuntu-dev-tools (0.171) unstable; urgency=medium + + * Add an autopkgtest running the package tests. + Currently it runs the tests directly over the sources, instead of the + installed package. + * ubuntutools/archive: Disable dsc signature verification for non-Debian. + Ubuntu doesn't have a unified keyring of developers like Debian has, so + it is not feasible to check for the dsc signatures. + + -- Mattia Rizzolo Mon, 12 Aug 2019 13:42:31 +0200 + +ubuntu-dev-tools (0.170) unstable; urgency=medium + + [ Robie Basak ] + * pull-debian-source: + + Add a new --no-verify-signature option option, to download a source + package without checking its signature. + + Port to Python 3. LP: #1700846 + + [ Mattia Rizzolo ] + * d/control: + + Bump debhelper compat level to 12. + * reverse-depends: + + prevent crash when specifying a specific architecture. Closes: #933018 + * ubuntutools/archive: + + Default to checking signatures while pulling a .dsc. + + -- Mattia Rizzolo Mon, 05 Aug 2019 13:28:23 +0200 + +ubuntu-dev-tools (0.169) unstable; urgency=medium + + [ Colin Watson ] + * mk-sbuild: + + Set personality=linux32 by default on armel and armhf as well. + + [ Sahid Orentino Ferdjaoui ] + * reverse-depends: + + New ability to find reverse-depends recursively, and print a tree. + + [ Mattia Rizzolo ] + * d/control: + + Add myself to uploaders. + + Bump Standards-Version to 4.4.0, no changes needed. + + -- Mattia Rizzolo Sat, 20 Jul 2019 11:18:00 +0200 + +ubuntu-dev-tools (0.168) eoan; urgency=medium + + * grep-merges: flake8-clean. + + -- Steve Langasek Tue, 07 May 2019 21:26:05 -0700 + +ubuntu-dev-tools (0.167) eoan; urgency=medium + + [ Colin Watson ] + * syncpackage: + + Support wildcards in sync-blacklist (LP: #1807992). + + [ Steve Langasek ] + * grep-merges: + + support grepping by team name (full name match) now that MoM exposes + this + + -- Steve Langasek Tue, 07 May 2019 18:53:46 -0700 + +ubuntu-dev-tools (0.166) unstable; urgency=medium + + * Team upload. + + [ Felipe Reyes ] + * pbuilder-dist: + + Fix handling of --othermirror when a local archive found. LP: #1314076 + + [ Jelmer Vernooij ] + * Recommend Bazaar (brz) or Breezy (brz); the latter provides a + command-line compatible interface. + + [ Mathieu Trudel-Lapierre ] + * Add a new tool "ubuntu-archive-assistant" tool for + proposed-migration / mir review. More information on: + https://lists.ubuntu.com/archives/ubuntu-devel/2018-September/040492.html + The tool is not currently installed, see the launchpad bug #1799568. + + [ Benjamin Drung ] + * ubuntutools/test: Introduce get_source_files helper function. + * Update pylint and flake8 unittests. + * Fix invalid escape sequences '\(' or '\)'. Closes: #911689 + + [ Mattia Rizzolo ] + * Add missing dependencies on sensible-utils (thanks lintian!). + * wrap-and-sort -ast. + * Bump Standards-Version to 4.2.1, no changes needed. + * Use the new debhelper-compat(=11) notation and drop d/compat. + * Clarify package descriptions for Python libraries. + Thanks to Ben Finney for the patch. Closes: #804198, #804199 + * Add a recommends on ubuntu-keyring | ubuntu-archive-keyring. + Closes: #838254 + * mk-sbuild: disable recommends also within the chroot. + Thanks to Steve Beattie for the patch. LP: #1268684 + + -- Mattia Rizzolo Tue, 23 Oct 2018 22:08:04 +0200 + +ubuntu-dev-tools (0.165) unstable; urgency=medium + + * Team upload. + * Bump debhelper compat level to 11. + * Fix FTBFS due to newest tar being picker about arguments order. + Closes: #897478 + + -- Mattia Rizzolo Thu, 10 May 2018 10:40:49 +0200 + ubuntu-dev-tools (0.164) unstable; urgency=medium * mk-sbuild: Initialise ubuntu_dist_ge vars so unknown releases work. @@ -24,6 +489,7 @@ [ Dimitri John Ledkov ] * mk-sbuild: add support for 'overlay' in favor of older 'overlayfs'. + Closes: 799267 [ Scott Kitterman ] * pbuilder-dist: add a --backports option to make it easier to build for @@ -2180,7 +2646,7 @@ [ Jonathan Davies ] * Added grab-merge from merges.ubuntu.com (LP: #155098). - -- Jonathan Davies Thu, 09 Mar 2009 17:01:19 +0000 + -- Jonathan Davies Mon, 09 Mar 2009 17:01:19 +0000 ubuntu-dev-tools (0.65) jaunty; urgency=low @@ -3007,10 +3473,10 @@ didn't work (LP: #175183) - added support for --http-proxy, honours now $http_proxy or $HTTP_PROXY - removed $COMPONENTS_LINE from pbuilder call, data is crippled in the - pbuilder chroot. - Instead of this behaviour add $BASE_DIR/etc/$DISTRIBUTION/apt.conf/ - directory and install a sane sources.list, depending on the releases of Ubuntu - and add --aptconfdir to pbuilder call (LP: #175183) + pbuilder chroot. Instead of this behaviour add + $BASE_DIR/etc/$DISTRIBUTION/apt.conf/ directory and install a sane + sources.list, depending on the releases of Ubuntu and add --aptconfdir to + pbuilder call (LP: #175183) - add support for gksudo|kdesudo|sudo depending on $DESKTOP_SESSION. or if $PBUILDAUTH is set to something else, it will be used instead of sudo|gksudo|kdesudo (LP: #172943) @@ -3258,7 +3724,8 @@ [ Siegfried-Angel Gevatter Pujals (RainCT) ] * Added a manpage for suspicious-source. - * Fixed a bug in pbuilder-dist (it needed ftp.debian.org in sources.list to work with Debian). + * Fixed a bug in pbuilder-dist (it needed ftp.debian.org in sources.list to + work with Debian). -- Daniel Holbach Mon, 24 Sep 2007 09:39:24 +0200 diff -Nru ubuntu-dev-tools-0.164/debian/clean ubuntu-dev-tools-0.187~bpo18.04.1/debian/clean --- ubuntu-dev-tools-0.164/debian/clean 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/debian/clean 2021-12-05 15:20:37.000000000 +0000 @@ -1,2 +1 @@ -*.egg-info/* -test-data/example_* +*.egg-info/ diff -Nru ubuntu-dev-tools-0.164/debian/compat ubuntu-dev-tools-0.187~bpo18.04.1/debian/compat --- ubuntu-dev-tools-0.164/debian/compat 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -10 diff -Nru ubuntu-dev-tools-0.164/debian/control ubuntu-dev-tools-0.187~bpo18.04.1/debian/control --- ubuntu-dev-tools-0.164/debian/control 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/debian/control 2021-12-05 15:20:37.000000000 +0000 @@ -2,89 +2,85 @@ Section: devel Priority: optional Maintainer: Ubuntu Developers -Uploaders: Benjamin Drung , - Stefano Rivera -Build-Depends: dctrl-tools, - debhelper (>= 10), - devscripts (>= 2.11.0~), - dh-python, - distro-info (>= 0.2~), - libwww-perl, - lsb-release, - pylint, - pylint3, - python-all (>= 2.6.5-13~), - python-apt (>= 0.7.93~), - python-debian (>= 0.1.20~), - python-distro-info (>= 0.4~), - python-flake8, - python-httplib2, - python-launchpadlib (>= 1.5.7), - python-mock, - python-setuptools, - python-soappy, - python-unittest2, - python3-all, - python3-apt, - python3-debian, - python3-distro-info, - python3-flake8, - python3-httplib2, - python3-launchpadlib, - python3-mock, - python3-setuptools -Standards-Version: 4.1.4 +Uploaders: + Benjamin Drung , + Stefano Rivera , + Mattia Rizzolo , +Build-Depends: + dctrl-tools, + debhelper-compat (= 13), + devscripts (>= 2.11.0~), + dh-make, + dh-python, + distro-info (>= 0.2~), + flake8, + lsb-release, + python3-all, + python3-apt, + python3-debian, + python3-debianbts, + python3-distro-info, + python3-httplib2, + python3-launchpadlib, + python3-pytest, + python3-requests , + python3-setuptools, +Standards-Version: 4.6.0 Rules-Requires-Root: no Vcs-Git: https://git.launchpad.net/ubuntu-dev-tools Vcs-Browser: https://git.launchpad.net/ubuntu-dev-tools Homepage: https://launchpad.net/ubuntu-dev-tools +X-Python3-Version: >= 3.6 Package: ubuntu-dev-tools Architecture: all -Depends: binutils, - dctrl-tools, - devscripts (>= 2.11.0~), - diffstat, - distro-info (>= 0.2~), - dpkg-dev, - lsb-release, - python-apt (>= 0.7.93~), - python-debian (>= 0.1.20~), - python-distro-info (>= 0.4~), - python-httplib2, - python-launchpadlib (>= 1.5.7), - python-lazr.restfulclient, - python-ubuntutools, - sensible-utils, - sudo, - ${misc:Depends}, - ${perl:Depends}, - ${python:Depends} -Recommends: bzr, - bzr-builddeb, - ca-certificates, - debian-archive-keyring, - debian-keyring, - debootstrap, - dput, - genisoimage, - libwww-perl, - lintian, - patch, - pbuilder | cowbuilder | sbuild, - python-dns, - python-soappy, - quilt, - reportbug (>= 3.39ubuntu1) -Suggests: python-simplejson | python (>= 2.7), qemu-user-static +Depends: + binutils, + dctrl-tools, + devscripts (>= 2.11.0~), + diffstat, + distro-info (>= 0.2~), + dpkg-dev, + dput, + lsb-release, + python3, + python3-apt, + python3-debian, + python3-debianbts, + python3-distro-info, + python3-httplib2, + python3-launchpadlib, + python3-lazr.restfulclient, + python3-ubuntutools (= ${binary:Version}), + sensible-utils, + sudo, + tzdata, + ${misc:Depends}, + ${perl:Depends}, +Recommends: + arch-test, + bzr | brz, + bzr-builddeb | brz-debian, + ca-certificates, + debian-archive-keyring, + debian-keyring, + debootstrap, + genisoimage, + lintian, + patch, + pbuilder | cowbuilder | sbuild, + python3-dns, + quilt, + reportbug (>= 3.39ubuntu1), + ubuntu-keyring | ubuntu-archive-keyring, +Suggests: + qemu-user-static, Description: useful tools for Ubuntu developers This is a collection of useful tools that Ubuntu developers use to make their packaging work a lot easier. . Such tools include: . - - 404main - used to check what components a package's deps are in, for - doing a main inclusion report for example. - backportpackage - helper to test package backports - bitesize - add the 'bitesize' tag to a bug and comment that you are willing to help fix it. @@ -94,7 +90,6 @@ - dch-repeat - used to repeat a change log into an older release. - grab-merge - grabs a merge from merges.ubuntu.com easily. - grep-merges - search for pending merges from Debian. - - hugdaylist - compile HugDay lists from bug list URLs. - import-bug-from-debian - copy a bug from the Debian BTS to Launchpad - merge-changelog - manually merges two Debian changelogs with the same base version. @@ -106,8 +101,13 @@ a Debian package and its immediate parent to generate a debdiff. - pull-debian-source - downloads the latest source package available in Debian of a package. - - pull-lp-source - downloads latest source package from Launchpad. - - pull-revu-source - downloads the latest source package from REVU + - pull-lp-source - downloads source package from Launchpad. + - pull-lp-debs - downloads debs package(s) from Launchpad. + - pull-lp-ddebs - downloads dbgsym/ddebs package(s) from Launchpad. + - pull-lp-udebs - downloads udebs package(s) from Launchpad. + - pull-debian-* - same as pull-lp-* but for Debian packages. + - pull-uca-* - same as pull-lp-* but for Ubuntu Cloud Archive packages. + - pull-pkg - common script that provides above pull-* functionality. - requestbackport - file a backporting request. - requestsync - files a sync request with Debian changelog and rationale. - reverse-depends - find the reverse dependencies (or build dependencies) of @@ -126,24 +126,21 @@ package. - update-maintainer - script to update maintainer field in ubuntu packages. -Package: python-ubuntutools -Architecture: all -Section: python -Depends: ${misc:Depends}, ${python:Depends} -Breaks: ubuntu-dev-tools (<< 0.154) -Replaces: ubuntu-dev-tools (<< 0.154) -Description: useful library of APIs for Ubuntu developer tools (Python 2) - This package ships a collection of APIs, helpers and wrappers used to - develop useful utilities for Ubuntu developers. - . - Python 2 variant. - Package: python3-ubuntutools Architecture: all Section: python -Depends: ${misc:Depends}, ${python3:Depends} -Description: useful library of APIs for Ubuntu developer tools +Depends: + python3-debian, + python3-distro-info, + python3-httplib2, + python3-launchpadlib, + python3-lazr.restfulclient, + python3-requests, + sensible-utils, + ${misc:Depends}, + ${python3:Depends}, +Description: useful APIs for Ubuntu developer tools — Python 3 library This package ships a collection of APIs, helpers and wrappers used to develop useful utilities for Ubuntu developers. . - Python 3 variant. + This package installs the library for Python 3. diff -Nru ubuntu-dev-tools-0.164/debian/copyright ubuntu-dev-tools-0.187~bpo18.04.1/debian/copyright --- ubuntu-dev-tools-0.164/debian/copyright 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/debian/copyright 2021-12-05 15:20:37.000000000 +0000 @@ -39,9 +39,7 @@ On Debian systems, the complete text of the GNU General Public License version 2 can be found in the /usr/share/common-licenses/GPL-2 file. -Files: 404main - doc/404main.1 - doc/import-bug-from-debian.1 +Files: doc/import-bug-from-debian.1 doc/pbuilder-dist-simple.1 doc/pbuilder-dist.1 doc/submittodebian.1 @@ -74,13 +72,11 @@ Files: doc/bitesize.1 doc/grab-merge.1 - doc/hugdaylist.1 doc/merge-changelog.1 doc/setup-packaging-environment.1 doc/syncpackage.1 bitesize grab-merge - hugdaylist merge-changelog setup-packaging-environment syncpackage @@ -107,15 +103,10 @@ doc/dch-repeat.1 doc/grep-merges.1 doc/mk-sbuild.1 - doc/pull-lp-source.1 - doc/pull-revu-source.1 doc/ubuntu-build.1 grep-merges mk-sbuild - pull-lp-source - pull-revu-source ubuntu-build - ubuntutools/lp/libsupport.py ubuntutools/lp/lpapicache.py ubuntutools/misc.py Copyright: 2007-2010, Canonical Ltd. @@ -143,7 +134,7 @@ version 3 can be found in the /usr/share/common-licenses/GPL-3 file. Files: doc/pull-debian-debdiff.1 - doc/pull-debian-source.1 + doc/pull-pkg.1 doc/requestbackport.1 doc/reverse-depends.1 doc/seeded-in-ubuntu.1 @@ -153,12 +144,11 @@ doc/update-maintainer.1 enforced-editing-wrapper pull-debian-debdiff - pull-debian-source + pull-pkg requestbackport reverse-depends seeded-in-ubuntu sponsor-patch - test-data/* ubuntu-upload-permission ubuntutools/archive.py ubuntutools/builder.py @@ -173,6 +163,7 @@ 2010, Evan Broder 2008, Siegfried-Angel Gevatter Pujals 2010-2011, Stefano Rivera + 2017-2021, Dan Streetman License: ISC Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff -Nru ubuntu-dev-tools-0.164/debian/gbp.conf ubuntu-dev-tools-0.187~bpo18.04.1/debian/gbp.conf --- ubuntu-dev-tools-0.164/debian/gbp.conf 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/debian/gbp.conf 2018-05-10 08:39:52.000000000 +0000 @@ -4,7 +4,6 @@ sign-tags = True [dch] -id-length = 7 meta = True auto = True full = True diff -Nru ubuntu-dev-tools-0.164/debian/python3-ubuntutools.install ubuntu-dev-tools-0.187~bpo18.04.1/debian/python3-ubuntutools.install --- ubuntu-dev-tools-0.164/debian/python3-ubuntutools.install 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/debian/python3-ubuntutools.install 2019-09-04 06:43:05.000000000 +0000 @@ -0,0 +1 @@ +/usr/lib/python3.* diff -Nru ubuntu-dev-tools-0.164/debian/rules ubuntu-dev-tools-0.187~bpo18.04.1/debian/rules --- ubuntu-dev-tools-0.164/debian/rules 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/debian/rules 2021-12-05 15:20:37.000000000 +0000 @@ -1,12 +1,15 @@ #!/usr/bin/make -f -export PYBUILD_NAME=ubuntutools +override_dh_auto_clean: + dh_auto_clean + rm -f .coverage + rm -rf .tox -%: - dh $@ --with python2,python3 --buildsystem=pybuild +override_dh_auto_test: +ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) + flake8 -v --max-line-length=99 + python3 -m pytest -v ubuntutools +endif -override_dh_install: - dh_install - mkdir -p debian/ubuntu-dev-tools/usr - mv debian/python-ubuntutools/usr/bin debian/ubuntu-dev-tools/usr/ - mv debian/python-ubuntutools/usr/share debian/ubuntu-dev-tools/usr/ +%: + dh $@ --with python3 --buildsystem=pybuild diff -Nru ubuntu-dev-tools-0.164/debian/tests/control ubuntu-dev-tools-0.187~bpo18.04.1/debian/tests/control --- ubuntu-dev-tools-0.164/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/debian/tests/control 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,12 @@ +Test-Command: flake8 -v --max-line-length=99 +Depends: + flake8, +Restrictions: allow-stderr + +Test-Command: python3 -m pytest -v ubuntutools +Depends: + dh-make, + python3-pytest, + python3-setuptools, + @, +Restrictions: allow-stderr diff -Nru ubuntu-dev-tools-0.164/debian/ubuntu-dev-tools.install ubuntu-dev-tools-0.187~bpo18.04.1/debian/ubuntu-dev-tools.install --- ubuntu-dev-tools-0.164/debian/ubuntu-dev-tools.install 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/debian/ubuntu-dev-tools.install 2019-09-04 06:43:05.000000000 +0000 @@ -0,0 +1,2 @@ +/usr/bin +/usr/share diff -Nru ubuntu-dev-tools-0.164/doc/404main.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/404main.1 --- ubuntu-dev-tools-0.164/doc/404main.1 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/404main.1 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -.TH 404main 1 "February 17, 2008" "ubuntu-dev-tools" - -.SH NAME -404main \- check if all build dependencies of a package are in main - -.SH SYNOPSIS -\fB404main\fP <\fIpackage name\fP> [<\fIdistribution\fP>] - -.SH DESCRIPTION -\fB404main\fP is a script that can be used to check if a package and -all its build dependencies are in Ubuntu's main component or not. - -.SH CAVEATS -\fB404main\fP will take the dependencies and build dependencies of the -packages from the distribution you have first in your -/etc/apt/sources.list file. -.PP -Also, because of this the <\fIdistribution\fP> option is NOT trustworthy; if -the dependencies changed YOU WILL GET INCORRECT RESULTS. - -.SH SEE ALSO -.BR apt-cache (8) - -.SH AUTHORS -\fB404main\fP was written by Pete Savage and -this manpage by Siegfried-Angel Gevatter Pujals . -.PP -Both are released under the GNU General Public License, version 2 or -later. diff -Nru ubuntu-dev-tools-0.164/doc/hugdaylist.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/hugdaylist.1 --- ubuntu-dev-tools-0.164/doc/hugdaylist.1 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/hugdaylist.1 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -.TH HUGDAYLIST "1" "August 27, 2008" "ubuntu-dev-tools" - -.SH NAME -hugdaylist \- produce MoinMoin wiki formatted tables based on a Launchpad bug list - -.SH SYNOPSIS -.B hugdaylist [\fB\-n\fP|\fB\-\-number \fP] \fBlaunchpad-buglist-url\fP - -.SH DESCRIPTION -\fBhugdaylist\fP produces MoinMoin wiki formatted tables based on a -Launchpad bug list - -.SH OPTIONS -.TP -\fB\-\-number=\fP -This option allows you to specify the number of entries to output. -.TP -\fBlaunchpad-buglist-url\fP -Required, this option is a URL pointing to a launchpad bug list. - -.SH AUTHOR -\fBhugdaylist\fP has been written by Canonical Ltd., Daniel Holbach - and Jonathan Patrick Davies . -This manual page was written by Ryan Kavanagh . -.PP -Both are released under the GNU General Public License, version 3. diff -Nru ubuntu-dev-tools-0.164/doc/mk-sbuild.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/mk-sbuild.1 --- ubuntu-dev-tools-0.164/doc/mk-sbuild.1 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/mk-sbuild.1 2021-12-05 15:20:37.000000000 +0000 @@ -64,6 +64,15 @@ debootstrap's \fB\-\-no\-check\-gpg\fR option. See \fBdebootstrap\fR (8) for more details. .TP +.B \-\-debootstrap\-proxy\fR=\fIPROXY +Use \fIPROXY\fR as apt proxy. +.TP +.B \-\-eatmydata +Install and use eatmydata (default) +.TP +.B \-\-skip\-eatmydata +Don't install and use eatmydata +.TP .B \-\-distro\fR=\fIDISTRO Enable distro-specific logic. When not provided, the distribution is determined from \fIrelease\fR. @@ -78,6 +87,21 @@ Specify a \fBSCHROOT_TYPE\fR. Supported values are "\fBdirectory\fR" (default if \fB\-\-vg\fR not specified), "\fBlvm-snapshot\fR" (default if \fB\-\-vg\fR specified), "\fBbtrfs-snapshot\fR", and "\fBfile\fR". +.TP +.B \-\-ccache +Enable usage of \fBccache\fR by default. See \fBccache\fR (1) for +more details. +.TP +.B \-\-ccache-dir=\fIPATH +Use \fBPATH\fR as schroot ccache directory. This directory can be +safely shared by multiple schroots, but they will all use the same +\fBCCACHE_MAXSIZE\fR. +Defaults to /var/cache/ccache-sbuild. +See \fBccache\fR (1) for more details. +.TP +.B \-\-ccache-size=\fISIZE +Sets \fBSIZE\fR as the schroot \fBCCACHE_DIR\fR max-size used by ccache. +See \fBccache\fR (1) for more details. .SH ENVIRONMENT VARIABLES .TP @@ -120,6 +144,14 @@ Disable gpg verification of retrieved release files (same as \fB\-\-debootstrap\-no\-check\-gpg\fR) .TP +.B DEBOOTSTRAP_PROXY +Proxy to use for apt. (same as +\fB\-\-debootstrap\-proxy\fR) +.TP +.B EATMYDATA +Enable or disable eatmydata usage, see \fB\-\-eatmydata\fR +and \fB\-\-skip\-eatmydata\fR +.TP .B SOURCE_CHROOTS_DIR Use \fBSOURCE_CHROOTS_DIR\fR as home of schroot source directories. (default \fB/var/lib/schroot/chroots\fR) @@ -131,6 +163,18 @@ .B CHROOT_SNAPSHOT_DIR Use \fBCHROOT_SNAPSHOT_DIR\fR as home of mounted btrfs snapshots. (default \fB/var/lib/schroot/snapshots\fR) +.TP +.B CCACHE +Enable \fBccache\fR (1) by default. +(defaults to \fB0\fR) +.TP +.B CCACHE_DIR +Use \fBCCACHE_DIR\fR as the \fBccache\fR (1) directory. +(default \fB/var/cache/ccache-sbuild\fR) +.TP +.B CCACHE_SIZE +Use \fBCCACHE_SIZE\fR as the \fBccache\fR (1) max-size. +(defaults to \fB4G\fR) .SH FILES diff -Nru ubuntu-dev-tools-0.164/doc/pull-debian-ddebs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-debian-ddebs.1 --- ubuntu-dev-tools-0.164/doc/pull-debian-ddebs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-debian-ddebs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-debian-debs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-debian-debs.1 --- ubuntu-dev-tools-0.164/doc/pull-debian-debs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-debian-debs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-debian-source.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-debian-source.1 --- ubuntu-dev-tools-0.164/doc/pull-debian-source.1 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-debian-source.1 2021-12-05 15:20:37.000000000 +0000 @@ -1,67 +1,100 @@ -.\" Copyright (C) 2010-2011, Stefano Rivera -.\" -.\" Permission to use, copy, modify, and/or distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -.\" AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -.\" OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -.\" PERFORMANCE OF THIS SOFTWARE. -.TH PULL\-DEBIAN\-SOURCE "1" "22 January 2011" "ubuntu\-dev\-tools" +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" .SH NAME -pull\-debian\-source \- download and extract a source package from Debian +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA .SH SYNOPSIS -.B pull\-debian\-source \fR[\fIoptions\fR] <\fIsource package\fR> +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> [\fIrelease\fR|\fIversion\fR] .SH DESCRIPTION -\fBpull\-debian\-source\fR downloads and extracts the specified -\fIversion\fR of \fIsource package\fR, or the latest version in the -specified Debian \fIrelease\fR. -.P -\fBpull\-debian\-source\fR will try the preferred mirror, default -mirror, security mirror, and fall back to \fBLaunchpad\fR or -\fBsnapshot.debian.org\fR, in search of the requested version. +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. .SH OPTIONS +Listed below are the command line options for pull\-pkg: .TP -.I source package -The source package to download from Debian. +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. .TP .I release -The release to download the source package from. Defaults to -\fBunstable\fR. +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. .TP -.I version -The specific version of the package to download. +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. .TP .BR \-d ", " \-\-download\-only -Do not extract the source package. +Do not extract the source package (applies only to source packages). .TP -.B \-m \fIDEBIAN_MIRROR\fR, \fB\-\-mirror\fR=\fIDEBIAN_MIRROR\fR -Use the specified mirror. -Should be in the form \fBhttp://ftp.debian.org/debian\fR. -If the package isn't found on this mirror, \fBpull\-debian\-source\fR -will fall back to the default mirror. -.TP -.B \-s \fIDEBSEC_MIRROR\fR, \fB\-\-security\-mirror\fR=\fIDEBSEC_MIRROR\fR -Use the specified mirror. -Should be in the form \fBhttp://security.debian.org\fR. -If the package isn't found on this mirror, \fBpull\-debian\-source\fR -will fall back to the default mirror. +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. .TP .B \-\-no\-conf -Do not read any configuration files, or configuration from environment -variables. +Do not use mirrors from the default configuration, or from +any environment variables. .TP -.BR \-h ", " \-\-help -Display the usage instructions and exit. +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. .SH ENVIRONMENT All of the \fBCONFIGURATION VARIABLES\fR below are also supported as @@ -76,14 +109,39 @@ In each case, the script\-specific variable takes precedence over the package\-wide variable. .TP -.BR PULL_DEBIAN_SOURCE_DEBIAN_MIRROR ", " UBUNTUTOOLS_DEBIAN_MIRROR -The default value for \fB\-\-mirror\fR. +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. .TP -.BR PULL_DEBIAN_SOURCE_DEBSEC_MIRROR ", " UBUNTUTOOLS_DEBSEC_MIRROR -The default value for \fB\-\-security\-mirror\fR. +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. .SH SEE ALSO .BR dget (1), -.BR pull\-debian\-debdiff (1), .BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), .BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-debian-udebs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-debian-udebs.1 --- ubuntu-dev-tools-0.164/doc/pull-debian-udebs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-debian-udebs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-lp-ddebs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-lp-ddebs.1 --- ubuntu-dev-tools-0.164/doc/pull-lp-ddebs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-lp-ddebs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-lp-debs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-lp-debs.1 --- ubuntu-dev-tools-0.164/doc/pull-lp-debs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-lp-debs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-lp-source.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-lp-source.1 --- ubuntu-dev-tools-0.164/doc/pull-lp-source.1 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-lp-source.1 2021-12-05 15:20:37.000000000 +0000 @@ -1,60 +1,106 @@ -.TH PULL\-LP\-SOURCE "1" "4 August 2008" "ubuntu-dev-tools" +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" .SH NAME -pull\-lp\-source \- download a source package from Launchpad +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA .SH SYNOPSIS -.B pull\-lp\-source \fR[\fIoptions\fR]\fB \fBsource package\fR +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> [\fIrelease\fR|\fIversion\fR] .SH DESCRIPTION -\fBpull\-lp\-source\fR downloads and extracts the specified -\fIversion\fR of <\fBsource package\fR> from Launchpad, or the latest -version of the specified \fIrelease\fR. -To request a version from a particular pocket say -\fIrelease\fB\-\fIpocket\fR (with a magic \fB\-release\fR for only the -release pocket). +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. If no \fIversion\fR or \fIrelease\fR is specified, the latest version in the development release will be downloaded. +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + .SH OPTIONS -Listed below are the command line options for pull\-lp\-source: -.TP -.B source package -This is the source package that you would like to be downloaded from Launchpad. +Listed below are the command line options for pull\-pkg: .TP -.B version -This is the version of the source package to be downloaded. -.TP -.B release -This is the release that you would like the source package to be downloaded from. -This value defaults to the current development release. +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. .TP .BR \-h ", " \-\-help Display a help message and exit. .TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP .BR \-d ", " \-\-download\-only -Do not extract the source package. +Do not extract the source package (applies only to source packages). .TP -.B \-m \fIUBUNTU_MIRROR\fR, \fB\-\-mirror\fR=\fIUBUNTU_MIRROR\fR -Use the specified Ubuntu mirror. -Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR. -If the package isn't found on this mirror, \fBpull\-lp\-source\fR will -fall back to Launchpad, as its name implies. +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. .TP .B \-\-no\-conf -Do not read any configuration files, or configuration from environment -variables. +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. .SH ENVIRONMENT All of the \fBCONFIGURATION VARIABLES\fR below are also supported as environment variables. Variables in the environment take precedence to those in configuration files. -.TP -.B -DIST -Specifies the default target. .SH CONFIGURATION VARIABLES The following variables can be set in the environment or in @@ -63,17 +109,39 @@ In each case, the script\-specific variable takes precedence over the package\-wide variable. .TP -.BR PULL_LP_SOURCE_UBUNTU_MIRROR ", " UBUNTUTOOLS_UBUNTU_MIRROR -The default value for \fB\-\-mirror\fR. +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. .SH SEE ALSO .BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), .BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), .BR pull\-debian\-debdiff (1), .BR ubuntu\-dev\-tools (5) .SH AUTHOR .PP -\fBpull\-lp\-source\fR and this manual page were written by Iain Lane -. -Both are released under the GNU General Public License, version 3 or later. +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-lp-udebs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-lp-udebs.1 --- ubuntu-dev-tools-0.164/doc/pull-lp-udebs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-lp-udebs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-pkg.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-pkg.1 --- ubuntu-dev-tools-0.164/doc/pull-pkg.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-pkg.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-ppa-ddebs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-ppa-ddebs.1 --- ubuntu-dev-tools-0.164/doc/pull-ppa-ddebs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-ppa-ddebs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-ppa-debs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-ppa-debs.1 --- ubuntu-dev-tools-0.164/doc/pull-ppa-debs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-ppa-debs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-ppa-source.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-ppa-source.1 --- ubuntu-dev-tools-0.164/doc/pull-ppa-source.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-ppa-source.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-ppa-udebs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-ppa-udebs.1 --- ubuntu-dev-tools-0.164/doc/pull-ppa-udebs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-ppa-udebs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-revu-source.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-revu-source.1 --- ubuntu-dev-tools-0.164/doc/pull-revu-source.1 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-revu-source.1 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -.TH PULL\-REVU\-SOURCE "1" "30 August 2009" "ubuntu-dev-tools" - -.SH NAME -pull\-revu\-source \- download a source package from REVU - -.SH SYNOPSIS -.B pull\-revu\-source \fR[\fB\-h\fR]\fB <\fBsource package\fR> - -.SH DESCRIPTION -\fBpull\-revu\-source\fR downloads and extracts the latest version of -<\fBsource package\fR> from REVU. - -.SH OPTIONS -Listed below are the command line options for pull\-revu\-source: -.TP -.B \-h, \-\-help -Display the usage instructions and exit. -.TP -.B -This is the source package that you would like to be downloaded from Debian. - -.SH AUTHOR -.PP -\fBpull\-revu\-source\fR and this manual page were written by Nathan Handler -. \fBpull\-revu\-source\fR is based on \fBrevupull\fR in -\fBkubuntu\-dev\-tools\fR, written by Harald Sitter . -Both are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-uca-ddebs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-uca-ddebs.1 --- ubuntu-dev-tools-0.164/doc/pull-uca-ddebs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-uca-ddebs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-uca-debs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-uca-debs.1 --- ubuntu-dev-tools-0.164/doc/pull-uca-debs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-uca-debs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-uca-source.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-uca-source.1 --- ubuntu-dev-tools-0.164/doc/pull-uca-source.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-uca-source.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/pull-uca-udebs.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-uca-udebs.1 --- ubuntu-dev-tools-0.164/doc/pull-uca-udebs.1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/pull-uca-udebs.1 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,147 @@ +.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools" + +.SH NAME +pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA + +.SH SYNOPSIS +.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR> +[\fIrelease\fR|\fIversion\fR] + +.SH DESCRIPTION +\fBpull\-pkg\fR downloads the specified \fIversion\fR of +<\fIpackage name\fR>, or the latest version from the +specified \fIrelease\fR. To request a version from +a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic +\fB\-release\fR for only the release pocket). If no \fIpocket\fR is +specified, all pockets will be searched except -backports. +If no \fIversion\fR or \fIrelease\fR is specified, the latest version in +the development release will be downloaded. + +There are convenience scripts that set pull type and distribution +appropriately: these are +\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR, +and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages; +\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR, +and \fBpull\-debian\-udebs\fR, which all pull Debian packages; +\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR, +and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages; +and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR, +and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package +Archive on Launchpad. Each script pulls the file type in its name, i.e. +\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR. + +.SH OPTIONS +Listed below are the command line options for pull\-pkg: +.TP +.I package name +This is name of the package to downloaded. +You can use either the source package name, or binary package name. +.TP +.I version +This is the version of the package to downloaded. +.TP +.I release +This is the release to downloaded from. +For debian, you can use either the release name like \fBjessie\fR +or \fBsid\fR, or you can use the special release names \fBunstable\fR, +\fBstable\fR, or \fBtesting\fR. +For ubuntu, you can use either the release name like \fBxenial\fR +or the release-pocket like \fBxenial-proposed\fR. +For ubuntu cloud archive (uca) you can use either the uca release +name like \fBmitaka\fR or the ubuntu and uca release names like +\fBtrusty-mitaka\fR. Defaults to the current development release. +.TP +.BR \-h ", " \-\-help +Display a help message and exit. +.TP +.BR \-v ", " \-\-verbose +Be verbose about what is being done. +.TP +.BR \-d ", " \-\-download\-only +Do not extract the source package (applies only to source packages). +.TP +.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR +Use the specified mirror server. +Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or +\fBhttp://deb.debian.org/debian\fR. If not specified or if the +package is not found on the specified mirror, this will fall +back to the default mirror(s) and/or mirror(s) from environment +variables, and then will fall back to Launchpad or Debian Snapshot. +This can be specified multiple times to try multiple mirrors. +.TP +.B \-\-no\-conf +Do not use mirrors from the default configuration, or from +any environment variables. +.TP +.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR +Get binary packages from the \fIARCH\fR architecture. +Defaults to the local architecture, if it can be deteected. +.TP +.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR +What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR, +or \fBlist\fR. The \fBlist\fR action only lists all a package's +source and binary files, but does not actually download any. +Defaults to \fBsource\fR. +.TP +.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR +Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR. +\fBlp\fR can be used instead of \fBubuntu\fR. +Any string containing \fBcloud\fR can be used instead of \fBuca\fR. +If pulling from a ppa, you must specify the PPA. Defaults to \fBubuntu\fR. +.TP +.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR +Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as +a value to the \fB\-\-ppa\fR option parameter, or as a plain option +(like \fIrelease\fR or \fIversion\fR). When specified as a plain option, +the form must be \fBppa:USER/NAME\fR; when specified as a value to the +\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional. + +.SH ENVIRONMENT +All of the \fBCONFIGURATION VARIABLES\fR below are also supported as +environment variables. +Variables in the environment take precedence to those in configuration +files. + +.SH CONFIGURATION VARIABLES +The following variables can be set in the environment or in +.BR ubuntu\-dev\-tools (5) +configuration files. +In each case, the script\-specific variable takes precedence over the +package\-wide variable. +.TP +.BR UBUNTUTOOLS_UBUNTU_MIRROR +The default mirror. +.TP +.BR PULL_PKG_UBUNTU_MIRROR +The default mirror when using the \fBpull\-pkg\fR script. +.TP +.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR +The default mirror when using the associated script. + +.SH SEE ALSO +.BR dget (1), +.BR pull\-lp\-source (1), +.BR pull\-lp\-debs (1), +.BR pull\-lp\-ddebs (1), +.BR pull\-lp\-udebs (1), +.BR pull\-debian\-source (1), +.BR pull\-debian\-debs (1), +.BR pull\-debian\-ddebs (1), +.BR pull\-debian\-udebs (1), +.BR pull\-ppa\-source (1), +.BR pull\-ppa\-debs (1), +.BR pull\-ppa\-ddebs (1), +.BR pull\-ppa\-udebs (1), +.BR pull\-uca\-source (1), +.BR pull\-uca\-debs (1), +.BR pull\-uca\-ddebs (1), +.BR pull\-uca\-udebs (1), +.BR pull\-debian\-debdiff (1), +.BR ubuntu\-dev\-tools (5) + +.SH AUTHOR +.PP +\fBpull\-pkg\fR was written by Dan Streetman , +based on the original \fBpull\-lp\-source\fR; it and this manual page +were written by Iain Lane . +All are released under the GNU General Public License, version 3 or later. diff -Nru ubuntu-dev-tools-0.164/doc/reverse-build-depends.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/reverse-build-depends.1 --- ubuntu-dev-tools-0.164/doc/reverse-build-depends.1 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/reverse-build-depends.1 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -.TH REVERSE-BUILD-DEPENDS "1" "June 2012" "ubuntu-dev-tools" -.SH NAME -reverse-build-depends \- find packages that depend on a specific package to -build (reverse build depends) -.SH SYNOPSIS -.TP -.B reverse-build-depends \fR[\fIoptions\fR] \fIpackage -.SH DESCRIPTION -\fBreverse-build-depends\fR has been replaced by \fBreverse-depends \-b\fR. -This script now wraps \fBreverse-depends\fR. -Please use it in the future. -.SH SEE ALSO -.BR reverse-depends (1) diff -Nru ubuntu-dev-tools-0.164/doc/ubuntu-build.1 ubuntu-dev-tools-0.187~bpo18.04.1/doc/ubuntu-build.1 --- ubuntu-dev-tools-0.164/doc/ubuntu-build.1 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/doc/ubuntu-build.1 2021-12-05 15:20:37.000000000 +0000 @@ -37,8 +37,9 @@ .IP \fB\-a\fR ARCHITECTURE, \fB\-\-arch\fR=\fIARCHITECTURE\fR Rebuild or rescore a specific architecture. Valid -architectures include: amd64, sparc, powerpc, i386, -armel, armhf, arm64, ia64, lpia, hppa, ppc64el, s390x. +architectures are: +armel, armhf, arm64, amd64, hppa, i386, ia64, +lpia, powerpc, ppc64el, riscv64, s390x, sparc. .TP Batch processing: .IP @@ -60,8 +61,9 @@ .IP \fB\-\-arch2\fR=\fIARCHITECTURE\fR Affect only 'architecture' (can be used several -times). Valid architectures are: amd64, sparc, -powerpc, i386, armel, armhf, arm64, ia64, lpia, hppa. +times). Valid architectures are: +armel, armhf, arm64, amd64, hppa, i386, ia64, +lpia, powerpc, ppc64el, riscv64, s390x, sparc. .SH AUTHORS \fBubuntu-build\fR was written by Martin Pitt , and diff -Nru ubuntu-dev-tools-0.164/enforced-editing-wrapper ubuntu-dev-tools-0.187~bpo18.04.1/enforced-editing-wrapper --- ubuntu-dev-tools-0.164/enforced-editing-wrapper 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/enforced-editing-wrapper 2019-09-10 12:14:20.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # # Copyright (C) 2011, Stefano Rivera # diff -Nru ubuntu-dev-tools-0.164/grep-merges ubuntu-dev-tools-0.187~bpo18.04.1/grep-merges --- ubuntu-dev-tools-0.164/grep-merges 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/grep-merges 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/python3 # # grep-merges - search for pending merges from Debian # @@ -27,6 +27,9 @@ import ubuntutools.misc +from ubuntutools import getLogger +Logger = getLogger() + def main(): parser = optparse.OptionParser( @@ -51,12 +54,12 @@ url = 'https://merges.ubuntu.com/%s.json' % component try: headers, page = Http().request(url) - except HttpLib2Error, e: - print >> sys.stderr, str(e) + except HttpLib2Error as e: + Logger.exception(e) sys.exit(1) if headers.status != 200: - print >> sys.stderr, "%s: %s %s" % (url, headers.status, - headers.reason) + Logger.error("%s: %s %s" % (url, headers.status, + headers.reason)) sys.exit(1) for merge in json.loads(page): @@ -66,9 +69,12 @@ author = merge['user'] if merge.get('uploader'): uploader = '(%s)' % merge['uploader'] - pretty_uploader = u'{} {}'.format(author, uploader) - if match is None or match in package or match in author or match in uploader: - print '%s\t%s' % (package.encode("utf-8"), pretty_uploader.encode("utf-8")) + teams = merge.get('teams', []) + + pretty_uploader = '{} {}'.format(author, uploader) + if (match is None or match in package or match in author + or match in uploader or match in teams): + Logger.info('%s\t%s' % (package, pretty_uploader)) if __name__ == '__main__': diff -Nru ubuntu-dev-tools-0.164/hugdaylist ubuntu-dev-tools-0.187~bpo18.04.1/hugdaylist --- ubuntu-dev-tools-0.164/hugdaylist 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/hugdaylist 1970-01-01 00:00:00.000000000 +0000 @@ -1,139 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2007 Canonical Ltd., Daniel Holbach -# Copyright (C) 2008 Jonathan Patrick Davies -# -# ################################################################## -# -# 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; version 3. -# -# 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. -# -# See file /usr/share/common-licenses/GPL-3 for more details. -# -# ################################################################## -# -# -# hugdaylist - produces MoinMoin wiki formatted tables based on a Launchpad bug -# list. -# -# hugdaylist -# - produces lists like https://wiki.ubuntu.com/UbuntuBugDay/20070912?action=raw -# -# hugdaylist -n -# - will only list URLs. - -import sys -from optparse import OptionParser - -from launchpadlib.launchpad import Launchpad - -from ubuntutools.lp.libsupport import translate_web_api - - -def check_args(): - howmany = -1 - url = "" - - # Our usage options. - usage = "usage: %prog [-n ] launchpad-buglist-url" - opt_parser = OptionParser(usage) - - # Options - namely just the number of bugs to output. - opt_parser.add_option("-n", "--number", type="int", - dest="number", help="Number of entries to output.") - - # Parse arguments. - (options, args) = opt_parser.parse_args() - - # Check if we want a number other than the default. - howmany = options.number - - # Check that we have an URL. - if not args: - print >> sys.stderr, "An URL pointing to a Launchpad bug list is " \ - "required." - opt_parser.print_help() - sys.exit(1) - else: - url = args[0] - - return (howmany, url) - - -def filter_unsolved(task): - # TODO: don't use this filter here, only check status and assignee of - # the given task - # Filter out special types of bugs: - # - https://wiki.ubuntu.com/Bugs/HowToTriage#Special%20types%20of%20bugs - # this is expensive, parse name out of self_link instead? - subscriptions = set(s.person.name for s in task.bug.subscriptions) - if (task.status != "Fix Committed" and - (not task.assignee or task.assignee.name in ['motu', 'desktop-bugs']) and - 'ubuntu-sponsors' not in subscriptions and - 'ubuntu-archive' not in subscriptions): - return True - return False - - -def main(): - (howmany, url) = check_args() - if len(url.split("?", 1)) == 2: - # search options not supported, because there is no mapping web ui - # options <-> API options - print >> sys.stderr, "Options in url are not supported, url: %s" % url - sys.exit(1) - - launchpad = None - try: - launchpad = Launchpad.login_with("ubuntu-dev-tools", 'production') - except IOError, error: - print error - sys.exit(1) - - api_url = translate_web_api(url, launchpad) - try: - product = launchpad.load(api_url) - except Exception, error: - response = getattr(error, "response", {}) - if response.get("status", None) == "404": - print >> sys.stderr, ("The URL at '%s' does not appear to be a " - "valid url to a product") % url - sys.exit(1) - else: - raise - - bug_list = [b for b in product.searchTasks() if filter_unsolved(b)] - - if not bug_list: - print "Bug list of %s is empty." % url - sys.exit(0) - if howmany == -1: - howmany = len(bug_list) - - print """ -## || This task is done || somebody || || -## || This task is assigned || somebody || || -## || This task isn't || ... || || -## || This task is blocked on something || somebody || || - -|| Bug || Subject || Triager ||""" - - for i in list(bug_list)[:howmany]: - bug = i.bug - print '|| [%s %s] || %s || ||' % \ - (bug.web_link, bug.id, bug.title) - - -if __name__ == '__main__': - try: - main() - except KeyboardInterrupt: - print >> sys.stderr, "Aborted." - sys.exit(1) diff -Nru ubuntu-dev-tools-0.164/import-bug-from-debian ubuntu-dev-tools-0.187~bpo18.04.1/import-bug-from-debian --- ubuntu-dev-tools-0.164/import-bug-from-debian 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/import-bug-from-debian 2021-12-05 15:20:37.000000000 +0000 @@ -1,5 +1,4 @@ -#!/usr/bin/python -# -*- coding: UTF-8 -*- +#!/usr/bin/python3 # Copyright © 2009 James Westby , # 2010, 2011 Stefano Rivera @@ -22,7 +21,9 @@ # # ################################################################## -from optparse import OptionParser, SUPPRESS_HELP +import argparse +import debianbts +import logging import re import sys import webbrowser @@ -30,51 +31,43 @@ from launchpadlib.launchpad import Launchpad from ubuntutools.config import UDTConfig -from ubuntutools.logger import Logger -try: - import SOAPpy -except ImportError: - Logger.error("Please install 'python-soappy' in order to use this utility.") - sys.exit(1) +from ubuntutools import getLogger +Logger = getLogger() def main(): bug_re = re.compile(r"bug=(\d+)") - url = 'http://bugs.debian.org/cgi-bin/soap.cgi' - namespace = 'Debbugs/SOAP' - debbugs = SOAPpy.SOAPProxy(url, namespace) - - # debug - # debbugs.config.dumpSOAPOut = 1 - # debbugs.config.dumpSOAPIn = 1 - - parser = OptionParser(usage="%prog [option] bug ...") - parser.add_option("-b", "--browserless", - help="Don't open the bug in the browser at the end", - dest="browserless", action="store_true") - parser.add_option("-l", "--lpinstance", metavar="INSTANCE", - help="Launchpad instance to connect to " - "(default: production)", - dest="lpinstance", default=None) - parser.add_option("-n", "--dry-run", - help=SUPPRESS_HELP, - dest="lpinstance", action="store_const", const="staging") - parser.add_option("-p", "--package", metavar="PACKAGE", - help="Launchpad package to file bug against " - "(default: Same as Debian)", - dest="package", default=None) - parser.add_option("--no-conf", dest="no_conf", default=False, - help="Don't read config files or environment variables.", - action="store_true") - (options, args) = parser.parse_args() + parser = argparse.ArgumentParser() + parser.add_argument("-b", "--browserless", action="store_true", + help="Don't open the bug in the browser at the end") + parser.add_argument("-l", "--lpinstance", metavar="INSTANCE", + help="LP instance to connect to (default: production)") + parser.add_argument("-v", "--verbose", action="store_true", + help="Print info about the bug being imported") + parser.add_argument("-n", "--dry-run", action="store_true", + help="Don't actually open a bug (also sets verbose)") + parser.add_argument("-p", "--package", + help="Launchpad package to file bug against " + "(default: Same as Debian)") + parser.add_argument("--no-conf", action="store_true", + help="Don't read config files or environment variables.") + parser.add_argument("bugs", nargs="+", help="Bug number(s) or URL(s)") + options = parser.parse_args() config = UDTConfig(options.no_conf) if options.lpinstance is None: options.lpinstance = config.get_value("LPINSTANCE") - launchpad = Launchpad.login_with("ubuntu-dev-tools", options.lpinstance) + if options.dry_run: + launchpad = Launchpad.login_anonymously("ubuntu-dev-tools") + options.verbose = True + else: + launchpad = Launchpad.login_with("ubuntu-dev-tools", options.lpinstance) + + if options.verbose: + Logger.setLevel(logging.DEBUG) debian = launchpad.distributions['debian'] ubuntu = launchpad.distributions['ubuntu'] @@ -82,7 +75,7 @@ bug_nums = [] - for bug_num in args: + for bug_num in options.bugs: if bug_num.startswith("http"): # bug URL match = bug_re.search(bug_num) @@ -94,35 +87,45 @@ bug_num = int(bug_num) bug_nums.append(bug_num) - bugs = debbugs.get_status(*bug_nums) - - if len(bug_nums) > 1: - bugs = bugs[0] + bugs = debianbts.get_status(*bug_nums) if not bugs: Logger.error("Cannot find any of the listed bugs") sys.exit(1) + err = False for bug in bugs: - bug = bug.value ubupackage = package = bug.source if options.package: ubupackage = options.package bug_num = bug.bug_num subject = bug.subject - log = debbugs.get_bug_log(bug_num) - summary = log[0][0] + log = debianbts.get_bug_log(bug_num) + summary = log[0]['message'].get_payload() target = ubuntu.getSourcePackage(name=ubupackage) if target is None: Logger.error("Source package '%s' is not in Ubuntu. Please specify " "the destination source package with --package", ubupackage) - sys.exit(1) + err = True + continue + + description = ('Imported from Debian bug http://bugs.debian.org/%d:\n\n%s' % + (bug_num, summary)) + # LP limits descriptions to 50K chars + description = (description[:49994] + ' [...]') if len(description) > 50000 else description + + Logger.debug('Target: %s' % target) + Logger.debug('Subject: %s' % subject) + Logger.debug('Description: ') + Logger.debug(description) + + if options.dry_run: + Logger.info('Dry-Run: not creating Ubuntu bug.') + continue - u_bug = launchpad.bugs.createBug( - target=target, title=subject, - description='Imported from Debian bug http://bugs.debian.org/%d:\n\n%s' % - (bug_num, summary)) + u_bug = launchpad.bugs.createBug(target=target, title=subject, + description=description) d_sp = debian.getSourcePackage(name=package) if d_sp is None and options.package: d_sp = debian.getSourcePackage(name=options.package) @@ -130,10 +133,13 @@ d_watch = u_bug.addWatch(remote_bug=bug_num, bug_tracker=lp_debbugs) d_task.bug_watch = d_watch d_task.lp_save() - Logger.normal("Opened %s", u_bug.web_link) + Logger.info("Opened %s", u_bug.web_link) if not options.browserless: webbrowser.open(u_bug.web_link) + if err: + sys.exit(1) + if __name__ == '__main__': main() diff -Nru ubuntu-dev-tools-0.164/merge-changelog ubuntu-dev-tools-0.187~bpo18.04.1/merge-changelog --- ubuntu-dev-tools-0.164/merge-changelog 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/merge-changelog 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # -*- coding: utf-8 -*- # Copyright © 2008 Canonical Ltd. # Author: Scott James Remnant . @@ -18,18 +18,22 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import re import sys +from debian.changelog import Changelog + +from ubuntutools import getLogger +Logger = getLogger() + def usage(exit_code=1): - print '''Usage: merge-changelog + Logger.info('''Usage: merge-changelog merge-changelog takes two changelogs that once shared a common source, merges them back together, and prints the merged result to stdout. This is useful if you need to manually merge a ubuntu package with a new Debian release of the package. -''' +''') sys.exit(exit_code) ######################################################################## @@ -37,233 +41,33 @@ ######################################################################## -# Regular expression for top of debian/changelog -CL_RE = re.compile(r'^(\w[-+0-9a-z.]*) \(([^\(\) \t]+)\)((\s+[-0-9a-z]+)+)\;', - re.IGNORECASE) - - def merge_changelog(left_changelog, right_changelog): """Merge a changelog file.""" - left_cl = read_changelog(left_changelog) - right_cl = read_changelog(right_changelog) - - for right_ver, right_text in right_cl: - while len(left_cl) and left_cl[0][0] > right_ver: - (left_ver, left_text) = left_cl.pop(0) - print left_text - - while len(left_cl) and left_cl[0][0] == right_ver: - (left_ver, left_text) = left_cl.pop(0) - - print right_text - - for _, left_text in left_cl: - print left_text - - return False - - -def read_changelog(filename): - """Return a parsed changelog file.""" - entries = [] - - changelog_file = open(filename) - try: - (ver, text) = (None, "") - for line in changelog_file: - match = CL_RE.search(line) - if match: - try: - ver = Version(match.group(2)) - except ValueError: - ver = None - - text += line - elif line.startswith(" -- "): - if ver is None: - ver = Version("0") - - text += line - entries.append((ver, text)) - (ver, text) = (None, "") - elif len(line.strip()) or ver is not None: - text += line - finally: - changelog_file.close() + with open(left_changelog) as f: + left_cl = Changelog(f) + with open(right_changelog) as f: + right_cl = Changelog(f) + + left_versions = set(left_cl.versions) + right_versions = set(right_cl.versions) + left_blocks = iter(left_cl) + right_blocks = iter(right_cl) + + clist = sorted(left_versions | right_versions, reverse=True) + ci = len(clist) + for version in clist: + ci -= 1 + if version in left_versions: + block = next(left_blocks) + if version in right_versions: + next(right_blocks) + else: + block = next(right_blocks) - if len(text): - entries.append((ver, text)) - - return entries - - -######################################################################## -# Version parsing code -######################################################################## -# Regular expressions make validating things easy -VALID_EPOCH = re.compile(r'^[0-9]+$') -VALID_UPSTREAM = re.compile(r'^[A-Za-z0-9+:.~-]*$') -VALID_REVISION = re.compile(r'^[A-Za-z0-9+.~]+$') - -# Character comparison table for upstream and revision components -CMP_TABLE = "~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-.:" - - -class Version(object): - """Debian version number. - - This class is designed to be reasonably transparent and allow you - to write code like: - - | s.version >= '1.100-1' - - The comparison will be done according to Debian rules, so '1.2' will - compare lower. - - Properties: - epoch Epoch - upstream Upstream version - revision Debian/local revision - """ - - def __init__(self, ver): - """Parse a string or number into the three components.""" - self.epoch = 0 - self.upstream = None - self.revision = None - - ver = str(ver) - if not len(ver): - raise ValueError - - # Epoch is component before first colon - idx = ver.find(":") - if idx != -1: - self.epoch = ver[:idx] - if not len(self.epoch): - raise ValueError - if not VALID_EPOCH.search(self.epoch): - raise ValueError - ver = ver[idx+1:] - - # Revision is component after last hyphen - idx = ver.rfind("-") - if idx != -1: - self.revision = ver[idx+1:] - if not len(self.revision): - raise ValueError - if not VALID_REVISION.search(self.revision): - raise ValueError - ver = ver[:idx] - - # Remaining component is upstream - self.upstream = ver - if not len(self.upstream): - raise ValueError - if not VALID_UPSTREAM.search(self.upstream): - raise ValueError - - self.epoch = int(self.epoch) - - def get_without_epoch(self): - """Return the version without the epoch.""" - string = self.upstream - if self.revision is not None: - string += "-%s" % (self.revision,) - return string - - without_epoch = property(get_without_epoch) - - def __str__(self): - """Return the class as a string for printing.""" - string = "" - if self.epoch > 0: - string += "%d:" % (self.epoch,) - string += self.upstream - if self.revision is not None: - string += "-%s" % (self.revision,) - return string - - def __repr__(self): - """Return a debugging representation of the object.""" - return "<%s epoch: %d, upstream: %r, revision: %r>" \ - % (self.__class__.__name__, self.epoch, - self.upstream, self.revision) - - def __cmp__(self, other): - """Compare two Version classes.""" - other = Version(other) - - result = cmp(self.epoch, other.epoch) - if result != 0: - return result - - result = deb_cmp(self.upstream, other.upstream) - if result != 0: - return result - - result = deb_cmp(self.revision or "", other.revision or "") - if result != 0: - return result - - return 0 - - -def strcut(string, idx, accept): - """Cut characters from string that are entirely in accept.""" - ret = "" - while idx < len(string) and string[idx] in accept: - ret += string[idx] - idx += 1 - - return (ret, idx) - - -def deb_order(string, idx): - """Return the comparison order of two characters.""" - if idx >= len(string): - return 0 - elif string[idx] == "~": - return -1 - else: - return CMP_TABLE.index(string[idx]) - - -def deb_cmp_str(x, y): - """Compare two strings in a deb version.""" - idx = 0 - while (idx < len(x)) or (idx < len(y)): - result = deb_order(x, idx) - deb_order(y, idx) - if result < 0: - return -1 - elif result > 0: - return 1 - - idx += 1 - - return 0 - - -def deb_cmp(x, y): - """Implement the string comparison outlined by Debian policy.""" - x_idx = y_idx = 0 - while x_idx < len(x) or y_idx < len(y): - # Compare strings - (x_str, x_idx) = strcut(x, x_idx, CMP_TABLE) - (y_str, y_idx) = strcut(y, y_idx, CMP_TABLE) - result = deb_cmp_str(x_str, y_str) - if result != 0: - return result - - # Compare numbers - (x_str, x_idx) = strcut(x, x_idx, "0123456789") - (y_str, y_idx) = strcut(y, y_idx, "0123456789") - result = cmp(int(x_str or "0"), int(y_str or "0")) - if result != 0: - return result + assert block.version == version - return 0 + Logger.info(str(block).strip() + ('\n' if ci else '')) def main(): diff -Nru ubuntu-dev-tools-0.164/mk-sbuild ubuntu-dev-tools-0.187~bpo18.04.1/mk-sbuild --- ubuntu-dev-tools-0.164/mk-sbuild 2018-04-24 11:24:38.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/mk-sbuild 2021-12-05 15:20:37.000000000 +0000 @@ -26,7 +26,7 @@ # ################################################################## # # This script creates chroots designed to be used in a snapshot mode -# (with LVM, btrfs, overlay, or aufs) with schroot and sbuild. +# (with LVM, btrfs, zfs, overlay, overlay or aufs) with schroot and sbuild. # Much love to "man sbuild-setup", https://wiki.ubuntu.com/PbuilderHowto, # and https://help.ubuntu.com/community/SbuildLVMHowto. # @@ -40,15 +40,18 @@ SOURCE_CHROOTS_TGZ="/var/lib/schroot/tarballs" CHROOT_SNAPSHOT_DIR="/var/lib/schroot/snapshots" SCHROOT_PROFILE="sbuild" +CCACHE_DIR="/var/cache/ccache-sbuild" +CCACHE_SIZE="4G" function usage() { - echo "Usage: $0 [OPTIONS] Release" >&2 + echo "Usage: $0 [OPTIONS] Release" echo "Options:" echo " --arch=ARCH What architecture to select" echo " --name=NAME Base name for the schroot (arch is appended)" echo " --personality=PERSONALITY What personality to use (defaults to match --arch)" echo " --vg=VG use LVM snapshots, with group VG" + echo " --zfs-dataset=DATASET use ZFS snapshots, with parent dataset DATASET" echo " --debug Turn on script debugging" echo " --skip-updates Do not include -updates pocket in sources.list" echo " --skip-security Do not include -security pocket in sources.list" @@ -62,14 +65,21 @@ echo " --debootstrap-keyring=KEYRING" echo " Use KEYRING to check signatures of retrieved Release files" echo " --debootstrap-no-check-gpg Disables checking gpg signatures of retrieved Release files" - echo " --eatmydata Install and use eatmydata" + echo " --skip-eatmydata Don't install and use eatmydata" + echo " --eatmydata Install and use eatmydata (default)" + echo " --ccache Install configure and use ccache as default" + echo " --ccache-dir=PATH Sets the CCACHE_DIR to PATH" + echo " (can be shared between all schroots, defaults to ${CCACHE_DIR})" + echo " --ccache-size=SIZE Sets the ccache max-size to SIZE" + echo " (shared by each CCACHE_DIR, defaults to ${CCACHE_SIZE})" echo " --distro=DISTRO Install specific distro:" echo " 'ubuntu' or 'debian' " echo " (defaults to determining from release name)" echo " --target=ARCH Target architecture for cross-building" echo " --type=SCHROOT_TYPE Define the schroot type:" - echo " 'directory'(default), 'file', or 'btrfs-snapshot'" + echo " 'directory' (default), 'file', or 'btrfs-snapshot'." echo " 'lvm-snapshot' is selected via --vg" + echo " 'zfs-snapshot' is selected via --zfs-dataset" echo "" echo "Configuration (via ~/.mk-sbuild.rc)" echo " LV_SIZE Size of source LVs (default ${LV_SIZE})" @@ -89,7 +99,12 @@ echo " DEBOOTSTRAP_PROXY Apt proxy (same as --debootstrap-proxy)" echo " DEBOOTSTRAP_KEYRING GPG keyring (same as --debootstrap-keyring)" echo " DEBOOTSTRAP_NO_CHECK_GPG Disable GPG verification (same as --debootstrap-no-check-gpg)" - echo " EATMYDATA Enable --eatmydata" + echo " EATMYDATA Enable or disable eatmydata usage, see --eatmydata and --skip-eatmydata" + echo " CCACHE Enable --ccache" + echo " CCACHE_DIR Path for ccache (can be shared between all schroots, " + echo " same as --ccache-dir, default ${CCACHE_DIR})" + echo " CCACHE_SIZE Sets the ccache max-size (shared by each CCACHE_DIR, " + echo " same as --ccache-size, default ${CCACHE_SIZE})" echo " TEMPLATE_SOURCES A template for sources.list" echo " TEMPLATE_SCHROOTCONF A template for schroot.conf stanza" if [ -z "$1" ]; then @@ -102,28 +117,61 @@ if [ -z "$1" ]; then usage fi -OPTS=`getopt -o 'h' --long "help,debug,skip-updates,skip-security,skip-proposed,eatmydata,arch:,name:,source-template:,debootstrap-mirror:,debootstrap-include:,debootstrap-exclude:,debootstrap-opts:,debootstrap-proxy:,debootstrap-no-check-gpg,debootstrap-keyring:,personality:,distro:,vg:,type:,target:" -- "$@"` +supported_options=( + help + debug + skip-updates + skip-security + skip-proposed + skip-eatmydata + ccache + arch: + name: + source-template: + debootstrap-mirror: + debootstrap-include: + debootstrap-exclude: + debootstrap-opts: + debootstrap-proxy: + debootstrap-no-check-gpg + debootstrap-keyring: + personality: + distro: + vg: + zfs-dataset: + type: + target: + ccache-dir: + ccache-size: +) +OPTS=$(getopt -o 'h' --long "$(IFS=, && echo "${supported_options[*]}")" -- "$@") eval set -- "$OPTS" VG="" DISTRO="" +COMMAND_PREFIX="" name="" proxy="_unset_" DEBOOTSTRAP_NO_CHECK_GPG=0 -EATMYDATA=0 +EATMYDATA=1 +CCACHE=0 while :; do case "$1" in --debug) + DEBUG=1 set -x shift ;; --arch) CHROOT_ARCH="$2" - if [ "$2" = "i386" ] || [ "$2" = "lpia" ] && [ -z "$personality" ]; - then - personality="linux32" - fi + case $2 in + armel|armhf|i386|lpia) + if [ -z "$personality" ]; then + personality="linux32" + fi + ;; + esac shift 2 ;; --personality) @@ -183,8 +231,12 @@ DEBOOTSTRAP_NO_CHECK_GPG=1 shift ;; - --eatmydata) - EATMYDATA=1 + --skip-eatmydata) + EATMYDATA=0 + shift + ;; + --ccache) + CCACHE=1 shift ;; --distro) @@ -195,6 +247,10 @@ VG="$2" shift 2 ;; + --zfs-dataset) + ZFS_PARENT_DATASET="$2" + shift 2 + ;; --type) SCHROOT_TYPE="$2" shift 2 @@ -203,6 +259,14 @@ TARGET_ARCH="$2" shift 2 ;; + --ccache-dir) + CCACHE_DIR="$2" + shift 2 + ;; + --ccache-size) + CCACHE_SIZE="$2" + shift 2 + ;; --) shift break @@ -399,10 +463,58 @@ esac fi +if [ $CCACHE -eq 1 ]; then + if [ -z "$CCACHE_DIR" ] || [[ "$(dirname "$CCACHE_DIR")" == '/' ]]; then + echo "Invalid ccache dir: ${CCACHE_DIR}" >&2 + exit 1 + fi + + # We can safely use a global cache path, in such case changing size applies + # to all the schroots + setup_script="$CCACHE_DIR"/mk-sbuild-setup + if [ -d "$CCACHE_DIR" ]; then + echo "Reusing $CCACHE_DIR as CCACHE_DIR, will be configured to use max-size=${CCACHE_SIZE}" + rm -f "$setup_script" + else + echo "Configuring $CCACHE_DIR as CCACHE_DIR with max-size=${CCACHE_SIZE}" + sudo install --group=sbuild --mode=2775 -d "$CCACHE_DIR" + fi + + if [ ! -x "$setup_script" ]; then + cat </dev/null +#!/bin/sh +export CCACHE_DIR="$CCACHE_DIR" +export CCACHE_MAXSIZE="${CCACHE_SIZE}" +export CCACHE_UMASK=002 +export CCACHE_COMPRESS=1 +unset CCACHE_HARDLINK +export CCACHE_NOHARDLINK=1 +export PATH="/usr/lib/ccache:\$PATH" +exec "\$@" +END + sudo chmod a+rx "$setup_script" + fi + + if ! sudo grep -qs "$CCACHE_DIR" /etc/schroot/sbuild/fstab; then + # This acts on host configuration, but there is no other way to handle + # this, however it won't affect anything + cat </dev/null +${CCACHE_DIR} ${CCACHE_DIR} none rw,bind 0 0 +END + fi + + DEBOOTSTRAP_INCLUDE="${DEBOOTSTRAP_INCLUDE:+$DEBOOTSTRAP_INCLUDE,}ccache" + BUILD_PKGS="$BUILD_PKGS ccache" + COMMAND_PREFIX="${COMMAND_PREFIX:+$COMMAND_PREFIX,}$setup_script" +fi + if [ -z "$SCHROOT_TYPE" ]; then # To build the LV, we need to know which volume group to use if [ -n "$VG" ]; then SCHROOT_TYPE="lvm-snapshot" + # To build the ZFS dataset, we need to know which parent to use + elif [ -n "$ZFS_PARENT_DATASET" ]; then + SCHROOT_TYPE="zfs-snapshot" else SCHROOT_TYPE="directory" fi @@ -449,7 +561,7 @@ # Set up some variables for use in the paths and names CHROOT_PATH="${SOURCE_CHROOTS_TGZ}/${CHROOT_NAME}.tgz" ;; -"btrfs-snapshot") +"btrfs-snapshot" | "zfs-snapshot") if [ ! -d "${SOURCE_CHROOTS_DIR}" ]; then sudo mkdir -p "${SOURCE_CHROOTS_DIR}" fi @@ -525,6 +637,7 @@ # Disable recommends for a smaller chroot (gutsy and later only) if ubuntu_dist_ge "$RELEASE" "gutsy"; then BUILD_PKGS="--no-install-recommends $BUILD_PKGS" + SKIP_RECOMMENDS=1 fi # Add pkg-create-dbgsym (edgy through zesty) if ! ubuntu_dist_ge "$RELEASE" "artful"; then @@ -561,6 +674,7 @@ fi # Keep the chroot as minimal as possible BUILD_PKGS="--no-install-recommends $BUILD_PKGS" + SKIP_RECOMMENDS=1 ;; *) echo "Unknown --distro '$DISTRO': aborting" >&2 @@ -653,6 +767,19 @@ fi sudo btrfs subvolume create "${MNT}" ;; + +"zfs-snapshot") + ZFS_DATASET="${ZFS_PARENT_DATASET}/${CHROOT_NAME}" + if sudo zfs list "${ZFS_DATASET}" >/dev/null 2>&1; then + echo "E: ZFS dataset ${ZFS_DATASET} already exists; aborting" >&2 + exit 1 + fi + sudo zfs create -p -o mountpoint=legacy "${ZFS_DATASET}" + + # Mount + MNT=`mktemp -d -t schroot-XXXXXX` + sudo mount -t zfs "${ZFS_DATASET}" "${MNT}" + ;; "file") MNT=`mktemp -d -t schroot-XXXXXX` esac @@ -676,6 +803,13 @@ # debootstrap the chroot sudo ${proxy:+"http_proxy=${proxy}"} "$DEBOOTSTRAP_COMMAND" --arch="$CHROOT_ARCH" $variant_opt $debootstrap_opts "$RELEASE" "$MNT" "${DEBOOTSTRAP_MIRROR:-http://archive.ubuntu.com/ubuntu}" +if [ $EATMYDATA -eq 1 ]; then + sudo mkdir -p "${MNT}/usr/local/libexec/mk-sbuild" + sudo ln -s /usr/bin/eatmydata "${MNT}/usr/local/libexec/mk-sbuild/dpkg" + echo 'Dir::Bin::dpkg "/usr/local/libexec/mk-sbuild/dpkg";' \ + | sudo tee "${MNT}/etc/apt/apt.conf.d/00mk-sbuild-eatmydata" > /dev/null +fi + # Update the package sources TEMP_SOURCES=`mktemp -t sources-XXXXXX` if [ -z "$TEMPLATE_SOURCES" ]; then @@ -773,9 +907,9 @@ type=SCHROOT_TYPE profile=$SCHROOT_PROFILE EOM - if [ $EATMYDATA -eq 1 ]; then + if [ -n "$COMMAND_PREFIX" ]; then cat >> "$TEMP_SCHROOTCONF" <> "${TEMP_SCHROOTCONF}" < /dev/null rm -f "$TEMP_SCHROOTCONF" @@ -835,7 +976,9 @@ # Create image finalization script sudo bash -c "cat >> $MNT/finish.sh" <> $MNT/finish.sh" < /etc/apt/apt.conf.d/99mk-sbuild-no-recommends <> $MNT/finish.sh" <, @@ -30,17 +30,22 @@ # that the target distribution is always meant to be Ubuntu Hardy. import os +import os.path import sys +import subprocess +import shutil import debian.deb822 +from contextlib import suppress from distro_info import DebianDistroInfo, UbuntuDistroInfo, DistroDataOutdated import ubuntutools.misc import ubuntutools.version from ubuntutools.config import UDTConfig -from ubuntutools.logger import Logger from ubuntutools.question import YesNoQuestion -from ubuntutools import subprocess + +from ubuntutools import getLogger +Logger = getLogger() class PbuilderDist(object): @@ -103,9 +108,10 @@ '~/pbuilder/')) if 'SUDO_USER' in os.environ: - Logger.warn('Running under sudo. ' - 'This is probably not what you want. ' - 'pbuilder-dist will use sudo itself, when necessary.') + Logger.warning('Running under sudo. ' + 'This is probably not what you want. ' + 'pbuilder-dist will use sudo itself, ' + 'when necessary.') if os.stat(os.environ['HOME']).st_uid != os.getuid(): Logger.error("You don't own $HOME") sys.exit(1) @@ -249,13 +255,6 @@ 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, - ] - config = UDTConfig() if self.target_distro in self._debian_distros: mirror = os.environ.get('MIRRORSITE', @@ -276,13 +275,18 @@ arguments += ['--mirror', mirror] othermirrors = [] + localrepo = '/var/cache/archive/' + self.target_distro + if os.path.exists(localrepo): + repo = 'deb file:///var/cache/archive/ %s/' % self.target_distro + othermirrors.append(repo) + if self.target_distro in self._debian_distros: debian_info = DebianDistroInfo() try: codename = debian_info.codename(self.target_distro, default=self.target_distro) - except DistroDataOutdated, error: - Logger.warn(error) + except DistroDataOutdated as error: + Logger.warning(error) if codename in (debian_info.devel(), 'experimental'): self.enable_security = False self.enable_updates = False @@ -291,9 +295,14 @@ self.enable_updates = False if self.enable_security: - othermirrors.append('deb %s %s/updates %s' + pocket = '-security' + with suppress(ValueError): + # before bullseye (version 11) security suite is /updates + if float(debian_info.version(codename)) < 11.0: + pocket = '/updates' + othermirrors.append('deb %s %s%s %s' % (config.get_value('DEBSEC_MIRROR'), - self.target_distro, components)) + self.target_distro, pocket, components)) if self.enable_updates: othermirrors.append('deb %s %s-updates %s' % (mirror, self.target_distro, components)) @@ -308,8 +317,8 @@ else: try: dev_release = self.target_distro == UbuntuDistroInfo().devel() - except DistroDataOutdated, error: - Logger.warn(error) + except DistroDataOutdated as error: + Logger.warning(error) dev_release = True if dev_release: @@ -398,7 +407,7 @@ Print a help message for pbuilder-dist, and exit with the given code. """ - print 'See man pbuilder-dist for more information.' + Logger.info('See man pbuilder-dist for more information.') sys.exit(exit_code) @@ -439,11 +448,26 @@ if len(parts) > 2: requested_arch = parts[2] - elif len(args) > 0 and args[0] in ( - 'alpha', 'amd64', 'arm', 'armeb', 'armel', 'armhf', 'arm64', - 'i386', 'lpia', 'm68k', 'mips', 'mipsel', 'powerpc', 'ppc64', - 'ppc64el', 's390x', 'sh4', 'sh4eb', 'sparc', 'sparc64'): - requested_arch = args.pop(0) + elif len(args) > 0: + if shutil.which('arch-test') is not None: + if subprocess.run( + ['arch-test', args[0]], + stdout=subprocess.DEVNULL).returncode == 0: + requested_arch = args.pop(0) + elif (os.path.isdir('/usr/lib/arch-test') + and args[0] in os.listdir('/usr/lib/arch-test/')): + Logger.error('Architecture "%s" is not supported on your ' + 'currently running kernal. Consider installing ' + 'the qemu-user-static package to enable the use of ' + 'foreign architectures.', args[0]) + sys.exit(1) + else: + requested_arch = None + else: + Logger.error('Cannot determine if "%s" is a valid architecture. ' + 'Please install the arch-test package and retry.', + args[0]) + sys.exit(1) else: requested_arch = None @@ -500,7 +524,7 @@ if '--debug-echo' not in args: sys.exit(subprocess.call(app.get_command(args))) else: - print app.get_command([arg for arg in args if arg != '--debug-echo']) + Logger.info(app.get_command([arg for arg in args if arg != '--debug-echo'])) if __name__ == '__main__': diff -Nru ubuntu-dev-tools-0.164/pull-debian-ddebs ubuntu-dev-tools-0.187~bpo18.04.1/pull-debian-ddebs --- ubuntu-dev-tools-0.164/pull-debian-ddebs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-debian-ddebs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/python3 +# +# pull-debian-ddebs -- pull ddeb package files for debian +# Basic usage: pull-debian-ddebs [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='debian', pull='ddebs') diff -Nru ubuntu-dev-tools-0.164/pull-debian-debdiff ubuntu-dev-tools-0.187~bpo18.04.1/pull-debian-debdiff --- ubuntu-dev-tools-0.164/pull-debian-debdiff 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-debian-debdiff 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # pull-debian-debdiff - find and download a specific version of a Debian # package and its immediate parent to generate a debdiff. # @@ -20,17 +20,19 @@ import optparse import sys -import debian.debian_support import debian.changelog from ubuntutools.archive import DebianSourcePackage, DownloadError from ubuntutools.config import UDTConfig -from ubuntutools.logger import Logger +from ubuntutools.version import Version + +from ubuntutools import getLogger +Logger = getLogger() def previous_version(package, version, distance): "Given an (extracted) package, determine the version distance versions ago" - upver = debian.debian_support.Version(version).upstream_version + upver = Version(version).upstream_version filename = '%s-%s/debian/changelog' % (package, upver) changelog_file = open(filename, 'r') changelog = debian.changelog.Changelog(changelog_file.read()) @@ -79,12 +81,12 @@ opts.debsec_mirror = config.get_value('DEBSEC_MIRROR') mirrors = [opts.debsec_mirror, opts.debian_mirror] - Logger.normal('Downloading %s %s', package, version) + Logger.info('Downloading %s %s', package, version) newpkg = DebianSourcePackage(package, version, mirrors=mirrors) try: newpkg.pull() - except DownloadError, e: + except DownloadError as e: Logger.error('Failed to download: %s', str(e)) sys.exit(1) newpkg.unpack() @@ -96,20 +98,19 @@ if not oldversion: Logger.error('No previous version could be found') sys.exit(1) - Logger.normal('Downloading %s %s', package, oldversion) + Logger.info('Downloading %s %s', package, oldversion) oldpkg = DebianSourcePackage(package, oldversion, mirrors=mirrors) try: oldpkg.pull() - except DownloadError, e: + except DownloadError as e: Logger.error('Failed to download: %s', str(e)) sys.exit(1) - oldpkg.unpack() - print 'file://' + oldpkg.debdiff(newpkg, diffstat=True) + Logger.info('file://' + oldpkg.debdiff(newpkg, diffstat=True)) if __name__ == '__main__': try: main() except KeyboardInterrupt: - Logger.normal('User abort.') + Logger.info('User abort.') diff -Nru ubuntu-dev-tools-0.164/pull-debian-debs ubuntu-dev-tools-0.187~bpo18.04.1/pull-debian-debs --- ubuntu-dev-tools-0.164/pull-debian-debs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-debian-debs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/python3 +# +# pull-debian-debs -- pull deb package files for debian +# Basic usage: pull-debian-debs [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='debian', pull='debs') diff -Nru ubuntu-dev-tools-0.164/pull-debian-source ubuntu-dev-tools-0.187~bpo18.04.1/pull-debian-source --- ubuntu-dev-tools-0.164/pull-debian-source 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-debian-source 2019-12-01 18:18:32.000000000 +0000 @@ -1,143 +1,11 @@ -#!/usr/bin/python +#!/usr/bin/python3 # -# pull-debian-source -- pull a source package from Launchpad -# Copyright (C) 2011, Stefano Rivera -# Inspired by a tool of the same name by Nathan Handler. +# pull-debian-source -- pull source package files for debian +# Basic usage: pull-debian-source [version|release] # -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -import json -import optparse -import sys -import urllib2 - -from distro_info import DebianDistroInfo, DistroDataOutdated - -from ubuntutools.archive import DebianSourcePackage, DownloadError, rmadison -from ubuntutools.config import UDTConfig -from ubuntutools.logger import Logger - - -def is_suite(version): - """If version could be considered to be a Debian suite, return the - canonical suite name. Otherwise None - """ - debian_info = DebianDistroInfo() - debian_releases = debian_info.all + ['experimental'] - - if '-' in version: - release, pocket = version.split('-', 1) - release = debian_info.codename(release, default=release) - if release in debian_releases: - if pocket in ('proposed-updates', 'p-u'): - return (release + '-proposed-updates') - elif pocket == 'security': - return (release + '-security') - else: - release = debian_info.codename(version, default=version) - if release in debian_releases: - return release - return None - - -def source_package_for(binary, release): - """Query DDE to find the source package for a particular binary""" - try: - release = DebianDistroInfo().codename(release, default=release) - except DistroDataOutdated, e: - Logger.warn(e) - url = ('http://dde.debian.net/dde/q/udd/dist/d:debian/r:%s/p:%s/?t=json' - % (release, binary)) - data = None - try: - data = json.load(urllib2.urlopen(url))['r'] - except urllib2.URLError, e: - Logger.error('Unable to retrieve package information from DDE: ' - '%s (%s)', url, str(e)) - except ValueError, e: - Logger.error('Unable to parse JSON response from DDE: ' - '%s (%s)', url, str(e)) - if not data: - return None - return data[0]['source'] - - -def main(): - usage = 'Usage: %prog [release|version]' - parser = optparse.OptionParser(usage) - parser.add_option('-d', '--download-only', - dest='download_only', default=False, action='store_true', - help='Do not extract the source package') - parser.add_option('-m', '--mirror', metavar='DEBIAN_MIRROR', - dest='debian_mirror', - help='Preferred Debian mirror (default: %s)' - % UDTConfig.defaults['DEBIAN_MIRROR']) - parser.add_option('-s', '--security-mirror', metavar='DEBSEC_MIRROR', - dest='debsec_mirror', - help='Preferred Debian Security mirror (default: %s)' - % UDTConfig.defaults['DEBSEC_MIRROR']) - parser.add_option('--no-conf', - dest='no_conf', default=False, action='store_true', - help="Don't read config files or environment variables") - (options, args) = parser.parse_args() - if not args: - parser.error('Must specify package name') - elif len(args) > 2: - parser.error('Too many arguments. ' - 'Must only specify package and (optionally) release.') - - config = UDTConfig(options.no_conf) - if options.debian_mirror is None: - options.debian_mirror = config.get_value('DEBIAN_MIRROR') - if options.debsec_mirror is None: - options.debsec_mirror = config.get_value('DEBSEC_MIRROR') - - package = args[0].lower() - - version = args[1] if len(args) > 1 else 'unstable' - component = None - - suite = is_suite(version) - if suite is not None: - line = list(rmadison('debian', package, suite, 'source')) - if not line: - source_package = source_package_for(package, suite) - if source_package is not None and package != source_package: - package = source_package - line = list(rmadison('debian', package, suite, 'source')) - if not line: - Logger.error('Unable to find %s in Debian suite "%s".', package, - suite) - sys.exit(1) - line = line[-1] - version = line['version'] - component = line['component'] - - Logger.normal('Downloading %s version %s', package, version) - srcpkg = DebianSourcePackage(package, version, component=component, - mirrors=[options.debian_mirror, - options.debsec_mirror]) - try: - srcpkg.pull() - except DownloadError, e: - Logger.error('Failed to download: %s', str(e)) - sys.exit(1) - if not options.download_only: - srcpkg.unpack() +# See pull-pkg +from ubuntutools.pullpkg import PullPkg if __name__ == '__main__': - try: - main() - except KeyboardInterrupt: - Logger.normal('User abort.') + PullPkg.main(distro='debian', pull='source') diff -Nru ubuntu-dev-tools-0.164/pull-debian-udebs ubuntu-dev-tools-0.187~bpo18.04.1/pull-debian-udebs --- ubuntu-dev-tools-0.164/pull-debian-udebs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-debian-udebs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/python3 +# +# pull-debian-udebs -- pull udeb package files for debian +# Basic usage: pull-debian-udebs [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='debian', pull='udebs') diff -Nru ubuntu-dev-tools-0.164/pull-lp-ddebs ubuntu-dev-tools-0.187~bpo18.04.1/pull-lp-ddebs --- ubuntu-dev-tools-0.164/pull-lp-ddebs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-lp-ddebs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/python3 +# +# pull-lp-ddebs -- pull ddeb package files for ubuntu +# Basic usage: pull-lp-ddebs [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='ubuntu', pull='ddebs') diff -Nru ubuntu-dev-tools-0.164/pull-lp-debs ubuntu-dev-tools-0.187~bpo18.04.1/pull-lp-debs --- ubuntu-dev-tools-0.164/pull-lp-debs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-lp-debs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/python3 +# +# pull-lp-debs -- pull deb package files for ubuntu +# Basic usage: pull-lp-debs [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='ubuntu', pull='debs') diff -Nru ubuntu-dev-tools-0.164/pull-lp-source ubuntu-dev-tools-0.187~bpo18.04.1/pull-lp-source --- ubuntu-dev-tools-0.164/pull-lp-source 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-lp-source 2019-12-01 18:18:32.000000000 +0000 @@ -1,149 +1,11 @@ -#!/usr/bin/python +#!/usr/bin/python3 # -# pull-lp-source -- pull a source package from Launchpad -# Basic usage: pull-lp-source [] +# pull-lp-source -- pull source package files for ubuntu +# Basic usage: pull-lp-source [version|release] # -# Copyright (C) 2008, Iain Lane , -# 2010-2011, Stefano Rivera -# -# ################################################################## -# -# 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 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. -# -# See file /usr/share/common-licenses/GPL for more details. -# -# ################################################################## - - -import json -import os -import sys -import urllib2 -from optparse import OptionParser - -from distro_info import UbuntuDistroInfo, DistroDataOutdated - -from ubuntutools.archive import UbuntuSourcePackage, DownloadError -from ubuntutools.config import UDTConfig -from ubuntutools.lp.lpapicache import Distribution, Launchpad -from ubuntutools.lp.udtexceptions import (SeriesNotFoundException, - PackageNotFoundException, - PocketDoesNotExistError) -from ubuntutools.logger import Logger -from ubuntutools.misc import split_release_pocket - - -def source_package_for(binary, release): - """Query DDE to find the source package for a particular binary - Should really do this with LP, but it's not possible LP: #597041 - """ - url = ('http://dde.debian.net/dde/q/udd/dist/d:ubuntu/r:%s/p:%s/?t=json' - % (release, binary)) - data = None - try: - data = json.load(urllib2.urlopen(url))['r'] - except urllib2.URLError, e: - Logger.error('Unable to retrieve package information from DDE: ' - '%s (%s)', url, str(e)) - except ValueError, e: - Logger.error('Unable to parse JSON response from DDE: ' - '%s (%s)', url, str(e)) - if not data: - return None - return data[0]['source'] - - -def main(): - usage = "Usage: %prog [release|version]" - opt_parser = OptionParser(usage) - opt_parser.add_option('-d', '--download-only', - dest='download_only', default=False, - action='store_true', - help="Do not extract the source package") - opt_parser.add_option('-m', '--mirror', metavar='UBUNTU_MIRROR', - dest='ubuntu_mirror', - help='Preferred Ubuntu mirror (default: Launchpad)') - opt_parser.add_option('--no-conf', - dest='no_conf', default=False, action='store_true', - help="Don't read config files or environment " - "variables") - (options, args) = opt_parser.parse_args() - if not args: - opt_parser.error("Must specify package name") - - config = UDTConfig(options.no_conf) - if options.ubuntu_mirror is None: - options.ubuntu_mirror = config.get_value('UBUNTU_MIRROR') - - # Login anonymously to LP - Launchpad.login_anonymously() - - package = str(args[0]).lower() - - ubuntu_info = UbuntuDistroInfo() - if len(args) > 1: # Custom distribution specified. - version = str(args[1]) - else: - try: - version = os.getenv('DIST') or ubuntu_info.devel() - except DistroDataOutdated, e: - Logger.warn("%s\nOr specify a distribution.", e) - sys.exit(1) - component = None - - # Release, not package version number: - release = None - pocket = None - try: - (release, pocket) = split_release_pocket(version, default=None) - except PocketDoesNotExistError, e: - pass - if release in ubuntu_info.all: - archive = Distribution('ubuntu').getArchive() - try: - spph = archive.getSourcePackage(package, release, pocket) - except SeriesNotFoundException, e: - Logger.error(str(e)) - sys.exit(1) - except PackageNotFoundException, e: - source_package = source_package_for(package, release) - if source_package is not None and source_package != package: - try: - spph = archive.getSourcePackage(source_package, release, - pocket) - package = source_package - except PackageNotFoundException: - Logger.error(str(e)) - sys.exit(1) - else: - Logger.error(str(e)) - sys.exit(1) - - version = spph.getVersion() - component = spph.getComponent() - - Logger.normal('Downloading %s version %s', package, version) - srcpkg = UbuntuSourcePackage(package, version, component=component, - mirrors=[options.ubuntu_mirror]) - try: - srcpkg.pull() - except DownloadError, e: - Logger.error('Failed to download: %s', str(e)) - sys.exit(1) - if not options.download_only: - srcpkg.unpack() +# See pull-pkg +from ubuntutools.pullpkg import PullPkg if __name__ == '__main__': - try: - main() - except KeyboardInterrupt: - Logger.normal('User abort.') + PullPkg.main(distro='ubuntu', pull='source') diff -Nru ubuntu-dev-tools-0.164/pull-lp-udebs ubuntu-dev-tools-0.187~bpo18.04.1/pull-lp-udebs --- ubuntu-dev-tools-0.164/pull-lp-udebs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-lp-udebs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/python3 +# +# pull-lp-udebs -- pull udeb package files for ubuntu +# Basic usage: pull-lp-udebs [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='ubuntu', pull='udebs') diff -Nru ubuntu-dev-tools-0.164/pull-pkg ubuntu-dev-tools-0.187~bpo18.04.1/pull-pkg --- ubuntu-dev-tools-0.164/pull-pkg 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-pkg 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,29 @@ +#!/usr/bin/python3 +# +# pull-pkg -- pull package files for debian/ubuntu/uca/ppa +# Basic usage: pull-pkg -D distro -p type [version|release] +# +# Copyright (C) 2008, Iain Lane , +# 2010-2011, Stefano Rivera +# 2017-2018, Dan Streetman +# +# ################################################################## +# +# 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 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. +# +# See file /usr/share/common-licenses/GPL for more details. +# +# ################################################################## + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main() diff -Nru ubuntu-dev-tools-0.164/pull-ppa-ddebs ubuntu-dev-tools-0.187~bpo18.04.1/pull-ppa-ddebs --- ubuntu-dev-tools-0.164/pull-ppa-ddebs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-ppa-ddebs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,12 @@ +#!/usr/bin/python3 +# +# pull-ppa-ddebs -- pull ddeb package files for a Launchpad Personal Package Archive +# Basic usage: pull-ppa-ddebs [version|release] +# pull-ppa-ddebs --ppa USER/NAME [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='ppa', pull='ddebs') diff -Nru ubuntu-dev-tools-0.164/pull-ppa-debs ubuntu-dev-tools-0.187~bpo18.04.1/pull-ppa-debs --- ubuntu-dev-tools-0.164/pull-ppa-debs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-ppa-debs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,12 @@ +#!/usr/bin/python3 +# +# pull-ppa-debs -- pull deb package files for a Launchpad Personal Package Archive +# Basic usage: pull-ppa-debs [version|release] +# pull-ppa-debs --ppa USER/NAME [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='ppa', pull='debs') diff -Nru ubuntu-dev-tools-0.164/pull-ppa-source ubuntu-dev-tools-0.187~bpo18.04.1/pull-ppa-source --- ubuntu-dev-tools-0.164/pull-ppa-source 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-ppa-source 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,12 @@ +#!/usr/bin/python3 +# +# pull-ppa-source -- pull source package files for a Launchpad Personal Package Archive +# Basic usage: pull-ppa-source [version|release] +# pull-ppa-source --ppa USER/NAME [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='ppa', pull='source') diff -Nru ubuntu-dev-tools-0.164/pull-ppa-udebs ubuntu-dev-tools-0.187~bpo18.04.1/pull-ppa-udebs --- ubuntu-dev-tools-0.164/pull-ppa-udebs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-ppa-udebs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,12 @@ +#!/usr/bin/python3 +# +# pull-ppa-udebs -- pull udeb package files for a Launchpad Personal Package Archive +# Basic usage: pull-ppa-udebs [version|release] +# pull-ppa-udebs --ppa USER/NAME [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='ppa', pull='udebs') diff -Nru ubuntu-dev-tools-0.164/pull-revu-source ubuntu-dev-tools-0.187~bpo18.04.1/pull-revu-source --- ubuntu-dev-tools-0.164/pull-revu-source 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-revu-source 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -#!/usr/bin/perl -# Script Name: pull-revu-source -# Author: Nathan Handler -# Usage: pull-revu-source -# Copyright (C) 2009 Nathan Handler -# Based on revupull in kubuntu-dev-tools, -# written by Harald Sitter -# License: GNU General Public License -# 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 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. -# On Debian GNU/Linux systems, the complete text of the GNU General -# Public License can be found in the /usr/share/common-licenses/GPL-3 file. - -use warnings; -use strict; -use File::Basename; -use Getopt::Long; - -my $REVU = "revu.ubuntuwire.com"; - -my($package) = lc($ARGV[0]) || usage(2); -my($help)=0; -GetOptions('help' => \$help); -usage(0) if($help); - -eval { require LWP::Simple; }; -if ($@=~ m#^Can\'t locate LWP/Simple#) { - print(STDERR "Please install libwww-perl.\n"); - exit(1); -} -use LWP::Simple; - -dget(getURL()); - -sub getURL { - my($url) = "http://" . $REVU . "/dsc.py?url&package=" . $package; - my($page)=get($url); - die("Could Not Get $url") unless (defined $page); - return $page; -} - -sub dget { - my($dsc) = @_; - exec("dget -xu $dsc"); -} - -sub usage { - my($exit) = @_; - my($name)=basename($0); - print("USAGE: $name [-h] \n"); - exit($exit); -} diff -Nru ubuntu-dev-tools-0.164/pull-uca-ddebs ubuntu-dev-tools-0.187~bpo18.04.1/pull-uca-ddebs --- ubuntu-dev-tools-0.164/pull-uca-ddebs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-uca-ddebs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/python3 +# +# pull-uca-ddebs -- pull ddeb package files for ubuntu cloud archive +# Basic usage: pull-uca-ddebs [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='uca', pull='ddebs') diff -Nru ubuntu-dev-tools-0.164/pull-uca-debs ubuntu-dev-tools-0.187~bpo18.04.1/pull-uca-debs --- ubuntu-dev-tools-0.164/pull-uca-debs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-uca-debs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/python3 +# +# pull-uca-debs -- pull deb package files for ubuntu cloud archive +# Basic usage: pull-uca-debs [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='uca', pull='debs') diff -Nru ubuntu-dev-tools-0.164/pull-uca-source ubuntu-dev-tools-0.187~bpo18.04.1/pull-uca-source --- ubuntu-dev-tools-0.164/pull-uca-source 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-uca-source 2019-12-01 18:18:32.000000000 +0000 @@ -1,157 +1,11 @@ -#!/usr/bin/python +#!/usr/bin/python3 # -# pull-uca-source -- pull a source package from Ubuntu Cloud Archive -# Basic usage: pull-uca-source [version] +# pull-uca-source -- pull source package files for ubuntu cloud archive +# Basic usage: pull-uca-source [version|release] # -# Copyright (C) 2008, Iain Lane , -# 2010-2011, Stefano Rivera -# 2016, Corey Bryant -# 2016, Dan Streetman -# -# ################################################################## -# -# 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 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. -# -# See file /usr/share/common-licenses/GPL for more details. -# -# ################################################################## - - -import re -import sys -from optparse import OptionParser - -from ubuntutools.archive import UbuntuCloudArchiveSourcePackage, DownloadError -from ubuntutools.config import UDTConfig -from ubuntutools.lp.lpapicache import Launchpad -from ubuntutools.lp.udtexceptions import PocketDoesNotExistError -from ubuntutools.logger import Logger -from ubuntutools.misc import split_release_pocket - -from lazr.restfulclient.errors import NotFound - -from launchpadlib.launchpad import Launchpad as LP - - -def showOpenstackReleases(uca): - releases = [] - for p in uca.ppas: - if re.match(r"\w*-staging", p.name): - releases.append(re.sub("-staging", "", p.name)) - Logger.error("Openstack releases are:\n\t%s", ", ".join(releases)) - - -def getSPPH(lp, archive, package, version=None, series=None, pocket=None, try_binary=True): - params = {'exact_match': True, 'order_by_date': True} - if pocket: - params['pocket'] = pocket - if series: - params['distro_series'] = series() - elif version: - params['version'] = version - Logger.normal("checking %s version %s pocket %s", package, version, pocket) - spphs = archive.getPublishedSources(source_name=package, **params) - if spphs: - return spphs[0] - if not try_binary: - return None - - # Didn't find any, maybe the package is a binary package name - if series: - del params['distro_series'] - archs = lp.load(series().architectures_collection_link).entries - params['distro_arch_series'] = archs[0]['self_link'] - bpphs = archive.getPublishedBinaries(binary_name=package, **params) - if bpphs: - bpph_build = lp.load(bpphs[0].build_link) - source_package = bpph_build.source_package_name - return getSPPH(lp, archive, source_package, version, series, pocket, - try_binary=False) - - return None - - -def main(): - usage = "Usage: %prog [version]" - opt_parser = OptionParser(usage) - opt_parser.add_option('-d', '--download-only', - dest='download_only', default=False, - action='store_true', - help="Do not extract the source package") - opt_parser.add_option('-m', '--mirror', metavar='OPENSTACK_MIRROR', - dest='openstack_mirror', - help='Preferred Openstack mirror (default: Launchpad)') - opt_parser.add_option('--no-conf', - dest='no_conf', default=False, action='store_true', - help="Don't read config files or environment " - "variables") - (options, args) = opt_parser.parse_args() - if len(args) < 2: - opt_parser.error("Must specify package name and openstack release") - - config = UDTConfig(options.no_conf) - if options.openstack_mirror is None: - options.openstack_mirror = config.get_value('OPENSTACK_MIRROR') - mirrors = [] - if options.openstack_mirror: - mirrors.append(options.openstack_mirror) - - # Login anonymously to LP - Launchpad.login_anonymously() - lp = LP.login_anonymously("pull-uca-source", "production") - uca = lp.people("ubuntu-cloud-archive") - - package = str(args[0]).lower() - release = str(args[1]).lower() - version = None - if len(args) > 2: - version = str(args[2]) - - pocket = None - try: - (release, pocket) = split_release_pocket(release, default=None) - except PocketDoesNotExistError, e: - pass - - try: - archive = uca.getPPAByName(name="%s-staging" % release) - except NotFound, e: - Logger.error('Archive does not exist for Openstack release: %s', - release) - showOpenstackReleases(uca) - sys.exit(1) - - spph = getSPPH(lp, archive, package, version, pocket=pocket) - if not spph: - Logger.error("Package %s in %s not found.", package, release) - sys.exit(1) - - package = spph.source_package_name - version = spph.source_package_version - component = spph.component_name - Logger.normal('Downloading %s version %s component %s', package, version, component) - srcpkg = UbuntuCloudArchiveSourcePackage(release, package, version, component=component, - mirrors=mirrors) - - try: - srcpkg.pull() - except DownloadError, e: - Logger.error('Failed to download: %s', str(e)) - sys.exit(1) - if not options.download_only: - srcpkg.unpack() +# See pull-pkg +from ubuntutools.pullpkg import PullPkg if __name__ == '__main__': - try: - main() - except KeyboardInterrupt: - Logger.normal('User abort.') + PullPkg.main(distro='uca', pull='source') diff -Nru ubuntu-dev-tools-0.164/pull-uca-udebs ubuntu-dev-tools-0.187~bpo18.04.1/pull-uca-udebs --- ubuntu-dev-tools-0.164/pull-uca-udebs 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/pull-uca-udebs 2019-12-01 18:18:32.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/python3 +# +# pull-uca-udebs -- pull udeb package files for ubuntu cloud archive +# Basic usage: pull-uca-udebs [version|release] +# +# See pull-pkg + +from ubuntutools.pullpkg import PullPkg + +if __name__ == '__main__': + PullPkg.main(distro='uca', pull='udebs') diff -Nru ubuntu-dev-tools-0.164/requestbackport ubuntu-dev-tools-0.187~bpo18.04.1/requestbackport --- ubuntu-dev-tools-0.164/requestbackport 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/requestbackport 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # # Copyright (C) 2011, Stefano Rivera # @@ -25,11 +25,13 @@ from ubuntutools.config import UDTConfig from ubuntutools.lp.lpapicache import Launchpad, Distribution from ubuntutools.lp.udtexceptions import PackageNotFoundException -from ubuntutools.logger import Logger from ubuntutools.question import (YesNoQuestion, EditBugReport, confirmation_prompt) from ubuntutools.rdepends import query_rdepends, RDependsException +from ubuntutools import getLogger +Logger = getLogger() + class DestinationException(Exception): pass @@ -90,7 +92,14 @@ query = re.findall(r'[a-z]+', package) bugs = [] for release in destinations: - project = Launchpad.projects[release + '-backports'] + project_name = '{}-backports'.format(release) + try: + project = Launchpad.projects[project_name] + except KeyError: + Logger.error("The backports tracking project '%s' doesn't seem to " + "exist. Please check the situation with the " + "backports team.", project_name) + sys.exit(1) bugs += project.searchTasks(omit_duplicates=True, search_text=query, status=["Incomplete", "New", "Confirmed", @@ -99,11 +108,11 @@ if not bugs: return - Logger.normal("There are existing bug reports that look similar to your " - "request. Please check before continuing:") + Logger.info("There are existing bug reports that look similar to your " + "request. Please check before continuing:") for bug in sorted(set(bug_task.bug for bug_task in bugs)): - Logger.normal(" * LP: #%-7i: %s %s", bug.id, bug.title, bug.web_link) + Logger.info(" * LP: #%-7i: %s %s", bug.id, bug.title, bug.web_link) confirmation_prompt() @@ -123,7 +132,7 @@ except RDependsException: # Not published? TODO: Check continue - for relationship, rdeps in raw_rdeps.iteritems(): + for relationship, rdeps in raw_rdeps.items(): for rdep in rdeps: # Ignore circular deps: if rdep['Package'] in published_binaries: @@ -134,14 +143,14 @@ intermediate[binpkg][rdep['Package']].append((release, relationship)) output = [] - for binpkg, rdeps in intermediate.iteritems(): + for binpkg, rdeps in intermediate.items(): output += ['', binpkg, '-' * len(binpkg)] - for pkg, appearences in rdeps.iteritems(): + for pkg, appearences in rdeps.items(): output += ['* %s' % pkg] for release, relationship in appearences: output += [' [ ] %s (%s)' % (release, relationship)] - found_any = sum(len(rdeps) for rdeps in intermediate.itervalues()) + found_any = sum(len(rdeps) for rdeps in intermediate.values()) if found_any: output = [ "Reverse dependencies:", @@ -168,7 +177,7 @@ try: package_spph = archive.getSourcePackage(package, distribution) return package_spph - except PackageNotFoundException, e: + except PackageNotFoundException as e: if pass_ == 'binary': Logger.error(str(e)) sys.exit(1) @@ -178,8 +187,8 @@ except KeyError: continue package = apt_pkg.candidate.source_name - Logger.normal("Binary package specified, considering its source " - "package instead: %s", package) + Logger.info("Binary package specified, considering its source " + "package instead: %s", package) def request_backport(package_spph, source, destinations): @@ -192,8 +201,8 @@ Logger.error("%s (%s) has no published binaries in %s. ", package_spph.getPackageName(), package_spph.getVersion(), source) - Logger.normal("Is it stuck in bin-NEW? It can't be backported until " - "the binaries have been accepted.") + Logger.info("Is it stuck in bin-NEW? It can't be backported until " + "the binaries have been accepted.") sys.exit(1) testing = [] @@ -244,8 +253,8 @@ editor.edit() subject, body = editor.get_report() - Logger.normal('The final report is:\nSummary: %s\nDescription:\n%s\n', - subject, body) + Logger.info('The final report is:\nSummary: %s\nDescription:\n%s\n', + subject, body) if YesNoQuestion().ask("Request this backport", "yes") == "no": sys.exit(1) @@ -256,7 +265,7 @@ for target in targets[1:]: bug.addTask(target=target) - Logger.normal("Backport request filed as %s", bug.web_link) + Logger.info("Backport request filed as %s", bug.web_link) def main(): @@ -292,7 +301,7 @@ try: destinations = determine_destinations(options.source, options.destination) - except DestinationException, e: + except DestinationException as e: Logger.error(str(e)) sys.exit(1) diff -Nru ubuntu-dev-tools-0.164/requestsync ubuntu-dev-tools-0.187~bpo18.04.1/requestsync --- ubuntu-dev-tools-0.164/requestsync 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/requestsync 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # -*- coding: utf-8 -*- # # (C) 2007 Canonical Ltd., Steve Kowalik @@ -30,13 +30,16 @@ import os import sys -from debian.changelog import Version from distro_info import UbuntuDistroInfo from ubuntutools.config import UDTConfig, ubu_email from ubuntutools.lp import udtexceptions from ubuntutools.misc import require_utf8 from ubuntutools.question import confirmation_prompt, EditBugReport +from ubuntutools.version import Version + +from ubuntutools import getLogger +Logger = getLogger() # # entry point @@ -97,7 +100,7 @@ config = UDTConfig(options.no_conf) if options.deprecated_lp_flag: - print "The --lp flag is now default, ignored." + Logger.info("The --lp flag is now default, ignored.") if options.email: options.lpapi = False else: @@ -115,8 +118,8 @@ elif options.lpinstance == 'staging': bug_mail_domain = 'bugs.staging.launchpad.net' else: - print >> sys.stderr, ('Error: Unknown launchpad instance: %s' - % options.lpinstance) + Logger.error('Error: Unknown launchpad instance: %s' + % options.lpinstance) sys.exit(1) mailserver_host = config.get_value('SMTP_SERVER', @@ -130,8 +133,8 @@ firstmx = mxlist[0] mailserver_host = firstmx[1] except ImportError: - print >> sys.stderr, ('Please install python-dns to support ' - 'Launchpad mail server lookup.') + Logger.error('Please install python-dns to support ' + 'Launchpad mail server lookup.') sys.exit(1) mailserver_port = config.get_value('SMTP_PORT', default=25, @@ -167,9 +170,8 @@ get_ubuntu_delta_changelog, mail_bug, need_sponsorship) if not any(x in os.environ for x in ('UBUMAIL', 'DEBEMAIL', 'EMAIL')): - print >> sys.stderr, ( - 'E: The environment variable UBUMAIL, DEBEMAIL or EMAIL needs ' - 'to be set to let this script mail the sync request.') + Logger.error('The environment variable UBUMAIL, DEBEMAIL or EMAIL needs ' + 'to be set to let this script mail the sync request.') sys.exit(1) newsource = options.newpkg @@ -187,14 +189,14 @@ else: ubu_info = UbuntuDistroInfo() release = ubu_info.devel() - print >> sys.stderr, 'W: Target release missing - assuming %s' % release + Logger.warning('Target release missing - assuming %s' % release) elif len(args) == 2: release = args[1] elif len(args) == 3: release = args[1] force_base_version = Version(args[2]) else: - print >> sys.stderr, 'E: Too many arguments.' + Logger.error('Too many arguments.') parser.print_help() sys.exit(1) @@ -209,12 +211,12 @@ ubuntu_version = Version('~') ubuntu_component = None # Set after getting the Debian info if not newsource: - print("'%s' doesn't exist in 'Ubuntu %s'.\nDo you want to sync a new package?" % - (srcpkg, release)) + Logger.info("'%s' doesn't exist in 'Ubuntu %s'." % (srcpkg, release)) + Logger.info("Do you want to sync a new package?") confirmation_prompt() newsource = True - except udtexceptions.SeriesNotFoundException, error: - print >> sys.stderr, "E: %s" % error + except udtexceptions.SeriesNotFoundException as error: + Logger.error(error) sys.exit(1) # Get the requested Debian source package @@ -222,11 +224,11 @@ debian_srcpkg = get_debian_srcpkg(srcpkg, distro) debian_version = Version(debian_srcpkg.getVersion()) debian_component = debian_srcpkg.getComponent() - except udtexceptions.PackageNotFoundException, error: - print >> sys.stderr, "E: %s" % error + except udtexceptions.PackageNotFoundException as error: + Logger.error(error) sys.exit(1) - except udtexceptions.SeriesNotFoundException, error: - print >> sys.stderr, "E: %s" % error + except udtexceptions.SeriesNotFoundException as error: + Logger.error(error) sys.exit(1) if ubuntu_component is None: @@ -243,18 +245,18 @@ debian_srcpkg = ubuntutools.requestsync.mail.get_debian_srcpkg(srcpkg, distro) debian_version = Version(debian_srcpkg.getVersion()) debian_component = debian_srcpkg.getComponent() - except udtexceptions.PackageNotFoundException, error: - print >> sys.stderr, "E: %s" % error + except udtexceptions.PackageNotFoundException as error: + Logger.error(error) sys.exit(1) if ubuntu_version == debian_version: - print >> sys.stderr, ('E: The versions in Debian and Ubuntu are the ' - 'same already (%s). Aborting.' % ubuntu_version) + Logger.error('The versions in Debian and Ubuntu are the ' + 'same already (%s). Aborting.' % ubuntu_version) sys.exit(1) if ubuntu_version > debian_version: - print >> sys.stderr, ('E: The version in Ubuntu (%s) is newer than ' - 'the version in Debian (%s). Aborting.' - % (ubuntu_version, debian_version)) + Logger.error('The version in Ubuntu (%s) is newer than ' + 'the version in Debian (%s). Aborting.' + % (ubuntu_version, debian_version)) sys.exit(1) # -s flag not specified - check if we do need sponsorship @@ -262,8 +264,8 @@ sponsorship = need_sponsorship(srcpkg, ubuntu_component, release) if not sponsorship and not ffe: - print >> sys.stderr, ('Consider using syncpackage(1) for syncs that ' - 'do not require feature freeze exceptions.') + Logger.error('Consider using syncpackage(1) for syncs that ' + 'do not require feature freeze exceptions.') # Check for existing package reports if not newsource: @@ -281,19 +283,19 @@ if 'ubuntu' in str(ubuntu_version): need_interaction = True - print('Changes have been made to the package in Ubuntu.\n' - 'Please edit the report and give an explanation.\n' - 'Not saving the report file will abort the request.') - report += (u'Explanation of the Ubuntu delta and why it can be ' - u'dropped:\n%s\n>>> ENTER_EXPLANATION_HERE <<<\n\n' + Logger.info('Changes have been made to the package in Ubuntu.') + Logger.info('Please edit the report and give an explanation.') + Logger.info('Not saving the report file will abort the request.') + report += ('Explanation of the Ubuntu delta and why it can be ' + 'dropped:\n%s\n>>> ENTER_EXPLANATION_HERE <<<\n\n' % get_ubuntu_delta_changelog(ubuntu_srcpkg)) if ffe: need_interaction = True - print('To approve FeatureFreeze exception, you need to state\n' - 'the reason why you feel it is necessary.\n' - 'Not saving the report file will abort the request.') + Logger.info('To approve FeatureFreeze exception, you need to state') + Logger.info('the reason why you feel it is necessary.') + Logger.info('Not saving the report file will abort the request.') report += ('Explanation of FeatureFreeze exception:\n' '>>> ENTER_EXPLANATION_HERE <<<\n\n') @@ -310,10 +312,10 @@ changelog = debian_srcpkg.getChangelog(since_version=base_version) if not changelog: if not options.missing_changelog_ok: - print >> sys.stderr, ("E: Did not retrieve any changelog entries. " - "Do you need to specify '-C'? " - "Was the package recently uploaded? (check " - "http://packages.debian.org/changelogs/)") + Logger.error("Did not retrieve any changelog entries. " + "Do you need to specify '-C'? " + "Was the package recently uploaded? (check " + "http://packages.debian.org/changelogs/)") sys.exit(1) else: need_interaction = True @@ -325,8 +327,8 @@ title, report = editor.get_report() if 'XXX FIXME' in report: - print >> sys.stderr, ("E: changelog boilerplate found in report, " - "please manually add changelog when using '-C'") + Logger.error("changelog boilerplate found in report, " + "please manually add changelog when using '-C'") sys.exit(1) # bug status and bug subscriber @@ -357,5 +359,5 @@ try: main() except KeyboardInterrupt: - print "\nUser abort." + Logger.error("User abort.") sys.exit(2) diff -Nru ubuntu-dev-tools-0.164/requirements.txt ubuntu-dev-tools-0.187~bpo18.04.1/requirements.txt --- ubuntu-dev-tools-0.164/requirements.txt 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/requirements.txt 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,7 @@ +python-debian +python-debianbts +distro-info +httplib2 +launchpadlib +requests +setuptools diff -Nru ubuntu-dev-tools-0.164/reverse-build-depends ubuntu-dev-tools-0.187~bpo18.04.1/reverse-build-depends --- ubuntu-dev-tools-0.164/reverse-build-depends 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/reverse-build-depends 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#!/bin/sh - -cat >&2 < # @@ -14,65 +14,65 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -import optparse +import argparse import sys from distro_info import DistroDataOutdated -from ubuntutools.logger import Logger from ubuntutools.misc import (system_distribution, vendor_to_distroinfo, codename_to_distribution) from ubuntutools.rdepends import query_rdepends, RDependsException +from ubuntutools import getLogger +Logger = getLogger() + +DEFAULT_MAX_DEPTH = 10 # We want avoid any infinite loop... + def main(): system_distro_info = vendor_to_distroinfo(system_distribution())() try: default_release = system_distro_info.devel() - except DistroDataOutdated, e: - Logger.warn(e) + except DistroDataOutdated as e: + Logger.warning(e) default_release = 'unstable' - parser = optparse.OptionParser( - '%prog [options] package', - description="List reverse-dependencies of package. " - "If the package name is prefixed with src: then the " - "reverse-dependencies of all the binary packages that " - "the specified source package builds will be listed.") - parser.add_option('-r', '--release', metavar='RELEASE', - default=default_release, - help='Query dependencies in RELEASE. ' - 'Default: %s' % default_release) - parser.add_option('-R', '--without-recommends', - action='store_false', dest='recommends', default=True, - help='Only consider Depends relationships, ' - 'not Recommends') - parser.add_option('-s', '--with-suggests', - action='store_true', dest='suggests', default=False, - help='Also consider Suggests relationships') - parser.add_option('-b', '--build-depends', - action='store_const', dest='arch', const='source', - help='Query build dependencies (synonym for --arch=source)') - parser.add_option('-a', '--arch', metavar='ARCH', default='any', - help='Query dependencies in ARCH. ' - 'Default: any') - parser.add_option('-c', '--component', metavar='COMPONENT', - action='append', - help='Only consider reverse-dependencies in COMPONENT. ' - 'Can be specified multiple times. Default: all') - parser.add_option('-l', '--list', - action='store_true', default=False, - help='Display a simple, machine-readable list') - parser.add_option('-u', '--service-url', metavar='URL', - dest='server', default=None, - help='Reverse Dependencies webservice URL. ' - 'Default: UbuntuWire') - - options, args = parser.parse_args() - - if len(args) != 1: - parser.error("One (and only one) package must be specified") - package = args[0] + description = ("List reverse-dependencies of package. " + "If the package name is prefixed with src: then the " + "reverse-dependencies of all the binary packages that " + "the specified source package builds will be listed.") + + parser = argparse.ArgumentParser(description=description) + parser.add_argument('-r', '--release', default=default_release, + help='Query dependencies in RELEASE. ' + 'Default: %s' % default_release) + parser.add_argument('-R', '--without-recommends', action='store_false', + dest='recommends', + help='Only consider Depends relationships, ' + 'not Recommends') + parser.add_argument('-s', '--with-suggests', action='store_true', + help='Also consider Suggests relationships') + parser.add_argument('-b', '--build-depends', action='store_true', + help='Query build dependencies (synonym for --arch=source)') + parser.add_argument('-a', '--arch', default='any', + help='Query dependencies in ARCH. Default: any') + parser.add_argument('-c', '--component', action='append', + help='Only consider reverse-dependencies in COMPONENT. ' + 'Can be specified multiple times. Default: all') + parser.add_argument('-l', '--list', action='store_true', + help='Display a simple, machine-readable list') + parser.add_argument('-u', '--service-url', metavar='URL', + dest='server', default=None, + help='Reverse Dependencies webservice URL. ' + 'Default: UbuntuWire') + parser.add_argument('-x', '--recursive', action='store_true', + help='Consider to find reverse dependencies recursively.') + parser.add_argument('-d', '--recursive-depth', type=int, + default=DEFAULT_MAX_DEPTH, + help='If recusive, you can specify the depth.') + parser.add_argument('package') + + options = parser.parse_args() opts = {} if options.server is not None: @@ -87,83 +87,123 @@ options.release = distro_info.codename(options.release, default=options.release) except DistroDataOutdated: - # We already printed a warning + # We already logged a warning pass - try: - data = query_rdepends(package, options.release, options.arch, **opts) - except RDependsException, e: - Logger.error(str(e)) - sys.exit(1) + if options.build_depends: + options.arch = 'source' if options.arch == 'source': - fields = ['Reverse-Build-Depends', 'Reverse-Build-Depends-Indep'] + fields = [ + 'Reverse-Build-Depends', + 'Reverse-Build-Depends-Indep', + 'Reverse-Build-Depends-Arch', + 'Reverse-Testsuite-Triggers', + ] else: fields = ['Reverse-Depends'] if options.recommends: fields.append('Reverse-Recommends') - if options.suggests: + if options.with_suggests: fields.append('Reverse-Suggests') - for field in data.keys(): - if field not in fields: - del data[field] - - if options.component: - for field, rdeps in data.items(): - filtered = [rdep for rdep in rdeps - if rdep['Component'] in options.component] - if not filtered: - del data[field] - else: - data[field] = filtered + def build_results(package, result, fields, component, recursive): + try: + data = query_rdepends(package, options.release, options.arch, **opts) + except RDependsException as e: + Logger.error(str(e)) + sys.exit(1) + if not data: + return + + if fields: + data = {k: v for k, v in data.items() if k in fields} + if component: + data = {k: [rdep for rdep in v + if rdep['Component'] in component] + for k, v in data.items()} + data = {k: v for k, v in data.items() if v} + + result[package] = data + + if recursive > 0: + for rdeps in result[package].values(): + for rdep in rdeps: + build_results( + rdep['Package'], result, fields, component, recursive - 1) + + result = {} + build_results( + options.package, result, fields, options.component, + options.recursive and options.recursive_depth or 0) if options.list: - display_consise(data) + display_consise(result) else: - display_verbose(data) + display_verbose(options.package, result) -def display_verbose(data): - if not data: - print "No reverse dependencies found" +def display_verbose(package, values): + if not values: + Logger.info("No reverse dependencies found") return + def log_field(field): + Logger.info(field) + Logger.info('=' * len(field)) + + def log_package(values, package, arch, dependency, offset=0): + line = ' ' * offset + '* %s' % package + if all_archs and set(arch) != all_archs: + line += ' [%s]' % ' '.join(sorted(arch)) + if dependency: + if len(line) < 30: + line += ' ' * (30 - len(line)) + line += ' (for %s)' % dependency + Logger.info(line) + data = values.get(package) + if data: + offset = offset + 1 + for rdeps in data.values(): + for rdep in rdeps: + log_package(values, + rdep['Package'], + rdep.get('Architectures', all_archs), + rdep.get('Dependency'), + offset) + all_archs = set() # This isn't accurate, but we make up for it by displaying what we found - for rdeps in data.itervalues(): - for rdep in rdeps: - if 'Architectures' in rdep: - all_archs.update(rdep['Architectures']) + for data in values.values(): + for rdeps in data.values(): + for rdep in rdeps: + if 'Architectures' in rdep: + all_archs.update(rdep['Architectures']) - for field, rdeps in data.iteritems(): - print field - print '=' * len(field) + for field, rdeps in values[package].items(): + Logger.info(field) rdeps.sort(key=lambda x: x['Package']) for rdep in rdeps: - line = '* %s' % rdep['Package'] - if all_archs and set(rdep['Architectures']) != all_archs: - line += ' [%s]' % ' '.join(sorted(rdep['Architectures'])) - if 'Dependency' in rdep: - if len(line) < 30: - line += ' ' * (30 - len(line)) - line += ' (for %s)' % rdep['Dependency'] - print line - print + log_package(values, + rdep['Package'], + rdep.get('Architectures', all_archs), + rdep.get('Dependency')) + Logger.info("") if all_archs: - print ("Packages without architectures listed are " - "reverse-dependencies in: %s" - % ', '.join(sorted(list(all_archs)))) + Logger.info("Packages without architectures listed are " + "reverse-dependencies in: %s" + % ', '.join(sorted(list(all_archs)))) -def display_consise(data): +def display_consise(values): result = set() - for rdeps in data.itervalues(): - for rdep in rdeps: - result.add(rdep['Package']) + for data in values.values(): + for rdeps in data.values(): + for rdep in rdeps: + result.add(rdep['Package']) - print u'\n'.join(sorted(list(result))) + Logger.info('\n'.join(sorted(list(result)))) if __name__ == '__main__': diff -Nru ubuntu-dev-tools-0.164/seeded-in-ubuntu ubuntu-dev-tools-0.187~bpo18.04.1/seeded-in-ubuntu --- ubuntu-dev-tools-0.164/seeded-in-ubuntu 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/seeded-in-ubuntu 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # # Copyright (C) 2011, Stefano Rivera # @@ -20,11 +20,13 @@ import optparse import os import time -import urllib +import urllib.request from ubuntutools.lp.lpapicache import (Distribution, Launchpad, PackageNotFoundException) -from ubuntutools.logger import Logger + +from ubuntutools import getLogger +Logger = getLogger() DATA_URL = 'http://qa.ubuntuwire.org/ubuntu-seeded-packages/seeded.json.gz' @@ -40,12 +42,12 @@ or time.time() - os.path.getmtime(fn) > 60 * 60 * 2): if not os.path.isdir(cachedir): os.makedirs(cachedir) - urllib.urlretrieve(url, fn) + urllib.request.urlretrieve(url, fn) try: with gzip.open(fn, 'r') as f: return json.load(f) - except Exception, e: + except Exception as e: Logger.error("Unable to parse seed data: %s. " "Deleting cached data, please try again.", str(e)) @@ -61,7 +63,7 @@ for source in sources: try: spph = archive.getSourcePackage(source) - except PackageNotFoundException, e: + except PackageNotFoundException as e: Logger.error(str(e)) continue binaries[source] = sorted(set(bpph.getPackageName() @@ -75,11 +77,11 @@ present = collections.defaultdict(set) for flavor, type_ in appearences: present[flavor].add(type_) - for flavor, types in present.iteritems(): + for flavor, types in present.items(): if len(types) > 1: types.discard('supported') output = [' %s: %s' % (flavor, ', '.join(sorted(types))) - for flavor, types in present.iteritems()] + for flavor, types in present.items()] output.sort() return '\n'.join(output) @@ -88,28 +90,28 @@ '''Print binaries found in index''' for binary in binaries: if binary in index: - print "%s is seeded in:" % binary - print present_on(index[binary]) + Logger.info("%s is seeded in:" % binary) + Logger.info(present_on(index[binary])) else: - print "%s is not seeded (and may not exist)." % binary + Logger.info("%s is not seeded (and may not exist)." % binary) def output_by_source(index, by_source): - '''Print binaries found in index. Grouped by source''' - for source, binaries in by_source.iteritems(): + '''Logger.Info(binaries found in index. Grouped by source''' + for source, binaries in by_source.items(): seen = False if not binaries: - print ("Status unknown: No binary packages built by the latest " - "%s.\nTry again using -b and the expected binary packages." - % source) + Logger.info("Status unknown: No binary packages built by the latest " + "%s.\nTry again using -b and the expected binary packages." + % source) continue for binary in binaries: if binary in index: seen = True - print "%s (from %s) is seeded in:" % (binary, source) - print present_on(index[binary]) + Logger.info("%s (from %s) is seeded in:" % (binary, source)) + Logger.info(present_on(index[binary])) if not seen: - print "%s's binaries are not seeded." % source + Logger.info("%s's binaries are not seeded." % source) def main(): diff -Nru ubuntu-dev-tools-0.164/setup.py ubuntu-dev-tools-0.187~bpo18.04.1/setup.py --- ubuntu-dev-tools-0.164/setup.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/setup.py 2021-12-05 15:20:37.000000000 +0000 @@ -1,64 +1,68 @@ -#!/usr/bin/python +#!/usr/bin/python3 from setuptools import setup import glob import os import re -import sys -import codecs # look/set what version we have changelog = "debian/changelog" if os.path.exists(changelog): - head = codecs.open(changelog, 'r', 'utf-8', 'replace').readline() - match = re.compile(".*\((.*)\).*").match(head) + head = open(changelog, 'r', encoding='utf-8').readline() + match = re.compile(r".*\((.*)\).*").match(head) if match: version = match.group(1) -if sys.version_info[0] >= 3: - scripts = [] - data_files = [] -else: - scripts = [ - '404main', - 'backportpackage', - 'bitesize', - 'check-mir', - 'check-symbols', - 'dch-repeat', - 'grab-merge', - 'grep-merges', - 'hugdaylist', - 'import-bug-from-debian', - 'merge-changelog', - 'mk-sbuild', - 'pbuilder-dist', - 'pbuilder-dist-simple', - 'pull-debian-debdiff', - 'pull-debian-source', - 'pull-lp-source', - 'pull-revu-source', - 'pull-uca-source', - 'requestbackport', - 'requestsync', - 'reverse-build-depends', - 'reverse-depends', - 'seeded-in-ubuntu', - 'setup-packaging-environment', - 'sponsor-patch', - 'submittodebian', - 'syncpackage', - 'ubuntu-build', - 'ubuntu-iso', - 'ubuntu-upload-permission', - 'update-maintainer', - ] - data_files = [ - ('share/bash-completion/completions', glob.glob("bash_completion/*")), - ('share/man/man1', glob.glob("doc/*.1")), - ('share/man/man5', glob.glob("doc/*.5")), - ('share/ubuntu-dev-tools', ['enforced-editing-wrapper']), - ] +scripts = [ + 'backportpackage', + 'bitesize', + 'check-mir', + 'check-symbols', + 'dch-repeat', + 'grab-merge', + 'grep-merges', + 'import-bug-from-debian', + 'merge-changelog', + 'mk-sbuild', + 'pbuilder-dist', + 'pbuilder-dist-simple', + 'pull-pkg', + 'pull-debian-debdiff', + 'pull-debian-source', + 'pull-debian-debs', + 'pull-debian-ddebs', + 'pull-debian-udebs', + 'pull-lp-source', + 'pull-lp-debs', + 'pull-lp-ddebs', + 'pull-lp-udebs', + 'pull-ppa-source', + 'pull-ppa-debs', + 'pull-ppa-ddebs', + 'pull-ppa-udebs', + 'pull-uca-source', + 'pull-uca-debs', + 'pull-uca-ddebs', + 'pull-uca-udebs', + 'requestbackport', + 'requestsync', + 'reverse-depends', + 'seeded-in-ubuntu', + 'setup-packaging-environment', + 'sponsor-patch', + 'submittodebian', + 'syncpackage', + 'ubuntu-build', + 'ubuntu-iso', + 'ubuntu-upload-permission', + 'update-maintainer', +] +data_files = [ + ('share/bash-completion/completions', glob.glob("bash_completion/*")), + ('share/man/man1', glob.glob("doc/*.1")), + ('share/man/man5', glob.glob("doc/*.5")), + ('share/ubuntu-dev-tools', ['enforced-editing-wrapper']), +] if __name__ == '__main__': setup( @@ -73,5 +77,5 @@ 'ubuntutools/test', ], data_files=data_files, - test_suite='ubuntutools.test.discover', + test_suite='ubuntutools.test', ) diff -Nru ubuntu-dev-tools-0.164/sponsor-patch ubuntu-dev-tools-0.187~bpo18.04.1/sponsor-patch --- ubuntu-dev-tools-0.164/sponsor-patch 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/sponsor-patch 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # # Copyright (C) 2010-2011, Benjamin Drung # @@ -19,12 +19,15 @@ import shutil import sys import tempfile +import logging from ubuntutools.builder import get_builder from ubuntutools.config import UDTConfig -from ubuntutools.logger import Logger from ubuntutools.sponsor_patch.sponsor_patch import sponsor_patch, check_dependencies +from ubuntutools import getLogger +Logger = getLogger() + def parse(script_name): """Parse the command line parameters.""" @@ -64,7 +67,8 @@ "temporary directory, deleted afterwards).") (options, args) = parser.parse_args() - Logger.set_verbosity(options.verbose) + if options.verbose: + Logger.setLevel(logging.DEBUG) check_dependencies() if len(args) == 0: @@ -123,7 +127,7 @@ options.keyid, options.lpinstance, options.update, options.upload, workdir) except KeyboardInterrupt: - print "\nUser abort." + Logger.error("User abort.") sys.exit(2) finally: if options.workdir is None: diff -Nru ubuntu-dev-tools-0.164/submittodebian ubuntu-dev-tools-0.187~bpo18.04.1/submittodebian --- ubuntu-dev-tools-0.164/submittodebian 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/submittodebian 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # -*- coding: utf-8 -*- # # submittodebian - tool to submit patches to Debian's BTS @@ -27,21 +27,20 @@ import re import shutil import sys + +from subprocess import call, check_call, run, Popen, PIPE, DEVNULL + from tempfile import mkdtemp +from debian.changelog import Changelog from distro_info import UbuntuDistroInfo, DistroDataOutdated from ubuntutools.config import ubu_email from ubuntutools.question import YesNoQuestion, EditFile -from ubuntutools.subprocess import call, check_call, Popen, PIPE from ubuntutools.update_maintainer import update_maintainer, restore_maintainer -try: - from debian.changelog import Changelog -except ImportError: - print(u"This utility requires modules from the «python-debian» package, " - u"which isn't currently installed.") - sys.exit(1) +from ubuntutools import getLogger +Logger = getLogger() def get_most_recent_debian_version(changelog): @@ -91,10 +90,9 @@ debdiff = os.path.join(tmpdir, '%s_%s.debdiff' % (pkg, newver)) - devnull = open('/dev/null', 'w') diff_cmd = ['bzr', 'diff', '-r', 'tag:' + str(oldver)] - if call(diff_cmd, stdout=devnull, stderr=devnull) == 1: - print "Extracting bzr diff between %s and %s" % (oldver, newver) + if call(diff_cmd, stdout=DEVNULL, stderr=DEVNULL) == 1: + Logger.info("Extracting bzr diff between %s and %s" % (oldver, newver)) else: if oldver.epoch is not None: oldver = str(oldver)[str(oldver).index(":") + 1:] @@ -107,17 +105,13 @@ check_file(olddsc) check_file(newdsc) - print "Generating debdiff between %s and %s" % (oldver, newver) + Logger.info("Generating debdiff between %s and %s" % (oldver, newver)) diff_cmd = ['debdiff', olddsc, newdsc] - diff = Popen(diff_cmd, stdout=PIPE) - debdiff_f = open(debdiff, 'w') - filterdiff = Popen(['filterdiff', '-x', '*changelog*'], - stdin=diff.stdout, stdout=debdiff_f) - diff.stdout.close() - filterdiff.wait() - debdiff_f.close() - devnull.close() + with Popen(diff_cmd, stdout=PIPE, encoding='utf-8') as diff: + with open(debdiff, 'w', encoding='utf-8') as debdiff_f: + run(['filterdiff', '-x', '*changelog*'], + stdin=diff.stdout, stdout=debdiff_f, encoding='utf-8') return debdiff @@ -128,15 +122,15 @@ else: if not critical: return False - print u"Couldn't find «%s».\n" % fname + Logger.info("Couldn't find «%s».\n" % fname) sys.exit(1) def submit_bugreport(body, debdiff, deb_version, changelog): try: devel = UbuntuDistroInfo().devel() - except DistroDataOutdated, e: - print str(e) + except DistroDataOutdated as e: + Logger.info(str(e)) devel = '' if os.path.dirname(sys.argv[0]).startswith('/usr/bin'): @@ -203,10 +197,10 @@ #smtptls """ % email - with file(fn, 'w') as f: + with open(fn, 'w') as f: f.write(reportbugrc) - print """\ + Logger.info("""\ You have not configured reportbug. Assuming this is the first time you have used it. Writing a ~/.reportbugrc that will use Debian's mail server, and CC the bug to you at <%s> @@ -217,7 +211,7 @@ If this is not correct, please exit now and edit ~/.reportbugrc or run reportbug --configure for its configuration wizard. -""" % (email, reportbugrc.strip()) +""" % (email, reportbugrc.strip())) if YesNoQuestion().ask("Continue submitting this bug", "yes") == "no": sys.exit(1) @@ -230,23 +224,23 @@ parser.parse_args() if not os.path.exists('/usr/bin/reportbug'): - print(u"This utility requires the «reportbug» package, which isn't " - u"currently installed.") + Logger.error("This utility requires the «reportbug» package, which isn't " + "currently installed.") sys.exit(1) check_reportbug_config() changelog_file = (check_file('debian/changelog', critical=False) or check_file('../debian/changelog')) - changelog = Changelog(file(changelog_file).read()) + with open(changelog_file) as f: + changelog = Changelog(f.read()) deb_version = get_most_recent_debian_version(changelog) bug_body = get_bug_body(changelog) tmpdir = mkdtemp() body = os.path.join(tmpdir, 'bug_body') - fp = open(body, 'w') - fp.write(bug_body.encode('utf-8')) - fp.close() + with open(body, 'wb') as f: + f.write(bug_body.encode('utf-8')) restore_maintainer('debian') build_source_package() diff -Nru ubuntu-dev-tools-0.164/syncpackage ubuntu-dev-tools-0.187~bpo18.04.1/syncpackage --- ubuntu-dev-tools-0.164/syncpackage 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/syncpackage 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # -*- coding: utf-8 -*- # # Copyright (C) 2008-2010 Martin Pitt , @@ -20,14 +20,15 @@ # # ################################################################## -import codecs +import fnmatch +import logging import optparse import os -import re import shutil +import subprocess import sys import textwrap -import urllib +import urllib.request from lazr.restfulclient.errors import HTTPError @@ -37,20 +38,21 @@ from ubuntutools.lp import udtexceptions from ubuntutools.lp.lpapicache import (Distribution, Launchpad, PersonTeam, SourcePackagePublishingHistory) -from ubuntutools.logger import Logger from ubuntutools.misc import split_release_pocket from ubuntutools.question import YesNoQuestion from ubuntutools.requestsync.mail import ( get_debian_srcpkg as requestsync_mail_get_debian_srcpkg) from ubuntutools.requestsync.lp import get_debian_srcpkg, get_ubuntu_srcpkg from ubuntutools.version import Version -from ubuntutools import subprocess + +from ubuntutools import getLogger +Logger = getLogger() def remove_signature(dscname): '''Removes the signature from a .dsc file if the .dsc file is signed.''' - dsc_file = open(dscname) + dsc_file = open(dscname, encoding='utf-8') if dsc_file.readline().strip() == "-----BEGIN PGP SIGNED MESSAGE-----": unsigned_file = [] # search until begin of body found @@ -65,7 +67,7 @@ unsigned_file.append(line) dsc_file.close() - dsc_file = open(dscname, "w") + dsc_file = open(dscname, "w", encoding='utf-8') dsc_file.writelines(unsigned_file) dsc_file.close() @@ -74,11 +76,11 @@ '''Add additional Launchpad bugs to the list of fixed bugs in changes file.''' - changes = [l for l in changes.split("\n") if l.strip() != ""] + changes = [line for line in changes.split("\n") if line.strip() != ""] # Remove duplicates bugs = set(str(bug) for bug in bugs) - for i in xrange(len(changes)): + for i in range(len(changes)): if changes[i].startswith("Launchpad-Bugs-Fixed:"): bugs.update(changes[i][22:].strip().split(" ")) changes[i] = "Launchpad-Bugs-Fixed: %s" % (" ".join(bugs)) @@ -100,7 +102,6 @@ uploader = name + " <" + email + ">" - src_pkg.pull_dsc() new_ver = Version(src_pkg.dsc["Version"]) try: @@ -111,13 +112,12 @@ ubu_pkg = UbuntuSourcePackage(src_pkg.source, ubuntu_ver.full_version, ubuntu_source.getComponent(), mirrors=[ubuntu_mirror]) - ubu_pkg.pull_dsc() need_orig = ubuntu_ver.upstream_version != new_ver.upstream_version except udtexceptions.PackageNotFoundException: ubuntu_ver = Version('~') ubu_pkg = None need_orig = True - Logger.normal('%s does not exist in Ubuntu.', name) + Logger.info('%s does not exist in Ubuntu.', name) Logger.debug('Source %s: current version %s, new version %s', src_pkg.source, ubuntu_ver, new_ver) @@ -129,15 +129,15 @@ Logger.error('--force is required to discard Ubuntu changes.') sys.exit(1) - Logger.warn('Overwriting modified Ubuntu version %s, ' - 'setting current version to %s', - ubuntu_ver.full_version, cur_ver.full_version) + Logger.warning('Overwriting modified Ubuntu version %s, ' + 'setting current version to %s', + ubuntu_ver.full_version, cur_ver.full_version) if simulate: return try: src_pkg.pull() - except DownloadError, e: + except DownloadError as e: Logger.error('Failed to download: %s', str(e)) sys.exit(1) src_pkg.unpack() @@ -145,7 +145,7 @@ needs_fakesync = not (need_orig or ubu_pkg.verify_orig()) if needs_fakesync and fakesync: - Logger.warn('Performing a fakesync') + Logger.warning('Performing a fakesync') elif not needs_fakesync and fakesync: Logger.error('Fakesync not required, aborting.') sys.exit(1) @@ -158,18 +158,18 @@ # Download Ubuntu files (override Debian source tarballs) try: ubu_pkg.pull() - except DownloadError, e: + except DownloadError as e: Logger.error('Failed to download: %s', str(e)) sys.exit(1) # change into package directory directory = src_pkg.source + '-' + new_ver.upstream_version - Logger.command(('cd', directory)) + Logger.debug('cd' + directory) os.chdir(directory) # read Debian distribution from debian/changelog if not specified if debian_dist is None: - line = open("debian/changelog").readline() + line = open("debian/changelog", encoding='utf-8').readline() debian_dist = line.split(" ")[2].strip(";") if not fakesync: @@ -184,23 +184,22 @@ cmd.append("-sa") else: cmd.append("-sd") - if not Logger.verbose: + if not Logger.isEnabledFor(logging.DEBUG): cmd += ["-q"] - Logger.command(cmd + ['>', '../' + changes_filename]) - process = subprocess.Popen(cmd, stdout=subprocess.PIPE) - changes = process.communicate()[0] + Logger.debug(' '.join(cmd) + '> ../' + changes_filename) + changes = subprocess.check_output(cmd, encoding='utf-8') # Add additional bug numbers if len(bugs) > 0: changes = add_fixed_bugs(changes, bugs) # remove extracted (temporary) files - Logger.command(('cd', '..')) + Logger.debug('cd ..') os.chdir('..') shutil.rmtree(directory, True) # write changes file - changes_file = open(changes_filename, "w") + changes_file = open(changes_filename, "w", encoding='utf-8') changes_file.writelines(changes) changes_file.close() @@ -210,7 +209,7 @@ cmd = ["debsign", changes_filename] if keyid is not None: cmd.insert(1, "-k" + keyid) - Logger.command(cmd) + Logger.debug(' '.join(cmd)) subprocess.check_call(cmd) else: # Create fakesync changelog entry @@ -225,14 +224,14 @@ cmd = ['dch', '-v', new_ver.full_version, '--force-distribution', '-D', release, message] env = {'DEBFULLNAME': name, 'DEBEMAIL': email} - Logger.command(cmd) + Logger.debug(' '.join(cmd)) subprocess.check_call(cmd, env=env) # update the Maintainer field cmd = ["update-maintainer"] - if not Logger.verbose: + if not Logger.isEnabledFor(logging.DEBUG): cmd.append("-q") - Logger.command(cmd) + Logger.debug(' '.join(cmd)) subprocess.check_call(cmd) # Build source package @@ -242,7 +241,7 @@ cmd += ['-sa'] if keyid: cmd += ["-k" + keyid] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) returncode = subprocess.call(cmd) if returncode != 0: Logger.error('Source-only build with debuild failed. ' @@ -274,7 +273,7 @@ try: debian_srcpkg = get_debian_srcpkg(package, dist) except (udtexceptions.PackageNotFoundException, - udtexceptions.SeriesNotFoundException), e: + udtexceptions.SeriesNotFoundException) as e: Logger.error(str(e)) sys.exit(1) if version is None: @@ -286,7 +285,7 @@ ubuntu_version = Version(ubuntu_srcpkg.getVersion()) except udtexceptions.PackageNotFoundException: ubuntu_version = Version('~') - except udtexceptions.SeriesNotFoundException, e: + except udtexceptions.SeriesNotFoundException as e: Logger.error(str(e)) sys.exit(1) if ubuntu_version >= version: @@ -341,9 +340,9 @@ ubuntu_spph.getComponent(), mirrors=[]) - Logger.normal('Source %s -> %s/%s: current version %s, new version %s', - src_pkg.source, ubuntu_series, ubuntu_pocket, - ubuntu_pkg.version, src_pkg.version) + Logger.info('Source %s -> %s/%s: current version %s, new version %s', + src_pkg.source, ubuntu_series, ubuntu_pocket, + ubuntu_pkg.version, src_pkg.version) ubuntu_version = Version(ubuntu_pkg.version.full_version) base_version = ubuntu_version.get_related_debian_version() @@ -352,29 +351,27 @@ sys.exit(1) # Check whether a fakesync would be required. - src_pkg.pull_dsc() - ubuntu_pkg.pull_dsc() if not src_pkg.dsc.compare_dsc(ubuntu_pkg.dsc): Logger.error('The checksums of the Debian and Ubuntu packages ' 'mismatch. A fake sync using --fakesync is required.') sys.exit(1) except udtexceptions.PackageNotFoundException: base_version = Version('~') - Logger.normal('Source %s -> %s/%s: not in Ubuntu, new version %s', - src_pkg.source, ubuntu_series, ubuntu_pocket, - src_pkg.version) + Logger.info('Source %s -> %s/%s: not in Ubuntu, new version %s', + src_pkg.source, ubuntu_series, ubuntu_pocket, + src_pkg.version) changes = debian_spph.getChangelog(since_version=base_version) if changes: changes = changes.strip() - Logger.normal("New changes:\n%s", changes) + Logger.info("New changes:\n%s", changes) if simulate: return if sponsoree: - Logger.normal("Sponsoring this sync for %s (%s)", - sponsoree.display_name, sponsoree.name) + Logger.info("Sponsoring this sync for %s (%s)", + sponsoree.display_name, sponsoree.name) answer = YesNoQuestion().ask("Sync this package", "no") if answer != "yes": return @@ -388,20 +385,20 @@ to_pocket=ubuntu_pocket, include_binaries=False, sponsored=sponsoree) - except HTTPError, error: + except HTTPError as error: Logger.error("HTTP Error %s: %s", error.response.status, error.response.reason) Logger.error(error.content) sys.exit(1) - Logger.normal('Request succeeded; you should get an e-mail once it is ' - 'processed.') + Logger.info('Request succeeded; you should get an e-mail once it is ' + 'processed.') bugs = sorted(set(bugs)) if bugs: - Logger.normal("Launchpad bugs to be closed: %s", - ', '.join(str(bug) for bug in bugs)) - Logger.normal('Please wait for the sync to be successful before ' - 'closing bugs.') + Logger.info("Launchpad bugs to be closed: %s", + ', '.join(str(bug) for bug in bugs)) + Logger.info('Please wait for the sync to be successful before ' + 'closing bugs.') answer = YesNoQuestion().ask("Close bugs", "yes") if answer == "yes": close_bugs(bugs, src_pkg.source, src_pkg.version.full_version, @@ -416,7 +413,7 @@ series = Launchpad.distributions['ubuntu'].current_series lp_comments = series.getDifferenceComments(source_package_name=query) blacklisted = False - comments = [u'%s\n -- %s %s' + comments = ['%s\n -- %s %s' % (c.body_text, c.comment_author.name, c.comment_date.strftime('%a, %d %b %Y %H:%M:%S +0000')) for c in lp_comments] @@ -430,16 +427,20 @@ # Old blacklist: url = 'http://people.canonical.com/~ubuntu-archive/sync-blacklist.txt' - with codecs.EncodedFile(urllib.urlopen(url), 'UTF-8') as f: + with urllib.request.urlopen(url) as f: applicable_lines = [] for line in f: + line = line.decode('utf-8') if not line.strip(): applicable_lines = [] continue - m = re.match(r'^\s*([a-z0-9.+-]+)?', line) - source = m.group(0) applicable_lines.append(line) - if source and query == source: + try: + line = line[:line.index('#')] + except ValueError: + pass + source = line.strip() + if source and fnmatch.fnmatch(query, source): comments += ["From sync-blacklist.txt:"] + applicable_lines blacklisted = 'ALWAYS' break @@ -466,13 +467,13 @@ if target == ubuntu or (target.name == package and getattr(target, 'distribution', None) == ubuntu): if task.status != 'Fix Released': - Logger.normal("Closed bug %s", task.web_link) + Logger.info("Closed bug %s", task.web_link) task.status = 'Fix Released' task.lp_save() bug.newMessage(content=message) break else: - Logger.error(u"Cannot find any tasks on LP: #%i to close.", bug.id) + Logger.error("Cannot find any tasks on LP: #%i to close.", bug.id) def parse(): @@ -595,7 +596,8 @@ '''Handle parameters and get the ball rolling''' (options, package) = parse() - Logger.verbose = options.verbose + if options.verbose: + Logger.setLevel('DEBUG') config = UDTConfig(options.no_conf) if options.debian_mirror is None: options.debian_mirror = config.get_value('DEBIAN_MIRROR') @@ -612,7 +614,7 @@ # devel for copyPackage and changelogUrl kwargs = {'service': options.lpinstance, 'api_version': 'devel'} - if options.lp: + if options.lp and not options.simulate: Launchpad.login(**kwargs) else: Launchpad.login_anonymously(**kwargs) @@ -624,10 +626,10 @@ options.release = "%s-proposed" % ubuntu.current_series.name if not options.fakesync and not options.lp: - Logger.warn("The use of --no-lp is not recommended for uploads " - "targeted at Ubuntu. " - "The archive-admins discourage its use, except for " - "fakesyncs.") + Logger.warning("The use of --no-lp is not recommended for uploads " + "targeted at Ubuntu. " + "The archive-admins discourage its use, except for " + "fakesyncs.") sponsoree = None if options.sponsoree: @@ -683,19 +685,19 @@ "reasoning and subscribe ~ubuntu-archive."] if blacklist_fail: - Logger.error(u"Source package %s is blacklisted.", src_pkg.source) + Logger.error("Source package %s is blacklisted.", src_pkg.source) elif blacklisted == 'ALWAYS': - Logger.normal(u"Source package %s is blacklisted.", src_pkg.source) + Logger.info(u"Source package %s is blacklisted.", src_pkg.source) if messages: for message in messages: for line in textwrap.wrap(message): - Logger.normal(line) + Logger.info(line) if comments: - Logger.normal("Blacklist Comments:") + Logger.info("Blacklist Comments:") for comment in comments: for line in textwrap.wrap(comment): - Logger.normal(u" " + line) + Logger.info(" " + line) if blacklist_fail: sys.exit(1) @@ -715,4 +717,4 @@ try: main() except KeyboardInterrupt: - Logger.normal('User abort.') + Logger.info('User abort.') diff -Nru ubuntu-dev-tools-0.164/test-data/blank-example/content ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/content --- ubuntu-dev-tools-0.164/test-data/blank-example/content 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/content 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -upstream diff -Nru ubuntu-dev-tools-0.164/test-data/blank-example/debian/compat ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/compat --- ubuntu-dev-tools-0.164/test-data/blank-example/debian/compat 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -7 diff -Nru ubuntu-dev-tools-0.164/test-data/blank-example/debian/control ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/control --- ubuntu-dev-tools-0.164/test-data/blank-example/debian/control 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/control 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -Source: example -Section: misc -Priority: extra -Maintainer: Ubuntu Developers -Build-Depends: debhelper (>= 7.0.50~) -Standards-Version: 3.9.1 - -Package: example -Architecture: all -Depends: ${misc:Depends}, ${shlibs:Depends} -Description: Example package for testing purposes - An example package used by the test suite. Useless. diff -Nru ubuntu-dev-tools-0.164/test-data/blank-example/debian/copyright ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/copyright --- ubuntu-dev-tools-0.164/test-data/blank-example/debian/copyright 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/copyright 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -Format: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=152 -Source: https://launchpad.net/ubuntu-dev-tools - -Files: * -Copyright: 2010-2011, Stefano Rivera -License: ISC - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - . - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. diff -Nru ubuntu-dev-tools-0.164/test-data/blank-example/debian/rules ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/rules --- ubuntu-dev-tools-0.164/test-data/blank-example/debian/rules 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/rules 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -#!/usr/bin/make -f - -%: - dh $@ diff -Nru ubuntu-dev-tools-0.164/test-data/blank-example/debian/source/format ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/source/format --- ubuntu-dev-tools-0.164/test-data/blank-example/debian/source/format 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/source/format 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -3.0 (quilt) diff -Nru ubuntu-dev-tools-0.164/test-data/blank-example/debian/source/options ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/source/options --- ubuntu-dev-tools-0.164/test-data/blank-example/debian/source/options 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/test-data/blank-example/debian/source/options 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -compression=xz diff -Nru ubuntu-dev-tools-0.164/test-requirements.txt ubuntu-dev-tools-0.187~bpo18.04.1/test-requirements.txt --- ubuntu-dev-tools-0.164/test-requirements.txt 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/test-requirements.txt 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,4 @@ +coverage +flake8 >= 3.8.0 +pytest +pytest-cov diff -Nru ubuntu-dev-tools-0.164/tox.ini ubuntu-dev-tools-0.187~bpo18.04.1/tox.ini --- ubuntu-dev-tools-0.164/tox.ini 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/tox.ini 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,22 @@ +[tox] +envlist = flake8,pytest +skipsdist = True + +[testenv] +base_python = python3 +setenv = VIRTUAL_ENV={envdir} + PYTHONHASHSEED=0 +usedevelop = True +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt +install_command = pip install {opts} {packages} + +[testenv:flake8] +commands = flake8 {posargs} + +[testenv:pytest] +commands = pytest -v --cov=ubuntutools {posargs:ubuntutools} + +[flake8] +verbose = 2 +max-line-length = 99 diff -Nru ubuntu-dev-tools-0.164/ubuntu-build ubuntu-dev-tools-0.187~bpo18.04.1/ubuntu-build --- ubuntu-dev-tools-0.164/ubuntu-build 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntu-build 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # # ubuntu-build - command line interface for Launchpad buildd operations. # @@ -32,6 +32,9 @@ from ubuntutools.lp.lpapicache import Distribution, PersonTeam from ubuntutools.misc import split_release_pocket +from ubuntutools import getLogger +Logger = getLogger() + def main(): # Usage. @@ -40,8 +43,10 @@ usage += "Only Launchpad Buildd Admins may rescore package builds." # Valid architectures. - valid_archs = set(["armel", "armhf", "arm64", "amd64", "hppa", "i386", "ia64", - "lpia", "powerpc", "ppc64el", "s390x", "sparc"]) + valid_archs = set([ + "armel", "armhf", "arm64", "amd64", "hppa", "i386", "ia64", + "lpia", "powerpc", "ppc64el", "riscv64", "s390x", "sparc", + ]) # Prepare our option parser. opt_parser = OptionParser(usage) @@ -108,15 +113,15 @@ # Check our operation. if op not in ("rescore", "retry", "status"): - print >> sys.stderr, "Invalid operation: %s." % op + Logger.error("Invalid operation: %s." % op) sys.exit(1) # If the user has specified an architecture to build, we only wish to # rebuild it and nothing else. if options.architecture: if options.architecture[0] not in valid_archs: - print >> sys.stderr, ("Invalid architecture specified: %s." - % options.architecture[0]) + Logger.error("Invalid architecture specified: %s." + % options.architecture[0]) sys.exit(1) else: one_arch = True @@ -126,8 +131,8 @@ # split release and pocket try: (release, pocket) = split_release_pocket(release) - except PocketDoesNotExistError, error: - print 'E: %s' % error + except PocketDoesNotExistError as error: + Logger.error(error) sys.exit(1) # Get the ubuntu archive @@ -140,8 +145,8 @@ try: sources = ubuntu_archive.getSourcePackage(package, release, pocket) distroseries = Distribution('ubuntu').getSeries(release) - except (SeriesNotFoundException, PackageNotFoundException), error: - print error + except (SeriesNotFoundException, PackageNotFoundException) as error: + Logger.error(error) sys.exit(1) # Get list of builds for that package. builds = sources.getBuilds() @@ -163,16 +168,16 @@ pocket=pocket) if op in ('rescore', 'retry') and not necessary_privs: - print >> sys.stderr, ("You cannot perform the %s operation on a %s " - "package as you do not have the permissions " - "to do this action." % (op, component)) + Logger.error("You cannot perform the %s operation on a %s " + "package as you do not have the permissions " + "to do this action." % (op, component)) sys.exit(1) # Output details. - print("The source version for '%s' in %s (%s) is at %s." % - (package, release.capitalize(), component, version)) + Logger.info("The source version for '%s' in %s (%s) is at %s." % + (package, release.capitalize(), component, version)) - print "Current build status for this package:" + Logger.info("Current build status for this package:") # Output list of arches for package and their status. done = False @@ -182,28 +187,28 @@ continue done = True - print "%s: %s." % (build.arch_tag, build.buildstate) + Logger.info("%s: %s." % (build.arch_tag, build.buildstate)) if op == 'rescore': if build.can_be_rescored: # FIXME: make priority an option priority = 5000 - print 'Rescoring build %s to %d...' % (build.arch_tag, priority) + Logger.info('Rescoring build %s to %d...' % (build.arch_tag, priority)) build.rescore(score=priority) else: - print 'Cannot rescore build on %s.' % build.arch_tag + Logger.info('Cannot rescore build on %s.' % build.arch_tag) if op == 'retry': if build.can_be_retried: - print 'Retrying build on %s...' % build.arch_tag + Logger.info('Retrying build on %s...' % build.arch_tag) build.retry() else: - print 'Cannot retry build on %s.' % build.arch_tag + Logger.info('Cannot retry build on %s.' % build.arch_tag) # We are done if done: sys.exit(0) - print("No builds for '%s' found in the %s release - it may have been " - "built in a former release." % (package, release.capitalize())) + Logger.info("No builds for '%s' found in the %s release" % (package, release.capitalize())) + Logger.info("It may have been built in a former release.") sys.exit(0) # Batch mode @@ -223,15 +228,15 @@ + '-proposed') try: (release, pocket) = split_release_pocket(release) - except PocketDoesNotExistError, error: - print 'E: %s' % error + except PocketDoesNotExistError as error: + Logger.error(error) sys.exit(1) ubuntu_archive = Distribution('ubuntu').getArchive() try: distroseries = Distribution('ubuntu').getSeries(release) - except SeriesNotFoundException, error: - print error + except SeriesNotFoundException as error: + Logger.error(error) sys.exit(1) me = PersonTeam.me @@ -240,14 +245,14 @@ and me.isLpTeamMember('launchpad-buildd-admins')) or False) if options.priority and not can_rescore: - print >> sys.stderr, ("You don't have the permissions to rescore " - "builds. Ignoring your rescore request.") + Logger.error("You don't have the permissions to rescore " + "builds. Ignoring your rescore request.") for pkg in args: try: pkg = ubuntu_archive.getSourcePackage(pkg, release, pocket) - except PackageNotFoundException, error: - print error + except PackageNotFoundException as error: + Logger.error(error) continue # Check permissions (part 2): check upload permissions for the source @@ -257,20 +262,20 @@ pkg.getPackageName(), pkg.getComponent()) if options.retry and not can_retry: - print >> sys.stderr, ("You don't have the permissions to retry the " - "build of '%s'. Ignoring your request." - % pkg.getPackageName()) + Logger.error("You don't have the permissions to retry the " + "build of '%s'. Ignoring your request." + % pkg.getPackageName()) - print "The source version for '%s' in '%s' (%s) is: %s" % ( - pkg.getPackageName(), release, pocket, pkg.getVersion()) + Logger.info("The source version for '%s' in '%s' (%s) is: %s" % + (pkg.getPackageName(), release, pocket, pkg.getVersion())) - print pkg.getBuildStates(archs) + Logger.info(pkg.getBuildStates(archs)) if can_retry: - print pkg.retryBuilds(archs) + Logger.info(pkg.retryBuilds(archs)) if options.priority and can_rescore: - print pkg.rescoreBuilds(archs, options.priority) + Logger.info(pkg.rescoreBuilds(archs, options.priority)) - print '' + Logger.info('') if __name__ == '__main__': diff -Nru ubuntu-dev-tools-0.164/ubuntu-iso ubuntu-dev-tools-0.187~bpo18.04.1/ubuntu-iso --- ubuntu-dev-tools-0.164/ubuntu-iso 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntu-iso 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # ubuntuiso - tool to examine Ubuntu CD (ISO) installation media # Copyright (C) 2008 Canonical Ltd. @@ -21,22 +21,24 @@ # ################################################################## import optparse +import subprocess import sys -from ubuntutools import subprocess +from ubuntutools import getLogger +Logger = getLogger() def extract(iso, path): command = ['isoinfo', '-R', '-i', iso, '-x', path] - pipe = subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = pipe.communicate() + pipe = subprocess.run(command, encoding='utf-8', + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) if pipe.returncode != 0: - sys.stderr.write(stderr) + sys.stderr.write(pipe.stderr) sys.exit(pipe.returncode) - return stdout + return pipe.stdout def main(): @@ -55,11 +57,11 @@ version = extract(iso, '/.disk/info') if len(version) == 0: - print >> sys.stderr, '%s does not appear to be an Ubuntu ISO' % iso + Logger.error('%s does not appear to be an Ubuntu ISO' % iso) err = True continue - print prefix + version + Logger.info(prefix + version) if err: sys.exit(1) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/archive.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/archive.py --- ubuntu-dev-tools-0.164/ubuntutools/archive.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/archive.py 2021-12-09 16:54:27.000000000 +0000 @@ -27,40 +27,46 @@ 3. Verify checksums. """ -from __future__ import with_statement, print_function - +from urllib.request import urlopen import codecs -import hashlib -import os.path -try: - from urllib.request import ProxyHandler, build_opener, urlopen - from urllib.parse import urlparse - from urllib.error import URLError, HTTPError -except ImportError: - from urllib2 import ProxyHandler, build_opener, urlopen, URLError, HTTPError - from urlparse import urlparse +import functools +import json +import os import re +import subprocess import sys +import tempfile + +from abc import (ABC, abstractmethod) -from debian.changelog import Changelog, Version +from debian.changelog import Changelog import debian.deb822 -import debian.debian_support -import httplib2 -from ubuntutools.config import UDTConfig -from ubuntutools.lp.lpapicache import (Launchpad, Distribution, - SourcePackagePublishingHistory) -from ubuntutools.logger import Logger -from ubuntutools import subprocess - -if sys.version_info[0] >= 3: - basestring = str - unicode = str +from contextlib import closing + +from pathlib import Path +from ubuntutools.config import UDTConfig +from ubuntutools.lp.lpapicache import (Launchpad, + Distribution, + PersonTeam, + Project, + SourcePackagePublishingHistory, + HTTPError) +from ubuntutools.lp.udtexceptions import (PackageNotFoundException, + SeriesNotFoundException, + PocketDoesNotExistError, + InvalidDistroValueError) +from ubuntutools.misc import (download, + download_bytes, + verify_file_checksum, + verify_file_checksums, + DownloadError, + NotFoundError) +from ubuntutools.version import Version -class DownloadError(Exception): - "Unable to pull a source package" - pass +import logging +Logger = logging.getLogger(__name__) class Dsc(debian.deb822.Dsc): @@ -82,21 +88,12 @@ def verify_file(self, pathname): "Verify that pathname matches the checksums in the dsc" - if os.path.isfile(pathname): - alg, checksums = self.get_strongest_checksum() - size, digest = checksums[os.path.basename(pathname)] - if os.path.getsize(pathname) != size: - return False - hash_func = getattr(hashlib, alg)() - f = open(pathname, 'rb') - while True: - buf = f.read(hash_func.block_size) - if buf == b'': - break - hash_func.update(buf) - f.close() - return hash_func.hexdigest() == digest - return False + p = Path(pathname) + if not p.is_file(): + return False + alg, checksums = self.get_strongest_checksum() + size, digest = checksums[p.name] + return verify_file_checksum(p, alg, digest, size) def compare_dsc(self, other): """Check whether any files in these two dscs that have the same name @@ -122,66 +119,148 @@ return True -class SourcePackage(object): +class SourcePackage(ABC): """Base class for source package downloading. Use DebianSourcePackage or UbuntuSourcePackage instead of using this directly. """ - distribution = None + + @property + @abstractmethod + def distribution(self): + return None + + @property + def spph_class(self): + return SourcePackagePublishingHistory def __init__(self, package=None, version=None, component=None, - dscfile=None, lp=None, mirrors=(), workdir='.', quiet=False): - "Can be initialised either using package, version or dscfile" - assert ((package is not None and version is not None) - or dscfile is not None) + *args, **kwargs): + """Can be initialised using either package or dscfile. + If package is specified, either the version or series can also be + specified; using version will get the specific package version, + while using the series will get the latest version from that series. + Specifying only the package with no version or series will get the + latest version from the development series. + """ + dscfile = kwargs.get('dscfile') + mirrors = kwargs.get('mirrors', ()) + workdir = kwargs.get('workdir') + series = kwargs.get('series') + pocket = kwargs.get('pocket') + status = kwargs.get('status') + verify_signature = kwargs.get('verify_signature', False) + try_binary = kwargs.get('try_binary', True) + + assert (package is not None or dscfile is not None) + + if 'lp' in kwargs: + # deprecated - please don't use this; if you want to use an + # existing lp object, just call login_existing() directly + Logger.warning("Deprecation warning: please don't pass 'lp' to SourcePackage") + if not Launchpad.logged_in: + Launchpad.login_existing(kwargs['lp']) self.source = package - self._lp = lp - self.workdir = workdir - self.quiet = quiet + self.binary = None + self.try_binary = try_binary + self.workdir = Path(workdir) if workdir else Path('.') + self._series = series + self._pocket = pocket + self._status = status + self._dsc_source = Path(dscfile) if dscfile else None + self._verify_signature = verify_signature # Cached values: + self._distribution = None self._component = component self._dsc = None self._spph = None - - # State: - self._dsc_fetched = False + self._version = Version(version) if version else None # Mirrors - self._dsc_source = dscfile - self.mirrors = list(mirrors) - if self.distribution: - self.masters = [UDTConfig.defaults['%s_MIRROR' - % self.distribution.upper()]] - if dscfile is not None: - if self.source is None: - self.source = 'unknown' - if version is None: - version = 'unknown' - - self.version = debian.debian_support.Version(version) - - # uses default proxies from the environment - proxy = ProxyHandler() - self.url_opener = build_opener(proxy) + self.mirrors = list(filter(None, mirrors)) + self.masters = list(filter(None, + [UDTConfig.defaults.get(f'{self.distribution.upper()}_{suffix}') + for suffix in ["MIRROR", "PORTS_MIRROR", "INTERNAL_MIRROR"]])) + + # If provided a dscfile, process it now to set our source and version + if self._dsc_source: + self._dsc = Dsc(download_bytes(self._dsc_source)) + self.source = self._dsc['Source'] + self._version = Version(self._dsc['Version']) + self._check_dsc_signature() @property def lp_spph(self): "Return the LP Source Package Publishing History entry" - if not self._spph: - if not Launchpad.logged_in: - if self._lp: - Launchpad.login_existing(self._lp) - else: - Launchpad.login_anonymously() - spph = Distribution(self.distribution).getArchive().getPublishedSources( - source_name=self.source, - version=self.version.full_version, - exact_match=True, - ) - self._spph = SourcePackagePublishingHistory(spph[0]) - return self._spph + if self._spph: + return self._spph + + archive = self.getArchive() + params = {} + if self._version: + # if version was specified, use that + params['version'] = self._version.full_version + elif self._series: + # if version not specified, get the latest from this series + params['series'] = self._series + # note that if not specified, pocket defaults to all EXCEPT -backports + if self._pocket: + params['pocket'] = self._pocket + else: + # We always want to search all series, if not specified + params['search_all_series'] = True + + params['status'] = self._status + + try: + self._spph = archive.getSourcePackage(self.source, + wrapper=self.spph_class, + **params) + return self._spph + except PackageNotFoundException as pnfe: + if not self.try_binary or self.binary: + # either we don't need to bother trying binary name lookup, + # or we've already tried + raise pnfe + + Logger.info('Source package lookup failed, ' + 'trying lookup of binary package %s' % self.source) + + try: + bpph = archive.getBinaryPackage(self.source, **params) + except PackageNotFoundException as bpnfe: + # log binary lookup failure, in case it provides hints + Logger.info(str(bpnfe)) + # raise the original exception for the source lookup + raise pnfe + + self.binary = self.source + self.source = bpph.getSourcePackageName() + Logger.info("Using source package '{}' for binary package '{}'" + .format(self.source, self.binary)) + + spph = bpph.getBuild().getSourcePackagePublishingHistory() + if spph: + self._spph = self.spph_class(spph.self_link) + return self._spph + + # binary build didn't include source link, unfortunately + # so try again with the updated self.source name + if not self._version: + # Get version first if user didn't specify it, as some + # binaries have their version hardcoded in their name, + # such as the kernel package + self._version = Version(bpph.getVersion()) + return self.lp_spph + + @property + def version(self): + "Return Package version" + if not self._version: + self._version = Version(self.lp_spph.getVersion()) + return self._version @property def component(self): @@ -194,193 +273,204 @@ @property def dsc_name(self): "Return the source package dsc filename for the given package" - version = self.version.upstream_version - if self.version.debian_version: - version += '-' + self.version.debian_version - return '%s_%s.dsc' % (self.source, version) + return f'{self.source}_{self.version.strip_epoch()}.dsc' @property def dsc_pathname(self): "Return the dsc_name, with the workdir path" - return os.path.join(self.workdir, self.dsc_name) + return str(self.workdir / self.dsc_name) @property def dsc(self): - "Return a the Dsc" - if self._dsc is None: - self.pull_dsc() + "Return the Dsc" + if not self._dsc: + if self._dsc_source: + raise RuntimeError('Internal error: we have a dsc file but dsc not set') + urls = self._source_urls(self.dsc_name) + with tempfile.TemporaryDirectory() as d: + tmpdsc = Path(d) / self.dsc_name + self._download_file_from_urls(urls, tmpdsc) + self._dsc = Dsc(tmpdsc.read_bytes()) + self._check_dsc_signature() return self._dsc - def _mirror_url(self, mirror, filename): + def getDistribution(self): + if not self._distribution: + self._distribution = Distribution(self.distribution) + return self._distribution + + def getArchive(self): + return self.getDistribution().getArchive() + + def _mirror_url(self, mirror, component, filename): "Build a source package URL on a mirror" if self.source.startswith('lib'): group = self.source[:4] else: group = self.source[0] - return os.path.join(mirror, 'pool', self.component, group, + return os.path.join(mirror, 'pool', component, group, self.source, filename) - def _lp_url(self, filename): - "Build a source package URL on Launchpad" - return os.path.join('https://launchpad.net', self.distribution, - '+archive', 'primary', '+files', filename) + def _archive_servers(self): + "Generator for mirror and master servers" + # Always provide the mirrors first + for server in self.mirrors: + yield server + # Don't repeat servers that are in both mirrors and masters + for server in set(self.masters) - set(self.mirrors): + yield server def _source_urls(self, name): "Generator of sources for name" if self._dsc_source: - yield os.path.join(os.path.dirname(self._dsc_source), name) - for mirror in self.mirrors: - yield self._mirror_url(mirror, name) - for mirror in self.masters: - if mirror not in self.mirrors: - yield self._mirror_url(mirror, name) - yield self._lp_url(name) - - def pull_dsc(self): - "Retrieve dscfile and parse" - if self._dsc_source: - parsed = urlparse(self._dsc_source) - if parsed.scheme == '': - self._dsc_source = 'file://' + os.path.abspath(self._dsc_source) - parsed = urlparse(self._dsc_source) - url = self._dsc_source - else: - url = self._lp_url(self.dsc_name) - self._download_dsc(url) - - self._check_dsc() - - def _download_dsc(self, url): - "Download specified dscfile and parse" - parsed = urlparse(url) - if parsed.scheme == 'file': - with open(parsed.path, 'r') as f: - body = f.read() - else: - try: - response, body = httplib2.Http().request(url) - except httplib2.HttpLib2Error as e: - raise DownloadError(e) - if response.status != 200: - raise DownloadError("%s: %s %s" % (url, response.status, - response.reason)) - self._dsc = Dsc(body) - self._dsc_fetched = True - - def _check_dsc(self, verify_signature=False): - "Check that the dsc matches what we are expecting" - assert self._dsc is not None - self.source = self.dsc['Source'] - self.version = debian.debian_support.Version(self.dsc['Version']) - - valid = False - message = None - gpg_info = None + yield str(self._dsc_source.parent / name) + for server in self._archive_servers(): + yield self._mirror_url(server, self.component, name) + if self.lp_spph.sourceFileUrl(name): + yield self.lp_spph.sourceFileUrl(name) + + def _binary_urls(self, name, bpph): + "Generator of URLs for name" + for server in self._archive_servers(): + yield self._mirror_url(server, bpph.getComponent(), name) + if bpph.binaryFileUrl(name): + yield bpph.binaryFileUrl(name) + if bpph.getUrl(): + yield bpph.getUrl() + + def _check_dsc_signature(self): + "Check that the dsc signature matches what we are expecting" + if not self._verify_signature: + return try: - gpg_info = self.dsc.get_gpg_info() - valid = gpg_info.valid() + gpg_info = self.dsc.get_gpg_info(( + '/usr/share/keyrings/debian-keyring.gpg', + '/usr/share/keyrings/debian-maintainers.gpg', + )) except IOError: - message = ('Signature on %s could not be verified, install ' - 'debian-keyring' % self.dsc_name) - if message is None: - if valid: - message = 'Valid signature' - else: - message = ('Signature on %s could not be verified' - % self.dsc_name) - if gpg_info is not None: + Logger.debug('Signature on %s could not be verified, install ' + 'debian-keyring' % self.dsc_name) + return + if gpg_info.valid(): if 'GOODSIG' in gpg_info: - message = ('Good signature by %s (0x%s)' - % (gpg_info['GOODSIG'][1], gpg_info['GOODSIG'][0])) + Logger.info('Good signature by %s (0x%s)' + % (gpg_info['GOODSIG'][1], gpg_info['GOODSIG'][0])) elif 'VALIDSIG' in gpg_info: - message = 'Valid signature by 0x%s' % gpg_info['VALIDSIG'][0] - if verify_signature: - if valid: - Logger.normal(message) + Logger.info('Valid signature by 0x%s' % gpg_info['VALIDSIG'][0]) else: - Logger.error(message) - raise DownloadError(message) + Logger.info('Valid signature') + elif 'NO_PUBKEY' in gpg_info: + Logger.warning('Public key not found, could not verify signature') + elif 'NODATA' in gpg_info: + Logger.warning('Package is not signed') else: - Logger.info(message) + Logger.warning('Signature on %s could not be verified' % self.dsc_name) - def _write_dsc(self): - "Write dsc file to workdir" - if self._dsc is None: - self.pull_dsc() - with open(self.dsc_pathname, 'wb') as f: - f.write(self.dsc.raw_text) - - def _download_file(self, url, filename): - "Download url to filename in workdir." - pathname = os.path.join(self.workdir, filename) - if self.dsc.verify_file(pathname): - Logger.debug('Using existing %s', filename) - return True - size = [entry['size'] for entry in self.dsc['Files'] - if entry['name'] == filename] - assert len(size) == 1 - size = int(size[0]) - parsed = urlparse(url) - if not self.quiet: - Logger.normal('Downloading %s from %s (%0.3f MiB)', - filename, parsed.hostname, size / 1024.0 / 1024) + def _verify_file(self, pathname, dscverify=False, sha1sum=None, sha256sum=None, size=0): + p = Path(pathname) + if not p.exists(): + return False + if dscverify and not self.dsc.verify_file(p): + return False + checksums = {} + if sha1sum: + checksums['SHA1'] = sha1sum + if sha256sum: + checksums['SHA256'] = sha256sum + if not verify_file_checksums(p, checksums, size): + return False + return True - if parsed.scheme == 'file': - in_ = open(parsed.path, 'rb') + def _download_file(self, url, filename, size=0, dscverify=False, sha1sum=None, sha256sum=None): + "Download url to filename; will be put in workdir unless filename is absolute path." + if Path(filename).is_absolute(): + p = Path(filename).expanduser().resolve() else: + p = self.workdir / filename + + can_verify = any((dscverify, sha1sum, sha256sum)) + if can_verify and self._verify_file(p, dscverify, sha1sum, sha256sum, size): + Logger.info(f'Using existing file {p}') + return True + + download(url, p, size) + + return self._verify_file(p, dscverify, sha1sum, sha256sum, size) + + def _download_file_from_urls(self, urls, filename, size=0, dscverify=False, + sha1sum=None, sha256sum=None): + "Try to download a file from a list of urls." + for url in urls: try: - in_ = self.url_opener.open(url) - except URLError: - return False + if self._download_file(url, filename, size, dscverify=dscverify, + sha1sum=sha1sum, sha256sum=sha256sum): + return + except NotFoundError: + # It's ok if the file isn't found, just try the next url + Logger.debug(f'File not found at {url}') + except DownloadError as e: + Logger.error(f'Download Error: {e}') + raise DownloadError(f'Failed to download {filename}') - downloaded = 0 - bar_width = 60 - try: - with open(pathname, 'wb') as out: - while True: - block = in_.read(10240) - if block == b'': - break - downloaded += len(block) - out.write(block) - if not self.quiet: - percent = downloaded * 100 // size - bar = '=' * int(round(downloaded * bar_width / size)) - bar = (bar + '>' + ' ' * bar_width)[:bar_width] - Logger.stdout.write('[%s] %#3i%%\r' % (bar, percent)) - Logger.stdout.flush() - in_.close() - finally: - if not self.quiet: - Logger.stdout.write(' ' * (bar_width + 7) + '\r') - Logger.stdout.flush() - if not self.dsc.verify_file(pathname): - Logger.error('Checksum for %s does not match.', filename) - return False - return True + def pull_dsc(self): + '''DEPRECATED + + This method is badly named and historically has only 'pulled' the + dsc into memory, not actually to a file. Since the other 'pull' methods + actually 'pull' to real files, this method makes no sense; additionally + there is no need for this method since we can 'pull' the dsc into + memory when the .dsc property is accessed. + + This method no longer does anything at all and should not be used by + anyone. + ''' + Logger.debug('Please fix your program: the "pull_dsc" method is deprecated') def pull(self): "Pull into workdir" - self._write_dsc() + Path(self.dsc_pathname).write_bytes(self.dsc.raw_text) for entry in self.dsc['Files']: name = entry['name'] - for url in self._source_urls(name): - try: - if self._download_file(url, name): - break - except HTTPError as e: - Logger.normal('HTTP Error %i: %s', e.code, str(e)) - except URLError as e: - Logger.normal('URL Error: %s', e.reason) - else: - raise DownloadError('File %s could not be found' % name) + urls = self._source_urls(name) + self._download_file_from_urls(urls, name, int(entry['size']), dscverify=True) + + def pull_binaries(self, arch=None, name=None, ext=None): + """Pull binary debs into workdir. + If name is specified, only binary packages matching the regex are included. + + If ext is specified, only binary packages with that ext are included; for + example to only download dbgsym ddebs, specify ext='ddeb'. + + If arch is not specified or is 'all', pull all archs. + + Returns the number of files downloaded. + """ + Logger.debug("pull_binaries(arch=%s, name=%s, ext=%s)" % (arch, name, ext)) + + if arch == 'all': + arch = None + + total = 0 + for bpph in self.lp_spph.getBinaries(arch=arch, name=name, ext=ext): + fname = bpph.getFileName() + fsha1 = bpph.binaryFileSha1(fname) + fsha256 = bpph.binaryFileSha256(fname) + fsize = bpph.binaryFileSize(fname) + urls = self._binary_urls(fname, bpph) + try: + self._download_file_from_urls(urls, fname, fsize, + sha1sum=fsha1, sha256sum=fsha256) + total += 1 + except DownloadError as e: + # log/print the error, but continue to get the rest of the files + Logger.error(e) + return total def verify(self): """Verify that the source package in workdir matches the dsc. Return boolean """ - return all(self.dsc.verify_file(os.path.join(self.workdir, - entry['name'])) + return all(self.dsc.verify_file(self.workdir / entry['name']) for entry in self.dsc['Files']) def verify_orig(self): @@ -388,8 +478,7 @@ Return boolean """ orig_re = re.compile(r'.*\.orig(-[^.]+)?\.tar\.[^.]+$') - return all(self.dsc.verify_file(os.path.join(self.workdir, - entry['name'])) + return all(self.dsc.verify_file(self.workdir / entry['name']) for entry in self.dsc['Files'] if orig_re.match(entry['name'])) @@ -398,10 +487,12 @@ cmd = ['dpkg-source', '-x', self.dsc_name] if destdir: cmd.append(destdir) - Logger.command(cmd) - if subprocess.call(cmd, cwd=self.workdir): + Logger.debug(' '.join(cmd)) + result = subprocess.run(cmd, cwd=str(self.workdir), encoding='utf-8', + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if result.returncode != 0: Logger.error('Source unpack failed.') - sys.exit(1) + Logger.debug(result.stdout) def debdiff(self, newpkg, diffstat=False): """Write a debdiff comparing this src pkg to a newer one. @@ -410,164 +501,752 @@ """ cmd = ['debdiff', self.dsc_name, newpkg.dsc_name] difffn = newpkg.dsc_name[:-3] + 'debdiff' - Logger.command(cmd + ['> %s' % difffn]) + Logger.debug(' '.join(cmd) + ('> %s' % difffn)) with open(difffn, 'w') as f: - if subprocess.call(cmd, stdout=f, cwd=self.workdir) > 2: + if subprocess.call(cmd, stdout=f, cwd=str(self.workdir)) > 2: Logger.error('Debdiff failed.') sys.exit(1) if diffstat: cmd = ('diffstat', '-p1', difffn) - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd): Logger.error('diffstat failed.') sys.exit(1) return os.path.abspath(difffn) +class DebianSPPH(SourcePackagePublishingHistory): + """SPPH with getBinaries() overridden, + as LP doesn't have Debian binaries + """ + resource_type = 'source_package_publishing_history' + + def __init__(self, *args, **kwargs): + super(DebianSPPH, self).__init__(*args, **kwargs) + self._srcpkg = None + + def getBinaries(self, arch=None, name=None, ext=None): + if not self._srcpkg: + Logger.info('Using Snapshot to find binary packages') + self._srcpkg = Snapshot.getSourcePackage(self.getPackageName(), + version=self.getVersion()) + return self._srcpkg.getSPPH().getBinaries(arch=arch, name=name, ext=ext) + + class DebianSourcePackage(SourcePackage): "Download / unpack a Debian source package" - distribution = 'debian' + + @property + def distribution(self): + return 'debian' + + @property + def spph_class(self): + return DebianSPPH def __init__(self, *args, **kwargs): super(DebianSourcePackage, self).__init__(*args, **kwargs) self.masters.append(UDTConfig.defaults['DEBSEC_MIRROR']) + # Cached values: - self._snapshot_list = None + self._snapshot_package = None + self._snapshot_files = None + # Don't bother searching in LP for debian binaries, they aren't there + self.try_binary = False + + # Debian doesn't have 'pockets' + if self._pocket: + if self._pocket.lower() != 'release': + Logger.error("Debian does not use 'pockets', ignoring pocket '%s'", + self._pocket) + self._pocket = None - # Overridden methods: + # Overridden properties/methods: @property def lp_spph(self): "Return the LP Source Package Publishing History entry" if not self._spph: try: + # superclass will set self._spph return super(DebianSourcePackage, self).lp_spph - except IndexError: + except PackageNotFoundException: + pass + except SeriesNotFoundException: pass - Logger.normal('Using rmadison for component determination') - comp = 'main' - for record in rmadison(self.distribution, self.source): - if record.get('source') != self.source: - continue - comp = record['component'] - if record['version'] == self.version.full_version: - self._spph = FakeSPPH(record['source'], record['version'], - comp, 'debian') - return self._spph - - Logger.normal('Guessing component from most recent upload') - self._spph = FakeSPPH(self.source, self.version.full_version, comp, - 'debian') + Logger.info('Package not found in Launchpad, using Snapshot') + self._spph = self.snapshot_package.getSPPH() return self._spph + @property + def component(self): + "Cached archive component, in available" + if not self._component: + Logger.debug('Determining component from Snapshot') + self._component = Snapshot.getComponent(self.source, self.version) + return self._component + def _source_urls(self, name): "Generator of sources for name" - wrapped_iterator = super(DebianSourcePackage, self)._source_urls(name) - while True: - try: - yield next(wrapped_iterator) - except StopIteration: - break - if self.snapshot_list: - yield self._snapshot_url(name) - - def pull_dsc(self): - "Retrieve dscfile and parse" - try: - super(DebianSourcePackage, self).pull_dsc() - return - except DownloadError: - pass - - # Not all Debian Source packages get imported to LP - # (or the importer could be lagging) - for url in self._source_urls(self.dsc_name): - try: - self._download_dsc(url) - except DownloadError: - continue - break - else: - raise DownloadError('dsc could not be found anywhere') - self._check_dsc(verify_signature=True) + for url in super(DebianSourcePackage, self)._source_urls(name): + yield url + if name in self.snapshot_files: + yield self.snapshot_files[name] # Local methods: @property - def snapshot_list(self): - "Return a filename -> hash dictionary from snapshot.debian.org" - if self._snapshot_list is None: - try: - import json - except ImportError: - import simplejson as json - except ImportError: - Logger.error("Please install python-simplejson.") - raise DownloadError("Unable to dowload from " - "snapshot.debian.org without " - "python-simplejson") + def snapshot_package(self): + if not self._snapshot_package: + if self._version or self._spph: + # as .version uses .lpph, and our .lpph might use us, + # only use .version if _version or _spph are set + version = self.version.full_version + srcpkg = Snapshot.getSourcePackage(self.source, version=version) + if not srcpkg: + msg = "Package {} {} not found".format(self.source, version) + raise PackageNotFoundException(msg) + self._snapshot_package = srcpkg + else: + # we have neither version nor spph, so look up our version using madison + Logger.info('Using madison to find latest version number') + series = self._series + params = {'series': series} if series else {} + srcpkg = Madison(self.distribution).getSourcePackage(self.source, **params) + if not srcpkg: + raise PackageNotFoundException("Package {} not found".format(self.source)) + if self.source != srcpkg.name: + self.binary = self.source + self.source = srcpkg.name + self._snapshot_package = srcpkg + return self._snapshot_package - try: - data = self.url_opener.open( - 'http://snapshot.debian.org/mr/package/%s/%s/srcfiles?fileinfo=1' % - (self.source, self.version.full_version)) - reader = codecs.getreader('utf-8') - srcfiles = json.load(reader(data)) - - except HTTPError: - Logger.error('Version %s of %s not found on ' - 'snapshot.debian.org', - self.version.full_version, self.source) - self._snapshot_list = False - return False - self._snapshot_list = dict((info[0]['name'], hash_) - for hash_, info - in srcfiles['fileinfo'].items()) - return self._snapshot_list - - def _snapshot_url(self, name): - "Return the snapshot.debian.org URL for name" - return os.path.join('http://snapshot.debian.org/file', - self.snapshot_list[name]) + @property + def snapshot_files(self): + if not self._snapshot_files: + files = self.snapshot_package.getFiles() + self._snapshot_files = {f.name: f.getUrl() for f in files} + return self._snapshot_files class UbuntuSourcePackage(SourcePackage): "Download / unpack an Ubuntu source package" - distribution = 'ubuntu' + @property + def distribution(self): + return 'ubuntu' + + +class PersonalPackageArchiveSourcePackage(UbuntuSourcePackage): + "Download / unpack an Ubuntu Personal Package Archive source package" + def __init__(self, *args, **kwargs): + super(PersonalPackageArchiveSourcePackage, self).__init__(*args, **kwargs) + assert 'ppa' in kwargs + ppa = kwargs['ppa'].split('/') + if len(ppa) != 2: + raise ValueError('Invalid PPA value "%s",' + 'must be "/"' % kwargs['ppa']) + self._teamname = ppa[0] + self._ppaname = ppa[1] + self.masters = [] + + @property + @functools.lru_cache(maxsize=None) + def team(self): + try: + return PersonTeam.fetch(self._teamname) + except KeyError: + raise ValueError(f"No user/team '{self._teamname}' found on Launchpad") + + @functools.lru_cache() + def getArchive(self): + ppa = self.team.getPPAByName(self._ppaname) + Logger.debug(f"Using PPA '{ppa.web_link}'") + return ppa + + def _private_ppa_url(self, filename): + "Format the URL for a filename using the private PPA server" + url = self.getArchive().getMySubscriptionURL() + pkg = self.source + subdir = pkg[:4] if pkg.startswith('lib') else pkg[:1] + return f'{url}/pool/main/{subdir}/{pkg}/{filename}' + + def _source_urls(self, name): + "Generator of sources for name" + if self.getArchive().private: + yield self._private_ppa_url(name) + else: + yield from super()._source_urls(name) -class UbuntuCloudArchiveSourcePackage(UbuntuSourcePackage): + def _binary_urls(self, name, bpph): + "Generator of URLs for name" + if self.getArchive().private: + yield self._private_ppa_url(name) + else: + yield from super()._binary_urls(name, bpph) + + +class UbuntuCloudArchiveSourcePackage(PersonalPackageArchiveSourcePackage): "Download / unpack an Ubuntu Cloud Archive source package" - def __init__(self, uca_release, *args, **kwargs): + TEAM = 'ubuntu-cloud-archive' + PROJECT = 'cloud-archive' + VALID_POCKETS = ['updates', 'proposed', 'staging'] + + def __init__(self, *args, **kwargs): + # Need to determine actual series/pocket ppa now, as it affects getArchive() + (series, pocket) = self._findReleaseAndPocketForPackage(kwargs.get('series'), + kwargs.get('pocket'), + kwargs.get('package'), + kwargs.get('version')) + # Drop series/pocket from kwargs, as UCA handles them completely different and we + # don't want to pass them up to the superclass + kwargs.pop('series', None) + orig_pocket = kwargs.pop('pocket', None) + if orig_pocket and orig_pocket != pocket and pocket == 'staging': + Logger.info(f"Ubuntu Cloud Archive release '{series}' pocket '{orig_pocket}'" + " PPA is not public, using 'staging' pocket instead") + + kwargs['ppa'] = f"{self.TEAM}/{series}-{pocket}" super(UbuntuCloudArchiveSourcePackage, self).__init__(*args, **kwargs) - self._uca_release = uca_release - self.masters = ["http://ubuntu-cloud.archive.canonical.com/ubuntu/"] - def _lp_url(self, filename): - "Build a source package URL on Launchpad" - return os.path.join('https://launchpad.net', "~ubuntu-cloud-archive", - '+archive', ("%s-staging" % self._uca_release), - '+files', filename) + if pocket == 'staging': + # Don't bother with the archive; just get directly from the staging ppa, since + # none of the binaries from the archive will match the staging checksums + self.masters = [] + else: + self.masters = ["http://ubuntu-cloud.archive.canonical.com/ubuntu/"] + def pull_binaries(self, arch=None, name=None, ext=None): + """Pull binary debs into workdir. -class FakeSPPH(object): - """Provide the same interface as - ubuntutools.lpapicache.SourcePackagePublishingHistory - """ - def __init__(self, name, version, component, distribution): + This is only a wrapper around the superclass method, to log warning if + pulling binaries when using a 'staging' ppa, since the published binaries + will not match the 'staging' binaries. + """ + if self._ppaname.endswith('-staging'): + Logger.warning("Binaries from 'staging' pocket will not match published binaries; " + "see https://bugs.launchpad.net/cloud-archive/+bug/1649979") + return super(UbuntuCloudArchiveSourcePackage, self).pull_binaries(arch, name, ext) + + @classmethod + @functools.lru_cache() + def getUbuntuCloudArchiveProject(cls): + return Project(cls.PROJECT) + + @classmethod + def getUbuntuCloudArchiveReleaseNames(cls): + """Get list of the main UCA release names + + The list will be sorted in descending chronological order. + """ + return [s.name for s in cls.getUbuntuCloudArchiveProject().series] + + @classmethod + def ppas(cls): + """DEPRECATED: use getUbuntuCloudArchiveReleaseNames()""" + return cls.getUbuntuCloudArchiveReleaseNames() + + @classmethod + def isValidRelease(cls, release): + return release in cls.getUbuntuCloudArchiveReleaseNames() + + @classmethod + def getDevelSeries(cls): + """Get the current UCA devel release name""" + return cls.getUbuntuCloudArchiveReleaseNames()[0] + + @classmethod + @functools.lru_cache() + def getUbuntuCloudArchiveTeam(cls): + return PersonTeam.fetch(cls.TEAM) + + @classmethod + @functools.lru_cache() + def getUbuntuCloudArchivePPAs(cls, release=None, pocket=None): + """ Get sorted list of UCA ppa Archive objects + + If release and/or pocket are specified, the list will be + filtered to return only matching ppa(s). + + This list will only contain ppas relevant to UCA releases; + it will not contain 'other' ppas, e.g. 'cloud-tools-next'. + """ + if not any((release, pocket)): + all_ppas = cls.getUbuntuCloudArchiveTeam().getPPAs() + ppas = [] + for r in cls.getUbuntuCloudArchiveReleaseNames(): + for p in cls.VALID_POCKETS: + name = f"{r}-{p}" + if name in all_ppas: + ppas.append(all_ppas[name]) + return ppas + + # Use recursive call without params to get the lru-cached list of ppas returned above + ppas = cls.getUbuntuCloudArchivePPAs() + if release: + ppas = list(filter(lambda p: p.name.partition('-')[0] == release, ppas)) + if pocket: + ppas = list(filter(lambda p: p.name.partition('-')[2] == pocket, ppas)) + if not ppas: + rname = release or '*' + pname = pocket or '*' + raise SeriesNotFoundException(f"UCA release '{rname}-{pname}' not found") + return ppas + + @classmethod + def parseReleaseAndPocket(cls, release): + """Parse the UCA release and pocket for the given string. + + We allow 'release' to be specified as: + 1. UCARELEASE + 2. UCARELEASE-POCKET + 3. UBUNTURELEASE-UCARELEASE + 4. UBUNTURELEASE-UCARELEASE-POCKET + 5. UBUNTURELEASE-POCKET/UCARELEASE + The UBUNTURELEASE is a standard Ubuntu release name, e.g. 'focal', + however it is NOT checked for validity. + The UCARELEASE is a standard Ubuntu Cloud Archive release name, e.g. 'train'. + The POCKET is limited to the standard pockets 'release', 'updates', or 'proposed', + or the special pocket 'staging'. The 'release' and 'updates' pockets are + equivalent (UCA has no 'release' pocket). + + This will return a tuple of (release, pocket), or (release, None) if no + pocket was specified. + + This will raise SeriesNotFoundException if the release and/or pocket were + not found. + """ + release = release.lower().strip() + + # Cases 1 and 2 + PATTERN1 = r'^(?P[a-z]+)(?:-(?P[a-z]+))?$' + # Cases 3 and 4 + PATTERN2 = r'^(?P[a-z]+)-(?P[a-z]+)(?:-(?P[a-z]+))?$' + # Case 5 + PATTERN3 = r'^(?P[a-z]+)-(?P[a-z]+)/(?P[a-z]+)$' + + for pattern in [PATTERN1, PATTERN2, PATTERN3]: + match = re.match(pattern, release) + if match: + r = match.group('ucarelease') + p = match.group('pocket') + # For UCA, there is no 'release' pocket, the default is 'updates' + if p and p == 'release': + Logger.warning("Ubuntu Cloud Archive does not use 'release' pocket," + " using 'updates' instead") + p = 'updates' + if (cls.isValidRelease(r) and (not p or p in cls.VALID_POCKETS)): + Logger.debug(f"Using Ubuntu Cloud Archive release '{r}'") + return (r, p) + raise SeriesNotFoundException(f"Ubuntu Cloud Archive release '{release}' not found") + + @classmethod + def _findReleaseAndPocketForPackage(cls, release, pocket, package, version): + if release and release not in cls.getUbuntuCloudArchiveReleaseNames(): + raise SeriesNotFoundException(f"Ubuntu Cloud Archive release '{release}' not found") + if pocket and pocket not in cls.VALID_POCKETS: + raise PocketDoesNotExistError(f"Ubuntu Cloud Archive pocket '{pocket}' is invalid") + DEFAULT = tuple(cls.getUbuntuCloudArchivePPAs(release=release or cls.getDevelSeries())[0] + .name.split('-', maxsplit=1)) + if not package: + # not much we can do without a package name + return DEFAULT + checked_pocket = False + for ppa in cls.getUbuntuCloudArchivePPAs(release=release): + if pocket and pocket != ppa.name.partition('-')[2]: + # If pocket is specified, only look at the requested pocket, or 'later' + # This allows using the 'staging' pocket for old releases that do not + # provide any 'updates' or 'proposed' pockets + if not checked_pocket: + continue + checked_pocket = True + params = {'exact_match': True, 'source_name': package} + if version: + params['version'] = version + if ppa.getPublishedSources(**params): + (r, _, p) = ppa.name.partition('-') + return (r, p) + # package/version not found in any ppa + return DEFAULT + + +class _WebJSON(object): + def getHostUrl(self): + raise Exception("Not implemented") + + def load(self, path=''): + reader = codecs.getreader('utf-8') + url = self.getHostUrl() + path + Logger.debug("Loading %s" % url) + with closing(urlopen(url)) as data: + return json.load(reader(data)) + + +# DAKweb madison API +# https://github.com/Debian/dak/blob/master/dakweb/queries/madison.py +# This is really only useful to easily find the latest version of a +# package for a specific series (or unstable). This does not provide +# any details at all for older-than-latest package versions. +class Madison(_WebJSON): + urls = { + 'debian': 'https://api.ftp-master.debian.org/madison', + 'ubuntu': 'http://people.canonical.com/~ubuntu-archive/madison.cgi', + } + + def __init__(self, distro='debian'): + super(Madison, self).__init__() + self._distro = distro + # This currently will NOT work with ubuntu; it doesn't support f=json + if distro != 'debian': + raise InvalidDistroValueError("Madison currently only supports Debian") + + def getHostUrl(self): + return self.urls[self._distro] + + def getSourcePackage(self, name, series='unstable'): + url = "?f=json&package={name}&s={series}".format(name=name, series=series) + try: + result = self.load(url) + except HTTPError: + result = None + if not result: + msg = "Package {} not found in '{}'".format(name, series) + raise PackageNotFoundException(msg) + versions = list(result[0][name].values())[0] + latest = versions[sorted(versions.keys(), reverse=True)[0]] + return Snapshot.getSourcePackage(name=latest['source'], + version=latest['source_version']) + + +# Snapshot API +# https://anonscm.debian.org/cgit/mirror/snapshot.debian.org.git/plain/API +class _Snapshot(_WebJSON): + DEBIAN_COMPONENTS = ["main", "contrib", "non-free"] + + def getHostUrl(self): + return "http://snapshot.debian.org" + + def getComponent(self, name, version): + # unfortunately there is no (easy) way to find the component for older + # package versions (madison only lists the most recent versions). + # so we have to parse the file path to determine the component :( + url = "/mr/package/{}/{}/srcfiles".format(name, version) + try: + response = self.load("{}?fileinfo=1".format(url)) + except HTTPError: + msg = "Package {} version {} not found" + raise PackageNotFoundException(msg.format(name, version)) + result = response.get('result') + info = response.get('fileinfo') + if len(result) < 1: + msg = "No source files for package {} version {}" + raise PackageNotFoundException(msg.format(name, version)) + path = info[result[0]['hash']][0]['path'] + # this expects the 'component' to follow 'pool[-*]' in the path + found_pool = False + component = None + for s in path.split('/'): + if found_pool: + component = s + break + if s.startswith('pool'): + found_pool = True + if not component: + Logger.warning("could not determine component from path %s" % path) + return self.DEBIAN_COMPONENTS[0] + if component not in self.DEBIAN_COMPONENTS: + Logger.warning("unexpected component %s" % component) + return component + + def _get_package(self, name, url, pkginit, version, sort_key): + try: + results = self.load("/mr/{}/{}/".format(url, name))['result'] + except HTTPError: + raise PackageNotFoundException("Package {} not found.".format(name)) + + results = sorted(results, key=lambda r: r[sort_key], reverse=True) + results = [pkginit(r) for r in results if version == r['version']] + if not results: + msg = "Package {name} version {version} not found." + raise PackageNotFoundException(msg.format(name=name, version=version)) + return results + + def getSourcePackages(self, name, version): + return self._get_package(name, "package", + lambda obj: SnapshotSourcePackage(obj, name), + version, "version") + + def getSourcePackage(self, name, version): + return self.getSourcePackages(name, version)[0] + + def getBinaryPackages(self, name, version): + return self._get_package(name, "binary", + lambda obj: SnapshotBinaryPackage(obj), + version, "binary_version") + + def getBinaryPackage(self, name, version): + return self.getBinaryPackages(name, version)[0] + + +Snapshot = _Snapshot() + + +class SnapshotPackage(object): + def __init__(self, obj): + self._obj = obj + self._files = None + self._component = None + + @property + def version(self): + return self._obj['version'] + + @property + def component(self): + if not self._component: + self._component = Snapshot.getComponent(self.name, self.version) + return self._component + + +class SnapshotSourcePackage(SnapshotPackage): + def __init__(self, obj, name): + # obj required fields: 'version' + super(SnapshotSourcePackage, self).__init__(obj) self.name = name - self.version = version + self._binary_files = None + self._spph = None + + def getSPPH(self): + if not self._spph: + self._spph = SnapshotSPPH(self) + return self._spph + + def getAllFiles(self): + return self.getFiles() + self.getBinaryFiles() + + def getBinaryFiles(self, arch=None, name=None, ext=None): + if not self._binary_files: + url = "/mr/package/{}/{}/allfiles".format(self.name, self.version) + response = Snapshot.load("{}?fileinfo=1".format(url)) + info = response['fileinfo'] + files = [SnapshotBinaryFile(b['name'], b['version'], self.component, + info[r['hash']][0], r['hash'], + r['architecture'], self.name) + for b in response['result']['binaries'] for r in b['files']] + self._binary_files = files + bins = list(self._binary_files) + if arch: + bins = [b for b in bins if b.isArch(arch)] + if name: + bins = [b for b in bins if re.match(name, b.package_name)] + if ext: + bins = [b for b in bins if re.match(ext, b.ext)] + return bins + + def getFiles(self): + if not self._files: + url = "/mr/package/{}/{}/srcfiles".format(self.name, self.version) + response = Snapshot.load("{}?fileinfo=1".format(url)) + info = response['fileinfo'] + self._files = [SnapshotSourceFile(self.name, self.version, self.component, + info[r['hash']][0], r['hash']) + for r in response['result']] + return list(self._files) + + +class SnapshotBinaryPackage(SnapshotPackage): + def __init__(self, obj): + # obj required fields: 'version', 'binary_version', 'name', 'source' + super(SnapshotBinaryPackage, self).__init__(obj) + + @property + def name(self): + return self._obj['name'] + + @property + def binary_version(self): + return self._obj['binary_version'] + + @property + def source(self): + return self._obj['source'] + + def getBPPH(self, arch): + f = self.getFiles(arch) + if not f: + return None + if not arch: + raise RuntimeError("Must specify arch") + # Can only be 1 binary file for this pkg name/version/arch + return f[0].getBPPH() + + def getFiles(self, arch=None): + if not self._files: + url = "/mr/binary/{}/{}/binfiles".format(self.name, self.version) + response = Snapshot.load("{}?fileinfo=1".format(url)) + info = response['fileinfo'] + self._files = [SnapshotBinaryFile(self.name, self.version, self.component, + info[r['hash']][0], r['hash'], + r['architecture'], self.source) + for r in response['result']] + if not arch: + return list(self._files) + return [f for f in self._files if f.isArch(arch)] + + +class SnapshotFile(object): + def __init__(self, pkg_name, pkg_version, component, obj, h): + self.package_name = pkg_name + self.package_version = pkg_version self.component = component - self.distribution = distribution - self._changelog = None + self._obj = obj + self._hash = h + + @property + def getType(self): + return None + + @property + def archive_name(self): + return self._obj['archive_name'] + + @property + def name(self): + return self._obj['name'] + + @property + def ext(self): + return self.name.rpartition('.')[2] + + @property + def path(self): + return self._obj['path'] + + @property + def size(self): + return int(self._obj['size']) + + @property + def date(self): + if 'run' in self._obj: + return self._obj['run'] + elif 'first_seen' in self._obj: + return self._obj['first_seen'] + else: + Logger.error('File {} has no date information', self.name) + return 'unknown' + + def getHash(self): + return self._hash + + def getUrl(self): + return "{}/file/{}".format(Snapshot.getHostUrl(), self.getHash()) + + def __repr__(self): + return "{}/{} {} bytes {}".format(self.path, self.name, self.size, self.date) + + +class SnapshotSourceFile(SnapshotFile): + def __init__(self, name, version, component, obj, h): + super(SnapshotSourceFile, self).__init__(name, version, component, obj, h) + + def getType(self): + return 'source' + + +class SnapshotBinaryFile(SnapshotFile): + def __init__(self, name, version, component, obj, h, arch, source): + super(SnapshotBinaryFile, self).__init__(name, version, component, obj, h) + self.source = source + self.arch = arch + self._bpph = None + + def isArch(self, arch): + if not arch: + return True + if self.arch == 'all': + return True + return arch == self.arch + + def getType(self): + return 'binary' + + def getBPPH(self): + if not self._bpph: + self._bpph = SnapshotBPPH(self) + return self._bpph + + +class SnapshotSPPH(object): + """Provide the same interface as SourcePackagePublishingHistory""" + def __init__(self, snapshot_pkg): + self._pkg = snapshot_pkg + + # LP API defined fields + + @property + def component_name(self): + return self.getComponent() + + @property + def display_name(self): + return ("{name} {version}" + .format(name=self.getPackageName(), + version=self.getVersion())) + + @property + def pocket(self): + # Debian does not use 'pockets' + return 'Release' + + @property + def source_package_name(self): + return self.getPackageName() + + @property + def source_package_version(self): + return self.getVersion() + + # SPPH functions def getPackageName(self): - return self.name + return self._pkg.name def getVersion(self): - return self.version + return self._pkg.version def getComponent(self): - return self.component + return self._pkg.component + + def sourceFileUrls(self, include_meta=False): + if include_meta: + return [{'url': f.getUrl(), + 'filename': f.name, + 'sha1': f.getHash(), + 'sha256': None, + 'size': f.size} + for f in self._pkg.getFiles()] + return [f.getUrl() for f in self._pkg.getFiles()] + + def sourceFileUrl(self, filename): + for f in self.sourceFileUrls(include_meta=True): + if filename == f['filename']: + return f['url'] + return None + + def sourceFileSha1(self, url_or_filename): + for f in self.sourceFileUrls(include_meta=True): + if url_or_filename in [f['url'], f['filename']]: + return f['sha1'] + return None + + def sourceFileSha256(self, url_or_filename): + return None + + def sourceFileSize(self, url_or_filename): + for f in self.sourceFileUrls(include_meta=True): + if url_or_filename in [f['url'], f['filename']]: + return int(f['size']) + return 0 def getChangelog(self, since_version=None): ''' @@ -575,98 +1254,135 @@ May return None if the changelog isn't available ''' if self._changelog is None: - if self.name.startswith('lib'): - subdir = 'lib%s' % self.name[3] + name = self.getPackageName() + if name.startswith('lib'): + subdir = 'lib%s' % name[3] else: - subdir = self.name[0] - # Strip epoch from version - pkgversion = self.version.split(':', 1)[-1] - extension = '' - if self.distribution == 'debian': - base = 'http://packages.debian.org/' - extension = '.txt' - elif self.distribution == 'ubuntu': - base = 'http://changelogs.ubuntu.com/' + subdir = name[0] + pkgversion = Version(self.getVersion()).strip_epoch() + base = 'http://packages.debian.org/' url = os.path.join(base, 'changelogs', 'pool', - self.component, subdir, self.name, - self.name + '_' + pkgversion, - 'changelog' + extension) + self.getComponent(), subdir, name, + name + '_' + pkgversion, + 'changelog.txt') try: - self._changelog = urlopen(url).read() + with closing(urlopen(url)) as f: + self._changelog = f.read() except HTTPError as error: - print(('%s: %s' % (url, error)), file=sys.stderr) + Logger.error('{}: {}'.format(url, error)) return None if since_version is None: return self._changelog - if isinstance(since_version, basestring): + if isinstance(since_version, str): since_version = Version(since_version) new_entries = [] for block in Changelog(self._changelog): if block.version <= since_version: break - new_entries.append(unicode(block)) - return u''.join(new_entries) + new_entries.append(str(block)) + return ''.join(new_entries) + def getBinaries(self, arch=None, name=None, ext=None): + return [b.getBPPH() + for b in self._pkg.getBinaryFiles(arch=arch, name=name, ext=ext)] -def rmadison(url, package, suite=None, arch=None): - "Call rmadison and parse the result" - cmd = ['rmadison', '-u', url] - if suite: - cmd += ['-s', suite] - if arch: - cmd += ['-a', arch] - cmd.append(package) - process = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, close_fds=True) - output, error_output = process.communicate() - if process.wait() != 0: - if error_output: - Logger.error('rmadison failed with: %s', error_output) - else: - Logger.error('rmadison failed') - sys.exit(1) - # rmadison uses some shorthand - if suite: - suite = suite.replace('-proposed-updates', '-p-u') - - # pylint bug: http://www.logilab.org/ticket/46273 - # pylint: disable=E1103 - for line in output.strip().splitlines(): - # pylint: enable=E1103 - pkg, ver, dist, archs = [x.strip() for x in line.split('|')] - comp = 'main' - if '/' in dist: - dist, comp = dist.split('/') - archs = set(x.strip() for x in archs.split(',')) - - # rmadison returns some results outside the requested set. - # It'll include backports, and when given an unknown suite, - # it ignores that argument - # - # some versions (2.14.1ubuntu0.1) of rmadison return 'sid' when - # asked about 'unstable'. Others return 'unstable'. Accept either. - if (suite and dist != suite and not - (suite == 'sid' and dist == 'unstable')): - continue - - if 'source' in archs: - yield { - 'source': pkg, - 'version': ver, - 'suite': dist, - 'component': comp, - } - archs.discard('source') - if archs: - yield { - 'binary': pkg, - 'version': ver, - 'suite': dist, - 'component': comp, - 'architectures': archs, - } +class SnapshotBPPH(object): + """Provide the same interface as BinaryPackagePublishingHistory""" + def __init__(self, snapshot_binfile): + self._file = snapshot_binfile + + # LP API defined fields + @property + def architecture_specific(self): + return self._file.arch != 'all' + + @property + def binary_package_name(self): + return self.getPackageName() + + @property + def binary_package_version(self): + return self.getVersion() + + @property + def component_name(self): + return self.getComponent() + + @property + def display_name(self): + return ("{name} {version}" + .format(name=self.getPackageName(), + version=self.getVersion())) + + @property + def pocket(self): + # Debian does not use 'pockets' + return 'Release' + + # BPPH functions + + @property + def arch(self): + return self._file.arch + + def getSourcePackageName(self): + return self._file.source + + def getPackageName(self): + return self._file.package_name + + def getVersion(self): + return self._file.package_version + + def getComponent(self): + return self._file.component + + def binaryFileUrls(self, include_meta=False): + if include_meta: + return [{'url': self.getUrl(), + 'filename': self.getFileName(), + 'sha1': self._file.getHash(), + 'sha256': None, + 'size': self._file.size}] + return [self.getUrl()] + + def binaryFileUrl(self, filename): + if filename == self.getFileName(): + return self.getUrl() + return None + + def binaryFileSha1(self, url_or_filename): + if url_or_filename in [self.getUrl(), self.getFileName()]: + return self._file.getHash() + return None + + def binaryFileSha256(self, url_or_filename): + return None + + def binaryFileSize(self, url_or_filename): + if url_or_filename in [self.getUrl(), self.getFileName()]: + return int(self._file.size) + return 0 + + def getBuild(self): + return None + + def getUrl(self): + return self._file.getUrl() + + def getFileVersion(self): + return self.getVersion() + + def getFileArch(self): + return self.arch + + def getFileExt(self): + return self._file.ext + + def getFileName(self): + return self._file.name diff -Nru ubuntu-dev-tools-0.164/ubuntutools/builder.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/builder.py --- ubuntu-dev-tools-0.164/ubuntutools/builder.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/builder.py 2019-12-01 18:18:32.000000000 +0000 @@ -19,9 +19,10 @@ # import os +import subprocess -from ubuntutools.logger import Logger -from ubuntutools import subprocess +import logging +Logger = logging.getLogger(__name__) def _build_preparation(result_directory): @@ -34,8 +35,7 @@ def __init__(self, name): self.name = name cmd = ["dpkg-architecture", "-qDEB_BUILD_ARCH_CPU"] - process = subprocess.Popen(cmd, stdout=subprocess.PIPE) - self.architecture = process.communicate()[0].strip() + self.architecture = subprocess.check_output(cmd, encoding='utf-8').strip() def _build_failure(self, returncode, dsc_file): if returncode != 0: @@ -72,7 +72,7 @@ self.name, "--build", "--architecture", self.architecture, "--distribution", dist, "--buildresult", result_directory, dsc_file] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) returncode = subprocess.call(cmd) return self._build_failure(returncode, dsc_file) @@ -80,7 +80,7 @@ cmd = ["sudo", "-E", "ARCH=" + self.architecture, "DIST=" + dist, self.name, "--update", "--architecture", self.architecture, "--distribution", dist] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) returncode = subprocess.call(cmd) return self._update_failure(returncode, dist) @@ -93,13 +93,13 @@ _build_preparation(result_directory) cmd = [self.name, dist, self.architecture, "build", dsc_file, "--buildresult", result_directory] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) returncode = subprocess.call(cmd) return self._build_failure(returncode, dsc_file) def update(self, dist): cmd = [self.name, dist, self.architecture, "update"] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) returncode = subprocess.call(cmd) return self._update_failure(returncode, dist) @@ -111,21 +111,21 @@ def build(self, dsc_file, dist, result_directory): _build_preparation(result_directory) workdir = os.getcwd() - Logger.command(["cd", result_directory]) + Logger.debug("cd " + result_directory) os.chdir(result_directory) cmd = ["sbuild", "--arch-all", "--dist=" + dist, "--arch=" + self.architecture, dsc_file] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) returncode = subprocess.call(cmd) - Logger.command(["cd", workdir]) + Logger.debug("cd " + workdir) os.chdir(workdir) return self._build_failure(returncode, dsc_file) def update(self, dist): cmd = ["schroot", "--list"] - Logger.command(cmd) - process = subprocess.Popen(cmd, stdout=subprocess.PIPE) - chroots, _ = process.communicate()[0].strip().split() + Logger.debug(' '.join(cmd)) + process = subprocess.run(cmd, stdout=subprocess.PIPE, encoding='utf-8') + chroots, _ = process.stdout.strip().split() if process.returncode != 0: return process.returncode @@ -145,7 +145,7 @@ ["sbuild-clean", "-a", "-c"]] for cmd in commands: # pylint: disable=W0631 - Logger.command(cmd + [chroot]) + Logger.debug(' '.join(cmd) + " " + chroot) ret = subprocess.call(cmd + [chroot]) # pylint: enable=W0631 if ret != 0: diff -Nru ubuntu-dev-tools-0.164/ubuntutools/config.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/config.py --- ubuntu-dev-tools-0.164/ubuntutools/config.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/config.py 2021-12-05 15:20:37.000000000 +0000 @@ -23,7 +23,8 @@ import sys import locale -from ubuntutools.logger import Logger +import logging +Logger = logging.getLogger(__name__) class UDTConfig(object): @@ -37,10 +38,13 @@ 'BUILDER': 'pbuilder', 'DEBIAN_MIRROR': 'http://deb.debian.org/debian', 'DEBSEC_MIRROR': 'http://security.debian.org', + 'DEBIAN_DDEBS_MIRROR': 'http://debug.mirrors.debian.org/debian-debug', 'LPINSTANCE': 'production', 'MIRROR_FALLBACK': True, 'UBUNTU_MIRROR': 'http://archive.ubuntu.com/ubuntu', 'UBUNTU_PORTS_MIRROR': 'http://ports.ubuntu.com', + 'UBUNTU_INTERNAL_MIRROR': 'http://ftpmaster.internal/ubuntu', + 'UBUNTU_DDEBS_MIRROR': 'http://ddebs.ubuntu.com', 'UPDATE_BUILDER': False, 'WORKDIR': None, 'KEYID': None, @@ -69,8 +73,8 @@ for line in f: parsed = shlex.split(line, comments=True) if len(parsed) > 1: - Logger.warn('Cannot parse variable assignment in %s: %s', - getattr(f, 'name', ''), line) + Logger.warning('Cannot parse variable assignment in %s: %s', + getattr(f, 'name', ''), line) if len(parsed) >= 1 and '=' in parsed[0]: key, value = parsed[0].split('=', 1) config[key] = value @@ -109,10 +113,8 @@ replacements = self.prefix + '_' + key if key in self.defaults: replacements += 'or UBUNTUTOOLS_' + key - Logger.warn( - 'Using deprecated configuration variable %s. ' - 'You should use %s.', - k, replacements) + Logger.warning('Using deprecated configuration variable %s. ' + 'You should use %s.', k, replacements) return value return default diff -Nru ubuntu-dev-tools-0.164/ubuntutools/__init__.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/__init__.py --- ubuntu-dev-tools-0.164/ubuntutools/__init__.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/__init__.py 2021-12-05 15:20:37.000000000 +0000 @@ -2,3 +2,52 @@ # # Ubuntu Development Tools # https://launchpad.net/ubuntu-dev-tools + +import logging +import sys + + +def getLogger(): + ''' Get the logger instance for this module + + Quick guide for using this or not: if you want to call ubuntutools + module code and have its output print to stdout/stderr ONLY, you can + use the logger this creates. You can also log directly to this logger + from your own code to send output to stdout/stderr. + + This creates the ubuntutools module-level logger, and sets some default + values for formatting and levels, and directs INFO-level logs messages to + stdout and logs higher than INFO to stderr. The logger's level may be + adjusted to show more logs (e.g. DEBUG) or less (e.g. WARNING, to suppress + all INFO messages). + + Without calling this module, the ubuntutools logs will propagate up to + higher level loggers (possibly the root logger) and be handled by them. + Note that the default for python logging is to print WARNING and above + logs to stderr. + + Note if any code calls this method, the ubuntutools module-level logger + will no longer propagate ubuntutools log message up to higher level + loggers. + + This should only be used by runnable scripts provided by the + ubuntu-dev-tools package, or other runnable scripts that want the behavior + described above. + ''' + logger = logging.getLogger(__name__) + logger.setLevel(logging.INFO) + logger.propagate = False + + fmt = logging.Formatter('%(message)s') + + stdout_handler = logging.StreamHandler(stream=sys.stdout) + stdout_handler.setFormatter(fmt) + stdout_handler.addFilter(lambda r: r.levelno <= logging.INFO) + logger.addHandler(stdout_handler) + + stderr_handler = logging.StreamHandler(stream=sys.stderr) + stderr_handler.setFormatter(fmt) + stderr_handler.setLevel(logging.INFO+1) + logger.addHandler(stderr_handler) + + return logger diff -Nru ubuntu-dev-tools-0.164/ubuntutools/logger.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/logger.py --- ubuntu-dev-tools-0.164/ubuntutools/logger.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/logger.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -# -# logger.py - A simple logging helper class -# -# Copyright (C) 2010, Benjamin Drung -# -# Permission to use, copy, modify, and/or distribute this software -# for any purpose with or without fee is hereby granted, provided -# that the above copyright notice and this permission notice appear -# in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE -# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR -# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import os -import sys - - -def escape_arg(arg): - """Shell-escpae arg, if necessary. - Fairly simplistic, doesn't escape anything except whitespace. - """ - if ' ' not in arg: - return arg - return '"%s"' % arg.replace('\\', r'\\').replace('"', r'\"') - - -class Logger(object): - script_name = os.path.basename(sys.argv[0]) - verbose = False - - stdout = sys.stdout - stderr = sys.stderr - - @classmethod - def _print(cls, format_, message, args=None, stderr=False): - if args: - message = message % args - stream = cls.stderr if stderr else cls.stdout - stream.write((format_ + "\n") % (cls.script_name, message)) - - @classmethod - def command(cls, cmd): - if cls.verbose: - cls._print("%s: I: %s", " ".join(escape_arg(arg) for arg in cmd)) - - @classmethod - def debug(cls, message, *args): - if cls.verbose: - cls._print("%s: D: %s", message, args, stderr=True) - - @classmethod - def error(cls, message, *args): - cls._print("%s: Error: %s", message, args, stderr=True) - - @classmethod - def warn(cls, message, *args): - cls._print("%s: Warning: %s", message, args, stderr=True) - - @classmethod - def info(cls, message, *args): - if cls.verbose: - cls._print("%s: I: %s", message, args) - - @classmethod - def normal(cls, message, *args): - cls._print("%s: %s", message, args) - - @classmethod - def set_verbosity(cls, verbose): - cls.verbose = verbose diff -Nru ubuntu-dev-tools-0.164/ubuntutools/lp/__init__.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/lp/__init__.py --- ubuntu-dev-tools-0.164/ubuntutools/lp/__init__.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/lp/__init__.py 2019-12-01 18:18:32.000000000 +0000 @@ -3,4 +3,4 @@ # service = 'production' -api_version = '1.0' +api_version = 'devel' diff -Nru ubuntu-dev-tools-0.164/ubuntutools/lp/libsupport.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/lp/libsupport.py --- ubuntu-dev-tools-0.164/ubuntutools/lp/libsupport.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/lp/libsupport.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -# -# libsupport.py - functions which add launchpadlib support to the Ubuntu -# Developer Tools package. -# -# Copyright (C) 2009 Markus Korn -# -# 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 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. -# -# Please see the /usr/share/common-licenses/GPL file for the full text of -# the GNU General Public License license. -# - -# Modules. -try: - from urllib.parse import urlsplit, urlencode, urlunsplit -except ImportError: - from urllib import urlencode - from urlparse import urlsplit, urlunsplit - - -def query_to_dict(query_string): - result = dict() - options = filter(None, query_string.split("&")) - for opt in options: - key, value = opt.split("=") - result.setdefault(key, set()).add(value) - return result - - -def translate_web_api(url, launchpad): - scheme, netloc, path, query, fragment = urlsplit(url) - query = query_to_dict(query) - - differences = set(netloc.split('.')).symmetric_difference( - set(launchpad._root_uri.host.split('.'))) - if ('staging' in differences or 'edge' in differences): - raise ValueError("url conflict (url: %s, root: %s" % - (url, launchpad._root_uri)) - if path.endswith("/+bugs"): - path = path[:-6] - if "ws.op" in query: - raise ValueError("Invalid web url, url: %s" % url) - query["ws.op"] = "searchTasks" - scheme, netloc, api_path, _, _ = urlsplit(str(launchpad._root_uri)) - query = urlencode(query) - url = urlunsplit((scheme, netloc, api_path + path.lstrip("/"), query, fragment)) - return url diff -Nru ubuntu-dev-tools-0.164/ubuntutools/lp/lpapicache.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/lp/lpapicache.py --- ubuntu-dev-tools-0.164/ubuntutools/lp/lpapicache.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/lp/lpapicache.py 2021-12-05 15:20:37.000000000 +0000 @@ -21,22 +21,25 @@ # # Based on code written by Jonathan Davies -from __future__ import print_function - -# Uncomment for tracing LP API calls -# import httplib2 -# httplib2.debuglevel = 1 - import collections -import sys +import os +import re + +from copy import copy -from debian.changelog import Changelog, Version -from httplib2 import Http, HttpLib2Error +from debian.changelog import Changelog from launchpadlib.launchpad import Launchpad as LP from launchpadlib.errors import HTTPError from lazr.restfulclient.resource import Entry +from urllib.error import URLError +from urllib.parse import urlparse +from ubuntutools.version import Version from ubuntutools.lp import (service, api_version) +from ubuntutools.misc import (download_text, + host_architecture, + DEFAULT_POCKETS, POCKETS, + DEFAULT_STATUSES, STATUSES) from ubuntutools.lp.udtexceptions import (AlreadyLoggedInError, ArchiveNotFoundException, ArchSeriesNotFoundException, @@ -44,26 +47,8 @@ PocketDoesNotExistError, SeriesNotFoundException) -if sys.version_info[0] >= 3: - basestring = str - unicode = str - - -# Shameless steal from python-six -def add_metaclass(metaclass): - """Class decorator for creating a class with a metaclass.""" - def wrapper(cls): - orig_vars = cls.__dict__.copy() - slots = orig_vars.get('__slots__') - if slots is not None: - if isinstance(slots, str): - slots = [slots] - for slots_var in slots: - orig_vars.pop(slots_var) - orig_vars.pop('__dict__', None) - orig_vars.pop('__weakref__', None) - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper +import logging +Logger = logging.getLogger(__name__) __all__ = [ @@ -73,13 +58,15 @@ 'Distribution', 'DistributionSourcePackage', 'DistroSeries', + 'DistroArchSeries', 'Launchpad', + 'PackageUpload', 'PersonTeam', + 'Project', + 'ProjectSeries', 'SourcePackagePublishingHistory', ] -_POCKETS = ('Release', 'Security', 'Updates', 'Proposed', 'Backports') - class _Launchpad(object): '''Singleton for LP API access.''' @@ -91,7 +78,7 @@ self.__lp = LP.login_with('ubuntu-dev-tools', service, version=api_version) except IOError as error: - print('E: %s' % error, file=sys.stderr) + Logger.error(str(error)) raise else: raise AlreadyLoggedInError('Already logged in to Launchpad.') @@ -118,7 +105,7 @@ def __getattr__(self, attr): if not self.logged_in: - self.login() + self.login_anonymously() return getattr(self.__lp, attr) def __call__(self): @@ -140,15 +127,14 @@ cls._cache = dict() -@add_metaclass(MetaWrapper) -class BaseWrapper(object): +class BaseWrapper(object, metaclass=MetaWrapper): ''' A base class from which other wrapper classes are derived. ''' resource_type = None # it's a base class after all def __new__(cls, data): - if isinstance(data, basestring) and data.startswith(str(Launchpad._root_uri)): + if isinstance(data, str) and data.startswith(str(Launchpad._root_uri)): # looks like a LP API URL # check if it's already cached cached = cls._cache.get(data) @@ -173,6 +159,7 @@ cached._lpobject = data # and add it to our cache cls._cache[data.self_link] = cached + Logger.debug("%s: %s" % (cls.__name__, data.self_link)) # add additional class specific caching (if available) cache = getattr(cls, 'cache', None) if isinstance(cache, collections.Callable): @@ -211,21 +198,29 @@ resource_type = 'distribution' def __init__(self, *args): - # Don't share _series and _archives between different Distributions - if '_series' not in self.__dict__: - self._series = dict() - if '_archives' not in self.__dict__: - self._archives = dict() + self._archives = dict() + self._series_by_name = dict() + self._series = dict() + self._dev_series = None + self._have_all_series = False def cache(self): self._cache[self.name] = self + def _cache_series(self, series): + ''' + Add the DistroSeries to the cache if needed. + ''' + if series.version not in self._series: + self._series_by_name[series.name] = series + self._series[series.version] = series + @classmethod def fetch(cls, dist): ''' Fetch the distribution object identified by 'dist' from LP. ''' - if not isinstance(dist, basestring): + if not isinstance(dist, str): raise TypeError("Don't know what do with '%r'" % dist) cached = cls._cache.get(dist) if not cached: @@ -266,28 +261,49 @@ (e.g. 'karmic') or version (e.g. '9.10'). If the series is not found: raise SeriesNotFoundException ''' - if name_or_version not in self._series: - try: - series = DistroSeries(self().getSeries(name_or_version=name_or_version)) - # Cache with name and version - self._series[series.name] = series - self._series[series.version] = series - except HTTPError: - message = "Release '%s' is unknown in '%s'." % \ - (name_or_version, self.display_name) - raise SeriesNotFoundException(message) - return self._series[name_or_version] + if name_or_version in self._series: + return self._series[name_or_version] + if name_or_version in self._series_by_name: + return self._series_by_name[name_or_version] + + try: + series = DistroSeries(self().getSeries(name_or_version=name_or_version)) + except HTTPError: + message = "Release '%s' is unknown in '%s'." % \ + (name_or_version, self.display_name) + raise SeriesNotFoundException(message) + + self._cache_series(series) + return series def getDevelopmentSeries(self): ''' Returns a DistroSeries object of the current development series. ''' - dev = DistroSeries(self.current_series_link) - # Cache it in _series if not already done - if dev.name not in self._series: - self._series[dev.name] = dev - self._series[dev.version] = dev - return dev + if not self._dev_series: + series = DistroSeries(self.current_series_link) + self._cache_series(series) + self._dev_series = series + return self._dev_series + + def getAllSeries(self, active=True): + ''' + Returns a list of all DistroSeries objects. + ''' + if not self._have_all_series: + for s in Launchpad.load(self.series_collection_link).entries: + series = DistroSeries(s['self_link']) + self._cache_series(series) + self._have_all_series = True + + allseries = filter(lambda s: s.active, self._series.values()) + allseries = sorted(allseries, + key=lambda s: float(s.version), + reverse=True) + Logger.debug("Found series: %s" % ", ".join(map(lambda s: "%s (%s)" % + (s.name, s.version), + allseries))) + return collections.OrderedDict((s.name, s) for s in allseries) class DistroArchSeries(BaseWrapper): @@ -296,6 +312,12 @@ ''' resource_type = 'distro_arch_series' + def getSeries(self): + ''' + Get DistroSeries for this. + ''' + return DistroSeries(self._lpobject.distroseries_link) + class DistroSeries(BaseWrapper): ''' @@ -307,12 +329,16 @@ if "_architectures" not in self.__dict__: self._architectures = dict() - def getArchSeries(self, archtag): + def getArchSeries(self, archtag=None): ''' Returns a DistroArchSeries object for an architecture passed by name (e.g. 'amd64'). + If arch is not specified, get the DistroArchSeries for the system arch. + The special archtag 'all' will get the system arch. If the architecture is not found: raise ArchSeriesNotFoundException. ''' + if not archtag or archtag == 'all': + archtag = host_architecture() if archtag not in self._architectures: try: architecture = DistroArchSeries( @@ -324,6 +350,78 @@ raise ArchSeriesNotFoundException(message) return self._architectures[archtag] + def getPackageUploads(self, name=None, pocket=None, version=None, + status='Unapproved'): + '''Returns a list of PackageUploads for this series.''' + params = {'exact_match': True} + if name: + params['name'] = name + if pocket: + params['pocket'] = pocket + if version: + params['version'] = version + if status: + params['status'] = status + return [PackageUpload(p) for p in self._lpobject.getPackageUploads(**params)] + + +class PackageUpload(BaseWrapper): + ''' + Wrapper class around a LP package_upload object. + ''' + resource_type = 'package_upload' + + def __init__(self, *args): + self._custom_urls = None + self._source_urls = None + self._binary_urls = None + self._binary_properties = None + self._binary_prop_dict = None + + def getArchive(self): + return Archive(self._lpobject.archive_link) + + def getSourceArchive(self): + if self._lpobject.copy_source_archive_link: + return Archive(self._lpobject.copy_source_archive_link) + return None + + def getDistroSeries(self): + return DistroSeries(self._lpobject.distroseries_link) + + def changesFileUrl(self): + return self._lpobject.changes_file_url + + def customFileUrls(self): + if not self._custom_urls: + self._custom_urls = self._lpobject.customFileUrls() + return copy(self._custom_urls) + + def sourceFileUrls(self): + if not self._source_urls: + self._source_urls = self._lpobject.sourceFileUrls() + return copy(self._source_urls) + + def binaryFileUrls(self): + if not self._binary_urls: + self._binary_urls = self._lpobject.binaryFileUrls() + return copy(self._binary_urls) + + def getBinaryProperties(self): + if not self._binary_properties: + self._binary_properties = self._lpobject.getBinaryProperties() + return copy(self._binary_properties) + + def binaryFileProperties(self, filename_or_url): + if not self._binary_prop_dict: + urls = self.binaryFileUrls() + props = self.getBinaryProperties() + self._binary_prop_dict = dict(zip(urls, props)) + for (k, v) in copy(self._binary_prop_dict).items(): + filename = os.path.basename(urlparse(k).path) + self._binary_prop_dict[filename] = v + return self._binary_prop_dict.get(filename_or_url, {}) + class Archive(BaseWrapper): ''' @@ -338,16 +436,35 @@ self._pkgset_uploaders = {} self._component_uploaders = {} - def getSourcePackage(self, name, series=None, pocket=None): + def getSourcePackage(self, name, series=None, pocket=None, version=None, + status=None, wrapper=None, search_all_series=False): ''' Returns a SourcePackagePublishingHistory object for the most recent source package in the distribution 'dist', series and pocket. series defaults to the current development series if not specified. + series must be either a series name string, or DistroSeries object. - pocket may be a list, if so, the highest version will be returned. - It defaults to all pockets except backports. + version may be specified to get only the exact version requested. + + pocket may be a string or a list. If no version is provided, it + defaults to all pockets except 'Backports'; if searching for a + specific version, it defaults to all pockets. Pocket strings must + be capitalized. + + status may be a string or a list. If no version is provided, it + defaults to only 'Pending' and 'Published'; if searching for a + specific version, it defaults to all statuses. Status strings must + be capitalized. + + wrapper is the class to return an instance of; defaults to + SourcePackagePublishingHistory. + + search_all_series is used if series is None. If False, this will + search only the latest devel series, and if True all series + will be searched, in reverse order, starting with the latest + devel series. Defaults to False. If the requested source package doesn't exist a PackageNotFoundException is raised. @@ -355,113 +472,236 @@ return self._getPublishedItem(name, series, pocket, cache=self._srcpkgs, function='getPublishedSources', name_key='source_name', - wrapper=SourcePackagePublishingHistory) - - def getBinaryPackage(self, name, archtag=None, series=None, pocket=None): + wrapper=wrapper or SourcePackagePublishingHistory, + version=version, + status=status, + search_all_series=search_all_series, + binary=False) + + def getBinaryPackage(self, name, archtag=None, series=None, pocket=None, + version=None, status=None, wrapper=None, + search_all_series=False): ''' Returns a BinaryPackagePublishingHistory object for the most recent source package in the distribution 'dist', architecture 'archtag', series and pocket. series defaults to the current development series if not specified. + series must be either a series name string, or DistroArchSeries object. + series may be omitted if version is specified. + + version may be specified to get only the exact version requested. - pocket may be a list, if so, the highest version will be returned. - It defaults to all pockets except backports. + pocket may be a string or a list. If no version is provided, it + defaults to all pockets except 'Backports'; if searching for a + specific version, it defaults to all pockets. Pocket strings must + be capitalized. + + status may be a string or a list. If no version is provided, it + defaults to only 'Pending' and 'Published'; if searching for a + specific version, it defaults to all statuses. Status strings must + be capitalized. + + wrapper is the class to return an instance of; defaults to + BinaryPackagePublishingHistory. + + search_all_series is used if series is None. If False, this will + search only the latest devel series, and if True all series + will be searched, in reverse order, starting with the latest + devel series. Defaults to False. If the requested binary package doesn't exist a PackageNotFoundException is raised. ''' - if archtag is None: - archtag = [] return self._getPublishedItem(name, series, pocket, archtag=archtag, cache=self._binpkgs, function='getPublishedBinaries', name_key='binary_name', - wrapper=BinaryPackagePublishingHistory) + wrapper=wrapper or BinaryPackagePublishingHistory, + version=version, + status=status, + search_all_series=search_all_series, + binary=True) def _getPublishedItem(self, name, series, pocket, cache, - function, name_key, wrapper, archtag=None): - '''Common code between getSourcePackage and getBinaryPackage - ''' - if pocket is None: - pockets = frozenset(('Proposed', 'Updates', 'Security', 'Release')) - elif isinstance(pocket, basestring): - pockets = frozenset((pocket,)) - else: - pockets = frozenset(pocket) - - for pocket in pockets: - if pocket not in _POCKETS: - raise PocketDoesNotExistError("Pocket '%s' does not exist." % - pocket) + function, name_key, wrapper, archtag=None, + version=None, status=None, search_all_series=False, + binary=False): + ''' + Common code between getSourcePackage and getBinaryPackage. + + Don't use this directly. + ''' + if not pocket: + if version and not series: + # check ALL pockets if specific version in any series + pockets = POCKETS + else: + # otherwise, check all pockets EXCEPT 'Backports' + pockets = DEFAULT_POCKETS + elif isinstance(pocket, str): + pockets = (pocket,) + else: + pockets = tuple(pocket) - dist = Distribution(self.distribution_link) - # Check if series is already a DistroSeries object or not - if not isinstance(series, DistroSeries): - if series: - series = dist.getSeries(series) + for p in pockets: + if p not in POCKETS: + raise PocketDoesNotExistError("Pocket '%s' does not exist." % p) + + if not status: + if version: + # check ALL statuses if specific version + statuses = STATUSES else: - series = dist.getDevelopmentSeries() + # otherwise, only check 'Pending' and 'Published' + statuses = DEFAULT_STATUSES + elif isinstance(status, str): + statuses = (status,) + else: + statuses = tuple(status) + + for s in statuses: + if s not in STATUSES: + raise ValueError("Status '%s' is not valid." % s) + + dist = Distribution(self.distribution_link) - # getPublishedSources requires a distro_series, while - # getPublishedBinaries requires a distro_arch_series. - # If archtag is not None, I'll assume it's getPublishedBinaries. - if archtag is not None and archtag != []: - if not isinstance(archtag, DistroArchSeries): - arch_series = series.getArchSeries(archtag=archtag) + # please don't pass DistroArchSeries as archtag! + # but, the code was like that before so keep + # backwards compatibility. + if isinstance(archtag, DistroArchSeries): + series = archtag + archtag = None + + series_to_check = [series] + if not version and not series: + # if neither version or series are specified, use either the + # devel series or search all series + if search_all_series: + series_to_check = dist.getAllSeries().values() else: - arch_series = archtag + series_to_check = [dist.getDevelopmentSeries()] - if archtag is not None and archtag != []: - index = (name, series.name, archtag, pockets) - else: - index = (name, series.name, pockets) + # check each series - if only version was provided, series will be None + for series in series_to_check: + arch_series = None + + if isinstance(series, DistroArchSeries): + arch_series = series + series = series.getSeries() + elif isinstance(series, DistroSeries): + pass + elif series: + series = dist.getSeries(series) + + if binary: + if arch_series is None and series: + arch_series = series.getArchSeries(archtag=archtag) + if archtag is None and arch_series: + archtag = arch_series.architecture_tag + if archtag is None: + archtag = host_architecture() + + index = (name, getattr(series, 'name', None), archtag, pockets, statuses, version) + + if index in cache: + return cache[index] - if index not in cache: params = { name_key: name, - 'status': 'Published', 'exact_match': True, } - if archtag is not None and archtag != []: + + if arch_series: params['distro_arch_series'] = arch_series() - else: + elif series: params['distro_series'] = series() if len(pockets) == 1: - params['pocket'] = list(pockets)[0] + params['pocket'] = pockets[0] + + if len(statuses) == 1: + params['status'] = statuses[0] + if version: + params['version'] = version + + Logger.debug('Calling %s(%s)' % (function, + ', '.join(['%s=%s' % (k, v) + for (k, v) in params.items()]))) records = getattr(self, function)(**params) - latest = None + err_msg = ("does not exist in the %s %s archive" % + (dist.display_name, self.name)) + for record in records: - if record.pocket not in pockets: - continue - if latest is None or (Version(latest.source_package_version) - < Version(record.source_package_version)): - latest = record - - if latest is None: - if name_key == 'binary_name': - package_type = "binary package" - elif name_key == 'source_name': - package_type = "source package" + if binary: + rversion = getattr(record, 'binary_package_version', None) else: - package_type = "package" - msg = ("The %s '%s' does not exist in the %s %s archive" % - (package_type, name, dist.display_name, self.name)) - if archtag is not None and archtag != []: - msg += " for architecture %s" % archtag - pockets = [series.name if pocket == 'Release' - else '%s-%s' % (series.name, pocket.lower()) - for pocket in pockets] - if len(pockets) > 1: - pockets[-2:] = [' or '.join(pockets[-2:])] - msg += " in " + ', '.join(pockets) - raise PackageNotFoundException(msg) + rversion = getattr(record, 'source_package_version', None) + skipmsg = ('Skipping version %s: ' % rversion) - cache[index] = wrapper(latest) - return cache[index] + if record.pocket not in pockets: + err_msg = 'pocket %s not in (%s)' % (record.pocket, ','.join(pockets)) + Logger.debug(skipmsg + err_msg) + continue + if record.status not in statuses: + err_msg = 'status %s not in (%s)' % (record.status, ','.join(statuses)) + Logger.debug(skipmsg + err_msg) + continue + r = wrapper(record) + if binary and archtag and archtag != r.arch: + err_msg = 'arch %s does not match requested arch %s' % (r.arch, archtag) + Logger.debug(skipmsg + err_msg) + continue + # results are ordered so first is latest + cache[index] = r + return r + + version_with_epoch = None + if version and version == Version(version).strip_epoch() and len(records) == 0: + # a specific version was asked for, but we found none; + # check if one exists with an epoch to give a hint in error msg + for epoch in range(1, 9): + v = Version(version) + v.epoch = epoch + params['version'] = v.full_version + if len(getattr(self, function)(**params)) > 0: + version_with_epoch = v.full_version + Logger.debug('Found version with epoch %s' % version_with_epoch) + break + + if name_key == 'binary_name': + package_type = "binary package" + elif name_key == 'source_name': + package_type = "source package" + else: + package_type = "package" + msg = "The %s '%s' " % (package_type, name) + if version: + msg += "version %s " % version + msg += err_msg + if binary and archtag: + msg += " for architecture %s" % archtag + if len(series_to_check) > 1: + msg += " in any release" + if len(pockets) == 1: + msg += " for pocket %s" % pockets[0] + elif len(pockets) != len(POCKETS): + msg += " for pockets " + ', '.join(pockets) + elif series: + msg += " in %s" % series.name + if len(pockets) == 1: + msg += "-%s" % pockets[0] + elif len(pockets) != len(POCKETS): + msg += " for pockets " + ', '.join(pockets) + if len(statuses) == 1: + msg += " with status %s" % statuses[0] + elif len(statuses) != len(STATUSES): + msg += " with status in " + ', '.join(statuses) + if version_with_epoch: + msg += " (did you forget the epoch? try %s)" % version_with_epoch + raise PackageNotFoundException(msg) def copyPackage(self, source_name, version, from_archive, to_pocket, to_series=None, sponsored=None, include_binaries=False): @@ -503,10 +743,13 @@ [Note: the permission records, themselves, aren't exposed] ''' if source_package_name not in self._pkg_uploaders: - self._pkg_uploaders[source_package_name] = sorted(set( - PersonTeam(permission.person_link) for permission in - self._lpobject.getUploadersForPackage(source_package_name=source_package_name) - )) + self._pkg_uploaders[source_package_name] = sorted( + set( + PersonTeam(permission.person_link) for permission in + self._lpobject.getUploadersForPackage(source_package_name=source_package_name) + ), + key=lambda s: s.name + ) return self._pkg_uploaders[source_package_name] def getUploadersForPackageset(self, packageset, direct_permissions=False): @@ -524,6 +767,17 @@ )) return self._pkgset_uploaders[key] + def getMySubscriptionURL(self): + '''Get the "subscription URL" for the logged in user + + If this is a private archive (i.e. private PPA), this returns + the "subscription URL" including authentication; otherwise + this returns None. + ''' + if self.private: + return PersonTeam.me.getArchiveSubscriptionURL(archive=self._lpobject) + return None + class SourcePackagePublishingHistory(BaseWrapper): ''' @@ -532,13 +786,24 @@ resource_type = 'source_package_publishing_history' def __init__(self, *args): + self._archive = None self._changelog = None - self._binaries = None + self._binaries = {} + self._distro_series = None + self._source_urls = None # Don't share _builds between different # SourcePackagePublishingHistory objects if '_builds' not in self.__dict__: self._builds = dict() + def getDistroSeries(self): + ''' + Return the DistroSeries. + ''' + if not self._distro_series: + self._distro_series = DistroSeries(self._lpobject.distro_series_link) + return self._distro_series + def getPackageName(self): ''' Returns the source package name. @@ -557,16 +822,33 @@ ''' return self._lpobject.component_name + def getSeriesName(self): + ''' + Returns the series + + Named getSeriesName() to avoid confusion with + getDistroSeries() + ''' + return self.getDistroSeries().name + def getSeriesAndPocket(self): ''' Returns a human-readable release-pocket ''' - series = DistroSeries(self._lpobject.distro_series_link) - release = series.name - if self._lpobject.pocket != 'Release': - release += '-' + self._lpobject.pocket.lower() + release = self.getSeriesName() + if self.pocket != 'Release': + release += '-' + self.pocket.lower() return release + def getArchive(self): + ''' + Get this SPPH's archive. + ''' + if not self._archive: + self._archive = Archive(self._lpobject.archive_link) + + return self._archive + def getChangelog(self, since_version=None): ''' Return the changelog, optionally since a particular version @@ -576,42 +858,193 @@ if self._changelog is None: url = self._lpobject.changelogUrl() if url is None: - print('E: No changelog available for %s %s' % - (self.getPackageName(), self.getVersion()), file=sys.stderr) + Logger.error('No changelog available for %s %s' % + (self.getPackageName(), self.getVersion())) return None try: - response, changelog = Http().request(url) - except HttpLib2Error as e: - print(str(e), file=sys.stderr) - return None - if response.status != 200: - print('%s: %s %s' % (url, response.status, response.reason), file=sys.stderr) + self._changelog = download_text(url) + except URLError as e: + Logger.error(f"Exception while downloading '{url}': {e}") return None - self._changelog = changelog if since_version is None: return self._changelog - if isinstance(since_version, basestring): + if isinstance(since_version, str): since_version = Version(since_version) new_entries = [] for block in Changelog(self._changelog): if block.version <= since_version: break - new_entries.append(unicode(block)) - return u''.join(new_entries) + new_entries.append(str(block)) + return ''.join(new_entries) + + def sourceFileUrls(self, include_meta=False): + ''' + Return the URL for this source publication's files. + + The include_meta param changes the return value; + when it is False (the default), an array of url strings is + returned. When include_meta is True, an array is returned + with dicts, containing the entries: + url: the url string + sha1: the SHA1 checksum of the source file (if provided) + sha256: the SHA256 checksum of the source file + size: the size of the source file + Also, this function adds a 'filename' field: + filename: the filename parsed from the url path + Note that while all the keys will be in the dict, their values + may be None. + ''' + if not self._source_urls: + urls = self._lpobject.sourceFileUrls(include_meta=True) + if not urls: + Logger.warning('SPPH %s_%s has no sourceFileUrls' % + (self.getPackageName(), self.getVersion())) + for u in urls: + # make sure mandatory fields are present + for field in ['url', 'sha1', 'sha256', 'size']: + if field not in u: + u[field] = None + u['filename'] = os.path.basename(urlparse(u['url']).path) + self._source_urls = urls + + if include_meta: + return list(self._source_urls) + return [f['url'] for f in self._source_urls] + + def sourceFileUrl(self, filename): + ''' + Returns the URL for the specified source filename. + + If the filename is not found in the sourceFileUrls(), this returns None. + ''' + for f in self.sourceFileUrls(include_meta=True): + if filename == f['filename']: + return f['url'] + return None + + def sourceFileSha1(self, url_or_filename): + ''' + Returns the SHA1 checksum for the specified source file url. + + If the url is not found in the sourceFileUrls(), this returns None. + + The url may be specified as a filename. + ''' + for f in self.sourceFileUrls(include_meta=True): + if url_or_filename in [f['url'], f['filename']]: + return f['sha1'] + return None + + def sourceFileSha256(self, url_or_filename): + ''' + Returns the SHA256 checksum for the specified source file url. + + If the url is not found in the sourceFileUrls(), this returns None. + + The url may be specified as a filename. + ''' + for f in self.sourceFileUrls(include_meta=True): + if url_or_filename in [f['url'], f['filename']]: + return f['sha256'] + return None + + def sourceFileSize(self, url_or_filename): + ''' + Returns the size for the specified source file url. - def getBinaries(self): + If the url is not found in the sourceFileUrls(), this returns 0. + + The url may be specified as a filename. + ''' + for f in self.sourceFileUrls(include_meta=True): + if url_or_filename in [f['url'], f['filename']]: + return int(f['size']) + return 0 + + def getBinaries(self, arch=None, name=None, ext=None): ''' - Returns the resulting BinaryPackagePublishingHistorys + Returns the resulting BinaryPackagePublishingHistorys. + If arch is specified, it returns binaries for only that arch, + plus any binaries with arch 'all'. If arch is not specified, or + if arch is specified as 'all', all archs are returned. + + If name is specified, only returns BPPH matching that (regex) name. + + If ext is specified, only returns BPPH matching that (regex) ext. ''' - if self._binaries is None: - self._binaries = [BinaryPackagePublishingHistory(bpph) - for bpph in - self._lpobject.getPublishedBinaries()] - return self._binaries + if arch == 'all': + arch = None + + if self.status in ["Pending", "Published"]: + # Published, great! Directly query the list of binaries + binaries = map(BinaryPackagePublishingHistory, + self._lpobject.getPublishedBinaries()) + for b in binaries: + a = b.arch + if a not in self._binaries: + self._binaries[a] = {} + self._binaries[a][b.binary_package_name] = b + else: + # we have to go the long way :( + Logger.info("Please wait, this may take some time...") + archive = self.getArchive() + urls = self.binaryFileUrls() + for url in urls: + # strip out the URL leading text. + filename = os.path.basename(urlparse(url).path) + # strip the file suffix + (pkgname, _, e) = filename.rpartition('.') + # split into name, version, arch + (n, v, a) = pkgname.rsplit('_', 2) + # arch 'all' has separate bpph for each real arch, + # but all point to the same binary url + if a == 'all': + a = arch or host_architecture() + # Only check the arch requested - saves time + if arch and arch != a: + continue + # Only check the name requested - saves time + if name and not re.match(name, n): + continue + # Only check the ext requested - saves time + if ext and not re.match(ext, e): + continue + # If we already have this BPPH, keep going + if a in self._binaries and n in self._binaries[a]: + continue + # we ignore the version, as it may be missing epoch + # also we can't use series, as some package versions + # span multiple series! (e.g. for different archs) + params = {'name': n, + 'archtag': a, + 'version': self.getVersion()} + try: + bpph = archive.getBinaryPackage(**params) + except PackageNotFoundException: + Logger.debug("Could not find pkg in archive: %s" % filename) + continue + if a not in self._binaries: + self._binaries[a] = {} + self._binaries[a][n] = bpph + + if not arch: + bpphs = [b for a in self._binaries.values() for b in a.values()] + elif arch in self._binaries: + bpphs = list(self._binaries[arch].values()) + else: + return [] + + if name: + bpphs = [b for b in bpphs if re.match(name, b.binary_package_name)] + + if ext: + bpphs = [b for b in bpphs if re.match(ext, b.getFileExt())] + + return bpphs def _fetch_builds(self): '''Populate self._builds with the build records.''' @@ -671,6 +1104,24 @@ ''' resource_type = 'binary_package_publishing_history' + def __init__(self, *args): + self._arch = None + self._ext = None + self._binary_urls = None + + @property + def arch(self): + if not self._arch: + das = DistroArchSeries(self._lpobject.distro_arch_series_link) + self._arch = das.architecture_tag + return self._arch + + def getSourcePackageName(self): + ''' + Returns the source package name. + ''' + return self.getBuild().source_package_name + def getPackageName(self): ''' Returns the binary package name. @@ -689,16 +1140,164 @@ ''' return self._lpobject.component_name - def binaryFileUrls(self): + def binaryFileUrls(self, include_meta=False): ''' Return the URL for this binary publication's files. Only available in the devel API, not 1.0 + + The include_meta param changes the return value; + when it is False (the default), an array of url strings is + returned (but typically there is only a single url in the array). + When include_meta is True, an array (again, with typically only one + entry) is returned with dicts, containing the entries: + url: the url string + sha1: the SHA1 checksum of the binary file + sha256: the SHA256 checksum of the binary file + size: the size of the binary file + Also, this function adds a 'filename' field: + filename: the filename parsed from the url path + Note that while all the keys will be in the dict, their values + may be None. + ''' + if not self._binary_urls: + try: + urls = self._lpobject.binaryFileUrls(include_meta=True) + except AttributeError: + raise AttributeError("binaryFileUrls can only be found in lpapi " + "devel, not 1.0. Login using devel to have it.") + if not urls: + Logger.warning('BPPH %s_%s has no binaryFileUrls' % + (self.getPackageName(), self.getVersion())) + for u in urls: + # make sure mandatory fields are present + for field in ['url', 'sha1', 'sha256', 'size']: + if field not in u: + u[field] = None + u['filename'] = os.path.basename(urlparse(u['url']).path) + self._binary_urls = urls + + if include_meta: + return list(self._binary_urls) + return [f['url'] for f in self._binary_urls] + + def binaryFileUrl(self, filename): + ''' + Returns the URL for the specified binary filename. + + If the filename is not found in the binaryFileUrls(), this returns None. + ''' + for f in self.binaryFileUrls(include_meta=True): + if filename == f['filename']: + return f['url'] + return None + + def binaryFileSha1(self, url_or_filename): + ''' + Returns the SHA1 checksum for the specified binary file url. + + If the url is not found in the binaryFileUrls(), this returns None. + + The url may be specified as a filename. + ''' + for f in self.binaryFileUrls(include_meta=True): + if url_or_filename in [f['url'], f['filename']]: + return f['sha1'] + return None + + def binaryFileSha256(self, url_or_filename): + ''' + Returns the SHA256 checksum for the specified binary file url. + + If the url is not found in the binaryFileUrls(), this returns None. + + The url may be specified as a filename. + ''' + for f in self.binaryFileUrls(include_meta=True): + if url_or_filename in [f['url'], f['filename']]: + return f['sha256'] + return None + + def binaryFileSize(self, url_or_filename): + ''' + Returns the size for the specified binary file url. + + If the url is not found in the binaryFileUrls(), this returns 0. + + The url may be specified as a filename. ''' + for f in self.binaryFileUrls(include_meta=True): + if url_or_filename in [f['url'], f['filename']]: + return int(f['size']) + return 0 + + def getBuild(self): + ''' + Returns the original build of the binary package. + ''' + return Build(self._lpobject.build_link) + + def getUrl(self): + ''' + Returns the original build URL of the binary package. + ''' + return "{build}/+files/{filename}".format(build=self.getBuild().getUrl(), + filename=self.getFileName()) + + def getFileVersion(self): + ''' + Returns the file version, which is the package version without the epoch + ''' + return Version(self.getVersion()).strip_epoch() + + def getFileArch(self): + ''' + Returns the file arch, which is 'all' if not arch-specific + ''' + if bool(self._lpobject.architecture_specific): + return self.arch + else: + return 'all' + + def getFileExt(self): + ''' + Returns the file extension; "deb", "ddeb", or "udeb". + ''' + if not self._ext: + self._ext = self._getFileExt() + + return self._ext + + def _getFileExt(self): try: - return self._lpobject.binaryFileUrls() + # this is the best way, from the actual URL filename + return self.binaryFileUrls()[0].rpartition('.')[2] + except (AttributeError, IndexError): + Logger.debug('Could not get file ext from url, trying to guess...') + + # is_debug should be reliable way of detecting ddeb...? + try: + if self.is_debug: + return "ddeb" except AttributeError: - raise AttributeError("binaryFileUrls can only be found in lpapi " - "devel, not 1.0. Login using devel to have it.") + # is_debug only available with api version 'devel' + if self.getPackageName().endswith("-dbgsym"): + return "ddeb" + + # is this reliable? + if self.getPackageName().endswith("-di") or self.getPackageName().endswith("-udeb"): + return "udeb" + + # everything else - assume regular deb + return "deb" + + def getFileName(self): + ''' + Returns the filename for this binary package. + ''' + return "{name}_{version}_{arch}.{ext}".format(name=self.getPackageName(), + version=self.getFileVersion(), + arch=self.getFileArch(), + ext=self.getFileExt()) class MetaPersonTeam(MetaWrapper): @@ -709,7 +1308,8 @@ ''' if '_me' not in cls.__dict__: try: - cls._me = PersonTeam(Launchpad.me) + # We have to use me.self_link due to LP: #504297 + cls._me = PersonTeam(Launchpad.me.self_link) except HTTPError as error: if error.response.status == 401: # Anonymous login @@ -719,8 +1319,7 @@ return cls._me -@add_metaclass(MetaPersonTeam) -class PersonTeam(BaseWrapper): +class PersonTeam(BaseWrapper, metaclass=MetaPersonTeam): ''' Wrapper class around a LP person or team object. ''' @@ -729,6 +1328,7 @@ def __init__(self, *args): # Don't share _upload between different PersonTeams + self._ppas = None if '_upload' not in self.__dict__: self._upload = dict() @@ -743,7 +1343,7 @@ ''' Fetch the person or team object identified by 'url' from LP. ''' - if not isinstance(person_or_team, basestring): + if not isinstance(person_or_team, str): raise TypeError("Don't know what do with '%r'" % person_or_team) cached = cls._cache.get(person_or_team) if not cached: @@ -771,14 +1371,14 @@ raise TypeError("'%r' is not an Archive object." % archive) if not isinstance(distroseries, DistroSeries): raise TypeError("'%r' is not a DistroSeries object." % distroseries) - if package is not None and not isinstance(package, basestring): + if package is not None and not isinstance(package, str): raise TypeError('A source package name expected.') - if component is not None and not isinstance(component, basestring): + if component is not None and not isinstance(component, str): raise TypeError('A component name expected.') if package is None and component is None: raise ValueError('Either a source package name or a component has ' 'to be specified.') - if pocket not in _POCKETS: + if pocket not in POCKETS: raise PocketDoesNotExistError("Pocket '%s' does not exist." % pocket) @@ -806,6 +1406,54 @@ return canUpload + def getPPAs(self): + if self._ppas is None: + ppas = [Archive(ppa['self_link']) for ppa in + Launchpad.load(self._lpobject.ppas_collection_link).entries] + self._ppas = {ppa.name: ppa for ppa in ppas} + return self._ppas + + def getPPAByName(self, name): + return Archive(self._lpobject.getPPAByName(name=name)) + + +class Project(BaseWrapper): + ''' + Wrapper class around a LP project object. + ''' + resource_type = ('project') + + def __init__(self, *args): + self._series = None + + @property + def series(self): + """Get a list of all ProjectSeries + + The list will be sorted by date_created, in descending order. + """ + if not self._series: + series = [ProjectSeries(s['self_link']) for s in + Launchpad.load(self._lpobject.series_collection_link).entries] + self._series = sorted(series, key=lambda s: s.date_created, reverse=True) + return self._series.copy() + + @classmethod + def fetch(cls, project): + ''' + Fetch the project object identified by 'project' from LP. + ''' + if not isinstance(project, str): + raise TypeError("Don't know what do with '%r'" % project) + return Project(Launchpad.projects(project)) + + +class ProjectSeries(BaseWrapper): + ''' + Wrapper class around a LP project_series object. + ''' + resource_type = ('project_series') + class Build(BaseWrapper): ''' @@ -816,6 +1464,18 @@ def __str__(self): return u'%s: %s' % (self.arch_tag, self.buildstate) + def getSourcePackagePublishingHistory(self): + link = self._lpobject.current_source_publication_link + if link: + if re.search('redacted', link): + # Too old - the link has been 'redacted' + return None + return SourcePackagePublishingHistory(link) + return None + + def getUrl(self): + return self() + def rescore(self, score): if self.can_be_rescored: self().rescore(score=score) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/lp/udtexceptions.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/lp/udtexceptions.py --- ubuntu-dev-tools-0.164/ubuntutools/lp/udtexceptions.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/lp/udtexceptions.py 2019-12-01 18:18:32.000000000 +0000 @@ -26,3 +26,8 @@ class ArchSeriesNotFoundException(BaseException): """Thrown when a distroarchseries is not found.""" pass + + +class InvalidDistroValueError(ValueError): + """ Thrown when distro value is invalid """ + pass diff -Nru ubuntu-dev-tools-0.164/ubuntutools/misc.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/misc.py --- ubuntu-dev-tools-0.164/ubuntutools/misc.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/misc.py 2021-12-05 15:20:37.000000000 +0000 @@ -22,21 +22,49 @@ # # ################################################################## -from __future__ import print_function - -# Modules. +import distro_info +import hashlib import locale import os +import requests +import shutil import sys +import tempfile -import distro_info +from contextlib import suppress +from pathlib import Path +from subprocess import check_output, CalledProcessError +from urllib.parse import urlparse from ubuntutools.lp.udtexceptions import PocketDoesNotExistError -from ubuntutools.subprocess import Popen, PIPE + +import logging +Logger = logging.getLogger(__name__) + + +DEFAULT_POCKETS = ('Release', 'Security', 'Updates', 'Proposed') +POCKETS = DEFAULT_POCKETS + ('Backports',) + +DEFAULT_STATUSES = ('Pending', 'Published') +STATUSES = DEFAULT_STATUSES + ('Superseded', 'Deleted', 'Obsolete') + +UPLOAD_QUEUE_STATUSES = ('New', 'Unapproved', 'Accepted', 'Done', 'Rejected') + +DOWNLOAD_BLOCKSIZE_DEFAULT = 8192 _system_distribution_chain = [] +class DownloadError(Exception): + "Unable to pull a source package" + pass + + +class NotFoundError(DownloadError): + "Source package not found" + pass + + def system_distribution_chain(): """ system_distribution_chain() -> [string] @@ -49,29 +77,22 @@ global _system_distribution_chain if len(_system_distribution_chain) == 0: try: - p = Popen(('dpkg-vendor', '--query', 'Vendor'), - stdout=PIPE) - _system_distribution_chain.append(p.communicate()[0].strip()) - except OSError: - print('Error: Could not determine what distribution you are running.') + vendor = check_output(('dpkg-vendor', '--query', 'Vendor'), + encoding='utf-8').strip() + _system_distribution_chain.append(vendor) + except CalledProcessError: + Logger.error('Could not determine what distribution you are running.') return [] while True: try: - p = Popen(('dpkg-vendor', - '--vendor', _system_distribution_chain[-1], - '--query', 'Parent'), - stdout=PIPE) - parent = p.communicate()[0].strip() - # Don't check return code, because if a vendor has no - # parent, dpkg-vendor returns 1 - if not parent: - break - _system_distribution_chain.append(parent) - except Exception: - print(('Error: Could not determine the parent of the ' - 'distribution %s' % _system_distribution_chain[-1])) - return [] + parent = check_output(( + 'dpkg-vendor', '--vendor', _system_distribution_chain[-1], + '--query', 'Parent'), encoding='utf-8').strip() + except CalledProcessError: + # Vendor has no parent + break + _system_distribution_chain.append(parent) return _system_distribution_chain @@ -93,14 +114,18 @@ architecture can't be determined, print an error message and return None. """ - arch = Popen(['dpkg', '--print-architecture'], stdout=PIPE, - stderr=PIPE).communicate()[0].split() - - if not arch or 'not found' in arch[0]: - print('Error: Not running on a Debian based system; could not detect its architecture.') + try: + arch = check_output(('dpkg', '--print-architecture'), + encoding='utf-8').strip() + except CalledProcessError: + arch = None + + if not arch or 'not found' in arch: + Logger.error('Not running on a Debian based system; ' + 'could not detect its architecture.') return None - return arch[0] + return arch def readlist(filename, uniq=True): @@ -109,15 +134,16 @@ Read a list of words from the indicated file. If 'uniq' is True, filter out duplicated words. """ + p = Path(filename) - if not os.path.isfile(filename): - print('File "%s" does not exist.' % filename) + if not p.is_file(): + Logger.error(f'File {p} does not exist.') return False - content = open(filename).read().replace('\n', ' ').replace(',', ' ') + content = p.read_text().replace('\n', ' ').replace(',', ' ') if not content.strip(): - print('File "%s" is empty.' % filename) + Logger.error(f'File {p} is empty.') return False items = [item for item in content.split() if item] @@ -145,7 +171,7 @@ (release, pocket) = release.rsplit('-', 1) pocket = pocket.capitalize() - if pocket not in ('Release', 'Security', 'Updates', 'Proposed', 'Backports'): + if pocket not in POCKETS: raise PocketDoesNotExistError("Pocket '%s' does not exist." % pocket) return (release, pocket) @@ -154,7 +180,7 @@ def require_utf8(): '''Can be called by programs that only function in UTF-8 locales''' if locale.getpreferredencoding() != 'UTF-8': - print("This program only functions in a UTF-8 locale. Aborting.", file=sys.stderr) + Logger.error("This program only functions in a UTF-8 locale. Aborting.") sys.exit(1) @@ -186,3 +212,246 @@ if info().valid(codename): return distro + + +def verify_file_checksums(pathname, checksums={}, size=0): + """ verify checksums of file + + Any failure will log an error. + + pathname: str or Path + full path to file + checksums: dict + keys are alg name, values are expected checksum + size: int + size of file, if known + + Returns True if all checks pass, False otherwise + """ + p = Path(pathname) + + if not p.is_file(): + Logger.error(f'File {p} not found') + return False + filesize = p.stat().st_size + if size and size != filesize: + Logger.error(f'File {p} incorrect size, got {filesize} expected {size}') + return False + + for (alg, checksum) in checksums.items(): + h = hashlib.new(alg) + with p.open('rb') as f: + while True: + block = f.read(h.block_size) + if len(block) == 0: + break + h.update(block) + digest = h.hexdigest() + if digest == checksum: + Logger.debug(f'File {p} checksum ({alg}) verified: {checksum}') + else: + Logger.error(f'File {p} checksum ({alg}) mismatch: got {digest} expected {checksum}') + return False + return True + + +def verify_file_checksum(pathname, alg, checksum, size=0): + """ verify checksum of file + + pathname: str or Path + full path to file + alg: str + name of checksum alg + checksum: str + expected checksum + size: int + size of file, if known + + Returns True if all checks pass, False otherwise + """ + return verify_file_checksums(pathname, {alg: checksum}, size) + + +def extract_authentication(url): + """ Remove plaintext authentication data from a URL + + If the URL has a username:password in its netloc, this removes it + and returns the remaining URL, along with the username and password + separately. If no authentication data is in the netloc, this just + returns the URL unchanged with None for the username and password. + + This returns a tuple in the form (url, username, password) + """ + u = urlparse(url) + if u.username or u.password: + return (u._replace(netloc=u.hostname).geturl(), u.username, u.password) + return (url, None, None) + + +def download(src, dst, size=0, *, blocksize=DOWNLOAD_BLOCKSIZE_DEFAULT): + """ download/copy a file/url to local file + + src: str or Path + Source to copy from (file path or url) + dst: str or Path + Destination dir or filename + size: int + Size of source, if known + blocksize: int or None + Blocksize to use when downloading + + If the URL contains authentication data in the URL 'netloc', + it will be stripped from the URL and passed to the requests library. + + This may throw a DownloadError. + + On success, this will return the dst as a Path object. + """ + src = str(src) + parsedsrc = urlparse(src) + + dst = Path(dst).expanduser().resolve() + if dst.is_dir(): + dst = dst / Path(parsedsrc.path).name + + # Copy if src is a local file + if parsedsrc.scheme in ['', 'file']: + src = Path(parsedsrc.path).expanduser().resolve() + if src != parsedsrc.path: + Logger.info(f'Parsed {parsedsrc.path} as {src}') + if not src.exists(): + raise NotFoundError(f'Source file {src} not found') + if dst.exists(): + if src.samefile(dst): + Logger.info(f'Using existing file {dst}') + return dst + Logger.info(f'Replacing existing file {dst}') + Logger.info(f'Copying file {src} to {dst}') + shutil.copyfile(src, dst) + return dst + + (src, username, password) = extract_authentication(src) + auth = (username, password) if username or password else None + + with tempfile.TemporaryDirectory() as d: + tmpdst = Path(d) / 'dst' + try: + with requests.get(src, stream=True, auth=auth) as fsrc, tmpdst.open('wb') as fdst: + fsrc.raise_for_status() + _download(fsrc, fdst, size, blocksize=blocksize) + except requests.exceptions.HTTPError as e: + if e.response is not None and e.response.status_code == 404: + raise NotFoundError(f'URL {src} not found: {e}') + raise DownloadError(e) + except requests.exceptions.ConnectionError as e: + # This is likely a archive hostname that doesn't resolve, like 'ftpmaster.internal' + raise NotFoundError(f'URL {src} not found: {e}') + except requests.exceptions.RequestException as e: + raise DownloadError(e) + shutil.move(tmpdst, dst) + return dst + + +class _StderrProgressBar(object): + BAR_WIDTH_MIN = 40 + BAR_WIDTH_DEFAULT = 60 + + def __init__(self, max_width): + self.full_width = min(max_width, self.BAR_WIDTH_DEFAULT) + self.width = self.full_width - len('[] 99%') + self.show_progress = self.full_width >= self.BAR_WIDTH_MIN + + def update(self, progress, total): + if not self.show_progress: + return + pct = progress * 100 // total + pctstr = f'{pct:>3}%' + barlen = self.width * pct // 100 + barstr = '=' * barlen + barstr = barstr[:-1] + '>' + barstr = barstr.ljust(self.width) + fullstr = f'\r[{barstr}]{pctstr}' + sys.stderr.write(fullstr) + sys.stderr.flush() + + def finish(self): + if not self.show_progress: + return + sys.stderr.write('\n') + sys.stderr.flush() + + +def _download(fsrc, fdst, size, *, blocksize): + """ helper method to download src to dst using requests library. """ + url = fsrc.url + Logger.debug(f'Using URL: {url}') + + if not size: + with suppress(AttributeError, TypeError, ValueError): + size = int(fsrc.headers.get('Content-Length')) + + parsed = urlparse(url) + filename = Path(parsed.path).name + hostname = parsed.hostname + sizemb = ' (%0.3f MiB)' % (size / 1024.0 / 1024) if size else '' + Logger.info(f'Downloading {filename} from {hostname}{sizemb}') + + # Don't show progress if: + # logging INFO is suppressed + # stderr isn't a tty + # we don't know the total file size + # the file is content-encoded (i.e. compressed) + show_progress = all((Logger.isEnabledFor(logging.INFO), + sys.stderr.isatty(), + size > 0, + 'Content-Encoding' not in fsrc.headers)) + + terminal_width = 0 + if show_progress: + try: + terminal_width = os.get_terminal_size(sys.stderr.fileno()).columns + except Exception as e: + Logger.error(f'Error finding stderr width, suppressing progress bar: {e}') + progress_bar = _StderrProgressBar(max_width=terminal_width) + + downloaded = 0 + try: + for block in fsrc.iter_content(blocksize): + fdst.write(block) + downloaded += len(block) + progress_bar.update(downloaded, size) + finally: + progress_bar.finish() + if size and size > downloaded: + Logger.error('Partial download: %0.3f MiB of %0.3f MiB' % + (downloaded / 1024.0 / 1024, + size / 1024.0 / 1024)) + + +def _download_text(src, binary, *, blocksize): + with tempfile.TemporaryDirectory() as d: + dst = Path(d) / 'dst' + download(src, dst, blocksize=blocksize) + return dst.read_bytes() if binary else dst.read_text() + + +def download_text(src, mode=None, *, blocksize=DOWNLOAD_BLOCKSIZE_DEFAULT): + """ Return the text content of a downloaded file + + src: str or Path + Source to copy from (file path or url) + mode: str + Deprecated, ignored unless a string that contains 'b' + blocksize: int or None + Blocksize to use when downloading + + Raises the same exceptions as download() + + Returns text content of downloaded file + """ + return _download_text(src, binary='b' in (mode or ''), blocksize=blocksize) + + +def download_bytes(src, *, blocksize=DOWNLOAD_BLOCKSIZE_DEFAULT): + """ Same as download_text() but returns bytes """ + return _download_text(src, binary=True, blocksize=blocksize) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/pullpkg.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/pullpkg.py --- ubuntu-dev-tools-0.164/ubuntutools/pullpkg.py 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/pullpkg.py 2021-12-05 15:20:37.000000000 +0000 @@ -0,0 +1,597 @@ +# pullpkg.py -- pull package files for debian/ubuntu/uca +# modified from ../pull-lp-source and converted to module +# +# Copyright (C) 2008, Iain Lane , +# 2010-2011, Stefano Rivera +# 2017, Dan Streetman +# +# ################################################################## +# +# 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 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. +# +# See file /usr/share/common-licenses/GPL for more details. +# +# ################################################################## + + +import os +import re +import sys +import errno +import subprocess + +from argparse import ArgumentParser + +from distro_info import DebianDistroInfo + +from urllib.parse import urlparse + +from ubuntutools.archive import (UbuntuSourcePackage, DebianSourcePackage, + UbuntuCloudArchiveSourcePackage, + PersonalPackageArchiveSourcePackage) +from ubuntutools.config import UDTConfig +from ubuntutools.lp.lpapicache import (Distribution, Launchpad) +from ubuntutools.lp.udtexceptions import (AlreadyLoggedInError, + SeriesNotFoundException, + PackageNotFoundException, + PocketDoesNotExistError, + InvalidDistroValueError) +from ubuntutools.misc import (split_release_pocket, + host_architecture, + download, + UPLOAD_QUEUE_STATUSES, + STATUSES) + + +# by default we use standard logging.getLogger() and only use +# ubuntutools.getLogger() in PullPkg().main() +from ubuntutools import getLogger as ubuntutools_getLogger +import logging +Logger = logging.getLogger(__name__) + +PULL_SOURCE = 'source' +PULL_DEBS = 'debs' +PULL_DDEBS = 'ddebs' +PULL_UDEBS = 'udebs' +PULL_LIST = 'list' + +VALID_PULLS = [PULL_SOURCE, PULL_DEBS, PULL_DDEBS, PULL_UDEBS, PULL_LIST] +VALID_BINARY_PULLS = [PULL_DEBS, PULL_DDEBS, PULL_UDEBS] + +DISTRO_DEBIAN = 'debian' +DISTRO_UBUNTU = 'ubuntu' +DISTRO_UCA = 'uca' +DISTRO_PPA = 'ppa' + +DISTRO_PKG_CLASS = { + DISTRO_DEBIAN: DebianSourcePackage, + DISTRO_UBUNTU: UbuntuSourcePackage, + DISTRO_UCA: UbuntuCloudArchiveSourcePackage, + DISTRO_PPA: PersonalPackageArchiveSourcePackage, +} +VALID_DISTROS = DISTRO_PKG_CLASS.keys() + + +class InvalidPullValueError(ValueError): + """ Thrown when --pull value is invalid """ + pass + + +class PullPkg(object): + """Class used to pull file(s) associated with a specific package""" + @classmethod + def main(cls, *args, **kwargs): + """For use by stand-alone cmdline scripts. + + This will handle catching certain exceptions or kbd interrupts, + setting up the root logger level to INFO, and printing out + (via Logger) a caught error message, instead of allowing the + exception to flow up to the script. This does not catch + unexpected exceptions, such as internal errors. + + On (expected) error, this will call sys.exit(error); + unexpected errors will flow up to the caller. + On success, this simply returns. + """ + Logger = ubuntutools_getLogger() + + try: + cls(*args, **kwargs).pull() + return + except KeyboardInterrupt: + Logger.info('User abort.') + except (PackageNotFoundException, SeriesNotFoundException, + PocketDoesNotExistError, InvalidDistroValueError, + InvalidPullValueError) as e: + Logger.error(str(e)) + sys.exit(errno.ENOENT) + + def __init__(self, *args, **kwargs): + self._default_pull = kwargs.get('pull') + self._default_distro = kwargs.get('distro') + self._default_arch = kwargs.get('arch', host_architecture()) + + def parse_args(self, args): + args = args[:] + + help_default_pull = "What to pull: " + ", ".join(VALID_PULLS) + if self._default_pull: + help_default_pull += (" (default: %s)" % self._default_pull) + help_default_distro = "Pull from: " + ", ".join(VALID_DISTROS) + if self._default_distro: + help_default_distro += (" (default: %s)" % self._default_distro) + help_default_arch = ("Get binary packages for arch") + help_default_arch += ("(default: %s)" % self._default_arch) + + # use add_help=False because we do parse_known_args() below, and if + # that sees --help then it exits immediately + parser = ArgumentParser(add_help=False) + parser.add_argument('-L', '--login', action='store_true', + help="Login to Launchpad") + parser.add_argument('-v', '--verbose', action='count', default=0, + help="Increase verbosity/debug") + parser.add_argument('-d', '--download-only', action='store_true', + help="Do not extract the source package") + parser.add_argument('-m', '--mirror', action='append', + help='Preferred mirror(s)') + parser.add_argument('--no-conf', action='store_true', + help="Don't read config files or environment variables") + parser.add_argument('--no-verify-signature', action='store_true', + help="Don't fail if dsc signature can't be verified") + parser.add_argument('-s', '--status', action='append', default=[], + help="Search for packages with specific status(es)") + parser.add_argument('-a', '--arch', default=self._default_arch, + help=help_default_arch) + parser.add_argument('-p', '--pull', default=self._default_pull, + help=help_default_pull) + parser.add_argument('-D', '--distro', default=self._default_distro, + help=help_default_distro) + + # add distro-specific params + try: + distro = self.parse_distro(parser.parse_known_args(args)[0].distro) + except InvalidDistroValueError: + # don't fail at this point, finish setting up parser help/usage + distro = None + + if distro == DISTRO_UBUNTU: + parser.add_argument('--security', action='store_true', + help='Pull from the Ubuntu Security Team (proposed) PPA') + parser.add_argument('--upload-queue', action='store_true', + help='Pull from the Ubuntu upload queue') + if distro == DISTRO_PPA: + parser.add_argument('--ppa', help='PPA to pull from') + if parser.parse_known_args(args)[0].ppa is None: + # check for any param starting with "ppa:" + # if found, move it to a --ppa param + for param in args: + if param.startswith('ppa:'): + args.remove(param) + args.insert(0, param) + args.insert(0, '--ppa') + break + + # add the positional params + parser.add_argument('package', help="Package name to pull") + parser.add_argument('release', nargs='?', help="Release to pull from") + parser.add_argument('version', nargs='?', help="Package version to pull") + + epilog = ("Note on --status: if a version is provided, all status types " + "will be searched; if no version is provided, by default only " + "'Pending' and 'Published' status will be searched.") + + # since parser has no --help handler, create a new parser that does + newparser = ArgumentParser(parents=[parser], epilog=epilog) + + return self.parse_options(vars(newparser.parse_args(args))) + + def parse_pull(self, pull): + if not pull: + raise InvalidPullValueError("Must specify --pull") + + # allow 'dbgsym' as alias for 'ddebs' + if pull == 'dbgsym': + Logger.debug("Pulling '%s' for '%s'", PULL_DDEBS, pull) + pull = PULL_DDEBS + # assume anything starting with 'bin' means 'debs' + if str(pull).startswith('bin'): + Logger.debug("Pulling '%s' for '%s'", PULL_DEBS, pull) + pull = PULL_DEBS + # verify pull action is valid + if pull not in VALID_PULLS: + raise InvalidPullValueError("Invalid pull action '%s'" % pull) + + return pull + + def parse_distro(self, distro): + if not distro: + raise InvalidDistroValueError("Must specify --distro") + + distro = distro.lower() + + # allow 'lp' for 'ubuntu' + if distro == 'lp': + Logger.debug("Using distro '%s' for '%s'", DISTRO_UBUNTU, distro) + distro = DISTRO_UBUNTU + # assume anything with 'cloud' is UCA + if re.match(r'.*cloud.*', distro): + Logger.debug("Using distro '%s' for '%s'", DISTRO_UCA, distro) + distro = DISTRO_UCA + # verify distro is valid + if distro not in VALID_DISTROS: + raise InvalidDistroValueError("Invalid distro '%s'" % distro) + + return distro + + def parse_release(self, distro, release): + if distro == DISTRO_UCA: + return UbuntuCloudArchiveSourcePackage.parseReleaseAndPocket(release) + + # Check if release[-pocket] is specified + (release, pocket) = split_release_pocket(release, default=None) + Logger.debug("Parsed release '%s' pocket '%s'", release, pocket) + + if distro == DISTRO_DEBIAN: + # This converts from the aliases like 'unstable' + debian_info = DebianDistroInfo() + codename = debian_info.codename(release) + if codename: + Logger.info("Using release '%s' for '%s'", codename, release) + release = codename + + if distro == DISTRO_PPA: + # PPAs are part of Ubuntu distribution + d = Distribution(DISTRO_UBUNTU) + else: + d = Distribution(distro) + + # let SeriesNotFoundException flow up + d.getSeries(release) + + Logger.debug("Using distro '%s' release '%s' pocket '%s'", + distro, release, pocket) + return (release, pocket) + + def parse_release_and_version(self, distro, release, version, try_swap=True): + # Verify specified release is valid, and params in correct order + pocket = None + try: + (release, pocket) = self.parse_release(distro, release) + except (SeriesNotFoundException, PocketDoesNotExistError): + if try_swap: + Logger.debug("Param '%s' not valid series, must be version", release) + release, version = version, release + if release: + return self.parse_release_and_version(distro, release, version, False) + else: + Logger.error("Can't find series for '%s' or '%s'", release, version) + raise + return (release, version, pocket) + + def parse_options(self, options): + # if any of these fail, there is a problem with the parser + # they should all be provided, though the optional ones may be None + + # type bool + assert 'verbose' in options + assert 'download_only' in options + assert 'no_conf' in options + assert 'no_verify_signature' in options + assert 'status' in options + # type string + assert 'pull' in options + assert 'distro' in options + assert 'arch' in options + assert 'package' in options + # type string, optional + assert 'release' in options + assert 'version' in options + # type list of strings, optional + assert 'mirror' in options + + options['pull'] = self.parse_pull(options['pull']) + options['distro'] = self.parse_distro(options['distro']) + + # ensure these are always included so we can just check for None/False later + options['ppa'] = options.get('ppa', None) + options['security'] = options.get('security', False) + options['upload_queue'] = options.get('upload_queue', False) + + return options + + def _get_params(self, options): + distro = options['distro'] + pull = options['pull'] + + params = {} + params['package'] = options['package'] + + if options['release']: + (r, v, p) = self.parse_release_and_version(distro, options['release'], + options['version']) + params['series'] = r + params['version'] = v + params['pocket'] = p + + if (params['package'].endswith('.dsc') and not params['series'] and not params['version']): + params['dscfile'] = params['package'] + params.pop('package') + + if options['security']: + if options['ppa']: + Logger.warning('Both --security and --ppa specified, ignoring --ppa') + Logger.debug('Checking Ubuntu Security PPA') + # --security is just a shortcut for --ppa ppa:ubuntu-security-proposed/ppa + options['ppa'] = 'ubuntu-security-proposed/ppa' + + if options['ppa']: + if options['ppa'].startswith('ppa:'): + params['ppa'] = options['ppa'][4:] + else: + params['ppa'] = options['ppa'] + elif distro == DISTRO_PPA: + raise ValueError('Must specify PPA to pull from') + + mirrors = [] + if options['mirror']: + mirrors.extend(options['mirror']) + if pull == PULL_DDEBS: + config = UDTConfig(options['no_conf']) + ddebs_mirror = config.get_value(distro.upper() + '_DDEBS_MIRROR') + if ddebs_mirror: + mirrors.append(ddebs_mirror) + if mirrors: + Logger.debug("using mirrors %s", ", ".join(mirrors)) + params['mirrors'] = mirrors + + params['verify_signature'] = not options['no_verify_signature'] + + params['status'] = STATUSES if 'all' in options['status'] else options['status'] + + # special handling for upload queue + if options['upload_queue']: + if len(options['status']) > 1: + raise ValueError("Too many --status provided, " + "can only search for a single status or 'all'") + if not options['status']: + params['status'] = None + elif options['status'][0].lower() == 'all': + params['status'] = 'all' + elif options['status'][0].capitalize() in UPLOAD_QUEUE_STATUSES: + params['status'] = options['status'][0].capitalize() + else: + msg = ("Invalid upload queue status '%s': valid values are %s" % + (options['status'][0], ', '.join(UPLOAD_QUEUE_STATUSES))) + raise ValueError(msg) + + return params + + def pull(self, args=sys.argv[1:]): + """Pull (download) specified package file(s)""" + options = self.parse_args(args) + + if options['verbose']: + Logger.setLevel(logging.DEBUG) + if options['verbose'] > 1: + logging.getLogger(__package__).setLevel(logging.DEBUG) + + Logger.debug("pullpkg options: %s", options) + + pull = options['pull'] + distro = options['distro'] + + if options['login']: + Logger.debug("Logging in to Launchpad:") + try: + Launchpad.login() + except AlreadyLoggedInError: + Logger.error("Launchpad singleton has already performed a login, " + "and its design prevents another login") + Logger.warning("Continuing anyway, with existing Launchpad instance") + + params = self._get_params(options) + package = params['package'] + + if options['upload_queue']: + # upload queue API is different/simpler + self.pull_upload_queue(pull, arch=options['arch'], + download_only=options['download_only'], + **params) + return + + # call implementation, and allow exceptions to flow up to caller + srcpkg = DISTRO_PKG_CLASS[distro](**params) + spph = srcpkg.lp_spph + + Logger.info('Found %s', spph.display_name) + + if pull == PULL_LIST: + Logger.info("Source files:") + for f in srcpkg.dsc['Files']: + Logger.info(" %s", f['name']) + Logger.info("Binary files:") + for f in spph.getBinaries(options['arch']): + archtext = '' + name = f.getFileName() + if name.rpartition('.')[0].endswith('all'): + archtext = f" ({f.arch})" + Logger.info(f" {name}{archtext}") + elif pull == PULL_SOURCE: + # allow DownloadError to flow up to caller + srcpkg.pull() + if options['download_only']: + Logger.debug("--download-only specified, not extracting") + else: + srcpkg.unpack() + elif pull in VALID_BINARY_PULLS: + name = None + if package != spph.getPackageName(): + Logger.info("Pulling only binary package '%s'", package) + Logger.info("Use package name '%s' to pull all binary packages", + spph.getPackageName()) + name = package + + # e.g. 'debs' -> 'deb' + ext = pull.rstrip('s') + + if distro == DISTRO_DEBIAN: + # Debian ddebs don't use .ddeb extension, unfortunately :( + if pull in [PULL_DEBS, PULL_DDEBS]: + name = name or '.*' + ext = 'deb' + if pull == PULL_DEBS: + name += r'(? 1: + msg = "Found multiple packages" + if version: + msg += " with version %s, please specify the ID instead" % version + else: + msg += ", please specify the version" + Logger.error("Available package versions/ids are:") + for p in packages: + Logger.error("%s %s (id %s)" % (p.package_name, p.package_version, p.id)) + raise PackageNotFoundException(msg) + + p = packages[0] + + urls = set(p.customFileUrls()) + if p.changesFileUrl(): + urls.add(p.changesFileUrl()) + + if pull == PULL_SOURCE: + urls |= set(p.sourceFileUrls()) + if not urls: + Logger.error("No source files to download") + dscfile = None + for url in urls: + dst = download(url, os.getcwd()) + if dst.name.endswith('.dsc'): + dscfile = dst + if download_only: + Logger.debug("--download-only specified, not extracting") + elif not dscfile: + Logger.error("No source dsc file found, cannot extract") + else: + cmd = ['dpkg-source', '-x', dscfile.name] + Logger.debug(' '.join(cmd)) + result = subprocess.run(cmd, encoding='utf-8', + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if result.returncode != 0: + Logger.error('Source unpack failed.') + Logger.debug(result.stdout) + else: + name = '.*' + if pull == PULL_DEBS: + name = r'{}(? max_number: + while not selected or selected < min_number or selected > max_number: try: selected = input(question).strip() except (EOFError, KeyboardInterrupt): @@ -133,7 +127,7 @@ def edit(self, optional=False): if optional: print("\n\nCurrently the %s looks like:" % self.description) - with open(self.filename, 'r') as f: + with open(self.filename, 'r', encoding='utf-8') as f: print(f.read()) if YesNoQuestion().ask("Edit", "no") == "no": return @@ -141,12 +135,11 @@ done = False while not done: old_mtime = os.stat(self.filename).st_mtime - ubuntutools.subprocess.check_call(['sensible-editor', - self.filename]) + subprocess.check_call(['sensible-editor', self.filename]) modified = old_mtime != os.stat(self.filename).st_mtime placeholders_present = False if self.placeholders: - with open(self.filename, 'r') as f: + with open(self.filename, 'r', encoding='utf-8') as f: for line in f: for placeholder in self.placeholders: if placeholder.search(line.strip()): @@ -188,8 +181,8 @@ placeholders) def check_edit(self): - with open(self.filename, 'r') as f: - report = f.read().decode('utf-8') + with open(self.filename, 'r', encoding='utf-8') as f: + report = f.read() if self.split_re.match(report) is None: print("The %s doesn't start with 'Summary:' and 'Description:' " @@ -199,8 +192,8 @@ return True def get_report(self): - with open(self.filename, 'r') as f: - report = f.read().decode('utf-8') + with open(self.filename, 'r', encoding='utf-8') as f: + report = f.read() match = self.split_re.match(report) title = match.group(1).replace(u'\n', u' ') diff -Nru ubuntu-dev-tools-0.164/ubuntutools/requestsync/lp.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/requestsync/lp.py --- ubuntu-dev-tools-0.164/ubuntutools/requestsync/lp.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/requestsync/lp.py 2019-12-01 18:18:32.000000000 +0000 @@ -20,8 +20,6 @@ # Please see the /usr/share/common-licenses/GPL-2 file for the full text # of the GNU General Public License license. -from __future__ import print_function - import re from debian.deb822 import Changes @@ -31,9 +29,11 @@ from ubuntutools.lp import udtexceptions from ubuntutools.lp.lpapicache import (Launchpad, Distribution, PersonTeam, DistributionSourcePackage) -from ubuntutools.logger import Logger from ubuntutools.question import confirmation_prompt +import logging +Logger = logging.getLogger(__name__) + def get_debian_srcpkg(name, release): debian = Distribution('debian') @@ -42,7 +42,7 @@ try: release = DebianDistroInfo().codename(release, None, release) except DistroDataOutdated as e: - Logger.warn(e) + Logger.warning(e) return debian_archive.getSourcePackage(name, release) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/requestsync/mail.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/requestsync/mail.py --- ubuntu-dev-tools-0.164/ubuntutools/requestsync/mail.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/requestsync/mail.py 2019-12-01 18:18:32.000000000 +0000 @@ -20,27 +20,23 @@ # Please see the /usr/share/common-licenses/GPL-2 file for the full text # of the GNU General Public License license. -from __future__ import print_function - import os import re import sys import smtplib import socket +import subprocess import tempfile -from debian.changelog import Changelog, Version +from debian.changelog import Changelog from distro_info import DebianDistroInfo, DistroDataOutdated -from ubuntutools.archive import rmadison, FakeSPPH +from ubuntutools.archive import DebianSourcePackage, UbuntuSourcePackage from ubuntutools.lp.udtexceptions import PackageNotFoundException -from ubuntutools.logger import Logger from ubuntutools.question import confirmation_prompt, YesNoQuestion -from ubuntutools import subprocess -if sys.version_info[0] >= 3: - basestring = str - unicode = str +import logging +Logger = logging.getLogger(__name__) __all__ = [ @@ -53,32 +49,21 @@ ] -def _get_srcpkg(distro, name, release): - if distro == 'debian': - # Canonicalise release: - debian_info = DebianDistroInfo() - try: - codename = debian_info.codename(release, default=release) - except DistroDataOutdated as e: - Logger.warn(e) - - lines = list(rmadison(distro, name, suite=codename, arch='source')) - if not lines: - lines = list(rmadison(distro, name, suite=release, arch='source')) - if not lines: - raise PackageNotFoundException("'%s' doesn't appear to exist in %s '%s'" % - (name, distro.capitalize(), release)) - pkg = max(lines, key=lambda x: Version(x['version'])) - - return FakeSPPH(pkg['source'], pkg['version'], pkg['component'], distro) - - def get_debian_srcpkg(name, release): - return _get_srcpkg('debian', name, release) + # Canonicalise release: + debian_info = DebianDistroInfo() + try: + codename = debian_info.codename(release, default=release) + return DebianSourcePackage(package=name, series=codename).lp_spph + except DistroDataOutdated as e: + Logger.warning(e) + except PackageNotFoundException: + pass + return DebianSourcePackage(package=name, series=release).lp_spph def get_ubuntu_srcpkg(name, release): - return _get_srcpkg('ubuntu', name, release) + return UbuntuSourcePackage(package=name, series=release).lp_spph def need_sponsorship(name, component, release): @@ -110,17 +95,17 @@ ''' changelog = Changelog(srcpkg.getChangelog()) if changelog is None: - return u'' + return '' delta = [] debian_info = DebianDistroInfo() for block in changelog: distribution = block.distributions.split()[0].split('-')[0] if debian_info.valid(distribution): break - delta += [unicode(change) for change in block.changes() + delta += [str(change) for change in block.changes() if change.strip()] - return u'\n'.join(delta) + return '\n'.join(delta) def mail_bug(srcpkg, subscribe, status, bugtitle, bugtext, bug_mail_domain, @@ -161,15 +146,16 @@ gpg_command.extend(('-u', keyid)) # sign the mail body - gpg = subprocess.Popen(gpg_command, stdin=subprocess.PIPE, - stdout=subprocess.PIPE) - signed_report = gpg.communicate(mailbody.encode('utf-8'))[0].decode('utf-8') + gpg = subprocess.Popen( + gpg_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + encoding='utf-8') + signed_report = gpg.communicate(mailbody)[0] if gpg.returncode != 0: Logger.error("%s failed.", gpg_command[0]) sys.exit(1) # generate email - mail = u'''\ + mail = '''\ From: %s To: %s Subject: %s @@ -189,14 +175,14 @@ with backup: backup.write(mail) - Logger.normal('The e-mail has been saved in %s and will be deleted ' - 'after succesful transmission', backup.name) + Logger.info('The e-mail has been saved in %s and will be deleted ' + 'after succesful transmission', backup.name) # connect to the server while True: try: - Logger.normal('Connecting to %s:%s ...', mailserver_host, - mailserver_port) + Logger.info('Connecting to %s:%s ...', mailserver_host, + mailserver_port) s = smtplib.SMTP(mailserver_host, mailserver_port) break except smtplib.SMTPConnectError as s: @@ -242,7 +228,7 @@ s.sendmail(myemailaddr, to, mail.encode('utf-8')) s.quit() os.remove(backup.name) - Logger.normal('Sync request mailed.') + Logger.info('Sync request mailed.') break except smtplib.SMTPRecipientsRefused as smtperror: smtp_code, smtp_message = smtperror.recipients[to] diff -Nru ubuntu-dev-tools-0.164/ubuntutools/sponsor_patch/bugtask.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/sponsor_patch/bugtask.py --- ubuntu-dev-tools-0.164/ubuntutools/sponsor_patch/bugtask.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/sponsor_patch/bugtask.py 2021-12-05 15:20:37.000000000 +0000 @@ -17,17 +17,16 @@ import os import re -try: - from urllib.parse import unquote - from urllib.request import urlretrieve -except ImportError: - from urllib import unquote, urlretrieve +from urllib.parse import unquote +from urllib.request import urlretrieve -import debian.debian_support import distro_info import httplib2 -from ubuntutools.logger import Logger +from ubuntutools.version import Version + +import logging +Logger = logging.getLogger(__name__) def is_sync(bug): @@ -43,7 +42,7 @@ self.bug_task = bug_task self.launchpad = launchpad - components = re.split(" \(| ", self.bug_task.bug_target_name.strip(")")) + components = re.split(r" \(| ", self.bug_task.bug_target_name.strip(")")) assert len(components) >= 1 and len(components) <= 3 if len(components) == 1: self.package = None @@ -59,7 +58,7 @@ self.series = components[2].lower() if self.package is None: - title_re = '^Sync ([a-z0-9+.-]+) [a-z0-9.+:~-]+ \([a-z]+\) from.*' + title_re = r'^Sync ([a-z0-9+.-]+) [a-z0-9.+:~-]+ \([a-z]+\) from.*' match = re.match(title_re, self.get_bug_title(), re.U | re.I) if match is not None: self.package = match.group(1) @@ -69,13 +68,13 @@ dsc_file = "" for url in source_files: filename = unquote(os.path.basename(url)) - Logger.info("Downloading %s..." % (filename)) + Logger.debug("Downloading %s..." % (filename)) # HttpLib2 isn't suitable for large files (it reads into memory), # but we want its https certificate validation on the .dsc if url.endswith(".dsc"): response, data = httplib2.Http().request(url) assert response.status == 200 - with open(filename, 'w') as f: + with open(filename, 'wb') as f: f.write(data) dsc_file = os.path.join(os.getcwd(), filename) @@ -152,7 +151,7 @@ def get_version(self): source_package_version = self.get_source().source_package_version - return debian.debian_support.Version(source_package_version) + return Version(source_package_version) def get_latest_released_version(self): source = self.get_source(True) @@ -160,7 +159,7 @@ version = '~' else: version = source.source_package_version - return debian.debian_support.Version(version) + return Version(version) def get_debian_source_series(self): title = self.bug_task.bug.title.lower().split() diff -Nru ubuntu-dev-tools-0.164/ubuntutools/sponsor_patch/patch.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/sponsor_patch/patch.py --- ubuntu-dev-tools-0.164/ubuntutools/sponsor_patch/patch.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/sponsor_patch/patch.py 2021-12-05 15:20:37.000000000 +0000 @@ -17,12 +17,14 @@ import os import re +import subprocess -from ubuntutools import subprocess -from ubuntutools.logger import Logger from ubuntutools.sponsor_patch.question import ask_for_manual_fixing from functools import reduce +import logging +Logger = logging.getLogger(__name__) + class Patch(object): """This object represents a patch that can be downloaded from Launchpad.""" @@ -32,8 +34,8 @@ self._patch_file = re.sub(" |/", "_", patch.title) if not reduce(lambda r, x: r or self._patch.title.endswith(x), (".debdiff", ".diff", ".patch"), False): - Logger.info("Patch %s does not have a proper file extension." % - (self._patch.title)) + Logger.debug("Patch %s does not have a proper file extension." % + (self._patch.title)) self._patch_file += ".patch" self._full_path = os.path.realpath(self._patch_file) self._changed_files = None @@ -45,7 +47,7 @@ if self.is_debdiff(): cmd = ["patch", "--merge", "--force", "-p", str(self.get_strip_level()), "-i", self._full_path] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd) != 0: Logger.error("Failed to apply debdiff %s to %s %s.", self._patch_file, task.package, task.get_version()) @@ -54,7 +56,7 @@ edit = True else: cmd = ["add-patch", self._full_path] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd) != 0: Logger.error("Failed to apply diff %s to %s %s.", self._patch_file, task.package, task.get_version()) @@ -65,14 +67,13 @@ def download(self): """Downloads the patch from Launchpad.""" - Logger.info("Downloading %s." % (self._patch_file)) - patch_f = open(self._patch_file, "w") + Logger.debug("Downloading %s." % (self._patch_file)) + patch_f = open(self._patch_file, "wb") patch_f.write(self._patch.data.open().read()) patch_f.close() cmd = ["diffstat", "-l", "-p0", self._full_path] - process = subprocess.Popen(cmd, stdout=subprocess.PIPE) - changed_files = process.communicate()[0] + changed_files = subprocess.check_output(cmd, encoding='utf-8') self._changed_files = [f for f in changed_files.split("\n") if f != ""] def get_strip_level(self): diff -Nru ubuntu-dev-tools-0.164/ubuntutools/sponsor_patch/question.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/sponsor_patch/question.py --- ubuntu-dev-tools-0.164/ubuntutools/sponsor_patch/question.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/sponsor_patch/question.py 2019-09-10 12:14:20.000000000 +0000 @@ -15,8 +15,6 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -from __future__ import print_function - import sys from ubuntutools.question import Question, YesNoQuestion diff -Nru ubuntu-dev-tools-0.164/ubuntutools/sponsor_patch/source_package.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/sponsor_patch/source_package.py --- ubuntu-dev-tools-0.164/ubuntutools/sponsor_patch/source_package.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/sponsor_patch/source_package.py 2019-12-01 18:18:32.000000000 +0000 @@ -15,23 +15,23 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -from __future__ import print_function - import os import re +import subprocess import sys import debian.changelog import debian.deb822 -from ubuntutools import subprocess -from ubuntutools.logger import Logger from ubuntutools.question import Question, YesNoQuestion from ubuntutools.sponsor_patch.question import (ask_for_ignoring_or_fixing, ask_for_manual_fixing, user_abort) +import logging +Logger = logging.getLogger(__name__) + def _get_series(launchpad): """Returns a tuple with the development and list of supported series.""" @@ -86,7 +86,7 @@ if task.importance == "Undecided": task.importance = "Wishlist" task.lp_save() - Logger.info("Set bug #%i status to Confirmed.", bug.id) + Logger.debug("Set bug #%i status to Confirmed.", bug.id) msg = "Sync request ACK'd." if self._build_log: @@ -94,26 +94,26 @@ (self._package, self._version, self._builder.get_architecture()) bug.newMessage(content=msg, subject="sponsor-patch") - Logger.info("Acknowledged sync request bug #%i.", bug.id) + Logger.debug("Acknowledged sync request bug #%i.", bug.id) bug.subscribe(person=launchpad.people['ubuntu-archive']) - Logger.info("Subscribed ubuntu-archive to bug #%i.", bug.id) + Logger.debug("Subscribed ubuntu-archive to bug #%i.", bug.id) bug.subscribe(person=launchpad.me) - Logger.info("Subscribed me to bug #%i.", bug.id) + Logger.debug("Subscribed me to bug #%i.", bug.id) sponsorsteam = launchpad.people['ubuntu-sponsors'] for sub in bug.subscriptions: if sub.person == sponsorsteam and sub.canBeUnsubscribedByUser(): bug.unsubscribe(person=launchpad.people['ubuntu-sponsors']) - Logger.info("Unsubscribed ubuntu-sponsors from bug #%i.", - bug.id) + Logger.debug("Unsubscribed ubuntu-sponsors from bug #%i.", + bug.id) elif sub.person == sponsorsteam: - Logger.info("Couldn't unsubscribe ubuntu-sponsors from " - "bug #%i.", bug.id) + Logger.debug("Couldn't unsubscribe ubuntu-sponsors from " + "bug #%i.", bug.id) - Logger.normal("Successfully acknowledged sync request bug #%i.", - bug.id) + Logger.info("Successfully acknowledged sync request bug #%i.", + bug.id) else: Logger.error("Sync requests can only be acknowledged when the " "upload target is Ubuntu.") @@ -141,7 +141,7 @@ elif answer == "no": user_abort() cmd = ["dput", "--force", upload, self._changes_file] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd) != 0: Logger.error("Upload of %s to %s failed." % (os.path.basename(self._changes_file), upload)) @@ -150,17 +150,17 @@ # Push the branch if the package is uploaded to the Ubuntu archive. if upload == "ubuntu" and self._branch: cmd = ['debcommit'] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd) != 0: Logger.error('Bzr commit failed.') sys.exit(1) cmd = ['bzr', 'mark-uploaded'] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd) != 0: Logger.error('Bzr tagging failed.') sys.exit(1) cmd = ['bzr', 'push', ':parent'] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd) != 0: Logger.error('Bzr push failed.') sys.exit(1) @@ -241,7 +241,7 @@ env = os.environ if upload == 'ubuntu': env['DEB_VENDOR'] = 'Ubuntu' - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd, env=env) != 0: Logger.error("Failed to build source tarball.") # TODO: Add a "retry" option @@ -324,11 +324,10 @@ assert os.path.isfile(self._dsc_file), "%s does not exist." % \ (self._dsc_file) cmd = ["debdiff", dsc_file, self._dsc_file] - if not Logger.verbose: + if not Logger.isEnabledFor(logging.DEBUG): cmd.insert(1, "-q") - Logger.command(cmd + [">", self._debdiff_filename]) - process = subprocess.Popen(cmd, stdout=subprocess.PIPE) - debdiff = process.communicate()[0] + Logger.debug(' '.join(cmd) + " > " + self._debdiff_filename) + debdiff = subprocess.check_output(cmd, encoding='utf-8') # write debdiff file debdiff_file = open(self._debdiff_filename, "w") @@ -420,9 +419,8 @@ lintian_filename = os.path.join(self._workdir, self._package + "_" + strip_epoch(self._version) + ".lintian") - Logger.command(cmd + [">", lintian_filename]) - process = subprocess.Popen(cmd, stdout=subprocess.PIPE) - report = process.communicate()[0] + Logger.debug(' '.join(cmd) + " > " + lintian_filename) + report = subprocess.check_output(cmd, encoding='utf-8') # write lintian report file lintian_file = open(lintian_filename, "w") @@ -438,7 +436,7 @@ cmd = ["syncpackage", self._package, "-b", str(bug_number), "-f", "-s", requester, "-V", str(self._version), "-d", series] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd) != 0: Logger.error("Syncing of %s %s failed.", self._package, str(self._version)) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/sponsor_patch/sponsor_patch.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/sponsor_patch/sponsor_patch.py --- ubuntu-dev-tools-0.164/ubuntutools/sponsor_patch/sponsor_patch.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/sponsor_patch/sponsor_patch.py 2019-12-01 18:18:32.000000000 +0000 @@ -15,19 +15,16 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -from __future__ import print_function - import os import pwd import shutil +import subprocess import sys from distro_info import UbuntuDistroInfo from launchpadlib.launchpad import Launchpad -from ubuntutools import subprocess -from ubuntutools.logger import Logger from ubuntutools.update_maintainer import (update_maintainer, MaintainerUpdateException) from ubuntutools.question import input_number @@ -37,8 +34,8 @@ from ubuntutools.sponsor_patch.question import ask_for_manual_fixing from ubuntutools.sponsor_patch.source_package import SourcePackage -if sys.version_info[0] < 3: - range = xrange # noqa, pylint: disable=redefined-builtin,undefined-variable +import logging +Logger = logging.getLogger(__name__) def is_command_available(command, check_sbin=False): @@ -64,8 +61,8 @@ missing.append('pbuilder/cowbuilder/sbuild') if missing: - Logger.warn("sponsor-patch requires %s to be installed for full " - "functionality", ', '.join(missing)) + Logger.warning("sponsor-patch requires %s to be installed for full " + "functionality", ', '.join(missing)) def get_source_package_name(bug_task): @@ -87,7 +84,7 @@ def edit_source(): # Spawn shell to allow modifications cmd = [get_user_shell()] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) print("""An interactive shell was launched in file://%s Edit your files. When you are done, exit the shell. If you wish to abort the @@ -117,7 +114,7 @@ patches += "es" msg = "https://launchpad.net/bugs/%i has %s linked and %s attached:" % \ (bug.id, branches, patches) - Logger.normal(msg) + Logger.info(msg) i = 0 for linked_branch in linked_branches: i += 1 @@ -165,7 +162,7 @@ if os.path.isdir(dir_name): shutil.rmtree(dir_name) cmd = ["bzr", "branch", branch] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd) != 0: Logger.error("Failed to download branch %s." % (branch)) sys.exit(1) @@ -175,7 +172,7 @@ def merge_branch(branch): edit = False cmd = ["bzr", "merge", branch] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd) != 0: Logger.error("Failed to merge branch %s." % (branch)) ask_for_manual_fixing() @@ -187,7 +184,7 @@ cmd = ["dpkg-source", "--no-preparation", "-x", dsc_file] if not verbose: cmd.insert(1, "-q") - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd) != 0: Logger.error("Extraction of %s failed." % (os.path.basename(dsc_file))) sys.exit(1) @@ -224,21 +221,21 @@ task = tasks[0] elif len(ubuntu_tasks) > 1: task_list = [t.get_short_info() for t in ubuntu_tasks] - Logger.info("%i Ubuntu tasks exist for bug #%i.\n%s", len(ubuntu_tasks), - bug_id, "\n".join(task_list)) + Logger.debug("%i Ubuntu tasks exist for bug #%i.\n%s", len(ubuntu_tasks), + bug_id, "\n".join(task_list)) open_ubuntu_tasks = [x for x in ubuntu_tasks if not x.is_complete()] if len(open_ubuntu_tasks) == 1: task = open_ubuntu_tasks[0] else: - Logger.normal("https://launchpad.net/bugs/%i has %i Ubuntu tasks:" % - (bug_id, len(ubuntu_tasks))) + Logger.info("https://launchpad.net/bugs/%i has %i Ubuntu tasks:" % + (bug_id, len(ubuntu_tasks))) for i in range(len(ubuntu_tasks)): print("%i) %s" % (i + 1, ubuntu_tasks[i].get_package_and_series())) selected = input_number("To which Ubuntu task does the patch belong", 1, len(ubuntu_tasks)) task = ubuntu_tasks[selected - 1] - Logger.info("Selected Ubuntu task: %s" % (task.get_short_info())) + Logger.debug("Selected Ubuntu task: %s" % (task.get_short_info())) return task @@ -253,15 +250,15 @@ (workdir, error.errno, error.strerror)) sys.exit(1) if workdir != os.getcwd(): - Logger.command(["cd", workdir]) + Logger.debug("cd " + workdir) os.chdir(workdir) def _update_maintainer_field(): """Update the Maintainer field in debian/control.""" - Logger.command(["update-maintainer"]) + Logger.debug("update-maintainer") try: - update_maintainer("debian", Logger.verbose) + update_maintainer("debian", Logger.isEnabledFor(logging.DEBUG)) except MaintainerUpdateException as e: Logger.error("update-maintainer failed: %s", str(e)) sys.exit(1) @@ -270,9 +267,9 @@ def _update_timestamp(): """Run dch to update the timestamp of debian/changelog.""" cmd = ["dch", "--maintmaint", "--release", ""] - Logger.command(cmd) + Logger.debug(' '.join(cmd)) if subprocess.call(cmd) != 0: - Logger.info("Failed to update timestamp in debian/changelog.") + Logger.debug("Failed to update timestamp in debian/changelog.") def _download_and_change_into(task, dsc_file, patch, branch): @@ -282,23 +279,23 @@ branch_dir = download_branch(task.get_branch_link()) # change directory - Logger.command(["cd", branch_dir]) + Logger.debug("cd " + branch_dir) os.chdir(branch_dir) else: if patch: patch.download() - Logger.info("Ubuntu package: %s" % (task.package)) + Logger.debug("Ubuntu package: %s" % (task.package)) if task.is_merge(): - Logger.info("The task is a merge request.") + Logger.debug("The task is a merge request.") if task.is_sync(): - Logger.info("The task is a sync request.") + Logger.debug("The task is a sync request.") - extract_source(dsc_file, Logger.verbose) + extract_source(dsc_file, Logger.isEnabledFor(logging.DEBUG)) # change directory directory = task.package + '-' + task.get_version().upstream_version - Logger.command(["cd", directory]) + Logger.debug("cd " + directory) os.chdir(directory) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/subprocess.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/subprocess.py --- ubuntu-dev-tools-0.164/ubuntutools/subprocess.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/subprocess.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ -"""Drop-in replacement for subprocess with better defaults - -This is an API-compatible replacement for the built-in subprocess -module whose defaults better line up with our tastes. - -In particular, it: - - Adds support for the restore_signals flag if subprocess itself - doesn't support it - - Defaults close_fds to True -""" - - -from __future__ import absolute_import - -import inspect -import signal -import subprocess -import sys - -from subprocess import PIPE, STDOUT, CalledProcessError - -__all__ = ['Popen', 'call', 'check_call', 'check_output', 'CalledProcessError', - 'PIPE', 'STDOUT'] - - -class Popen(subprocess.Popen): - def __init__(self, *args, **kwargs): - kwargs.setdefault('close_fds', True) - if sys.version_info[0] >= 3: - getargs = inspect.getfullargspec - else: - getargs = inspect.getargspec - - if 'restore_signals' not in getargs(subprocess.Popen.__init__)[0]: - given_preexec_fn = kwargs.pop('preexec_fn', None) - restore_signals = kwargs.pop('restore_signals', True) - - def preexec_fn(): - if restore_signals: - for sig in ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ'): - if hasattr(signal, sig): - signal.signal(getattr(signal, sig), - signal.SIG_DFL) - - if given_preexec_fn: - given_preexec_fn() - kwargs['preexec_fn'] = preexec_fn - - subprocess.Popen.__init__(self, *args, **kwargs) - - -# call, check_call, and check_output are copied directly from the -# subprocess module shipped with Python 2.7.1-5ubuntu2 - - -def call(*popenargs, **kwargs): - """Run command with arguments. Wait for command to complete, then - return the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - retcode = call(["ls", "-l"]) - """ - return Popen(*popenargs, **kwargs).wait() - - -def check_call(*popenargs, **kwargs): - """Run command with arguments. Wait for command to complete. If - the exit code was zero then return, otherwise raise - CalledProcessError. The CalledProcessError object will have the - return code in the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - check_call(["ls", "-l"]) - """ - retcode = call(*popenargs, **kwargs) - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise CalledProcessError(retcode, cmd) - return 0 - - -def check_output(*popenargs, **kwargs): - r"""Run command with arguments and return its output as a byte string. - - If the exit code was non-zero it raises a CalledProcessError. The - CalledProcessError object will have the return code in the returncode - attribute and output in the output attribute. - - The arguments are the same as for the Popen constructor. Example: - - >>> check_output(["ls", "-l", "/dev/null"]) - 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' - - The stdout argument is not allowed as it is used internally. - To capture standard error in the result, use stderr=STDOUT. - - >>> check_output(["/bin/sh", "-c", - ... "ls -l non_existent_file ; exit 0"], - ... stderr=STDOUT) - 'ls: non_existent_file: No such file or directory\n' - """ - if 'stdout' in kwargs: - raise ValueError('stdout argument not allowed, it will be overridden.') - process = Popen(stdout=PIPE, *popenargs, **kwargs) - output, unused_err = process.communicate() - retcode = process.poll() - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise CalledProcessError(retcode, cmd, output=output) - return output diff -Nru ubuntu-dev-tools-0.164/ubuntutools/test/example_package.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/example_package.py --- ubuntu-dev-tools-0.164/ubuntutools/test/example_package.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/example_package.py 2021-12-05 15:20:37.000000000 +0000 @@ -14,50 +14,69 @@ # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -import os.path -import shutil +import os import subprocess +import tempfile -import debian.debian_support +from pathlib import Path +from ubuntutools.version import Version class ExamplePackage(object): - def __init__(self, source='example', version='1.0-1'): + def __init__(self, source='example', version='1.0-1', destdir='test-data'): self.source = source - self.version = debian.debian_support.Version(version) - self.srcdir = os.path.join('test-data', '%s-%s' % (source, - self.version.upstream_version)) - if os.path.exists(self.srcdir): - shutil.rmtree(self.srcdir) - shutil.copytree('test-data/blank-example', self.srcdir) - - def create_orig(self): - "Create .orig.tar.gz" - orig = '%s_%s.orig.tar.gz' % (self.source, - self.version.upstream_version) - subprocess.check_call(('tar', '-czf', orig, - os.path.basename(self.srcdir), - '--exclude', 'debian'), - cwd='test-data') - - def changelog_entry(self, version=None, create=False): - "Add a changelog entry" - cmd = ['dch', '--noconf', '--preserve', '--package', self.source] - if create: - cmd.append('--create') - cmd += ['--newversion', version or self.version.full_version] - cmd.append('') - env = dict(os.environ) - env['DEBFULLNAME'] = 'Example' - env['DEBEMAIL'] = 'example@example.net' - subprocess.check_call(cmd, env=env, cwd=self.srcdir) + self.version = Version(version) + self.destdir = Path(destdir) + + self.env = dict(os.environ) + self.env['DEBFULLNAME'] = 'Example' + self.env['DEBEMAIL'] = 'example@example.net' + + @property + def orig(self): + return self.destdir / f'{self.source}_{self.version.upstream_version}.orig.tar.xz' + + @property + def debian(self): + return self.destdir / f'{self.source}_{self.version}.debian.tar.xz' + + @property + def dsc(self): + return self.destdir / f'{self.source}_{self.version}.dsc' + + @property + def dirname(self): + return f'{self.source}-{self.version.upstream_version}' + + @property + def content_filename(self): + return 'content' + + @property + def content_text(self): + return 'my content' def create(self): - "Build source package" - self.changelog_entry(create=True) - (basename, dirname) = os.path.split(self.srcdir) - subprocess.check_call(('dpkg-source', '-b', dirname), cwd=basename) - - def cleanup(self): - "Remove srcdir" - shutil.rmtree(self.srcdir) + with tempfile.TemporaryDirectory() as d: + self._create(Path(d)) + + def _create(self, d): + pkgdir = d / self.dirname + pkgdir.mkdir() + (pkgdir / self.content_filename).write_text(self.content_text) + + # run dh_make to create orig tarball + subprocess.run('dh_make -sy --createorig'.split(), + check=True, env=self.env, cwd=str(pkgdir), + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + # run dpkg-source -b to create debian tar and dsc + subprocess.run(f'dpkg-source -b {self.dirname}'.split(), + check=True, env=self.env, cwd=str(d), + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + # move tarballs and dsc to destdir + self.destdir.mkdir(parents=True, exist_ok=True) + (d / self.orig.name).rename(self.orig) + (d / self.debian.name).rename(self.debian) + (d / self.dsc.name).rename(self.dsc) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/test/__init__.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/__init__.py --- ubuntu-dev-tools-0.164/ubuntutools/test/__init__.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/__init__.py 2021-12-05 15:20:37.000000000 +0000 @@ -1,30 +0,0 @@ -# Test suite for ubuntutools -# -# Copyright (C) 2010, Stefano Rivera -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -import os -import sys - -if sys.version_info < (2, 7): - import unittest2 as unittest -else: - import unittest - - -def discover(): - # import __main__ triggers code re-execution - __main__ = sys.modules['__main__'] - setupDir = os.path.abspath(os.path.dirname(__main__.__file__)) - return unittest.defaultTestLoader.discover(setupDir) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/test/pylint.conf ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/pylint.conf --- ubuntu-dev-tools-0.164/ubuntutools/test/pylint.conf 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/pylint.conf 2019-11-11 13:25:02.000000000 +0000 @@ -1,3 +1,36 @@ +[MASTER] + +# Pickle collected data for later comparisons. +persistent=no + +# Use all cpus, to speed up testing +jobs=0 + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence=HIGH + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=locally-disabled + + +[REPORTS] + +# Tells whether to display a full report or only the messages +reports=no + + [TYPECHECK] # List of classes names for which member attributes should not be checked @@ -5,6 +38,7 @@ # lpapicache classes, urlparse ignored-classes=Launchpad,BaseWrapper,PersonTeam,Distribution,Consumer,Credentials,ParseResult,apt_pkg,apt_pkg.Dependency,apt_pkg.BaseDependency + [FORMAT] # Maximum number of characters on a single line. @@ -14,6 +48,7 @@ # tab). indent-string=' ' + [BASIC] # Allow variables called e, f, lp diff -Nru ubuntu-dev-tools-0.164/ubuntutools/test/test_archive.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_archive.py --- ubuntu-dev-tools-0.164/ubuntutools/test/test_archive.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_archive.py 2021-12-05 15:20:37.000000000 +0000 @@ -15,68 +15,40 @@ # PERFORMANCE OF THIS SOFTWARE. -import os.path -import shutil -import sys +import filecmp import tempfile -from io import BytesIO -try: - from urllib.request import OpenerDirector, urlopen - from urllib.error import HTTPError, URLError -except ImportError: - from urllib2 import OpenerDirector, urlopen - from urllib2 import HTTPError, URLError -import httplib2 -import mock - -import debian.deb822 +import unittest import ubuntutools.archive -from ubuntutools.test import unittest - -from ubuntutools.test.example_package import ExamplePackage +from pathlib import Path -def setUpModule(): - if not os.path.exists('test-data/example-0.1-1.dsc'): - ex_pkg = ExamplePackage() - ex_pkg.create_orig() - ex_pkg.create() - ex_pkg.cleanup() +from ubuntutools.test.example_package import ExamplePackage -class DscVerificationTestCase(unittest.TestCase): +class BaseVerificationTestCase(unittest.TestCase): def setUp(self): - with open('test-data/example_1.0-1.dsc', 'rb') as f: - self.dsc = ubuntutools.archive.Dsc(f.read()) + d = tempfile.TemporaryDirectory() + self.addCleanup(d.cleanup) + self.pkg = ExamplePackage(destdir=Path(d.name)) + self.pkg.create() + self.dsc = ubuntutools.archive.Dsc(self.pkg.dsc.read_bytes()) + +class DscVerificationTestCase(BaseVerificationTestCase): def test_good(self): - self.assertTrue(self.dsc.verify_file( - 'test-data/example_1.0.orig.tar.gz')) - self.assertTrue(self.dsc.verify_file( - 'test-data/example_1.0-1.debian.tar.xz')) + self.assertTrue(self.dsc.verify_file(self.pkg.orig)) + self.assertTrue(self.dsc.verify_file(self.pkg.debian)) def test_missing(self): - self.assertFalse(self.dsc.verify_file( - 'test-data/does.not.exist')) + self.assertFalse(self.dsc.verify_file(self.pkg.destdir / 'does.not.exist')) def test_bad(self): - fn = 'test-data/example_1.0.orig.tar.gz' - with open(fn, 'rb') as f: - data = f.read() - if sys.version_info[0] >= 3: - last_byte = chr(data[-1] ^ 8).encode() - else: - last_byte = chr(ord(data[-1]) ^ 8) + data = self.pkg.orig.read_bytes() + last_byte = chr(data[-1] ^ 8).encode() data = data[:-1] + last_byte - m = mock.MagicMock(name='open', spec=open) - m.return_value = BytesIO(data) - if sys.version_info[0] >= 3: - target = 'builtins.open' - else: - target = '__builtin__.open' - with mock.patch(target, m): - self.assertFalse(self.dsc.verify_file(fn)) + self.pkg.orig.write_bytes(data) + self.assertFalse(self.dsc.verify_file(self.pkg.orig)) def test_sha1(self): del self.dsc['Checksums-Sha256'] @@ -90,211 +62,64 @@ self.test_bad() -class LocalSourcePackageTestCase(unittest.TestCase): +class LocalSourcePackageTestCase(BaseVerificationTestCase): SourcePackage = ubuntutools.archive.UbuntuSourcePackage def setUp(self): - self.workdir = tempfile.mkdtemp(prefix='udt-test') - - self._stubout('ubuntutools.archive.Distribution') - self._stubout('ubuntutools.archive.rmadison') + super().setUp() + d = tempfile.TemporaryDirectory() + self.addCleanup(d.cleanup) + self.workdir = Path(d.name) + + def pull(self, **kwargs): + ''' Do the pull from pkg dir to the workdir, return the SourcePackage ''' + srcpkg = self.SourcePackage(dscfile=self.pkg.dsc, workdir=self.workdir, **kwargs) + srcpkg.pull() + return srcpkg + + def test_pull(self, **kwargs): + srcpkg = self.pull(**kwargs) + self.assertTrue(filecmp.cmp(self.pkg.dsc, self.workdir / self.pkg.dsc.name)) + self.assertTrue(filecmp.cmp(self.pkg.orig, self.workdir / self.pkg.orig.name)) + self.assertTrue(filecmp.cmp(self.pkg.debian, self.workdir / self.pkg.debian.name)) + return srcpkg + + def test_unpack(self, **kwargs): + srcpkg = kwargs.get('srcpkg', self.pull(**kwargs)) + srcpkg.unpack() + content = self.workdir / self.pkg.dirname / self.pkg.content_filename + self.assertEqual(self.pkg.content_text, content.read_text()) + debian = self.workdir / self.pkg.dirname / 'debian' + self.assertTrue(debian.exists()) + self.assertTrue(debian.is_dir()) + + def test_pull_and_unpack(self, **kwargs): + self.test_unpack(srcpkg=self.test_pull(**kwargs)) + + def test_with_package(self): + self.test_pull_and_unpack(package=self.pkg.source) + + def test_with_package_version(self): + self.test_pull_and_unpack(package=self.pkg.source, version=self.pkg.version) + + def test_with_package_version_component(self): + self.test_pull_and_unpack(package=self.pkg.source, + version=self.pkg.version, + componet='main') - self.mock_http = self._stubout('httplib2.Http.request') - self.mock_http.side_effect = self.request_proxy + def test_verification(self): + corruption = b'CORRUPTION' - self.url_opener = mock.MagicMock(spec=OpenerDirector) - self.url_opener.open.side_effect = self.urlopen_proxy - - # Silence the tests a little: - self._stubout('ubuntutools.logger.Logger.stdout') - self._stubout('ubuntutools.logger.Logger.stderr') - - def _stubout(self, stub): - patcher = mock.patch(stub) - self.addCleanup(patcher.stop) - return patcher.start() - - def tearDown(self): - shutil.rmtree(self.workdir) - - def urlopen_proxy(self, url, destname=None): - "urllib2 proxy for grabbing the file from test-data" - if destname is None: - destname = os.path.basename(url) - destpath = os.path.join(os.path.abspath('test-data'), destname) - return urlopen('file://' + destpath) - - def urlopen_file(self, filename): - "Wrapper for urlopen_proxy for named files" - return lambda url: self.urlopen_proxy(url, filename) - - def urlopen_null(self, url): - "urlopen for zero length files" - return BytesIO(b'') - - def urlopen_404(self, url): - "urlopen for errors" - raise HTTPError(url, 404, "Not Found", {}, None) - - def request_proxy(self, url, destname=None): - "httplib2 proxy for grabbing the file from test-data" - if destname is None: - destname = os.path.basename(url) - destpath = os.path.join(os.path.abspath('test-data'), destname) - response = httplib2.Response({}) - with open(destpath, 'rb') as f: - body = f.read() - return response, body - - def request_404(self, url): - "httplib2 for errors" - response = httplib2.Response({'status': 404}) - return response, "I'm a 404 Error" - - def request_404_then_proxy(self, url, destname=None): - "mock side_effect callable to chain request 404 & proxy" - if self.mock_http.called: - return self.request_proxy(url, destname) - return self.request_404(url) - - def test_local_copy(self): - pkg = self.SourcePackage('example', '1.0-1', 'main', - dscfile='test-data/example_1.0-1.dsc', - workdir=self.workdir) - pkg.quiet = True - pkg.pull() - pkg.unpack() - - def test_workdir_srcpkg_noinfo(self): - shutil.copy2('test-data/example_1.0-1.dsc', self.workdir) - shutil.copy2('test-data/example_1.0.orig.tar.gz', self.workdir) - shutil.copy2('test-data/example_1.0-1.debian.tar.xz', self.workdir) - - pkg = self.SourcePackage(dscfile=os.path.join(self.workdir, - 'example_1.0-1.dsc'), - workdir=self.workdir) - pkg.quiet = True - pkg.pull() - pkg.unpack() - - def test_workdir_srcpkg_info(self): - shutil.copy2('test-data/example_1.0-1.dsc', self.workdir) - shutil.copy2('test-data/example_1.0.orig.tar.gz', self.workdir) - shutil.copy2('test-data/example_1.0-1.debian.tar.xz', self.workdir) - - pkg = self.SourcePackage('example', '1.0-1', 'main', - dscfile=os.path.join(self.workdir, - 'example_1.0-1.dsc'), - workdir=self.workdir) - pkg.quiet = True - pkg.pull() - pkg.unpack() + self.pull() - def test_verification(self): - shutil.copy2('test-data/example_1.0-1.dsc', self.workdir) - shutil.copy2('test-data/example_1.0.orig.tar.gz', self.workdir) - shutil.copy2('test-data/example_1.0-1.debian.tar.xz', self.workdir) - with open(os.path.join(self.workdir, 'example_1.0-1.debian.tar.xz'), - 'r+b') as f: - f.write(b'CORRUPTION') - - pkg = self.SourcePackage('example', '1.0-1', 'main', - dscfile='test-data/example_1.0-1.dsc', - workdir=self.workdir) - pkg.quiet = True - pkg.pull() - - def test_pull(self): - pkg = self.SourcePackage('example', '1.0-1', 'main', - workdir=self.workdir) - - pkg.url_opener = self.url_opener - pkg.quiet = True - pkg.pull() - - def test_mirrors(self): - mirror = 'http://mirror' - sequence = [self.urlopen_null, self.urlopen_404, self.urlopen_proxy, - self.urlopen_proxy] - - def _callable_iter(*args, **kwargs): - return sequence.pop(0)(*args, **kwargs) - url_opener = mock.MagicMock(spec=OpenerDirector) - url_opener.open.side_effect = _callable_iter - - pkg = self.SourcePackage('example', '1.0-1', 'main', - workdir=self.workdir, mirrors=[mirror]) - pkg.url_opener = url_opener - pkg.quiet = True - pkg.pull() - - def test_dsc_missing(self): - self.mock_http.side_effect = self.request_404 - pkg = self.SourcePackage('example', '1.0-1', 'main', - workdir=self.workdir) - pkg.quiet = True - self.assertRaises(ubuntutools.archive.DownloadError, pkg.pull) - - -class DebianLocalSourcePackageTestCase(LocalSourcePackageTestCase): - SourcePackage = ubuntutools.archive.DebianSourcePackage - - def test_mirrors(self): - debian_mirror = 'http://mirror/debian' - debsec_mirror = 'http://mirror/debsec' - - sequence = [self.urlopen_null, - self.urlopen_404, - self.urlopen_404, - self.urlopen_404, - self.urlopen_404, - lambda x: BytesIO( - b'{"fileinfo": {"hashabc": [{"name": "example_1.0.orig.tar.gz"}]}}'), - self.urlopen_file('example_1.0.orig.tar.gz'), - self.urlopen_proxy] - - def _callable_iter(*args, **kwargs): - return sequence.pop(0)(*args, **kwargs) - url_opener = mock.MagicMock(spec=OpenerDirector) - url_opener.open.side_effect = _callable_iter - - pkg = self.SourcePackage('example', '1.0-1', 'main', - workdir=self.workdir, mirrors=[debian_mirror, - debsec_mirror]) - pkg.quiet = True - pkg.url_opener = url_opener - pkg.pull() - pkg.unpack() - - def test_dsc_missing(self): - mirror = 'http://mirror' - self.mock_http.side_effect = self.request_404_then_proxy - - patcher = mock.patch.object(debian.deb822.GpgInfo, 'from_sequence') - self.addCleanup(patcher.stop) - mock_gpg_info = patcher.start() - mock_gpg_info.return_value = debian.deb822.GpgInfo.from_output( - '[GNUPG:] GOODSIG DEADBEEF Joe Developer ' - '') - - pkg = self.SourcePackage('example', '1.0-1', 'main', - workdir=self.workdir, mirrors=[mirror]) - pkg.url_opener = self.url_opener - pkg.pull() - - def test_dsc_badsig(self): - mirror = 'http://mirror' - self.mock_http.side_effect = self.request_404_then_proxy - - patcher = mock.patch.object(debian.deb822.GpgInfo, 'from_sequence') - self.addCleanup(patcher.stop) - mock_gpg_info = patcher.start() - mock_gpg_info.return_value = debian.deb822.GpgInfo.from_output( - '[GNUPG:] ERRSIG DEADBEEF') - - pkg = self.SourcePackage('example', '1.0-1', 'main', - workdir=self.workdir, mirrors=[mirror]) - try: - self.assertRaises(ubuntutools.archive.DownloadError, pkg.pull) - except URLError: - raise unittest.SkipTest('Test needs addr resolution to work') + testfile = self.workdir / self.pkg.debian.name + self.assertTrue(testfile.exists()) + self.assertTrue(testfile.is_file()) + self.assertNotEqual(testfile.read_bytes(), corruption) + testfile.write_bytes(corruption) + self.assertEqual(testfile.read_bytes(), corruption) + + self.test_pull() + self.assertTrue(testfile.exists()) + self.assertTrue(testfile.is_file()) + self.assertNotEqual(testfile.read_bytes(), corruption) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/test/test_config.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_config.py --- ubuntu-dev-tools-0.164/ubuntutools/test/test_config.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_config.py 2021-12-05 15:20:37.000000000 +0000 @@ -15,19 +15,15 @@ # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -import os -import sys import locale -try: - from StringIO import StringIO -except ImportError: - from io import StringIO +import os +# import sys +import unittest -import mock +from io import StringIO +from unittest import mock from ubuntutools.config import UDTConfig, ubu_email -from ubuntutools.logger import Logger -from ubuntutools.test import unittest class ConfigTestCase(unittest.TestCase): @@ -49,28 +45,22 @@ def setUp(self): super(ConfigTestCase, self).setUp() - if sys.version_info[0] < 3: - self.assertRegex = self.assertRegexpMatches m = mock.mock_open() m.side_effect = self._fake_open - if sys.version_info[0] >= 3: - target = 'builtins.open' - else: - target = '__builtin__.open' - patcher = mock.patch(target, m) + patcher = mock.patch('builtins.open', m) self.addCleanup(patcher.stop) patcher.start() - Logger.stdout = StringIO() - Logger.stderr = StringIO() + # Logger.stdout = StringIO() + # Logger.stderr = StringIO() self.clean_environment() def tearDown(self): - self.assertEqual(Logger.stdout.getvalue(), '') - self.assertEqual(Logger.stderr.getvalue(), '') - Logger.stdout = sys.stdout - Logger.stderr = sys.stderr + # self.assertEqual(Logger.stdout.getvalue(), '') + # self.assertEqual(Logger.stderr.getvalue(), '') + # Logger.stdout = sys.stdout + # Logger.stderr = sys.stderr self.clean_environment() @@ -108,11 +98,11 @@ 'INHERIT': 'user', 'REPEAT': 'yes', }) - errs = Logger.stderr.getvalue().strip() - Logger.stderr = StringIO() - self.assertEqual(len(errs.splitlines()), 1) - self.assertRegex(errs, - r'Warning: Cannot parse.*\bCOMMAND_EXECUTION=a') + # errs = Logger.stderr.getvalue().strip() + # Logger.stderr = StringIO() + # self.assertEqual(len(errs.splitlines()), 1) + # self.assertRegex(errs, + # r'Warning: Cannot parse.*\bCOMMAND_EXECUTION=a') def get_value(self, *args, **kwargs): config = UDTConfig(prefix='TEST') @@ -148,11 +138,11 @@ self._config_files['user'] = 'COMPATFOOBAR=bar' self.assertEqual(self.get_value('QUX', compat_keys=['COMPATFOOBAR']), 'bar') - errs = Logger.stderr.getvalue().strip() - Logger.stderr = StringIO() - self.assertEqual(len(errs.splitlines()), 1) - self.assertRegex(errs, - r'deprecated.*\bCOMPATFOOBAR\b.*\bTEST_QUX\b') + # errs = Logger.stderr.getvalue().strip() + # Logger.stderr = StringIO() + # self.assertEqual(len(errs.splitlines()), 1) + # self.assertRegex(errs, + # r'deprecated.*\bCOMPATFOOBAR\b.*\bTEST_QUX\b') def test_boolean(self): self._config_files['user'] = "TEST_BOOLEAN=yes" diff -Nru ubuntu-dev-tools-0.164/ubuntutools/test/test_flake8.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_flake8.py --- ubuntu-dev-tools-0.164/ubuntutools/test/test_flake8.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_flake8.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -# Copyright (C) 2017, Benjamin Drung -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -"""test_flake8.py - Run flake8 check""" - -import subprocess -import sys - -import setup -from ubuntutools.test import unittest - - -class Flake8TestCase(unittest.TestCase): - def test_flake8(self): - "Test: Run flake8 on Python source code" - files = ['ubuntutools', 'setup.py'] - for script in setup.scripts: - with open(script, 'r') as script_file: - shebang = script_file.readline() - if ((sys.version_info[0] == 3 and 'python3' in shebang) or - ('python' in shebang and 'python3' not in shebang)): - files.append(script) - - with open('/proc/self/cmdline', 'r') as cmdline_file: - python_binary = cmdline_file.read().split('\0')[0] - cmd = [python_binary, '-m', 'flake8', '--max-line-length=99'] + files - sys.stderr.write("Running following command:\n{}\n".format(" ".join(cmd))) - process = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, close_fds=True) - - out, err = process.communicate() - self.assertFalse(err, "Unexpected standard error from flake8 run:\n" + err.decode()) - self.assertFalse(out, "flake8 found issues:\n" + out.decode()) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/test/test_help.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_help.py --- ubuntu-dev-tools-0.164/ubuntutools/test/test_help.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_help.py 2021-12-05 15:20:37.000000000 +0000 @@ -14,68 +14,23 @@ # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -import fcntl -import os -import select -import signal -import time - -import setup -from ubuntutools import subprocess -from ubuntutools.test import unittest - -TIMEOUT = 5 - - -def load_tests(loader, tests, pattern): - "Give HelpTestCase a chance to populate before loading its test cases" - suite = unittest.TestSuite() - HelpTestCase.populate() - suite.addTests(loader.loadTestsFromTestCase(HelpTestCase)) - return suite +import subprocess +import unittest + +from setup import scripts + + +TIMEOUT = 10 class HelpTestCase(unittest.TestCase): - @classmethod - def populate(cls): - for script in setup.scripts: - setattr(cls, 'test_' + script, cls.make_help_tester(script)) - - @classmethod - def make_help_tester(cls, script): - def tester(self): - null = open('/dev/null', 'r') - process = subprocess.Popen(['./' + script, '--help'], - close_fds=True, stdin=null, - universal_newlines=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - started = time.time() - out = [] - - fds = [process.stdout.fileno(), process.stderr.fileno()] - for fd in fds: - fcntl.fcntl(fd, fcntl.F_SETFL, - fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK) - - while time.time() - started < TIMEOUT: - for fd in select.select(fds, [], fds, TIMEOUT)[0]: - output = os.read(fd, 1024) - if not isinstance(output, str): - output = output.decode('utf-8') - out.append(output) - if process.poll() is not None: - break - - if process.poll() is None: - os.kill(process.pid, signal.SIGTERM) - time.sleep(1) - if process.poll() is None: - os.kill(process.pid, signal.SIGKILL) - null.close() - - self.assertEqual(process.poll(), 0, - "%s failed to return usage within %i seconds.\n" - "Output:\n%s" - % (script, TIMEOUT, ''.join(out))) - return tester + def test_script(self): + for script in scripts: + with self.subTest(script=script): + result = subprocess.run([f'./{script}', '--help'], + encoding='UTF-8', + timeout=10, + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + self.assertFalse(result.stderr.strip()) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/test/test_logger.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_logger.py --- ubuntu-dev-tools-0.164/ubuntutools/test/test_logger.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_logger.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -# test_logger.py - Test ubuntutools.logger.Logger. -# -# Copyright (C) 2012, Stefano Rivera -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -try: - from StringIO import StringIO -except ImportError: - from io import StringIO -import sys - -from ubuntutools.logger import Logger -from ubuntutools.test import unittest - - -class LoggerTestCase(unittest.TestCase): - def setUp(self): - Logger.stdout = StringIO() - Logger.stderr = StringIO() - self._script_name = Logger.script_name - Logger.script_name = 'test' - self._verbose = Logger.verbose - - def tearDown(self): - Logger.stdout = sys.stdout - Logger.stderr = sys.stderr - Logger.script_name = self._script_name - Logger.verbose = self._verbose - - def testCommand(self): - Logger.command(('ls', 'a b')) - self.assertEqual(Logger.stdout.getvalue(), '') - Logger.set_verbosity(True) - Logger.command(('ls', 'a b')) - self.assertEqual(Logger.stdout.getvalue(), 'test: I: ls "a b"\n') - self.assertEqual(Logger.stderr.getvalue(), '') - - def testNoArgs(self): - Logger.normal('hello %s') - self.assertEqual(Logger.stdout.getvalue(), 'test: hello %s\n') - self.assertEqual(Logger.stderr.getvalue(), '') - - def testArgs(self): - Logger.normal('hello %s', 'world') - self.assertEqual(Logger.stdout.getvalue(), 'test: hello world\n') - self.assertEqual(Logger.stderr.getvalue(), '') diff -Nru ubuntu-dev-tools-0.164/ubuntutools/test/test_pylint.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_pylint.py --- ubuntu-dev-tools-0.164/ubuntutools/test/test_pylint.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_pylint.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -# test_pylint.py - Run pylint in errors-only mode. -# -# Copyright (C) 2010, Stefano Rivera -# Copyright (C) 2017, Benjamin Drung -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -import sys - -import setup -from ubuntutools.test import unittest -from ubuntutools import subprocess - - -class PylintTestCase(unittest.TestCase): - def test_pylint(self): - "Test: Run pylint on Python source code" - files = ['ubuntutools', 'setup.py'] - for script in setup.scripts: - with open(script, 'r') as script_file: - shebang = script_file.readline() - if ((sys.version_info[0] == 3 and 'python3' in shebang) or - ('python' in shebang and 'python3' not in shebang)): - files.append(script) - - if sys.version_info[0] == 3: - pylint_binary = 'pylint3' - else: - pylint_binary = 'pylint' - cmd = [pylint_binary, '--rcfile=ubuntutools/test/pylint.conf', '-E', - '--reports=n', '--confidence=HIGH', '--'] + files - sys.stderr.write("Running following command:\n{}\n".format(" ".join(cmd))) - try: - subprocess.check_output(cmd, stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: - self.fail( - '%s crashed (%d). Error output:\n%s' % - (pylint_binary, e.returncode, e.output.decode()) - ) diff -Nru ubuntu-dev-tools-0.164/ubuntutools/test/test_update_maintainer.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_update_maintainer.py --- ubuntu-dev-tools-0.164/ubuntutools/test/test_update_maintainer.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/test/test_update_maintainer.py 2021-12-05 15:20:37.000000000 +0000 @@ -16,18 +16,13 @@ """Test suite for ubuntutools.update_maintainer""" -try: - from StringIO import StringIO -except ImportError: - from io import StringIO - import os -import sys +# import sys +import unittest -import mock +from io import StringIO +from unittest import mock -from ubuntutools.logger import Logger -from ubuntutools.test import unittest from ubuntutools.update_maintainer import update_maintainer _LUCID_CHANGELOG = """\ @@ -231,15 +226,9 @@ # pylint: disable=C0103 def setUp(self): - if sys.version_info[0] < 3: - self.assertRegex = self.assertRegexpMatches m = mock.mock_open() m.side_effect = self._fake_open - if sys.version_info[0] >= 3: - target = 'builtins.open' - else: - target = '__builtin__.open' - patcher = mock.patch(target, m) + patcher = mock.patch('builtins.open', m) self.addCleanup(patcher.stop) patcher.start() m = mock.MagicMock(side_effect=self._fake_isfile) @@ -247,18 +236,18 @@ self.addCleanup(patcher.stop) patcher.start() self._files["rules"] = StringIO(_SIMPLE_RULES) - Logger.stdout = StringIO() - Logger.stderr = StringIO() + # Logger.stdout = StringIO() + # Logger.stderr = StringIO() def tearDown(self): - self.assertEqual(Logger.stdout.getvalue(), '') - self.assertEqual(Logger.stderr.getvalue(), '') + # self.assertEqual(Logger.stdout.getvalue(), '') + # self.assertEqual(Logger.stderr.getvalue(), '') self._files["changelog"] = None self._files["control"] = None self._files["control.in"] = None self._files["rules"] = None - Logger.stdout = sys.stdout - Logger.stderr = sys.stderr + # Logger.stdout = sys.stdout + # Logger.stderr = sys.stderr # pylint: enable=C0103 def test_debian_package(self): @@ -277,11 +266,11 @@ self._files["control"] = StringIO(_AXIS2C_CONTROL) update_maintainer(self._directory) self.assertEqual(self._files["control"].getvalue(), _AXIS2C_UPDATED) - warnings = Logger.stderr.getvalue().strip() - Logger.stderr = StringIO() - self.assertEqual(len(warnings.splitlines()), 1) - self.assertRegex(warnings, "Warning: Overwriting original maintainer: " - "Soren Hansen ") + # warnings = Logger.stderr.getvalue().strip() + # Logger.stderr = StringIO() + # self.assertEqual(len(warnings.splitlines()), 1) + # self.assertRegex(warnings, "Warning: Overwriting original maintainer: " + # "Soren Hansen ") def test_update_maintainer(self): """Test: Update Maintainer field.""" diff -Nru ubuntu-dev-tools-0.164/ubuntutools/update_maintainer.py ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/update_maintainer.py --- ubuntu-dev-tools-0.164/ubuntutools/update_maintainer.py 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntutools/update_maintainer.py 2019-12-01 18:18:32.000000000 +0000 @@ -14,15 +14,15 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -from __future__ import print_function - """This module is for updating the Maintainer field of an Ubuntu package.""" import os import re import debian.changelog -from ubuntutools.logger import Logger + +import logging +Logger = logging.getLogger(__name__) # Prior May 2009 these Maintainers were used: _PREVIOUS_UBUNTU_MAINTAINER = ( @@ -178,8 +178,8 @@ return if control.get_original_maintainer() is not None: - Logger.warn("Overwriting original maintainer: %s", - control.get_original_maintainer()) + Logger.warning("Overwriting original maintainer: %s", + control.get_original_maintainer()) if verbose: print("The original maintainer is: %s" % original_maintainer) diff -Nru ubuntu-dev-tools-0.164/ubuntu-upload-permission ubuntu-dev-tools-0.187~bpo18.04.1/ubuntu-upload-permission --- ubuntu-dev-tools-0.164/ubuntu-upload-permission 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/ubuntu-upload-permission 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # # Copyright (C) 2011, Stefano Rivera # @@ -20,9 +20,11 @@ from ubuntutools.lp.lpapicache import (Launchpad, Distribution, PersonTeam, Packageset, PackageNotFoundException, SeriesNotFoundException) -from ubuntutools.logger import Logger from ubuntutools.misc import split_release_pocket +from ubuntutools import getLogger +Logger = getLogger() + def parse_arguments(): '''Parse arguments and return (options, package)''' @@ -62,13 +64,13 @@ try: release, pocket = split_release_pocket(options.release) series = ubuntu.getSeries(release) - except SeriesNotFoundException, e: + except SeriesNotFoundException as e: Logger.error(str(e)) sys.exit(2) try: spph = archive.getSourcePackage(package) - except PackageNotFoundException, e: + except PackageNotFoundException as e: Logger.error(str(e)) sys.exit(2) component = spph.getComponent() @@ -77,50 +79,50 @@ component_uploader = archive.getUploadersForComponent( component_name=component)[0] - print "All upload permissions for %s:" % package - print - print "Component (%s)" % component - print "============" + ("=" * len(component)) + Logger.info("All upload permissions for %s:" % package) + Logger.info("") + Logger.info("Component (%s)" % component) + Logger.info("============" + ("=" * len(component))) print_uploaders([component_uploader], options.list_team_members) packagesets = sorted(Packageset.setsIncludingSource( distroseries=series, - sourcepackagename=package)) + sourcepackagename=package), key=lambda p: p.name) if packagesets: - print - print "Packagesets" - print "===========" + Logger.info("") + Logger.info("Packagesets") + Logger.info("===========") for packageset in packagesets: - print - print "%s:" % packageset.name + Logger.info("") + Logger.info("%s:" % packageset.name) print_uploaders(archive.getUploadersForPackageset( packageset=packageset), options.list_team_members) ppu_uploaders = archive.getUploadersForPackage( source_package_name=package) if ppu_uploaders: - print - print "Per-Package-Uploaders" - print "=====================" - print + Logger.info("") + Logger.info("Per-Package-Uploaders") + Logger.info("=====================") + Logger.info("") print_uploaders(ppu_uploaders, options.list_team_members) - print + Logger.info("") if PersonTeam.me.canUploadPackage(archive, series, package, component, pocket): - print "You can upload %s to %s." % (package, options.release) + Logger.info("You can upload %s to %s." % (package, options.release)) else: - print("You can not upload %s to %s, yourself." % (package, options.release)) + Logger.info("You can not upload %s to %s, yourself." % (package, options.release)) if (series.status in ('Current Stable Release', 'Supported', 'Obsolete') and pocket == 'Release'): - print("%s is in the '%s' state. You may want to query the %s-proposed pocket." % - (release, series.status, release)) + Logger.info("%s is in the '%s' state. You may want to query the %s-proposed pocket." % + (release, series.status, release)) else: - print("But you can still contribute to it via the sponsorship " - "process: https://wiki.ubuntu.com/SponsorshipProcess") + Logger.info("But you can still contribute to it via the sponsorship " + "process: https://wiki.ubuntu.com/SponsorshipProcess") if not options.list_uploaders: - print("To see who has the necessary upload rights, " - "use the --list-uploaders option.") + Logger.info("To see who has the necessary upload rights, " + "use the --list-uploaders option.") sys.exit(1) @@ -131,9 +133,9 @@ recursion. """ for uploader in sorted(uploaders, key=lambda p: p.display_name): - print("%s* %s (%s)%s" % - (prefix, uploader.display_name, uploader.name, - ' [team]' if uploader.is_team else '')) + Logger.info("%s* %s (%s)%s" % + (prefix, uploader.display_name, uploader.name, + ' [team]' if uploader.is_team else '')) if expand_teams and uploader.is_team: print_uploaders(uploader.participants, True, prefix=prefix + ' ') diff -Nru ubuntu-dev-tools-0.164/update-maintainer ubuntu-dev-tools-0.187~bpo18.04.1/update-maintainer --- ubuntu-dev-tools-0.164/update-maintainer 2018-04-24 08:38:10.000000000 +0000 +++ ubuntu-dev-tools-0.187~bpo18.04.1/update-maintainer 2021-12-05 15:20:37.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # # Copyright (C) 2010, Benjamin Drung # @@ -23,6 +23,21 @@ MaintainerUpdateException) +def find_debian_dir(depth=6): + """Scans up the directory hierarchy looking for a ./debian dir + + :param int depth: Levels to scan up the directory tree. + :rtype: str + :returns: a path to an existing debian/ directory, or None + """ + for path in ['../'*n or './' for n in list(range(0, depth+1))]: + debian_path = '{}debian'.format(path) + if os.path.exists(os.path.join(debian_path, 'control')) \ + and os.path.exists(os.path.join(debian_path, 'changelog')): + return debian_path + return None + + def main(): script_name = os.path.basename(sys.argv[0]) usage = "%s [options]" % (script_name) @@ -30,7 +45,8 @@ parser = optparse.OptionParser(usage=usage, epilog=epilog) parser.add_option("-d", "--debian-directory", dest="debian_directory", help="location of the 'debian' directory (default: " - "%default).", metavar="PATH", default="./debian") + "%default).", metavar="PATH", + default=find_debian_dir() or './debian') parser.add_option("-r", "--restore", help="Restore the original maintainer", action='store_true', default=False) @@ -39,8 +55,8 @@ (options, args) = parser.parse_args() if len(args) != 0: - print >> sys.stderr, ("%s: Error: Unsupported additional parameters " - "specified: %s") % (script_name, ", ".join(args)) + print("%s: Error: Unsupported additional parameters specified: %s" + % (script_name, ", ".join(args)), file=sys.stderr) sys.exit(1) if not options.restore: