28
27
from canonical.librarian.utils import copy_and_close
29
28
from lp.app.errors import NotFoundError
30
29
from lp.buildmaster.enums import BuildStatus
31
from lp.soyuz.adapters.notification import notify
32
30
from lp.soyuz.adapters.packagelocation import build_package_location
33
from lp.soyuz.enums import (
31
from lp.soyuz.enums import ArchivePurpose
32
from lp.soyuz.interfaces.archive import (
37
from lp.soyuz.interfaces.archive import CannotCopy
38
35
from lp.soyuz.interfaces.binarypackagebuild import BuildSetStatus
39
36
from lp.soyuz.interfaces.publishing import (
40
37
active_publishing_status,
47
44
IPackageUploadCustom,
47
from lp.soyuz.enums import SourcePackageFormat
50
48
from lp.soyuz.scripts.ftpmasterbase import (
54
52
from lp.soyuz.scripts.processaccepted import close_bugs_for_sourcepublication
57
54
# XXX cprov 2009-06-12: This function could be incorporated in ILFA,
58
55
# I just don't see a clear benefit in doing that right now.
59
56
def re_upload_file(libraryfile, restricted=False):
197
193
return {'status': BuildSetStatus.NEEDSBUILD}
200
def check_copy_permissions(person, archive, series, pocket,
202
"""Check that `person` has permission to copy a package.
204
:param person: User attempting the upload.
205
:param archive: Destination `Archive`.
206
:param series: Destination `DistroSeries`.
207
:param pocket: Destination `Pocket`.
208
:param sourcepackagenames: Sequence of `SourcePackageName`s for the
209
packages to be copied.
210
:raises CannotCopy: If the copy is not allowed.
213
raise CannotCopy("Cannot check copy permissions (no requester).")
215
# If there is a requester, check that he has upload permission into
216
# the destination (archive, component, pocket). This check is done
217
# here rather than in the security adapter because it requires more
218
# info than is available in the security adapter.
219
for spn in set(sourcepackagenames):
220
package = series.getSourcePackage(spn)
221
destination_component = package.latest_published_component
223
# If destination_component is not None, make sure the person
224
# has upload permission for this component. Otherwise, any
225
# upload permission on this archive will do.
226
strict_component = destination_component is not None
227
reason = archive.checkUpload(
228
person, series, spn, destination_component, pocket,
229
strict_component=strict_component)
231
if reason is not None:
232
raise CannotCopy(reason)
235
196
class CopyChecker:
236
197
"""Check copy candiates.
238
199
Allows the checker function to identify conflicting copy candidates
239
200
within the copying batch.
241
def __init__(self, archive, include_binaries, allow_delayed_copies=True,
242
strict_binaries=True):
243
"""Initialize a copy checker.
245
:param archive: the target `IArchive`.
246
:param include_binaries: controls whether or not the published
247
binaries for each given source should be also copied along
249
:param allow_delayed_copies: boolean indicating whether or not private
250
sources can be copied to public archives using delayed_copies.
251
:param strict_binaries: If 'include_binaries' is True then setting
252
this to True will make the copy fail if binaries cannot be also
202
def __init__(self, archive, include_binaries, allow_delayed_copies=True):
255
203
self.archive = archive
256
204
self.include_binaries = include_binaries
257
self.strict_binaries = strict_binaries
258
205
self.allow_delayed_copies = allow_delayed_copies
259
206
self._inventory = {}
427
374
"%s already exists in destination archive with "
428
375
"different contents." % lf.libraryfile.filename)
430
def checkCopy(self, source, series, pocket, person=None,
431
check_permissions=True):
377
def checkCopy(self, source, series, pocket):
432
378
"""Check if the source can be copied to the given location.
434
380
Check possible conflicting publications in the destination archive.
438
384
higher than any version of the same source present in the
439
385
destination suite (series + pocket).
441
If person is not None, check that this person has upload rights to
442
the destination (archive, component, pocket).
444
387
:param source: copy candidate, `ISourcePackagePublishingHistory`.
445
388
:param series: destination `IDistroSeries`.
446
389
:param pocket: destination `PackagePublishingPocket`.
447
:param person: requester `IPerson`.
448
:param check_permissions: boolean indicating whether or not the
449
requester's permissions to copy should be checked.
451
391
:raise CannotCopy when a copy is not allowed to be performed
452
392
containing the reason of the error.
454
if check_permissions:
455
check_copy_permissions(
456
person, self.archive, series, pocket,
457
[source.sourcepackagerelease.sourcepackagename])
459
394
if series not in self.archive.distribution.series:
460
395
raise CannotCopy(
461
396
"No such distro series %s in distribution %s." %
475
410
if source_file.libraryfile.expires is not None:
476
411
raise CannotCopy('source contains expired files')
478
if self.include_binaries and self.strict_binaries:
413
if self.include_binaries:
479
414
built_binaries = source.getBuiltBinaries(want_files=True)
480
415
if len(built_binaries) == 0:
481
416
raise CannotCopy("source has no binaries to be copied")
526
461
def do_copy(sources, archive, series, pocket, include_binaries=False,
527
allow_delayed_copies=True, person=None, check_permissions=True,
528
overrides=None, send_email=False, strict_binaries=True):
462
allow_delayed_copies=True):
529
463
"""Perform the complete copy of the given sources incrementally.
531
465
Verifies if each copy can be performed using `CopyChecker` and
537
471
Wrapper for `do_direct_copy`.
539
:param sources: a list of `ISourcePackagePublishingHistory`.
540
:param archive: the target `IArchive`.
541
:param series: the target `IDistroSeries`, if None is given the same
473
:param: sources: a list of `ISourcePackagePublishingHistory`.
474
:param: archive: the target `IArchive`.
475
:param: series: the target `IDistroSeries`, if None is given the same
542
476
current source distroseries will be used as destination.
543
:param pocket: the target `PackagePublishingPocket`.
544
:param include_binaries: optional boolean, controls whether or
477
:param: pocket: the target `PackagePublishingPocket`.
478
:param: include_binaries: optional boolean, controls whether or
545
479
not the published binaries for each given source should be also
546
480
copied along with the source.
547
481
:param allow_delayed_copies: boolean indicating whether or not private
548
482
sources can be copied to public archives using delayed_copies.
549
483
Defaults to True, only set as False in the UnembargoPackage context.
550
:param person: the requester `IPerson`.
551
:param check_permissions: boolean indicating whether or not the
552
requester's permissions to copy should be checked.
553
:param overrides: A list of `IOverride` as returned from one of the copy
554
policies which will be used as a manual override insyead of using the
555
default override returned by IArchive.getOverridePolicy(). There
556
must be the same number of overrides as there are sources and each
557
override must be for the corresponding source in the sources list.
558
Overrides will be ignored for delayed copies.
559
:param send_email: Should we notify for the copy performed?
560
:param strict_binaries: If 'include_binaries' is True then setting this
561
to True will make the copy fail if binaries cannot be also copied.
563
485
:raise CannotCopy when one or more copies were not allowed. The error
564
486
will contain the reason why each copy was denied.
580
501
destination_series = series
582
copy_checker.checkCopy(
583
source, destination_series, pocket, person, check_permissions)
503
copy_checker.checkCopy(source, destination_series, pocket)
584
504
except CannotCopy, reason:
585
505
errors.append("%s (%s)" % (source.displayname, reason))
596
515
destination_series = series
597
516
if source.delayed:
598
517
delayed_copy = _do_delayed_copy(
599
source, archive, destination_series, pocket,
518
source, archive, destination_series, pocket, include_binaries)
601
519
sub_copies = [delayed_copy]
605
override = overrides[overrides_index]
606
521
sub_copies = _do_direct_copy(
607
source, archive, destination_series, pocket,
608
include_binaries, override)
611
person, source.sourcepackagerelease, [], [], archive,
612
destination_series, pocket, changes=None,
522
source, archive, destination_series, pocket, include_binaries)
616
524
copies.extend(sub_copies)
621
def _do_direct_copy(source, archive, series, pocket, include_binaries,
529
def _do_direct_copy(source, archive, series, pocket, include_binaries):
623
530
"""Copy publishing records to another location.
625
532
Copy each item of the given list of `SourcePackagePublishingHistory`
629
536
Also copy published binaries for each source if requested to. Again,
630
537
only copy binaries that were not yet copied before.
632
:param source: an `ISourcePackagePublishingHistory`.
633
:param archive: the target `IArchive`.
634
:param series: the target `IDistroSeries`, if None is given the same
539
:param: source: an `ISourcePackagePublishingHistory`.
540
:param: archive: the target `IArchive`.
541
:param: series: the target `IDistroSeries`, if None is given the same
635
542
current source distroseries will be used as destination.
636
:param pocket: the target `PackagePublishingPocket`.
637
:param include_binaries: optional boolean, controls whether or
543
:param: pocket: the target `PackagePublishingPocket`.
544
:param: include_binaries: optional boolean, controls whether or
638
545
not the published binaries for each given source should be also
639
546
copied along with the source.
640
:param override: An `IOverride` as per do_copy().
642
548
:return: a list of `ISourcePackagePublishingHistory` and
643
549
`BinaryPackagePublishingHistory` corresponding to the copied
651
557
version=source.sourcepackagerelease.version,
652
558
status=active_publishing_status,
653
559
distroseries=series, pocket=pocket)
654
policy = archive.getOverridePolicy()
655
560
if source_in_destination.is_empty():
656
# If no manual overrides were specified and the archive has an
657
# override policy then use that policy to get overrides.
658
if override is None and policy is not None:
659
package_names = (source.sourcepackagerelease.sourcepackagename,)
660
# Only one override can be returned so take the first
661
# element of the returned list.
662
overrides = policy.calculateSourceOverrides(
663
archive, series, pocket, package_names)
664
# Only one override can be returned so take the first
665
# element of the returned list.
666
assert len(overrides) == 1, (
667
"More than one override encountered, something is wrong.")
668
override = overrides[0]
669
source_copy = source.copyTo(series, pocket, archive, override)
561
source_copy = source.copyTo(series, pocket, archive)
670
562
close_bugs_for_sourcepublication(source_copy)
671
563
copies.append(source_copy)
682
574
# irrelevant arch-indep publications) and IBPPH.copy is prepared
683
575
# to expand arch-indep publications.
684
576
binary_copies = getUtility(IPublishingSet).copyBinariesTo(
685
source.getBuiltBinaries(), series, pocket, archive, policy=policy)
577
source.getBuiltBinaries(), series, pocket, archive)
687
if binary_copies is not None:
688
copies.extend(binary_copies)
579
copies.extend(binary_copies)
690
581
# Always ensure the needed builds exist in the copy destination
691
582
# after copying the binaries.
718
609
Also include published builds for each source if requested to.
720
:param source: an `ISourcePackagePublishingHistory`.
721
:param archive: the target `IArchive`.
722
:param series: the target `IDistroSeries`.
723
:param pocket: the target `PackagePublishingPocket`.
724
:param include_binaries: optional boolean, controls whether or
611
:param: source: an `ISourcePackagePublishingHistory`.
612
:param: archive: the target `IArchive`.
613
:param: series: the target `IDistroSeries`.
614
:param: pocket: the target `PackagePublishingPocket`.
615
:param: include_binaries: optional boolean, controls whether or
725
616
not the published binaries for each given source should be also
726
617
copied along with the source.
887
778
copies = do_copy(
888
779
sources, self.destination.archive,
889
780
self.destination.distroseries, self.destination.pocket,
890
self.options.include_binaries, self.allow_delayed_copies,
891
check_permissions=False)
781
self.options.include_binaries, self.allow_delayed_copies)
892
782
except CannotCopy, error:
893
783
self.logger.error(str(error))