Skip to content

Commit db3ec73

Browse files
committed
Add flat repo sync will always assign 'flat-repo' distribution
closes pulp#1258
1 parent 04d1103 commit db3ec73

File tree

5 files changed

+160
-59
lines changed

5 files changed

+160
-59
lines changed

CHANGES/1258.feature

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Syncing flat repositories will now always publish distribution "flat-repo".

pulp_deb/app/tasks/synchronizing.py

+51-43
Original file line numberDiff line numberDiff line change
@@ -624,16 +624,19 @@ def _to_d_artifact(self, relative_path, data=None):
624624
)
625625

626626
async def _handle_distribution(self, distribution):
627+
is_flat = distribution.endswith("/")
628+
stored_distribution = "flat-repo" if is_flat else distribution
629+
627630
log.info(_('Downloading Release file for distribution: "{}"').format(distribution))
628631
# Create release_file
629-
if distribution[-1] == "/":
630-
release_file_dir = distribution.strip("/")
632+
if is_flat:
633+
upstream_file_dir = distribution.strip("/")
631634
else:
632-
release_file_dir = os.path.join("dists", distribution)
635+
upstream_file_dir = os.path.join("dists", distribution)
633636
release_file_dc = DeclarativeContent(
634-
content=ReleaseFile(distribution=distribution, relative_path=release_file_dir),
637+
content=ReleaseFile(distribution=stored_distribution, relative_path=upstream_file_dir),
635638
d_artifacts=[
636-
self._to_d_artifact(os.path.join(release_file_dir, filename))
639+
self._to_d_artifact(os.path.join(upstream_file_dir, filename))
637640
for filename in ReleaseFile.SUPPORTED_ARTIFACTS
638641
],
639642
)
@@ -665,7 +668,7 @@ async def _handle_distribution(self, distribution):
665668
release_fields = {
666669
"codename": release_file.codename,
667670
"suite": release_file.suite,
668-
"distribution": distribution,
671+
"distribution": stored_distribution,
669672
}
670673

671674
if "version" in release_file_dict:
@@ -680,17 +683,17 @@ async def _handle_distribution(self, distribution):
680683
await self.put(DeclarativeContent(content=Release(**release_fields)))
681684

682685
# Create release architectures
683-
if release_file.architectures:
684-
architectures = _filter_split_architectures(
685-
release_file.architectures, self.remote.architectures, distribution
686-
)
687-
elif distribution[-1] == "/":
686+
if is_flat:
688687
message = (
689-
"The ReleaseFile content unit architecrures are unset for the flat repo with "
688+
"The ReleaseFile content unit architectures are unset for the flat repo with "
690689
"distribution '{}'. ReleaseArchitecture content creation is deferred!"
691690
)
692691
log.warning(_(message).format(distribution))
693692
architectures = []
693+
elif release_file.architectures:
694+
architectures = _filter_split_architectures(
695+
release_file.architectures, self.remote.architectures, distribution
696+
)
694697

