You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
9.8 KiB

#! /usr/bin/python3
# Copyright (C) 2012 Canonical Ltd.
# Author: Colin Watson <cjwatson@ubuntu.com>
# 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 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Copy package publication records."""
from __future__ import print_function
import argparse
import sys
from launchpadlib.errors import HTTPError
from launchpadlib.launchpad import Launchpad
try:
from ubuntutools.question import YesNoQuestion
except ImportError:
print("No ubuntutools installed: sudo apt-get install ubuntu-dev-tools")
exit()
import lputils
def find_publications(args, package):
source = lputils.find_latest_published_source(args, package)
yield source, source.source_package_version
if args.include_binaries:
for binary in source.getPublishedBinaries():
yield binary, binary.binary_package_version
def copy_packages(args):
ret = True
for package in args.packages:
print("Copy candidates:")
try:
source = lputils.find_latest_published_source(args, package)
except lputils.PackageMissing as error:
print(error)
if args.skip_missing:
print('Skipping')
continue
else:
# Bail with exit code non-zero.
return False
print("\t%s" % source.display_name)
num_copies = 1
if args.include_binaries:
for binary in source.getPublishedBinaries():
print("\t%s" % binary.display_name)
num_copies += 1
print("Candidate copy target: %s" % args.destination.archive)
if args.sponsoree:
print("Sponsored for: %s" % args.sponsoree)
if args.dry_run:
print("Dry run; no packages copied.")
else:
if not args.confirm_all:
if YesNoQuestion().ask("Copy", "no") == "no":
continue
try:
args.destination.archive.copyPackage(
source_name=package, version=source.source_package_version,
from_archive=args.archive,
from_series=args.series.name,
from_pocket=args.pocket,
to_series=args.destination.series.name,
to_pocket=args.destination.pocket,
include_binaries=args.include_binaries,
unembargo=args.unembargo,
auto_approve=args.auto_approve,
silent=args.silent,
sponsored=args.sponsoree)
print("%d %s requested." % (
num_copies, "copy" if num_copies == 1 else "copies"))
except HTTPError as e:
print(e.content, file=sys.stderr)
ret = False
return ret
def main():
parser = argparse.ArgumentParser(
epilog=lputils.ARCHIVE_REFERENCE_DESCRIPTION)
parser.add_argument(
"-l", "--launchpad", dest="launchpad_instance", default="production")
parser.add_argument(
"-n", "--dry-run", default=False, action="store_true",
help="only show copies that would be performed")
parser.add_argument(
"-y", "--confirm-all", default=False, action="store_true",
help="do not ask for confirmation")
parser.add_argument(
"--from", metavar="ARCHIVE", dest="archive",
help="copy from ARCHIVE (default: ubuntu)")
parser.add_argument(
"-s", "--suite", "--from-suite", metavar="SUITE",
help="copy from SUITE (default: development release pocket)")
parser.add_argument(
"--to", metavar="ARCHIVE",
help="copy to ARCHIVE (default: copy from archive)")
parser.add_argument(
"--to-suite", metavar="SUITE",
help="copy to SUITE (default: copy from suite)")
parser.add_argument(
"-e", "--version",
metavar="VERSION", help="package version (default: current version)")
parser.add_argument(
"-b", "--include-binaries", default=False, action="store_true",
help="copy related binaries")
parser.add_argument(
"--unembargo", default=False, action="store_true",
help="allow copying from a private archive to a public archive")
parser.add_argument(
"--auto-approve", default=False, action="store_true",
help="automatically approve copy (requires queue admin permissions)")
parser.add_argument(
"--silent", default=False, action="store_true",
help="suppress mail notifications (requires queue admin permissions)")
parser.add_argument(
"--force-same-destination", default=False, action="store_true",
help=(
"force copy when source == destination (e.g. when reverting to "
"a previous version in the same suite)"))
parser.add_argument(
"--skip-missing", default=False, action="store_true",
help=(
"When a package cannot be copied, normally this script exits "
"with a non-zero status. With --skip-missing instead, the "
"error is printed and copying continues"))
parser.add_argument(
"--sponsor", metavar="USERNAME", dest="sponsoree", default=None,
help="Sponsor the sync for USERNAME (a Launchpad username).")
# Deprecated in favour of --to and --from.
parser.add_argument(
"-d", "--distribution", default="ubuntu", help=argparse.SUPPRESS)
parser.add_argument("-p", "--ppa", help=argparse.SUPPRESS)
parser.add_argument("--ppa-name", help=argparse.SUPPRESS)
parser.add_argument(
"-j", "--partner", default=False, action="store_true",
help=argparse.SUPPRESS)
parser.add_argument(
"--to-primary", default=False, action="store_true",
help=argparse.SUPPRESS)
parser.add_argument("--to-distribution", help=argparse.SUPPRESS)
parser.add_argument("--to-ppa", help=argparse.SUPPRESS)
parser.add_argument("--to-ppa-name", help=argparse.SUPPRESS)
parser.add_argument(
"--to-partner", default=False, action="store_true",
help=argparse.SUPPRESS)
parser.add_argument(
"packages", metavar="package", nargs="+",
help="name of package to copy")
args = parser.parse_args()
args.launchpad = Launchpad.login_with(
"copy-package", args.launchpad_instance, version="devel")
args.destination = argparse.Namespace()
args.destination.launchpad = args.launchpad
args.destination.suite = args.to_suite or args.suite
if args.archive or args.to:
# Use modern single-option archive references.
if ((args.distribution and args.distribution != u'ubuntu') or
args.ppa or args.ppa_name or args.partner or
args.to_distribution or args.to_ppa or
args.to_ppa_name or args.to_partner):
parser.error(
"cannot use --to/--from and the deprecated archive selection "
"options together")
args.destination.archive = args.to or args.archive
else:
# Use the deprecated four-option archive specifiers.
if args.ppa and args.partner:
parser.error(
"cannot copy from partner archive and PPA simultaneously")
if args.to_ppa and args.to_partner:
parser.error(
"cannot copy to partner archive and PPA simultaneously")
args.destination.distribution = (
args.to_distribution or args.distribution)
args.destination.ppa = args.to_ppa
args.destination.ppa_name = args.to_ppa_name
args.destination.partner = args.to_partner
# In cases where source is specified, but destination is not,
# default to destination = source
if (args.ppa is not None and args.to_ppa is None and
not args.to_primary and not args.destination.partner):
args.destination.ppa = args.ppa
if (args.ppa_name is not None and args.to_ppa_name is None and
args.destination.ppa is not None):
args.destination.ppa_name = args.ppa_name
if (args.partner and not args.destination.partner and
not args.ppa):
args.destination.partner = args.partner
if args.to_primary and args.to_ppa_name is not None:
parser.error(
"--to-ppa-name option set for copy to primary archive")
lputils.setup_location(args)
lputils.setup_location(args.destination)
if args.archive.private and not args.destination.archive.private:
if not args.unembargo:
parser.error(
"copying from a private archive to a public archive requires "
"the --unembargo option")
# TODO some equivalent of canModifySuite check?
if (not args.force_same_destination and
args.distribution == args.destination.distribution and
args.suite == args.destination.suite and
args.pocket == args.destination.pocket and
args.archive.reference == args.destination.archive.reference):
parser.error("copy destination must differ from source")
if args.sponsoree:
try:
args.sponsoree = args.launchpad.people[args.sponsoree]
except KeyError:
parser.error(
"Person to sponsor for not found: %s" % args.sponsoree)
if copy_packages(args):
return 0
else:
return 1
if __name__ == '__main__':
sys.exit(main())