From 122e711d28cf3e3deb8e8ebcee99b5ce379501d3 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 15:32:48 +0100 Subject: [PATCH 01/38] syncpackage: Convert to new LP API, with --no-lp available for the old style of operation. --- debian/changelog | 4 ++ syncpackage | 103 ++++++++++++++++++++++++++++++----- ubuntutools/lp/lpapicache.py | 3 + 3 files changed, 97 insertions(+), 13 deletions(-) diff --git a/debian/changelog b/debian/changelog index 516ac3c..68041cf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -6,6 +6,10 @@ ubuntu-dev-tools (0.128) UNRELEASED; urgency=low [ Julian Taylor ] * lp-shell: use ipython shell if available + [ Colin Watson ] + * syncpackage: Convert to new LP API, with --no-lp available for the old + style of operation. + -- Julian Taylor Sun, 14 Aug 2011 18:56:52 +0200 ubuntu-dev-tools (0.127) unstable; urgency=low diff --git a/syncpackage b/syncpackage index a47a182..17a5214 100755 --- a/syncpackage +++ b/syncpackage @@ -35,8 +35,9 @@ from ubuntutools.config import UDTConfig, ubu_email from ubuntutools.requestsync.mail import (getDebianSrcPkg as requestsync_mail_getDebianSrcPkg) from ubuntutools.requestsync.lp import getDebianSrcPkg, getUbuntuSrcPkg -from ubuntutools.lp import udtexceptions -from ubuntutools.lp.lpapicache import Launchpad +from ubuntutools.lp import udtexceptions, api_version +from ubuntutools.lp.lpapicache import Distribution, Launchpad +from ubuntutools.misc import split_release_pocket from ubuntutools import subprocess @@ -110,7 +111,7 @@ def add_fixed_bugs(changes, bugs): return "\n".join(changes + [""]) def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror, - keyid=None): + keyid=None, simulate=False): uploader = name + " <" + email + ">" src_pkg.pull_dsc() @@ -139,6 +140,8 @@ def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror, Logger.warn('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() @@ -292,6 +295,45 @@ def fetch_source_pkg(package, dist, version, component, ubuntu_release, mirror): return DebianSourcePackage(package, version.full_version, component, mirrors=[mirror]) +def copy(src_pkg, debian_version, release, simulate=False): + debian = Distribution('debian') + ubuntu = Distribution('ubuntu') + debian_archive = debian.getArchive() + ubuntu_archive = ubuntu.getArchive() + if release is None: + ubuntu_series = ubuntu.getDevelopmentSeries().name + ubuntu_pocket = 'Release' + else: + ubuntu_series, ubuntu_pocket = split_release_pocket(release) + + if debian_version is None: + debian_version = debian_archive.getSourcePackage(src_pkg).getVersion() + try: + ubuntu_version = ubuntu_archive.getSourcePackage( + src_pkg, ubuntu_series, ubuntu_pocket).getVersion() + + Logger.info('Source %s -> %s/%s: current version %s, new version %s', + src_pkg, ubuntu_series, ubuntu_pocket, + ubuntu_version, debian_version) + if Version(debian_version) <= Version(ubuntu_version): + Logger.error('Debian version is <= Ubuntu version; nothing to do!') + sys.exit(1) + except udtexceptions.PackageNotFoundException: + Logger.info('Source %s -> %s/%s: not in Ubuntu, new version %s', + src_pkg, ubuntu_series, ubuntu_pocket, debian_version) + if simulate: + return + + ubuntu_archive.copyPackage( + source_name=src_pkg, + version=debian_version, + from_archive=debian_archive.lp_object(), + to_series=ubuntu_series, + to_pocket=ubuntu_pocket, + include_binaries=False) + Logger.info('Request succeeded; you should get an e-mail once it is ' + 'processed.') + def main(): usage = "%prog [options] <.dsc URL/path or package name>" epilog = "See %s(1) for more info." % os.path.basename(sys.argv[0]) @@ -312,6 +354,14 @@ def main(): parser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False, help="Display more progress information.") + parser.add_option("--no-lp", + dest="lp", action="store_false", default=True, + help="Construct sync locally rather than letting " + "Launchpad copy the package directly.") + parser.add_option('-l', '--lpinstance', metavar='INSTANCE', + dest='lpinstance', default=None, + help='Launchpad instance to connect to ' + '(default: production).') parser.add_option("-n", "--uploader-name", dest="uploader_name", default=None, help="Use UPLOADER_NAME as the name of the maintainer " @@ -343,6 +393,10 @@ def main(): parser.add_option('--no-conf', dest='no_conf', default=False, action='store_true', help="Don't read config files or environment variables.") + parser.add_option('--simulate', + dest='simulate', default=False, action='store_true', + help="Show what would be done, but don't actually do " + "it.") (options, args) = parser.parse_args() @@ -362,6 +416,14 @@ def main(): 'It should be one of main, contrib, or non-free.' % options.component) + if options.lp and options.uploader_name: + parser.error('Uploader name can only be overridden using --no-lp.') + if options.lp and options.uploader_email: + parser.error('Uploader email address can only be overridden using ' + '--no-lp.') + # --key, --dont-sign, --debian-mirror, and --ubuntu-mirror are just + # ignored with options.lp, and do not require warnings. + Logger.verbose = options.verbose config = UDTConfig(options.no_conf) if options.debian_mirror is None: @@ -373,19 +435,34 @@ def main(): if options.uploader_email is None: options.uploader_email = ubu_email(export=False)[1] - Launchpad.login_anonymously() - if options.release is None: - options.release = Launchpad.distributions["ubuntu"].current_series.name + if options.lp: + # We need devel for now. + api_version = 'devel' - os.environ['DEB_VENDOR'] = 'Ubuntu' + if options.lpinstance is None: + options.lpinstance = config.get_value('LPINSTANCE') - src_pkg = fetch_source_pkg(args[0], options.dist, options.debversion, - options.component, options.release, - options.debian_mirror) + try: + Launchpad.login(service=options.lpinstance) + except IOError: + sys.exit(1) - sync_dsc(src_pkg, options.dist, options.release, options.uploader_name, - options.uploader_email, options.bugs, options.ubuntu_mirror, - options.keyid) + copy(args[0], options.debversion, options.release, options.simulate) + else: + Launchpad.login_anonymously() + if options.release is None: + ubuntu = Launchpad.distributions["ubuntu"] + options.release = ubuntu.current_series.name + + os.environ['DEB_VENDOR'] = 'Ubuntu' + + src_pkg = fetch_source_pkg(args[0], options.dist, options.debversion, + options.component, options.release, + options.debian_mirror) + + sync_dsc(src_pkg, options.dist, options.release, options.uploader_name, + options.uploader_email, options.bugs, options.ubuntu_mirror, + options.keyid, options.simulate) if __name__ == "__main__": main() diff --git a/ubuntutools/lp/lpapicache.py b/ubuntutools/lp/lpapicache.py index 097b63f..b223333 100644 --- a/ubuntutools/lp/lpapicache.py +++ b/ubuntutools/lp/lpapicache.py @@ -172,6 +172,9 @@ class BaseWrapper(object): else: return '<%s: %r>' % (self.__class__.__name__, self._lpobject) + def lp_object(self): + return self._lpobject + class Distribution(BaseWrapper): ''' From fdfef34b372fd71cf3dcc47ca94638894acee219 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 15:42:23 +0100 Subject: [PATCH 02/38] document new syncpackage behaviour --- doc/syncpackage.1 | 32 +++++++++++++++++++++----------- syncpackage | 3 ++- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/doc/syncpackage.1 b/doc/syncpackage.1 index 22f10dc..57416f9 100644 --- a/doc/syncpackage.1 +++ b/doc/syncpackage.1 @@ -1,12 +1,11 @@ .TH SYNCPACKAGE "1" "June 2010" "ubuntu-dev-tools" .SH NAME -syncpackage \- helper to prepare .changes file to upload synced packages +syncpackage \- copy packages from Debian to Ubuntu .SH SYNOPSIS .B syncpackage [\fIoptions\fR] \fI<.dsc URL/path or package name>\fR .SH DESCRIPTION -\fBsyncpackage\fR generates a changes file to be directly uploaded to Ubuntu -primary archive or PPA starting from a pristine Debian package. +\fBsyncpackage\fR causes a package to be copied from Debian to Ubuntu. .PP \fBsyncpackage\fR allows you to upload files with the same checksums of the Debian ones, as the common script used by Ubuntu archive administrators does, @@ -15,14 +14,15 @@ this way you can preserve source files integrity between the two distributions. \fBsyncpackage\fR will detect source tarballs with mismatching checksums and will automatically create fake syncs instead. .SH WARNING -The use of \fBsyncpackage\fR is discouraged by the Ubuntu Archive -Administrators, as it introduces an unnecessary window for error. -In future launchpad will offer the ability to directly perform sync -requests, without a developer having to do an upload. -Until then, it's advised to use \fBsyncpackage\fR with caution, and -request syncs via bugs with -.BR requestsync (1) -where possible. +The use of \fBsyncpackage \-\-no-\-lp\fR, which generates a changes file to +be directly uploaded to the Ubuntu primary archive or a PPA, is discouraged +by the Ubuntu Archive Administrators, as it introduces an unnecessary window +for error. +This only exists for backward compatibility, for unusual corner cases, and +for uploads to archives other than the Ubuntu primary archive. +Omitting this option will cause Launchpad to perform the sync request +directly, which is the preferred method for uploads to the Ubuntu primary +archive. .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR @@ -43,6 +43,13 @@ Specify the component to sync from. \fB\-v\fR, \fB\-\-verbose\fR Display more progress information. .TP +.B \-\-no\-lp +Construct sync locally rather than letting Launchpad copy the package +directly (not recommended). +.TP +\fB\-l\fI INSTANCE\fR, \fB\-\-lpinstance\fR=\fIINSTANCE\fR +Launchpad instance to connect to (default: production). +.TP \fB\-n\fI UPLOADER_NAME\fR, \fB\-\-uploader\-name\fR=\fIUPLOADER_NAME\fR Use UPLOADER_NAME as the name of the maintainer for this upload instead of evaluating DEBFULLNAME and UBUMAIL. @@ -75,6 +82,9 @@ back to the default mirror. .B \-\-no\-conf Do not read any configuration files, or configuration from environment variables. +.TP +.B \-\-simulate +Show what would be done, but don't actually do it. .SH ENVIRONMENT .TP .BR DEBFULLNAME ", " DEBEMAIL ", " UBUMAIL diff --git a/syncpackage b/syncpackage index 17a5214..65cea03 100755 --- a/syncpackage +++ b/syncpackage @@ -357,7 +357,8 @@ def main(): parser.add_option("--no-lp", dest="lp", action="store_false", default=True, help="Construct sync locally rather than letting " - "Launchpad copy the package directly.") + "Launchpad copy the package directly (not " + "recommended).") parser.add_option('-l', '--lpinstance', metavar='INSTANCE', dest='lpinstance', default=None, help='Launchpad instance to connect to ' From 91bad45ec1f551c5c238c7e52abd40a7b7d2bd0b Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 15:45:33 +0100 Subject: [PATCH 03/38] .dsc syncs only work with --no-lp --- syncpackage | 3 +++ 1 file changed, 3 insertions(+) diff --git a/syncpackage b/syncpackage index 65cea03..79e94a6 100755 --- a/syncpackage +++ b/syncpackage @@ -437,6 +437,9 @@ def main(): options.uploader_email = ubu_email(export=False)[1] if options.lp: + if args[0].endswith('.dsc'): + parser.error('.dsc files can only be synced using --no-lp.') + # We need devel for now. api_version = 'devel' From 2b03e3ca99e49ac512b9749221e6a41f2c762598 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 15:47:21 +0100 Subject: [PATCH 04/38] more logging by default --- syncpackage | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/syncpackage b/syncpackage index 79e94a6..80fc2c2 100755 --- a/syncpackage +++ b/syncpackage @@ -312,15 +312,15 @@ def copy(src_pkg, debian_version, release, simulate=False): ubuntu_version = ubuntu_archive.getSourcePackage( src_pkg, ubuntu_series, ubuntu_pocket).getVersion() - Logger.info('Source %s -> %s/%s: current version %s, new version %s', - src_pkg, ubuntu_series, ubuntu_pocket, - ubuntu_version, debian_version) + Logger.normal('Source %s -> %s/%s: current version %s, new version %s', + src_pkg, ubuntu_series, ubuntu_pocket, + ubuntu_version, debian_version) if Version(debian_version) <= Version(ubuntu_version): Logger.error('Debian version is <= Ubuntu version; nothing to do!') sys.exit(1) except udtexceptions.PackageNotFoundException: - Logger.info('Source %s -> %s/%s: not in Ubuntu, new version %s', - src_pkg, ubuntu_series, ubuntu_pocket, debian_version) + Logger.normal('Source %s -> %s/%s: not in Ubuntu, new version %s', + src_pkg, ubuntu_series, ubuntu_pocket, debian_version) if simulate: return @@ -331,8 +331,8 @@ def copy(src_pkg, debian_version, release, simulate=False): to_series=ubuntu_series, to_pocket=ubuntu_pocket, include_binaries=False) - Logger.info('Request succeeded; you should get an e-mail once it is ' - 'processed.') + Logger.normal('Request succeeded; you should get an e-mail once it is ' + 'processed.') def main(): usage = "%prog [options] <.dsc URL/path or package name>" From e6bde18b04d11470277c0ae06a3197f8b457f480 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 16:00:30 +0100 Subject: [PATCH 05/38] add explicit confirmation step --- syncpackage | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/syncpackage b/syncpackage index 80fc2c2..74ce307 100755 --- a/syncpackage +++ b/syncpackage @@ -324,6 +324,16 @@ def copy(src_pkg, debian_version, release, simulate=False): if simulate: return + if 'ubuntu' in ubuntu_version: + print "Ubuntu version had Ubuntu-specific modifications; check them " \ + "carefully!" + try: + answer = raw_input("Sync this package? [y/N] ") + except: + print >>sys.stderr, "Aborted" + if answer.lower() not in ("y", "yes"): + return + ubuntu_archive.copyPackage( source_name=src_pkg, version=debian_version, From e8b02a39b2d42ba91fc25520fb9c1ac699b045d1 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 16:20:29 +0100 Subject: [PATCH 06/38] monkeypatching doesn't work right; extend Launchpad.login instead --- syncpackage | 7 ++----- ubuntutools/lp/lpapicache.py | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/syncpackage b/syncpackage index 74ce307..a5bd5b5 100755 --- a/syncpackage +++ b/syncpackage @@ -35,7 +35,7 @@ from ubuntutools.config import UDTConfig, ubu_email from ubuntutools.requestsync.mail import (getDebianSrcPkg as requestsync_mail_getDebianSrcPkg) from ubuntutools.requestsync.lp import getDebianSrcPkg, getUbuntuSrcPkg -from ubuntutools.lp import udtexceptions, api_version +from ubuntutools.lp import udtexceptions from ubuntutools.lp.lpapicache import Distribution, Launchpad from ubuntutools.misc import split_release_pocket from ubuntutools import subprocess @@ -450,14 +450,11 @@ def main(): if args[0].endswith('.dsc'): parser.error('.dsc files can only be synced using --no-lp.') - # We need devel for now. - api_version = 'devel' - if options.lpinstance is None: options.lpinstance = config.get_value('LPINSTANCE') try: - Launchpad.login(service=options.lpinstance) + Launchpad.login(service=options.lpinstance, api_version='devel') except IOError: sys.exit(1) diff --git a/ubuntutools/lp/lpapicache.py b/ubuntutools/lp/lpapicache.py index b223333..ea7f17d 100644 --- a/ubuntutools/lp/lpapicache.py +++ b/ubuntutools/lp/lpapicache.py @@ -53,7 +53,7 @@ _POCKETS = ('Release', 'Security', 'Updates', 'Proposed', 'Backports') class _Launchpad(object): '''Singleton for LP API access.''' - def login(self, service=service): + def login(self, service=service, api_version=api_version): '''Enforce a non-anonymous login.''' if not self.logged_in: try: From b9353d781a0eb4bae710cb7efcca3618ccfcd22c Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 16:30:10 +0100 Subject: [PATCH 07/38] better error presentation --- syncpackage | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/syncpackage b/syncpackage index a5bd5b5..5fa671d 100755 --- a/syncpackage +++ b/syncpackage @@ -29,6 +29,8 @@ import sys from devscripts.logger import Logger +from lazr.restfulclient.errors import HTTPError + from ubuntutools.archive import (DebianSourcePackage, UbuntuSourcePackage, DownloadError) from ubuntutools.config import UDTConfig, ubu_email @@ -334,13 +336,20 @@ def copy(src_pkg, debian_version, release, simulate=False): if answer.lower() not in ("y", "yes"): return - ubuntu_archive.copyPackage( - source_name=src_pkg, - version=debian_version, - from_archive=debian_archive.lp_object(), - to_series=ubuntu_series, - to_pocket=ubuntu_pocket, - include_binaries=False) + try: + ubuntu_archive.copyPackage( + source_name=src_pkg, + version=debian_version, + from_archive=debian_archive.lp_object(), + to_series=ubuntu_series, + to_pocket=ubuntu_pocket, + include_binaries=False) + except HTTPError, 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.') From ecaaa33fdce0ae415f51334f6f5418d021507ddd Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 17:37:52 +0100 Subject: [PATCH 08/38] typo --- doc/syncpackage.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/syncpackage.1 b/doc/syncpackage.1 index 57416f9..979b748 100644 --- a/doc/syncpackage.1 +++ b/doc/syncpackage.1 @@ -14,7 +14,7 @@ this way you can preserve source files integrity between the two distributions. \fBsyncpackage\fR will detect source tarballs with mismatching checksums and will automatically create fake syncs instead. .SH WARNING -The use of \fBsyncpackage \-\-no-\-lp\fR, which generates a changes file to +The use of \fBsyncpackage \-\-no\-lp\fR, which generates a changes file to be directly uploaded to the Ubuntu primary archive or a PPA, is discouraged by the Ubuntu Archive Administrators, as it introduces an unnecessary window for error. From f8d4866cbc29970ec678b66b9a054096216cb966 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 18:07:58 +0100 Subject: [PATCH 09/38] move copyPackage into lpapicache for better encapsulation --- syncpackage | 2 +- ubuntutools/lp/lpapicache.py | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/syncpackage b/syncpackage index 5fa671d..7bd272a 100755 --- a/syncpackage +++ b/syncpackage @@ -340,7 +340,7 @@ def copy(src_pkg, debian_version, release, simulate=False): ubuntu_archive.copyPackage( source_name=src_pkg, version=debian_version, - from_archive=debian_archive.lp_object(), + from_archive=debian_archive, to_series=ubuntu_series, to_pocket=ubuntu_pocket, include_binaries=False) diff --git a/ubuntutools/lp/lpapicache.py b/ubuntutools/lp/lpapicache.py index ea7f17d..b7339ca 100644 --- a/ubuntutools/lp/lpapicache.py +++ b/ubuntutools/lp/lpapicache.py @@ -172,9 +172,6 @@ class BaseWrapper(object): else: return '<%s: %r>' % (self.__class__.__name__, self._lpobject) - def lp_object(self): - return self._lpobject - class Distribution(BaseWrapper): ''' @@ -335,6 +332,25 @@ class Archive(BaseWrapper): return self._srcpkgs[(name, series.name, pocket)] + def copyPackage(self, source_name, version, from_archive, to_pocket, + to_series = None, include_binaries = False): + '''Copy a single named source into this archive. + + Asynchronously copy a specific version of a named source to the + destination archive if necessary. Calls to this method will return + immediately if the copy passes basic security checks and the copy + will happen sometime later with full checking. + ''' + + self._lpobject.copyPackage( + source_name=source_name, + version=version, + from_archive=from_archive._lpobject, + to_pocket=to_pocket, + to_series=to_series, + include_binaries=include_binaries + ) + class SourcePackagePublishingHistory(BaseWrapper): ''' From 0735ad8de3d06c231a320343268691458fff7d90 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 18:16:52 +0100 Subject: [PATCH 10/38] handle -d in Launchpad copy mode --- syncpackage | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/syncpackage b/syncpackage index 7bd272a..56b14a7 100755 --- a/syncpackage +++ b/syncpackage @@ -29,6 +29,8 @@ import sys from devscripts.logger import Logger +from distro_info import DebianDistroInfo + from lazr.restfulclient.errors import HTTPError from ubuntutools.archive import (DebianSourcePackage, UbuntuSourcePackage, @@ -297,7 +299,7 @@ def fetch_source_pkg(package, dist, version, component, ubuntu_release, mirror): return DebianSourcePackage(package, version.full_version, component, mirrors=[mirror]) -def copy(src_pkg, debian_version, release, simulate=False): +def copy(src_pkg, debian_dist, debian_version, release, simulate=False): debian = Distribution('debian') ubuntu = Distribution('ubuntu') debian_archive = debian.getArchive() @@ -309,7 +311,12 @@ def copy(src_pkg, debian_version, release, simulate=False): ubuntu_series, ubuntu_pocket = split_release_pocket(release) if debian_version is None: - debian_version = debian_archive.getSourcePackage(src_pkg).getVersion() + if debian_dist is None: + debian_dist = 'unstable' + debian_info = DebianDistroInfo() + debian_dist = debian_info.codename(debian_dist, default=debian_dist) + debian_version = debian_archive.getSourcePackage( + src_pkg, debian_dist).getVersion() try: ubuntu_version = ubuntu_archive.getSourcePackage( src_pkg, ubuntu_series, ubuntu_pocket).getVersion() @@ -467,7 +474,8 @@ def main(): except IOError: sys.exit(1) - copy(args[0], options.debversion, options.release, options.simulate) + copy(args[0], options.dist, options.debversion, options.release, + options.simulate) else: Launchpad.login_anonymously() if options.release is None: From 87e1cadcb06547a0068a4a5d704704c37877db4e Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 19:39:07 +0100 Subject: [PATCH 11/38] use ubuntutools.question --- syncpackage | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/syncpackage b/syncpackage index 56b14a7..e5bbf99 100755 --- a/syncpackage +++ b/syncpackage @@ -42,6 +42,7 @@ from ubuntutools.requestsync.lp import getDebianSrcPkg, getUbuntuSrcPkg from ubuntutools.lp import udtexceptions from ubuntutools.lp.lpapicache import Distribution, Launchpad from ubuntutools.misc import split_release_pocket +from ubuntutools.question import YesNoQuestion from ubuntutools import subprocess @@ -336,11 +337,8 @@ def copy(src_pkg, debian_dist, debian_version, release, simulate=False): if 'ubuntu' in ubuntu_version: print "Ubuntu version had Ubuntu-specific modifications; check them " \ "carefully!" - try: - answer = raw_input("Sync this package? [y/N] ") - except: - print >>sys.stderr, "Aborted" - if answer.lower() not in ("y", "yes"): + answer = YesNoQuestion().ask("Sync this package", "no") + if answer != "yes": return try: From 0ef30ff6652d8a5cf5b2b59362c9d80e8ee669f6 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 16 Aug 2011 19:56:38 +0100 Subject: [PATCH 12/38] syncpackage: Require -f/--force option to overwrite Ubuntu changes. --- debian/changelog | 1 + doc/syncpackage.1 | 3 +++ syncpackage | 30 +++++++++++++++++++++--------- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/debian/changelog b/debian/changelog index a49cb51..8a77a29 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,7 @@ ubuntu-dev-tools (0.129) UNRELEASED; urgency=low * syncpackage: Convert to new LP API, with --no-lp available for the old style of operation. + * syncpackage: Require -f/--force option to overwrite Ubuntu changes. -- Colin Watson Tue, 16 Aug 2011 16:40:22 +0100 diff --git a/doc/syncpackage.1 b/doc/syncpackage.1 index 979b748..67e7630 100644 --- a/doc/syncpackage.1 +++ b/doc/syncpackage.1 @@ -67,6 +67,9 @@ Do not sign the upload. \fB\-b\fI BUG\fR, \fB\-\-bug\fR=\fIBUG\fR Mark a Launchpad bug as being fixed by this upload. .TP +\fB\-f\fR, \fB\-\-force\fR +Force sync over the top of Ubuntu changes. +.TP .B \-d \fIDEBIAN_MIRROR\fR, \fB\-\-debian\-mirror\fR=\fIDEBIAN_MIRROR\fR Use the specified mirror. Should be in the form \fBhttp://ftp.debian.org/debian\fR. diff --git a/syncpackage b/syncpackage index e5bbf99..7ccd6b4 100755 --- a/syncpackage +++ b/syncpackage @@ -116,7 +116,7 @@ def add_fixed_bugs(changes, bugs): return "\n".join(changes + [""]) def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror, - keyid=None, simulate=False): + keyid=None, simulate=False, force=False): uploader = name + " <" + email + ">" src_pkg.pull_dsc() @@ -142,6 +142,10 @@ def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror, cur_ver = ubuntu_ver.get_related_debian_version() if ubuntu_ver.is_modified_in_ubuntu(): + if not force: + 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) @@ -300,7 +304,8 @@ def fetch_source_pkg(package, dist, version, component, ubuntu_release, mirror): return DebianSourcePackage(package, version.full_version, component, mirrors=[mirror]) -def copy(src_pkg, debian_dist, debian_version, release, simulate=False): +def copy(src_pkg, debian_dist, debian_version, release, simulate=False, + force=False): debian = Distribution('debian') ubuntu = Distribution('ubuntu') debian_archive = debian.getArchive() @@ -322,21 +327,25 @@ def copy(src_pkg, debian_dist, debian_version, release, simulate=False): ubuntu_version = ubuntu_archive.getSourcePackage( src_pkg, ubuntu_series, ubuntu_pocket).getVersion() + debian_version = Version(debian_version) + ubuntu_version = Version(ubuntu_version) + Logger.normal('Source %s -> %s/%s: current version %s, new version %s', src_pkg, ubuntu_series, ubuntu_pocket, ubuntu_version, debian_version) - if Version(debian_version) <= Version(ubuntu_version): + if debian_version <= ubuntu_version: Logger.error('Debian version is <= Ubuntu version; nothing to do!') sys.exit(1) + + if not force and ubuntu_version.is_modified_in_ubuntu(): + Logger.error('--force is required to discard Ubuntu changes.') + sys.exit(1) except udtexceptions.PackageNotFoundException: Logger.normal('Source %s -> %s/%s: not in Ubuntu, new version %s', src_pkg, ubuntu_series, ubuntu_pocket, debian_version) if simulate: return - if 'ubuntu' in ubuntu_version: - print "Ubuntu version had Ubuntu-specific modifications; check them " \ - "carefully!" answer = YesNoQuestion().ask("Sync this package", "no") if answer != "yes": return @@ -344,7 +353,7 @@ def copy(src_pkg, debian_dist, debian_version, release, simulate=False): try: ubuntu_archive.copyPackage( source_name=src_pkg, - version=debian_version, + version=str(debian_version), from_archive=debian_archive, to_series=ubuntu_series, to_pocket=ubuntu_pocket, @@ -405,6 +414,9 @@ def main(): dest="bugs", action="append", default=list(), help="Mark Launchpad bug BUG as being fixed by this " "upload.") + parser.add_option("-f", "--force", + dest="force", action="store_true", default=False, + help="Force sync over the top of Ubuntu changes.") parser.add_option('-D', '--debian-mirror', metavar='DEBIAN_MIRROR', dest='debian_mirror', help='Preferred Debian mirror ' @@ -473,7 +485,7 @@ def main(): sys.exit(1) copy(args[0], options.dist, options.debversion, options.release, - options.simulate) + options.simulate, options.force) else: Launchpad.login_anonymously() if options.release is None: @@ -488,7 +500,7 @@ def main(): sync_dsc(src_pkg, options.dist, options.release, options.uploader_name, options.uploader_email, options.bugs, options.ubuntu_mirror, - options.keyid, options.simulate) + options.keyid, options.simulate, options.force) if __name__ == "__main__": main() From da15a350633c0d47f242585cfbca2e6282f620fd Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 17 Aug 2011 00:01:45 +0100 Subject: [PATCH 13/38] validate that the provided Debian version exists --- syncpackage | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/syncpackage b/syncpackage index 7ccd6b4..e473330 100755 --- a/syncpackage +++ b/syncpackage @@ -323,6 +323,15 @@ def copy(src_pkg, debian_dist, debian_version, release, simulate=False, debian_dist = debian_info.codename(debian_dist, default=debian_dist) debian_version = debian_archive.getSourcePackage( src_pkg, debian_dist).getVersion() + else: + # Ensure that the provided Debian version actually exists. + debian_sources = debian_archive.getPublishedSources( + source_name=src_pkg, + version=debian_version, + exact_match=True) + if not debian_sources: + Logger.error('Debian version %s does not exist!', debian_version) + sys.exit(1) try: ubuntu_version = ubuntu_archive.getSourcePackage( src_pkg, ubuntu_series, ubuntu_pocket).getVersion() From a3e252dece4265833a593c345b3f23c5f8fc6ed9 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 17 Aug 2011 00:07:34 +0100 Subject: [PATCH 14/38] document restriction of -n and -e to --no-lp mode --- doc/syncpackage.1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/syncpackage.1 b/doc/syncpackage.1 index 67e7630..5117e9a 100644 --- a/doc/syncpackage.1 +++ b/doc/syncpackage.1 @@ -53,10 +53,12 @@ Launchpad instance to connect to (default: production). \fB\-n\fI UPLOADER_NAME\fR, \fB\-\-uploader\-name\fR=\fIUPLOADER_NAME\fR Use UPLOADER_NAME as the name of the maintainer for this upload instead of evaluating DEBFULLNAME and UBUMAIL. +This option may only be used in \fB\-\-no\-lp\fR mode. .TP \fB\-e\fI UPLOADER_EMAIL\fR, \fB\-\-uploader\-email\fR=\fIUPLOADER_EMAIL\fR Use UPLOADER_EMAIL as the email address of the maintainer for this upload instead of evaluating DEBEMAIL and UBUMAIL. +This option may only be used in \fB\-\-no\-lp\fR mode. .TP \fB\-k\fI KEYID\fR, \fB\-\-key\fR=\fIKEYID\fR Specify the key ID to be used for signing. From d26a7521b02e613a8e3b5bc9c4437f7fe8482379 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 17 Aug 2011 02:54:37 +0100 Subject: [PATCH 15/38] make it possible to quieten download progress information, particularly useful if downloading only the small .dsc files --- ubuntutools/archive.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/ubuntutools/archive.py b/ubuntutools/archive.py index f54c4dd..1604b53 100644 --- a/ubuntutools/archive.py +++ b/ubuntutools/archive.py @@ -207,7 +207,7 @@ class SourcePackage(object): yield self._mirror_url(mirror, name) yield self._lp_url(name) - def pull_dsc(self): + def pull_dsc(self, quiet = False): "Retrieve dscfile and parse" if self._dsc_source: parsed = urlparse.urlparse(self._dsc_source) @@ -221,11 +221,12 @@ class SourcePackage(object): # Temporarily rename to the filename we are going to open os.rename(parsed.path, self.dsc_pathname) else: - if not self._download_file(self._dsc_source, self.dsc_name): + if not self._download_file(self._dsc_source, self.dsc_name, + quiet=quiet): raise DownloadError('dsc not found') else: if not self._download_file(self._lp_url(self.dsc_name), - self.dsc_name): + self.dsc_name, quiet=quiet): raise DownloadError('dsc not found') self._check_dsc() @@ -272,7 +273,7 @@ class SourcePackage(object): else: Logger.info(message) - def _download_file(self, url, filename): + def _download_file(self, url, filename, quiet = False): "Download url to filename in workdir." logurl = url if os.path.basename(url) != filename: @@ -286,10 +287,12 @@ class SourcePackage(object): if entry['name'] == filename] assert len(size) == 1 size = int(size[0]) - Logger.normal('Downloading %s (%0.3f MiB)', logurl, - size / 1024.0 / 1024) + if not quiet: + Logger.normal('Downloading %s (%0.3f MiB)', logurl, + size / 1024.0 / 1024) else: - Logger.normal('Downloading %s', logurl) + if not quiet: + Logger.normal('Downloading %s', logurl) # Launchpad will try to redirect us to plain-http Launchpad Librarian, # but we want SSL when fetching the dsc @@ -309,11 +312,13 @@ class SourcePackage(object): if block == '': break out.write(block) - Logger.stdout.write('.') - Logger.stdout.flush() + if not quiet: + Logger.stdout.write('.') + Logger.stdout.flush() in_.close() - Logger.stdout.write(' done\n') - Logger.stdout.flush() + if not quiet: + Logger.stdout.write(' done\n') + Logger.stdout.flush() if self.dsc and not url.endswith('.dsc'): if not self.dsc.verify_file(pathname): Logger.error('Checksum does not match.') @@ -432,10 +437,10 @@ class DebianSourcePackage(SourcePackage): if self.snapshot_list: yield self._snapshot_url(name) - def pull_dsc(self): + def pull_dsc(self, quiet = False): "Retrieve dscfile and parse" try: - super(DebianSourcePackage, self).pull_dsc() + super(DebianSourcePackage, self).pull_dsc(quiet=quiet) return except DownloadError: pass @@ -443,7 +448,7 @@ class DebianSourcePackage(SourcePackage): # Not all Debian Source packages get imported to LP # (or the importer could be lagging) for url in self._source_urls(self.dsc_name): - if self._download_file(url, self.dsc_name): + if self._download_file(url, self.dsc_name, quiet=quiet): break else: raise DownloadError('dsc could not be found anywhere') From 5eb960dd3fe57daa16d8cee8cefee035cebb8e5d Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 17 Aug 2011 03:03:01 +0100 Subject: [PATCH 16/38] make better use of ubuntutools.archive, allowing us to detect when fakesyncs are required in LP mode --- syncpackage | 91 ++++++++++++++++++++++------------- ubuntutools/requestsync/lp.py | 4 +- 2 files changed, 59 insertions(+), 36 deletions(-) diff --git a/syncpackage b/syncpackage index e473330..ce6b87e 100755 --- a/syncpackage +++ b/syncpackage @@ -260,8 +260,13 @@ def fetch_source_pkg(package, dist, version, component, ubuntu_release, mirror): """Download the specified source package. dist, version, component, mirror can all be None. """ + if mirror is None: + mirrors = [] + else: + mirrors = [mirror] + if package.endswith('.dsc'): - return DebianSourcePackage(dscfile=package, mirrors=[mirror]) + return DebianSourcePackage(dscfile=package, mirrors=mirrors) if dist is None: dist = "unstable" @@ -302,10 +307,9 @@ def fetch_source_pkg(package, dist, version, component, ubuntu_release, mirror): assert component in ('main', 'contrib', 'non-free') return DebianSourcePackage(package, version.full_version, component, - mirrors=[mirror]) + mirrors=mirrors) -def copy(src_pkg, debian_dist, debian_version, release, simulate=False, - force=False): +def copy(src_pkg, debian_dist, release, simulate=False, force=False): debian = Distribution('debian') ubuntu = Distribution('ubuntu') debian_archive = debian.getArchive() @@ -316,42 +320,58 @@ def copy(src_pkg, debian_dist, debian_version, release, simulate=False, else: ubuntu_series, ubuntu_pocket = split_release_pocket(release) - if debian_version is None: - if debian_dist is None: - debian_dist = 'unstable' - debian_info = DebianDistroInfo() - debian_dist = debian_info.codename(debian_dist, default=debian_dist) - debian_version = debian_archive.getSourcePackage( - src_pkg, debian_dist).getVersion() - else: - # Ensure that the provided Debian version actually exists. - debian_sources = debian_archive.getPublishedSources( - source_name=src_pkg, - version=debian_version, - exact_match=True) - if not debian_sources: - Logger.error('Debian version %s does not exist!', debian_version) - sys.exit(1) + # Ensure that the provided Debian version actually exists. try: - ubuntu_version = ubuntu_archive.getSourcePackage( - src_pkg, ubuntu_series, ubuntu_pocket).getVersion() + debian_spph = src_pkg.lp_spph() + except IndexError: + Logger.error('Debian version %s does not exist!', src_pkg.version) + sys.exit(1) - debian_version = Version(debian_version) - ubuntu_version = Version(ubuntu_version) + try: + ubuntu_spph = getUbuntuSrcPkg(src_pkg.source, + ubuntu_series, ubuntu_pocket) + ubuntu_pkg = UbuntuSourcePackage(src_pkg.source, + ubuntu_spph.getVersion(), + ubuntu_spph.getComponent(), + mirrors=[]) Logger.normal('Source %s -> %s/%s: current version %s, new version %s', - src_pkg, ubuntu_series, ubuntu_pocket, - ubuntu_version, debian_version) - if debian_version <= ubuntu_version: - Logger.error('Debian version is <= Ubuntu version; nothing to do!') - sys.exit(1) + src_pkg.source, ubuntu_series, ubuntu_pocket, + ubuntu_pkg.version, src_pkg.version) + ubuntu_version = Version(ubuntu_pkg.version.full_version) if not force and ubuntu_version.is_modified_in_ubuntu(): Logger.error('--force is required to discard Ubuntu changes.') sys.exit(1) + + # Check whether a fakesync would be required. + src_pkg.pull_dsc(quiet=not Logger.verbose) + ubuntu_pkg.pull_dsc(quiet=not Logger.verbose) + for field, key in (('Checksums-Sha256', 'sha256'), + ('Checksums-Sha1', 'sha1'), + ('Files', 'md5sum')): + if field not in src_pkg.dsc or field not in ubuntu_pkg.dsc: + continue + debian_checksums = \ + dict((entry['name'], (int(entry['size']), entry[key])) + for entry in src_pkg.dsc[field]) + ubuntu_checksums = \ + dict((entry['name'], (int(entry['size']), entry[key])) + for entry in ubuntu_pkg.dsc[field]) + for name, (size, checksum) in debian_checksums.iteritems(): + if name not in ubuntu_checksums: + # new file + continue + if (size != ubuntu_checksums[name][0] or + checksum != ubuntu_checksums[name][1]): + Logger.error('The checksums of the Debian and Ubuntu ' + 'packages mismatch. A fake sync is required.') + sys.exit(1) + break # one checksum is good enough except udtexceptions.PackageNotFoundException: Logger.normal('Source %s -> %s/%s: not in Ubuntu, new version %s', - src_pkg, ubuntu_series, ubuntu_pocket, debian_version) + src_pkg.source, ubuntu_series, ubuntu_pocket, + src_pkg.version) if simulate: return @@ -361,8 +381,8 @@ def copy(src_pkg, debian_dist, debian_version, release, simulate=False, try: ubuntu_archive.copyPackage( - source_name=src_pkg, - version=str(debian_version), + source_name=src_pkg.source, + version=str(src_pkg.version), from_archive=debian_archive, to_series=ubuntu_series, to_pocket=ubuntu_pocket, @@ -493,8 +513,11 @@ def main(): except IOError: sys.exit(1) - copy(args[0], options.dist, options.debversion, options.release, - options.simulate, options.force) + src_pkg = fetch_source_pkg(args[0], options.dist, options.debversion, + options.component, options.release, None) + + copy(src_pkg, options.dist, options.release, options.simulate, + options.force) else: Launchpad.login_anonymously() if options.release is None: diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py index 60ce01f..710758c 100644 --- a/ubuntutools/requestsync/lp.py +++ b/ubuntutools/requestsync/lp.py @@ -34,11 +34,11 @@ def getDebianSrcPkg(name, release): return debian_archive.getSourcePackage(name, release) -def getUbuntuSrcPkg(name, release): +def getUbuntuSrcPkg(name, release, pocket = 'Release'): ubuntu = Distribution('ubuntu') ubuntu_archive = ubuntu.getArchive() - return ubuntu_archive.getSourcePackage(name, release) + return ubuntu_archive.getSourcePackage(name, release, pocket) def needSponsorship(name, component, release): ''' From f91f61f8d45382da9523e5fc41daa540349f6500 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 17 Aug 2011 12:59:54 +0100 Subject: [PATCH 17/38] DebianSourcePackage.lp_spph is annoyingly overloaded; just do the check directly --- syncpackage | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/syncpackage b/syncpackage index ce6b87e..64ebb34 100755 --- a/syncpackage +++ b/syncpackage @@ -322,7 +322,10 @@ def copy(src_pkg, debian_dist, release, simulate=False, force=False): # Ensure that the provided Debian version actually exists. try: - debian_spph = src_pkg.lp_spph() + debian_spph = debian_archive.getPublishedSources( + source_name=src_pkg.source, + version=src_pkg.version.full_version, + exact_match=True)[0] except IndexError: Logger.error('Debian version %s does not exist!', src_pkg.version) sys.exit(1) From 0a2d4b11a83b31d06f79a04738dacf48de649372 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 17 Aug 2011 13:02:07 +0100 Subject: [PATCH 18/38] use version.full_version rather than str(version) --- syncpackage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncpackage b/syncpackage index 64ebb34..e90934a 100755 --- a/syncpackage +++ b/syncpackage @@ -385,7 +385,7 @@ def copy(src_pkg, debian_dist, release, simulate=False, force=False): try: ubuntu_archive.copyPackage( source_name=src_pkg.source, - version=str(src_pkg.version), + version=src_pkg.version.full_version, from_archive=debian_archive, to_series=ubuntu_series, to_pocket=ubuntu_pocket, From e3693820e5361d878e443102b39f78633f859bfc Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 17 Aug 2011 16:44:07 +0100 Subject: [PATCH 19/38] refer to syncpackage from requestsync(1) for users with upload permission --- doc/requestsync.1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/requestsync.1 b/doc/requestsync.1 index 67bde76..702cd70 100644 --- a/doc/requestsync.1 +++ b/doc/requestsync.1 @@ -32,6 +32,11 @@ This check is only performed if \fBrequestsync\fR is allowed to use the LP API answer the question about upload permissions honestly to determine if a team with approval rights is to be subscribed to the bug. +If you have permission to upload the package directly, then you may prefer +to use \fBsyncpackage\fR instead to copy the package using the Launchpad +API. At some future point, \fBrequestsync\fR will be changed to do this +automatically. + .PP \fBrequestsync\fR uses launchpadlib authentication to file its requests. From 1d68d8064c345240c7db090b25a0589f2c795513 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 17 Aug 2011 16:48:17 +0100 Subject: [PATCH 20/38] add note on requestsync stderr about syncpackage --- requestsync | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/requestsync b/requestsync index 9b3ff59..33a6462 100755 --- a/requestsync +++ b/requestsync @@ -239,6 +239,10 @@ def main(): if not sponsorship: sponsorship = needSponsorship(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.') + # Check for existing package reports if not newsource: checkExistingReports(srcpkg) From 189bfa238ab6671b79fdf846c3c7725624a7f7dc Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 17 Aug 2011 17:10:09 +0100 Subject: [PATCH 21/38] fake syncs require --no-lp --- syncpackage | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/syncpackage b/syncpackage index e90934a..f07bb0c 100755 --- a/syncpackage +++ b/syncpackage @@ -368,7 +368,8 @@ def copy(src_pkg, debian_dist, release, simulate=False, force=False): if (size != ubuntu_checksums[name][0] or checksum != ubuntu_checksums[name][1]): Logger.error('The checksums of the Debian and Ubuntu ' - 'packages mismatch. A fake sync is required.') + 'packages mismatch. A fake sync using ' + '--no-lp is required.') sys.exit(1) break # one checksum is good enough except udtexceptions.PackageNotFoundException: From 38ade0ea7da88f1c213bd3815b4c7fbdb6760554 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 18 Aug 2011 12:57:19 +0100 Subject: [PATCH 22/38] avoid shadowing global "debian" name --- syncpackage | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/syncpackage b/syncpackage index f07bb0c..3349c3c 100755 --- a/syncpackage +++ b/syncpackage @@ -310,9 +310,8 @@ def fetch_source_pkg(package, dist, version, component, ubuntu_release, mirror): mirrors=mirrors) def copy(src_pkg, debian_dist, release, simulate=False, force=False): - debian = Distribution('debian') ubuntu = Distribution('ubuntu') - debian_archive = debian.getArchive() + debian_archive = Distribution('debian').getArchive() ubuntu_archive = ubuntu.getArchive() if release is None: ubuntu_series = ubuntu.getDevelopmentSeries().name From f40db6836e379078e1478b2917dc6e0f9095a508 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 18 Aug 2011 12:59:15 +0100 Subject: [PATCH 23/38] drop unused argument --- syncpackage | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/syncpackage b/syncpackage index 3349c3c..89e74f0 100755 --- a/syncpackage +++ b/syncpackage @@ -309,7 +309,7 @@ def fetch_source_pkg(package, dist, version, component, ubuntu_release, mirror): return DebianSourcePackage(package, version.full_version, component, mirrors=mirrors) -def copy(src_pkg, debian_dist, release, simulate=False, force=False): +def copy(src_pkg, release, simulate=False, force=False): ubuntu = Distribution('ubuntu') debian_archive = Distribution('debian').getArchive() ubuntu_archive = ubuntu.getArchive() @@ -519,8 +519,7 @@ def main(): src_pkg = fetch_source_pkg(args[0], options.dist, options.debversion, options.component, options.release, None) - copy(src_pkg, options.dist, options.release, options.simulate, - options.force) + copy(src_pkg, options.release, options.simulate, options.force) else: Launchpad.login_anonymously() if options.release is None: From 9bc479dbcbf382f48ec035af93788a8a002b4128 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 18 Aug 2011 13:00:00 +0100 Subject: [PATCH 24/38] drop unused variable --- syncpackage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncpackage b/syncpackage index 89e74f0..222cd04 100755 --- a/syncpackage +++ b/syncpackage @@ -321,7 +321,7 @@ def copy(src_pkg, release, simulate=False, force=False): # Ensure that the provided Debian version actually exists. try: - debian_spph = debian_archive.getPublishedSources( + debian_archive.getPublishedSources( source_name=src_pkg.source, version=src_pkg.version.full_version, exact_match=True)[0] From d624e9d18f93de9f700b0c09cb9118f2493407ad Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 18 Aug 2011 15:06:05 +0100 Subject: [PATCH 25/38] factor out dsc comparison into a method on ubuntutools.archive.Dsc --- syncpackage | 26 ++++---------------------- ubuntutools/archive.py | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/syncpackage b/syncpackage index 222cd04..7d87a55 100755 --- a/syncpackage +++ b/syncpackage @@ -349,28 +349,10 @@ def copy(src_pkg, release, simulate=False, force=False): # Check whether a fakesync would be required. src_pkg.pull_dsc(quiet=not Logger.verbose) ubuntu_pkg.pull_dsc(quiet=not Logger.verbose) - for field, key in (('Checksums-Sha256', 'sha256'), - ('Checksums-Sha1', 'sha1'), - ('Files', 'md5sum')): - if field not in src_pkg.dsc or field not in ubuntu_pkg.dsc: - continue - debian_checksums = \ - dict((entry['name'], (int(entry['size']), entry[key])) - for entry in src_pkg.dsc[field]) - ubuntu_checksums = \ - dict((entry['name'], (int(entry['size']), entry[key])) - for entry in ubuntu_pkg.dsc[field]) - for name, (size, checksum) in debian_checksums.iteritems(): - if name not in ubuntu_checksums: - # new file - continue - if (size != ubuntu_checksums[name][0] or - checksum != ubuntu_checksums[name][1]): - Logger.error('The checksums of the Debian and Ubuntu ' - 'packages mismatch. A fake sync using ' - '--no-lp is required.') - sys.exit(1) - break # one checksum is good enough + 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 --no-lp is required.') + sys.exit(1) except udtexceptions.PackageNotFoundException: Logger.normal('Source %s -> %s/%s: not in Ubuntu, new version %s', src_pkg.source, ubuntu_series, ubuntu_pocket, diff --git a/ubuntutools/archive.py b/ubuntutools/archive.py index 1604b53..b1e09a3 100644 --- a/ubuntutools/archive.py +++ b/ubuntutools/archive.py @@ -95,6 +95,30 @@ class Dsc(debian.deb822.Dsc): return hash_func.hexdigest() == digest return False + def compare_dsc(self, other): + """Check whether any files in these two dscs that have the same name + also have the same checksum.""" + for field, key in (('Checksums-Sha256', 'sha256'), + ('Checksums-Sha1', 'sha1'), + ('Files', 'md5sum')): + if field not in self or field not in other: + continue + our_checksums = \ + dict((entry['name'], (int(entry['size']), entry[key])) + for entry in self[field]) + their_checksums = \ + dict((entry['name'], (int(entry['size']), entry[key])) + for entry in other[field]) + for name, (size, checksum) in our_checksums.iteritems(): + if name not in their_checksums: + # file only in one dsc + continue + if (size != their_checksums[name][0] or + checksum != their_checksums[name][1]): + return False + return True # one checksum is good enough + return True + class SourcePackage(object): """Base class for source package downloading. From 2aaa7de246910157524c527bda8c550588896b75 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 18 Aug 2011 15:07:09 +0100 Subject: [PATCH 26/38] docstring for copy() --- syncpackage | 1 + 1 file changed, 1 insertion(+) diff --git a/syncpackage b/syncpackage index 7d87a55..eb43072 100755 --- a/syncpackage +++ b/syncpackage @@ -310,6 +310,7 @@ def fetch_source_pkg(package, dist, version, component, ubuntu_release, mirror): mirrors=mirrors) def copy(src_pkg, release, simulate=False, force=False): + """Copy a source package from Debian to Ubuntu using the Launchpad API.""" ubuntu = Distribution('ubuntu') debian_archive = Distribution('debian').getArchive() ubuntu_archive = ubuntu.getArchive() From 44df5e308170bccd66bc5591c297a6f23367bd3f Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 18 Aug 2011 15:08:01 +0100 Subject: [PATCH 27/38] tweak to manual page suggested by bdrung --- doc/syncpackage.1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/syncpackage.1 b/doc/syncpackage.1 index 5117e9a..009f654 100644 --- a/doc/syncpackage.1 +++ b/doc/syncpackage.1 @@ -1,11 +1,12 @@ .TH SYNCPACKAGE "1" "June 2010" "ubuntu-dev-tools" .SH NAME -syncpackage \- copy packages from Debian to Ubuntu +syncpackage \- copy source packages from Debian to Ubuntu .SH SYNOPSIS .B syncpackage [\fIoptions\fR] \fI<.dsc URL/path or package name>\fR .SH DESCRIPTION -\fBsyncpackage\fR causes a package to be copied from Debian to Ubuntu. +\fBsyncpackage\fR causes a source package to be copied from Debian to +Ubuntu. .PP \fBsyncpackage\fR allows you to upload files with the same checksums of the Debian ones, as the common script used by Ubuntu archive administrators does, From a4000c606c547f08ef8874166e166b778dad7cea Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 18 Aug 2011 15:10:19 +0100 Subject: [PATCH 28/38] drop quiet download stuff, not worth an API debate --- syncpackage | 4 ++-- ubuntutools/archive.py | 33 ++++++++++++++------------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/syncpackage b/syncpackage index eb43072..832019b 100755 --- a/syncpackage +++ b/syncpackage @@ -348,8 +348,8 @@ def copy(src_pkg, release, simulate=False, force=False): sys.exit(1) # Check whether a fakesync would be required. - src_pkg.pull_dsc(quiet=not Logger.verbose) - ubuntu_pkg.pull_dsc(quiet=not Logger.verbose) + 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 --no-lp is required.') diff --git a/ubuntutools/archive.py b/ubuntutools/archive.py index b1e09a3..4647615 100644 --- a/ubuntutools/archive.py +++ b/ubuntutools/archive.py @@ -231,7 +231,7 @@ class SourcePackage(object): yield self._mirror_url(mirror, name) yield self._lp_url(name) - def pull_dsc(self, quiet = False): + def pull_dsc(self): "Retrieve dscfile and parse" if self._dsc_source: parsed = urlparse.urlparse(self._dsc_source) @@ -245,12 +245,11 @@ class SourcePackage(object): # Temporarily rename to the filename we are going to open os.rename(parsed.path, self.dsc_pathname) else: - if not self._download_file(self._dsc_source, self.dsc_name, - quiet=quiet): + if not self._download_file(self._dsc_source, self.dsc_name): raise DownloadError('dsc not found') else: if not self._download_file(self._lp_url(self.dsc_name), - self.dsc_name, quiet=quiet): + self.dsc_name): raise DownloadError('dsc not found') self._check_dsc() @@ -297,7 +296,7 @@ class SourcePackage(object): else: Logger.info(message) - def _download_file(self, url, filename, quiet = False): + def _download_file(self, url, filename): "Download url to filename in workdir." logurl = url if os.path.basename(url) != filename: @@ -311,12 +310,10 @@ class SourcePackage(object): if entry['name'] == filename] assert len(size) == 1 size = int(size[0]) - if not quiet: - Logger.normal('Downloading %s (%0.3f MiB)', logurl, - size / 1024.0 / 1024) + Logger.normal('Downloading %s (%0.3f MiB)', logurl, + size / 1024.0 / 1024) else: - if not quiet: - Logger.normal('Downloading %s', logurl) + Logger.normal('Downloading %s', logurl) # Launchpad will try to redirect us to plain-http Launchpad Librarian, # but we want SSL when fetching the dsc @@ -336,13 +333,11 @@ class SourcePackage(object): if block == '': break out.write(block) - if not quiet: - Logger.stdout.write('.') - Logger.stdout.flush() + Logger.stdout.write('.') + Logger.stdout.flush() in_.close() - if not quiet: - Logger.stdout.write(' done\n') - Logger.stdout.flush() + Logger.stdout.write(' done\n') + Logger.stdout.flush() if self.dsc and not url.endswith('.dsc'): if not self.dsc.verify_file(pathname): Logger.error('Checksum does not match.') @@ -461,10 +456,10 @@ class DebianSourcePackage(SourcePackage): if self.snapshot_list: yield self._snapshot_url(name) - def pull_dsc(self, quiet = False): + def pull_dsc(self): "Retrieve dscfile and parse" try: - super(DebianSourcePackage, self).pull_dsc(quiet=quiet) + super(DebianSourcePackage, self).pull_dsc() return except DownloadError: pass @@ -472,7 +467,7 @@ class DebianSourcePackage(SourcePackage): # Not all Debian Source packages get imported to LP # (or the importer could be lagging) for url in self._source_urls(self.dsc_name): - if self._download_file(url, self.dsc_name, quiet=quiet): + if self._download_file(url, self.dsc_name): break else: raise DownloadError('dsc could not be found anywhere') From a6b95b7d53d4eb9a37948c560ecf3cc88b88b7a4 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 18 Aug 2011 15:11:36 +0100 Subject: [PATCH 29/38] style --- ubuntutools/requestsync/lp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py index 710758c..0165161 100644 --- a/ubuntutools/requestsync/lp.py +++ b/ubuntutools/requestsync/lp.py @@ -34,7 +34,7 @@ def getDebianSrcPkg(name, release): return debian_archive.getSourcePackage(name, release) -def getUbuntuSrcPkg(name, release, pocket = 'Release'): +def getUbuntuSrcPkg(name, release, pocket='Release'): ubuntu = Distribution('ubuntu') ubuntu_archive = ubuntu.getArchive() From ce2f96bc0dc0dbd09dda86355208972fb7ce7705 Mon Sep 17 00:00:00 2001 From: Benjamin Drung Date: Sat, 20 Aug 2011 11:31:02 +0200 Subject: [PATCH 30/38] Make pylint happier and code more PEP-8 compliant. --- lp-shell | 8 ++++---- ubuntutools/config.py | 1 - ubuntutools/lp/lpapicache.py | 8 ++++---- ubuntutools/misc.py | 1 - ubuntutools/test/test_config.py | 1 - 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/lp-shell b/lp-shell index 83c715c..22a1ef2 100755 --- a/lp-shell +++ b/lp-shell @@ -33,11 +33,11 @@ def main(): opt_parser.add_option('-a', action='store_true', dest='anonymous', default=False, help='Login anonymously into LP.') - opt_parser.add_option('--ipython',action='store_const', - dest='shell',const='ipython', default="ipython", + opt_parser.add_option('--ipython', action='store_const', + dest='shell', const='ipython', default="ipython", help='Use ipython shell (default).') - opt_parser.add_option('--python',action='store_const', - dest='shell',const='python', + opt_parser.add_option('--python', action='store_const', + dest='shell', const='python', help='Use python shell.') diff --git a/ubuntutools/config.py b/ubuntutools/config.py index 0680c0e..1743247 100644 --- a/ubuntutools/config.py +++ b/ubuntutools/config.py @@ -16,7 +16,6 @@ # PERFORMANCE OF THIS SOFTWARE. import os -import os.path import pwd import re import shlex diff --git a/ubuntutools/lp/lpapicache.py b/ubuntutools/lp/lpapicache.py index b7339ca..93601a3 100644 --- a/ubuntutools/lp/lpapicache.py +++ b/ubuntutools/lp/lpapicache.py @@ -201,7 +201,7 @@ class Distribution(BaseWrapper): cached = Distribution(Launchpad.distributions[dist]) return cached - def getArchive(self, archive = None): + def getArchive(self, archive=None): ''' Returns an Archive object for the requested archive. Raises a ArchiveNotFoundException if the archive doesn't exist. @@ -278,7 +278,7 @@ class Archive(BaseWrapper): if '_srcpkgs' not in self.__dict__: self._srcpkgs = dict() - def getSourcePackage(self, name, series = None, pocket = 'Release'): + def getSourcePackage(self, name, series=None, pocket='Release'): ''' Returns a SourcePackagePublishingHistory object for the most recent source package in the distribution 'dist', series and @@ -333,7 +333,7 @@ class Archive(BaseWrapper): return self._srcpkgs[(name, series.name, pocket)] def copyPackage(self, source_name, version, from_archive, to_pocket, - to_series = None, include_binaries = False): + to_series=None, include_binaries=False): '''Copy a single named source into this archive. Asynchronously copy a specific version of a named source to the @@ -446,7 +446,7 @@ class MetaPersonTeam(MetaWrapper): except HTTPError, error: if error.response.status == 401: # Anonymous login - cls._me = None + cls._me = None else: raise return cls._me diff --git a/ubuntutools/misc.py b/ubuntutools/misc.py index 94bc8af..ca8a82a 100644 --- a/ubuntutools/misc.py +++ b/ubuntutools/misc.py @@ -25,7 +25,6 @@ # Modules. import locale import os -import os.path import sys import distro_info diff --git a/ubuntutools/test/test_config.py b/ubuntutools/test/test_config.py index 2f4a2ed..cf78a3c 100644 --- a/ubuntutools/test/test_config.py +++ b/ubuntutools/test/test_config.py @@ -16,7 +16,6 @@ import __builtin__ import os -import os.path import sys from StringIO import StringIO From e04d4df8894f5ec8becb143559acb767d2fb9a2d Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 24 Aug 2011 14:46:11 +0200 Subject: [PATCH 31/38] Check the sync blacklist --- syncpackage | 67 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/syncpackage b/syncpackage index ee4225c..74ad824 100755 --- a/syncpackage +++ b/syncpackage @@ -20,15 +20,17 @@ # # ################################################################## -import debian.deb822 -import debian.debian_support +import codecs import optparse import os +import re import shutil import sys +import urllib +import debian.deb822 +import debian.debian_support from devscripts.logger import Logger - from lazr.restfulclient.errors import HTTPError from ubuntutools.archive import (DebianSourcePackage, UbuntuSourcePackage, @@ -380,6 +382,27 @@ def copy(src_pkg, release, simulate=False, force=False): Logger.normal('Request succeeded; you should get an e-mail once it is ' 'processed.') +def is_blacklisted(query): + url = 'http://people.canonical.com/~ubuntu-archive/sync-blacklist.txt' + with codecs.EncodedFile(urllib.urlopen(url), 'UTF-8') as f: + applicable_comments = [] + for line in f: + if not line.strip(): + applicable_comments = [] + continue + m = re.match(r'^\s*([a-z0-9.+-]+)?\s*(?:#\s*(.+)?)?$', line) + source, comment = m.groups() + if source and query == source: + if comment: + applicable_comments.append(comment) + if applicable_comments: + return u'; '.join(applicable_comments) + else: + return True + elif comment: + applicable_comments.append(comment) + return False + def main(): usage = "%prog [options] <.dsc URL/path or package name>" epilog = "See %s(1) for more info." % os.path.basename(sys.argv[0]) @@ -489,30 +512,32 @@ def main(): if args[0].endswith('.dsc'): parser.error('.dsc files can only be synced using --no-lp.') - if options.lpinstance is None: - options.lpinstance = config.get_value('LPINSTANCE') + if options.lpinstance is None: + options.lpinstance = config.get_value('LPINSTANCE') + try: + Launchpad.login(service=options.lpinstance, api_version='devel') + except IOError: + sys.exit(1) - try: - Launchpad.login(service=options.lpinstance, api_version='devel') - except IOError: - sys.exit(1) + if options.release is None: + ubuntu = Launchpad.distributions["ubuntu"] + options.release = ubuntu.current_series.name - src_pkg = fetch_source_pkg(args[0], options.dist, options.debversion, - options.component, options.release, None) + src_pkg = fetch_source_pkg(args[0], options.dist, options.debversion, + options.component, options.release, + options.debian_mirror) + blacklisted = is_blacklisted(src_pkg.source) + if blacklisted: + Logger.error("Source package is blacklisted") + if isinstance(blacklisted, basestring): + Logger.error(u"Reason: %s", blacklisted) + sys.exit(1) + + if options.lp: copy(src_pkg, options.release, options.simulate, options.force) else: - Launchpad.login_anonymously() - if options.release is None: - ubuntu = Launchpad.distributions["ubuntu"] - options.release = ubuntu.current_series.name - os.environ['DEB_VENDOR'] = 'Ubuntu' - - src_pkg = fetch_source_pkg(args[0], options.dist, options.debversion, - options.component, options.release, - options.debian_mirror) - sync_dsc(src_pkg, options.dist, options.release, options.uploader_name, options.uploader_email, options.bugs, options.ubuntu_mirror, options.keyid, options.simulate, options.force) From 1d1f86cb9c4784e57b229cbe37e4eabe71dddea9 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 24 Aug 2011 14:59:22 +0200 Subject: [PATCH 32/38] Docstring --- syncpackage | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/syncpackage b/syncpackage index 74ad824..dafaf81 100755 --- a/syncpackage +++ b/syncpackage @@ -383,6 +383,10 @@ def copy(src_pkg, release, simulate=False, force=False): 'processed.') def is_blacklisted(query): + """"Determine if package "query" is in the sync blacklist + Returns True or a string of all relevant comments if blacklisted, + False if not + """ url = 'http://people.canonical.com/~ubuntu-archive/sync-blacklist.txt' with codecs.EncodedFile(urllib.urlopen(url), 'UTF-8') as f: applicable_comments = [] From 1277344ec8820a8a2ace4583e50863a98ec17868 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 24 Aug 2011 19:52:21 +0200 Subject: [PATCH 33/38] Check the +localpackagediffs blacklist too --- syncpackage | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/syncpackage b/syncpackage index dafaf81..58b8ba6 100755 --- a/syncpackage +++ b/syncpackage @@ -387,6 +387,18 @@ def is_blacklisted(query): Returns True or a string of all relevant comments if blacklisted, False if not """ + # LP: + series = Launchpad.distributions['ubuntu'].current_series + diffs = series.getDifferencesTo(source_package_name_filter=query, + status='Needs attention') + if len(diffs) == 0: + comments = getDifferenceComments(source_package_name=query) + comment = '; '.join(c.body_text for c in comments) + if comment: + return comment + return True + + # Old blacklist: url = 'http://people.canonical.com/~ubuntu-archive/sync-blacklist.txt' with codecs.EncodedFile(urllib.urlopen(url), 'UTF-8') as f: applicable_comments = [] From 76fabbe0baa1c6016b6ce1f9c41583d3a88d5e77 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 24 Aug 2011 19:54:02 +0200 Subject: [PATCH 34/38] Add blacklisting explanation --- syncpackage | 3 +++ 1 file changed, 3 insertions(+) diff --git a/syncpackage b/syncpackage index 58b8ba6..c00d1a9 100755 --- a/syncpackage +++ b/syncpackage @@ -548,6 +548,9 @@ def main(): Logger.error("Source package is blacklisted") if isinstance(blacklisted, basestring): Logger.error(u"Reason: %s", blacklisted) + Logger.error("If you think this package shouldn't be blacklisted, " + "please file a bug explaining your reasoning and " + "subscribe ~ubuntu-archive.") sys.exit(1) if options.lp: From 95e5437f44382345660144c0379a94fc1a04a332 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 24 Aug 2011 23:52:45 +0200 Subject: [PATCH 35/38] Note on LP bug to improve getDifferencesTo() --- syncpackage | 1 + 1 file changed, 1 insertion(+) diff --git a/syncpackage b/syncpackage index c00d1a9..491c210 100755 --- a/syncpackage +++ b/syncpackage @@ -388,6 +388,7 @@ def is_blacklisted(query): False if not """ # LP: + # TODO: Refactor when LP: #833080 is fixed series = Launchpad.distributions['ubuntu'].current_series diffs = series.getDifferencesTo(source_package_name_filter=query, status='Needs attention') From 91c70189fd07f878496242c4ea575019cfe99f98 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Thu, 25 Aug 2011 14:29:36 +0200 Subject: [PATCH 36/38] getDifferenceComments is a method on series --- syncpackage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncpackage b/syncpackage index 491c210..3c7e8ba 100755 --- a/syncpackage +++ b/syncpackage @@ -393,7 +393,7 @@ def is_blacklisted(query): diffs = series.getDifferencesTo(source_package_name_filter=query, status='Needs attention') if len(diffs) == 0: - comments = getDifferenceComments(source_package_name=query) + comments = series.getDifferenceComments(source_package_name=query) comment = '; '.join(c.body_text for c in comments) if comment: return comment From 497177760b1de7d3a357176734e3b1b557523590 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Thu, 25 Aug 2011 14:30:30 +0200 Subject: [PATCH 37/38] Allow --force ing a blacklist override, when doing a non-native sync --- syncpackage | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/syncpackage b/syncpackage index 3c7e8ba..1624c5d 100755 --- a/syncpackage +++ b/syncpackage @@ -469,7 +469,8 @@ def main(): "upload.") parser.add_option("-f", "--force", dest="force", action="store_true", default=False, - help="Force sync over the top of Ubuntu changes.") + help="Force sync over the top of Ubuntu changes " + "or a fake-sync when blacklisted.") parser.add_option('-D', '--debian-mirror', metavar='DEBIAN_MIRROR', dest='debian_mirror', help='Preferred Debian mirror ' @@ -552,7 +553,12 @@ def main(): Logger.error("If you think this package shouldn't be blacklisted, " "please file a bug explaining your reasoning and " "subscribe ~ubuntu-archive.") - sys.exit(1) + if options.force and not options.lp: + Logger.warning(u"Forcing fake-sync, overriding blacklist") + else: + Logger.error("--force and --no-lp are required to override the " + "blacklist, if this package needs a fakesync") + sys.exit(1) if options.lp: copy(src_pkg, options.release, options.simulate, options.force) From dbda709ce35ea7139a00e20a7f2400c350c15fe5 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Thu, 25 Aug 2011 14:32:07 +0200 Subject: [PATCH 38/38] Update manpage --- doc/syncpackage.1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/syncpackage.1 b/doc/syncpackage.1 index 009f654..fe0de27 100644 --- a/doc/syncpackage.1 +++ b/doc/syncpackage.1 @@ -72,6 +72,9 @@ Mark a Launchpad bug as being fixed by this upload. .TP \fB\-f\fR, \fB\-\-force\fR Force sync over the top of Ubuntu changes. +If a sync is blacklisted because of an .orig.tar mismatch, +\fB\-\-force\fR can be used to override the blacklist, when doing a +local sync (\fB\-\-no\-lp\fR). .TP .B \-d \fIDEBIAN_MIRROR\fR, \fB\-\-debian\-mirror\fR=\fIDEBIAN_MIRROR\fR Use the specified mirror.