Merge lp:~jelmer/launchpad/613468-xb-ppa-qa into lp:launchpad/db-devel

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merged at revision: 9741
Proposed branch: lp:~jelmer/launchpad/613468-xb-ppa-qa
Merge into: lp:launchpad/db-devel
Diff against target: 780 lines (+138/-112)
16 files modified
lib/lp/archiveuploader/changesfile.py (+20/-20)
lib/lp/archiveuploader/dscfile.py (+37/-36)
lib/lp/archiveuploader/nascentuploadfile.py (+4/-3)
lib/lp/archiveuploader/tagfiles.py (+14/-7)
lib/lp/archiveuploader/tests/nascentupload-closing-bugs.txt (+1/-1)
lib/lp/archiveuploader/tests/nascentuploadfile.txt (+2/-2)
lib/lp/archiveuploader/tests/test_nascentuploadfile.py (+15/-1)
lib/lp/archiveuploader/tests/test_tagfiles.py (+4/-4)
lib/lp/archiveuploader/tests/test_uploadprocessor.py (+2/-2)
lib/lp/soyuz/doc/soyuz-upload.txt (+4/-4)
lib/lp/soyuz/model/queue.py (+14/-14)
lib/lp/soyuz/scripts/gina/handlers.py (+3/-0)
lib/lp/soyuz/scripts/processaccepted.py (+1/-1)
lib/lp/soyuz/scripts/tests/test_queue.py (+2/-2)
lib/lp/soyuz/scripts/tests/test_sync_source.py (+14/-14)
scripts/ftpmaster-tools/sync-source.py (+1/-1)
To merge this branch: bzr merge lp:~jelmer/launchpad/613468-xb-ppa-qa
Reviewer Review Type Date Requested Status
Abel Deuring (community) code Approve
Review via email: mp+33804@code.launchpad.net

Commit message

Preserve the case of user defined fields in control files.

Description of the change

This branch fixes some qa-badness in the fix for bug 613468.

Debian control fields have case-insensitive names:

http://www.debian.org/doc/debian-policy/ch-controlfields.html

Previously we would lowercase the field names when parsing them so we could always do lookups on lowercased names. When printing out these fields we would always use predefined formatting, as we only supported a limited set of fields (Build-Depends, Depends, Maintainer, etc.).

Now that custom fields are supported we need to preserve the original field name. To still support case-insensitive lookups we now use the custom Deb822Dict() class from python-debian, which provides support for case-preserving field names on which we can do case-insensitive lookups.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

I've also updated the existing field names that were used to use the standard casing as is used in the Debian policy documentation.