695698
for architecture in architectures:
696699
release_architecture_dc = DeclarativeContent(
@@ -719,9 +722,16 @@ async def _handle_distribution(self, distribution):
719722
for unit in release_file_dict[digest_name]:
720723
file_references[unit["Name"]].update(unit)
721724

722-
if distribution[-1] == "/":
725+
if is_flat:
723726
# Handle flat repo
724-
sub_tasks = [self._handle_flat_repo(file_references, release_file, distribution)]
727+
sub_tasks = [
728+
self._handle_flat_repo(
729+
file_references,
730+
release_file,
731+
distribution=stored_distribution,
732+
upstream_dist_path=upstream_file_dir,
733+
)
734+
]
725735
else:
726736
# Handle components
727737
sub_tasks = [
@@ -833,7 +843,9 @@ async def _handle_component(
833843
)
834844
await asyncio.gather(*pending_tasks)
835845

836-
async def _handle_flat_repo(self, file_references, release_file, distribution):
846+
async def _handle_flat_repo(
847+
self, file_references, release_file, distribution, upstream_dist_path
848+
):
837849
# We are creating a component so the flat repo can be published as a structured repo!
838850
release_component_dc = DeclarativeContent(
839851
content=ReleaseComponent(component="flat-repo-component", distribution=distribution)
@@ -849,6 +861,7 @@ async def _handle_flat_repo(self, file_references, release_file, distribution):
849861
architecture="",
850862
file_references=file_references,
851863
distribution=distribution,
864+
is_flat=True,
852865
)
853866
)
854867

@@ -868,15 +881,19 @@ async def _handle_package_index(
868881
infix="",
869882
distribution=None,
870883
hybrid_format=False,
884+
is_flat=False,
871885
):
886+
if is_flat:
887+
release_file_package_index_dir = ""
888+
else:
889+
release_file_package_index_dir = os.path.join(
890+
release_component.plain_component,
891+
infix,
892+
f"binary-{architecture}",
893+
)
872894
# Create package_index
873895
release_base_path = os.path.dirname(release_file.relative_path)
874-
# Package index directory relative to the release file:
875-
release_file_package_index_dir = (
876-
os.path.join(release_component.plain_component, infix, "binary-{}".format(architecture))
877-
if release_file.distribution[-1] != "/"
878-
else ""
879-
)
896+
880897
# Package index directory relative to the repository root:
881898
package_index_dir = os.path.join(release_base_path, release_file_package_index_dir)
882899
d_artifacts = []
@@ -948,7 +965,7 @@ async def _handle_package_index(
948965
):
949966
# Sanity check the architecture from the package paragraph:
950967
package_paragraph_architecture = package_paragraph["Architecture"]
951-
if release_file.distribution[-1] == "/":
968+
if is_flat:
952969
if (
953970
self.remote.architectures
954971
and package_paragraph_architecture != "all"
@@ -1035,32 +1052,23 @@ async def _handle_package_index(
10351052
)
10361053
)
10371054
await self.put(package_release_component_dc)
1038-
if release_file.distribution[-1] == "/":
1055+
if is_flat:
10391056
package_architectures.add(package.architecture)
10401057

10411058
# For flat repos we may still need to create ReleaseArchitecture content:
1042-
if release_file.distribution[-1] == "/":
1059+
if is_flat:
10431060
if release_file.architectures:
10441061
for architecture in package_architectures:
1045-
if architecture not in release_file.architectures.split():
1046-
message = (
1047-
"The flat repo with distribution '{}' contains packages with "
1048-
"architecture '{}' but this is not included in the ReleaseFile's "
1049-
"architectures field '{}'!"
1050-
)
1051-
log.warning(
1052-
_(message).format(
1053-
release_file.distribution, architecture, release_file.architectures
1054-
)
1055-
)
1056-
message = "Creating additional ReleaseArchitecture for architecture '{}'!"
1057-
log.warning(_(message).format(architecture))
1058-
release_architecture_dc = DeclarativeContent(
1059-
content=ReleaseArchitecture(
1060-
architecture=architecture, distribution=distribution
1061-
)
1062+
log.debug(
1063+
"Flat Repo Architecture handling: "
1064+
f"Creating ReleaseArchitecture for architecture {architecture}."
1065+
)
1066+
release_architecture_dc = DeclarativeContent(
1067+
content=ReleaseArchitecture(
1068+
architecture=architecture, distribution="flat-repo"
10621069
)
1063-
await self.put(release_architecture_dc)
1070+
)
1071+
await self.put(release_architecture_dc)
10641072
else:
10651073
package_architectures_string = " ".join(package_architectures)
10661074
message = (
@@ -1076,7 +1084,7 @@ async def _handle_package_index(
10761084
for architecture in package_architectures:
10771085
release_architecture_dc = DeclarativeContent(
10781086
content=ReleaseArchitecture(
1079-
architecture=architecture, distribution=distribution
1087+
architecture=architecture, distribution="flat-repo"
10801088
)
10811089
)
10821090
await self.put(release_architecture_dc)

pulp_deb/tests/functional/api/test_publish.py

+55-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from pulp_deb.tests.functional.constants import (
77
DEB_FIXTURE_ALT_SINGLE_DIST,
8+
DEB_FIXTURE_BASE,
89
DEB_FIXTURE_COMPLEX_REPOSITORY_NAME,
910
DEB_FIXTURE_DISTRIBUTIONS,
1011
DEB_FIXTURE_FLAT_REPOSITORY_NAME,
@@ -320,14 +321,16 @@ def test_publish_empty_repository(
320321

321322
@pytest.mark.parallel
322323
@pytest.mark.parametrize(
323-
"expected_data", [DEB_PUBLISH_FLAT_VERBATIM, DEB_PUBLISH_FLAT_NESTED_VERBATIM]
324+
"expected_data, flat_dist",
325+
[(DEB_PUBLISH_FLAT_VERBATIM, "/"), (DEB_PUBLISH_FLAT_NESTED_VERBATIM, "nest/fjalar/")],
324326
)
325327
def test_publish_flat_repository_verbatim(
326328
create_publication_and_verify_repo_version,
327329
deb_distribution_factory,
328330
verify_distribution,
329331
verify_publication_data,
330332
expected_data,
333+
flat_dist,
331334
):
332335
"""Test whether a particular flat repository can be published verbatim.
333336
@@ -336,7 +339,7 @@ def test_publish_flat_repository_verbatim(
336339
* `Publish a flat repository verbatim.`_
337340
* `Publish a nested flat repository verbatim.`_
338341
"""
339-
remote_args = {"distributions": expected_data["distribution"]}
342+
remote_args = {"distributions": flat_dist}
340343

341344
# Create a publication
342345
publication, _, _, _ = create_publication_and_verify_repo_version(
@@ -351,12 +354,12 @@ def test_publish_flat_repository_verbatim(
351354

352355
@pytest.mark.parallel
353356
@pytest.mark.parametrize(
354-
"expected_data, publication_args",
357+
"expected_data, publication_args, flat_dist",
355358
[
356-
(DEB_PUBLISH_FLAT_STRUCTURED, DEB_PUBLICATION_ARGS_ONLY_STRUCTURED),
357-
(DEB_PUBLISH_FLAT_SIMPLE, DEB_PUBLICATION_ARGS_ONLY_SIMPLE),
358-
(DEB_PUBLISH_FLAT_NESTED_STRUCTURED, DEB_PUBLICATION_ARGS_ONLY_STRUCTURED),
359-
(DEB_PUBLISH_FLAT_NESTED_SIMPLE, DEB_PUBLICATION_ARGS_ONLY_SIMPLE),
359+
(DEB_PUBLISH_FLAT_STRUCTURED, DEB_PUBLICATION_ARGS_ONLY_STRUCTURED, "/"),
360+
(DEB_PUBLISH_FLAT_SIMPLE, DEB_PUBLICATION_ARGS_ONLY_SIMPLE, "/"),
361+
(DEB_PUBLISH_FLAT_NESTED_STRUCTURED, DEB_PUBLICATION_ARGS_ONLY_STRUCTURED, "nest/fjalar/"),
362+
(DEB_PUBLISH_FLAT_NESTED_SIMPLE, DEB_PUBLICATION_ARGS_ONLY_SIMPLE, "nest/fjalar/"),
360363
],
361364
)
362365
def test_publish_flat_repository(
@@ -366,6 +369,7 @@ def test_publish_flat_repository(
366369
verify_distribution,
367370
verify_publication_data,
368371
publication_args,
372+
flat_dist,
369373
):
370374
"""Test whether a particular flat repository can be published.
371375
@@ -376,7 +380,7 @@ def test_publish_flat_repository(
376380
* `Publish a nested flat repository structured.`_
377381
* `Publish a nested flat repository simple.`_
378382
"""
379-
remote_args = {"distributions": expected_data["distribution"]}
383+
remote_args = {"distributions": flat_dist}
380384

381385
# Create a publication
382386
publication, _, _, _ = create_publication_and_verify_repo_version(
@@ -391,6 +395,49 @@ def test_publish_flat_repository(
391395
verify_distribution(distribution, expected_data)
392396

393397

398+
@pytest.mark.parallel
399+
@pytest.mark.parametrize(
400+
"remote_args, remote_name",
401+
[
402+
({"distributions": "/"}, DEB_FIXTURE_FLAT_REPOSITORY_NAME),
403+
({"distributions": "debian-flat/"}, DEB_FIXTURE_BASE),
404+
],
405+
)
406+
def test_published_flat_repo_content(
407+
create_publication_and_verify_repo_version,
408+
deb_distribution_factory,
409+
download_content_unit,
410+
remote_args,
411+
remote_name,
412+
):
413+
"""
414+
Test that published flat repository results in a normalized Release file and package indices.
415+
"""
416+
publication, _, _, _ = create_publication_and_verify_repo_version(
417+
remote_args=remote_args,
418+
remote_name=remote_name,
419+
)
420+
421+
distribution = deb_distribution_factory(publication)
422+
base_url = distribution.base_path
423+
424+
expected_release_path = os.path.join("dists", "flat-repo", "Release")
425+
expected_pkg_index_path = os.path.join(
426+
"dists", "flat-repo", "flat-repo-component", "binary-ppc64", "Packages"
427+
)
428+
429+
release_file = download_content_unit(base_url, expected_release_path)
430+
release_file_str = release_file.decode("utf-8")
431+
assert "flat-repo" in release_file_str
432+
433+
pkg_index = download_content_unit(base_url, expected_pkg_index_path)
434+
from debian import deb822
435+
436+
pkgs = list(deb822.Packages.iter_paragraphs(pkg_index, use_apt_pkg=False))
437+
ppc64_pkgs = [pkg for pkg in pkgs if pkg.get("Architecture") == "ppc64"]
438+
assert ppc64_pkgs, "No packages with architecture 'ppc64' found in the published package index."
439+
440+
394441
@pytest.mark.skip("Skip - ignore_missing_package_indices sync parameter does currently not work")
395442
@pytest.mark.parallel
396443
def test_publish_missing_architecture(

pulp_deb/tests/functional/api/test_pulp_to_pulp.py

+28
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import pytest
44

55
from pulp_deb.tests.functional.constants import (
6+
DEB_FIXTURE_FLAT_REPOSITORY_NAME,
7+
DEB_P2P_FLAT_STRUCTURED,
8+
DEB_P2P_REMOTE_ARGS_FLAT,
69
DEB_P2P_SIMPLE_THEN_STRUCTURED,
710
DEB_PUBLICATION_ARGS_ONLY_SIMPLE,
811
DEB_PUBLICATION_ARGS_ONLY_STRUCTURED,
@@ -206,3 +209,28 @@ def test_pulp_to_pulp_sync_simple_to_structured(
206209
added_both = get_counts_from_content_summary(summary_both.added)
207210
assert added_both == DEB_P2P_SIMPLE_THEN_STRUCTURED
208211
assert present_both == DEB_P2P_SIMPLE_AND_STRUCTURED
212+
213+
214+
def test_pulp_to_pulp_sync_flat(
215+
deb_init_and_sync,
216+
deb_publication_factory,
217+
deb_distribution_factory,
218+
deb_get_content_summary,
219+
delete_orphans_pre,
220+
):
221+
"""Verify whether a repository served by Pulp can sync its content originally
222+
stemming from a flat repository.
223+
"""
224+
repo_flat, _ = deb_init_and_sync(
225+
remote_args={"distributions": "/", "policy": "immediate"},
226+
url=DEB_FIXTURE_FLAT_REPOSITORY_NAME,
227+
)
228+
publication = deb_publication_factory(repo_flat, **DEB_PUBLICATION_ARGS_ONLY_STRUCTURED)
229+
distribution = deb_distribution_factory(publication)
230+
231+
repo_new, _ = deb_init_and_sync(url=distribution.base_url, remote_args=DEB_P2P_REMOTE_ARGS_FLAT)
232+
summary_new = deb_get_content_summary(repo_new)
233+
present_new = get_counts_from_content_summary(summary_new.present)
234+
added_new = get_counts_from_content_summary(summary_new.added)
235+
assert present_new == DEB_P2P_FLAT_STRUCTURED
236+
assert added_new == DEB_P2P_FLAT_STRUCTURED

0 commit comments

Comments
 (0)