Merge lp:~wgrant/launchpad/distroseries-source-format-selection into lp:launchpad/db-devel

Proposed by William Grant
Status: Merged
Merge reported by: William Grant
Merged at revision: not available
Proposed branch: lp:~wgrant/launchpad/distroseries-source-format-selection
Merge into: lp:launchpad/db-devel
Diff against target: 1205 lines (+727/-96)
20 files modified
lib/lp/archiveuploader/dscfile.py (+144/-58)
lib/lp/archiveuploader/nascentuploadfile.py (+8/-4)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1.dsc (+10/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1_source.changes (+20/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.dsc (+9/-3)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1_source.changes (+12/-6)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2.dsc (+22/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2_source.changes (+25/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0.dsc (+13/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0_source.changes (+25/-0)
lib/lp/archiveuploader/tests/nascentuploadfile.txt (+172/-0)
lib/lp/archiveuploader/tests/test_ppauploadprocessor.py (+47/-0)
lib/lp/archiveuploader/tests/test_uploadprocessor.py (+119/-0)
lib/lp/archiveuploader/tests/test_utils.py (+46/-12)
lib/lp/archiveuploader/uploadpolicy.py (+4/-0)
lib/lp/archiveuploader/utils.py (+13/-6)
lib/lp/registry/interfaces/sourcepackage.py (+19/-1)
lib/lp/soyuz/interfaces/files.py (+6/-1)
lib/lp/soyuz/model/files.py (+12/-2)
lib/lp/soyuz/model/queue.py (+1/-3)
To merge this branch: bzr merge lp:~wgrant/launchpad/distroseries-source-format-selection
Reviewer Review Type Date Requested Status
Julian Edwards (community) code Approve
Review via email: mp+14977@code.launchpad.net
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) wrote :

This is hopefully the last of my Debian source format 3.0 branches. It is a pretty simple extension and testing of existing code.

The two new formats are:

 - 3.0 (native): Like 1.0's native variant, but with bz2 compression permitted on the tarball.
 - 3.0 (quilt): Replaces 1.0's non-native variant. Requires an orig.tar.(gz|bz2), a debian.tar.(gz|bz2) (replacing 1.0's diff.gz), and at most one orig-$COMPONENT.tar.(gz|bz2) for each COMPONENT.

determine_source_file_type is extended to identify bz2 compression, debian tarballs, and component orig tarballs. All checks to allow duplicated ORIG_TARBALLS are extended to also permit COMPONENT_ORIG_TARBALLs, as they should be treated identically.

There are pretty simple additional checks in NascentUpload. Additional file type counters are added, as is one for bz2 compression. Compression and new file checks are added to the 1.0 section, as are fairly obvious new 3.0 (quilt) and 3.0 (native) sections.

A few new test source packages are required. I also convinced the 'absolutely-anything' upload policy to permit PPA uploads, since I needed to test with an unsigned PPA upload. I haven't tested all filetype-related rejection cases (the old code did not either), since that would require constructing several more bad source packages.

Revision history for this message
Julian Edwards (julian-edwards) wrote :
Download full text (41.8 KiB)

Thanks for making this change William. I've commented inline.

> === modified file 'lib/lp/archiveuploader/dscfile.py'
> --- lib/lp/archiveuploader/dscfile.py 2009-11-16 22:06:14 +0000
> +++ lib/lp/archiveuploader/dscfile.py 2009-11-18 03:10:29 +0000
> @@ -32,7 +32,8 @@
> from lp.archiveuploader.utils import (
> prefix_multi_line_string, safe_fix_maintainer, ParseMaintError,
> re_valid_pkg_name, re_valid_version, re_issource,
> - determine_source_file_type)
> + re_is_component_orig_tar_ext, determine_source_file_type,
> + get_source_file_extension)

Can you put the imports in alphabetical order please.

> from canonical.encoding import guess as guess_encoding
> from lp.registry.interfaces.person import IPersonSet, PersonCreationRationale
> from lp.registry.interfaces.sourcepackage import SourcePackageFileType
> @@ -347,8 +348,9 @@
> distribution=self.policy.distro,
> purpose=ArchivePurpose.PARTNER)]
> elif (self.policy.archive.purpose == ArchivePurpose.PPA and
> - determine_source_file_type(filename) ==
> - SourcePackageFileType.ORIG_TARBALL):
> + determine_source_file_type(filename) in (
> + SourcePackageFileType.ORIG_TARBALL,
> + SourcePackageFileType.COMPONENT_ORIG_TARBALL)):
> archives = [self.policy.archive, self.policy.distro.main_archive]
> else:
> archives = [self.policy.archive]
> @@ -374,9 +376,13 @@
> """
>
> diff_count = 0
> + debian_tar_count = 0
> orig_tar_count = 0
> + component_orig_tar_counts = {}
> native_tar_count = 0
>
> + bzip2_count = 0
> +
> files_missing = False
> for sub_dsc_file in self.files:
> filetype = determine_source_file_type(sub_dsc_file.filename)
> @@ -385,12 +391,23 @@
> diff_count += 1
> elif filetype == SourcePackageFileType.ORIG_TARBALL:
> orig_tar_count += 1
> + elif filetype == SourcePackageFileType.COMPONENT_ORIG_TARBALL:
> + component = re_is_component_orig_tar_ext.match(
> + get_source_file_extension(sub_dsc_file.filename)).group(1)
> + if component not in component_orig_tar_counts:
> + component_orig_tar_counts[component] = 0
> + component_orig_tar_counts[component] += 1
> + elif filetype == SourcePackageFileType.DEBIAN_TARBALL:
> + debian_tar_count += 1
> elif filetype == SourcePackageFileType.NATIVE_TARBALL:
> native_tar_count += 1

This big list of "elif" statements is looking a bit unwieldy, especially with all the new conditions. Unless you can suggest anything better, how about we do something like:

            def orig_tarball_handler:
                orig_tar_count += 1

            def ....

            filetype_to_action_map = {
                SourcePackageFileType.ORIG_TARBALL : orig_tarball_handler,
                ...
                }

            # Or you could use lambda funcs there --^ it's probably tidier.

            file_type...

review: Needs Fixing (code)
Revision history for this message
William Grant (wgrant) wrote :
Download full text (9.4 KiB)

On Tue, 2009-11-24 at 23:20 +0000, Julian Edwards wrote:
> Review: Needs Fixing code
> Thanks for making this change William. I've commented inline.

Thanks for the review, Julian. I've fixed the main issues -- an
intermediate diff is attached.

> > === modified file 'lib/lp/archiveuploader/dscfile.py'
> > --- lib/lp/archiveuploader/dscfile.py 2009-11-16 22:06:14 +0000
> > +++ lib/lp/archiveuploader/dscfile.py 2009-11-18 03:10:29 +0000
> > @@ -32,7 +32,8 @@
> > from lp.archiveuploader.utils import (
> > prefix_multi_line_string, safe_fix_maintainer, ParseMaintError,
> > re_valid_pkg_name, re_valid_version, re_issource,
> > - determine_source_file_type)
> > + re_is_component_orig_tar_ext, determine_source_file_type,
> > + get_source_file_extension)
>
> Can you put the imports in alphabetical order please.

Done.

> > from canonical.encoding import guess as guess_encoding
> > from lp.registry.interfaces.person import IPersonSet, PersonCreationRationale
> > from lp.registry.interfaces.sourcepackage import SourcePackageFileType
> > @@ -347,8 +348,9 @@
> > distribution=self.policy.distro,
> > purpose=ArchivePurpose.PARTNER)]
> > elif (self.policy.archive.purpose == ArchivePurpose.PPA and
> > - determine_source_file_type(filename) ==
> > - SourcePackageFileType.ORIG_TARBALL):
> > + determine_source_file_type(filename) in (
> > + SourcePackageFileType.ORIG_TARBALL,
> > + SourcePackageFileType.COMPONENT_ORIG_TARBALL)):
> > archives = [self.policy.archive, self.policy.distro.main_archive]
> > else:
> > archives = [self.policy.archive]
> > @@ -374,9 +376,13 @@
> > """
> >
> > diff_count = 0
> > + debian_tar_count = 0
> > orig_tar_count = 0
> > + component_orig_tar_counts = {}
> > native_tar_count = 0
> >
> > + bzip2_count = 0
> > +
> > files_missing = False
> > for sub_dsc_file in self.files:
> > filetype = determine_source_file_type(sub_dsc_file.filename)
> > @@ -385,12 +391,23 @@
> > diff_count += 1
> > elif filetype == SourcePackageFileType.ORIG_TARBALL:
> > orig_tar_count += 1
> > + elif filetype == SourcePackageFileType.COMPONENT_ORIG_TARBALL:
> > + component = re_is_component_orig_tar_ext.match(
> > + get_source_file_extension(sub_dsc_file.filename)).group(1)
> > + if component not in component_orig_tar_counts:
> > + component_orig_tar_counts[component] = 0
> > + component_orig_tar_counts[component] += 1
> > + elif filetype == SourcePackageFileType.DEBIAN_TARBALL:
> > + debian_tar_count += 1
> > elif filetype == SourcePackageFileType.NATIVE_TARBALL:
> > native_tar_count += 1
>
> This big list of "elif" statements is looking a bit unwieldy, especially with all the new conditions. Unless you can suggest anything better, how about we do something like:
> [snip]

While your suggested solution would...

Read more...