Revision history for this message
Abel Deuring (adeuring) :
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/changesfile.py'
--- lib/lp/archiveuploader/changesfile.py 2010-08-24 11:31:13 +0000
+++ lib/lp/archiveuploader/changesfile.py 2010-09-02 16:32:16 +0000
@@ -58,12 +58,12 @@
58 """Changesfile model."""58 """Changesfile model."""
5959
60 mandatory_fields = set([60 mandatory_fields = set([
61 "source", "binary", "architecture", "version", "distribution",61 "Source", "Binary", "Architecture", "Version", "Distribution",
62 "maintainer", "files", "changes", "date",62 "Maintainer", "Files", "Changes", "Date",
63 # Changed-By is not technically mandatory according to63 # Changed-By is not technically mandatory according to
64 # Debian policy but Soyuz relies on it being set in64 # Debian policy but Soyuz relies on it being set in
65 # various places.65 # various places.
66 "changed-by"])66 "Changed-By"])
6767
68 # Map urgencies to their dbschema values.68 # Map urgencies to their dbschema values.
69 # Debian policy only permits low, medium, high, emergency.69 # Debian policy only permits low, medium, high, emergency.
@@ -117,7 +117,7 @@
117 "file." % field)117 "file." % field)
118118
119 try:119 try:
120 format = float(self._dict["format"])120 format = float(self._dict["Format"])
121 except KeyError:121 except KeyError:
122 # If format is missing, pretend it's 1.5122 # If format is missing, pretend it's 1.5
123 format = 1.5123 format = 1.5
@@ -158,12 +158,12 @@
158 # signed upload. This is desireable because it avoids us158 # signed upload. This is desireable because it avoids us
159 # doing ensurePerson() for buildds and sync owners.159 # doing ensurePerson() for buildds and sync owners.
160 try:160 try:
161 self.maintainer = self.parseAddress(self._dict['maintainer'])161 self.maintainer = self.parseAddress(self._dict['Maintainer'])
162 except UploadError, error:162 except UploadError, error:
163 yield error163 yield error
164164
165 try:165 try:
166 self.changed_by = self.parseAddress(self._dict['changed-by'])166 self.changed_by = self.parseAddress(self._dict['Changed-By'])
167 except UploadError, error:167 except UploadError, error:
168 yield error168 yield error
169169
@@ -188,7 +188,7 @@
188 files.188 files.
189 """189 """
190 files = []190 files = []
191 for fileline in self._dict['files'].strip().split("\n"):191 for fileline in self._dict['Files'].strip().split("\n"):
192 # files lines from a changes file are always of the form:192 # files lines from a changes file are always of the form:
193 # CHECKSUM SIZE [COMPONENT/]SECTION PRIORITY FILENAME193 # CHECKSUM SIZE [COMPONENT/]SECTION PRIORITY FILENAME
194 digest, size, component_and_section, priority_name, filename = (194 digest, size, component_and_section, priority_name, filename = (
@@ -237,16 +237,16 @@
237 if len(self.files) == 0:237 if len(self.files) == 0:
238 yield UploadError("No files found in the changes")238 yield UploadError("No files found in the changes")
239239
240 if 'urgency' not in self._dict:240 if 'Urgency' not in self._dict:
241 # Urgency is recommended but not mandatory. Default to 'low'241 # Urgency is recommended but not mandatory. Default to 'low'
242 self._dict['urgency'] = "low"242 self._dict['Urgency'] = "low"
243243
244 raw_urgency = self._dict['urgency'].lower()244 raw_urgency = self._dict['Urgency'].lower()
245 if raw_urgency not in self.urgency_map:245 if raw_urgency not in self.urgency_map:
246 yield UploadWarning(246 yield UploadWarning(
247 "Unable to grok urgency %s, overriding with 'low'"247 "Unable to grok urgency %s, overriding with 'low'"
248 % (raw_urgency))248 % (raw_urgency))
249 self._dict['urgency'] = "low"249 self._dict['Urgency'] = "low"
250250
251 if not self.policy.unsigned_changes_ok:251 if not self.policy.unsigned_changes_ok:
252 assert self.signer is not None, (252 assert self.signer is not None, (
@@ -295,7 +295,7 @@
295295
296 For example, 'hoary' or 'hoary-security'.296 For example, 'hoary' or 'hoary-security'.
297 """297 """
298 return self._dict['distribution']298 return self._dict['Distribution']
299299
300 @property300 @property
301 def architectures(self):301 def architectures(self):
@@ -304,22 +304,22 @@
304 For instance ['source', 'all'] or ['source', 'i386', 'amd64']304 For instance ['source', 'all'] or ['source', 'i386', 'amd64']
305 or ['source'].305 or ['source'].
306 """306 """
307 return set(self._dict['architecture'].split())307 return set(self._dict['Architecture'].split())
308308
309 @property309 @property
310 def binaries(self):310 def binaries(self):
311 """Return set of binary package names listed."""311 """Return set of binary package names listed."""
312 return set(self._dict['binary'].strip().split())312 return set(self._dict['Binary'].strip().split())
313313
314 @property314 @property
315 def converted_urgency(self):315 def converted_urgency(self):
316 """Return the appropriate SourcePackageUrgency item."""316 """Return the appropriate SourcePackageUrgency item."""
317 return self.urgency_map[self._dict['urgency'].lower()]317 return self.urgency_map[self._dict['Urgency'].lower()]
318318
319 @property319 @property
320 def version(self):320 def version(self):
321 """Return changesfile claimed version."""321 """Return changesfile claimed version."""
322 return self._dict['version']322 return self._dict['Version']
323323
324 @classmethod324 @classmethod
325 def formatChangesComment(cls, comment):325 def formatChangesComment(cls, comment):
@@ -336,24 +336,24 @@
336 @property336 @property
337 def changes_comment(self):337 def changes_comment(self):
338 """Return changesfile 'change' comment."""338 """Return changesfile 'change' comment."""
339 comment = self._dict['changes']339 comment = self._dict['Changes']
340340
341 return self.formatChangesComment(comment)341 return self.formatChangesComment(comment)
342342
343 @property343 @property
344 def date(self):344 def date(self):
345 """Return changesfile date."""345 """Return changesfile date."""
346 return self._dict['date']346 return self._dict['Date']
347347
348 @property348 @property
349 def source(self):349 def source(self):
350 """Return changesfile claimed source name."""350 """Return changesfile claimed source name."""
351 return self._dict['source']351 return self._dict['Source']
352352
353 @property353 @property
354 def architecture_line(self):354 def architecture_line(self):
355 """Return changesfile archicteture line."""355 """Return changesfile archicteture line."""
356 return self._dict['architecture']356 return self._dict['Architecture']
357357
358 @property358 @property
359 def filecontents(self):359 def filecontents(self):
360360
=== modified file 'lib/lp/archiveuploader/dscfile.py'
--- lib/lp/archiveuploader/dscfile.py 2010-08-30 19:06:34 +0000
+++ lib/lp/archiveuploader/dscfile.py 2010-09-02 16:32:16 +0000
@@ -17,7 +17,9 @@
17 'find_copyright',17 'find_copyright',
18 ]18 ]
1919
20import apt_pkg
20from cStringIO import StringIO21from cStringIO import StringIO
22from debian.deb822 import Deb822Dict
21import errno23import errno
22import glob24import glob
23import os25import os
@@ -25,7 +27,6 @@
25import subprocess27import subprocess
26import tempfile28import tempfile
2729
28import apt_pkg
29from zope.component import getUtility30from zope.component import getUtility
3031
31from canonical.encoding import guess as guess_encoding32from canonical.encoding import guess as guess_encoding
@@ -206,8 +207,8 @@
206207
207 person = getUtility(IPersonSet).getByEmail(email)208 person = getUtility(IPersonSet).getByEmail(email)
208 if person is None and self.policy.create_people:209 if person is None and self.policy.create_people:
209 package = self._dict['source']210 package = self._dict['Source']
210 version = self._dict['version']211 version = self._dict['Version']
211 if self.policy.distroseries and self.policy.pocket:212 if self.policy.distroseries and self.policy.pocket:
212 policy_suite = ('%s/%s' % (self.policy.distroseries.name,213 policy_suite = ('%s/%s' % (self.policy.distroseries.name,
213 self.policy.pocket.name))214 self.policy.pocket.name))
@@ -235,20 +236,20 @@
235 """Models a given DSC file and its content."""236 """Models a given DSC file and its content."""
236237
237 mandatory_fields = set([238 mandatory_fields = set([
238 "source",239 "Source",
239 "version",240 "Version",
240 "binary",241 "Binary",
241 "maintainer",242 "Maintainer",
242 "architecture",243 "Architecture",
243 "files"])244 "Files"])
244245
245 known_fields = mandatory_fields.union(set([246 known_fields = mandatory_fields.union(set([
246 "build-depends",247 "Build-Depends",
247 "build-depends-indep",248 "Build-Depends-Indep",
248 "build-conflicts",249 "Build-Conflicts",
249 "build-conflicts-indep",250 "Build-Conflicts-Indep",
250 "format",251 "Format",
251 "standards-version",252 "Standards-Version",
252 "filecontents",253 "filecontents",
253 "homepage",254 "homepage",
254 ]))255 ]))
@@ -289,17 +290,17 @@
289 "Unable to find mandatory field %s in %s" % (290 "Unable to find mandatory field %s in %s" % (
290 mandatory_field, self.filename))291 mandatory_field, self.filename))
291292
292 self.maintainer = self.parseAddress(self._dict['maintainer'])293 self.maintainer = self.parseAddress(self._dict['Maintainer'])
293294
294 # If format is not present, assume 1.0. At least one tool in295 # If format is not present, assume 1.0. At least one tool in
295 # the wild generates dsc files with format missing, and we need296 # the wild generates dsc files with format missing, and we need
296 # to accept them.297 # to accept them.
297 if 'format' not in self._dict:298 if 'Format' not in self._dict:
298 self._dict['format'] = "1.0"299 self._dict['Format'] = "1.0"
299300
300 if self.format is None:301 if self.format is None:
301 raise EarlyReturnUploadError(302 raise EarlyReturnUploadError(
302 "Unsupported source format: %s" % self._dict['format'])303 "Unsupported source format: %s" % self._dict['Format'])
303304
304 if self.policy.unsigned_dsc_ok:305 if self.policy.unsigned_dsc_ok:
305 self.logger.debug("DSC file can be unsigned.")306 self.logger.debug("DSC file can be unsigned.")
@@ -312,31 +313,31 @@
312 @property313 @property
313 def source(self):314 def source(self):
314 """Return the DSC source name."""315 """Return the DSC source name."""
315 return self._dict['source']316 return self._dict['Source']
316317
317 @property318 @property
318 def dsc_version(self):319 def dsc_version(self):
319 """Return the DSC source version."""320 """Return the DSC source version."""
320 return self._dict['version']321 return self._dict['Version']
321322
322 @property323 @property
323 def format(self):324 def format(self):
324 """Return the DSC format."""325 """Return the DSC format."""
325 try:326 try:
326 return SourcePackageFormat.getTermByToken(327 return SourcePackageFormat.getTermByToken(
327 self._dict['format']).value328 self._dict['Format']).value
328 except LookupError:329 except LookupError:
329 return None330 return None
330331
331 @property332 @property
332 def architecture(self):333 def architecture(self):
333 """Return the DSC source architecture."""334 """Return the DSC source architecture."""
334 return self._dict['architecture']335 return self._dict['Architecture']
335336
336 @property337 @property
337 def binary(self):338 def binary(self):
338 """Return the DSC claimed binary line."""339 """Return the DSC claimed binary line."""
339 return self._dict['binary']340 return self._dict['Binary']
340341
341342
342 #343 #
@@ -359,7 +360,7 @@
359 yield error360 yield error
360361
361 files = []362 files = []
362 for fileline in self._dict['files'].strip().split("\n"):363 for fileline in self._dict['Files'].strip().split("\n"):
363 # DSC lines are always of the form: CHECKSUM SIZE FILENAME364 # DSC lines are always of the form: CHECKSUM SIZE FILENAME
364 digest, size, filename = fileline.strip().split()365 digest, size, filename = fileline.strip().split()
365 if not re_issource.match(filename):366 if not re_issource.match(filename):
@@ -393,7 +394,7 @@
393 (self.filename, self.format, self.policy.distroseries.name))394 (self.filename, self.format, self.policy.distroseries.name))
394395
395 # Validate the build dependencies396 # Validate the build dependencies
396 for field_name in ['build-depends', 'build-depends-indep']:397 for field_name in ['Build-Depends', 'Build-Depends-Indep']:
397 field = self._dict.get(field_name, None)398 field = self._dict.get(field_name, None)
398 if field is not None:399 if field is not None:
399 if field.startswith("ARRAY"):400 if field.startswith("ARRAY"):
@@ -672,7 +673,7 @@
672673
673 # We have no way of knowing what encoding the original copyright674 # We have no way of knowing what encoding the original copyright
674 # file is in, unfortunately, and there is no standard, so guess.675 # file is in, unfortunately, and there is no standard, so guess.
675 encoded = {}676 encoded = Deb822Dict()
676 for key, value in pending.items():677 for key, value in pending.items():
677 if value is not None:678 if value is not None:
678 encoded[key] = guess_encoding(value)679 encoded[key] = guess_encoding(value)
@@ -701,20 +702,20 @@
701 sourcepackagename=source_name,702 sourcepackagename=source_name,
702 version=self.dsc_version,703 version=self.dsc_version,
703 maintainer=self.maintainer['person'],704 maintainer=self.maintainer['person'],
704 builddepends=encoded.get('build-depends', ''),705 builddepends=encoded.get('Build-Depends', ''),
705 builddependsindep=encoded.get('build-depends-indep', ''),706 builddependsindep=encoded.get('Build-Depends-Indep', ''),
706 build_conflicts=encoded.get('build-conflicts', ''),707 build_conflicts=encoded.get('Build-Conflicts', ''),
707 build_conflicts_indep=encoded.get('build-conflicts-indep', ''),708 build_conflicts_indep=encoded.get('Build-Conflicts-Indep', ''),
708 architecturehintlist=encoded.get('architecture', ''),709 architecturehintlist=encoded.get('Architecture', ''),
709 creator=self.changes.changed_by['person'],710 creator=self.changes.changed_by['person'],
710 urgency=self.changes.converted_urgency,711 urgency=self.changes.converted_urgency,
711 homepage=encoded.get('homepage'),712 homepage=encoded.get('homepage'),
712 dsc=encoded['filecontents'],713 dsc=encoded['filecontents'],
713 dscsigningkey=self.signingkey,714 dscsigningkey=self.signingkey,
714 dsc_maintainer_rfc822=encoded['maintainer'],715 dsc_maintainer_rfc822=encoded['Maintainer'],
715 dsc_format=encoded['format'],716 dsc_format=encoded['Format'],
716 dsc_binaries=encoded['binary'],717 dsc_binaries=encoded['Binary'],
717 dsc_standards_version=encoded.get('standards-version'),718 dsc_standards_version=encoded.get('Standards-Version'),
718 component=self.component,719 component=self.component,
719 changelog=changelog_lfa,720 changelog=changelog_lfa,
720 changelog_entry=encoded.get('simulated_changelog'),721 changelog_entry=encoded.get('simulated_changelog'),
721722
=== modified file 'lib/lp/archiveuploader/nascentuploadfile.py'
--- lib/lp/archiveuploader/nascentuploadfile.py 2010-08-30 19:06:34 +0000
+++ lib/lp/archiveuploader/nascentuploadfile.py 2010-09-02 16:32:16 +0000
@@ -19,14 +19,15 @@
19 'splitComponentAndSection',19 'splitComponentAndSection',
20 ]20 ]
2121
22import apt_inst
23import apt_pkg
24from debian.deb822 import Deb822Dict
22import hashlib25import hashlib
23import os26import os
24import subprocess27import subprocess
25import sys28import sys
26import time29import time
2730
28import apt_inst
29import apt_pkg
30from zope.component import getUtility31from zope.component import getUtility
3132
32from canonical.encoding import guess as guess_encoding33from canonical.encoding import guess as guess_encoding
@@ -883,7 +884,7 @@
883 """Insert this binary release and build into the database."""884 """Insert this binary release and build into the database."""
884 # Reencode everything we are supplying, because old packages885 # Reencode everything we are supplying, because old packages
885 # contain latin-1 text and that sucks.886 # contain latin-1 text and that sucks.
886 encoded = {}887 encoded = Deb822Dict()
887 for key, value in self.control.items():888 for key, value in self.control.items():
888 encoded[key] = guess_encoding(value)889 encoded[key] = guess_encoding(value)
889890
890891
=== modified file 'lib/lp/archiveuploader/tagfiles.py'
--- lib/lp/archiveuploader/tagfiles.py 2010-08-20 20:31:18 +0000
+++ lib/lp/archiveuploader/tagfiles.py 2010-09-02 16:32:16 +0000
@@ -1,14 +1,20 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the1# Copyright 2009 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Utility classes for parsing Debian tag files."""
5
6__all__ = [
7 'TagFile',
8 'TagStanza',
9 'TagFileParseError',
10 'parse_tagfile',
11 'parse_tagfile_lines'
12 ]
13
14
15import apt_pkg
4import re16import re
517
6import apt_pkg
7
8
9__all__ = [
10 'TagFile', 'TagStanza', 'TagFileParseError',
11 'parse_tagfile', 'parse_tagfile_lines']
1218
13class TagFile(object):19class TagFile(object):
14 """Provide an iterable interface to the apt_pkg.TagFile object"""20 """Provide an iterable interface to the apt_pkg.TagFile object"""
@@ -92,6 +98,7 @@
92 '-----BEGIN PGP SIGNATURE-----'.98 '-----BEGIN PGP SIGNATURE-----'.
93 """99 """
94 error = ""100 error = ""
101
95 changes = {}102 changes = {}
96103
97 # Reindex by line number so we can easily verify the format of104 # Reindex by line number so we can easily verify the format of
@@ -152,7 +159,7 @@
152 continue159 continue
153 slf = re_single_line_field.match(line)160 slf = re_single_line_field.match(line)
154 if slf:161 if slf:
155 field = slf.groups()[0].lower()162 field = slf.groups()[0]
156 changes[field] = slf.groups()[1]163 changes[field] = slf.groups()[1]
157164
158 # If there is no value on this line, we assume this is165 # If there is no value on this line, we assume this is
159166
=== modified file 'lib/lp/archiveuploader/tests/nascentupload-closing-bugs.txt'
--- lib/lp/archiveuploader/tests/nascentupload-closing-bugs.txt 2008-09-15 08:13:00 +0000
+++ lib/lp/archiveuploader/tests/nascentupload-closing-bugs.txt 2010-09-02 16:32:16 +0000
@@ -79,7 +79,7 @@
79 >>> bar2_src.changes.changed_by['person'].name79 >>> bar2_src.changes.changed_by['person'].name
80 u'kinnison'80 u'kinnison'
8181
82 >>> bar2_src.changes._dict['launchpad-bugs-fixed']82 >>> bar2_src.changes._dict['Launchpad-bugs-fixed']
83 '6'83 '6'
8484
85 >>> print bar2_src.changes.changes_comment85 >>> print bar2_src.changes.changes_comment
8686
=== modified file 'lib/lp/archiveuploader/tests/nascentuploadfile.txt'
--- lib/lp/archiveuploader/tests/nascentuploadfile.txt 2010-08-24 20:23:48 +0000
+++ lib/lp/archiveuploader/tests/nascentuploadfile.txt 2010-09-02 16:32:16 +0000
@@ -233,8 +233,8 @@
233present in ChangesFile and DSCFile:233present in ChangesFile and DSCFile:
234234
235 >>> sig_file._dict = {}235 >>> sig_file._dict = {}
236 >>> sig_file._dict['source'] = 'some-source'236 >>> sig_file._dict['Source'] = 'some-source'
237 >>> sig_file._dict['version'] = '6.6.6'237 >>> sig_file._dict['Version'] = '6.6.6'
238238
239After initiliasing sig_file we can parse addresses and look them up in239After initiliasing sig_file we can parse addresses and look them up in
240Launchpad:240Launchpad:
241241
=== modified file 'lib/lp/archiveuploader/tests/test_nascentuploadfile.py'
--- lib/lp/archiveuploader/tests/test_nascentuploadfile.py 2010-09-02 11:02:24 +0000
+++ lib/lp/archiveuploader/tests/test_nascentuploadfile.py 2010-09-02 16:32:16 +0000
@@ -175,6 +175,20 @@
175 self.assertEquals("0.42", release.version)175 self.assertEquals("0.42", release.version)
176 self.assertEquals("dpkg, bzr", release.builddepends)176 self.assertEquals("dpkg, bzr", release.builddepends)
177177
178 def test_storeInDatabase_case_sensitivity(self):
179 # storeInDatabase supports field names with different cases,
180 # confirming to Debian policy.
181 dsc = self.getBaseDsc()
182 dsc["buIld-depends"] = "dpkg, bzr"
183 changes = self.getBaseChanges()
184 uploadfile = self.createDSCFile(
185 "foo.dsc", dsc, "main/net", "extra", "dulwich", "0.42",
186 self.createChangesFile("foo.changes", changes))
187 uploadfile.files = []
188 uploadfile.changelog = "DUMMY"
189 release = uploadfile.storeInDatabase(None)
190 self.assertEquals("dpkg, bzr", release.builddepends)
191
178 def test_user_defined_fields(self):192 def test_user_defined_fields(self):
179 # storeInDatabase updates user_defined_fields.193 # storeInDatabase updates user_defined_fields.
180 dsc = self.getBaseDsc()194 dsc = self.getBaseDsc()
@@ -188,7 +202,7 @@
188 release = uploadfile.storeInDatabase(None)202 release = uploadfile.storeInDatabase(None)
189 # DSCFile lowercases the field names203 # DSCFile lowercases the field names
190 self.assertEquals(204 self.assertEquals(
191 [["python-version", u"2.5"]], release.user_defined_fields)205 [["Python-Version", u"2.5"]], release.user_defined_fields)
192206
193 def test_homepage(self):207 def test_homepage(self):
194 # storeInDatabase updates homepage.208 # storeInDatabase updates homepage.
195209
=== modified file 'lib/lp/archiveuploader/tests/test_tagfiles.py'
--- lib/lp/archiveuploader/tests/test_tagfiles.py 2010-08-20 20:31:18 +0000
+++ lib/lp/archiveuploader/tests/test_tagfiles.py 2010-09-02 16:32:16 +0000
@@ -76,7 +76,7 @@
76 parse_tagfile, datadir("bad-multiline-changes"), 1)76 parse_tagfile, datadir("bad-multiline-changes"), 1)
7777
78 def testCheckParseUnterminatedSigRaises(self):78 def testCheckParseUnterminatedSigRaises(self):
79 """lp.archiveuploader.tagfiles.parse_chantges should raise79 """lp.archiveuploader.tagfiles.parse_changes should raise
80 TagFileParseError on unterminated signatures80 TagFileParseError on unterminated signatures
81 """81 """
82 self.assertRaises(TagFileParseError,82 self.assertRaises(TagFileParseError,
@@ -128,7 +128,7 @@
128128
129 self.assertEqual(129 self.assertEqual(
130 expected_text,130 expected_text,
131 self.parse_tagfile_version['binary'])131 self.parse_tagfile_version['Binary'])
132132
133 def test_parse_tagfile_with_newline_delimited_field(self):133 def test_parse_tagfile_with_newline_delimited_field(self):
134 """parse_tagfile should not leave leading or tailing '\n' when134 """parse_tagfile should not leave leading or tailing '\n' when
@@ -157,7 +157,7 @@
157157
158 self.assertEqual(158 self.assertEqual(
159 expected_text,159 expected_text,
160 self.parse_tagfile_version['files'])160 self.parse_tagfile_version['Files'])
161161
162 def test_parse_description_field(self):162 def test_parse_description_field(self):
163 """Apt-pkg preserves the blank-line indicator and does not strip163 """Apt-pkg preserves the blank-line indicator and does not strip
@@ -186,4 +186,4 @@
186 # replaced by ParseTagFiles).186 # replaced by ParseTagFiles).
187 self.assertEqual(187 self.assertEqual(
188 expected_text,188 expected_text,
189 self.parse_tagfile_version['description'])189 self.parse_tagfile_version['Description'])
190190
=== modified file 'lib/lp/archiveuploader/tests/test_uploadprocessor.py'
--- lib/lp/archiveuploader/tests/test_uploadprocessor.py 2010-08-27 11:19:54 +0000
+++ lib/lp/archiveuploader/tests/test_uploadprocessor.py 2010-09-02 16:32:16 +0000
@@ -1202,7 +1202,7 @@
1202 error_report.write(fp)1202 error_report.write(fp)
1203 error_text = fp.getvalue()1203 error_text = fp.getvalue()
1204 self.assertTrue(1204 self.assertTrue(
1205 "Unable to find mandatory field 'files' in the changes file" in error_text)1205 "Unable to find mandatory field 'Files' in the changes file" in error_text)
12061206
1207 # Housekeeping so the next test won't fail.1207 # Housekeeping so the next test won't fail.
1208 shutil.rmtree(upload_dir)1208 shutil.rmtree(upload_dir)
@@ -1369,7 +1369,7 @@
1369 % error_text)1369 % error_text)
13701370
1371 expected_explanation = (1371 expected_explanation = (
1372 "Unable to find mandatory field 'files' in the changes file.")1372 "Unable to find mandatory field 'Files' in the changes file.")
1373 self.failUnless(1373 self.failUnless(
1374 error_text.find(expected_explanation) >= 0,1374 error_text.find(expected_explanation) >= 0,
1375 'Expected Exception text not found in OOPS report:\n%s'1375 'Expected Exception text not found in OOPS report:\n%s'
13761376
=== modified file 'lib/lp/soyuz/doc/soyuz-upload.txt'
--- lib/lp/soyuz/doc/soyuz-upload.txt 2010-08-24 12:25:48 +0000
+++ lib/lp/soyuz/doc/soyuz-upload.txt 2010-09-02 16:32:16 +0000
@@ -94,14 +94,14 @@
94 ...94 ...
95 ... tf = parse_tagfile(changes_filepath)95 ... tf = parse_tagfile(changes_filepath)
96 ...96 ...
97 ... if tf.has_key("source"):97 ... if tf.has_key("Source"):
98 ... package_names.append(tf["source"])98 ... package_names.append(tf["Source"])
99 ...99 ...
100 ... send_filepaths = [changes_filepath]100 ... send_filepaths = [changes_filepath]
101 ... if tf.has_key("files"):101 ... if tf.has_key("Files"):
102 ... send_filepaths.extend(102 ... send_filepaths.extend(
103 ... [os.path.join(test_files_dir, line.split()[-1])103 ... [os.path.join(test_files_dir, line.split()[-1])
104 ... for line in tf["files"].splitlines() if line])104 ... for line in tf["Files"].splitlines() if line])
105 ...105 ...
106 ... sent_filenames.extend(106 ... sent_filenames.extend(
107 ... os.path.basename(filepath) for filepath in send_filepaths)107 ... os.path.basename(filepath) for filepath in send_filepaths)
108108
=== modified file 'lib/lp/soyuz/model/queue.py'
--- lib/lp/soyuz/model/queue.py 2010-08-24 12:25:48 +0000
+++ lib/lp/soyuz/model/queue.py 2010-09-02 16:32:16 +0000
@@ -801,16 +801,16 @@
801 :changes: A dictionary with the changes file content.801 :changes: A dictionary with the changes file content.
802 """802 """
803 # Add the date field.803 # Add the date field.
804 message.DATE = 'Date: %s' % changes['date']804 message.DATE = 'Date: %s' % changes['Date']
805805
806 # Add the debian 'Changed-By:' field.806 # Add the debian 'Changed-By:' field.
807 changed_by = changes.get('changed-by')807 changed_by = changes.get('Changed-By')
808 if changed_by is not None:808 if changed_by is not None:
809 changed_by = sanitize_string(changed_by)809 changed_by = sanitize_string(changed_by)
810 message.CHANGEDBY = '\nChanged-By: %s' % changed_by810 message.CHANGEDBY = '\nChanged-By: %s' % changed_by
811811
812 # Add maintainer if present and different from changed-by.812 # Add maintainer if present and different from changed-by.
813 maintainer = changes.get('maintainer')813 maintainer = changes.get('Maintainer')
814 if maintainer is not None:814 if maintainer is not None:
815 maintainer = sanitize_string(maintainer)815 maintainer = sanitize_string(maintainer)
816 if maintainer != changed_by:816 if maintainer != changed_by:
@@ -831,8 +831,8 @@
831 message.SIGNER = '\nSigned-By: %s' % signer_signature831 message.SIGNER = '\nSigned-By: %s' % signer_signature
832832
833 # Add the debian 'Origin:' field if present.833 # Add the debian 'Origin:' field if present.
834 if changes.get('origin') is not None:834 if changes.get('Origin') is not None:
835 message.ORIGIN = '\nOrigin: %s' % changes['origin']835 message.ORIGIN = '\nOrigin: %s' % changes['Origin']
836836
837 if self.sources or self.builds:837 if self.sources or self.builds:
838 message.SPR_URL = canonical_url(self.my_source_package_release)838 message.SPR_URL = canonical_url(self.my_source_package_release)
@@ -855,7 +855,7 @@
855 template = get_email_template('upload-rejection.txt')855 template = get_email_template('upload-rejection.txt')
856 SUMMARY = sanitize_string(summary_text)856 SUMMARY = sanitize_string(summary_text)
857 CHANGESFILE = sanitize_string(857 CHANGESFILE = sanitize_string(
858 ChangesFile.formatChangesComment(changes['changes']))858 ChangesFile.formatChangesComment(changes['Changes']))
859 CHANGEDBY = ''859 CHANGEDBY = ''
860 ORIGIN = ''860 ORIGIN = ''
861 SIGNER = ''861 SIGNER = ''
@@ -933,7 +933,7 @@
933 STATUS = "New"933 STATUS = "New"
934 SUMMARY = summarystring934 SUMMARY = summarystring
935 CHANGESFILE = sanitize_string(935 CHANGESFILE = sanitize_string(
936 ChangesFile.formatChangesComment(changes['changes']))936 ChangesFile.formatChangesComment(changes['Changes']))
937 DISTRO = self.distroseries.distribution.title937 DISTRO = self.distroseries.distribution.title
938 if announce_list:938 if announce_list:
939 ANNOUNCE = 'Announcing to %s' % announce_list939 ANNOUNCE = 'Announcing to %s' % announce_list
@@ -948,7 +948,7 @@
948 SUMMARY = summarystring + (948 SUMMARY = summarystring + (
949 "\nThis upload awaits approval by a distro manager\n")949 "\nThis upload awaits approval by a distro manager\n")
950 CHANGESFILE = sanitize_string(950 CHANGESFILE = sanitize_string(
951 ChangesFile.formatChangesComment(changes['changes']))951 ChangesFile.formatChangesComment(changes['Changes']))
952 DISTRO = self.distroseries.distribution.title952 DISTRO = self.distroseries.distribution.title
953 if announce_list:953 if announce_list:
954 ANNOUNCE = 'Announcing to %s' % announce_list954 ANNOUNCE = 'Announcing to %s' % announce_list
@@ -967,7 +967,7 @@
967 STATUS = "Accepted"967 STATUS = "Accepted"
968 SUMMARY = summarystring968 SUMMARY = summarystring
969 CHANGESFILE = sanitize_string(969 CHANGESFILE = sanitize_string(
970 ChangesFile.formatChangesComment(changes['changes']))970 ChangesFile.formatChangesComment(changes['Changes']))
971 DISTRO = self.distroseries.distribution.title971 DISTRO = self.distroseries.distribution.title
972 if announce_list:972 if announce_list:
973 ANNOUNCE = 'Announcing to %s' % announce_list973 ANNOUNCE = 'Announcing to %s' % announce_list
@@ -994,7 +994,7 @@
994 STATUS = "Accepted"994 STATUS = "Accepted"
995 SUMMARY = summarystring995 SUMMARY = summarystring
996 CHANGESFILE = sanitize_string(996 CHANGESFILE = sanitize_string(
997 ChangesFile.formatChangesComment(changes['changes']))997 ChangesFile.formatChangesComment(changes['Changes']))
998 CHANGEDBY = ''998 CHANGEDBY = ''
999 ORIGIN = ''999 ORIGIN = ''
1000 SIGNER = ''1000 SIGNER = ''
@@ -1045,14 +1045,14 @@
1045 do_sendmail(AcceptedMessage)1045 do_sendmail(AcceptedMessage)
10461046
1047 # Don't send announcements for Debian auto sync uploads.1047 # Don't send announcements for Debian auto sync uploads.
1048 if self.isAutoSyncUpload(changed_by_email=changes['changed-by']):1048 if self.isAutoSyncUpload(changed_by_email=changes['Changed-By']):
1049 return1049 return
10501050
1051 if announce_list:1051 if announce_list:
1052 if not self.signing_key:1052 if not self.signing_key:
1053 from_addr = None1053 from_addr = None
1054 else:1054 else:
1055 from_addr = guess_encoding(changes['changed-by'])1055 from_addr = guess_encoding(changes['Changed-By'])
10561056
1057 do_sendmail(1057 do_sendmail(
1058 AnnouncementMessage,1058 AnnouncementMessage,
@@ -1135,7 +1135,7 @@
1135 """Return a list of recipients for notification emails."""1135 """Return a list of recipients for notification emails."""
1136 candidate_recipients = []1136 candidate_recipients = []
1137 debug(self.logger, "Building recipients list.")1137 debug(self.logger, "Building recipients list.")
1138 changer = self._emailToPerson(changes['changed-by'])1138 changer = self._emailToPerson(changes['Changed-By'])
11391139
1140 if self.signing_key:1140 if self.signing_key:
1141 # This is a signed upload.1141 # This is a signed upload.
@@ -1157,7 +1157,7 @@
11571157
1158 # If this is not a PPA, we also consider maintainer and changed-by.1158 # If this is not a PPA, we also consider maintainer and changed-by.
1159 if self.signing_key and not self.isPPA():1159 if self.signing_key and not self.isPPA():
1160 maintainer = self._emailToPerson(changes['maintainer'])1160 maintainer = self._emailToPerson(changes['Maintainer'])
1161 if (maintainer and maintainer != signer and1161 if (maintainer and maintainer != signer and
1162 maintainer.isUploader(self.distroseries.distribution)):1162 maintainer.isUploader(self.distroseries.distribution)):
1163 debug(self.logger, "Adding maintainer to recipients")1163 debug(self.logger, "Adding maintainer to recipients")
11641164
=== modified file 'lib/lp/soyuz/scripts/gina/handlers.py'
--- lib/lp/soyuz/scripts/gina/handlers.py 2010-08-27 11:19:54 +0000
+++ lib/lp/soyuz/scripts/gina/handlers.py 2010-09-02 16:32:16 +0000
@@ -520,6 +520,9 @@
520 log.debug("Found a source package for %s (%s) in %s" % (sp_name,520 log.debug("Found a source package for %s (%s) in %s" % (sp_name,
521 sp_version, sp_component))521 sp_version, sp_component))
522 dsc_contents = parse_tagfile(dsc_path, allow_unsigned=True)522 dsc_contents = parse_tagfile(dsc_path, allow_unsigned=True)
523 dsc_contents = dict([
524 (name.lower(), value) for
525 (name, value) in dsc_contents.iteritems()])
523526
524 # Since the dsc doesn't know, we add in the directory, package527 # Since the dsc doesn't know, we add in the directory, package
525 # component and section528 # component and section
526529
=== modified file 'lib/lp/soyuz/scripts/processaccepted.py'
--- lib/lp/soyuz/scripts/processaccepted.py 2010-08-24 12:25:48 +0000
+++ lib/lp/soyuz/scripts/processaccepted.py 2010-09-02 16:32:16 +0000
@@ -48,7 +48,7 @@
48 contents = changes_file.read()48 contents = changes_file.read()
49 changes_lines = contents.splitlines(True)49 changes_lines = contents.splitlines(True)
50 tags = parse_tagfile_lines(changes_lines, allow_unsigned=True)50 tags = parse_tagfile_lines(changes_lines, allow_unsigned=True)
51 bugs_fixed_line = tags.get('launchpad-bugs-fixed', '')51 bugs_fixed_line = tags.get('Launchpad-bugs-fixed', '')
52 bugs = []52 bugs = []
53 for bug_id in bugs_fixed_line.split():53 for bug_id in bugs_fixed_line.split():
54 if not bug_id.isdigit():54 if not bug_id.isdigit():
5555
=== modified file 'lib/lp/soyuz/scripts/tests/test_queue.py'
--- lib/lp/soyuz/scripts/tests/test_queue.py 2010-08-24 15:29:01 +0000
+++ lib/lp/soyuz/scripts/tests/test_queue.py 2010-09-02 16:32:16 +0000
@@ -382,10 +382,10 @@
382 queue_action = self.execute_command('accept bar', no_mail=False)382 queue_action = self.execute_command('accept bar', no_mail=False)
383383
384 # The upload wants to close bug 6:384 # The upload wants to close bug 6:
385 bugs_fixed_header = bar2_src.changes._dict['launchpad-bugs-fixed']385 bugs_fixed_header = bar2_src.changes._dict['Launchpad-bugs-fixed']
386 self.assertEqual(386 self.assertEqual(
387 bugs_fixed_header, str(the_bug_id),387 bugs_fixed_header, str(the_bug_id),
388 'Expected bug %s in launchpad-bugs-fixed, got %s'388 'Expected bug %s in Launchpad-bugs-fixed, got %s'
389 % (the_bug_id, bugs_fixed_header))389 % (the_bug_id, bugs_fixed_header))
390390
391 # The upload should be in the DONE state:391 # The upload should be in the DONE state:
392392
=== modified file 'lib/lp/soyuz/scripts/tests/test_sync_source.py'
--- lib/lp/soyuz/scripts/tests/test_sync_source.py 2010-08-20 20:31:18 +0000
+++ lib/lp/soyuz/scripts/tests/test_sync_source.py 2010-09-02 16:32:16 +0000
@@ -322,25 +322,25 @@
322 expected_changesfile, allow_unsigned=True)322 expected_changesfile, allow_unsigned=True)
323323
324 # It refers to the right source/version.324 # It refers to the right source/version.
325 self.assertEqual(parsed_changes['source'], 'bar')325 self.assertEqual(parsed_changes['Source'], 'bar')
326 self.assertEqual(parsed_changes['version'], '1.0-1')326 self.assertEqual(parsed_changes['Version'], '1.0-1')
327327
328 # It includes the correct 'origin' and 'target' information.328 # It includes the correct 'origin' and 'target' information.
329 self.assertEqual(parsed_changes['origin'], 'Debian/incoming')329 self.assertEqual(parsed_changes['Origin'], 'Debian/incoming')
330 self.assertEqual(parsed_changes['distribution'], 'hoary')330 self.assertEqual(parsed_changes['Distribution'], 'hoary')
331331
332 # 'closes' and 'launchpad-bug-fixed' are filled according to332 # 'closes' and 'launchpad-bug-fixed' are filled according to
333 # what is listed in the debian/changelog.333 # what is listed in the debian/changelog.
334 self.assertEqual(parsed_changes['closes'], '1 2 1234 4321')334 self.assertEqual(parsed_changes['Closes'], '1 2 1234 4321')
335 self.assertEqual(parsed_changes['launchpad-bugs-fixed'], '1234 4321')335 self.assertEqual(parsed_changes['Launchpad-bugs-fixed'], '1234 4321')
336336
337 # And finally, 'maintainer' role was preserved and 'changed-by'337 # And finally, 'maintainer' role was preserved and 'changed-by'
338 # role was assigned as specified in the sync-source command-line.338 # role was assigned as specified in the sync-source command-line.
339 self.assertEqual(339 self.assertEqual(
340 parsed_changes['maintainer'],340 parsed_changes['Maintainer'],
341 'Launchpad team <launchpad@lists.canonical.com>')341 'Launchpad team <launchpad@lists.canonical.com>')
342 self.assertEqual(342 self.assertEqual(
343 parsed_changes['changed-by'],343 parsed_changes['Changed-By'],
344 'Celso Providelo <celso.providelo@canonical.com>')344 'Celso Providelo <celso.providelo@canonical.com>')
345345
346 os.unlink(expected_changesfile)346 os.unlink(expected_changesfile)
@@ -397,20 +397,20 @@
397 expected_changesfile, allow_unsigned=True)397 expected_changesfile, allow_unsigned=True)
398398
399 # It refers to the right source/version.399 # It refers to the right source/version.
400 self.assertEqual(parsed_changes['source'], 'sample1')400 self.assertEqual(parsed_changes['Source'], 'sample1')
401 self.assertEqual(parsed_changes['version'], '1.0-1')401 self.assertEqual(parsed_changes['Version'], '1.0-1')
402402
403 # It includes the correct 'origin' and 'target' information.403 # It includes the correct 'origin' and 'target' information.
404 self.assertEqual(parsed_changes['origin'], 'Debian/incoming')404 self.assertEqual(parsed_changes['Origin'], 'Debian/incoming')
405 self.assertEqual(parsed_changes['distribution'], 'hoary')405 self.assertEqual(parsed_changes['Distribution'], 'hoary')
406406
407 # And finally, 'maintainer' role was preserved and 'changed-by'407 # And finally, 'maintainer' role was preserved and 'changed-by'
408 # role was assigned as specified in the sync-source command-line.408 # role was assigned as specified in the sync-source command-line.
409 self.assertEqual(409 self.assertEqual(
410 parsed_changes['maintainer'],410 parsed_changes['Maintainer'],
411 'Raphael Hertzog <hertzog@debian.org>')411 'Raphael Hertzog <hertzog@debian.org>')
412 self.assertEqual(412 self.assertEqual(
413 parsed_changes['changed-by'],413 parsed_changes['Changed-By'],
414 'Celso Providelo <celso.providelo@canonical.com>')414 'Celso Providelo <celso.providelo@canonical.com>')
415415
416 os.unlink(expected_changesfile)416 os.unlink(expected_changesfile)
417417
=== modified file 'scripts/ftpmaster-tools/sync-source.py'
--- scripts/ftpmaster-tools/sync-source.py 2010-08-26 08:02:08 +0000
+++ scripts/ftpmaster-tools/sync-source.py 2010-09-02 16:32:16 +0000
@@ -170,7 +170,7 @@
170 if closes:170 if closes:
171 changes += "Closes: %s\n" % (" ".join(closes))171 changes += "Closes: %s\n" % (" ".join(closes))
172 if lp_closes:172 if lp_closes:
173 changes += "Launchpad-Bugs-Fixed: %s\n" % (" ".join(lp_closes))173 changes += "Launchpad-bugs-fixed: %s\n" % (" ".join(lp_closes))
174 changes += "Changes: \n"174 changes += "Changes: \n"
175 changes += changelog175 changes += changelog
176 changes += "Files: \n"176 changes += "Files: \n"

Subscribers

People subscribed via source and target branches

to status/vote changes: