Merge ~cjwatson/launchpad:diskpool-add-source-version into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: c16ac81d9570472366ba50b3c1d07147166cec81
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:diskpool-add-source-version
Merge into: launchpad:master
Prerequisite: ~cjwatson/launchpad:diskpool-add-archive
Diff against target: 888 lines (+191/-107)
12 files modified
lib/lp/archivepublisher/artifactory.py (+24/-17)
lib/lp/archivepublisher/deathrow.py (+10/-8)
lib/lp/archivepublisher/diskpool.py (+27/-22)
lib/lp/archivepublisher/model/ftparchive.py (+8/-1)
lib/lp/archivepublisher/publishing.py (+4/-3)
lib/lp/archivepublisher/tests/deathrow.txt (+1/-0)
lib/lp/archivepublisher/tests/test_artifactory.py (+63/-28)
lib/lp/archivepublisher/tests/test_deathrow.py (+1/-0)
lib/lp/archivepublisher/tests/test_ftparchive.py (+13/-12)
lib/lp/archivepublisher/tests/test_pool.py (+29/-13)
lib/lp/archivepublisher/tests/test_publisher.py (+6/-0)
lib/lp/soyuz/model/publishing.py (+5/-3)
Reviewer Review Type Date Requested Status
Jürgen Gmach Approve
Review via email: mp+423537@code.launchpad.net

Commit message

Tell DiskPool about source version when adding/removing files

Description of the change

Some repository formats, such as Python indexes, organize files by version as well as by name. To accommodate this, tell the disk pool about the source package version as well as the source package name when adding or removing files. The Artifactory pool implementation also needs to store this in a property so that it can construct an entry for the file when updating its properties.

