launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #00640
[Merge] lp:~jelmer/launchpad/613468-xb-ppa into lp:launchpad
Jelmer Vernooij has proposed merging lp:~jelmer/launchpad/613468-xb-ppa into lp:launchpad with lp:~jelmer/launchpad/nascentuploadfile-tests as a prerequisite.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers): code
This branch makes us write user-defined fields into Packages and Sources files.
To do this we need to do two things:
- when parsing newly uploaded files the custom upload fields need to be stored in the
database.
- when generating Sources and Packages files, write out the custom user fields
--
https://code.launchpad.net/~jelmer/launchpad/613468-xb-ppa/+merge/32908
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jelmer/launchpad/613468-xb-ppa into lp:launchpad.
=== modified file 'lib/lp/archiveuploader/dscfile.py'
--- lib/lp/archiveuploader/dscfile.py 2010-08-17 18:15:59 +0000
+++ lib/lp/archiveuploader/dscfile.py 2010-08-17 18:16:00 +0000
@@ -152,6 +152,16 @@
"architecture",
"files"])
+ known_fields = mandatory_fields.union(set([
+ "build-depends",
+ "build-depends-indep",
+ "build-conflicts",
+ "build-conflicts-indep",
+ "format",
+ "standards-version",
+ "filecontents",
+ ]))
+
# Note that files is actually only set inside verify().
files = None
# Copyright and changelog_path are only set inside unpackAndCheckSource().
@@ -626,6 +636,9 @@
source_name = getUtility(
ISourcePackageNameSet).getOrCreateByName(self.source)
+ user_defined_fields = self.extractUserDefinedFields([
+ (field, encoded[field]) for field in self._dict])
+
release = self.policy.distroseries.createUploadedSourcePackageRelease(
sourcepackagename=source_name,
version=self.dsc_version,
@@ -651,6 +664,7 @@
source_package_recipe_build=build,
copyright=encoded.get('copyright'),
# dateuploaded by default is UTC:now in the database
+ user_defined_fields=user_defined_fields,
)
# SourcePackageFiles should contain also the DSC
=== modified file 'lib/lp/archiveuploader/nascentuploadfile.py'
--- lib/lp/archiveuploader/nascentuploadfile.py 2010-08-17 18:15:59 +0000
+++ lib/lp/archiveuploader/nascentuploadfile.py 2010-08-17 18:16:00 +0000
@@ -331,6 +331,12 @@
"""Return an ISection for self.section_name."""
return getUtility(ISectionSet)[self.section_name]
+ def extractUserDefinedFields(self, control):
+ """Extract the user defined fields out of a control file list.
+ """
+ return [(field, contents) for (field, contents) in
+ control if field not in self.known_fields]
+
class SourceUploadFile(SourceFileMixin, PackageUploadFile):
"""Files mentioned in changesfile as source (orig, diff, tar).
@@ -376,6 +382,25 @@
# Capitalised because we extract these directly from the control file.
mandatory_fields = set(["Package", "Architecture", "Version"])
+ known_fields = mandatory_fields.union(set([
+ "Depends",
+ "Conflicts",
+ "Breaks",
+ "Recommends",
+ "Suggests",
+ "Replaces",
+ "Provides",
+ "Pre-Depends",
+ "Enhances",
+ "Essential",
+ "Description",
+ "Installed-Size",
+ "Priority",
+ "Section",
+ "Maintainer",
+ "Source",
+ ]))
+
# Map priorities to their dbschema valuesa
# We treat a priority of '-' as EXTRA since some packages in some distros
# are broken and we can't fix the world.
@@ -873,6 +898,9 @@
else:
debug_package = None
+ user_defined_fields = self.extractUserDefinedFields(
+ [(field, encoded[field]) for field in self.control])
+
binary = build.createBinaryPackageRelease(
binarypackagename=binary_name,
version=self.control_version,
@@ -895,6 +923,7 @@
essential=is_essential,
installedsize=installedsize,
architecturespecific=architecturespecific,
+ user_defined_fields=user_defined_fields,
debug_package=debug_package)
library_file = self.librarian.create(self.filename,
=== modified file 'lib/lp/archiveuploader/tests/__init__.py'
--- lib/lp/archiveuploader/tests/__init__.py 2010-08-06 13:52:46 +0000
+++ lib/lp/archiveuploader/tests/__init__.py 2010-08-17 18:16:00 +0000
@@ -8,7 +8,7 @@
__metaclass__ = type
__all__ = ['datadir', 'getPolicy', 'insertFakeChangesFile',
- 'insertFakeChangesFileForAllPackageUploads', 'mock_options',
+ 'insertFakeChangesFileForAllPackageUploads',
'mock_logger', 'mock_logger_quiet']
import os
@@ -98,6 +98,5 @@
self.print_traceback(exc_info)
-mock_options = MockUploadOptions()
mock_logger = MockUploadLogger()
mock_logger_quiet = MockUploadLogger(verbose=False)
=== modified file 'lib/lp/archiveuploader/tests/test_nascentuploadfile.py'
--- lib/lp/archiveuploader/tests/test_nascentuploadfile.py 2010-08-17 18:15:59 +0000
+++ lib/lp/archiveuploader/tests/test_nascentuploadfile.py 2010-08-17 18:16:00 +0000
@@ -175,6 +175,22 @@
self.assertEquals("0.42", release.version)
self.assertEquals("dpkg, bzr", release.builddepends)
+ def test_user_defined_fields(self):
+ # Test that storeInDatabase updates user_defined_fields.
+ dsc = self.getBaseDsc()
+ dsc["Python-Version"] = "2.5"
+ changes = self.getBaseChanges()
+ uploadfile = self.createDSCFile(
+ "foo.dsc", dsc, "main/net", "extra", "dulwich", "0.42",
+ self.createChangesFile("foo.changes", changes))
+ (uploadfile.changelog_path, changelog_digest, changelog_size) = (
+ self.writeUploadFile("changelog", "DUMMY"))
+ uploadfile.files = []
+ release = uploadfile.storeInDatabase(None)
+ # DSCFile lowercases the field names
+ self.assertEquals(
+ [["python-version", u"2.5"]], release.user_defined_fields)
+
class DebBinaryUploadFileTests(PackageUploadFileTestCase):
"""Tests for DebBinaryUploadFile."""
@@ -241,5 +257,19 @@
self.assertEquals(False, bpr.essential)
self.assertEquals(524, bpr.installedsize)
self.assertEquals(True, bpr.architecturespecific)
- self.assertEquals(None, bpr.recommends)
+ self.assertEquals("", bpr.recommends)
self.assertEquals("0.42", bpr.version)
+
+ def test_user_defined_fields(self):
+ # Test that storeInDatabase stores user defined fields
+ uploadfile = self.createDebBinaryUploadFile(
+ "foo_0.42_i386.deb", "main/python", "unknown", "mypkg", "0.42",
+ None)
+ control = self.getBaseControl()
+ control["Python-Version"] = "2.5"
+ uploadfile.parseControl(control)
+ build = self.factory.makeBinaryPackageBuild()
+ bpr = uploadfile.storeInDatabase(build)
+ self.assertEquals(
+ [[u"Homepage", u"http://samba.org/~jelmer/dulwich"],
+ [u"Python-Version", u"2.5"]], bpr.user_defined_fields)
=== modified file 'lib/lp/soyuz/model/publishing.py'
--- lib/lp/soyuz/model/publishing.py 2010-08-03 08:49:19 +0000
+++ lib/lp/soyuz/model/publishing.py 2010-08-17 18:16:00 +0000
@@ -325,6 +325,12 @@
"""
self.fields.append((name, value))
+ def extend(self, entries):
+ """Extend the internal list with the key-value pairs in entries.
+
+ """
+ self.fields.extend(entries)
+
def makeOutput(self):
"""Return a line-by-line aggregation of appended fields.
@@ -672,6 +678,8 @@
fields.append('Format', spr.dsc_format)
fields.append('Directory', pool_path)
fields.append('Files', files_subsection)
+ if spr.user_defined_fields:
+ fields.extend(spr.user_defined_fields)
return fields
@@ -941,6 +949,8 @@
fields.append('MD5sum', bin_md5)
fields.append('SHA1', bin_sha1)
fields.append('Description', bin_description)
+ if bpr.user_defined_fields:
+ fields.extend(bpr.user_defined_fields)
# XXX cprov 2006-11-03: the extra override fields (Bugs, Origin and
# Task) included in the template be were not populated.
=== modified file 'lib/lp/soyuz/tests/test_publish_archive_indexes.py'
--- lib/lp/soyuz/tests/test_publish_archive_indexes.py 2010-07-20 12:06:36 +0000
+++ lib/lp/soyuz/tests/test_publish_archive_indexes.py 2010-08-17 18:16:00 +0000
@@ -8,6 +8,8 @@
import tempfile
import unittest
+from lp.soyuz.model.publishing import IndexStanzaFields
+
from lp.soyuz.tests.test_publishing import TestNativePublishingBase
@@ -52,6 +54,34 @@
u' 5913c3ad52c14a62e6ae7eef51f9ef42 28 foo_666.dsc'],
pub_source.getIndexStanza().splitlines())
+ def testSourceStanzaCustomFields(self):
+ """Check just-created source publication Index stanza
+ with custom fields (Python-Version).
+ """
+ pub_source = self.getPubSource(
+ builddepends='fooish', builddependsindep='pyfoo',
+ build_conflicts='bar', build_conflicts_indep='pybar',
+ user_defined_fields=[("Python-Version", "< 1.5")])
+
+ self.assertEqual(
+ [u'Package: foo',
+ u'Binary: foo-bin',
+ u'Version: 666',
+ u'Section: base',
+ u'Maintainer: Foo Bar <foo@xxxxxxx>',
+ u'Build-Depends: fooish',
+ u'Build-Depends-Indep: pyfoo',
+ u'Build-Conflicts: bar',
+ u'Build-Conflicts-Indep: pybar',
+ u'Architecture: all',
+ u'Standards-Version: 3.6.2',
+ u'Format: 1.0',
+ u'Directory: pool/main/f/foo',
+ u'Files:',
+ u' 5913c3ad52c14a62e6ae7eef51f9ef42 28 foo_666.dsc',
+ u'Python-Version: < 1.5'],
+ pub_source.getIndexStanza().splitlines())
+
def testBinaryStanza(self):
"""Check just-created binary publication Index stanza.
@@ -90,6 +120,45 @@
u' it does nothing, though'],
pub_binary.getIndexStanza().splitlines())
+ def testBinaryStanzaWithCustomFields(self):
+ """Check just-created binary publication Index stanza with
+ custom fields (Python-Version).
+
+ """
+ pub_binaries = self.getPubBinaries(
+ depends='biscuit', recommends='foo-dev', suggests='pyfoo',
+ conflicts='old-foo', replaces='old-foo', provides='foo-master',
+ pre_depends='master-foo', enhances='foo-super', breaks='old-foo',
+ user_defined_fields=[("Python-Version", ">= 2.4")])
+ pub_binary = pub_binaries[0]
+ self.assertEqual(
+ [u'Package: foo-bin',
+ u'Source: foo',
+ u'Priority: standard',
+ u'Section: base',
+ u'Installed-Size: 100',
+ u'Maintainer: Foo Bar <foo@xxxxxxx>',
+ u'Architecture: all',
+ u'Version: 666',
+ u'Recommends: foo-dev',
+ u'Replaces: old-foo',
+ u'Suggests: pyfoo',
+ u'Provides: foo-master',
+ u'Depends: biscuit',
+ u'Conflicts: old-foo',
+ u'Pre-Depends: master-foo',
+ u'Enhances: foo-super',
+ u'Breaks: old-foo',
+ u'Filename: pool/main/f/foo/foo-bin_666_all.deb',
+ u'Size: 18',
+ u'MD5sum: 008409e7feb1c24a6ccab9f6a62d24c5',
+ u'SHA1: 30b7b4e583fa380772c5a40e428434628faef8cf',
+ u'Description: Foo app is great',
+ u' Well ...',
+ u' it does nothing, though',
+ u'Python-Version: >= 2.4'],
+ pub_binary.getIndexStanza().splitlines())
+
def testBinaryStanzaDescription(self):
""" Check the description field.
@@ -301,18 +370,16 @@
class TestIndexStanzaFieldsHelper(unittest.TestCase):
-
- def testIndexStanzaFields(self):
- """Check how this auxiliary class works...
-
- This class provides simple FIFO API for aggregating fields
- (name & values) in a ordered way.
-
- Provides an method to format the option in a ready-to-use string.
- """
- # Avoid circular imports.
- from lp.soyuz.model.publishing import IndexStanzaFields
-
+ """Check how this auxiliary class works...
+
+ This class provides simple FIFO API for aggregating fields
+ (name & values) in a ordered way.
+
+ Provides an method to format the option in a ready-to-use string.
+ """
+
+
+ def test_simple(self):
fields = IndexStanzaFields()
fields.append('breakfast', 'coffee')
fields.append('lunch', 'beef')
@@ -324,15 +391,18 @@
['breakfast: coffee', 'lunch: beef', 'dinner: fish',
], fields.makeOutput().splitlines())
+ def test_preserves_order(self):
fields = IndexStanzaFields()
fields.append('one', 'um')
fields.append('three', 'tres')
fields.append('two', 'dois')
+ fields.append(None, None)
self.assertEqual(
['one: um', 'three: tres', 'two: dois',
], fields.makeOutput().splitlines())
+ def test_files(self):
# Special treatment for field named 'Files'
# do not add a space between <name>:<value>
# <value> will always start with a new line.
@@ -342,3 +412,12 @@
self.assertEqual(
['one: um', 'Files:<no_sep>'], fields.makeOutput().splitlines())
+
+ def test_extend(self):
+ fields = IndexStanzaFields()
+ fields.append('one', 'um')
+ fields.extend([('three', 'tres'), ['four', 'five']])
+
+ self.assertEqual(
+ ['one: um', 'three: tres', 'four: five',
+ ], fields.makeOutput().splitlines())
=== modified file 'lib/lp/soyuz/tests/test_publishing.py'
--- lib/lp/soyuz/tests/test_publishing.py 2010-08-12 14:03:47 +0000
+++ lib/lp/soyuz/tests/test_publishing.py 2010-08-17 18:16:00 +0000
@@ -47,8 +47,7 @@
from lp.soyuz.interfaces.queue import PackageUploadStatus
from canonical.launchpad.scripts import FakeLogger
from lp.testing import TestCaseWithFactory
-from lp.testing.factory import (
- LaunchpadObjectFactory, remove_security_proxy_and_shout_at_engineer)
+from lp.testing.factory import LaunchpadObjectFactory
from lp.testing.fakemethod import FakeMethod
@@ -172,7 +171,7 @@
build_conflicts_indep=None,
dsc_maintainer_rfc822='Foo Bar <foo@xxxxxxx>',
maintainer=None, creator=None, date_uploaded=UTC_NOW,
- spr_only=False):
+ spr_only=False, user_defined_fields=None):
"""Return a mock source publishing record.
if spr_only is specified, the source is not published and the
@@ -216,7 +215,8 @@
dsc_standards_version=dsc_standards_version,
dsc_format=dsc_format,
dsc_binaries=dsc_binaries,
- archive=archive, dateuploaded=date_uploaded)
+ archive=archive, dateuploaded=date_uploaded,
+ user_defined_fields=user_defined_fields)
changes_file_name = "%s_%s_source.changes" % (sourcename, version)
if spr_only:
@@ -279,7 +279,7 @@
architecturespecific=False,
builder=None,
component='main',
- with_debug=False):
+ with_debug=False, user_defined_fields=None):
"""Return a list of binary publishing records."""
if distroseries is None:
distroseries = self.distroseries
@@ -323,7 +323,8 @@
build, binaryname, filecontent, summary, description,
shlibdep, depends, recommends, suggests, conflicts, replaces,
provides, pre_depends, enhances, breaks, format,
- binarypackagerelease_ddeb)
+ binarypackagerelease_ddeb,
+ user_defined_fields=user_defined_fields)
pub_binaries += self.publishBinaryInArchive(
binarypackagerelease, archive, status, pocket,
scheduleddeletiondate, dateremoved)
@@ -344,7 +345,8 @@
summary="summary", description="description", shlibdep=None,
depends=None, recommends=None, suggests=None, conflicts=None,
replaces=None, provides=None, pre_depends=None, enhances=None,
- breaks=None, format=BinaryPackageFormat.DEB, debug_package=None):
+ breaks=None, format=BinaryPackageFormat.DEB, debug_package=None,
+ user_defined_fields=None):
"""Return the corresponding `BinaryPackageRelease`."""
sourcepackagerelease = build.source_package_release
distroarchseries = build.distro_arch_series
@@ -376,7 +378,8 @@
architecturespecific=architecturespecific,
binpackageformat=format,
priority=PackagePublishingPriority.STANDARD,
- debug_package=debug_package)
+ debug_package=debug_package,
+ user_defined_fields=user_defined_fields)
# Create the corresponding binary file.
if architecturespecific: