Merge lp:~cjwatson/launchpad/gina-user-defined-fields into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 17516
Proposed branch: lp:~cjwatson/launchpad/gina-user-defined-fields
Merge into: lp:launchpad
Diff against target: 264 lines (+124/-7)
3 files modified
lib/lp/soyuz/scripts/gina/handlers.py (+10/-3)
lib/lp/soyuz/scripts/gina/packages.py (+24/-3)
lib/lp/soyuz/scripts/tests/test_gina.py (+90/-1)
To merge this branch: bzr merge lp:~cjwatson/launchpad/gina-user-defined-fields
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+259602@code.launchpad.net

Commit message

Make gina import user-defined fields.

Description of the change

Make gina import user-defined fields.

Ideally this would use much more of archiveuploader, but for now I at least arranged to use the sets of known fields encoded there. We have to take account of Packages/Sources files having a few extra fields.

The name of the new set_field method doesn't fit LP style, but I was fitting in with the rest of the file in question.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/soyuz/scripts/gina/handlers.py'
2--- lib/lp/soyuz/scripts/gina/handlers.py 2014-10-31 06:37:14 +0000
3+++ lib/lp/soyuz/scripts/gina/handlers.py 2015-05-20 11:49:53 +0000
4@@ -1,4 +1,4 @@
5-# Copyright 2009-2014 Canonical Ltd. This software is licensed under the
6+# Copyright 2009-2015 Canonical Ltd. This software is licensed under the
7 # GNU Affero General Public License version 3 (see the file LICENSE).
8
9 """Gina db handlers.
10@@ -606,6 +606,9 @@
11 sectionID = self.distro_handler.ensureSection(src.section).id
12 maintainer_line = "%s <%s>" % (displayname, emailaddress)
13 name = self.ensureSourcePackageName(src.package)
14+ kwargs = {}
15+ if src._user_defined:
16+ kwargs["user_defined_fields"] = src._user_defined
17 spr = SourcePackageRelease(
18 section=sectionID,
19 creator=maintainer.id,
20@@ -630,7 +633,8 @@
21 dsc_maintainer_rfc822=maintainer_line,
22 dsc_standards_version=src.standards_version,
23 dsc_binaries=", ".join(src.binaries),
24- upload_archive=distroseries.main_archive)
25+ upload_archive=distroseries.main_archive,
26+ **kwargs)
27 log.info('Source Package Release %s (%s) created' %
28 (name.name, src.version))
29
30@@ -787,6 +791,9 @@
31 build = self.ensureBuild(bin, srcpkg, distroarchseries, archtag)
32
33 # Create the binarypackage entry on lp db.
34+ kwargs = {}
35+ if bin._user_defined:
36+ kwargs["user_defined_fields"] = bin._user_defined
37 binpkg = BinaryPackageRelease(
38 binarypackagename=bin_name.id,
39 component=componentID,
40@@ -810,7 +817,7 @@
41 essential=bin.essential,
42 installedsize=bin.installed_size,
43 architecturespecific=architecturespecific,
44- )
45+ **kwargs)
46 log.info('Binary Package Release %s (%s) created' %
47 (bin_name.name, bin.version))
48
49
50=== modified file 'lib/lp/soyuz/scripts/gina/packages.py'
51--- lib/lp/soyuz/scripts/gina/packages.py 2013-05-22 09:51:08 +0000
52+++ lib/lp/soyuz/scripts/gina/packages.py 2015-05-20 11:49:53 +0000
53@@ -1,4 +1,4 @@
54-# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
55+# Copyright 2009-2015 Canonical Ltd. This software is licensed under the
56 # GNU Affero General Public License version 3 (see the file LICENSE).
57
58 """Package information classes.
59@@ -31,6 +31,8 @@
60 from lp.app.validators.version import valid_debian_version
61 from lp.archivepublisher.diskpool import poolify
62 from lp.archiveuploader.changesfile import ChangesFile
63+from lp.archiveuploader.dscfile import DSCFile
64+from lp.archiveuploader.nascentuploadfile import BaseBinaryUploadFile
65 from lp.archiveuploader.utils import (
66 DpkgSourceError,
67 extract_dpkg_source,
68@@ -210,6 +212,7 @@
69 archive_root = None
70 package = None
71 _required = None
72+ _user_defined = None
73 version = None
74
75 # Component is something of a special case. It is set up in
76@@ -251,6 +254,20 @@
77 self.date_uploaded = UTC_NOW
78 return True
79
80+ def set_field(self, key, value):
81+ """Record an arbitrary control field."""
82+ lowkey = key.lower()
83+ # _known_fields contains the fields that archiveuploader recognises
84+ # from a raw .dsc or .*deb; _required contains a few extra fields
85+ # that are added to Sources and Packages index files. If a field is
86+ # in neither, it counts as user-defined.
87+ if lowkey in self._known_fields or lowkey in self._required:
88+ setattr(self, lowkey.replace("-", "_"), value)
89+ else:
90+ if self._user_defined is None:
91+ self._user_defined = []
92+ self._user_defined.append([key, value])
93+
94 def do_package(self, distro_name, archive_root):
95 """To be provided by derived class."""
96 raise NotImplementedError
97@@ -286,6 +303,8 @@
98 'component',
99 ]
100
101+ _known_fields = set(k.lower() for k in DSCFile.known_fields)
102+
103 def __init__(self, **args):
104 for k, v in args.items():
105 if k == 'Binary':
106@@ -318,7 +337,7 @@
107 for f in files:
108 self.files.append(stripseq(f.split(" ")))
109 else:
110- setattr(self, k.lower().replace("-", "_"), v)
111+ self.set_field(k, v)
112
113 if self.section is None:
114 self.section = 'misc'
115@@ -405,6 +424,8 @@
116 'priority',
117 ]
118
119+ _known_fields = set(k.lower() for k in BaseBinaryUploadFile.known_fields)
120+
121 # Set in __init__
122 source = None
123 source_version = None
124@@ -452,7 +473,7 @@
125 raise MissingRequiredArguments("Installed-Size is "
126 "not a valid integer: %r" % v)
127 else:
128- setattr(self, k.lower().replace("-", "_"), v)
129+ self.set_field(k, v)
130
131 if self.source:
132 # We need to handle cases like "Source: myspell
133
134=== modified file 'lib/lp/soyuz/scripts/tests/test_gina.py'
135--- lib/lp/soyuz/scripts/tests/test_gina.py 2013-10-18 04:33:58 +0000
136+++ lib/lp/soyuz/scripts/tests/test_gina.py 2015-05-20 11:49:53 +0000
137@@ -1,4 +1,4 @@
138-# Copyright 2009-2013 Canonical Ltd. This software is licensed under the
139+# Copyright 2009-2015 Canonical Ltd. This software is licensed under the
140 # GNU Affero General Public License version 3 (see the file LICENSE).
141
142 from doctest import DocTestSuite
143@@ -12,9 +12,11 @@
144 from lp.archiveuploader.tagfiles import parse_tagfile
145 from lp.registry.interfaces.pocket import PackagePublishingPocket
146 from lp.registry.interfaces.series import SeriesStatus
147+from lp.services.database.constants import UTC_NOW
148 from lp.services.features.testing import FeatureFixture
149 from lp.services.log.logger import DevNullLogger
150 from lp.services.tarfile_helpers import LaunchpadWriteTarFile
151+from lp.services.osutils import write_file
152 from lp.soyuz.enums import PackagePublishingStatus
153 from lp.soyuz.scripts.gina import ExecutionError
154 from lp.soyuz.scripts.gina.archive import (
155@@ -24,8 +26,10 @@
156 from lp.soyuz.scripts.gina.dominate import dominate_imported_source_packages
157 import lp.soyuz.scripts.gina.handlers
158 from lp.soyuz.scripts.gina.handlers import (
159+ BinaryPackageHandler,
160 BinaryPackagePublisher,
161 ImporterHandler,
162+ SourcePackageHandler,
163 SourcePackagePublisher,
164 )
165 from lp.soyuz.scripts.gina.packages import (
166@@ -223,6 +227,49 @@
167 sp_data.do_package("debian", archive_root)
168
169
170+class TestSourcePackageHandler(TestCaseWithFactory):
171+
172+ layer = LaunchpadZopelessLayer
173+
174+ def test_user_defined_fields(self):
175+ series = self.factory.makeDistroSeries()
176+ archive_root = self.useTempDir()
177+ sphandler = SourcePackageHandler(
178+ series.distribution.name, archive_root,
179+ PackagePublishingPocket.RELEASE, None)
180+ dsc_contents = {
181+ "Format": "3.0 (quilt)",
182+ "Source": "foo",
183+ "Binary": "foo",
184+ "Architecture": "all arm64",
185+ "Version": "1.0-1",
186+ "Maintainer": "Foo Bar <foo@canonical.com>",
187+ "Files": "xxx 000 foo_1.0-1.dsc",
188+ "Build-Indep-Architecture": "amd64",
189+ "Directory": "pool/main/f/foo",
190+ "Package": "foo",
191+ "Component": "main",
192+ "Section": "misc",
193+ }
194+ sp_data = SourcePackageData(**dsc_contents)
195+ self.assertEqual(
196+ [["Build-Indep-Architecture", "amd64"]], sp_data._user_defined)
197+ sp_data.archive_root = archive_root
198+ sp_data.dsc = ""
199+ sp_data.copyright = ""
200+ sp_data.urgency = "low"
201+ sp_data.changelog = None
202+ sp_data.changelog_entry = None
203+ sp_data.date_uploaded = UTC_NOW
204+ # We don't need a real .dsc here.
205+ write_file(
206+ os.path.join(archive_root, "pool/main/f/foo/foo_1.0-1.dsc"), "x")
207+ spr = sphandler.createSourcePackageRelease(sp_data, series)
208+ self.assertIsNotNone(spr)
209+ self.assertEqual(
210+ [["Build-Indep-Architecture", "amd64"]], spr.user_defined_fields)
211+
212+
213 class TestSourcePackagePublisher(TestCaseWithFactory):
214
215 layer = ZopelessDatabaseLayer
216@@ -244,6 +291,48 @@
217 self.assertEqual(PackagePublishingStatus.PUBLISHED, spph.status)
218
219
220+class TestBinaryPackageHandler(TestCaseWithFactory):
221+
222+ layer = LaunchpadZopelessLayer
223+
224+ def test_user_defined_fields(self):
225+ das = self.factory.makeDistroArchSeries()
226+ archive_root = self.useTempDir()
227+ sphandler = SourcePackageHandler(
228+ das.distroseries.distribution.name, archive_root,
229+ PackagePublishingPocket.RELEASE, None)
230+ bphandler = BinaryPackageHandler(
231+ sphandler, archive_root, PackagePublishingPocket.RELEASE)
232+ spr = self.factory.makeSourcePackageRelease(
233+ distroseries=das.distroseries)
234+ deb_contents = {
235+ "Package": "foo",
236+ "Installed-Size": "0",
237+ "Maintainer": "Foo Bar <foo@canonical.com>",
238+ "Section": "misc",
239+ "Architecture": "amd64",
240+ "Version": "1.0-1",
241+ "Filename": "pool/main/f/foo/foo_1.0-1_amd64.deb",
242+ "Component": "main",
243+ "Size": "0",
244+ "MD5sum": "0" * 32,
245+ "Description": "",
246+ "Summary": "",
247+ "Priority": "extra",
248+ "Python-Version": "2.7",
249+ }
250+ bp_data = BinaryPackageData(**deb_contents)
251+ self.assertEqual([["Python-Version", "2.7"]], bp_data._user_defined)
252+ bp_data.archive_root = archive_root
253+ # We don't need a real .deb here.
254+ write_file(
255+ os.path.join(archive_root, "pool/main/f/foo/foo_1.0-1_amd64.deb"),
256+ "x")
257+ bpr = bphandler.createBinaryPackage(bp_data, spr, das, "amd64")
258+ self.assertIsNotNone(bpr)
259+ self.assertEqual([["Python-Version", "2.7"]], bpr.user_defined_fields)
260+
261+
262 class TestBinaryPackagePublisher(TestCaseWithFactory):
263
264 layer = ZopelessDatabaseLayer