Skip to content

Commit 42fb9b8

Browse files
committed
Added Support for syncing DEP11 files
This change aims to add support for syncing of DEP11 metadata files, enabling the use of application stores like KDE Discover which are based on Appstream.
1 parent 254405f commit 42fb9b8

3 files changed

Lines changed: 122 additions & 2 deletions

File tree

CHANGES/1276.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added support to sync DEP11 metadata files if available in the source repo.

pulp_deb/app/tasks/publishing.py

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from datetime import datetime, timezone
1010
from debian import deb822
11-
from gzip import GzipFile
11+
import gzip
1212
import tempfile
1313

1414
from django.conf import settings
@@ -23,6 +23,7 @@
2323
PublishedMetadata,
2424
RemoteArtifact,
2525
RepositoryVersion,
26+
ContentArtifact,
2627
)
2728

2829
from pulp_deb.app.constants import NULL_VALUE
@@ -38,6 +39,7 @@
3839
AptReleaseSigningService,
3940
SourcePackage,
4041
SourcePackageReleaseComponent,
42+
GenericContent,
4143
)
4244

4345
from pulp_deb.app.serializers import (
@@ -244,8 +246,59 @@ def publish(
244246
release=release,
245247
temp_dir=temp_dir,
246248
signing_service=signing_service,
249+
dep11_file_paths=[],
247250
)
248251

252+
log.info("publish(): looking for dep11 files ...")
253+
dep11_files = GenericContent.objects.filter(
254+
pk__in=repo_version.content.order_by("-pulp_created"),
255+
relative_path__contains="/dep11/",
256+
)
257+
258+
for dep11_file in dep11_files:
259+
release_helper.dep11_file_paths.append(dep11_file.relative_path)
260+
# make sure that there actually are artifacts for dep11 files
261+
try:
262+
artifact = ContentArtifact.objects.get(
263+
content_id=dep11_file.content_ptr_id
264+
)
265+
except Exception as e:
266+
log.warning(
267+
f"DEP11: artifact not found for {dep11_file}: {e}, skipping"
268+
)
269+
continue
270+
271+
artifact_path = f"{settings.MEDIA_ROOT}/{artifact.artifact.file}"
272+
dep11_metadata = PublishedMetadata.create_from_file(
273+
publication=publication,
274+
file=File(open(artifact_path, "rb")),
275+
relative_path=dep11_file.relative_path,
276+
)
277+
dep11_metadata.save()
278+
release_helper.add_metadata(dep11_metadata)
279+
280+
# this is a "hack" because we need a mention of the
281+
# uncompressed files in the Release file,
282+
# for Appstream to find them
283+
# We normally don't care about the artifact of the
284+
# uncompressed files but every logic like
285+
# sync and publish relies on the availability of an artifact.
286+
# We also need to decompress those files to avoid hash mismatch errors
287+
if "CID-Index" not in dep11_file.relative_path:
288+
if dep11_file.relative_path.endswith(".gz"):
289+
dep11_file_uncompressed = dep11_file.relative_path.strip(".gz")
290+
with gzip.open(artifact_path, "rb") as f_in:
291+
with open(dep11_file_uncompressed, "wb") as f_out:
292+
shutil.copyfileobj(f_in, f_out)
293+
294+
dep11_metadata_uncompressed = PublishedMetadata.create_from_file(
295+
publication=publication,
296+
file=File(open(dep11_file_uncompressed, "rb")),
297+
relative_path=dep11_file_uncompressed,
298+
)
299+
dep11_metadata_uncompressed.save()
300+
release_helper.add_metadata(dep11_metadata_uncompressed)
301+
249302
package_release_components = PackageReleaseComponent.objects.filter(
250303
pk__in=repo_version.content.order_by("-pulp_created"),
251304
release_component__in=release_components_filtered,
@@ -301,6 +354,8 @@ def __init__(self, parent, component):
301354
self.plain_component = os.path.basename(component)
302355
self.package_index_files = {}
303356
self.source_index_file_info = None
357+
self.dep11_path = None
358+
self.dep11_file_paths = []
304359

305360
for architecture in self.parent.architectures:
306361
package_index_path = os.path.join(
@@ -329,6 +384,12 @@ def __init__(self, parent, component):
329384
source_index_path,
330385
)
331386

387+
# DEP11 directory
388+
self.dep11_dir = os.path.join(
389+
"dists", self.parent.dists_subfolder, self.plain_component, "dep11"
390+
)
391+
os.makedirs(self.dep11_dir, exist_ok=True)
392+
332393
def add_packages(self, packages, artifact_dict, remote_artifact_dict):
333394
published_artifacts = []
334395
package_data = []
@@ -471,6 +532,7 @@ def __init__(
471532
release,
472533
temp_dir,
473534
signing_service=None,
535+
dep11_file_paths=None,
474536
):
475537
self.publication = publication
476538
self.temp_env = {"PULP_TEMP_WORKING_DIR": _create_random_directory(temp_dir)}
@@ -508,6 +570,7 @@ def __init__(
508570
self.architectures = architectures
509571
self.components = {component: _ComponentHelper(self, component) for component in components}
510572
self.signing_service = publication.signing_service or signing_service
573+
self.dep11_file_paths = dep11_file_paths
511574

512575
def add_metadata(self, metadata):
513576
artifact = metadata._artifacts.get()
@@ -573,7 +636,7 @@ def save_signed_metadata(self):
573636
def _zip_file(file_path):
574637
gz_file_path = file_path + ".gz"
575638
with open(file_path, "rb") as f_in:
576-
with GzipFile(gz_file_path, "wb") as f_out:
639+
with gzip.GzipFile(gz_file_path, "wb") as f_out:
577640
shutil.copyfileobj(f_in, f_out)
578641
return gz_file_path
579642

pulp_deb/app/tasks/synchronizing.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,10 @@ async def _handle_component(
843843
pending_tasks.extend(
844844
[self._handle_source_index(release_file, release_component, file_references)]
845845
)
846+
847+
pending_tasks.extend(
848+
[self._handle_dep11_files(release_file, release_component, file_references)]
849+
)
846850
await asyncio.gather(*pending_tasks)
847851

848852
async def _handle_flat_repo(self, file_references, release_file, distribution):
@@ -871,6 +875,58 @@ async def _handle_flat_repo(self, file_references, release_file, distribution):
871875
# Await all tasks
872876
await asyncio.gather(*pending_tasks)
873877

878+
async def _handle_dep11_files(self, release_file, release_component, file_references):
879+
dep11_dir = os.path.join(release_component.plain_component, "dep11")
880+
paths = [path for path in file_references.keys() if path.startswith(dep11_dir)]
881+
882+
if paths:
883+
# CID-Index-amd64.json.gz is missing in file_references (not in Release file)
884+
# Inject it manually?
885+
dep11s = {}
886+
supported_artifacts = [
887+
"CID-Index-amd64.json.gz",
888+
"Components-amd64.yml.gz",
889+
"Components-amd64.yml.xz",
890+
"icons-48x48.tar.gz",
891+
"icons-48x48@2.tar.gz",
892+
"icons-64x64.tar.gz",
893+
"icons-64x64@2.tar.gz",
894+
"icons-128x128.tar.gz",
895+
"icons-128x128@2.tar.gz",
896+
]
897+
898+
for path in paths:
899+
relative_path = os.path.join(os.path.dirname(release_file.relative_path), path)
900+
basename = os.path.basename(relative_path)
901+
902+
if basename not in supported_artifacts:
903+
log.warning(f"DEP11: {basename} is not in supported artifacts, skipping")
904+
continue
905+
906+
d_artifact = self._to_d_artifact(relative_path, file_references[path])
907+
key = relative_path
908+
909+
if key not in dep11s:
910+
sha256 = d_artifact.artifact.sha256
911+
dep11s[key] = {"sha256": sha256, "d_artifacts": []}
912+
log.warning(f"_handle_dep11_files: adding key={key}, sha256={sha256}")
913+
914+
dep11s[key]["d_artifacts"].append(d_artifact)
915+
916+
# handle CID-Index-amd64.json.gz separately
917+
# because it is not listed in upstream Release file
918+
cid_file_path = os.path.join(
919+
os.path.dirname(release_file.relative_path), dep11_dir, "CID-Index-amd64.json.gz"
920+
)
921+
artifact = self._to_d_artifact(cid_file_path)
922+
dep11s[cid_file_path] = {"sha256": artifact.artifact.sha256, "d_artifacts": []}
923+
dep11s[cid_file_path]["d_artifacts"].append(artifact)
924+
for relative_path, dep11 in dep11s.items():
925+
content_unit = GenericContent(sha256=dep11["sha256"], relative_path=relative_path)
926+
await self.put(
927+
DeclarativeContent(content=content_unit, d_artifacts=dep11["d_artifacts"])
928+
)
929+
874930
async def _handle_package_index(
875931
self,
876932
release_file,

0 commit comments

Comments
 (0)