1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
|
= NascentUpload Epoch Handling =
NascentUpload class supports 'epoch' on versions as specified by:
http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
Note that for this tests we already have getUploadFor{Source, Binary}
helper functions added in the globals by test_nascentupload_documentation.py.
Ubuntu/hoary in sampledata is ready to receive uploads in RELEASE
pocket.
>>> from lp.registry.interfaces.distribution import (
... IDistributionSet)
>>> ubuntu = getUtility(IDistributionSet)['ubuntu']
>>> hoary = ubuntu.getSeries('hoary')
>>> print hoary.status.name
DEVELOPMENT
== Epoch Version Conflicts ==
Debian-like archives don't include epochs in the version specified in
the filename of pool files.
This makes it possible for packages with different versions to include
the same filename, for instance:
* source 'bar' version '1.0-1' uses 'bar_1.0-1.diff.gz'
* source 'bar' version 1:1.0-1' also uses 'bar_1.0-1.diff.gz'
Because of this, we need to be careful when publishing to the archive
to ensure that published files don't get overwritten.
In Soyuz we try to catch such situations by performing a file lookup in the
archive against the proposed source files before 'accepting' it.
=== Collision in Upload-Time ===
When the 'non-epoched' version is already published before uploading
the candidate, we need to detect collisions at upload-time, returning
a rejection email to the user.
Upload and publish 'non-epoched' version:
>>> bar_src_upload = getUploadForSource(
... 'suite/bar_1.0-1/bar_1.0-1_source.changes')
>>> bar_src_upload.process()
>>> result = bar_src_upload.do_accept()
>>> bar_src_queue_noepoch = bar_src_upload.queue_root
>>> bar_src_queue_noepoch.displayversion
u'1.0-1'
>>> bar_src_queue_noepoch.status.name
'NEW'
>>> bar_src_queue_noepoch.setAccepted()
>>> pub_records = bar_src_queue_noepoch.realiseUpload()
>>> bar_src_queue_noepoch.status.name
'DONE'
Upload 'epoched' bar version:
>>> bar_src_upload = getUploadForSource(
... 'suite/bar_1.0-1_epoched/bar_1.0-1_source.changes')
>>> bar_src_upload.process()
>>> print bar_src_upload.rejection_message
File bar_1.0-1.diff.gz already exists in Primary Archive for Ubuntu
Linux, but uploaded version has different contents. See more
information about this error in
https://help.launchpad.net/Packaging/UploadErrors.
Files specified in DSC are broken or missing, skipping package
unpack verification.
We rely on uploadprocessor to abort the transaction at this point not
storing the respective SourcePackageRelease.
Clean up this change and carry on:
>>> from canonical.database.sqlbase import rollback
>>> rollback()
=== Collision in queue DONE ===
When the 'non-epoched' version is still in queue, we need to identify
collisions when publishing the new candidate:
Upload 'non-epoched' bar source:
>>> bar_src_upload = getUploadForSource(
... 'suite/bar_1.0-1/bar_1.0-1_source.changes')
>>> bar_src_upload.process()
>>> result = bar_src_upload.do_accept()
>>> bar_src_queue_noepoch = bar_src_upload.queue_root
>>> bar_src_queue_noepoch.status.name
'NEW'
Upload 'epoched' bar source :
>>> bar_src_upload = getUploadForSource(
... 'suite/bar_1.0-1_epoched/bar_1.0-1_source.changes')
>>> bar_src_upload.process()
>>> result = bar_src_upload.do_accept()
>>> bar_src_queue_epoch = bar_src_upload.queue_root
>>> bar_src_queue_epoch.status.name
'NEW'
Upload a newer'epoched' bar source :
>>> bar_src_upload = getUploadForSource(
... 'suite/bar_1.0-2_epoched/bar_1.0-2_source.changes')
>>> bar_src_upload.process()
>>> result = bar_src_upload.do_accept()
>>> bar_src_queue_epoch2 = bar_src_upload.queue_root
>>> bar_src_queue_epoch2.status.name
'NEW'
Accept all bar sources:
>>> bar_src_queue_noepoch.displayversion
u'1.0-1'
>>> bar_src_queue_noepoch.setAccepted()
>>> bar_src_queue_noepoch.status.name
'ACCEPTED'
>>> bar_src_queue_epoch.displayversion
u'1:1.0-1'
>>> bar_src_queue_epoch.setAccepted()
>>> bar_src_queue_epoch.status.name
'ACCEPTED'
>>> bar_src_queue_epoch2.displayversion
u'1:1.0-2'
>>> bar_src_queue_epoch2.setAccepted()
>>> bar_src_queue_epoch2.status.name
'ACCEPTED'
Published the 'non-epoched' bar source version as the base package:
>>> pub_records = bar_src_queue_noepoch.realiseUpload()
>>> bar_src_queue_noepoch.status.name
'DONE'
When publishing the 'epoched' bar source the collision is detected:
>>> bar_src_queue_epoch.realiseUpload()
Traceback (most recent call last):
...
QueueInconsistentStateError: bar_1.0-1.diff.gz is already published in archive for hoary
>>> bar_src_queue_epoch.status.name
'ACCEPTED'
At this point the archive-admins can 'reject' the record manually or
it will be ignored (with the error message below) every cron.daily cycle.
>>> bar_src_queue_epoch.setRejected()
>>> bar_src_queue_epoch.status.name
'REJECTED'
We also detect a collision when publishing the newer 'epoched' version
containing a orig file with diferent contents than the one already
published in 'non-epoched' version:
>>> bar_src_queue_epoch2.realiseUpload()
Traceback (most recent call last):
...
QueueInconsistentStateError: bar_1.0.orig.tar.gz is already published in archive for hoary with a different SHA1 hash (e918d6f5ec2184ae1d795a130da36c9a82c4beaf != 73a04163fee97fd2257ab266bd48f1d3d528e012)
>>> bar_src_queue_epoch2.status.name
'ACCEPTED'
Similar to what happens to the 'epoched' version, the ignored queue
item should be rejected:
>>> bar_src_queue_epoch2.setRejected()
>>> bar_src_queue_epoch2.status.name
'REJECTED'
Clean up this change and carry on:
>>> rollback()
== Dealing with Epochs and diverging binary versions ==
Let's process an source upload and ensure that the resulting
SourcePackageRelease record store a proper 'version':
>>> bar_src_upload = getUploadForSource(
... 'suite/bar_1.0-9/bar_1.0-9_source.changes')
>>> bar_src_upload.process()
>>> result = bar_src_upload.do_accept()
For source uploads, Changes.version == DSC.version == SPR.version:
>>> bar_src_upload.changes.version
'1:1.0-9'
>>> bar_src_upload.changes.dsc.dsc_version
'1:1.0-9'
>>> bar_src_queue = bar_src_upload.queue_root
>>> bar_spr = bar_src_queue.sources[0].sourcepackagerelease
>>> bar_spr.version
u'1:1.0-9'
>>> from lp.registry.interfaces.pocket import PackagePublishingPocket
>>> from lp.soyuz.interfaces.publishing import IPublishingSet
>>> getUtility(IPublishingSet).newSourcePublication(
... bar_src_upload.policy.distro.main_archive, bar_spr,
... bar_src_upload.policy.distroseries, bar_spr.component,
... bar_spr.section, PackagePublishingPocket.RELEASE)
<SourcePackagePublishingHistory at ...>
Let's accept the source and claim 'build from accepted' to process the
respective binary:
>>> bar_src_queue.status.name
'NEW'
>>> bar_src_queue.setAccepted()
>>> bar_src_queue.status.name
'ACCEPTED'
For a binary upload we expect the same, a BinaryPackageRelease
'version' that includes 'epoch':
>>> bar_bin_upload = getUploadForBinary(
... 'suite/bar_1.0-9_binary/bar_1.0-9_i386.changes')
>>> bar_bin_upload.process()
>>> result = bar_bin_upload.do_accept()
>>> bar_bin_queue = bar_bin_upload.queue_root
>>> bar_bin_queue.status.name
'NEW'
The Changesfile version always refers to the source version and the
binary versions included in the upload can diverge between themselves
and from the source version.
>>> bar_bin_upload.changes.version
'1:1.0-9'
>>> deb_file = bar_bin_upload.changes.files[0]
>>> deb_file.filename
'bar_6.6.6_i386.deb'
>>> deb_file.version
'1:1.0-9'
>>> deb_file.source_version
'1:1.0-9'
>>> deb_file.control_version
'1:6.6.6'
Anyway, the proper value for BinaryPackageRelease.version is the
version stored in the binary control file:
>>> bar_bpr = bar_bin_queue.builds[0].build.binarypackages[0]
>>> bar_bpr.version
u'1:6.6.6'
|