~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/archiveuploader/uploadpolicy.py

  • Committer: Julian Edwards
  • Date: 2010-08-26 15:28:34 UTC
  • mfrom: (11450 launchpad)
  • mto: This revision was merged to the branch mainline in revision 11453.
  • Revision ID: julian.edwards@canonical.com-20100826152834-p16tp6o6v2qg3hgu
merge devel

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 
8
8
__all__ = [
9
9
    "AbstractUploadPolicy",
 
10
    "ArchiveUploadType",
10
11
    "BuildDaemonUploadPolicy",
11
12
    "findPolicyByName",
12
13
    "IArchiveUploadPolicy",
14
15
    "UploadPolicyError",
15
16
    ]
16
17
 
 
18
from textwrap import dedent
 
19
 
17
20
from zope.component import (
18
21
    getGlobalSiteManager,
19
22
    getUtility,
28
31
from lp.registry.interfaces.pocket import PackagePublishingPocket
29
32
from lp.registry.interfaces.series import SeriesStatus
30
33
 
 
34
from lazr.enum import EnumeratedType, Item
 
35
 
 
36
 
31
37
# Defined here so that uploadpolicy.py doesn't depend on lp.code.
32
38
SOURCE_PACKAGE_RECIPE_UPLOAD_POLICY_NAME = 'recipe'
33
39
# Number of seconds in an hour (used later)
52
58
    """
53
59
 
54
60
 
 
61
class ArchiveUploadType(EnumeratedType):
 
62
 
 
63
    SOURCE_ONLY = Item("Source only")
 
64
    BINARY_ONLY = Item("Binary only")
 
65
    MIXED_ONLY = Item("Mixed only")
 
66
 
 
67
 
55
68
class AbstractUploadPolicy:
56
69
    """Encapsulate the policy of an upload to a launchpad archive.
57
70
 
63
76
    """
64
77
    implements(IArchiveUploadPolicy)
65
78
 
 
79
    name = 'abstract'
66
80
    options = None
67
 
    name = 'abstract'
 
81
    accepted_type = None # Must be defined in subclasses.
68
82
 
69
83
    def __init__(self):
70
84
        """Prepare a policy..."""
75
89
        self.unsigned_changes_ok = False
76
90
        self.unsigned_dsc_ok = False
77
91
        self.create_people = True
78
 
        self.can_upload_source = True
79
 
        self.can_upload_binaries = True
80
 
        self.can_upload_mixed = True
81
92
        # future_time_grace is in seconds. 28800 is 8 hours
82
93
        self.future_time_grace = 8 * HOURS
83
94
        # The earliest year we accept in a deb's file's mtime
84
95
        self.earliest_year = 1984
85
96
 
 
97
    def validateUploadType(self, upload):
 
98
        """Check that the type of the given upload is accepted by this policy.
 
99
 
 
100
        When the type (e.g. sourceful, binaryful or mixed) is not accepted,
 
101
        the upload is rejected.
 
102
        """
 
103
        if upload.sourceful and upload.binaryful:
 
104
            if self.accepted_type != ArchiveUploadType.MIXED_ONLY:
 
105
                upload.reject(
 
106
                    "Source/binary (i.e. mixed) uploads are not allowed.")
 
107
 
 
108
        elif upload.sourceful:
 
109
            if self.accepted_type != ArchiveUploadType.SOURCE_ONLY:
 
110
                upload.reject(
 
111
                    "Sourceful uploads are not accepted by this policy.")
 
112
 
 
113
        elif upload.binaryful:
 
114
            if self.accepted_type != ArchiveUploadType.BINARY_ONLY:
 
115
                message = dedent("""
 
116
                    Upload rejected because it contains binary packages.
 
117
                    Ensure you are using `debuild -S`, or an equivalent
 
118
                    command, to generate only the source package before
 
119
                    re-uploading.""")
 
120
 
 
121
                if upload.is_ppa:
 
122
                    message += dedent("""
 
123
                        See https://help.launchpad.net/Packaging/PPA for
 
124
                        more information.""")
 
125
                upload.reject(message)
 
126
 
 
127
        else:
 
128
            raise AssertionError(
 
129
                "Upload is not sourceful, binaryful or mixed.")
 
130
 
86
131
    def getUploader(self, changes):
87
132
        """Get the person who is doing the uploading."""
88
133
        return changes.signer
171
216
    """The insecure upload policy is used by the poppy interface."""
172
217
 
173
218
    name = 'insecure'
174
 
 
175
 
    def __init__(self):
176
 
        AbstractUploadPolicy.__init__(self)
177
 
        self.can_upload_binaries = False
178
 
        self.can_upload_mixed = False
 
219
    accepted_type = ArchiveUploadType.SOURCE_ONLY
179
220
 
180
221
    def rejectPPAUploads(self, upload):
181
222
        """Insecure policy allows PPA upload."""
283
324
    """The build daemon upload policy is invoked by the slave scanner."""
284
325
 
285
326
    name = 'buildd'
 
327
    accepted_type = ArchiveUploadType.BINARY_ONLY
286
328
 
287
329
    def __init__(self):
288
330
        super(BuildDaemonUploadPolicy, self).__init__()
289
331
        # We permit unsigned uploads because we trust our build daemons
290
332
        self.unsigned_changes_ok = True
291
333
        self.unsigned_dsc_ok = True
292
 
        self.can_upload_source = False
293
 
        self.can_upload_mixed = False
294
334
 
295
335
    def setOptions(self, options):
296
336
        AbstractUploadPolicy.setOptions(self, options)
314
354
    """This policy is invoked when processing sync uploads."""
315
355
 
316
356
    name = 'sync'
 
357
    accepted_type = ArchiveUploadType.SOURCE_ONLY
317
358
 
318
359
    def __init__(self):
319
360
        AbstractUploadPolicy.__init__(self)
320
361
        # We don't require changes or dsc to be signed for syncs
321
362
        self.unsigned_changes_ok = True
322
363
        self.unsigned_dsc_ok = True
323
 
        # We don't want binaries in a sync
324
 
        self.can_upload_mixed = False
325
 
        self.can_upload_binaries = False
326
364
 
327
365
    def policySpecificChecks(self, upload):
328
366
        """Perform sync specific checks."""
331
369
        pass
332
370
 
333
371
 
334
 
class SecurityUploadPolicy(AbstractUploadPolicy):
335
 
    """The security-upload policy.
336
 
 
337
 
    It allows unsigned changes and binary uploads.
338
 
    """
339
 
 
340
 
    name = 'security'
341
 
 
342
 
    def __init__(self):
343
 
        AbstractUploadPolicy.__init__(self)
344
 
        self.unsigned_dsc_ok = True
345
 
        self.unsigned_changes_ok = True
346
 
        self.can_upload_mixed = True
347
 
        self.can_upload_binaries = True
348
 
 
349
 
    def policySpecificChecks(self, upload):
350
 
        """Deny uploads to any pocket other than the security pocket."""
351
 
        if self.pocket != PackagePublishingPocket.SECURITY:
352
 
            upload.reject(
353
 
                "Not permitted to do security upload to non SECURITY pocket")
354
 
 
355
 
 
356
372
def findPolicyByName(policy_name):
357
373
    """Return a new policy instance for the given policy name."""
358
374
    return getUtility(IArchiveUploadPolicy, policy_name)()
362
378
    policies = [
363
379
        BuildDaemonUploadPolicy,
364
380
        InsecureUploadPolicy,
365
 
        SyncUploadPolicy, 
366
 
        SecurityUploadPolicy]
 
381
        SyncUploadPolicy]
367
382
    sm = getGlobalSiteManager()
368
383
    for policy in policies:
369
384
        sm.registerUtility(