=== modified file 'lib/lp/archiveuploader/dscfile.py'
--- lib/lp/archiveuploader/dscfile.py 2009-11-18 02:58:23 +0000
+++ lib/lp/archiveuploader/dscfile.py 2009-11-25 09:40:30 +0000
@@ -30,10 +30,9 @@
30from lp.archiveuploader.tagfiles import (30from lp.archiveuploader.tagfiles import (
31 parse_tagfile, TagFileParseError)31 parse_tagfile, TagFileParseError)
32from lp.archiveuploader.utils import (32from lp.archiveuploader.utils import (
33 prefix_multi_line_string, safe_fix_maintainer, ParseMaintError,33 determine_source_file_type, get_source_file_extension,
34 re_valid_pkg_name, re_valid_version, re_issource,34 ParseMaintError, prefix_multi_line_string, re_is_component_orig_tar_ext,
35 re_is_component_orig_tar_ext, determine_source_file_type,35 re_issource, re_valid_pkg_name, re_valid_version, safe_fix_maintainer)
36 get_source_file_extension)
37from canonical.encoding import guess as guess_encoding36from canonical.encoding import guess as guess_encoding
38from lp.registry.interfaces.person import IPersonSet, PersonCreationRationale37from lp.registry.interfaces.person import IPersonSet, PersonCreationRationale
39from lp.registry.interfaces.sourcepackage import SourcePackageFileType38from lp.registry.interfaces.sourcepackage import SourcePackageFileType
@@ -161,6 +160,9 @@
161160
162 Can raise UploadError.161 Can raise UploadError.
163 """162 """
163 # Avoid circular imports.
164 from lp.archiveuploader.nascentupload import EarlyReturnUploadError
165
164 SourceUploadFile.__init__(166 SourceUploadFile.__init__(
165 self, filepath, digest, size, component_and_section, priority,167 self, filepath, digest, size, component_and_section, priority,
166 package, version, changes, policy, logger)168 package, version, changes, policy, logger)
@@ -187,6 +189,10 @@
187 if 'format' not in self._dict:189 if 'format' not in self._dict:
188 self._dict['format'] = "1.0"190 self._dict['format'] = "1.0"
189191
192 if self.format is None:
193 raise EarlyReturnUploadError(
194 "Unsupported source format: %s" % self._dict['format'])
195
190 if self.policy.unsigned_dsc_ok:196 if self.policy.unsigned_dsc_ok:
191 self.logger.debug("DSC file can be unsigned.")197 self.logger.debug("DSC file can be unsigned.")
192 else:198 else:
@@ -209,7 +215,11 @@
209 @property215 @property
210 def format(self):216 def format(self):
211 """Return the DSC format."""217 """Return the DSC format."""
212 return self._dict['format']218 try:
219 return SourcePackageFormat.getTermByToken(
220 self._dict['format']).value
221 except LookupError:
222 return None
213223
214 @property224 @property
215 def architecture(self):225 def architecture(self):
@@ -232,8 +242,6 @@
232 This method is an error generator, i.e, it returns an iterator over all242 This method is an error generator, i.e, it returns an iterator over all
233 exceptions that are generated while processing DSC file checks.243 exceptions that are generated while processing DSC file checks.
234 """244 """
235 # Avoid circular imports.
236 from lp.archiveuploader.nascentupload import EarlyReturnUploadError
237245
238 for error in SourceUploadFile.verify(self):246 for error in SourceUploadFile.verify(self):
239 yield error247 yield error
@@ -272,14 +280,8 @@
272 yield UploadError(280 yield UploadError(
273 "%s: invalid version %s" % (self.filename, self.dsc_version))281 "%s: invalid version %s" % (self.filename, self.dsc_version))
274282
275 try:
276 format_term = SourcePackageFormat.getTermByToken(self.format)
277 except LookupError:
278 raise EarlyReturnUploadError(
279 "Unsupported source format: %s" % self.format)
280
281 if not self.policy.distroseries.isSourcePackageFormatPermitted(283 if not self.policy.distroseries.isSourcePackageFormatPermitted(
282 format_term.value):284 self.format):
283 yield UploadError(285 yield UploadError(
284 "%s: format '%s' is not permitted in %s." %286 "%s: format '%s' is not permitted in %s." %
285 (self.filename, self.format, self.policy.distroseries.name))287 (self.filename, self.format, self.policy.distroseries.name))
@@ -375,35 +377,32 @@
375 and checksum.377 and checksum.
376 """378 """
377379
378 diff_count = 0380 file_type_counts = {
379 debian_tar_count = 0381 SourcePackageFileType.DIFF: 0,
380 orig_tar_count = 0382 SourcePackageFileType.ORIG_TARBALL: 0,
383 SourcePackageFileType.DEBIAN_TARBALL: 0,
384 SourcePackageFileType.NATIVE_TARBALL: 0,
385 }
381 component_orig_tar_counts = {}386 component_orig_tar_counts = {}
382 native_tar_count = 0
383
384 bzip2_count = 0387 bzip2_count = 0
385
386 files_missing = False388 files_missing = False
389
387 for sub_dsc_file in self.files:390 for sub_dsc_file in self.files:
388 filetype = determine_source_file_type(sub_dsc_file.filename)391 file_type = determine_source_file_type(sub_dsc_file.filename)
389392
390 if filetype == SourcePackageFileType.DIFF:393 if file_type is None:
391 diff_count += 1394 yield UploadError('Unknown file: ' + sub_dsc_file.filename)
392 elif filetype == SourcePackageFileType.ORIG_TARBALL:395 continue
393 orig_tar_count += 1396
394 elif filetype == SourcePackageFileType.COMPONENT_ORIG_TARBALL:397 if file_type == SourcePackageFileType.COMPONENT_ORIG_TARBALL:
398 # Split the count by component name.
395 component = re_is_component_orig_tar_ext.match(399 component = re_is_component_orig_tar_ext.match(
396 get_source_file_extension(sub_dsc_file.filename)).group(1)400 get_source_file_extension(sub_dsc_file.filename)).group(1)
397 if component not in component_orig_tar_counts:401 if component not in component_orig_tar_counts:
398 component_orig_tar_counts[component] = 0402 component_orig_tar_counts[component] = 0
399 component_orig_tar_counts[component] += 1403 component_orig_tar_counts[component] += 1
400 elif filetype == SourcePackageFileType.DEBIAN_TARBALL:
401 debian_tar_count += 1
402 elif filetype == SourcePackageFileType.NATIVE_TARBALL:
403 native_tar_count += 1
404 else:404 else:
405 yield UploadError('Unknown file: ' + sub_dsc_file.filename)405 file_type_counts[file_type] += 1
406 continue
407406
408 if sub_dsc_file.filename.endswith('.bz2'):407 if sub_dsc_file.filename.endswith('.bz2'):
409 bzip2_count += 1408 bzip2_count += 1
@@ -452,99 +451,10 @@
452 yield error451 yield error
453 files_missing = True452 files_missing = True
454453
455 # Reject if we have more than one file of any type.454 for error in format_to_file_checker_map[self.format](
456 if orig_tar_count > 1:455 self.filename, file_type_counts, component_orig_tar_counts,
457 yield UploadError(456 bzip2_count):
458 "%s: has more than one orig.tar.*."457 yield error
459 % self.filename)
460 if debian_tar_count > 1:
461 yield UploadError(
462 "%s: has more than one debian.tar.*."
463 % self.filename)
464 if native_tar_count > 1:
465 yield UploadError(
466 "%s: has more than one tar.*."
467 % self.filename)
468 if diff_count > 1:
469 yield UploadError(
470 "%s: has more than one diff.gz."
471 % self.filename)
472
473 if ((orig_tar_count == 0 and native_tar_count == 0) or
474 (orig_tar_count > 0 and native_tar_count > 0)):
475 yield UploadError(
476 "%s: must have exactly one tar.* or orig.tar.*."
477 % self.filename)
478
479 if native_tar_count > 0 and debian_tar_count > 0:
480 yield UploadError(
481 "%s: must have no more than one tar.* or debian.tar.*."
482 % self.filename)
483
484 # Format 1.0 must be native (exactly one tar.gz), or
485 # have an orig.tar.gz and a diff.gz. It cannot have
486 # compression types other than 'gz'.
487 if self.format == '1.0':
488 if bzip2_count > 0:
489 yield UploadError(
490 "%s: is format 1.0 but uses bzip2 compression."
491 % self.filename)
492
493 if ((diff_count == 0 and native_tar_count == 0) or
494 (diff_count > 0 and native_tar_count > 0)):
495 yield UploadError(
496 "%s: must have exactly one diff.gz or tar.gz."
497 % self.filename)
498
499 if debian_tar_count > 0:
500 yield UploadError(
501 "%s: is format 1.0 but has debian.tar.*."
502 % self.filename)
503
504 if len(component_orig_tar_counts) > 0:
505 yield UploadError(
506 "%s: is format 1.0 but has orig-COMPONENT.tar.*."
507 % self.filename)
508 # Format 3.0 (native) must have exactly one tar.*.
509 # gz and bz2 are valid compression types.
510 elif self.format == '3.0 (native)':
511 if native_tar_count == 0:
512 yield UploadError(
513 "%s: must have exactly one tar.*."
514 % self.filename)
515
516 if diff_count > 0:
517 yield UploadError(
518 "%s: is format 3.0 but has diff.gz."
519 % self.filename)
520
521 if len(component_orig_tar_counts) > 0:
522 yield UploadError(
523 "%s: is native but has orig-COMPONENT.tar.*."
524 % self.filename)
525 elif self.format == '3.0 (quilt)':
526 if orig_tar_count == 0:
527 yield UploadError(
528 "%s: must have exactly one orig.tar.*."
529 % self.filename)
530
531 if debian_tar_count == 0:
532 yield UploadError(
533 "%s: must have exactly one debian.tar.*."
534 % self.filename)
535
536 if diff_count > 0:
537 yield UploadError(
538 "%s: is format 3.0 but has diff.gz."
539 % self.filename)
540
541 for component in component_orig_tar_counts:
542 if component_orig_tar_counts[component] > 1:
543 yield UploadError(
544 "%s: has more than one orig-%s.tar.*."
545 % (self.filename, component))
546 else:
547 raise AssertionError("Unknown source format.")
548458
549 if files_missing:459 if files_missing:
550 yield UploadError(460 yield UploadError(
@@ -727,3 +637,78 @@
727 yield error637 yield error
728638
729639
640def check_format_1_0_files(filename, file_type_counts, component_counts,
641 bzip2_count):
642 """Check that the given counts of each file type suit format 1.0.
643
644 A 1.0 source must be native (with only one tar.gz), or have an orig.tar.gz
645 and a diff.gz. It cannot use bzip2 compression.
646 """
647 if bzip2_count > 0:
648 yield UploadError(
649 "%s: is format 1.0 but uses bzip2 compression."
650 % filename)
651
652 if file_type_counts not in ({
653 SourcePackageFileType.NATIVE_TARBALL: 1,
654 SourcePackageFileType.ORIG_TARBALL: 0,
655 SourcePackageFileType.DEBIAN_TARBALL: 0,
656 SourcePackageFileType.DIFF: 0,
657 }, {
658 SourcePackageFileType.ORIG_TARBALL: 1,
659 SourcePackageFileType.DIFF: 1,
660 SourcePackageFileType.NATIVE_TARBALL: 0,
661 SourcePackageFileType.DEBIAN_TARBALL: 0,
662 }) or len(component_counts) > 0:
663 yield UploadError(
664 "%s: must have exactly one tar.gz, or an orig.tar.gz and diff.gz"
665 % filename)
666
667
668def check_format_3_0_native_files(filename, file_type_counts,
669 component_counts, bzip2_count):
670 """Check that the given counts of each file type suit format 3.0 (native).
671
672 A 3.0 (native) source must have only one tar.*. Both gzip and bzip2
673 compression are permissible.
674 """
675
676 if file_type_counts != {
677 SourcePackageFileType.NATIVE_TARBALL: 1,
678 SourcePackageFileType.ORIG_TARBALL: 0,
679 SourcePackageFileType.DEBIAN_TARBALL: 0,
680 SourcePackageFileType.DIFF: 0,
681 } or len(component_counts) > 0:
682 yield UploadError("%s: must have only a tar.*." % filename)
683
684
685def check_format_3_0_quilt_files(filename, file_type_counts,
686 component_counts, bzip2_count):
687 """Check that the given counts of each file type suit format 3.0 (native).
688
689 A 3.0 (quilt) source must have exactly one orig.tar.*, one debian.tar.*,
690 and at most one orig-COMPONENT.tar.* for each COMPONENT. Both gzip and
691 bzip2 compression are permissible.
692 """
693 if file_type_counts != {
694 SourcePackageFileType.ORIG_TARBALL: 1,
695 SourcePackageFileType.DEBIAN_TARBALL: 1,
696 SourcePackageFileType.NATIVE_TARBALL: 0,
697 SourcePackageFileType.DIFF: 0,
698 }:
699 yield UploadError(
700 "%s: must have only an orig.tar.*, a debian.tar.*, and "
701 "optionally orig-*.tar.*" % filename)
702
703 for component in component_counts:
704 if component_counts[component] > 1:
705 yield UploadError(
706 "%s: has more than one orig-%s.tar.*."
707 % (filename, component))
708
709
710format_to_file_checker_map = {
711 SourcePackageFormat.FORMAT_1_0: check_format_1_0_files,
712 SourcePackageFormat.FORMAT_3_0_NATIVE: check_format_3_0_native_files,
713 SourcePackageFormat.FORMAT_3_0_QUILT: check_format_3_0_quilt_files,
714 }
Revision history for this message
Julian Edwards (julian-edwards) wrote :
Download full text (5.6 KiB)

> While your suggested solution would not work (at least not without the
> 'nonlocal' keyword), I believe I have found something better. I keep one
> dict mapping SPFTs to counts, and another mapping component names to
> counts. This means there's only one special case (for
> COMPONENT_ORIG_TARBALL), and the code for each format becomes much
> cleaner too.

Ah, this is 100% better than my suggestion, nice one!

> I've split it, and completely changed the verification style. The
> failure messages are much less verbose, but one would have to manually
> edit the .dsc to get any of them anyway. I feel the reduction in code
> makes things much better.

Actually it is not only better, it's easier to test because there are
fewer cases!

> This does make testing much easier.
>
> However, there are now just a few code paths, but a lot of potential
> failure cases. How completely should I test?

We always test 100% code coverage at least and any peculiar corner cases
that are obvious.

I'd be happy here to have 2 tests per format type; one that tests it accepts
correctly and one that tests it fails correctly, since that's pretty much
all the code is doing now.

> > Also, can you please change it to compare against the format enum instead
> > of strings. Then the assertion error below will make more sense.
> >
> > > else:
> > > raise AssertionError("Unknown source format.")
>
> It will now die with a KeyError when looking up the file checker, which
> seems as reasonable as the old explicit AssertionError.

I don't really like that, it's not as explicit as the old error, particularly
because the error will appear in the rejection email (unlikely as it is).

Can you catch the KeyError and re-raise it as AssertionError with some good
text. This will ensure if/when we add more format types, it will be easier to
track down why the failure occurred.

> The two uses are on different types: this is a SourceUploadFile, while
> the other is a SourcePackageReleaseFile. Should I instead create a
> utility function alongside SPFT, perhaps?

I would make a mix-in class that both can inherit from and put the property
on that.

> @@ -375,35 +377,32 @@
> and checksum.
> """
>
> - diff_count = 0
> - debian_tar_count = 0
> - orig_tar_count = 0
> + file_type_counts = {
> + SourcePackageFileType.DIFF: 0,
> + SourcePackageFileType.ORIG_TARBALL: 0,
> + SourcePackageFileType.DEBIAN_TARBALL: 0,
> + SourcePackageFileType.NATIVE_TARBALL: 0,
> + }
> component_orig_tar_counts = {}
> - native_tar_count = 0
> -
> bzip2_count = 0
> -

*Loads* better!

> files_missing = False
> +
> for sub_dsc_file in self.files:
> - filetype = determine_source_file_type(sub_dsc_file.filename)
> -
> - if filetype == SourcePackageFileType.DIFF:
> - diff_count += 1
> - elif filetype == SourcePackageFileType.ORIG_TARBALL:
> - orig_tar_count += 1
> - elif filetype == SourcePackageFileType.COMPONENT_ORIG_TARBALL:
> + file_type = determine_source_file_t...

Read more...

review: Needs Fixing (code)
Revision history for this message
William Grant (wgrant) wrote :
Download full text (6.2 KiB)

On Wed, 2009-11-25 at 23:03 +0000, Julian Edwards wrote:
> Review: Needs Fixing code
> > While your suggested solution would not work (at least not without the
> > 'nonlocal' keyword), I believe I have found something better. I keep one
> > dict mapping SPFTs to counts, and another mapping component names to
> > counts. This means there's only one special case (for
> > COMPONENT_ORIG_TARBALL), and the code for each format becomes much
> > cleaner too.
>
> Ah, this is 100% better than my suggestion, nice one!
>
> > I've split it, and completely changed the verification style. The
> > failure messages are much less verbose, but one would have to manually
> > edit the .dsc to get any of them anyway. I feel the reduction in code
> > makes things much better.
>
> Actually it is not only better, it's easier to test because there are
> fewer cases!
>
> > This does make testing much easier.
> >
> > However, there are now just a few code paths, but a lot of potential
> > failure cases. How completely should I test?
>
> We always test 100% code coverage at least and any peculiar corner cases
> that are obvious.
>
> I'd be happy here to have 2 tests per format type; one that tests it accepts
> correctly and one that tests it fails correctly, since that's pretty much
> all the code is doing now.

I've added tests in nascentuploadfile.txt.

> > > Also, can you please change it to compare against the format enum instead
> > > of strings. Then the assertion error below will make more sense.
> > >
> > > > else:
> > > > raise AssertionError("Unknown source format.")
> >
> > It will now die with a KeyError when looking up the file checker, which
> > seems as reasonable as the old explicit AssertionError.
>
> I don't really like that, it's not as explicit as the old error, particularly
> because the error will appear in the rejection email (unlikely as it is).
>
> Can you catch the KeyError and re-raise it as AssertionError with some good
> text. This will ensure if/when we add more format types, it will be easier to
> track down why the failure occurred.

Done.

> > The two uses are on different types: this is a SourceUploadFile, while
> > the other is a SourcePackageReleaseFile. Should I instead create a
> > utility function alongside SPFT, perhaps?
>
> I would make a mix-in class that both can inherit from and put the property
> on that.

As you suggested on IRC, I've put it in
lp.soyuz.model.files.SourceFileMixin.

> > @@ -375,35 +377,32 @@
> > and checksum.
> > """
> >
> > - diff_count = 0
> > - debian_tar_count = 0
> > - orig_tar_count = 0
> > + file_type_counts = {
> > + SourcePackageFileType.DIFF: 0,
> > + SourcePackageFileType.ORIG_TARBALL: 0,
> > + SourcePackageFileType.DEBIAN_TARBALL: 0,
> > + SourcePackageFileType.NATIVE_TARBALL: 0,
> > + }
> > component_orig_tar_counts = {}
> > - native_tar_count = 0
> > -
> > bzip2_count = 0
> > -
>
> *Loads* better!
>
> > files_missing = False
> > +
> > for sub_dsc_file in self.files:
> > - filetype = determine_source_fil...

Read more...

=== modified file 'lib/lp/archiveuploader/dscfile.py'
--- lib/lp/archiveuploader/dscfile.py 2009-11-25 09:40:38 +0000
+++ lib/lp/archiveuploader/dscfile.py 2009-11-26 00:42:45 +0000
@@ -451,7 +451,13 @@
451 yield error451 yield error
452 files_missing = True452 files_missing = True
453453
454 for error in format_to_file_checker_map[self.format](454 try:
455 file_checker = format_to_file_checker_map[self.format]
456 except KeyError:
457 raise AssertionError(
458 "No file checker for source format %s." % self.format)
459
460 for error in file_checker(
455 self.filename, file_type_counts, component_orig_tar_counts,461 self.filename, file_type_counts, component_orig_tar_counts,
456 bzip2_count):462 bzip2_count):
457 yield error463 yield error
@@ -649,17 +655,23 @@
649 "%s: is format 1.0 but uses bzip2 compression."655 "%s: is format 1.0 but uses bzip2 compression."
650 % filename)656 % filename)
651657
652 if file_type_counts not in ({658 valid_file_type_counts = [
653 SourcePackageFileType.NATIVE_TARBALL: 1,659 {
654 SourcePackageFileType.ORIG_TARBALL: 0,660 SourcePackageFileType.NATIVE_TARBALL: 1,
655 SourcePackageFileType.DEBIAN_TARBALL: 0,661 SourcePackageFileType.ORIG_TARBALL: 0,
656 SourcePackageFileType.DIFF: 0,662 SourcePackageFileType.DEBIAN_TARBALL: 0,
657 }, {663 SourcePackageFileType.DIFF: 0,
658 SourcePackageFileType.ORIG_TARBALL: 1,664 },
659 SourcePackageFileType.DIFF: 1,665 {
660 SourcePackageFileType.NATIVE_TARBALL: 0,666 SourcePackageFileType.ORIG_TARBALL: 1,
661 SourcePackageFileType.DEBIAN_TARBALL: 0,667 SourcePackageFileType.DIFF: 1,
662 }) or len(component_counts) > 0:668 SourcePackageFileType.NATIVE_TARBALL: 0,
669 SourcePackageFileType.DEBIAN_TARBALL: 0,
670 },
671 ]
672
673 if (file_type_counts not in valid_file_type_counts or
674 len(component_counts) > 0):
663 yield UploadError(675 yield UploadError(
664 "%s: must have exactly one tar.gz, or an orig.tar.gz and diff.gz"676 "%s: must have exactly one tar.gz, or an orig.tar.gz and diff.gz"
665 % filename)677 % filename)
@@ -673,12 +685,17 @@
673 compression are permissible.685 compression are permissible.
674 """686 """
675687
676 if file_type_counts != {688 valid_file_type_counts = [
677 SourcePackageFileType.NATIVE_TARBALL: 1,689 {
678 SourcePackageFileType.ORIG_TARBALL: 0,690 SourcePackageFileType.NATIVE_TARBALL: 1,
679 SourcePackageFileType.DEBIAN_TARBALL: 0,691 SourcePackageFileType.ORIG_TARBALL: 0,
680 SourcePackageFileType.DIFF: 0,692 SourcePackageFileType.DEBIAN_TARBALL: 0,
681 } or len(component_counts) > 0:693 SourcePackageFileType.DIFF: 0,
694 },
695 ]
696
697 if (file_type_counts not in valid_file_type_counts or
698 len(component_counts) > 0):
682 yield UploadError("%s: must have only a tar.*." % filename)699 yield UploadError("%s: must have only a tar.*." % filename)
683700
684701
@@ -690,12 +707,17 @@
690 and at most one orig-COMPONENT.tar.* for each COMPONENT. Both gzip and707 and at most one orig-COMPONENT.tar.* for each COMPONENT. Both gzip and
691 bzip2 compression are permissible.708 bzip2 compression are permissible.
692 """709 """
693 if file_type_counts != {710
694 SourcePackageFileType.ORIG_TARBALL: 1,711 valid_file_type_counts = [
695 SourcePackageFileType.DEBIAN_TARBALL: 1,712 {
696 SourcePackageFileType.NATIVE_TARBALL: 0,713 SourcePackageFileType.ORIG_TARBALL: 1,
697 SourcePackageFileType.DIFF: 0,714 SourcePackageFileType.DEBIAN_TARBALL: 1,
698 }:715 SourcePackageFileType.NATIVE_TARBALL: 0,
716 SourcePackageFileType.DIFF: 0,
717 },
718 ]
719
720 if file_type_counts not in valid_file_type_counts:
699 yield UploadError(721 yield UploadError(
700 "%s: must have only an orig.tar.*, a debian.tar.*, and "722 "%s: must have only an orig.tar.*, a debian.tar.*, and "
701 "optionally orig-*.tar.*" % filename)723 "optionally orig-*.tar.*" % filename)
702724
=== modified file 'lib/lp/archiveuploader/nascentuploadfile.py'
--- lib/lp/archiveuploader/nascentuploadfile.py 2009-11-14 02:55:15 +0000
+++ lib/lp/archiveuploader/nascentuploadfile.py 2009-11-25 23:38:51 +0000
@@ -35,7 +35,6 @@
35 re_no_epoch, re_no_revision, re_valid_version, re_valid_pkg_name,35 re_no_epoch, re_no_revision, re_valid_version, re_valid_pkg_name,
36 re_extract_src_version, determine_source_file_type)36 re_extract_src_version, determine_source_file_type)
37from canonical.encoding import guess as guess_encoding37from canonical.encoding import guess as guess_encoding
38from lp.registry.interfaces.sourcepackage import SourcePackageFileType
39from lp.soyuz.interfaces.binarypackagename import (38from lp.soyuz.interfaces.binarypackagename import (
40 IBinaryPackageNameSet)39 IBinaryPackageNameSet)
41from lp.soyuz.interfaces.binarypackagerelease import (40from lp.soyuz.interfaces.binarypackagerelease import (
@@ -49,6 +48,7 @@
49from lp.soyuz.interfaces.publishing import (48from lp.soyuz.interfaces.publishing import (
50 PackagePublishingPriority)49 PackagePublishingPriority)
51from lp.soyuz.interfaces.section import ISectionSet50from lp.soyuz.interfaces.section import ISectionSet
51from lp.soyuz.model.files import SourceFileMixin
52from canonical.librarian.utils import filechunks52from canonical.librarian.utils import filechunks
5353
5454
@@ -332,7 +332,7 @@
332 return getUtility(ISectionSet)[self.section_name]332 return getUtility(ISectionSet)[self.section_name]
333333
334334
335class SourceUploadFile(PackageUploadFile):335class SourceUploadFile(SourceFileMixin, PackageUploadFile):
336 """Files mentioned in changesfile as source (orig, diff, tar).336 """Files mentioned in changesfile as source (orig, diff, tar).
337337
338 This class only check consistency on information contained in338 This class only check consistency on information contained in
@@ -340,6 +340,11 @@
340 Further checks on file contents and package consistency are done340 Further checks on file contents and package consistency are done
341 in DSCFile.341 in DSCFile.
342 """342 """
343
344 @property
345 def filetype(self):
346 return determine_source_file_type(self.filename)
347
343 def verify(self):348 def verify(self):
344 """Verify the uploaded source file.349 """Verify the uploaded source file.
345350
@@ -352,9 +357,7 @@
352 "Architecture field." % (self.filename))357 "Architecture field." % (self.filename))
353358
354 version_chopped = re_no_epoch.sub('', self.version)359 version_chopped = re_no_epoch.sub('', self.version)
355 if determine_source_file_type(self.filename) in (360 if self.is_orig:
356 SourcePackageFileType.ORIG_TARBALL,
357 SourcePackageFileType.COMPONENT_ORIG_TARBALL):
358 version_chopped = re_no_revision.sub('', version_chopped)361 version_chopped = re_no_revision.sub('', version_chopped)
359362
360 source_match = re_issource.match(self.filename)363 source_match = re_issource.match(self.filename)
361364
=== modified file 'lib/lp/archiveuploader/tests/nascentuploadfile.txt'
--- lib/lp/archiveuploader/tests/nascentuploadfile.txt 2009-10-28 05:24:11 +0000
+++ lib/lp/archiveuploader/tests/nascentuploadfile.txt 2009-11-26 00:36:18 +0000
@@ -569,6 +569,115 @@
569 ['File ed_0.2-20.dsc mentioned in the changes has a size mismatch. 578 != 500']569 ['File ed_0.2-20.dsc mentioned in the changes has a size mismatch. 578 != 500']
570570
571571
572=== Format file type verification ===
573
574DSCFile performs additional verification on the types of the referenced
575files, confirming that they are suitable for the source package's
576format. There is an error generator to verify each format.
577
578 >>> from lp.archiveuploader.dscfile import (check_format_1_0_files,
579 ... check_format_3_0_native_files, check_format_3_0_quilt_files)
580 >>> from lp.registry.interfaces.sourcepackage import SourcePackageFileType
581
582==== 1.0 ====
583
584A 1.0 source can contain either a tar.gz or an orig.tar.gz and diff.gz.
585
586 >>> list(check_format_1_0_files('foo_1.dsc', {
587 ... SourcePackageFileType.ORIG_TARBALL: 1,
588 ... SourcePackageFileType.DIFF: 1,
589 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
590 ... SourcePackageFileType.NATIVE_TARBALL: 0,
591 ... }, {}, 0))
592 []
593
594 >>> list(check_format_1_0_files('foo_1.dsc', {
595 ... SourcePackageFileType.NATIVE_TARBALL: 1,
596 ... SourcePackageFileType.ORIG_TARBALL: 0,
597 ... SourcePackageFileType.DIFF: 0,
598 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
599 ... }, {}, 0))
600 []
601
602But if we have some other combination, or bzip2 compression, errors
603will be generated.
604
605 >>> list(check_format_1_0_files('foo_1.dsc', {
606 ... SourcePackageFileType.NATIVE_TARBALL: 1,
607 ... SourcePackageFileType.ORIG_TARBALL: 1,
608 ... SourcePackageFileType.DIFF: 1,
609 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
610 ... }, {}, 1))
611 [UploadError('foo_1.dsc: is format 1.0 but uses bzip2 compression.',), UploadError('foo_1.dsc: must have exactly one tar.gz, or an orig.tar.gz and diff.gz',)]
612
613The files are also bad if there are any components:
614
615 >>> list(check_format_1_0_files('foo_1.dsc', {
616 ... SourcePackageFileType.ORIG_TARBALL: 1,
617 ... SourcePackageFileType.DIFF: 1,
618 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
619 ... SourcePackageFileType.NATIVE_TARBALL: 0,
620 ... }, {'foo': 1}, 0))
621 [UploadError('foo_1.dsc: must have exactly one tar.gz, or an orig.tar.gz and diff.gz',)]
622
623==== 3.0 (native) ====
624
625A 3.0 (native) source must contain just a tar.(gz|bz2).
626
627 >>> list(check_format_3_0_native_files('foo_1.dsc', {
628 ... SourcePackageFileType.NATIVE_TARBALL: 1,
629 ... SourcePackageFileType.ORIG_TARBALL: 0,
630 ... SourcePackageFileType.DIFF: 0,
631 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
632 ... }, {}, 1))
633 []
634
635 >>> list(check_format_3_0_native_files('foo_1.dsc', {
636 ... SourcePackageFileType.NATIVE_TARBALL: 1,
637 ... SourcePackageFileType.ORIG_TARBALL: 1,
638 ... SourcePackageFileType.DIFF: 0,
639 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
640 ... }, {}, 1))
641 [UploadError('foo_1.dsc: must have only a tar.*.',)]
642
643 >>> list(check_format_3_0_native_files('foo_1.dsc', {
644 ... SourcePackageFileType.NATIVE_TARBALL: 1,
645 ... SourcePackageFileType.ORIG_TARBALL: 0,
646 ... SourcePackageFileType.DIFF: 0,
647 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
648 ... }, {'foo': 1}, 0))
649 [UploadError('foo_1.dsc: must have only a tar.*.',)]
650
651==== 3.0 (quilt) ====
652
653A 3.0 (quilt) source must have an orig.tar.*, a debian.tar.*, and at
654most one orig-COMPONENT.tar.* for each COMPONENT.
655
656 >>> list(check_format_3_0_quilt_files('foo_1.dsc', {
657 ... SourcePackageFileType.ORIG_TARBALL: 1,
658 ... SourcePackageFileType.DEBIAN_TARBALL: 1,
659 ... SourcePackageFileType.NATIVE_TARBALL: 0,
660 ... SourcePackageFileType.DIFF: 0,
661 ... }, {'foo': 1}, 1))
662 []
663
664 >>> list(check_format_3_0_quilt_files('foo_1.dsc', {
665 ... SourcePackageFileType.NATIVE_TARBALL: 1,
666 ... SourcePackageFileType.ORIG_TARBALL: 1,
667 ... SourcePackageFileType.DIFF: 0,
668 ... SourcePackageFileType.DEBIAN_TARBALL: 1,
669 ... }, {}, 1))
670 [UploadError('foo_1.dsc: must have only an orig.tar.*, a debian.tar.*, and optionally orig-*.tar.*',)]
671
672 >>> list(check_format_3_0_quilt_files('foo_1.dsc', {
673 ... SourcePackageFileType.ORIG_TARBALL: 1,
674 ... SourcePackageFileType.DEBIAN_TARBALL: 1,
675 ... SourcePackageFileType.NATIVE_TARBALL: 0,
676 ... SourcePackageFileType.DIFF: 0,
677 ... }, {'foo': 2}, 0))
678 [UploadError('foo_1.dsc: has more than one orig-foo.tar.*.',)]
679
680
572=== Sub-DSC files or DSCUploadedFiles ===681=== Sub-DSC files or DSCUploadedFiles ===
573682
574Sub-DSCFiles are DSCUploadedFile objects.683Sub-DSCFiles are DSCUploadedFile objects.
575684
=== modified file 'lib/lp/soyuz/interfaces/files.py'
--- lib/lp/soyuz/interfaces/files.py 2009-06-25 04:06:00 +0000
+++ lib/lp/soyuz/interfaces/files.py 2009-11-25 23:23:30 +0000
@@ -14,7 +14,7 @@
14 'ISourcePackageReleaseFileSet',14 'ISourcePackageReleaseFileSet',
15 ]15 ]
1616
17from zope.schema import Int17from zope.schema import Bool, Int
18from zope.interface import Interface18from zope.interface import Interface
19from canonical.launchpad import _19from canonical.launchpad import _
2020
@@ -68,6 +68,11 @@
68 title=_('The type of this file'), required=True, readonly=False,68 title=_('The type of this file'), required=True, readonly=False,
69 )69 )
7070
71 is_orig = Bool(
72 title=_('Whether this file is an original tarball'),
73 required=True, readonly=False,
74 )
75
7176
72class ISourcePackageReleaseFileSet(Interface):77class ISourcePackageReleaseFileSet(Interface):
73 """The set of all `SourcePackageRelease`s."""78 """The set of all `SourcePackageRelease`s."""
7479
=== modified file 'lib/lp/soyuz/model/files.py'
--- lib/lp/soyuz/model/files.py 2009-06-25 04:06:00 +0000
+++ lib/lp/soyuz/model/files.py 2009-11-25 23:38:57 +0000
@@ -60,7 +60,18 @@
60 "binarypackagerelease.binarypackagename"])60 "binarypackagerelease.binarypackagename"])
6161
6262
63class SourcePackageReleaseFile(SQLBase):63class SourceFileMixin:
64 """Mix-in class for common functionality between source file classes."""
65
66 @property
67 def is_orig(self):
68 return self.filetype in (
69 SourcePackageFileType.ORIG_TARBALL,
70 SourcePackageFileType.COMPONENT_ORIG_TARBALL
71 )
72
73
74class SourcePackageReleaseFile(SourceFileMixin, SQLBase):
64 """See ISourcePackageFile"""75 """See ISourcePackageFile"""
6576
66 implements(ISourcePackageReleaseFile)77 implements(ISourcePackageReleaseFile)
@@ -90,4 +101,3 @@
90 prejoins=["libraryfile", "libraryfile.content",101 prejoins=["libraryfile", "libraryfile.content",
91 "sourcepackagerelease",102 "sourcepackagerelease",
92 "sourcepackagerelease.sourcepackagename"])103 "sourcepackagerelease.sourcepackagename"])
93
94104
=== modified file 'lib/lp/soyuz/model/queue.py'
--- lib/lp/soyuz/model/queue.py 2009-11-14 02:55:15 +0000
+++ lib/lp/soyuz/model/queue.py 2009-11-25 23:36:55 +0000
@@ -61,7 +61,6 @@
61 NonBuildableSourceUploadError, QueueBuildAcceptError,61 NonBuildableSourceUploadError, QueueBuildAcceptError,
62 QueueInconsistentStateError, QueueSourceAcceptError,62 QueueInconsistentStateError, QueueSourceAcceptError,
63 QueueStateWriteProtectedError)63 QueueStateWriteProtectedError)
64from lp.registry.interfaces.sourcepackage import SourcePackageFileType
65from canonical.launchpad.mail import (64from canonical.launchpad.mail import (
66 format_address, signed_message_from_string, sendmail)65 format_address, signed_message_from_string, sendmail)
67from lp.soyuz.scripts.processaccepted import (66from lp.soyuz.scripts.processaccepted import (
@@ -1468,9 +1467,7 @@
1468 published_sha1 = published_file.content.sha11467 published_sha1 = published_file.content.sha1
14691468
1470 # Multiple orig(s) with the same content are fine.1469 # Multiple orig(s) with the same content are fine.
1471 if source_file.filetype in (1470 if source_file.is_orig:
1472 SourcePackageFileType.ORIG_TARBALL,
1473 SourcePackageFileType.COMPONENT_ORIG_TARBALL):
1474 if proposed_sha1 == published_sha1:1471 if proposed_sha1 == published_sha1:
1475 continue1472 continue
1476 raise QueueInconsistentStateError(1473 raise QueueInconsistentStateError(
Revision history for this message
Julian Edwards (julian-edwards) wrote :

Looks good! Sorry for the delay in replying. I'll catch up with you about this my Monday morning.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/archiveuploader/dscfile.py'
--- lib/lp/archiveuploader/dscfile.py 2009-11-16 22:06:14 +0000
+++ lib/lp/archiveuploader/dscfile.py 2009-12-12 05:58:17 +0000
@@ -30,9 +30,9 @@
30from lp.archiveuploader.tagfiles import (30from lp.archiveuploader.tagfiles import (
31 parse_tagfile, TagFileParseError)31 parse_tagfile, TagFileParseError)
32from lp.archiveuploader.utils import (32from lp.archiveuploader.utils import (
33 prefix_multi_line_string, safe_fix_maintainer, ParseMaintError,33 determine_source_file_type, get_source_file_extension,
34 re_valid_pkg_name, re_valid_version, re_issource,34 ParseMaintError, prefix_multi_line_string, re_is_component_orig_tar_ext,
35 determine_source_file_type)35 re_issource, re_valid_pkg_name, re_valid_version, safe_fix_maintainer)
36from canonical.encoding import guess as guess_encoding36from canonical.encoding import guess as guess_encoding
37from lp.registry.interfaces.person import IPersonSet, PersonCreationRationale37from lp.registry.interfaces.person import IPersonSet, PersonCreationRationale
38from lp.registry.interfaces.sourcepackage import SourcePackageFileType38from lp.registry.interfaces.sourcepackage import SourcePackageFileType
@@ -160,6 +160,9 @@
160160
161 Can raise UploadError.161 Can raise UploadError.
162 """162 """
163 # Avoid circular imports.
164 from lp.archiveuploader.nascentupload import EarlyReturnUploadError
165
163 SourceUploadFile.__init__(166 SourceUploadFile.__init__(
164 self, filepath, digest, size, component_and_section, priority,167 self, filepath, digest, size, component_and_section, priority,
165 package, version, changes, policy, logger)168 package, version, changes, policy, logger)
@@ -186,6 +189,10 @@
186 if 'format' not in self._dict:189 if 'format' not in self._dict:
187 self._dict['format'] = "1.0"190 self._dict['format'] = "1.0"
188191
192 if self.format is None:
193 raise EarlyReturnUploadError(
194 "Unsupported source format: %s" % self._dict['format'])
195
189 if self.policy.unsigned_dsc_ok:196 if self.policy.unsigned_dsc_ok:
190 self.logger.debug("DSC file can be unsigned.")197 self.logger.debug("DSC file can be unsigned.")
191 else:198 else:
@@ -208,7 +215,11 @@
208 @property215 @property
209 def format(self):216 def format(self):
210 """Return the DSC format."""217 """Return the DSC format."""
211 return self._dict['format']218 try:
219 return SourcePackageFormat.getTermByToken(
220 self._dict['format']).value
221 except LookupError:
222 return None
212223
213 @property224 @property
214 def architecture(self):225 def architecture(self):
@@ -231,8 +242,6 @@
231 This method is an error generator, i.e, it returns an iterator over all242 This method is an error generator, i.e, it returns an iterator over all
232 exceptions that are generated while processing DSC file checks.243 exceptions that are generated while processing DSC file checks.
233 """244 """
234 # Avoid circular imports.
235 from lp.archiveuploader.nascentupload import EarlyReturnUploadError
236245
237 for error in SourceUploadFile.verify(self):246 for error in SourceUploadFile.verify(self):
238 yield error247 yield error
@@ -271,14 +280,8 @@
271 yield UploadError(280 yield UploadError(
272 "%s: invalid version %s" % (self.filename, self.dsc_version))281 "%s: invalid version %s" % (self.filename, self.dsc_version))
273282
274 try:
275 format_term = SourcePackageFormat.getTermByToken(self.format)
276 except LookupError:
277 raise EarlyReturnUploadError(
278 "Unsupported source format: %s" % self.format)
279
280 if not self.policy.distroseries.isSourcePackageFormatPermitted(283 if not self.policy.distroseries.isSourcePackageFormatPermitted(
281 format_term.value):284 self.format):
282 yield UploadError(285 yield UploadError(
283 "%s: format '%s' is not permitted in %s." %286 "%s: format '%s' is not permitted in %s." %
284 (self.filename, self.format, self.policy.distroseries.name))287 (self.filename, self.format, self.policy.distroseries.name))
@@ -347,8 +350,9 @@
347 distribution=self.policy.distro,350 distribution=self.policy.distro,
348 purpose=ArchivePurpose.PARTNER)]351 purpose=ArchivePurpose.PARTNER)]
349 elif (self.policy.archive.purpose == ArchivePurpose.PPA and352 elif (self.policy.archive.purpose == ArchivePurpose.PPA and
350 determine_source_file_type(filename) ==353 determine_source_file_type(filename) in (
351 SourcePackageFileType.ORIG_TARBALL):354 SourcePackageFileType.ORIG_TARBALL,
355 SourcePackageFileType.COMPONENT_ORIG_TARBALL)):
352 archives = [self.policy.archive, self.policy.distro.main_archive]356 archives = [self.policy.archive, self.policy.distro.main_archive]
353 else:357 else:
354 archives = [self.policy.archive]358 archives = [self.policy.archive]
@@ -373,24 +377,36 @@
373 and checksum.377 and checksum.
374 """378 """
375379
376 diff_count = 0380 file_type_counts = {
377 orig_tar_count = 0381 SourcePackageFileType.DIFF: 0,
378 native_tar_count = 0382 SourcePackageFileType.ORIG_TARBALL: 0,
379383 SourcePackageFileType.DEBIAN_TARBALL: 0,
384 SourcePackageFileType.NATIVE_TARBALL: 0,
385 }
386 component_orig_tar_counts = {}
387 bzip2_count = 0
380 files_missing = False388 files_missing = False
389
381 for sub_dsc_file in self.files:390 for sub_dsc_file in self.files:
382 filetype = determine_source_file_type(sub_dsc_file.filename)391 file_type = determine_source_file_type(sub_dsc_file.filename)
383392
384 if filetype == SourcePackageFileType.DIFF:393 if file_type is None:
385 diff_count += 1
386 elif filetype == SourcePackageFileType.ORIG_TARBALL:
387 orig_tar_count += 1
388 elif filetype == SourcePackageFileType.NATIVE_TARBALL:
389 native_tar_count += 1
390 else:
391 yield UploadError('Unknown file: ' + sub_dsc_file.filename)394 yield UploadError('Unknown file: ' + sub_dsc_file.filename)
392 continue395 continue
393396
397 if file_type == SourcePackageFileType.COMPONENT_ORIG_TARBALL:
398 # Split the count by component name.
399 component = re_is_component_orig_tar_ext.match(
400 get_source_file_extension(sub_dsc_file.filename)).group(1)
401 if component not in component_orig_tar_counts:
402 component_orig_tar_counts[component] = 0
403 component_orig_tar_counts[component] += 1
404 else:
405 file_type_counts[file_type] += 1
406
407 if sub_dsc_file.filename.endswith('.bz2'):
408 bzip2_count += 1
409
394 try:410 try:
395 library_file, file_archive = self._getFileByName(411 library_file, file_archive = self._getFileByName(
396 sub_dsc_file.filename)412 sub_dsc_file.filename)
@@ -435,37 +451,16 @@
435 yield error451 yield error
436 files_missing = True452 files_missing = True
437453
438 # Reject if we have more than one file of any type.454 try:
439 if orig_tar_count > 1:455 file_checker = format_to_file_checker_map[self.format]
440 yield UploadError(456 except KeyError:
441 "%s: has more than one orig.tar.*."457 raise AssertionError(
442 % self.filename)458 "No file checker for source format %s." % self.format)
443 if native_tar_count > 1:459
444 yield UploadError(460 for error in file_checker(
445 "%s: has more than one tar.*."461 self.filename, file_type_counts, component_orig_tar_counts,
446 % self.filename)462 bzip2_count):
447 if diff_count > 1:463 yield error
448 yield UploadError(
449 "%s: has more than one diff.gz."
450 % self.filename)
451
452 if ((orig_tar_count == 0 and native_tar_count == 0) or
453 (orig_tar_count > 0 and native_tar_count > 0)):
454 yield UploadError(
455 "%s: must have exactly one tar.* or orig.tar.*."
456 % self.filename)
457
458 # Format 1.0 must be native (exactly one tar.gz), or
459 # have an orig.tar.gz and a diff.gz. It cannot have
460 # compression types other than 'gz'.
461 if self.format == '1.0':
462 if ((diff_count == 0 and native_tar_count == 0) or
463 (diff_count > 0 and native_tar_count > 0)):
464 yield UploadError(
465 "%s: must have exactly one diff.gz or tar.gz."
466 % self.filename)
467 else:
468 raise AssertionError("Unknown source format.")
469464
470 if files_missing:465 if files_missing:
471 yield UploadError(466 yield UploadError(
@@ -648,3 +643,94 @@
648 yield error643 yield error
649644
650645
646def check_format_1_0_files(filename, file_type_counts, component_counts,
647 bzip2_count):
648 """Check that the given counts of each file type suit format 1.0.
649
650 A 1.0 source must be native (with only one tar.gz), or have an orig.tar.gz
651 and a diff.gz. It cannot use bzip2 compression.
652 """
653 if bzip2_count > 0:
654 yield UploadError(
655 "%s: is format 1.0 but uses bzip2 compression."
656 % filename)
657
658 valid_file_type_counts = [
659 {
660 SourcePackageFileType.NATIVE_TARBALL: 1,
661 SourcePackageFileType.ORIG_TARBALL: 0,
662 SourcePackageFileType.DEBIAN_TARBALL: 0,
663 SourcePackageFileType.DIFF: 0,
664 },
665 {
666 SourcePackageFileType.ORIG_TARBALL: 1,
667 SourcePackageFileType.DIFF: 1,
668 SourcePackageFileType.NATIVE_TARBALL: 0,
669 SourcePackageFileType.DEBIAN_TARBALL: 0,
670 },
671 ]
672
673 if (file_type_counts not in valid_file_type_counts or
674 len(component_counts) > 0):
675 yield UploadError(
676 "%s: must have exactly one tar.gz, or an orig.tar.gz and diff.gz"
677 % filename)
678
679
680def check_format_3_0_native_files(filename, file_type_counts,
681 component_counts, bzip2_count):
682 """Check that the given counts of each file type suit format 3.0 (native).
683
684 A 3.0 (native) source must have only one tar.*. Both gzip and bzip2
685 compression are permissible.
686 """
687
688 valid_file_type_counts = [
689 {
690 SourcePackageFileType.NATIVE_TARBALL: 1,
691 SourcePackageFileType.ORIG_TARBALL: 0,
692 SourcePackageFileType.DEBIAN_TARBALL: 0,
693 SourcePackageFileType.DIFF: 0,
694 },
695 ]
696
697 if (file_type_counts not in valid_file_type_counts or
698 len(component_counts) > 0):
699 yield UploadError("%s: must have only a tar.*." % filename)
700
701
702def check_format_3_0_quilt_files(filename, file_type_counts,
703 component_counts, bzip2_count):
704 """Check that the given counts of each file type suit format 3.0 (native).
705
706 A 3.0 (quilt) source must have exactly one orig.tar.*, one debian.tar.*,
707 and at most one orig-COMPONENT.tar.* for each COMPONENT. Both gzip and
708 bzip2 compression are permissible.
709 """
710
711 valid_file_type_counts = [
712 {
713 SourcePackageFileType.ORIG_TARBALL: 1,
714 SourcePackageFileType.DEBIAN_TARBALL: 1,
715 SourcePackageFileType.NATIVE_TARBALL: 0,
716 SourcePackageFileType.DIFF: 0,
717 },
718 ]
719
720 if file_type_counts not in valid_file_type_counts:
721 yield UploadError(
722 "%s: must have only an orig.tar.*, a debian.tar.*, and "
723 "optionally orig-*.tar.*" % filename)
724
725 for component in component_counts:
726 if component_counts[component] > 1:
727 yield UploadError(
728 "%s: has more than one orig-%s.tar.*."
729 % (filename, component))
730
731
732format_to_file_checker_map = {
733 SourcePackageFormat.FORMAT_1_0: check_format_1_0_files,
734 SourcePackageFormat.FORMAT_3_0_NATIVE: check_format_3_0_native_files,
735 SourcePackageFormat.FORMAT_3_0_QUILT: check_format_3_0_quilt_files,
736 }
651737
=== modified file 'lib/lp/archiveuploader/nascentuploadfile.py'
--- lib/lp/archiveuploader/nascentuploadfile.py 2009-12-07 10:53:13 +0000
+++ lib/lp/archiveuploader/nascentuploadfile.py 2009-12-12 05:58:17 +0000
@@ -35,7 +35,6 @@
35 re_no_epoch, re_no_revision, re_valid_version, re_valid_pkg_name,35 re_no_epoch, re_no_revision, re_valid_version, re_valid_pkg_name,
36 re_extract_src_version, determine_source_file_type)36 re_extract_src_version, determine_source_file_type)
37from canonical.encoding import guess as guess_encoding37from canonical.encoding import guess as guess_encoding
38from lp.registry.interfaces.sourcepackage import SourcePackageFileType
39from lp.soyuz.interfaces.binarypackagename import (38from lp.soyuz.interfaces.binarypackagename import (
40 IBinaryPackageNameSet)39 IBinaryPackageNameSet)
41from lp.soyuz.interfaces.binarypackagerelease import (40from lp.soyuz.interfaces.binarypackagerelease import (
@@ -49,6 +48,7 @@
49from lp.soyuz.interfaces.publishing import (48from lp.soyuz.interfaces.publishing import (
50 PackagePublishingPriority)49 PackagePublishingPriority)
51from lp.soyuz.interfaces.section import ISectionSet50from lp.soyuz.interfaces.section import ISectionSet
51from lp.soyuz.model.files import SourceFileMixin
52from canonical.librarian.utils import filechunks52from canonical.librarian.utils import filechunks
5353
5454
@@ -332,7 +332,7 @@
332 return getUtility(ISectionSet)[self.section_name]332 return getUtility(ISectionSet)[self.section_name]
333333
334334
335class SourceUploadFile(PackageUploadFile):335class SourceUploadFile(SourceFileMixin, PackageUploadFile):
336 """Files mentioned in changesfile as source (orig, diff, tar).336 """Files mentioned in changesfile as source (orig, diff, tar).
337337
338 This class only check consistency on information contained in338 This class only check consistency on information contained in
@@ -340,6 +340,11 @@
340 Further checks on file contents and package consistency are done340 Further checks on file contents and package consistency are done
341 in DSCFile.341 in DSCFile.
342 """342 """
343
344 @property
345 def filetype(self):
346 return determine_source_file_type(self.filename)
347
343 def verify(self):348 def verify(self):
344 """Verify the uploaded source file.349 """Verify the uploaded source file.
345350
@@ -352,8 +357,7 @@
352 "Architecture field." % (self.filename))357 "Architecture field." % (self.filename))
353358
354 version_chopped = re_no_epoch.sub('', self.version)359 version_chopped = re_no_epoch.sub('', self.version)
355 if determine_source_file_type(self.filename) == (360 if self.is_orig:
356 SourcePackageFileType.ORIG_TARBALL):
357 version_chopped = re_no_revision.sub('', version_chopped)361 version_chopped = re_no_revision.sub('', version_chopped)
358362
359 source_match = re_issource.match(self.filename)363 source_match = re_issource.match(self.filename)
360364
=== added directory 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2'
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1.diff.gz'
361Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1.diff.gz 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1.diff.gz 2009-12-12 05:58:17 +0000 differ365Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1.diff.gz 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1.diff.gz 2009-12-12 05:58:17 +0000 differ
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1.dsc'
--- lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1.dsc 1970-01-01 00:00:00 +0000
+++ lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1.dsc 2009-12-12 05:58:17 +0000
@@ -0,0 +1,10 @@
1Format: 1.0
2Source: bar
3Version: 1.0-1
4Binary: bar
5Maintainer: Launchpad team <launchpad@lists.canonical.com>
6Architecture: any
7Standards-Version: 3.6.2
8Files:
9 f1b3ab12b2d0886bc5d87737bb933b83 170 bar_1.0.orig.tar.bz2
10 1e35b810764f140af9616de8274e6e73 537 bar_1.0-1.diff.gz
011
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1_source.changes'
--- lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1_source.changes 1970-01-01 00:00:00 +0000
+++ lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1_source.changes 2009-12-12 05:58:17 +0000
@@ -0,0 +1,20 @@
1Format: 1.7
2Date: Thu, 16 Feb 2006 15:34:09 +0000
3Source: bar
4Binary: bar
5Architecture: source
6Version: 1.0-1
7Distribution: breezy
8Urgency: low
9Maintainer: Launchpad team <launchpad@lists.canonical.com>
10Changed-By: Daniel Silverstone <daniel.silverstone@canonical.com>
11Description:
12 bar - Stuff for testing
13Changes:
14 bar (1.0-1) breezy; urgency=low
15 .
16 * Initial version
17Files:
18 8e34d4e135decd09145c08a78a2a61ff 276 devel optional bar_1.0-1.dsc
19 f1b3ab12b2d0886bc5d87737bb933b83 170 devel optional bar_1.0.orig.tar.bz2
20 1e35b810764f140af9616de8274e6e73 537 devel optional bar_1.0-1.diff.gz
021
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0.orig.tar.bz2'
1Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0.orig.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0.orig.tar.bz2 2009-12-12 05:58:17 +0000 differ22Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0.orig.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0.orig.tar.bz2 2009-12-12 05:58:17 +0000 differ
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.debian.tar.bz2'
2Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.debian.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.debian.tar.bz2 2009-12-12 05:58:17 +0000 differ23Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.debian.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.debian.tar.bz2 2009-12-12 05:58:17 +0000 differ
=== removed file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.debian.tar.gz'
3Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.debian.tar.gz 2009-11-12 11:54:56 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.debian.tar.gz 1970-01-01 00:00:00 +0000 differ24Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.debian.tar.gz 2009-11-12 11:54:56 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.debian.tar.gz 1970-01-01 00:00:00 +0000 differ
=== modified file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.dsc'
--- lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.dsc 2009-11-12 11:54:56 +0000
+++ lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.dsc 2009-12-12 05:58:17 +0000
@@ -6,11 +6,17 @@
6Maintainer: Launchpad team <launchpad@lists.canonical.com>6Maintainer: Launchpad team <launchpad@lists.canonical.com>
7Standards-Version: 3.6.27Standards-Version: 3.6.2
8Checksums-Sha1: 8Checksums-Sha1:
9 e7a106587e0f11220e27ccc5db7527cae05e4054 178 bar_1.0.orig-comp1.tar.gz
10 a645cc0856469f549f11bb9bdc4ca6dda4eedd4b 156 bar_1.0.orig-comp2.tar.bz2
9 73a04163fee97fd2257ab266bd48f1d3d528e012 164 bar_1.0.orig.tar.gz11 73a04163fee97fd2257ab266bd48f1d3d528e012 164 bar_1.0.orig.tar.gz
10 abce262314a7c0ca00e43598f21b41a3e6ff6b21 688 bar_1.0-1.debian.tar.gz12 727de2395d3a3e35c375159db01072935fea02f8 737 bar_1.0-1.debian.tar.bz2
11Checksums-Sha256: 13Checksums-Sha256:
14 aff0bbc01c5883ac76e89cba7a9b6cd79b521183f0de86c93e93ab8804f5a256 178 bar_1.0.orig-comp1.tar.gz
15 955131b3a5bd881c008ff822c0f9b7544350647fe1f355f65a138e0e5e5e8d71 156 bar_1.0.orig-comp2.tar.bz2
12 f1ecff929899b567f45d6734b69d59a4f3c04dabce3cc8e6ed6d64073eda360e 164 bar_1.0.orig.tar.gz16 f1ecff929899b567f45d6734b69d59a4f3c04dabce3cc8e6ed6d64073eda360e 164 bar_1.0.orig.tar.gz
13 ffdcce60fca14618f68483ca77a206f332a3773dc7ece1c3e6de55c0118c69c6 688 bar_1.0-1.debian.tar.gz17 3d2137f9f80f4b6c80f73acb8b3ac7986c962c4268d8948f54823d27148a6116 737 bar_1.0-1.debian.tar.bz2
14Files: 18Files:
19 eed105761436486f7eebaa8c017bc59a 178 bar_1.0.orig-comp1.tar.gz
20 0a30b50fa846e75261808ee1f41d1cbe 156 bar_1.0.orig-comp2.tar.bz2
15 fc1464e5985b962a042d5354452f361d 164 bar_1.0.orig.tar.gz21 fc1464e5985b962a042d5354452f361d 164 bar_1.0.orig.tar.gz
16 056db4dfe7de8322296b6d417592ee01 688 bar_1.0-1.debian.tar.gz22 e68110184d4d9e7afd81520cc490b396 737 bar_1.0-1.debian.tar.bz2
1723
=== modified file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1_source.changes'
--- lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1_source.changes 2009-11-12 11:54:56 +0000
+++ lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1_source.changes 2009-12-12 05:58:17 +0000
@@ -15,14 +15,20 @@
15 .15 .
16 * Initial version16 * Initial version
17Checksums-Sha1: 17Checksums-Sha1:
18 bc97e185cf31af33bf8d109044ce51f32d09c229 645 bar_1.0-1.dsc18 762b018e756c1d9be905d40291bc8e975c57a8f0 1115 bar_1.0-1.dsc
19 e7a106587e0f11220e27ccc5db7527cae05e4054 178 bar_1.0.orig-comp1.tar.gz
20 a645cc0856469f549f11bb9bdc4ca6dda4eedd4b 156 bar_1.0.orig-comp2.tar.bz2
19 73a04163fee97fd2257ab266bd48f1d3d528e012 164 bar_1.0.orig.tar.gz21 73a04163fee97fd2257ab266bd48f1d3d528e012 164 bar_1.0.orig.tar.gz
20 abce262314a7c0ca00e43598f21b41a3e6ff6b21 688 bar_1.0-1.debian.tar.gz22 727de2395d3a3e35c375159db01072935fea02f8 737 bar_1.0-1.debian.tar.bz2
21Checksums-Sha256: 23Checksums-Sha256:
22 ae0fb16941a95518332a8ee962d00d55963b491c2df94b3f230a65d2bdbeedf8 645 bar_1.0-1.dsc24 49f2656a0e221b0f07dc208f583e2523b09bc30104855372534b5562478efdb5 1115 bar_1.0-1.dsc
25 aff0bbc01c5883ac76e89cba7a9b6cd79b521183f0de86c93e93ab8804f5a256 178 bar_1.0.orig-comp1.tar.gz
26 955131b3a5bd881c008ff822c0f9b7544350647fe1f355f65a138e0e5e5e8d71 156 bar_1.0.orig-comp2.tar.bz2
23 f1ecff929899b567f45d6734b69d59a4f3c04dabce3cc8e6ed6d64073eda360e 164 bar_1.0.orig.tar.gz27 f1ecff929899b567f45d6734b69d59a4f3c04dabce3cc8e6ed6d64073eda360e 164 bar_1.0.orig.tar.gz
24 ffdcce60fca14618f68483ca77a206f332a3773dc7ece1c3e6de55c0118c69c6 688 bar_1.0-1.debian.tar.gz28 3d2137f9f80f4b6c80f73acb8b3ac7986c962c4268d8948f54823d27148a6116 737 bar_1.0-1.debian.tar.bz2
25Files: 29Files:
26 c320d2827f08f09ec2e1bbbac635225c 645 devel optional bar_1.0-1.dsc30 662977e76501561c902c34bf94a2054d 1115 devel optional bar_1.0-1.dsc
31 eed105761436486f7eebaa8c017bc59a 178 devel optional bar_1.0.orig-comp1.tar.gz
32 0a30b50fa846e75261808ee1f41d1cbe 156 devel optional bar_1.0.orig-comp2.tar.bz2
27 fc1464e5985b962a042d5354452f361d 164 devel optional bar_1.0.orig.tar.gz33 fc1464e5985b962a042d5354452f361d 164 devel optional bar_1.0.orig.tar.gz
28 056db4dfe7de8322296b6d417592ee01 688 devel optional bar_1.0-1.debian.tar.gz34 e68110184d4d9e7afd81520cc490b396 737 devel optional bar_1.0-1.debian.tar.bz2
2935
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0.orig-comp1.tar.gz'
30Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0.orig-comp1.tar.gz 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0.orig-comp1.tar.gz 2009-12-12 05:58:17 +0000 differ36Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0.orig-comp1.tar.gz 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0.orig-comp1.tar.gz 2009-12-12 05:58:17 +0000 differ
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0.orig-comp2.tar.bz2'
31Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0.orig-comp2.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0.orig-comp2.tar.bz2 2009-12-12 05:58:17 +0000 differ37Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0.orig-comp2.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0.orig-comp2.tar.bz2 2009-12-12 05:58:17 +0000 differ
=== added directory 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig'
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2.debian.tar.bz2'
32Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2.debian.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2.debian.tar.bz2 2009-12-12 05:58:17 +0000 differ38Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2.debian.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2.debian.tar.bz2 2009-12-12 05:58:17 +0000 differ
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2.dsc'
--- lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2.dsc 1970-01-01 00:00:00 +0000
+++ lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2.dsc 2009-12-12 05:58:17 +0000
@@ -0,0 +1,22 @@
1Format: 3.0 (quilt)
2Source: bar
3Binary: bar
4Architecture: any
5Version: 1.0-2
6Maintainer: Launchpad team <launchpad@lists.canonical.com>
7Standards-Version: 3.6.2
8Checksums-Sha1:
9 e7a106587e0f11220e27ccc5db7527cae05e4054 178 bar_1.0.orig-comp1.tar.gz
10 a645cc0856469f549f11bb9bdc4ca6dda4eedd4b 156 bar_1.0.orig-comp2.tar.bz2
11 73a04163fee97fd2257ab266bd48f1d3d528e012 164 bar_1.0.orig.tar.gz
12 62776c07df0412798956af8b625a9f1744c8f0fb 807 bar_1.0-2.debian.tar.bz2
13Checksums-Sha256:
14 aff0bbc01c5883ac76e89cba7a9b6cd79b521183f0de86c93e93ab8804f5a256 178 bar_1.0.orig-comp1.tar.gz
15 955131b3a5bd881c008ff822c0f9b7544350647fe1f355f65a138e0e5e5e8d71 156 bar_1.0.orig-comp2.tar.bz2
16 f1ecff929899b567f45d6734b69d59a4f3c04dabce3cc8e6ed6d64073eda360e 164 bar_1.0.orig.tar.gz
17 a2a4a82e6f6b212e7de11df327fea18bf2b8e846d221e417b0a479d0f8bf9d79 807 bar_1.0-2.debian.tar.bz2
18Files:
19 eed105761436486f7eebaa8c017bc59a 178 bar_1.0.orig-comp1.tar.gz
20 0a30b50fa846e75261808ee1f41d1cbe 156 bar_1.0.orig-comp2.tar.bz2
21 fc1464e5985b962a042d5354452f361d 164 bar_1.0.orig.tar.gz
22 8b17b1469943483df4d5093955553992 807 bar_1.0-2.debian.tar.bz2
023
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2_source.changes'
--- lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2_source.changes 1970-01-01 00:00:00 +0000
+++ lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2_source.changes 2009-12-12 05:58:17 +0000
@@ -0,0 +1,25 @@
1Format: 1.8
2Date: Sun, 01 Nov 2009 10:49:22 +1100
3Source: bar
4Binary: bar
5Architecture: source
6Version: 1.0-2
7Distribution: breezy
8Urgency: low
9Maintainer: Launchpad team <launchpad@lists.canonical.com>
10Changed-By: William Grant <me@williamgrant.id.au>
11Description:
12 bar - Stuff for testing
13Changes:
14 bar (1.0-2) breezy; urgency=low
15 .
16 * Another version
17Checksums-Sha1:
18 d9ccd09135965a759bd741fba1f5223a0314aac8 1115 bar_1.0-2.dsc
19 62776c07df0412798956af8b625a9f1744c8f0fb 807 bar_1.0-2.debian.tar.bz2
20Checksums-Sha256:
21 53ec1fb4c1671e203c433db570a667750bf4a503e4556ac2c9600389e119744a 1115 bar_1.0-2.dsc
22 a2a4a82e6f6b212e7de11df327fea18bf2b8e846d221e417b0a479d0f8bf9d79 807 bar_1.0-2.debian.tar.bz2
23Files:
24 014288c2cdeca7a9a5e3201aca044c3b 1115 devel optional bar_1.0-2.dsc
25 8b17b1469943483df4d5093955553992 807 devel optional bar_1.0-2.debian.tar.bz2
026
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig-comp1.tar.gz'
1Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig-comp1.tar.gz 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig-comp1.tar.gz 2009-12-12 05:58:17 +0000 differ27Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig-comp1.tar.gz 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig-comp1.tar.gz 2009-12-12 05:58:17 +0000 differ
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig-comp2.tar.bz2'
2Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig-comp2.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig-comp2.tar.bz2 2009-12-12 05:58:17 +0000 differ28Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig-comp2.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig-comp2.tar.bz2 2009-12-12 05:58:17 +0000 differ
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig.tar.gz'
3Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig.tar.gz 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig.tar.gz 2009-12-12 05:58:17 +0000 differ29Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig.tar.gz 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0.orig.tar.gz 2009-12-12 05:58:17 +0000 differ
=== added directory 'lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native'
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0.dsc'
--- lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0.dsc 1970-01-01 00:00:00 +0000
+++ lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0.dsc 2009-12-12 05:58:17 +0000
@@ -0,0 +1,13 @@
1Format: 3.0 (native)
2Source: bar
3Binary: bar
4Architecture: any
5Version: 1.0
6Maintainer: Launchpad team <launchpad@lists.canonical.com>
7Standards-Version: 3.6.2
8Checksums-Sha1:
9 f931b8f8fe90b365ad19d84387712e64784cd5ef 776 bar_1.0.tar.bz2
10Checksums-Sha256:
11 1193877b5fc00c410550ad01ec2ed6f97f98a3c8dd2de3753a49251734c842ab 776 bar_1.0.tar.bz2
12Files:
13 f9c5c454799806682e832bb4a73d8c5c 776 bar_1.0.tar.bz2
014
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0.tar.bz2'
1Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0.tar.bz2 2009-12-12 05:58:17 +0000 differ15Binary files lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0.tar.bz2 1970-01-01 00:00:00 +0000 and lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0.tar.bz2 2009-12-12 05:58:17 +0000 differ
=== added file 'lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0_source.changes'
--- lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0_source.changes 1970-01-01 00:00:00 +0000
+++ lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0_source.changes 2009-12-12 05:58:17 +0000
@@ -0,0 +1,25 @@
1Format: 1.8
2Date: Thu, 16 Feb 2006 15:34:09 +0000
3Source: bar
4Binary: bar
5Architecture: source
6Version: 1.0
7Distribution: breezy
8Urgency: low
9Maintainer: Launchpad team <launchpad@lists.canonical.com>
10Changed-By: Daniel Silverstone <daniel.silverstone@canonical.com>
11Description:
12 bar - Stuff for testing
13Changes:
14 bar (1.0) breezy; urgency=low
15 .
16 * Initial version
17Checksums-Sha1:
18 3662dbba7c9f5afcdb6aa240a579ffbe1307f64d 406 bar_1.0.dsc
19 f931b8f8fe90b365ad19d84387712e64784cd5ef 776 bar_1.0.tar.bz2
20Checksums-Sha256:
21 b874abb035c04a228272a45625bfd8259998addcbdfd8df0c5c61024b9d40857 406 bar_1.0.dsc
22 1193877b5fc00c410550ad01ec2ed6f97f98a3c8dd2de3753a49251734c842ab 776 bar_1.0.tar.bz2
23Files:
24 0fbea3d7be741c94c5f964ee023ef164 406 devel optional bar_1.0.dsc
25 f9c5c454799806682e832bb4a73d8c5c 776 devel optional bar_1.0.tar.bz2
026
=== modified file 'lib/lp/archiveuploader/tests/nascentuploadfile.txt'
--- lib/lp/archiveuploader/tests/nascentuploadfile.txt 2009-12-03 15:51:44 +0000
+++ lib/lp/archiveuploader/tests/nascentuploadfile.txt 2009-12-12 05:58:17 +0000
@@ -216,6 +216,16 @@
216 >>> src_match.group(3)216 >>> src_match.group(3)
217 'tar.gz'217 'tar.gz'
218218
219 >>> src_match = re_issource.match('foo_1.0.tar.bz2')
220 >>> src_match.group(0)
221 'foo_1.0.tar.bz2'
222 >>> src_match.group(1)
223 'foo'
224 >>> src_match.group(2)
225 '1.0'
226 >>> src_match.group(3)
227 'tar.bz2'
228
219 >>> src_match = re_issource.match('foo_1.0.diff.gz')229 >>> src_match = re_issource.match('foo_1.0.diff.gz')
220 >>> src_match.group(0)230 >>> src_match.group(0)
221 'foo_1.0.diff.gz'231 'foo_1.0.diff.gz'
@@ -236,6 +246,56 @@
236 >>> src_match.group(3)246 >>> src_match.group(3)
237 'dsc'247 'dsc'
238248
249 >>> src_match = re_issource.match('foo_1.0.debian.tar.gz')
250 >>> src_match.group(0)
251 'foo_1.0.debian.tar.gz'
252 >>> src_match.group(1)
253 'foo'
254 >>> src_match.group(2)
255 '1.0'
256 >>> src_match.group(3)
257 'debian.tar.gz'
258
259 >>> src_match = re_issource.match('foo_1.0.debian.tar.bz2')
260 >>> src_match.group(0)
261 'foo_1.0.debian.tar.bz2'
262 >>> src_match.group(1)
263 'foo'
264 >>> src_match.group(2)
265 '1.0'
266 >>> src_match.group(3)
267 'debian.tar.bz2'
268
269 >>> src_match = re_issource.match('foo_1.0.orig-foo.tar.gz')
270 >>> src_match.group(0)
271 'foo_1.0.orig-foo.tar.gz'
272 >>> src_match.group(1)
273 'foo'
274 >>> src_match.group(2)
275 '1.0'
276 >>> src_match.group(3)
277 'orig-foo.tar.gz'
278
279 >>> src_match = re_issource.match('foo_1.0.orig-bar.tar.bz2')
280 >>> src_match.group(0)
281 'foo_1.0.orig-bar.tar.bz2'
282 >>> src_match.group(1)
283 'foo'
284 >>> src_match.group(2)
285 '1.0'
286 >>> src_match.group(3)
287 'orig-bar.tar.bz2'
288
289 >>> src_match = re_issource.match('foo_1.0.porig-bar.tar.bz2')
290 >>> src_match.group(0)
291 'foo_1.0.porig-bar.tar.bz2'
292 >>> src_match.group(1)
293 'foo'
294 >>> src_match.group(2)
295 '1.0.porig-bar'
296 >>> src_match.group(3)
297 'tar.bz2'
298
239And finally some failures:299And finally some failures:
240300
241 >>> re_isadeb.match('foo-bar_1.0_i386.bed') is None301 >>> re_isadeb.match('foo-bar_1.0_i386.bed') is None
@@ -244,6 +304,9 @@
244 >>> re_issource.match('foo_1.0.c') is None304 >>> re_issource.match('foo_1.0.c') is None
245 True305 True
246306
307 >>> re_issource.match('foo_1.0.diff.bz2') is None
308 True
309
247However a custom upload is essencially a tarball, so it also matches310However a custom upload is essencially a tarball, so it also matches
248the is_source regexp:311the is_source regexp:
249312
@@ -506,6 +569,115 @@
506 ['File ed_0.2-20.dsc mentioned in the changes has a size mismatch. 578 != 500']569 ['File ed_0.2-20.dsc mentioned in the changes has a size mismatch. 578 != 500']
507570
508571
572=== Format file type verification ===
573
574DSCFile performs additional verification on the types of the referenced
575files, confirming that they are suitable for the source package's
576format. There is an error generator to verify each format.
577
578 >>> from lp.archiveuploader.dscfile import (check_format_1_0_files,
579 ... check_format_3_0_native_files, check_format_3_0_quilt_files)
580 >>> from lp.registry.interfaces.sourcepackage import SourcePackageFileType
581
582==== 1.0 ====
583
584A 1.0 source can contain either a tar.gz or an orig.tar.gz and diff.gz.
585
586 >>> list(check_format_1_0_files('foo_1.dsc', {
587 ... SourcePackageFileType.ORIG_TARBALL: 1,
588 ... SourcePackageFileType.DIFF: 1,
589 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
590 ... SourcePackageFileType.NATIVE_TARBALL: 0,
591 ... }, {}, 0))
592 []
593
594 >>> list(check_format_1_0_files('foo_1.dsc', {
595 ... SourcePackageFileType.NATIVE_TARBALL: 1,
596 ... SourcePackageFileType.ORIG_TARBALL: 0,
597 ... SourcePackageFileType.DIFF: 0,
598 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
599 ... }, {}, 0))
600 []
601
602But if we have some other combination, or bzip2 compression, errors
603will be generated.
604
605 >>> list(check_format_1_0_files('foo_1.dsc', {
606 ... SourcePackageFileType.NATIVE_TARBALL: 1,
607 ... SourcePackageFileType.ORIG_TARBALL: 1,
608 ... SourcePackageFileType.DIFF: 1,
609 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
610 ... }, {}, 1))
611 [UploadError('foo_1.dsc: is format 1.0 but uses bzip2 compression.',), UploadError('foo_1.dsc: must have exactly one tar.gz, or an orig.tar.gz and diff.gz',)]
612
613The files are also bad if there are any components:
614
615 >>> list(check_format_1_0_files('foo_1.dsc', {
616 ... SourcePackageFileType.ORIG_TARBALL: 1,
617 ... SourcePackageFileType.DIFF: 1,
618 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
619 ... SourcePackageFileType.NATIVE_TARBALL: 0,
620 ... }, {'foo': 1}, 0))
621 [UploadError('foo_1.dsc: must have exactly one tar.gz, or an orig.tar.gz and diff.gz',)]
622
623==== 3.0 (native) ====
624
625A 3.0 (native) source must contain just a tar.(gz|bz2).
626
627 >>> list(check_format_3_0_native_files('foo_1.dsc', {
628 ... SourcePackageFileType.NATIVE_TARBALL: 1,
629 ... SourcePackageFileType.ORIG_TARBALL: 0,
630 ... SourcePackageFileType.DIFF: 0,
631 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
632 ... }, {}, 1))
633 []
634
635 >>> list(check_format_3_0_native_files('foo_1.dsc', {
636 ... SourcePackageFileType.NATIVE_TARBALL: 1,
637 ... SourcePackageFileType.ORIG_TARBALL: 1,
638 ... SourcePackageFileType.DIFF: 0,
639 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
640 ... }, {}, 1))
641 [UploadError('foo_1.dsc: must have only a tar.*.',)]
642
643 >>> list(check_format_3_0_native_files('foo_1.dsc', {
644 ... SourcePackageFileType.NATIVE_TARBALL: 1,
645 ... SourcePackageFileType.ORIG_TARBALL: 0,
646 ... SourcePackageFileType.DIFF: 0,
647 ... SourcePackageFileType.DEBIAN_TARBALL: 0,
648 ... }, {'foo': 1}, 0))
649 [UploadError('foo_1.dsc: must have only a tar.*.',)]
650
651==== 3.0 (quilt) ====
652
653A 3.0 (quilt) source must have an orig.tar.*, a debian.tar.*, and at
654most one orig-COMPONENT.tar.* for each COMPONENT.
655
656 >>> list(check_format_3_0_quilt_files('foo_1.dsc', {
657 ... SourcePackageFileType.ORIG_TARBALL: 1,
658 ... SourcePackageFileType.DEBIAN_TARBALL: 1,
659 ... SourcePackageFileType.NATIVE_TARBALL: 0,
660 ... SourcePackageFileType.DIFF: 0,
661 ... }, {'foo': 1}, 1))
662 []
663
664 >>> list(check_format_3_0_quilt_files('foo_1.dsc', {
665 ... SourcePackageFileType.NATIVE_TARBALL: 1,
666 ... SourcePackageFileType.ORIG_TARBALL: 1,
667 ... SourcePackageFileType.DIFF: 0,
668 ... SourcePackageFileType.DEBIAN_TARBALL: 1,
669 ... }, {}, 1))
670 [UploadError('foo_1.dsc: must have only an orig.tar.*, a debian.tar.*, and optionally orig-*.tar.*',)]
671
672 >>> list(check_format_3_0_quilt_files('foo_1.dsc', {
673 ... SourcePackageFileType.ORIG_TARBALL: 1,
674 ... SourcePackageFileType.DEBIAN_TARBALL: 1,
675 ... SourcePackageFileType.NATIVE_TARBALL: 0,
676 ... SourcePackageFileType.DIFF: 0,
677 ... }, {'foo': 2}, 0))
678 [UploadError('foo_1.dsc: has more than one orig-foo.tar.*.',)]
679
680
509=== Sub-DSC files or DSCUploadedFiles ===681=== Sub-DSC files or DSCUploadedFiles ===
510682
511Sub-DSCFiles are DSCUploadedFile objects.683Sub-DSCFiles are DSCUploadedFile objects.
512684
=== modified file 'lib/lp/archiveuploader/tests/test_ppauploadprocessor.py'
--- lib/lp/archiveuploader/tests/test_ppauploadprocessor.py 2009-11-08 02:26:46 +0000
+++ lib/lp/archiveuploader/tests/test_ppauploadprocessor.py 2009-12-12 05:58:17 +0000
@@ -32,6 +32,8 @@
32from lp.registry.interfaces.pocket import PackagePublishingPocket32from lp.registry.interfaces.pocket import PackagePublishingPocket
33from lp.soyuz.interfaces.publishing import PackagePublishingStatus33from lp.soyuz.interfaces.publishing import PackagePublishingStatus
34from lp.soyuz.interfaces.queue import NonBuildableSourceUploadError34from lp.soyuz.interfaces.queue import NonBuildableSourceUploadError
35from lp.soyuz.interfaces.sourcepackageformat import (
36 ISourcePackageFormatSelectionSet, SourcePackageFormat)
35from canonical.launchpad.interfaces import (37from canonical.launchpad.interfaces import (
36 ILaunchpadCelebrities, ILibraryFileAliasSet, NotFoundError)38 ILaunchpadCelebrities, ILibraryFileAliasSet, NotFoundError)
37from canonical.launchpad.testing.fakepackager import FakePackager39from canonical.launchpad.testing.fakepackager import FakePackager
@@ -1161,6 +1163,51 @@
1161 self.uploadprocessor.last_processed_upload.queue_root.status,1163 self.uploadprocessor.last_processed_upload.queue_root.status,
1162 PackageUploadStatus.DONE)1164 PackageUploadStatus.DONE)
11631165
1166 def test30QuiltMultipleReusedOrigs(self):
1167 """Official orig*.tar.* can be reused for PPA uploads.
1168
1169 The 3.0 (quilt) format supports multiple original tarballs. In a
1170 PPA upload, any number of these can be reused from the primary
1171 archive.
1172 """
1173 # We need to accept unsigned .changes and .dscs, and 3.0 (quilt)
1174 # sources.
1175 self.options.context = 'absolutely-anything'
1176 getUtility(ISourcePackageFormatSelectionSet).add(
1177 self.breezy, SourcePackageFormat.FORMAT_3_0_QUILT)
1178
1179 # First upload a complete 3.0 (quilt) source to the primary
1180 # archive.
1181 upload_dir = self.queueUpload("bar_1.0-1_3.0-quilt")
1182 self.processUpload(self.uploadprocessor, upload_dir)
1183
1184 self.assertEqual(
1185 self.uploadprocessor.last_processed_upload.queue_root.status,
1186 PackageUploadStatus.NEW)
1187
1188 [queue_item] = self.breezy.getQueueItems(
1189 status=PackageUploadStatus.NEW, name="bar",
1190 version="1.0-1", exact_match=True)
1191 queue_item.setAccepted()
1192 queue_item.realiseUpload()
1193 self.layer.commit()
1194 unused = stub.test_emails.pop()
1195
1196 # Now upload a 3.0 (quilt) source with missing orig*.tar.* to a
1197 # PPA. All of the missing files will be retrieved from the
1198 # primary archive.
1199 upload_dir = self.queueUpload(
1200 "bar_1.0-2_3.0-quilt_without_orig", "~name16/ubuntu")
1201 self.assertEquals(
1202 self.processUpload(self.uploadprocessor, upload_dir),
1203 ['accepted'])
1204
1205 queue_item = self.uploadprocessor.last_processed_upload.queue_root
1206
1207 self.assertEqual(queue_item.status, PackageUploadStatus.DONE)
1208 self.assertEqual(
1209 queue_item.sources[0].sourcepackagerelease.files.count(), 5)
1210
11641211
1165class TestPPAUploadProcessorQuotaChecks(TestPPAUploadProcessorBase):1212class TestPPAUploadProcessorQuotaChecks(TestPPAUploadProcessorBase):
1166 """Functional test for uploadprocessor.py quota checks in PPA."""1213 """Functional test for uploadprocessor.py quota checks in PPA."""
11671214
=== modified file 'lib/lp/archiveuploader/tests/test_uploadprocessor.py'
--- lib/lp/archiveuploader/tests/test_uploadprocessor.py 2009-11-16 22:06:14 +0000
+++ lib/lp/archiveuploader/tests/test_uploadprocessor.py 2009-12-12 05:58:17 +0000
@@ -40,6 +40,7 @@
40from lp.registry.interfaces.distribution import IDistributionSet40from lp.registry.interfaces.distribution import IDistributionSet
41from lp.registry.interfaces.distroseries import DistroSeriesStatus41from lp.registry.interfaces.distroseries import DistroSeriesStatus
42from lp.registry.interfaces.pocket import PackagePublishingPocket42from lp.registry.interfaces.pocket import PackagePublishingPocket
43from lp.registry.interfaces.sourcepackage import SourcePackageFileType
43from lp.soyuz.interfaces.archive import ArchivePurpose, IArchiveSet44from lp.soyuz.interfaces.archive import ArchivePurpose, IArchiveSet
44from lp.soyuz.interfaces.queue import PackageUploadStatus45from lp.soyuz.interfaces.queue import PackageUploadStatus
45from lp.soyuz.interfaces.publishing import PackagePublishingStatus46from lp.soyuz.interfaces.publishing import PackagePublishingStatus
@@ -1501,6 +1502,124 @@
1501 "breezy." in raw_msg,1502 "breezy." in raw_msg,
1502 "Source was not rejected properly:\n%s" % raw_msg)1503 "Source was not rejected properly:\n%s" % raw_msg)
15031504
1505 def test30QuiltUpload(self):
1506 """Ensure that 3.0 (quilt) uploads work properly. """
1507 self.setupBreezy(
1508 permitted_formats=[SourcePackageFormat.FORMAT_3_0_QUILT])
1509 self.layer.txn.commit()
1510 self.options.context = 'absolutely-anything'
1511 uploadprocessor = UploadProcessor(
1512 self.options, self.layer.txn, self.log)
1513
1514 # Upload the source.
1515 upload_dir = self.queueUpload("bar_1.0-1_3.0-quilt")
1516 self.processUpload(uploadprocessor, upload_dir)
1517 # Make sure it went ok:
1518 from_addr, to_addrs, raw_msg = stub.test_emails.pop()
1519 self.assertTrue(
1520 "rejected" not in raw_msg,
1521 "Failed to upload bar source:\n%s" % raw_msg)
1522 spph = self._publishPackage("bar", "1.0-1")
1523
1524 self.assertEquals(
1525 sorted((sprf.libraryfile.filename, sprf.filetype)
1526 for sprf in spph.sourcepackagerelease.files),
1527 [('bar_1.0-1.debian.tar.bz2',
1528 SourcePackageFileType.DEBIAN_TARBALL),
1529 ('bar_1.0-1.dsc',
1530 SourcePackageFileType.DSC),
1531 ('bar_1.0.orig-comp1.tar.gz',
1532 SourcePackageFileType.COMPONENT_ORIG_TARBALL),
1533 ('bar_1.0.orig-comp2.tar.bz2',
1534 SourcePackageFileType.COMPONENT_ORIG_TARBALL),
1535 ('bar_1.0.orig.tar.gz',
1536 SourcePackageFileType.ORIG_TARBALL)])
1537
1538 def test30QuiltUploadWithSameComponentOrig(self):
1539 """Ensure that 3.0 (quilt) uploads with shared component origs work.
1540 """
1541 self.setupBreezy(
1542 permitted_formats=[SourcePackageFormat.FORMAT_3_0_QUILT])
1543 self.layer.txn.commit()
1544 self.options.context = 'absolutely-anything'
1545 uploadprocessor = UploadProcessor(
1546 self.options, self.layer.txn, self.log)
1547
1548 # Upload the first source.
1549 upload_dir = self.queueUpload("bar_1.0-1_3.0-quilt")
1550 self.processUpload(uploadprocessor, upload_dir)
1551 # Make sure it went ok:
1552 from_addr, to_addrs, raw_msg = stub.test_emails.pop()
1553 self.assertTrue(
1554 "rejected" not in raw_msg,
1555 "Failed to upload bar source:\n%s" % raw_msg)
1556 spph = self._publishPackage("bar", "1.0-1")
1557
1558 # Upload another source sharing the same (component) orig.
1559 upload_dir = self.queueUpload("bar_1.0-2_3.0-quilt_without_orig")
1560 self.assertEquals(
1561 self.processUpload(uploadprocessor, upload_dir), ['accepted'])
1562
1563 queue_item = uploadprocessor.last_processed_upload.queue_root
1564 self.assertEquals(
1565 sorted((sprf.libraryfile.filename, sprf.filetype) for sprf
1566 in queue_item.sources[0].sourcepackagerelease.files),
1567 [('bar_1.0-2.debian.tar.bz2',
1568 SourcePackageFileType.DEBIAN_TARBALL),
1569 ('bar_1.0-2.dsc',
1570 SourcePackageFileType.DSC),
1571 ('bar_1.0.orig-comp1.tar.gz',
1572 SourcePackageFileType.COMPONENT_ORIG_TARBALL),
1573 ('bar_1.0.orig-comp2.tar.bz2',
1574 SourcePackageFileType.COMPONENT_ORIG_TARBALL),
1575 ('bar_1.0.orig.tar.gz',
1576 SourcePackageFileType.ORIG_TARBALL)])
1577
1578 def test30NativeUpload(self):
1579 """Ensure that 3.0 (native) uploads work properly. """
1580 self.setupBreezy(
1581 permitted_formats=[SourcePackageFormat.FORMAT_3_0_NATIVE])
1582 self.layer.txn.commit()
1583 self.options.context = 'absolutely-anything'
1584 uploadprocessor = UploadProcessor(
1585 self.options, self.layer.txn, self.log)
1586
1587 # Upload the source.
1588 upload_dir = self.queueUpload("bar_1.0_3.0-native")
1589 self.processUpload(uploadprocessor, upload_dir)
1590 # Make sure it went ok:
1591 from_addr, to_addrs, raw_msg = stub.test_emails.pop()
1592 self.assertTrue(
1593 "rejected" not in raw_msg,
1594 "Failed to upload bar source:\n%s" % raw_msg)
1595 spph = self._publishPackage("bar", "1.0")
1596
1597 self.assertEquals(
1598 sorted((sprf.libraryfile.filename, sprf.filetype)
1599 for sprf in spph.sourcepackagerelease.files),
1600 [('bar_1.0.dsc',
1601 SourcePackageFileType.DSC),
1602 ('bar_1.0.tar.bz2',
1603 SourcePackageFileType.NATIVE_TARBALL)])
1604
1605 def test10Bzip2UploadIsRejected(self):
1606 """Ensure that 1.0 sources with bzip2 compression are rejected."""
1607 self.setupBreezy()
1608 self.layer.txn.commit()
1609 self.options.context = 'absolutely-anything'
1610 uploadprocessor = UploadProcessor(
1611 self.options, self.layer.txn, self.log)
1612
1613 # Upload the source.
1614 upload_dir = self.queueUpload("bar_1.0-1_1.0-bzip2")
1615 self.processUpload(uploadprocessor, upload_dir)
1616 # Make sure it was rejected.
1617 from_addr, to_addrs, raw_msg = stub.test_emails.pop()
1618 self.assertTrue(
1619 "bar_1.0-1.dsc: is format 1.0 but uses bzip2 compression."
1620 in raw_msg,
1621 "Source was not rejected properly:\n%s" % raw_msg)
1622
15041623
1505def test_suite():1624def test_suite():
1506 return unittest.TestLoader().loadTestsFromName(__name__)1625 return unittest.TestLoader().loadTestsFromName(__name__)
15071626
=== modified file 'lib/lp/archiveuploader/tests/test_utils.py'
--- lib/lp/archiveuploader/tests/test_utils.py 2009-11-17 21:38:28 +0000
+++ lib/lp/archiveuploader/tests/test_utils.py 2009-12-12 05:58:17 +0000
@@ -23,18 +23,52 @@
23 """lp.archiveuploader.utils.determine_source_file_type should work."""23 """lp.archiveuploader.utils.determine_source_file_type should work."""
24 from lp.archiveuploader.utils import determine_source_file_type24 from lp.archiveuploader.utils import determine_source_file_type
2525
26 self.assertEquals(26 # .dsc -> DSC
27 SourcePackageFileType.DSC,27 self.assertEquals(
28 determine_source_file_type('foo_1.0-1.dsc'))28 determine_source_file_type('foo_1.0-1.dsc'),
29 self.assertEquals(29 SourcePackageFileType.DSC)
30 SourcePackageFileType.DIFF,30
31 determine_source_file_type('foo_1.0-1.diff.gz'))31 # .diff.gz -> DIFF
32 self.assertEquals(32 self.assertEquals(
33 SourcePackageFileType.ORIG_TARBALL,33 determine_source_file_type('foo_1.0-1.diff.gz'),
34 determine_source_file_type('foo_1.0.orig.tar.gz'))34 SourcePackageFileType.DIFF)
35 self.assertEquals(35
36 SourcePackageFileType.NATIVE_TARBALL,36 # DIFFs can only be gzipped.
37 determine_source_file_type('foo_1.0.tar.gz'))37 self.assertEquals(
38 determine_source_file_type('foo_1.0.diff.bz2'), None)
39
40 # Plain original tarballs can be gzipped or bzip2ed.
41 self.assertEquals(
42 determine_source_file_type('foo_1.0.orig.tar.gz'),
43 SourcePackageFileType.ORIG_TARBALL)
44 self.assertEquals(
45 determine_source_file_type('foo_1.0.orig.tar.bz2'),
46 SourcePackageFileType.ORIG_TARBALL)
47
48 # Component original tarballs too.
49 self.assertEquals(
50 determine_source_file_type('foo_1.0.orig-foo.tar.gz'),
51 SourcePackageFileType.COMPONENT_ORIG_TARBALL)
52 self.assertEquals(
53 determine_source_file_type('foo_1.0.orig-bar.tar.bz2'),
54 SourcePackageFileType.COMPONENT_ORIG_TARBALL)
55
56 # And Debian tarballs...
57 self.assertEquals(
58 determine_source_file_type('foo_1.0-1.debian.tar.gz'),
59 SourcePackageFileType.DEBIAN_TARBALL)
60 self.assertEquals(
61 determine_source_file_type('foo_1.0-2.debian.tar.bz2'),
62 SourcePackageFileType.DEBIAN_TARBALL)
63
64 # And even native tarballs!
65 self.assertEquals(
66 determine_source_file_type('foo_1.0.tar.gz'),
67 SourcePackageFileType.NATIVE_TARBALL)
68 self.assertEquals(
69 determine_source_file_type('foo_1.0.tar.bz2'),
70 SourcePackageFileType.NATIVE_TARBALL)
71
38 self.assertEquals(None, determine_source_file_type('foo_1.0'))72 self.assertEquals(None, determine_source_file_type('foo_1.0'))
39 self.assertEquals(None, determine_source_file_type('foo_1.0.blah.gz'))73 self.assertEquals(None, determine_source_file_type('foo_1.0.blah.gz'))
4074
4175
=== modified file 'lib/lp/archiveuploader/uploadpolicy.py'
--- lib/lp/archiveuploader/uploadpolicy.py 2009-11-05 21:57:35 +0000
+++ lib/lp/archiveuploader/uploadpolicy.py 2009-12-12 05:58:17 +0000
@@ -373,6 +373,10 @@
373 """Nothing, let it go."""373 """Nothing, let it go."""
374 pass374 pass
375375
376 def rejectPPAUploads(self, upload):
377 """We allow PPA uploads."""
378 return False
379
376AbstractUploadPolicy._registerPolicy(AnythingGoesUploadPolicy)380AbstractUploadPolicy._registerPolicy(AnythingGoesUploadPolicy)
377381
378382
379383
=== modified file 'lib/lp/archiveuploader/utils.py'
--- lib/lp/archiveuploader/utils.py 2009-11-11 21:50:56 +0000
+++ lib/lp/archiveuploader/utils.py 2009-12-12 05:58:17 +0000
@@ -9,6 +9,7 @@
9 're_taint_free',9 're_taint_free',
10 're_isadeb',10 're_isadeb',
11 're_issource',11 're_issource',
12 're_is_component_orig_tar_ext',
12 're_no_epoch',13 're_no_epoch',
13 're_no_revision',14 're_no_revision',
14 're_valid_version',15 're_valid_version',
@@ -34,13 +35,15 @@
3435
35re_isadeb = re.compile(r"(.+?)_(.+?)_(.+)\.(u?d?deb)$")36re_isadeb = re.compile(r"(.+?)_(.+?)_(.+)\.(u?d?deb)$")
3637
37source_file_exts = ['orig.tar.gz', 'diff.gz', 'tar.gz', 'dsc']38source_file_exts = [
39 'orig(?:-.+)?\.tar\.(?:gz|bz2)', 'diff.gz',
40 '(?:debian\.)?tar\.(?:gz|bz2)', 'dsc']
38re_issource = re.compile(41re_issource = re.compile(
39 r"(.+)_(.+?)\.(%s)" % "|".join(42 r"(.+)_(.+?)\.(%s)" % "|".join(ext for ext in source_file_exts))
40 re.escape(ext) for ext in source_file_exts))43re_is_component_orig_tar_ext = re.compile(r"^orig-(.+).tar.(?:gz|bz2)$")
4144re_is_orig_tar_ext = re.compile(r"^orig.tar.(?:gz|bz2)$")
42re_is_orig_tar_ext = re.compile(r"^orig.tar.gz$")45re_is_debian_tar_ext = re.compile(r"^debian.tar.(?:gz|bz2)$")
43re_is_native_tar_ext = re.compile(r"^tar.gz$")46re_is_native_tar_ext = re.compile(r"^tar.(?:gz|bz2)$")
4447
45re_no_epoch = re.compile(r"^\d+\:")48re_no_epoch = re.compile(r"^\d+\:")
46re_no_revision = re.compile(r"-[^-]+$")49re_no_revision = re.compile(r"-[^-]+$")
@@ -75,6 +78,10 @@
75 return SourcePackageFileType.DIFF78 return SourcePackageFileType.DIFF
76 elif re_is_orig_tar_ext.match(extension):79 elif re_is_orig_tar_ext.match(extension):
77 return SourcePackageFileType.ORIG_TARBALL80 return SourcePackageFileType.ORIG_TARBALL
81 elif re_is_component_orig_tar_ext.match(extension):
82 return SourcePackageFileType.COMPONENT_ORIG_TARBALL
83 elif re_is_debian_tar_ext.match(extension):
84 return SourcePackageFileType.DEBIAN_TARBALL
78 elif re_is_native_tar_ext.match(extension):85 elif re_is_native_tar_ext.match(extension):
79 return SourcePackageFileType.NATIVE_TARBALL86 return SourcePackageFileType.NATIVE_TARBALL
80 else:87 else:
8188
=== modified file 'lib/lp/registry/interfaces/sourcepackage.py'
--- lib/lp/registry/interfaces/sourcepackage.py 2009-11-21 08:56:44 +0000
+++ lib/lp/registry/interfaces/sourcepackage.py 2009-12-12 05:58:17 +0000
@@ -310,7 +310,9 @@
310 This is an Ubuntu "diff" file, containing changes that need to be310 This is an Ubuntu "diff" file, containing changes that need to be
311 made to upstream code for the packaging on Ubuntu. Typically this311 made to upstream code for the packaging on Ubuntu. Typically this
312 diff creates additional directories with patches and documentation312 diff creates additional directories with patches and documentation
313 used to build the binary packages for Ubuntu. """)313 used to build the binary packages for Ubuntu.
314
315 This is only part of the 1.0 source package format.""")
314316
315 NATIVE_TARBALL = DBItem(6, """317 NATIVE_TARBALL = DBItem(6, """
316 Native Tarball318 Native Tarball
@@ -318,6 +320,22 @@
318 This is a tarball, usually of a mixture of Ubuntu and upstream code,320 This is a tarball, usually of a mixture of Ubuntu and upstream code,
319 used in the build process for this source package. """)321 used in the build process for this source package. """)
320322
323 DEBIAN_TARBALL = DBItem(7, """
324 Debian Tarball
325
326 This file is an Ubuntu "orig" file, typically an upstream tarball or
327 other lightly-modified upstreamish thing.
328
329 This is only part of the 3.0 (quilt) source package format.""")
330
331 COMPONENT_ORIG_TARBALL = DBItem(8, """
332 Component Orig Tarball
333
334 This file is an Ubuntu component "orig" file, typically an upstream
335 tarball containing a component of the source package.
336
337 This is only part of the 3.0 (quilt) source package format.""")
338
321339
322class SourcePackageType(DBEnumeratedType):340class SourcePackageType(DBEnumeratedType):
323 """Source Package Format341 """Source Package Format
324342
=== modified file 'lib/lp/soyuz/interfaces/files.py'
--- lib/lp/soyuz/interfaces/files.py 2009-06-25 04:06:00 +0000
+++ lib/lp/soyuz/interfaces/files.py 2009-12-12 05:58:17 +0000
@@ -14,7 +14,7 @@
14 'ISourcePackageReleaseFileSet',14 'ISourcePackageReleaseFileSet',
15 ]15 ]
1616
17from zope.schema import Int17from zope.schema import Bool, Int
18from zope.interface import Interface18from zope.interface import Interface
19from canonical.launchpad import _19from canonical.launchpad import _
2020
@@ -68,6 +68,11 @@
68 title=_('The type of this file'), required=True, readonly=False,68 title=_('The type of this file'), required=True, readonly=False,
69 )69 )
7070
71 is_orig = Bool(
72 title=_('Whether this file is an original tarball'),
73 required=True, readonly=False,
74 )
75
7176
72class ISourcePackageReleaseFileSet(Interface):77class ISourcePackageReleaseFileSet(Interface):
73 """The set of all `SourcePackageRelease`s."""78 """The set of all `SourcePackageRelease`s."""
7479
=== modified file 'lib/lp/soyuz/model/files.py'
--- lib/lp/soyuz/model/files.py 2009-06-25 04:06:00 +0000
+++ lib/lp/soyuz/model/files.py 2009-12-12 05:58:17 +0000
@@ -60,7 +60,18 @@
60 "binarypackagerelease.binarypackagename"])60 "binarypackagerelease.binarypackagename"])
6161
6262
63class SourcePackageReleaseFile(SQLBase):63class SourceFileMixin:
64 """Mix-in class for common functionality between source file classes."""
65
66 @property
67 def is_orig(self):
68 return self.filetype in (
69 SourcePackageFileType.ORIG_TARBALL,
70 SourcePackageFileType.COMPONENT_ORIG_TARBALL
71 )
72
73
74class SourcePackageReleaseFile(SourceFileMixin, SQLBase):
64 """See ISourcePackageFile"""75 """See ISourcePackageFile"""
6576
66 implements(ISourcePackageReleaseFile)77 implements(ISourcePackageReleaseFile)
@@ -90,4 +101,3 @@
90 prejoins=["libraryfile", "libraryfile.content",101 prejoins=["libraryfile", "libraryfile.content",
91 "sourcepackagerelease",102 "sourcepackagerelease",
92 "sourcepackagerelease.sourcepackagename"])103 "sourcepackagerelease.sourcepackagename"])
93
94104
=== modified file 'lib/lp/soyuz/model/queue.py'
--- lib/lp/soyuz/model/queue.py 2009-12-07 10:04:25 +0000
+++ lib/lp/soyuz/model/queue.py 2009-12-12 05:58:17 +0000
@@ -61,7 +61,6 @@
61 NonBuildableSourceUploadError, QueueBuildAcceptError,61 NonBuildableSourceUploadError, QueueBuildAcceptError,
62 QueueInconsistentStateError, QueueSourceAcceptError,62 QueueInconsistentStateError, QueueSourceAcceptError,
63 QueueStateWriteProtectedError)63 QueueStateWriteProtectedError)
64from lp.registry.interfaces.sourcepackage import SourcePackageFileType
65from canonical.launchpad.mail import (64from canonical.launchpad.mail import (
66 format_address, signed_message_from_string, sendmail)65 format_address, signed_message_from_string, sendmail)
67from lp.soyuz.scripts.processaccepted import (66from lp.soyuz.scripts.processaccepted import (
@@ -1471,8 +1470,7 @@
1471 published_sha1 = published_file.content.sha11470 published_sha1 = published_file.content.sha1
14721471
1473 # Multiple orig(s) with the same content are fine.1472 # Multiple orig(s) with the same content are fine.
1474 if source_file.filetype == (1473 if source_file.is_orig:
1475 SourcePackageFileType.ORIG_TARBALL):
1476 if proposed_sha1 == published_sha1:1474 if proposed_sha1 == published_sha1:
1477 continue1475 continue
1478 raise QueueInconsistentStateError(1476 raise QueueInconsistentStateError(

Subscribers

People subscribed via source and target branches

to status/vote changes: