~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/soyuz/scripts/packagecopier.py

  • Committer: Francis J. Lacoste
  • Date: 2011-04-27 21:40:03 UTC
  • mto: This revision was merged to the branch mainline in revision 12971.
  • Revision ID: francis.lacoste@canonical.com-20110427214003-iiqhcyyswppyqjsx
Change the default timeout to production value, improved options documentation and use only one bin above timeout value.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
 
1
# Copyright 2009 Canonical Ltd.  This software is licensed under the
2
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
3
 
4
4
"""PackageCopier utilities."""
9
9
    'PackageCopier',
10
10
    'UnembargoSecurityPackage',
11
11
    'CopyChecker',
12
 
    'check_copy_permissions',
13
12
    'do_copy',
14
13
    '_do_delayed_copy',
15
14
    '_do_direct_copy',
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 (
34
 
    ArchivePurpose,
35
 
    SourcePackageFormat,
 
31
from lp.soyuz.enums import ArchivePurpose
 
32
from lp.soyuz.interfaces.archive import (
 
33
    CannotCopy,
36
34
    )
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,
48
45
    IPackageUploadSet,
49
46
    )
 
47
from lp.soyuz.enums import SourcePackageFormat
50
48
from lp.soyuz.scripts.ftpmasterbase import (
51
49
    SoyuzScript,
52
50
    SoyuzScriptError,
53
51
    )
54
52
from lp.soyuz.scripts.processaccepted import close_bugs_for_sourcepublication
55
53
 
56
 
 
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):
87
84
 
88
85
    return new_lfa
89
86
 
90
 
 
91
87
# XXX cprov 2009-06-12: this function should be incorporated in
92
88
# IPublishing.
93
89
def update_files_privacy(pub_record):
197
193
            return {'status': BuildSetStatus.NEEDSBUILD}
198
194
 
199
195
 
200
 
def check_copy_permissions(person, archive, series, pocket,
201
 
                           sourcepackagenames):
202
 
    """Check that `person` has permission to copy a package.
203
 
 
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.
211
 
    """
212
 
    if person is None:
213
 
        raise CannotCopy("Cannot check copy permissions (no requester).")
214
 
 
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
222
 
 
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)
230
 
 
231
 
        if reason is not None:
232
 
            raise CannotCopy(reason)
233
 
 
234
 
 
235
196
class CopyChecker:
236
197
    """Check copy candiates.
237
198
 
238
199
    Allows the checker function to identify conflicting copy candidates
239
200
    within the copying batch.
240
201
    """
241
 
    def __init__(self, archive, include_binaries, allow_delayed_copies=True,
242
 
                 strict_binaries=True):
243
 
        """Initialize a copy checker.
244
 
 
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
248
 
            with the source.
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
253
 
            copied.
254
 
        """
 
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 = {}
260
207
 
427
374
                        "%s already exists in destination archive with "
428
375
                        "different contents." % lf.libraryfile.filename)
429
376
 
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.
433
379
 
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).
440
386
 
441
 
        If person is not None, check that this person has upload rights to
442
 
        the destination (archive, component, pocket).
443
 
 
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.
450
390
 
451
391
        :raise CannotCopy when a copy is not allowed to be performed
452
392
            containing the reason of the error.
453
393
        """
454
 
        if check_permissions:
455
 
            check_copy_permissions(
456
 
                person, self.archive, series, pocket,
457
 
                [source.sourcepackagerelease.sourcepackagename])
458
 
 
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')
477
412
 
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")
524
459
 
525
460
 
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.
530
464
 
531
465
    Verifies if each copy can be performed using `CopyChecker` and
536
470
 
537
471
    Wrapper for `do_direct_copy`.
538
472
 
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.
562
484
 
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.
570
492
    copies = []
571
493
    errors = []
572
494
    copy_checker = CopyChecker(
573
 
        archive, include_binaries, allow_delayed_copies,
574
 
        strict_binaries=strict_binaries)
 
495
        archive, include_binaries, allow_delayed_copies)
575
496
 
576
497
    for source in sources:
577
498
        if series is None:
579
500
        else:
580
501
            destination_series = series
581
502
        try:
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))
586
506
            continue
588
508
    if len(errors) != 0:
589
509
        raise CannotCopy("\n".join(errors))
590
510
 
591
 
    overrides_index = 0
592
511
    for source in copy_checker.getCheckedCopies():
593
512
        if series is None:
594
513
            destination_series = source.distroseries
596
515
            destination_series = series
597
516
        if source.delayed:
598
517
            delayed_copy = _do_delayed_copy(
599
 
                source, archive, destination_series, pocket,
600
 
                include_binaries)
 
518
                source, archive, destination_series, pocket, include_binaries)
601
519
            sub_copies = [delayed_copy]
602
520
        else:
603
 
            override = None
604
 
            if overrides:
605
 
                override = overrides[overrides_index]
606
521
            sub_copies = _do_direct_copy(
607
 
                source, archive, destination_series, pocket,
608
 
                include_binaries, override)
609
 
            if send_email:
610
 
                notify(
611
 
                    person, source.sourcepackagerelease, [], [], archive,
612
 
                    destination_series, pocket, changes=None,
613
 
                    action='accepted')
 
522
                source, archive, destination_series, pocket, include_binaries)
614
523
 
615
 
        overrides_index += 1
616
524
        copies.extend(sub_copies)
617
525
 
618
526
    return copies
619
527
 
620
528
 
621
 
def _do_direct_copy(source, archive, series, pocket, include_binaries,
622
 
                    override=None):
 
529
def _do_direct_copy(source, archive, series, pocket, include_binaries):
623
530
    """Copy publishing records to another location.
624
531
 
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.
631
538
 
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().
641
547
 
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)
672
564
    else:
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)
686
578
 
687
 
    if binary_copies is not None:
688
 
        copies.extend(binary_copies)
 
579
    copies.extend(binary_copies)
689
580
 
690
581
    # Always ensure the needed builds exist in the copy destination
691
582
    # after copying the binaries.
717
608
 
718
609
    Also include published builds for each source if requested to.
719
610
 
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.
727
618
 
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))
894
784
            return []