To post a comment you must log in.
Revision history for this message
Jürgen Gmach (jugmac00) :
review: Approve
Revision history for this message
Colin Watson (cjwatson) :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/lib/lp/archivepublisher/artifactory.py b/lib/lp/archivepublisher/artifactory.py
index 2873855..53b43a6 100644
--- a/lib/lp/archivepublisher/artifactory.py
+++ b/lib/lp/archivepublisher/artifactory.py
@@ -44,9 +44,12 @@ from lp.soyuz.interfaces.publishing import (
44class ArtifactoryPoolEntry:44class ArtifactoryPoolEntry:
4545
46 def __init__(self, archive: IArchive, rootpath: ArtifactoryPath,46 def __init__(self, archive: IArchive, rootpath: ArtifactoryPath,
47 source: str, filename: str, logger: logging.Logger) -> None:47 source_name: str, source_version: str, filename: str,
48 logger: logging.Logger) -> None:
49 self.archive = archive
48 self.rootpath = rootpath50 self.rootpath = rootpath
49 self.source = source51 self.source_name = source_name
52 self.source_version = source_version
50 self.filename = filename53 self.filename = filename
51 self.logger = logger54 self.logger = logger
5255
@@ -60,7 +63,7 @@ class ArtifactoryPoolEntry:
60 # the pool structure, and doing so would introduce significant63 # the pool structure, and doing so would introduce significant
61 # complications in terms of having to keep track of components just64 # complications in terms of having to keep track of components just
62 # in order to update an artifact's properties.65 # in order to update an artifact's properties.
63 return self.rootpath / poolify(self.source) / self.filename66 return self.rootpath / poolify(self.source_name) / self.filename
6467
65 def makeReleaseID(self, pub_file: IPackageReleaseFile) -> str:68 def makeReleaseID(self, pub_file: IPackageReleaseFile) -> str:
66 """69 """
@@ -129,7 +132,8 @@ class ArtifactoryPoolEntry:
129 """132 """
130 properties = {}133 properties = {}
131 properties["launchpad.release-id"] = [release_id]134 properties["launchpad.release-id"] = [release_id]
132 properties["launchpad.source-name"] = [self.source]135 properties["launchpad.source-name"] = [self.source_name]
136 properties["launchpad.source-version"] = [self.source_version]
133 if publications:137 if publications:
134 archives = {publication.archive for publication in publications}138 archives = {publication.archive for publication in publications}
135 if len(archives) > 1:139 if len(archives) > 1:
@@ -259,12 +263,14 @@ class ArtifactoryPool:
259 session.auth = XJFrogArtApiAuth(write_creds.split(":", 1)[1])263 session.auth = XJFrogArtApiAuth(write_creds.split(":", 1)[1])
260 return session264 return session
261265
262 def _getEntry(self, sourcename, file) -> ArtifactoryPoolEntry:266 def _getEntry(self, source_name: str, source_version: str,
267 file: str) -> ArtifactoryPoolEntry:
263 """See `DiskPool._getEntry`."""268 """See `DiskPool._getEntry`."""
264 return ArtifactoryPoolEntry(269 return ArtifactoryPoolEntry(
265 self.archive, self.rootpath, sourcename, file, self.logger)270 self.archive, self.rootpath, source_name, source_version, file,
271 self.logger)
266272
267 def pathFor(self, comp: str, source: str,273 def pathFor(self, comp: str, source_name: str, source_version: str,
268 file: Optional[str] = None) -> Path:274 file: Optional[str] = None) -> Path:
269 """Return the path for the given pool folder or file.275 """Return the path for the given pool folder or file.
270276
@@ -279,16 +285,17 @@ class ArtifactoryPool:
279 # the pool structure, and doing so would introduce significant285 # the pool structure, and doing so would introduce significant
280 # complications in terms of having to keep track of components just286 # complications in terms of having to keep track of components just
281 # in order to update an artifact's properties.287 # in order to update an artifact's properties.
282 path = self.rootpath / poolify(source)288 path = self.rootpath / poolify(source_name)
283 if file:289 if file:
284 path = path / file290 path = path / file
285 return path291 return path
286292
287 def addFile(self, component: str, sourcename: str, filename: str,293 def addFile(self, component: str, source_name: str, source_version: str,
288 pub_file: IPackageReleaseFile):294 filename: str, pub_file: IPackageReleaseFile):
289 """Add a file with the given contents to the pool.295 """Add a file with the given contents to the pool.
290296
291 `sourcename` and `filename` are used to calculate the location.297 `source_name`, `source_version`, and `filename` are used to
298 calculate the location.
292299
293 pub_file is an `IPackageReleaseFile` providing the file's contents300 pub_file is an `IPackageReleaseFile` providing the file's contents
294 and SHA-1 hash. The SHA-1 hash is used to compare the given file301 and SHA-1 hash. The SHA-1 hash is used to compare the given file
@@ -308,10 +315,10 @@ class ArtifactoryPool:
308 This is similar to `DiskPool.addFile`, except that there is no315 This is similar to `DiskPool.addFile`, except that there is no
309 symlink handling and the component is ignored.316 symlink handling and the component is ignored.
310 """317 """
311 entry = self._getEntry(sourcename, filename)318 entry = self._getEntry(source_name, source_version, filename)
312 return entry.addFile(pub_file)319 return entry.addFile(pub_file)
313320
314 def removeFile(self, component: str, sourcename: str,321 def removeFile(self, component: str, source_name: str, source_version: str,
315 filename: str) -> int:322 filename: str) -> int:
316 """Remove the specified file from the pool.323 """Remove the specified file from the pool.
317324
@@ -324,13 +331,13 @@ class ArtifactoryPool:
324 This is similar to `DiskPool.removeFile`, except that there is no331 This is similar to `DiskPool.removeFile`, except that there is no
325 symlink handling and the component is ignored.332 symlink handling and the component is ignored.
326 """333 """
327 entry = self._getEntry(sourcename, filename)334 entry = self._getEntry(source_name, source_version, filename)
328 return entry.removeFile()335 return entry.removeFile()
329336
330 def updateProperties(self, sourcename, filename, publications,337 def updateProperties(self, source_name: str, source_version: str,
331 old_properties=None):338 filename: str, publications, old_properties=None):
332 """Update a file's properties in Artifactory."""339 """Update a file's properties in Artifactory."""
333 entry = self._getEntry(sourcename, filename)340 entry = self._getEntry(source_name, source_version, filename)
334 entry.updateProperties(publications, old_properties=old_properties)341 entry.updateProperties(publications, old_properties=old_properties)
335342
336 def getArtifactPatterns(self, repository_format):343 def getArtifactPatterns(self, repository_format):
diff --git a/lib/lp/archivepublisher/deathrow.py b/lib/lp/archivepublisher/deathrow.py
index 06e430a..9071a53 100644
--- a/lib/lp/archivepublisher/deathrow.py
+++ b/lib/lp/archivepublisher/deathrow.py
@@ -87,10 +87,10 @@ class DeathRow:
87 removed."""87 removed."""
88 if dry_run:88 if dry_run:
89 # Don't actually remove the files if we are dry running89 # Don't actually remove the files if we are dry running
90 def _mockRemoveFile(cn, sn, fn):90 def _mockRemoveFile(cn, sn, sv, fn):
91 self.logger.debug("(Not really!) removing %s %s/%s" %91 self.logger.debug("(Not really!) removing %s %s/%s/%s" %
92 (cn, sn, fn))92 (cn, sn, sv, fn))
93 fullpath = self.diskpool.pathFor(cn, sn, fn)93 fullpath = self.diskpool.pathFor(cn, sn, sv, fn)
94 if not fullpath.exists():94 if not fullpath.exists():
95 raise NotInPool95 raise NotInPool
96 return fullpath.lstat().st_size96 return fullpath.lstat().st_size
@@ -227,9 +227,10 @@ class DeathRow:
227227
228 # Calculating the file path in pool.228 # Calculating the file path in pool.
229 pub_file_details = (229 pub_file_details = (
230 pub_file.libraryfile.filename,
231 pub_record.source_package_name,
232 pub_record.component_name,230 pub_record.component_name,
231 pub_record.source_package_name,
232 pub_record.source_package_version,
233 pub_file.libraryfile.filename,
233 )234 )
234 file_path = str(self.diskpool.pathFor(*pub_file_details))235 file_path = str(self.diskpool.pathFor(*pub_file_details))
235236
@@ -264,10 +265,11 @@ class DeathRow:
264 "Removing %s files marked for reaping" % len(condemned_files))265 "Removing %s files marked for reaping" % len(condemned_files))
265266
266 for condemned_file in sorted(condemned_files, reverse=True):267 for condemned_file in sorted(condemned_files, reverse=True):
267 file_name, source_name, component_name = details[condemned_file]268 component_name, source_name, source_version, file_name = (
269 details[condemned_file])
268 try:270 try:
269 bytes += self._removeFile(271 bytes += self._removeFile(
270 component_name, source_name, file_name)272 component_name, source_name, source_version, file_name)
271 except NotInPool as info:273 except NotInPool as info:
272 # It's safe for us to let this slide because it means that274 # It's safe for us to let this slide because it means that
273 # the file is already gone.275 # the file is already gone.
diff --git a/lib/lp/archivepublisher/diskpool.py b/lib/lp/archivepublisher/diskpool.py
index 620c728..01ce763 100644
--- a/lib/lp/archivepublisher/diskpool.py
+++ b/lib/lp/archivepublisher/diskpool.py
@@ -139,11 +139,13 @@ class DiskPoolEntry:
139 require manual removal after further investigation.139 require manual removal after further investigation.
140 """140 """
141 def __init__(self, archive: IArchive, rootpath: Path, temppath: Path,141 def __init__(self, archive: IArchive, rootpath: Path, temppath: Path,
142 source: str, filename: str, logger: logging.Logger) -> None:142 source_name: str, source_version: str, filename: str,
143 logger: logging.Logger) -> None:
143 self.archive = archive144 self.archive = archive
144 self.rootpath = rootpath145 self.rootpath = rootpath
145 self.temppath = temppath146 self.temppath = temppath
146 self.source = source147 self.source_name = source_name
148 self.source_version = source_version
147 self.filename = filename149 self.filename = filename
148 self.logger = logger150 self.logger = logger
149151
@@ -165,7 +167,9 @@ class DiskPoolEntry:
165167
166 def pathFor(self, component: str) -> Path:168 def pathFor(self, component: str) -> Path:
167 """Return the path for this file in the given component."""169 """Return the path for this file in the given component."""
168 return self.rootpath / poolify(self.source, component) / self.filename170 return (
171 self.rootpath / poolify(self.source_name, component) /
172 self.filename)
169173
170 def preferredComponent(self, add: Optional[str] = None,174 def preferredComponent(self, add: Optional[str] = None,
171 remove: Optional[str] = None) -> Optional[str]:175 remove: Optional[str] = None) -> Optional[str]:
@@ -230,7 +234,7 @@ class DiskPoolEntry:
230 assert not targetpath.exists()234 assert not targetpath.exists()
231235
232 self.debug("Making new file in %s for %s/%s" %236 self.debug("Making new file in %s for %s/%s" %
233 (component, self.source, self.filename))237 (component, self.source_name, self.filename))
234238
235 file_to_write = _diskpool_atomicfile(239 file_to_write = _diskpool_atomicfile(
236 targetpath, "wb", rootpath=self.temppath)240 targetpath, "wb", rootpath=self.temppath)
@@ -253,13 +257,13 @@ class DiskPoolEntry:
253 if not self.file_component:257 if not self.file_component:
254 raise NotInPool(258 raise NotInPool(
255 "File for removing %s %s/%s is not in pool, skipping." %259 "File for removing %s %s/%s is not in pool, skipping." %
256 (component, self.source, self.filename))260 (component, self.source_name, self.filename))
257261
258 # Okay, it's there, if it's a symlink then we need to remove262 # Okay, it's there, if it's a symlink then we need to remove
259 # it simply.263 # it simply.
260 if component in self.symlink_components:264 if component in self.symlink_components:
261 self.debug("Removing %s %s/%s as it is a symlink"265 self.debug("Removing %s %s/%s as it is a symlink"
262 % (component, self.source, self.filename))266 % (component, self.source_name, self.filename))
263 # ensure we are removing a symbolic link and267 # ensure we are removing a symbolic link and
264 # it is published in one or more components268 # it is published in one or more components
265 link_path = self.pathFor(component)269 link_path = self.pathFor(component)
@@ -269,13 +273,13 @@ class DiskPoolEntry:
269 if component != self.file_component:273 if component != self.file_component:
270 raise MissingSymlinkInPool(274 raise MissingSymlinkInPool(
271 "Symlink for %s/%s in %s is missing, skipping." %275 "Symlink for %s/%s in %s is missing, skipping." %
272 (self.source, self.filename, component))276 (self.source_name, self.filename, component))
273277
274 # It's not a symlink, this means we need to check whether we278 # It's not a symlink, this means we need to check whether we
275 # have symlinks or not.279 # have symlinks or not.
276 if len(self.symlink_components) == 0:280 if len(self.symlink_components) == 0:
277 self.debug("Removing %s/%s from %s" %281 self.debug("Removing %s/%s from %s" %
278 (self.source, self.filename, component))282 (self.source_name, self.filename, component))
279 else:283 else:
280 # The target for removal is the real file, and there are symlinks284 # The target for removal is the real file, and there are symlinks
281 # pointing to it. In order to avoid breakage, we need to first285 # pointing to it. In order to avoid breakage, we need to first
@@ -398,33 +402,34 @@ class DiskPool:
398 self.entries = {}402 self.entries = {}
399 self.logger = logger403 self.logger = logger
400404
401 def _getEntry(self, sourcename: str, file: str) -> DiskPoolEntry:405 def _getEntry(self, source_name: str, source_version: str,
402 """Return a new DiskPoolEntry for the given sourcename and file."""406 file: str) -> DiskPoolEntry:
407 """Return a new DiskPoolEntry for the given source and file."""
403 return DiskPoolEntry(408 return DiskPoolEntry(
404 self.archive, self.rootpath, self.temppath, sourcename,409 self.archive, self.rootpath, self.temppath, source_name,
405 file, self.logger)410 source_version, file, self.logger)
406411
407 def pathFor(self, comp: str, source: str,412 def pathFor(self, comp: str, source_name: str, source_version: str,
408 file: Optional[str] = None) -> Path:413 file: Optional[str] = None) -> Path:
409 """Return the path for the given pool folder or file.414 """Return the path for the given pool folder or file.
410415
411 If file is none, the path to the folder containing all packages416 If file is none, the path to the folder containing all packages
412 for the given component and source package name will be returned.417 for the given component and source package will be returned.
413418
414 If file is specified, the path to the specific package file will419 If file is specified, the path to the specific package file will
415 be returned.420 be returned.
416 """421 """
417 path = self.rootpath / poolify(source, comp)422 path = self.rootpath / poolify(source_name, comp)
418 if file:423 if file:
419 path = path / file424 path = path / file
420 return path425 return path
421426
422 def addFile(self, component: str, sourcename: str, filename: str,427 def addFile(self, component: str, source_name: str, source_version: str,
423 pub_file: IPackageReleaseFile):428 filename: str, pub_file: IPackageReleaseFile):
424 """Add a file with the given contents to the pool.429 """Add a file with the given contents to the pool.
425430
426 Component, sourcename and filename are used to calculate the431 `component`, `source_name`, `source_version`, and `filename` are
427 on-disk location.432 used to calculate the on-disk location.
428433
429 pub_file is an `IPackageReleaseFile` providing the file's contents434 pub_file is an `IPackageReleaseFile` providing the file's contents
430 and SHA-1 hash. The SHA-1 hash is used to compare the given file435 and SHA-1 hash. The SHA-1 hash is used to compare the given file
@@ -450,10 +455,10 @@ class DiskPool:
450 either as a file or a symlink, and the hash check passes,455 either as a file or a symlink, and the hash check passes,
451 results.NONE will be returned and nothing will be done.456 results.NONE will be returned and nothing will be done.
452 """457 """
453 entry = self._getEntry(sourcename, filename)458 entry = self._getEntry(source_name, source_version, filename)
454 return entry.addFile(component, pub_file)459 return entry.addFile(component, pub_file)
455460
456 def removeFile(self, component: str, sourcename: str,461 def removeFile(self, component: str, source_name: str, source_version: str,
457 filename: str) -> int:462 filename: str) -> int:
458 """Remove the specified file from the pool.463 """Remove the specified file from the pool.
459464
@@ -469,5 +474,5 @@ class DiskPool:
469 will be deleted, and the file will be moved to replace it. The474 will be deleted, and the file will be moved to replace it. The
470 size of the deleted symlink will be returned.475 size of the deleted symlink will be returned.
471 """476 """
472 entry = self._getEntry(sourcename, filename)477 entry = self._getEntry(source_name, source_version, filename)
473 return entry.removeFile(component)478 return entry.removeFile(component)
diff --git a/lib/lp/archivepublisher/model/ftparchive.py b/lib/lp/archivepublisher/model/ftparchive.py
index 469b1cb..7e94441 100644
--- a/lib/lp/archivepublisher/model/ftparchive.py
+++ b/lib/lp/archivepublisher/model/ftparchive.py
@@ -693,8 +693,15 @@ class FTPArchiveHandler:
693693
694 def updateFileList(sourcepackagename, filename, component,694 def updateFileList(sourcepackagename, filename, component,
695 architecturetag=None):695 architecturetag=None):
696 # DiskPool.pathFor takes a source package version parameter. We
697 # could fetch that in getSourceFiles/getBinaryFiles and pass it
698 # down here. However, it adds another column to a query with an
699 # already large number of rows, and it's only needed for
700 # non-Debian-format archives, which by definition aren't
701 # involved here; so we just pass None as the version.
696 ondiskname = str(702 ondiskname = str(
697 self._diskpool.pathFor(component, sourcepackagename, filename))703 self._diskpool.pathFor(
704 component, sourcepackagename, None, filename))
698 if architecturetag is None:705 if architecturetag is None:
699 architecturetag = "source"706 architecturetag = "source"
700 filelist[component][architecturetag].append(ondiskname)707 filelist[component][architecturetag].append(ondiskname)
diff --git a/lib/lp/archivepublisher/publishing.py b/lib/lp/archivepublisher/publishing.py
index 69fb7e3..b0ddd32 100644
--- a/lib/lp/archivepublisher/publishing.py
+++ b/lib/lp/archivepublisher/publishing.py
@@ -752,12 +752,13 @@ class Publisher:
752 for path, properties in sorted(artifacts.items()):752 for path, properties in sorted(artifacts.items()):
753 release_id = properties.get("launchpad.release-id")753 release_id = properties.get("launchpad.release-id")
754 source_name = properties.get("launchpad.source-name")754 source_name = properties.get("launchpad.source-name")
755 if not release_id or not source_name:755 source_version = properties.get("launchpad.source-version")
756 if not release_id or not source_name or not source_version:
756 # Skip any files that Launchpad didn't put in Artifactory.757 # Skip any files that Launchpad didn't put in Artifactory.
757 continue758 continue
758 self._diskpool.updateProperties(759 self._diskpool.updateProperties(
759 source_name[0], path.name, pubs_by_id.get(release_id[0]),760 source_name[0], source_version[0], path.name,
760 old_properties=properties)761 pubs_by_id.get(release_id[0]), old_properties=properties)
761762
762 def D_writeReleaseFiles(self, is_careful):763 def D_writeReleaseFiles(self, is_careful):
763 """Write out the Release files for the provided distribution.764 """Write out the Release files for the provided distribution.
diff --git a/lib/lp/archivepublisher/tests/deathrow.txt b/lib/lp/archivepublisher/tests/deathrow.txt
index 92b0752..5f8ac79 100644
--- a/lib/lp/archivepublisher/tests/deathrow.txt
+++ b/lib/lp/archivepublisher/tests/deathrow.txt
@@ -208,6 +208,7 @@ Publish files on disk and build a list of all created file paths
208 ... file_path = quiet_disk_pool.pathFor(208 ... file_path = quiet_disk_pool.pathFor(
209 ... pub.component.name,209 ... pub.component.name,
210 ... pub.source_package_name,210 ... pub.source_package_name,
211 ... pub.source_package_version,
211 ... pub_file.libraryfile.filename212 ... pub_file.libraryfile.filename
212 ... )213 ... )
213 ... unique_file_paths.add(file_path)214 ... unique_file_paths.add(file_path)
diff --git a/lib/lp/archivepublisher/tests/test_artifactory.py b/lib/lp/archivepublisher/tests/test_artifactory.py
index 49f7ace..241f277 100644
--- a/lib/lp/archivepublisher/tests/test_artifactory.py
+++ b/lib/lp/archivepublisher/tests/test_artifactory.py
@@ -62,7 +62,8 @@ class ArtifactoryPoolTestingFile(PoolTestingFile):
62 return super().checkIsFile(None)62 return super().checkIsFile(None)
6363
64 def getProperties(self):64 def getProperties(self):
65 path = self.pool.pathFor(None, self.sourcename, self.filename)65 path = self.pool.pathFor(
66 None, self.source_name, self.source_version, self.filename)
66 return path.properties67 return path.properties
6768
6869
@@ -81,8 +82,9 @@ class TestArtifactoryPool(TestCase):
8182
82 def test_addFile(self):83 def test_addFile(self):
83 foo = ArtifactoryPoolTestingFile(84 foo = ArtifactoryPoolTestingFile(
84 self.pool, "foo", "foo-1.0.deb",85 pool=self.pool, source_name="foo", source_version="1.0",
85 release_type=FakeReleaseType.BINARY, release_id=1)86 filename="foo-1.0.deb", release_type=FakeReleaseType.BINARY,
87 release_id=1)
86 self.assertFalse(foo.checkIsFile())88 self.assertFalse(foo.checkIsFile())
87 result = foo.addToPool()89 result = foo.addToPool()
88 self.assertEqual(self.pool.results.FILE_ADDED, result)90 self.assertEqual(self.pool.results.FILE_ADDED, result)
@@ -91,13 +93,15 @@ class TestArtifactoryPool(TestCase):
91 {93 {
92 "launchpad.release-id": ["binary:1"],94 "launchpad.release-id": ["binary:1"],
93 "launchpad.source-name": ["foo"],95 "launchpad.source-name": ["foo"],
96 "launchpad.source-version": ["1.0"],
94 },97 },
95 foo.getProperties())98 foo.getProperties())
9699
97 def test_addFile_exists_identical(self):100 def test_addFile_exists_identical(self):
98 foo = ArtifactoryPoolTestingFile(101 foo = ArtifactoryPoolTestingFile(
99 self.pool, "foo", "foo-1.0.deb",102 pool=self.pool, source_name="foo", source_version="1.0",
100 release_type=FakeReleaseType.BINARY, release_id=1)103 filename="foo-1.0.deb", release_type=FakeReleaseType.BINARY,
104 release_id=1)
101 foo.addToPool()105 foo.addToPool()
102 self.assertTrue(foo.checkIsFile())106 self.assertTrue(foo.checkIsFile())
103 result = foo.addToPool()107 result = foo.addToPool()
@@ -106,15 +110,18 @@ class TestArtifactoryPool(TestCase):
106110
107 def test_addFile_exists_overwrite(self):111 def test_addFile_exists_overwrite(self):
108 foo = ArtifactoryPoolTestingFile(112 foo = ArtifactoryPoolTestingFile(
109 self.pool, "foo", "foo-1.0.deb",113 pool=self.pool, source_name="foo", source_version="1.0",
110 release_type=FakeReleaseType.BINARY, release_id=1)114 filename="foo-1.0.deb", release_type=FakeReleaseType.BINARY,
115 release_id=1)
111 foo.addToPool()116 foo.addToPool()
112 self.assertTrue(foo.checkIsFile())117 self.assertTrue(foo.checkIsFile())
113 foo.contents = b"different"118 foo.contents = b"different"
114 self.assertRaises(PoolFileOverwriteError, foo.addToPool)119 self.assertRaises(PoolFileOverwriteError, foo.addToPool)
115120
116 def test_removeFile(self):121 def test_removeFile(self):
117 foo = ArtifactoryPoolTestingFile(self.pool, "foo", "foo-1.0.deb")122 foo = ArtifactoryPoolTestingFile(
123 pool=self.pool, source_name="foo", source_version="1.0",
124 filename="foo-1.0.deb")
118 foo.addToPool()125 foo.addToPool()
119 self.assertTrue(foo.checkIsFile())126 self.assertTrue(foo.checkIsFile())
120 size = foo.removeFromPool()127 size = foo.removeFromPool()
@@ -145,23 +152,28 @@ class TestArtifactoryPool(TestCase):
145 # with it. This test mainly ensures that we transform the response152 # with it. This test mainly ensures that we transform the response
146 # correctly.153 # correctly.
147 ArtifactoryPoolTestingFile(154 ArtifactoryPoolTestingFile(
148 self.pool, "foo", "foo-1.0.deb",155 pool=self.pool, source_name="foo", source_version="1.0",
149 release_type=FakeReleaseType.BINARY, release_id=1).addToPool()156 filename="foo-1.0.deb", release_type=FakeReleaseType.BINARY,
157 release_id=1).addToPool()
150 ArtifactoryPoolTestingFile(158 ArtifactoryPoolTestingFile(
151 self.pool, "foo", "foo-1.1.deb",159 pool=self.pool, source_name="foo", source_version="1.1",
152 release_type=FakeReleaseType.BINARY, release_id=2).addToPool()160 filename="foo-1.1.deb", release_type=FakeReleaseType.BINARY,
161 release_id=2).addToPool()
153 ArtifactoryPoolTestingFile(162 ArtifactoryPoolTestingFile(
154 self.pool, "bar", "bar-1.0.whl",163 pool=self.pool, source_name="bar", source_version="1.0",
155 release_type=FakeReleaseType.BINARY, release_id=3).addToPool()164 filename="bar-1.0.whl", release_type=FakeReleaseType.BINARY,
165 release_id=3).addToPool()
156 self.assertEqual(166 self.assertEqual(
157 {167 {
158 PurePath("pool/f/foo/foo-1.0.deb"): {168 PurePath("pool/f/foo/foo-1.0.deb"): {
159 "launchpad.release-id": ["binary:1"],169 "launchpad.release-id": ["binary:1"],
160 "launchpad.source-name": ["foo"],170 "launchpad.source-name": ["foo"],
171 "launchpad.source-version": ["1.0"],
161 },172 },
162 PurePath("pool/f/foo/foo-1.1.deb"): {173 PurePath("pool/f/foo/foo-1.1.deb"): {
163 "launchpad.release-id": ["binary:2"],174 "launchpad.release-id": ["binary:2"],
164 "launchpad.source-name": ["foo"],175 "launchpad.source-name": ["foo"],
176 "launchpad.source-version": ["1.1"],
165 },177 },
166 },178 },
167 self.pool.getAllArtifacts(179 self.pool.getAllArtifacts(
@@ -171,6 +183,7 @@ class TestArtifactoryPool(TestCase):
171 PurePath("pool/b/bar/bar-1.0.whl"): {183 PurePath("pool/b/bar/bar-1.0.whl"): {
172 "launchpad.release-id": ["binary:3"],184 "launchpad.release-id": ["binary:3"],
173 "launchpad.source-name": ["bar"],185 "launchpad.source-name": ["bar"],
186 "launchpad.source-version": ["1.0"],
174 },187 },
175 },188 },
176 self.pool.getAllArtifacts(189 self.pool.getAllArtifacts(
@@ -199,7 +212,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
199 spph = self.factory.makeSourcePackagePublishingHistory(212 spph = self.factory.makeSourcePackagePublishingHistory(
200 archive=self.archive, distroseries=dses[0],213 archive=self.archive, distroseries=dses[0],
201 pocket=PackagePublishingPocket.RELEASE, component="main",214 pocket=PackagePublishingPocket.RELEASE, component="main",
202 sourcepackagename="foo")215 sourcepackagename="foo", version="1.0")
203 spr = spph.sourcepackagerelease216 spr = spph.sourcepackagerelease
204 sprf = self.factory.makeSourcePackageReleaseFile(217 sprf = self.factory.makeSourcePackageReleaseFile(
205 sourcepackagerelease=spr,218 sourcepackagerelease=spr,
@@ -210,7 +223,8 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
210 spphs.append(spph.copyTo(223 spphs.append(spph.copyTo(
211 dses[1], PackagePublishingPocket.RELEASE, self.archive))224 dses[1], PackagePublishingPocket.RELEASE, self.archive))
212 transaction.commit()225 transaction.commit()
213 self.pool.addFile(None, spr.name, sprf.libraryfile.filename, sprf)226 self.pool.addFile(
227 None, spr.name, spr.version, sprf.libraryfile.filename, sprf)
214 path = self.pool.rootpath / "f" / "foo" / "foo_1.0.dsc"228 path = self.pool.rootpath / "f" / "foo" / "foo_1.0.dsc"
215 self.assertTrue(path.exists())229 self.assertTrue(path.exists())
216 self.assertFalse(path.is_symlink())230 self.assertFalse(path.is_symlink())
@@ -218,13 +232,16 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
218 {232 {
219 "launchpad.release-id": ["source:%d" % spr.id],233 "launchpad.release-id": ["source:%d" % spr.id],
220 "launchpad.source-name": ["foo"],234 "launchpad.source-name": ["foo"],
235 "launchpad.source-version": ["1.0"],
221 },236 },
222 path.properties)237 path.properties)
223 self.pool.updateProperties(spr.name, sprf.libraryfile.filename, spphs)238 self.pool.updateProperties(
239 spr.name, spr.version, sprf.libraryfile.filename, spphs)
224 self.assertEqual(240 self.assertEqual(
225 {241 {
226 "launchpad.release-id": ["source:%d" % spr.id],242 "launchpad.release-id": ["source:%d" % spr.id],
227 "launchpad.source-name": ["foo"],243 "launchpad.source-name": ["foo"],
244 "launchpad.source-version": ["1.0"],
228 "deb.distribution": list(sorted(ds.name for ds in dses)),245 "deb.distribution": list(sorted(ds.name for ds in dses)),
229 "deb.component": ["main"],246 "deb.component": ["main"],
230 },247 },
@@ -240,10 +257,12 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
240 self.factory.makeDistroArchSeries(257 self.factory.makeDistroArchSeries(
241 distroseries=ds, architecturetag=processor.name)258 distroseries=ds, architecturetag=processor.name)
242 for ds in dses]259 for ds in dses]
260 spr = self.factory.makeSourcePackageRelease(
261 archive=self.archive, sourcepackagename="foo", version="1.0")
243 bpph = self.factory.makeBinaryPackagePublishingHistory(262 bpph = self.factory.makeBinaryPackagePublishingHistory(
244 archive=self.archive, distroarchseries=dases[0],263 archive=self.archive, distroarchseries=dases[0],
245 pocket=PackagePublishingPocket.RELEASE, component="main",264 pocket=PackagePublishingPocket.RELEASE, component="main",
246 sourcepackagename="foo", binarypackagename="foo",265 source_package_release=spr, binarypackagename="foo",
247 architecturespecific=True)266 architecturespecific=True)
248 bpr = bpph.binarypackagerelease267 bpr = bpph.binarypackagerelease
249 bpf = self.factory.makeBinaryPackageFile(268 bpf = self.factory.makeBinaryPackageFile(
@@ -256,7 +275,8 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
256 dses[1], PackagePublishingPocket.RELEASE, self.archive)[0])275 dses[1], PackagePublishingPocket.RELEASE, self.archive)[0])
257 transaction.commit()276 transaction.commit()
258 self.pool.addFile(277 self.pool.addFile(
259 None, bpr.sourcepackagename, bpf.libraryfile.filename, bpf)278 None, bpr.sourcepackagename, bpr.sourcepackageversion,
279 bpf.libraryfile.filename, bpf)
260 path = (280 path = (
261 self.pool.rootpath / "f" / "foo" /281 self.pool.rootpath / "f" / "foo" /
262 ("foo_1.0_%s.deb" % processor.name))282 ("foo_1.0_%s.deb" % processor.name))
@@ -266,14 +286,17 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
266 {286 {
267 "launchpad.release-id": ["binary:%d" % bpr.id],287 "launchpad.release-id": ["binary:%d" % bpr.id],
268 "launchpad.source-name": ["foo"],288 "launchpad.source-name": ["foo"],
289 "launchpad.source-version": ["1.0"],
269 },290 },
270 path.properties)291 path.properties)
271 self.pool.updateProperties(292 self.pool.updateProperties(
272 bpr.sourcepackagename, bpf.libraryfile.filename, bpphs)293 bpr.sourcepackagename, bpr.sourcepackageversion,
294 bpf.libraryfile.filename, bpphs)
273 self.assertEqual(295 self.assertEqual(
274 {296 {
275 "launchpad.release-id": ["binary:%d" % bpr.id],297 "launchpad.release-id": ["binary:%d" % bpr.id],
276 "launchpad.source-name": ["foo"],298 "launchpad.source-name": ["foo"],
299 "launchpad.source-version": ["1.0"],
277 "deb.distribution": list(sorted(ds.name for ds in dses)),300 "deb.distribution": list(sorted(ds.name for ds in dses)),
278 "deb.component": ["main"],301 "deb.component": ["main"],
279 "deb.architecture": [processor.name],302 "deb.architecture": [processor.name],
@@ -286,9 +309,11 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
286 dases = [309 dases = [
287 self.factory.makeDistroArchSeries(distroseries=ds)310 self.factory.makeDistroArchSeries(distroseries=ds)
288 for _ in range(2)]311 for _ in range(2)]
312 spr = self.factory.makeSourcePackageRelease(
313 archive=self.archive, sourcepackagename="foo", version="1.0")
289 bpb = self.factory.makeBinaryPackageBuild(314 bpb = self.factory.makeBinaryPackageBuild(
290 archive=self.archive, distroarchseries=dases[0],315 archive=self.archive, source_package_release=spr,
291 pocket=PackagePublishingPocket.RELEASE, sourcepackagename="foo")316 distroarchseries=dases[0], pocket=PackagePublishingPocket.RELEASE)
292 bpr = self.factory.makeBinaryPackageRelease(317 bpr = self.factory.makeBinaryPackageRelease(
293 binarypackagename="foo", build=bpb, component="main",318 binarypackagename="foo", build=bpb, component="main",
294 architecturespecific=False)319 architecturespecific=False)
@@ -302,7 +327,8 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
302 {bpr: (bpr.component, bpr.section, bpr.priority, None)})327 {bpr: (bpr.component, bpr.section, bpr.priority, None)})
303 transaction.commit()328 transaction.commit()
304 self.pool.addFile(329 self.pool.addFile(
305 None, bpr.sourcepackagename, bpf.libraryfile.filename, bpf)330 None, bpr.sourcepackagename, bpr.sourcepackageversion,
331 bpf.libraryfile.filename, bpf)
306 path = self.pool.rootpath / "f" / "foo" / "foo_1.0_all.deb"332 path = self.pool.rootpath / "f" / "foo" / "foo_1.0_all.deb"
307 self.assertTrue(path.exists())333 self.assertTrue(path.exists())
308 self.assertFalse(path.is_symlink())334 self.assertFalse(path.is_symlink())
@@ -310,14 +336,17 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
310 {336 {
311 "launchpad.release-id": ["binary:%d" % bpr.id],337 "launchpad.release-id": ["binary:%d" % bpr.id],
312 "launchpad.source-name": ["foo"],338 "launchpad.source-name": ["foo"],
339 "launchpad.source-version": ["1.0"],
313 },340 },
314 path.properties)341 path.properties)
315 self.pool.updateProperties(342 self.pool.updateProperties(
316 bpr.sourcepackagename, bpf.libraryfile.filename, bpphs)343 bpr.sourcepackagename, bpr.sourcepackageversion,
344 bpf.libraryfile.filename, bpphs)
317 self.assertEqual(345 self.assertEqual(
318 {346 {
319 "launchpad.release-id": ["binary:%d" % bpr.id],347 "launchpad.release-id": ["binary:%d" % bpr.id],
320 "launchpad.source-name": ["foo"],348 "launchpad.source-name": ["foo"],
349 "launchpad.source-version": ["1.0"],
321 "deb.distribution": [ds.name],350 "deb.distribution": [ds.name],
322 "deb.component": ["main"],351 "deb.component": ["main"],
323 "deb.architecture": list(sorted(352 "deb.architecture": list(sorted(
@@ -331,9 +360,11 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
331 ds = self.factory.makeDistroSeries(360 ds = self.factory.makeDistroSeries(
332 distribution=self.archive.distribution)361 distribution=self.archive.distribution)
333 das = self.factory.makeDistroArchSeries(distroseries=ds)362 das = self.factory.makeDistroArchSeries(distroseries=ds)
363 spr = self.factory.makeSourcePackageRelease(
364 archive=self.archive, sourcepackagename="foo", version="1.0")
334 bpb = self.factory.makeBinaryPackageBuild(365 bpb = self.factory.makeBinaryPackageBuild(
335 archive=self.archive, distroarchseries=das,366 archive=self.archive, source_package_release=spr,
336 pocket=PackagePublishingPocket.RELEASE, sourcepackagename="foo")367 distroarchseries=das, pocket=PackagePublishingPocket.RELEASE)
337 bpr = self.factory.makeBinaryPackageRelease(368 bpr = self.factory.makeBinaryPackageRelease(
338 binarypackagename="foo", build=bpb, component="main",369 binarypackagename="foo", build=bpb, component="main",
339 architecturespecific=False)370 architecturespecific=False)
@@ -347,22 +378,26 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
347 {bpr: (bpr.component, bpr.section, bpr.priority, None)})378 {bpr: (bpr.component, bpr.section, bpr.priority, None)})
348 transaction.commit()379 transaction.commit()
349 self.pool.addFile(380 self.pool.addFile(
350 None, bpr.sourcepackagename, bpf.libraryfile.filename, bpf)381 None, bpr.sourcepackagename, bpr.sourcepackageversion,
382 bpf.libraryfile.filename, bpf)
351 path = self.pool.rootpath / "f" / "foo" / "foo_1.0_all.deb"383 path = self.pool.rootpath / "f" / "foo" / "foo_1.0_all.deb"
352 path.set_properties({"deb.version": ["1.0"]}, recursive=False)384 path.set_properties({"deb.version": ["1.0"]}, recursive=False)
353 self.assertEqual(385 self.assertEqual(
354 {386 {
355 "launchpad.release-id": ["binary:%d" % bpr.id],387 "launchpad.release-id": ["binary:%d" % bpr.id],
356 "launchpad.source-name": ["foo"],388 "launchpad.source-name": ["foo"],
389 "launchpad.source-version": ["1.0"],
357 "deb.version": ["1.0"],390 "deb.version": ["1.0"],
358 },391 },
359 path.properties)392 path.properties)
360 self.pool.updateProperties(393 self.pool.updateProperties(
361 bpr.sourcepackagename, bpf.libraryfile.filename, bpphs)394 bpr.sourcepackagename, bpr.sourcepackageversion,
395 bpf.libraryfile.filename, bpphs)
362 self.assertEqual(396 self.assertEqual(
363 {397 {
364 "launchpad.release-id": ["binary:%d" % bpr.id],398 "launchpad.release-id": ["binary:%d" % bpr.id],
365 "launchpad.source-name": ["foo"],399 "launchpad.source-name": ["foo"],
400 "launchpad.source-version": ["1.0"],
366 "deb.distribution": [ds.name],401 "deb.distribution": [ds.name],
367 "deb.component": ["main"],402 "deb.component": ["main"],
368 "deb.architecture": [das.architecturetag],403 "deb.architecture": [das.architecturetag],
diff --git a/lib/lp/archivepublisher/tests/test_deathrow.py b/lib/lp/archivepublisher/tests/test_deathrow.py
index 10efb6f..9fd62e5 100644
--- a/lib/lp/archivepublisher/tests/test_deathrow.py
+++ b/lib/lp/archivepublisher/tests/test_deathrow.py
@@ -53,6 +53,7 @@ class TestDeathRow(TestCase):
53 return diskpool.pathFor(53 return diskpool.pathFor(
54 pub.component.name,54 pub.component.name,
55 pub.source_package_name,55 pub.source_package_name,
56 pub.source_package_version,
56 pub_file.libraryfile.filename)57 pub_file.libraryfile.filename)
5758
58 def assertIsFile(self, path: Path) -> None:59 def assertIsFile(self, path: Path) -> None:
diff --git a/lib/lp/archivepublisher/tests/test_ftparchive.py b/lib/lp/archivepublisher/tests/test_ftparchive.py
index 9ea5778..9b407a7 100755
--- a/lib/lp/archivepublisher/tests/test_ftparchive.py
+++ b/lib/lp/archivepublisher/tests/test_ftparchive.py
@@ -147,10 +147,11 @@ class TestFTPArchive(TestCaseWithFactory):
147 with open_func(path) as result_file:147 with open_func(path) as result_file:
148 self.assertEqual(b"", result_file.read())148 self.assertEqual(b"", result_file.read())
149149
150 def _addRepositoryFile(self, component, sourcename, leafname,150 def _addRepositoryFile(self, component, source_name, source_version,
151 samplename=None):151 leafname, samplename=None):
152 """Create a repository file."""152 """Create a repository file."""
153 fullpath = self._dp.pathFor(component, sourcename, leafname)153 fullpath = self._dp.pathFor(
154 component, source_name, source_version, leafname)
154 fullpath.parent.mkdir(parents=True, exist_ok=True)155 fullpath.parent.mkdir(parents=True, exist_ok=True)
155 if samplename is None:156 if samplename is None:
156 samplename = leafname157 samplename = leafname
@@ -515,9 +516,9 @@ class TestFTPArchive(TestCaseWithFactory):
515 self._publishDefaultFileLists(fa, 'main')516 self._publishDefaultFileLists(fa, 'main')
516517
517 # Add mentioned files in the repository pool/.518 # Add mentioned files in the repository pool/.
518 self._addRepositoryFile('main', 'tiny', 'tiny_0.1.dsc')519 self._addRepositoryFile('main', 'tiny', '0.1', 'tiny_0.1.dsc')
519 self._addRepositoryFile('main', 'tiny', 'tiny_0.1.tar.gz')520 self._addRepositoryFile('main', 'tiny', '0.1', 'tiny_0.1.tar.gz')
520 self._addRepositoryFile('main', 'tiny', 'tiny_0.1_i386.deb')521 self._addRepositoryFile('main', 'tiny', '0.1', 'tiny_0.1_i386.deb')
521522
522 # When include_long_descriptions is set, apt.conf has523 # When include_long_descriptions is set, apt.conf has
523 # LongDescription "true" for that series.524 # LongDescription "true" for that series.
@@ -649,9 +650,9 @@ class TestFTPArchive(TestCaseWithFactory):
649 fa.createEmptyPocketRequests(fullpublish=True)650 fa.createEmptyPocketRequests(fullpublish=True)
650 self._publishDefaultOverrides(fa, "main")651 self._publishDefaultOverrides(fa, "main")
651 self._publishDefaultFileLists(fa, "main")652 self._publishDefaultFileLists(fa, "main")
652 self._addRepositoryFile("main", "tiny", "tiny_0.1.dsc")653 self._addRepositoryFile("main", "tiny", "0.1", "tiny_0.1.dsc")
653 self._addRepositoryFile("main", "tiny", "tiny_0.1.tar.gz")654 self._addRepositoryFile("main", "tiny", "0.1", "tiny_0.1.tar.gz")
654 self._addRepositoryFile("main", "tiny", "tiny_0.1_i386.deb")655 self._addRepositoryFile("main", "tiny", "0.1", "tiny_0.1_i386.deb")
655 comp_dir = os.path.join(self._distsdir, "hoary-test", "main")656 comp_dir = os.path.join(self._distsdir, "hoary-test", "main")
656 os.makedirs(os.path.join(comp_dir, "signed"))657 os.makedirs(os.path.join(comp_dir, "signed"))
657 with open(os.path.join(comp_dir, "signed", "stuff"), "w"):658 with open(os.path.join(comp_dir, "signed", "stuff"), "w"):
@@ -778,10 +779,10 @@ class TestFTPArchive(TestCaseWithFactory):
778 fa.publishFileLists(779 fa.publishFileLists(
779 self._distribution["hoary-test"], PackagePublishingPocket.RELEASE,780 self._distribution["hoary-test"], PackagePublishingPocket.RELEASE,
780 source_files, binary_files)781 source_files, binary_files)
781 self._addRepositoryFile("main", "tiny", "tiny_0.1.dsc")782 self._addRepositoryFile("main", "tiny", "0.1", "tiny_0.1.dsc")
782 for i in range(50):783 for i in range(50):
783 self._addRepositoryFile(784 self._addRepositoryFile(
784 "main", "bin%d" % i, "bin%d_1_i386.deb" % i,785 "main", "bin%d" % i, "1", "bin%d_1_i386.deb" % i,
785 samplename="tiny_0.1_i386.deb")786 samplename="tiny_0.1_i386.deb")
786 apt_conf = fa.generateConfig(fullpublish=True)787 apt_conf = fa.generateConfig(fullpublish=True)
787 fa.runApt(apt_conf)788 fa.runApt(apt_conf)
@@ -790,7 +791,7 @@ class TestFTPArchive(TestCaseWithFactory):
790 # something to do.791 # something to do.
791 for i in range(49):792 for i in range(49):
792 self._dp.pathFor(793 self._dp.pathFor(
793 "main", "bin%d" % i, "bin%d_1_i386.deb" % i).unlink()794 "main", "bin%d" % i, "1", "bin%d_1_i386.deb" % i).unlink()
794795
795 cache_path = os.path.join(self._config.cacheroot, "packages-i386.db")796 cache_path = os.path.join(self._config.cacheroot, "packages-i386.db")
796 old_cache_size = os.stat(cache_path).st_size797 old_cache_size = os.stat(cache_path).st_size
diff --git a/lib/lp/archivepublisher/tests/test_pool.py b/lib/lp/archivepublisher/tests/test_pool.py
index 4beeea5..97669ff 100644
--- a/lib/lp/archivepublisher/tests/test_pool.py
+++ b/lib/lp/archivepublisher/tests/test_pool.py
@@ -83,30 +83,34 @@ class FakePackageReleaseFile:
8383
84class PoolTestingFile:84class PoolTestingFile:
8585
86 def __init__(self, pool, sourcename, filename,86 def __init__(self, pool, source_name, source_version, filename,
87 release_type=FakeReleaseType.BINARY, release_id=1):87 release_type=FakeReleaseType.BINARY, release_id=1):
88 self.pool = pool88 self.pool = pool
89 self.sourcename = sourcename89 self.source_name = source_name
90 self.source_version = source_version
90 self.filename = filename91 self.filename = filename
91 self.contents = sourcename.encode("UTF-8")92 self.contents = source_name.encode("UTF-8")
92 self.release_type = release_type93 self.release_type = release_type
93 self.release_id = release_id94 self.release_id = release_id
9495
95 def addToPool(self, component: str):96 def addToPool(self, component: str):
96 return self.pool.addFile(97 return self.pool.addFile(
97 component, self.sourcename, self.filename,98 component, self.source_name, self.source_version, self.filename,
98 FakePackageReleaseFile(99 FakePackageReleaseFile(
99 self.contents, self.release_type, self.release_id))100 self.contents, self.release_type, self.release_id))
100101
101 def removeFromPool(self, component: str) -> int:102 def removeFromPool(self, component: str) -> int:
102 return self.pool.removeFile(component, self.sourcename, self.filename)103 return self.pool.removeFile(
104 component, self.source_name, self.source_version, self.filename)
103105
104 def checkExists(self, component: str) -> bool:106 def checkExists(self, component: str) -> bool:
105 path = self.pool.pathFor(component, self.sourcename, self.filename)107 path = self.pool.pathFor(
108 component, self.source_name, self.source_version, self.filename)
106 return path.exists()109 return path.exists()
107110
108 def checkIsLink(self, component: str) -> bool:111 def checkIsLink(self, component: str) -> bool:
109 path = self.pool.pathFor(component, self.sourcename, self.filename)112 path = self.pool.pathFor(
113 component, self.source_name, self.source_version, self.filename)
110 return path.is_symlink()114 return path.is_symlink()
111115
112 def checkIsFile(self, component: str) -> bool:116 def checkIsFile(self, component: str) -> bool:
@@ -140,14 +144,18 @@ class TestPool(unittest.TestCase):
140144
141 def testSimpleAdd(self):145 def testSimpleAdd(self):
142 """Adding a new file should work."""146 """Adding a new file should work."""
143 foo = PoolTestingFile(self.pool, "foo", "foo-1.0.deb")147 foo = PoolTestingFile(
148 pool=self.pool, source_name="foo", source_version="1.0",
149 filename="foo-1.0.deb")
144 result = foo.addToPool("main")150 result = foo.addToPool("main")
145 self.assertEqual(self.pool.results.FILE_ADDED, result)151 self.assertEqual(self.pool.results.FILE_ADDED, result)
146 self.assertTrue(foo.checkIsFile("main"))152 self.assertTrue(foo.checkIsFile("main"))
147153
148 def testSimpleSymlink(self):154 def testSimpleSymlink(self):
149 """Adding a file twice should result in a symlink."""155 """Adding a file twice should result in a symlink."""
150 foo = PoolTestingFile(self.pool, "foo", "foo-1.0.deb")156 foo = PoolTestingFile(
157 pool=self.pool, source_name="foo", source_version="1.0",
158 filename="foo-1.0.deb")
151 foo.addToPool("main")159 foo.addToPool("main")
152 result = foo.addToPool("universe")160 result = foo.addToPool("universe")
153 self.assertEqual(self.pool.results.SYMLINK_ADDED, result)161 self.assertEqual(self.pool.results.SYMLINK_ADDED, result)
@@ -156,7 +164,9 @@ class TestPool(unittest.TestCase):
156164
157 def testSymlinkShuffleOnAdd(self):165 def testSymlinkShuffleOnAdd(self):
158 """If the second add is a more preferred component, links shuffle."""166 """If the second add is a more preferred component, links shuffle."""
159 foo = PoolTestingFile(self.pool, "foo", "foo-1.0.deb")167 foo = PoolTestingFile(
168 pool=self.pool, source_name="foo", source_version="1.0",
169 filename="foo-1.0.deb")
160 foo.addToPool("universe")170 foo.addToPool("universe")
161 result = foo.addToPool("main")171 result = foo.addToPool("main")
162 self.assertEqual(self.pool.results.SYMLINK_ADDED, result)172 self.assertEqual(self.pool.results.SYMLINK_ADDED, result)
@@ -165,7 +175,9 @@ class TestPool(unittest.TestCase):
165175
166 def testRemoveSymlink(self):176 def testRemoveSymlink(self):
167 """Remove file should just remove a symlink"""177 """Remove file should just remove a symlink"""
168 foo = PoolTestingFile(self.pool, "foo", "foo-1.0.deb")178 foo = PoolTestingFile(
179 pool=self.pool, source_name="foo", source_version="1.0",
180 filename="foo-1.0.deb")
169 foo.addToPool("main")181 foo.addToPool("main")
170 foo.addToPool("universe")182 foo.addToPool("universe")
171183
@@ -175,7 +187,9 @@ class TestPool(unittest.TestCase):
175187
176 def testRemoveLoneFile(self):188 def testRemoveLoneFile(self):
177 """Removing a file with no symlinks removes it."""189 """Removing a file with no symlinks removes it."""
178 foo = PoolTestingFile(self.pool, "foo", "foo-1.0.deb")190 foo = PoolTestingFile(
191 pool=self.pool, source_name="foo", source_version="1.0",
192 filename="foo-1.0.deb")
179 foo.addToPool("main")193 foo.addToPool("main")
180194
181 size = foo.removeFromPool("main")195 size = foo.removeFromPool("main")
@@ -184,7 +198,9 @@ class TestPool(unittest.TestCase):
184198
185 def testSymlinkShuffleOnRemove(self):199 def testSymlinkShuffleOnRemove(self):
186 """Removing a file with a symlink shuffles links."""200 """Removing a file with a symlink shuffles links."""
187 foo = PoolTestingFile(self.pool, "foo", "foo-1.0.deb")201 foo = PoolTestingFile(
202 pool=self.pool, source_name="foo", source_version="1.0",
203 filename="foo-1.0.deb")
188 foo.addToPool("universe")204 foo.addToPool("universe")
189 foo.addToPool("main")205 foo.addToPool("main")
190206
diff --git a/lib/lp/archivepublisher/tests/test_publisher.py b/lib/lp/archivepublisher/tests/test_publisher.py
index f247242..a2cbb54 100644
--- a/lib/lp/archivepublisher/tests/test_publisher.py
+++ b/lib/lp/archivepublisher/tests/test_publisher.py
@@ -3607,6 +3607,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
3607 "launchpad.release-id":3607 "launchpad.release-id":
3608 ["source:%d" % source.sourcepackagereleaseID],3608 ["source:%d" % source.sourcepackagereleaseID],
3609 "launchpad.source-name": ["hello"],3609 "launchpad.source-name": ["hello"],
3610 "launchpad.source-version": ["1.0"],
3610 },3611 },
3611 source_path.properties)3612 source_path.properties)
3612 binary_path = (3613 binary_path = (
@@ -3620,6 +3621,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
3620 "launchpad.release-id":3621 "launchpad.release-id":
3621 ["binary:%d" % binary.binarypackagereleaseID],3622 ["binary:%d" % binary.binarypackagereleaseID],
3622 "launchpad.source-name": ["hello"],3623 "launchpad.source-name": ["hello"],
3624 "launchpad.source-version": ["1.0"],
3623 },3625 },
3624 binary_path.properties)3626 binary_path.properties)
36253627
@@ -3669,6 +3671,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
3669 "launchpad.release-id":3671 "launchpad.release-id":
3670 ["source:%d" % source.sourcepackagereleaseID],3672 ["source:%d" % source.sourcepackagereleaseID],
3671 "launchpad.source-name": ["hello"],3673 "launchpad.source-name": ["hello"],
3674 "launchpad.source-version": ["1.0"],
3672 },3675 },
3673 source_path.properties)3676 source_path.properties)
3674 self.assertEqual(3677 self.assertEqual(
@@ -3679,6 +3682,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
3679 "launchpad.release-id":3682 "launchpad.release-id":
3680 ["binary:%d" % binary.binarypackagereleaseID],3683 ["binary:%d" % binary.binarypackagereleaseID],
3681 "launchpad.source-name": ["hello"],3684 "launchpad.source-name": ["hello"],
3685 "launchpad.source-version": ["1.0"],
3682 },3686 },
3683 binary_path.properties)3687 binary_path.properties)
36843688
@@ -3722,6 +3726,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
3722 "launchpad.release-id":3726 "launchpad.release-id":
3723 ["source:%d" % source.sourcepackagereleaseID],3727 ["source:%d" % source.sourcepackagereleaseID],
3724 "launchpad.source-name": ["hello"],3728 "launchpad.source-name": ["hello"],
3729 "launchpad.source-version": ["1.0"],
3725 },3730 },
3726 source_path.properties)3731 source_path.properties)
3727 self.assertEqual(3732 self.assertEqual(
@@ -3729,6 +3734,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
3729 "launchpad.release-id":3734 "launchpad.release-id":
3730 ["binary:%d" % binary.binarypackagereleaseID],3735 ["binary:%d" % binary.binarypackagereleaseID],
3731 "launchpad.source-name": ["hello"],3736 "launchpad.source-name": ["hello"],
3737 "launchpad.source-version": ["1.0"],
3732 },3738 },
3733 binary_path.properties)3739 binary_path.properties)
37343740
diff --git a/lib/lp/soyuz/model/publishing.py b/lib/lp/soyuz/model/publishing.py
index b229c47..b17194e 100644
--- a/lib/lp/soyuz/model/publishing.py
+++ b/lib/lp/soyuz/model/publishing.py
@@ -178,14 +178,16 @@ class ArchivePublisherBase:
178 """See `IPublishing`"""178 """See `IPublishing`"""
179 try:179 try:
180 for pub_file in self.files:180 for pub_file in self.files:
181 source = self.source_package_name181 source_name = self.source_package_name
182 source_version = self.source_package_version
182 component = (183 component = (
183 None if self.component is None else self.component.name)184 None if self.component is None else self.component.name)
184 filename = pub_file.libraryfile.filename185 filename = pub_file.libraryfile.filename
185 path = diskpool.pathFor(component, source, filename)186 path = diskpool.pathFor(
187 component, source_name, source_version, filename)
186188
187 action = diskpool.addFile(189 action = diskpool.addFile(
188 component, source, filename, pub_file)190 component, source_name, source_version, filename, pub_file)
189 if action == diskpool.results.FILE_ADDED:191 if action == diskpool.results.FILE_ADDED:
190 log.debug("Added %s from library" % path)192 log.debug("Added %s from library" % path)
191 elif action == diskpool.results.SYMLINK_ADDED:193 elif action == diskpool.results.SYMLINK_ADDED:

Subscribers

People subscribed via source and target branches

to status/vote changes: