From 1be91cf954e3b180c7ae11f676490c34410b4f43 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Fri, 8 May 2026 17:32:11 -0700 Subject: [PATCH] Refactor into a module with two CLI scripts, add tests, fix bug Packaging two Python scripts, one of which is a wrapper for the other, is pretty awkward. But more importantly, we can make the EL "wrapper" work better with a refactor, too. It's now a stand alone script called `rdc-compose`. The original script is renamed to `rdc-repos`. The CLI scripts now share a lot of bits via `shared.py`. We put handy run-it-locally wrappers for each CLI script at the top level; you *can* install the package properly and you'll get `rdc-repos` and `rdc-compose` executables but we'll likely rarely do that. `rdc-compose` will now run faster because it will reuse the same metadata between variants (previously it got re-downloaded with every execution of `rmdepcheck.py`) and it can now nicely collect up all the repoclosure strings before using the same parse-and- exit code as rmdepcheck, which solves a lot of awkward issues around output. We also add tests covering `rdc-compose`, as part of which it made sense to factor out the Pungi config URL discovery (which I meant to do anyway). We fix a bug that was exposed by writing the tests: we have to check variants that depend on variants we have packages for, even if we don't have packages for those variants. This isn't great git hygiene, sorry. Should have made the refactor, the addition of tests and the bug fix into separate commits. But it's awkward and time-consuming to unpick now and I don't think it's a good use of time. Signed-off-by: Adam Williamson --- .forgejo/workflows/ci.yml | 2 +- README.md | 75 +- install.requires | 1 + pyproject.toml | 5 +- rdc-compose | 14 + rdc-el-wrapper.py | 256 ------- rdc-repos | 14 + rmdepcheck.py | 446 +----------- src/rmdepcheck/__init__.py | 29 + src/rmdepcheck/compose.py | 279 ++++++++ src/rmdepcheck/repos.py | 204 ++++++ src/rmdepcheck/shared.py | 341 +++++++++ tests/conftest.py | 52 ++ tests/test_rmdepcheck.py | 666 +++++++++++------- .../testdata/repos/base/aaa-1.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes .../testdata/repos/base/bbb-1.0-1.x86_64.rpm | Bin 6341 -> 6341 bytes .../testdata/repos/base/ccc-1.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes .../testdata/repos/base/ddd-1.0-1.x86_64.rpm | Bin 6341 -> 6341 bytes .../testdata/repos/base/eee-1.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes .../testdata/repos/base/fff-1.0-1.x86_64.rpm | Bin 6341 -> 6341 bytes tests/testdata/repos/base/ggg-1.0-1.i686.rpm | Bin 6273 -> 6293 bytes .../testdata/repos/base/ggg-1.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes tests/testdata/repos/base/hhh-1.0-1.i686.rpm | Bin 6289 -> 6309 bytes .../testdata/repos/base/hhh-1.0-1.x86_64.rpm | Bin 6345 -> 6345 bytes ...1af87b32a27819f776ecacb6-filelists.xml.zst | Bin 621 -> 0 bytes ...6cac98e1c7047bb0de5c8f4e8b63-other.xml.zst | Bin 710 -> 0 bytes ...63901130fe94c708e7d0cf429d-primary.xml.zst | Bin 1281 -> 0 bytes ...01e10f1dffe1db40462fcab118-primary.xml.zst | Bin 0 -> 1278 bytes ...3d9af49f402ac5d0072b505c-filelists.xml.zst | Bin 0 -> 624 bytes ...0615e628cbf96518ffe4ab1bc376-other.xml.zst | Bin 0 -> 710 bytes tests/testdata/repos/base/repodata/repomd.xml | 30 +- ...607ebc17319d7a8d143a8e066e-primary.xml.zst | Bin 0 -> 123 bytes ...1191dceb5c100bac2e66249d518d-other.xml.zst | Bin 0 -> 117 bytes ...fbaca48f629465be5f53f82b-filelists.xml.zst | Bin 0 -> 118 bytes .../repos/eln/AppStream/repodata/repomd.xml | 28 + .../BaseOS/epa-1.0-1.x86_64.rpm} | Bin 6329 -> 6329 bytes .../repos/eln/BaseOS/epb-1.0-1.x86_64.rpm | Bin 0 -> 6329 bytes ...58ade283876a72ca7b92fbf246c4-other.xml.zst | Bin 0 -> 352 bytes ...97a03ae87214197284cbbbfad8-primary.xml.zst | Bin 0 -> 676 bytes ...cc7bfcf739f32edd1afae3d2-filelists.xml.zst | Bin 0 -> 279 bytes .../repos/eln/BaseOS/repodata/repomd.xml | 28 + .../Buildroot/epe-1.0-1.x86_64.rpm} | Bin 6341 -> 6341 bytes ...e722ace44fbf1f0688f4cf68-filelists.xml.zst | Bin 0 -> 223 bytes ...2cef332765e97c2252c4df6431-primary.xml.zst | Bin 0 -> 626 bytes ...615393e5f15408b577e2114818d7-other.xml.zst | Bin 0 -> 304 bytes .../repos/eln/Buildroot/repodata/repomd.xml | 28 + .../{elnroot => eln/CRB}/epd-1.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes .../CRB/epe-1.0-1.x86_64.rpm} | Bin 6341 -> 6281 bytes ...765b80abb684b7a38f70e2bd977a-other.xml.zst | Bin 0 -> 353 bytes ...a4b324f784caeca60580b944-filelists.xml.zst | Bin 0 -> 279 bytes ...0f137c2dd783447099c23683cb-primary.xml.zst | Bin 0 -> 704 bytes .../repos/eln/CRB/repodata/repomd.xml | 28 + .../Extras}/epc-1.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes ...0a835e3ac0d666d1e5acfbaa-filelists.xml.zst | Bin 0 -> 224 bytes ...7986c9fa22323a36fdb2d73a06-primary.xml.zst | Bin 0 -> 606 bytes ...bb314370553c518be659d83b0ada-other.xml.zst | Bin 0 -> 306 bytes .../repos/eln/Extras/repodata/repomd.xml | 28 + .../repos/eln/metadata/composeinfo.json | 53 ++ tests/testdata/repos/eln/override.conf | 91 +++ ...8656c9517eac9a52a058d7793a31-other.xml.zst | Bin 351 -> 0 bytes ...d29aeffa765a71451a8856dc-filelists.xml.zst | Bin 279 -> 0 bytes ...27d66aaee819fc22ba37ab262c-primary.xml.zst | Bin 699 -> 0 bytes .../repos/elnbase/repodata/repomd.xml | 28 - .../repos/elnnew/epa-2.0-1.x86_64.rpm | Bin 0 -> 6329 bytes .../epb-2.0-1.x86_64.rpm} | Bin 6341 -> 6337 bytes ...-2.0-1.x86_64.rpm => epd-2.0-1.x86_64.rpm} | Bin 6341 -> 6337 bytes ...b934d857d9bddb4234e9c942-filelists.xml.zst | Bin 226 -> 0 bytes ...8ce34bf64a112a510aed46f8-filelists.xml.zst | Bin 0 -> 323 bytes ...9cc4c57fe63d7e4206a869c10925-other.xml.zst | Bin 0 -> 398 bytes ...d70f21731b1b4acc5195658e7890-other.xml.zst | Bin 305 -> 0 bytes ...b2075891beabbdedf2a74608b0-primary.xml.zst | Bin 629 -> 0 bytes ...0142fe7150924d08f34acc1356-primary.xml.zst | Bin 0 -> 764 bytes .../testdata/repos/elnnew/repodata/repomd.xml | 38 +- ...a2e7a9d8d448de7e636c948b-filelists.xml.zst | Bin 366 -> 0 bytes ...4d190e710ed797182925cfad70ba-other.xml.zst | Bin 445 -> 0 bytes ...8d310a6f6b9aaf5f9913c7ac7b-primary.xml.zst | Bin 830 -> 0 bytes .../repos/elnroot/repodata/repomd.xml | 28 - .../testdata/repos/empty/repodata/repomd.xml | 8 +- tests/testdata/repos/mkrepos.py | 63 +- tests/testdata/repos/new/111-3.0-1.x86_64.rpm | Bin 6345 -> 6345 bytes tests/testdata/repos/new/222-3.0-1.x86_64.rpm | Bin 6341 -> 6341 bytes tests/testdata/repos/new/aaa-3.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes tests/testdata/repos/new/ccc-3.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes tests/testdata/repos/new/eee-3.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes tests/testdata/repos/new/fff-3.0-1.x86_64.rpm | Bin 6341 -> 6341 bytes tests/testdata/repos/new/ggg-3.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes ...87f45492897b95bd1a425da7ce-primary.xml.zst | Bin 0 -> 1067 bytes ...b31eb9233b18b6ce68fa86ba05-primary.xml.zst | Bin 1069 -> 0 bytes ...b731fb75a9b664a8e0b9f6516c09-other.xml.zst | Bin 0 -> 580 bytes ...9e8db935bd9358e22f4b86a8-filelists.xml.zst | Bin 499 -> 0 bytes ...63f9b2dc006bc980a91f7393-filelists.xml.zst | Bin 0 -> 499 bytes ...c646d2350605999882725a5b0862-other.xml.zst | Bin 581 -> 0 bytes tests/testdata/repos/new/repodata/repomd.xml | 30 +- .../repos/unfixed/ddd-3.0-1.x86_64.rpm | Bin 6341 -> 6341 bytes ...070f75fbeb4b1e844973835b-filelists.xml.zst | Bin 225 -> 0 bytes ...e8408ee3167134b0a453255d-filelists.xml.zst | Bin 0 -> 225 bytes ...28cff25324ce894d3dd9c80cf961-other.xml.zst | Bin 305 -> 0 bytes ...050986ed49457124116013f4ef-primary.xml.zst | Bin 626 -> 0 bytes ...06c5884b4561d83a97d7c341c7-primary.xml.zst | Bin 0 -> 628 bytes ...668033b107b8706a39f2c37f8026-other.xml.zst | Bin 0 -> 305 bytes .../repos/unfixed/repodata/repomd.xml | 28 +- .../repos/updates/aaa-2.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes .../repos/updates/bbb-2.0-1.x86_64.rpm | Bin 6341 -> 6341 bytes .../repos/updates/ccc-2.0-1.x86_64.rpm | Bin 6329 -> 6329 bytes .../repos/updates/ddd-2.0-1.x86_64.rpm | Bin 6341 -> 6341 bytes ...852096bb6f61077a40e6ea2b-filelists.xml.zst | Bin 0 -> 372 bytes ...8b661a423c3e00b0b6072fe3d690-other.xml.zst | Bin 447 -> 0 bytes ...8337163d5b44e75a95e684d91a-primary.xml.zst | Bin 0 -> 852 bytes ...579fbb3179e2ce4d72c9586e48-primary.xml.zst | Bin 847 -> 0 bytes ...ad31e2d111d1ae2ed978e34c-filelists.xml.zst | Bin 369 -> 0 bytes ...d76c45c79661ca57763750c7b986-other.xml.zst | Bin 0 -> 448 bytes .../repos/updates/repodata/repomd.xml | 32 +- tests/testdata/test_e2e_devel.txt | 4 +- tests/testdata/test_e2e_devel_onlyerrors.txt | 4 +- tests/testdata/test_e2e_eln.txt | 8 +- tests/testdata/test_e2e_updates.txt | 2 +- tox.ini | 9 +- tox.requires | 3 + 118 files changed, 1795 insertions(+), 1188 deletions(-) create mode 100755 rdc-compose delete mode 100755 rdc-el-wrapper.py create mode 100755 rdc-repos mode change 100755 => 120000 rmdepcheck.py create mode 100644 src/rmdepcheck/__init__.py create mode 100644 src/rmdepcheck/compose.py create mode 100644 src/rmdepcheck/repos.py create mode 100644 src/rmdepcheck/shared.py create mode 100644 tests/conftest.py delete mode 100644 tests/testdata/repos/base/repodata/1acaeb6689285db3bfe681d374748eed2bc7cd9c1af87b32a27819f776ecacb6-filelists.xml.zst delete mode 100644 tests/testdata/repos/base/repodata/6868a9258bc5b257d087b3f926cbdbc014866cac98e1c7047bb0de5c8f4e8b63-other.xml.zst delete mode 100644 tests/testdata/repos/base/repodata/6b696476761c56d8bceb3e8997d31ca6977aaf63901130fe94c708e7d0cf429d-primary.xml.zst create mode 100644 tests/testdata/repos/base/repodata/725d5a8541dc6ac107257c1ccd264b53cfdfb601e10f1dffe1db40462fcab118-primary.xml.zst create mode 100644 tests/testdata/repos/base/repodata/934bc8a9464d6232eb2e22aea3275da638dd1d733d9af49f402ac5d0072b505c-filelists.xml.zst create mode 100644 tests/testdata/repos/base/repodata/9a69e354abcfd9f7de70b62321bab6263e340615e628cbf96518ffe4ab1bc376-other.xml.zst create mode 100644 tests/testdata/repos/eln/AppStream/repodata/69a3730a283b85a4b3cff7d04bfde3b2b234f0607ebc17319d7a8d143a8e066e-primary.xml.zst create mode 100644 tests/testdata/repos/eln/AppStream/repodata/6b37cc67608a24beaa81e1191d218f2ffd6b1191dceb5c100bac2e66249d518d-other.xml.zst create mode 100644 tests/testdata/repos/eln/AppStream/repodata/9b07d97dc6ececed89aac0650b67bfb292647fe9fbaca48f629465be5f53f82b-filelists.xml.zst create mode 100644 tests/testdata/repos/eln/AppStream/repodata/repomd.xml rename tests/testdata/repos/{elnbase/epc-1.0-1.x86_64.rpm => eln/BaseOS/epa-1.0-1.x86_64.rpm} (90%) create mode 100644 tests/testdata/repos/eln/BaseOS/epb-1.0-1.x86_64.rpm create mode 100644 tests/testdata/repos/eln/BaseOS/repodata/73c134c24423339ee3c1b12e215c925e853b58ade283876a72ca7b92fbf246c4-other.xml.zst create mode 100644 tests/testdata/repos/eln/BaseOS/repodata/9daa049560d116a0c3e824db9385975140f68e97a03ae87214197284cbbbfad8-primary.xml.zst create mode 100644 tests/testdata/repos/eln/BaseOS/repodata/e9b667b6a1059447627647ab73574fdee0a9c934cc7bfcf739f32edd1afae3d2-filelists.xml.zst create mode 100644 tests/testdata/repos/eln/BaseOS/repodata/repomd.xml rename tests/testdata/repos/{elnbase/epa-1.0-1.x86_64.rpm => eln/Buildroot/epe-1.0-1.x86_64.rpm} (89%) create mode 100644 tests/testdata/repos/eln/Buildroot/repodata/4c41bd6e67d5b8fc2da462e55f106fcdc729daf0e722ace44fbf1f0688f4cf68-filelists.xml.zst create mode 100644 tests/testdata/repos/eln/Buildroot/repodata/8d4fa97f0d4d6bdeca349744217b0e9d694aea2cef332765e97c2252c4df6431-primary.xml.zst create mode 100644 tests/testdata/repos/eln/Buildroot/repodata/f4ecf39d19149d8918b7485eea237aa87723615393e5f15408b577e2114818d7-other.xml.zst create mode 100644 tests/testdata/repos/eln/Buildroot/repodata/repomd.xml rename tests/testdata/repos/{elnroot => eln/CRB}/epd-1.0-1.x86_64.rpm (91%) rename tests/testdata/repos/{elnroot/epb-1.0-1.x86_64.rpm => eln/CRB/epe-1.0-1.x86_64.rpm} (80%) create mode 100644 tests/testdata/repos/eln/CRB/repodata/63510d69370f860af7ae99ffd909ecee7358765b80abb684b7a38f70e2bd977a-other.xml.zst create mode 100644 tests/testdata/repos/eln/CRB/repodata/a939af998dafa1b5c771494f948ca1a12e7c8e0ba4b324f784caeca60580b944-filelists.xml.zst create mode 100644 tests/testdata/repos/eln/CRB/repodata/adce22870e107115797acfb5b60eb3ae16af020f137c2dd783447099c23683cb-primary.xml.zst create mode 100644 tests/testdata/repos/eln/CRB/repodata/repomd.xml rename tests/testdata/repos/{elnroot => eln/Extras}/epc-1.0-1.x86_64.rpm (93%) create mode 100644 tests/testdata/repos/eln/Extras/repodata/718eae20ba82ada746eb049df2e88a420766a22c0a835e3ac0d666d1e5acfbaa-filelists.xml.zst create mode 100644 tests/testdata/repos/eln/Extras/repodata/d852b0588e7a6b861bf02df7aff77fd692bc597986c9fa22323a36fdb2d73a06-primary.xml.zst create mode 100644 tests/testdata/repos/eln/Extras/repodata/ef66a3ad019261b3603fddafbb1a8aafdc9ebb314370553c518be659d83b0ada-other.xml.zst create mode 100644 tests/testdata/repos/eln/Extras/repodata/repomd.xml create mode 100644 tests/testdata/repos/eln/metadata/composeinfo.json create mode 100644 tests/testdata/repos/eln/override.conf delete mode 100644 tests/testdata/repos/elnbase/repodata/6212147882b929cefe09ce147e26e1020b738656c9517eac9a52a058d7793a31-other.xml.zst delete mode 100644 tests/testdata/repos/elnbase/repodata/e66e2d334117944d094138fdc62fda05db2e252cd29aeffa765a71451a8856dc-filelists.xml.zst delete mode 100644 tests/testdata/repos/elnbase/repodata/f4ed4ad1632ef201cb823cb62f2408918097df27d66aaee819fc22ba37ab262c-primary.xml.zst delete mode 100644 tests/testdata/repos/elnbase/repodata/repomd.xml create mode 100644 tests/testdata/repos/elnnew/epa-2.0-1.x86_64.rpm rename tests/testdata/repos/{elnroot/epa-1.0-1.x86_64.rpm => elnnew/epb-2.0-1.x86_64.rpm} (72%) rename tests/testdata/repos/elnnew/{epc-2.0-1.x86_64.rpm => epd-2.0-1.x86_64.rpm} (71%) delete mode 100644 tests/testdata/repos/elnnew/repodata/029e08c67f723be4b217594371bb7f9f223cb866b934d857d9bddb4234e9c942-filelists.xml.zst create mode 100644 tests/testdata/repos/elnnew/repodata/6f2f32cc8b75d194c83ef1075936ed263a468f298ce34bf64a112a510aed46f8-filelists.xml.zst create mode 100644 tests/testdata/repos/elnnew/repodata/b5d3790249f642dafa96a7b5ba61938b50e19cc4c57fe63d7e4206a869c10925-other.xml.zst delete mode 100644 tests/testdata/repos/elnnew/repodata/c083429e71ea2c4bea418159abf7debbf79dd70f21731b1b4acc5195658e7890-other.xml.zst delete mode 100644 tests/testdata/repos/elnnew/repodata/e1fb8cbc0efa75785de59ffca8a3de5dd3928ab2075891beabbdedf2a74608b0-primary.xml.zst create mode 100644 tests/testdata/repos/elnnew/repodata/ec7341345e04def216d16e0db04b625570797b0142fe7150924d08f34acc1356-primary.xml.zst delete mode 100644 tests/testdata/repos/elnroot/repodata/081516c8122bf9e116d0314902b635ef595c121ba2e7a9d8d448de7e636c948b-filelists.xml.zst delete mode 100644 tests/testdata/repos/elnroot/repodata/117a29ab84c4728bf8da3b0b942c823be18f4d190e710ed797182925cfad70ba-other.xml.zst delete mode 100644 tests/testdata/repos/elnroot/repodata/5548c16c17c9999a288149e4c028529fea3de98d310a6f6b9aaf5f9913c7ac7b-primary.xml.zst delete mode 100644 tests/testdata/repos/elnroot/repodata/repomd.xml create mode 100644 tests/testdata/repos/new/repodata/0a7860c188784cab59dcc483eea7c38d8e9da287f45492897b95bd1a425da7ce-primary.xml.zst delete mode 100644 tests/testdata/repos/new/repodata/182e2add8c3d3069057852ed9944419578aa72b31eb9233b18b6ce68fa86ba05-primary.xml.zst create mode 100644 tests/testdata/repos/new/repodata/4f693bcdc44f61c53c77e39ee300085d9e54b731fb75a9b664a8e0b9f6516c09-other.xml.zst delete mode 100644 tests/testdata/repos/new/repodata/8e6cd282fee67920e9fd5728c68c86ad8d8ca56f9e8db935bd9358e22f4b86a8-filelists.xml.zst create mode 100644 tests/testdata/repos/new/repodata/cf45583b0c95946ca4ca3d567a3da5db1183158763f9b2dc006bc980a91f7393-filelists.xml.zst delete mode 100644 tests/testdata/repos/new/repodata/d6dae028f2d94a20a5ada403a89d418b7d31c646d2350605999882725a5b0862-other.xml.zst delete mode 100644 tests/testdata/repos/unfixed/repodata/77dfe7c593c3e37af3f924516b5aa25cc512a5b8070f75fbeb4b1e844973835b-filelists.xml.zst create mode 100644 tests/testdata/repos/unfixed/repodata/9d54f4c3d3ab7c943b7e15193e2544bcb82bf7b2e8408ee3167134b0a453255d-filelists.xml.zst delete mode 100644 tests/testdata/repos/unfixed/repodata/a583ea09de5b85171eb9110dacfd240e527828cff25324ce894d3dd9c80cf961-other.xml.zst delete mode 100644 tests/testdata/repos/unfixed/repodata/daa25dfd3c818ca6b5104612d827dac24e70a2050986ed49457124116013f4ef-primary.xml.zst create mode 100644 tests/testdata/repos/unfixed/repodata/dd80d9c03852999e37b04db876c82b0483a6e906c5884b4561d83a97d7c341c7-primary.xml.zst create mode 100644 tests/testdata/repos/unfixed/repodata/ef5302dc1a621cb60e1087af579f4e2bb66e668033b107b8706a39f2c37f8026-other.xml.zst create mode 100644 tests/testdata/repos/updates/repodata/3126b56a66fb9df617bc7a7c1182bf8142d919f9852096bb6f61077a40e6ea2b-filelists.xml.zst delete mode 100644 tests/testdata/repos/updates/repodata/5f112f5ba0bd830d4f7d2b42a6d57c1041d78b661a423c3e00b0b6072fe3d690-other.xml.zst create mode 100644 tests/testdata/repos/updates/repodata/63c56609259c2a5620e4da4ccf34898028efb88337163d5b44e75a95e684d91a-primary.xml.zst delete mode 100644 tests/testdata/repos/updates/repodata/736fcb107df83b5ae000865878a1f670603afb579fbb3179e2ce4d72c9586e48-primary.xml.zst delete mode 100644 tests/testdata/repos/updates/repodata/ca771b7fed377c578d3d9ffd1b856a9c1c0e5192ad31e2d111d1ae2ed978e34c-filelists.xml.zst create mode 100644 tests/testdata/repos/updates/repodata/e07157006906a954f6b20bd3998d53515332d76c45c79661ca57763750c7b986-other.xml.zst diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 7dcbd95..d3bba7c 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: image: quay.io/fedora/fedora:latest steps: - name: Install required packages - run: dnf -y install nodejs tox git + run: dnf -y install nodejs tox git createrepo_c - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 with: fetch-depth: 0 diff --git a/README.md b/README.md index 6ebe6f1..3979edc 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,18 @@ # rmdepcheck -rmdepcheck is an RPM dependency check tool based on a repository metadata modification approach. -It works by comparing a checked repository to one or more base repositories. First, checks are run -on the base repositories as-is. Next, we re-run the checks, but with the checked repository -available and using dnf's `excludepkgs` option to hide from the base repositories all packages from -the same source RPM(s) as the package(s) in the checked repositories removed. The results of the -two runs are compared. New failures should indicate problems introduced by the checked repositories. -Also, some relevant checks are run on the checked repositories with reference to the modified base -repositories. +rmdepcheck is an RPM dependency check tool based on a repository metadata modification approach. It +exists as an installable library, but is not usually intended to be installed or imported; you are +meant to use one of the two CLI interfaces, which can be run directly with no need for installation. + +## rdc-repos + +rdc-repos is the original form of rmdepcheck. It works by comparing a checked repository to one +or more base repositories. First, checks are run on the base repositories as-is. Next, we re-run +the checks, but with the checked repository available and using dnf's `excludepkgs` option to hide +from the base repositories all packages from the same source RPM(s) as the package(s) in the +checked repositories removed. The results of the two runs are compared. New failures should +indicate problems introduced by the checked repositories. Also, some relevant checks are run on the +checked repositories with reference to the modified base repositories. Optionally, other types of repository can be specified: @@ -24,8 +29,8 @@ HighAvailability variant can depend on packages in the BaseOS and Appstream vari testing an update containing packages destined for all three variants, which we split into three repositories. When testing the HA repository, we would want to have the "new package" BaseOS and Appstream repositories "in scope" but not checked ("additional new repositories"), and the "base" -BaseOS and Appstream repositories "in scope" and modified, but not checked -("non-checked base repositories"). +BaseOS and Appstream repositories "in scope" and modified, but not checked ("non-checked base +repositories"). Additional new repositories might also be used for multilib scenarios; it may be desirable to use such an additional repository for packages for the multilib arch(es), if e.g. installability of @@ -35,28 +40,23 @@ An alternative mode allows simply testing the consequences of *removing* a list entirely; in this mode, in the second step, we exclude all binary packages built from the specified source packages. The installability check is skipped in this context. -## rdc-el-wrapper +## rdc-compose -rdc-el-wrapper is an opinionated wrapper for running rmdepcheck on Enterprise Linux. The EL case -is complicated because EL composes contain multiple variants with package repositories. These -contain a subset of all packages in the buildroot. Each variant is expected to be repoclosure- -complete with regard to itself and possibly some or all of the other variants; the mapping for -this is kept in Pungi configuration. - -Because of this we cannot just test the packages-under-test against the buildroot, as we do for -Fedora. We must split the packages-under-test set into per-variant repositories, with each package -included in each repository it should be part of (we assume this mapping is not changed from the -compose we're testing against, and discover it from that). We then test each of the split repos -against the same variant repo from the compose, with other variant repos in scope on both sides, -as per the Pungi mapping. This is a lot of work but should provide the most accurate and useful -results. +rdc-compose is alternative interface which takes a distribution compose URL (this must be a Pungi +/ productmd-style compose) and a local filesystem path containing the packages under test as inputs. +It discovers the variants contained in the compose, splits the packages-under-test into per-variant +repositories, and then checks those against the target compose appropriately in much the same way +described above, testing appropriate sets of variants against each other according to the rules on +which variants can depend on packages from which other variants. This is a lot of work but should +provide the most accurate and useful results. ## Requirements -rmdepcheck has no run-time Python dependencies outside the standard library. Its only external -dependency is dnf. It checks for dnf, and will exit early with an error if it is not found. +rdc-repos has no run-time Python dependencies outside the standard library. rdc-compose requires +the requests and urllib3 libraries. Both scripts require dnf; rdc-compose also requires createrepo. +The scripts checks for their dependencies, and will exit early with an error if they are not found. rmdepcheck is written primarily for Red Hat-family distributions, but should in theory be usable -anywhere these utilities can be installed (and forward slashes act as directory separators). +anywhere these dependencies can be installed (and forward slashes act as directory separators). If you use a version of dnf older than 5.2.15.0, you may see false failures for 'rich' dependencies, as older dnf versions did not handle these correctly. Use 5.4.0.0 or newer for the best handling @@ -74,7 +74,7 @@ directly from PyPI with pip and other tools. Simple usage looks like this: ``` -rmdepcheck https://a.base.repo.example/repo,file:///another/baserepo file:///the/testedrepo +rdc-repos https://a.base.repo.example/repo,file:///another/baserepo file:///the/testedrepo ``` The repositories are specified as a comma-separated list. Repositories should be specified as URLs, @@ -82,7 +82,7 @@ but for convenience, file:// can be omitted. Only file:// , http:// and https:// For the alternative 'removal' mode, usage looks like: ``` -rmdepcheck --removes https://a.base.repo.example/repo,file:///another/baserepo sourcepkg1,sourcepkg2 +rdc-repos --removes https://a.base.repo.example/repo,file:///another/baserepo sourcepkg1,sourcepkg2 ``` This tests removing sourcepkg1 and sourcepkg2, and all binary packages built from them, from the @@ -91,20 +91,17 @@ base repositories. If you want to test repositories containing packages of an arch that does not match the system on which you are testing, pass `--arch `, where `` is the arch you wish to test. -For more complex usage, see `rmdepcheck --help`. +For more complex usage, see `rdc-repos --help`. -Note rmdepcheck is really only intended for use as a script, not as an importable library. If you -want to use it as a library go ahead, but this isn't a supported use case and bugs in it may not -be addressed. - -rdc-el-wrapper usage looks like this: +rdc-compose usage looks like this: ``` -rdc-el-wrapper https://kojipkgs.fedoraproject.org/compose/eln/latest-Fedora-eln/compose /the/testedrepo +rdc-compose https://kojipkgs.fedoraproject.org/compose/eln/latest-Fedora-eln/compose /the/testedrepo ``` An optional `--arch` arg can be passed as for rmdepcheck. Note that you **MUST NOT** include -file:// in the tested repo arg, and it **MUST** be a local filesystem path. rdc-el-wrapper does -not support remote tested repos. +file:// in the tested repo arg, and it **MUST** be a local filesystem path. rdc-compose does not +support remote tested repos.It does not actually need to be a repository; it just needs to be a +directory with RPMs in it. ### Testing build dependencies @@ -118,7 +115,7 @@ of all source packages will be unresolvable and the tool will run slowly and pro Example: ``` -rmdepcheck https://a.base.repo.example/binaryrepo,https://a.base.repo.example/sourcerepo file:///the/testedrepo +rdc-repos https://a.base.repo.example/binaryrepo,https://a.base.repo.example/sourcerepo file:///the/testedrepo ``` ## License diff --git a/install.requires b/install.requires index f229360..804abb1 100644 --- a/install.requires +++ b/install.requires @@ -1 +1,2 @@ requests +urllib3 diff --git a/pyproject.toml b/pyproject.toml index d2d3dbd..6187694 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,8 @@ Issues = "https://codeberg.org/AdamWill/rmdepcheck/issues" Changelog = "https://codeberg.org/AdamWill/rmdepcheck/src/branch/main/CHANGELOG.md" [project.scripts] -rmdepcheck = "rmdepcheck:main" +rdc-repos = "rmdepcheck.repos:main" +rdc-compose = "rmdepcheck.compose:main" [build-system] requires = ["setuptools>=40.6.0", "setuptools-git", "wheel"] @@ -47,7 +48,7 @@ branch = true source_pkgs = ["rmdepcheck"] [tool.coverage.paths] -source = [".", ".tox/**/site-packages"] +source = ["src", ".tox/**/site-packages"] [tool.coverage.report] show_missing = true diff --git a/rdc-compose b/rdc-compose new file mode 100755 index 0000000..261612a --- /dev/null +++ b/rdc-compose @@ -0,0 +1,14 @@ +#!/usr/bin/python3 + +"""Convenience wrapper for executing rdc-compose from a git checkout.""" + +import os +import sys + +# add src subdirectory directory to module import path +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), "src")) + +from rmdepcheck.compose import main # pylint: disable=wrong-import-position + +if __name__ == "__main__": + main() diff --git a/rdc-el-wrapper.py b/rdc-el-wrapper.py deleted file mode 100755 index 30b03d8..0000000 --- a/rdc-el-wrapper.py +++ /dev/null @@ -1,256 +0,0 @@ -#!/usr/bin/python3 - -# Copyright Red Hat -# -# This file is part of rmdepcheck. -# -# rmdepcheck is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation, either version 3 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Author(s): Adam Williamson - - -"""Opinionated rmdepcheck wrapper that handles the awkward Enterprise -Linux case, where we have to test against multiple shipped variants -with complex lookaside relationships, all filtered from a shared build -root. -""" - -# Standard libraries - -import argparse -import ast -import os -import pathlib -import platform -import re -import shutil -import subprocess -import sys -import tempfile -from functools import partial -from urllib.parse import urlparse - -from requests import Session -from requests.adapters import HTTPAdapter -from requests.packages.urllib3.util.retry import Retry - -VrDict = dict[str, str] - -DNFTEMP = tempfile.TemporaryDirectory(prefix="rdcelndnf", dir="/var/tmp") -DNFARGS = ["dnf", "--setopt", f"cachedir={DNFTEMP.name}", "-q", "--disablerepo=*"] -HERE = os.path.abspath(os.path.dirname(__file__)) -SESSION = Session() -SUBPCAPTURE = partial(subprocess.run, capture_output=True, text=True, check=False) - - -def split_put(put: pathlib.Path, repotemp: pathlib.Path, vrs: VrDict) -> set[str]: - """Splits a directory containing the packages to be tested into - multiple repositories per variant. put ('packages under test') - is the filesystem path containing packages under test (it cannot - be an HTTP URL, in this opinionated wrapper). repotemp is a Path - to a temporary directory to store the split repos. vrs is a dict - with variant IDs as keys and full compose repo URLs as values. - For each package under test, we get its name, look for a package - of the same name in each of the variant repositories, and if - there is one, we put the package in a subdirectory of repotemp, - named for the variant. At the end, we run createrepo in each of - the subdirectories we created, and return their names. - """ - if not (put.exists() and put.is_dir()): - raise ValueError(f"split_put: invalid put value {put}") - put = put.absolute() - # generate per-variant package name lists - pkgs = {} - for variant, repo in vrs.items(): - args = DNFARGS + [ - "--repofrompath", f"{variant},{repo}", "repoquery", "--queryformat", "%{name}\n" - ] - res = SUBPCAPTURE(args) - res.check_returncode() - pkgs[variant] = res.stdout.splitlines() - # track which variants we 'populate' - populated = set() - for _file in os.listdir(put): - if _file.endswith(".rpm"): - pkgname = _file.rsplit("-", 2)[0] - for (variant, pkgnames) in pkgs.items(): - if pkgname in pkgnames: - populated.add(variant) - os.makedirs(repotemp / variant, exist_ok=True) - try: - # hardlink - os.link(put / _file, repotemp / variant / _file) - except OSError: - # copy - shutil.copy2(put / _file, repotemp / variant / _file) - for variant in populated: - subprocess.run(("createrepo", str(repotemp / variant)), capture_output=True, check=True) - return populated - - -def get_variant_repos(compose: str, arch: str) -> VrDict: - """Discover variants with repositories in a compose, return a - dict with variant IDs as keys and repo URLs as values. - """ - resp = SESSION.get(f"{compose}/metadata/composeinfo.json") - resp.raise_for_status() - ci = resp.json() - variants = ci["payload"]["variants"] - ret = {} - for variant in variants: - if variants[variant]["id"].lower() == "buildroot": - continue - repopath = variants[variant]["paths"].get("repository", {}).get(arch, "") - if not repopath: - continue - ret[variants[variant]["id"]] = f"{compose}/{repopath}" - return ret - - -def get_val(): - """Get the variants_as_lookaside list which tells us which - variants pull in which other variants. FIXME: this is currently - ELN specific. - """ - resp = SESSION.get( - "https://forge.fedoraproject.org/releng/pungi-fedora/raw/branch/eln/fedora/override.conf" - ) - resp.raise_for_status() - override = resp.text - # next three lines suggested by AI - match = re.search(r"variant_as_lookaside\s*=\s*(\[.*?\])", override, re.DOTALL) - if not match: - raise ValueError("Could not find variant_as_lookaside in configuration") - # eek - return ast.literal_eval(match.group(1)) - - -def url_check(arg: str) -> str: - """Check arg is an http or https URL.""" - parsed = urlparse(arg) - if parsed.scheme in ("http", "https"): - return arg - if parsed.scheme: - raise ValueError(f"Unsupported URL scheme {parsed.scheme} in {arg}") - raise ValueError(f"No URL scheme in {arg}") - - -def check_arch(arg: str) -> str: - """Use host arch if no value passed.""" - if arg: - return arg - return platform.machine() - - -def check_utils() -> None: - """Check required utilities are installed.""" - missing = [] - for prog in (("dnf", "--version"), ("createrepo", "--version")): - try: - subprocess.run(prog, stdout=subprocess.DEVNULL, check=True) - except FileNotFoundError: - missing.append(prog[0]) - if missing: - sys.exit("Please install missing required utilities: " + " ".join(missing)) - - -def parse_args() -> argparse.Namespace: - """Parse arguments with argparse.""" - parser = argparse.ArgumentParser( - description=("Opinionated rmdepcheck wrapper for EL use cases.") - ) - parser.add_argument( - "compose", - type=url_check, - help="The URL(s) of a compose to discover variant repos from and check against", - ) - parser.add_argument( - "repo", - type=pathlib.Path, - help="Local filesystem path containing packages to test", - ) - parser.add_argument( - "--arch", - type=check_arch, - default="", - help="Arch to operate on. Must match arch of passed repository", - ) - return parser.parse_args() - - -def main() -> None: - """Main loop.""" - try: - # set up requests session with retries - retries = Retry( - total=5, - backoff_factor=0.5, - status_forcelist=[502, 503, 504], - allowed_methods={'GET'}, - ) - SESSION.mount('https://', HTTPAdapter(max_retries=retries)) - - # check DNF is installed - check_utils() - - # set up args - args = parse_args() - if f"--forcearch={args.arch}" not in DNFARGS: - DNFARGS.append(f"--forcearch={args.arch}") - - # find variants, do the repo split - vrs = get_variant_repos(args.compose, args.arch) - val = get_val() - with tempfile.TemporaryDirectory(prefix="rdcelnrepo", dir="/var/tmp") as repotd: - repotemp = pathlib.Path(repotd) - variants = split_put(args.repo, repotemp, vrs) - - rets = set() - for variant in variants: - # figure out what other variants to pull in per val - depvars = set() - for pair in val: - if pair[0] == variant: - depvars.add(pair[1]) - # put the compose repos for all variants in basearg, even - # ones we didn't 'populate' locally - basearg = vrs[variant] - ncbasearg = ",".join(vrs[var] for var in depvars) - newarg = str(repotemp / variant) - # put depended-on variant-split PUT repos that actually - # exist in addrepos - # variants contains only variants we 'populated' - addarg = ",".join(str(repotemp / var) for var in depvars if var in variants) - # run rmdepcheck, track return code - # FIXME: what to do about JSON mode? capture output, combine? - rargs = [f"{HERE}/rmdepcheck.py", "--arch", args.arch] - if addarg: - rargs.extend(("--addrepos", addarg)) - if ncbasearg: - rargs.extend(("--ncbaserepos", ncbasearg)) - rargs.extend((basearg, newarg)) - rets.add(subprocess.run(rargs, check=False).returncode) - - # we exit the sum of all *unique* return codes - sys.exit(sum(rets)) - - except KeyboardInterrupt: - sys.stderr.write("Interrupted, exiting...\n") - sys.exit(1) - - -if __name__ == "__main__": # pragma: no cover - main() - -# vim: set textwidth=100 ts=8 et sw=4: diff --git a/rdc-repos b/rdc-repos new file mode 100755 index 0000000..bebd111 --- /dev/null +++ b/rdc-repos @@ -0,0 +1,14 @@ +#!/usr/bin/python3 + +"""Convenience wrapper for executing rdc-repos from a git checkout.""" + +import os +import sys + +# add src subdirectory directory to module import path +sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), "src")) + +from rmdepcheck.repos import main # pylint: disable=wrong-import-position + +if __name__ == "__main__": + main() diff --git a/rmdepcheck.py b/rmdepcheck.py deleted file mode 100755 index 41e9c06..0000000 --- a/rmdepcheck.py +++ /dev/null @@ -1,445 +0,0 @@ -#!/usr/bin/python3 - -# Copyright Red Hat -# -# This file is part of rmdepcheck. -# -# rmdepcheck is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation, either version 3 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Author(s): Adam Williamson - - -"""RPM package installability and reverse-dependency checks using a -repository modification strategy (hence 'rm'). -""" - -# Standard libraries - -import argparse -import hashlib -import json -import os -import platform -import subprocess -import sys -import tempfile -from functools import partial -from typing import Iterable -from urllib.parse import urlparse - -# type alias for the tuples produced by parse_repoclosure -# can't properly declare this because type statement was only added in -# 3.12, and TypeAlias is deprecated since 3.12 and wasn't in 3.9 -DepTuple = tuple[str, str, str] - -# use a fresh temporary cache for each run to avoid collisions between -# runs and polluting the 'real' cache -# pylint: disable-next=consider-using-with -DNFTEMP = tempfile.TemporaryDirectory(prefix="rmdepcheck", dir="/var/tmp") -DNFARGS = ["dnf", "--setopt", f"cachedir={DNFTEMP.name}", "-q", "--disablerepo=*"] -SUBPCAPTURE = partial(subprocess.run, capture_output=True, text=True, check=False) -SUBPCAPTCHECK = partial(subprocess.run, capture_output=True, text=True, check=True) -SUBPCHECK = partial(subprocess.run, check=True) -REPOHASHES: dict[str, str] = {} - - -def hash_repo(repo: str) -> str: - """Generate a hash for the repo name, stash it in a dict so we can - map back out later, and return it. This is so we can show the repo - URLs in our final output, as opposed to non-useful made-up repo - names. Not security sensitive. - """ - gothash = hashlib.sha256(repo.encode(encoding="utf-8")).hexdigest()[:8] - REPOHASHES[gothash] = repo - return gothash - - -def parse_repoclosure(rc: str) -> list[DepTuple]: - """Given some `dnf repoclosure` output, parse it into a list of - 3-tuples each containing a package name, a repo URL (or generated - repo name if we can't look up the hash, should only happen in - tests) and an unresolved dependency for that package. - """ - out = [] - pkg = None - for line in rc.splitlines(): - if not line.strip(): - continue - if line.strip().startswith("package:"): - # package, repo - elems = line.split() - pkg = (elems[1], REPOHASHES.get(elems[3], elems[3])) - continue - if line.strip().startswith("unresolved deps (") or line.strip().startswith("Error:"): - continue - # anything else is an unresolved dep - if pkg: - out.append(pkg + (line.strip(),)) - return out - - -def format_rc_errors(errors: list[DepTuple]) -> None: - """Format and print parse_repoclosure-style tuples for humans to - read. Used for final output after we do some diffing on the lists - of tuples. - """ - pkg = ("", "") - for error in errors: - if error[:2] != pkg: - pkg = error[:2] - print(f"package: {error[0]} from {error[1]}") - print(f" {error[2]}") - - -def get_base_repoclosure( - baserepos: Iterable[str], ncbaserepos: Iterable[str], nmbaserepos: Iterable[str] -) -> str: - """Gets the reference repoclosure text. Base repos, non-checked - base repos and non-modified base repos are available to the - solver, but only the base repos are checked. - """ - cmdargs = DNFARGS + ["repoclosure"] - for repo in list(baserepos) + list(nmbaserepos) + list(ncbaserepos): - cmdargs.extend(["--repofrompath", f"{hash_repo(repo)},{repo}"]) - cmdargs.append("--check") - # only check the repos that will be modified - cmdargs.append(",".join([hash_repo(baserepo) for baserepo in baserepos])) - return SUBPCAPTURE(cmdargs).stdout - - -def get_modified_and_new_repoclosure( - baserepos: list[str], - ncbaserepos: list[str], - nmbaserepos: list[str], - newrepos: list[str], - removes: Iterable[str], -) -> tuple[str, str]: - """Runs repoclosure with new repo included and excludepkgs used - for modified base repos, and returns the modified repoclosure - text. Non-modified base repos, modified base repos and non-checked - base repos after modification, and new repos are available to - the solver; only the base repos are checked in the "modified" - check and only the first new repo is checked in the "new" check. - """ - queryargs = DNFARGS + ["repoquery", "--queryformat", "%{source_name},%{full_nevra}\n"] - rcargs = DNFARGS + ["repoclosure"] - for mrepo in baserepos + ncbaserepos: - # figure out what to exclude - excludes = [] - args = queryargs + ["--repofrompath", f"{hash_repo(mrepo)},{mrepo}"] - out = SUBPCAPTURE(args).stdout - for line in out.splitlines(): - # sname, nevr - elems = line.split(",") - if len(elems) != 2: - continue - if elems[0] in removes: - excludes.append(elems[1]) - # add each modified base repo with excludepkgs set to the - # list we discovered above, in the repoclosure args - rcargs.extend(["--repofrompath", f"{hash_repo(mrepo)},{mrepo}"]) - # there is a theoretical risk we might exceed MAX_ARG_STRLEN - # here, which is usually 131072: - # https://stackoverflow.com/a/29802900/4460661 - # still, 131072 is enough for 2621 50-character NEVRs... - rcargs.extend(["--setopt", f"{hash_repo(mrepo)}.excludepkgs={','.join(excludes)}"]) - - # now add the non-modified base repos and new package repos - for repo in nmbaserepos + newrepos: - rcargs.extend(["--repofrompath", f"{hash_repo(repo)},{repo}"]) - - # finally, add the check arg - rcargs.append("--check") - rcargs.append(",".join([hash_repo(baserepo) for baserepo in baserepos])) - - # get the modified repoclosure - mod = SUBPCAPTURE(rcargs).stdout - new = "" - if newrepos: - # the first newrepo is the checked repo, only check that - rcargs[-1] = hash_repo(newrepos[0]) - # get the new repoclosure - new = SUBPCAPTURE(rcargs).stdout - return (mod, new) - - -def get_source_packages(repos: Iterable[str]) -> set[str]: - """Finds and returns the source package names for all packages in - the repositories specified, as a set. - """ - args = list(DNFARGS) - for repo in repos: - args.extend(["--repofrompath", f"{hash_repo(repo)},{repo}"]) - args.extend(["repoquery", "--qf", "%{sourcerpm} "]) - srpms = SUBPCAPTCHECK(args).stdout.split() - return {srpm.rsplit("-", 2)[0] for srpm in srpms} - - -def handle_preexisting(fixederrors: list[DepTuple], newrc: list[DepTuple]) -> list[DepTuple]: - """Catch cases where an error 'moved' from baserc to newrc - a - package in the set under test previously had a dependency issue, - and the new build does not fix it. We should not report this as a - fixed issue in the old repo and a new issue in the repo under - test. Note this modifies the passed lists in-place. See: - https://forge.fedoraproject.org/quality/rmdepcheck/issues/17 - """ - preexisting = [] - if fixederrors and newrc: - # iterate over copies so we can modify originals on the fly - fecopy = fixederrors.copy() - nrcopy = newrc.copy() - for fixeddep in fecopy: - # see if we can find a broken dep in newrc - the set of - # errors in the repository under test - that exactly - # matches this one, and is for the same package name - newmatch = [ - newdep - for newdep in nrcopy - if newdep[0].rsplit("-", 2)[0] == fixeddep[0].rsplit("-", 2)[0] - and newdep[2] == fixeddep[2] - ] - if len(newmatch) == 1: - # if so, remove the dep from both lists and add it - # to the new return list so we report it correctly - fixederrors.remove(fixeddep) - newrc.remove(newmatch[0]) - preexisting.append(newmatch[0]) - return preexisting - - -def url_check(arg: str) -> str: - """Check arg is a file, http or https URL. Automatically converts - local paths to file:// URIs.""" - # If it's an existing local path, convert to file:// URI - if os.path.exists(arg): - return f"file://{os.path.abspath(arg)}" - - parsed = urlparse(arg) - if parsed.scheme in ("http", "https", "file"): - return arg - if parsed.scheme: - raise ValueError(f"Unsupported URL scheme {parsed.scheme} in {arg}") - raise ValueError(f"No URL scheme in {arg}") - - -def comma_url(arg: str) -> list[str]: - """Check arg is a comma-separated list of URLs and return them - all as a list. If arg is the empty string, return empty list. - """ - if arg == "": - return [] - split = arg.split(",") - for item in split: - try: - url_check(item) - except ValueError as err: - newerr = str(err) + f"from {arg}" - raise ValueError(newerr) from err - return split - - -def comma_list(arg: str) -> list[str]: - """Handle a comma-separated list, return as a list.""" - if arg == "": - return [] - return arg.split(",") - - -def check_arch(arg: str) -> str: - """Use host arch if no value passed.""" - if arg: - return arg - return platform.machine() - - -def parse_args() -> argparse.Namespace: - """Parse arguments with argparse.""" - parser = argparse.ArgumentParser( - description=("Reverse dependency check implemented as a repoclosure diff.") - ) - parser.add_argument( - "--addrepos", - type=comma_url, - default="", - help="The URL(s) of additional repositories containing new packages to be tested " - "(comma-separated). This is mainly intended for multilib cases: i.e. for testing " - "x86_64 package sets it should contain the matching i686 packages. It will be " - "available to the repoclosure check, but will be ignored by the installability check", - ) - parser.add_argument( - "--ncbaserepos", - type=comma_url, - default="", - help="The URL(s) of non-checked base repositories to compare against (comma-separated). " - "These repositories *will* be modified as part of testing, but they will not be checked " - "for repoclosure. They should be repositories whose packages would be replaced with those " - "from the new package repo(s), and which we want to be available to the dependency solver " - "when checking the repoclosure of other repositories, but which we are for some reason not " - "interested in checking the repoclosure of - e.g. the buildroot for Fedora ELN", - ) - parser.add_argument( - "--nmbaserepos", - type=comma_url, - default="", - help="The URL(s) of non-modified base repositories to compare against (comma-separated). " - "These repositories *will not* be modified as part of testing. They should be repositories " - "whose packages would *not* be replaced with those from the new package repo(s) - e.g. " - "the frozen release repository for a stable release, which is never changed", - ) - parser.add_argument( - "--json", - action="store_true", - help="Output results in JSON rather than human-readable format", - ) - parser.add_argument( - "--onlyerrors", - action="store_true", - help="Only print messages about problems caused, not about things that would be fixed", - ) - parser.add_argument( - "--removes", - action="store_true", - help="Alternative mode: test removal (only) of all binary packages in the baserepos built " - "from the source package(s) specified as the final argument (a comma-separated list)", - ) - parser.add_argument( - "--arch", - type=check_arch, - default="", - help="Arch to operate on. Must match arch of passed repositories. Defaults to host arch", - ) - parser.add_argument( - "baserepos", - type=comma_url, - help="The URL(s) of base repositories to compare against (comma-separated). " - "These repositories *will* be modified as part of testing. They should be " - "repositories whose packages would be replaced with those from the new package " - "repo(s) - e.g. the main repository for a development release, or the updates repository " - "for a stable release", - ) - # I wanted to do this with parse_known_args, but it messes up --help. aw - if "--removes" in sys.argv: - parser.add_argument( - "removes", - type=comma_list, - help="A comma-separated list of source packages to test the removal of", - ) - else: - parser.add_argument( - "repo", - metavar="repo_or_removes", - type=url_check, - help="The URL of the repo containing the main set of new packages to be tested, " - "or a comma-separated list of source packages to test the removal of (if --removes " - "is passed)", - ) - args = parser.parse_args() - if args.removes: - args.repo = "" - else: - args.removes = "" - return args - - -def check_dnf() -> None: - """Check DNF is installed.""" - try: - subprocess.run(("dnf", "--version"), stdout=subprocess.DEVNULL, check=True) - except FileNotFoundError: - sys.exit("Please install missing required utilities: dnf") - - -def main() -> None: - """Main loop.""" - try: - check_dnf() - exitcode = 0 - args = parse_args() - if f"--forcearch={args.arch}" not in DNFARGS: - DNFARGS.append(f"--forcearch={args.arch}") - if args.removes: - newrepos = [] - sources = args.removes - iut = "the specified source package removals" - else: - newrepos = [args.repo] + args.addrepos - # find source package(s) of our tested repo(s) - # whether to include addrepos is arguable, but should usually be moot - sources = get_source_packages(newrepos) - iut = "the tested packages" - - baseraw = get_base_repoclosure(args.baserepos, args.ncbaserepos, args.nmbaserepos) - baserc = parse_repoclosure(baseraw) - - # get the modified rpmclosure output - modraw, newraw = get_modified_and_new_repoclosure( - args.baserepos, args.ncbaserepos, args.nmbaserepos, newrepos, sources - ) - modrc = parse_repoclosure(modraw) - newrc = [] - if newraw: - newrc = parse_repoclosure(newraw) - - newerrors = [dep for dep in modrc if dep not in baserc] - fixederrors = [dep for dep in baserc if dep not in modrc] - preexisting = handle_preexisting(fixederrors, newrc) - - # output - if args.json: - jsonout = {} - if newerrors: - if args.json: - jsonout["newerrors"] = [list(err) for err in newerrors] - else: - print(f"Dependencies of other packages that would be BROKEN by {iut}:") - format_rc_errors(newerrors) - exitcode += 1 - if newrc: - if args.json: - jsonout["installability"] = [list(err) for err in newrc] - else: - print("") - print("New dependency problems in the tested packages themselves:") - format_rc_errors(newrc) - exitcode += 2 - if preexisting: - if args.json: - jsonout["installability_preexisting"] = [list(err) for err in preexisting] - else: - print("") - print("Pre-existing dependency problems in the tested packages themselves:") - format_rc_errors(preexisting) - exitcode += 4 - if fixederrors: - if args.json: - jsonout["fixederrors"] = [list(err) for err in fixederrors] - elif not args.onlyerrors: - print("") - print(f"Dependencies of other packages that would be FIXED by {iut}:") - format_rc_errors(fixederrors) - if args.json: - json.dump(jsonout, sys.stdout, indent=4) - sys.stdout.write("\n") - - sys.exit(exitcode) - - except KeyboardInterrupt: - sys.stderr.write("Interrupted, exiting...\n") - sys.exit(1) - - -if __name__ == "__main__": # pragma: no cover - main() - -# vim: set textwidth=100 ts=8 et sw=4: diff --git a/rmdepcheck.py b/rmdepcheck.py new file mode 120000 index 0000000..e033b75 --- /dev/null +++ b/rmdepcheck.py @@ -0,0 +1 @@ +rdc-repos \ No newline at end of file diff --git a/src/rmdepcheck/__init__.py b/src/rmdepcheck/__init__.py new file mode 100644 index 0000000..ae9f5b5 --- /dev/null +++ b/src/rmdepcheck/__init__.py @@ -0,0 +1,29 @@ +#!/usr/bin/python3 + +# Copyright Red Hat +# +# This file is part of rmdepcheck. +# +# rmdepcheck is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Author(s): Adam Williamson + + +"""RPM package installability and reverse-dependency checks using a +repository modification strategy (hence 'rm'). +""" + +__version__ = "1.0.0" + +# vim: set textwidth=100 ts=8 et sw=4: diff --git a/src/rmdepcheck/compose.py b/src/rmdepcheck/compose.py new file mode 100644 index 0000000..31c2b32 --- /dev/null +++ b/src/rmdepcheck/compose.py @@ -0,0 +1,279 @@ +# Copyright Red Hat +# +# This file is part of rmdepcheck. +# +# rmdepcheck is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Author(s): Adam Williamson + + +"""RPM package installability and reverse-dependency checks using a +repository modification strategy (hence 'rm'). This module contains +the rdc-compose CLI which operates against composes and contains the +logic for splitting and testing variants appropriately. +""" + +# Standard libraries + +import argparse +import ast +import os +import pathlib +import re +import shutil +import subprocess +import sys +import tempfile + +from requests import Session +from requests.adapters import HTTPAdapter +from urllib3.util.retry import Retry + +from rmdepcheck.shared import ( + SUBPCAPTURE, + get_dnf_args, + check_arch, + url_check, + check_utils, + get_source_packages, + get_base_repoclosure, + get_modified_and_new_repoclosure, + parse_display_exit, +) + +VrDict = dict[str, str] + + +def split_put( + put: pathlib.Path, repotemp: pathlib.Path, vrs: VrDict, dnfargs: list[str] +) -> set[str]: + """Splits a directory containing the packages to be tested into + multiple repositories per variant. put ('packages under test') + is the filesystem path containing packages under test (it cannot + be an HTTP URL, on this path). repotemp is a Path to a temporary + directory to store the split repos. vrs is a dict with variant IDs + as keys and full compose repo URLs as values. For each package + under test, we get its name, look for a package of the same name + in each of the variant repositories, and if there is one, we put + the package in a subdirectory of repotemp, named for the variant. + At the end, we run createrepo in each of the subdirectories we + created, and return their names. + """ + if not (put.exists() and put.is_dir()): + raise ValueError(f"split_put: invalid put value {put}") + put = put.absolute() + # generate per-variant package name lists + pkgs = {} + for variant, repo in vrs.items(): + args = dnfargs + [ + "--repofrompath", + f"{variant},{repo}", + "repoquery", + "--queryformat", + "%{name}\n", + ] + res = SUBPCAPTURE(args) + res.check_returncode() + pkgs[variant] = res.stdout.splitlines() + # track which variants we 'populate' + populated = set() + for _file in os.listdir(put): + if _file.endswith(".rpm"): + pkgname = _file.rsplit("-", 2)[0] + for variant, pkgnames in pkgs.items(): + if pkgname in pkgnames: + populated.add(variant) + os.makedirs(repotemp / variant, exist_ok=True) + try: + # hardlink + os.link(put / _file, repotemp / variant / _file) + except OSError: + # copy + shutil.copy2(put / _file, repotemp / variant / _file) + for variant in populated: + subprocess.run(("createrepo", str(repotemp / variant)), capture_output=True, check=True) + return populated + + +def get_variant_repos(compose: str, ci: dict, arch: str) -> VrDict: + """Discover variants with repositories in a compose, return a + dict with variant IDs as keys and repo URLs as values. + """ + variants = ci.get("payload", {}).get("variants", {}) + ret = {} + for variant in variants: + vid = variants[variant].get("id", variant) + # as of 2026-05 yselkowitz says he does not want to know about + # buildroot-only dep issues + if vid.lower() == "buildroot": + continue + repopath = variants[variant].get("paths", {}).get("repository", {}).get(arch, "") + if not repopath: + continue + ret[vid] = f"{compose}/{repopath}" + return ret + + +def pungi_config_url(ci: dict) -> str: + """Return the URL with the appropriate Pungi config for the + release. Here be magic knowledge. + """ + version = ci.get("payload", {}).get("release", {}).get("version", "") + short = ci.get("payload", {}).get("release", {}).get("short", "") + if version.lower() == "eln" and short.lower() == "fedora": + # pylint: disable-next=line-too-long + return "https://forge.fedoraproject.org/releng/pungi-fedora/raw/branch/eln/fedora/override.conf" + raise ValueError(f"Don't know Pungi config URL for {short} {version}") + + +def get_val(ci: dict, session: Session) -> dict: + """Get the variants_as_lookaside list which tells us which + variants pull in which other variants. + """ + url = pungi_config_url(ci) + resp = session.get(url) + resp.raise_for_status() + override = resp.text + # next three lines suggested by AI + match = re.search(r"variant_as_lookaside\s*=\s*(\[.*?\])", override, re.DOTALL) + if not match: + raise ValueError(f"Could not find variant_as_lookaside in configuration at {url}") + # eek + return ast.literal_eval(match.group(1)) + + +def url_check_http(arg: str) -> str: + """Check arg is an http or https URL.""" + return url_check(arg, fileok=False) + + +def parse_args() -> argparse.Namespace: + """Parse arguments with argparse.""" + parser = argparse.ArgumentParser( + description="Reverse dependency check implemented as a repoclosure diff. Checks against " + "a compose. Intended for Enterprise Linux use cases." + ) + parser.add_argument( + "compose", + type=url_check_http, + help="The URL(s) of a compose to discover variant repos from and check against", + ) + parser.add_argument( + "repo", + type=pathlib.Path, + help="Local filesystem path containing packages to test", + ) + parser.add_argument( + "--arch", + type=check_arch, + default="", + help="Arch to operate on. Must match arch of passed repository", + ) + parser.add_argument( + "--json", + action="store_true", + help="Output results in JSON rather than human-readable format", + ) + return parser.parse_args() + + +def main() -> None: # pylint: disable=too-many-locals + """Main loop.""" + try: + # set up requests session with retries + session = Session() + retries = Retry( + total=5, + backoff_factor=0.5, + status_forcelist=[502, 503, 504], + allowed_methods={"GET"}, + ) + session.mount("https://", HTTPAdapter(max_retries=retries)) + + # check DNF and createrepo are installed + check_utils((("dnf", "--version"), ("createrepo", "--version"))) + + # set up args + args = parse_args() + + # repoclosure output strings + basercs = "" + modrcs = "" + newrcs = "" + # get composeinfo + resp = session.get(f"{args.compose}/metadata/composeinfo.json") + resp.raise_for_status() + ci = resp.json() + # find variants, do the repo split + vrs = get_variant_repos(args.compose, ci, args.arch) + val = get_val(ci, session) + with ( + tempfile.TemporaryDirectory(prefix="rdccomposerepo", dir="/var/tmp") as repotd, + tempfile.TemporaryDirectory(prefix="rdccomposednf", dir="/var/tmp") as dnftemp, + ): + dnfargs = get_dnf_args(dnftemp, args.arch) + repotemp = pathlib.Path(repotd) + # this is "all the variants with packages in the new repo" + variants = split_put(args.repo, repotemp, vrs, dnfargs) + # we have to check all variants we have new packages in + # *and* all variants that depend on them + tocheck = set(variants) + for pair in val: + if pair[0] in variants: + tocheck.add(pair[1]) + + for variant in tocheck: + baserepo = vrs[variant] + # figure out what other variants to pull in per val + depvars = set() + for pair in val: + if pair[0] == variant: + depvars.add(pair[1]) + # put the compose repos for all depended-on variants in + # ncbaserepos, even ones we didn't 'populate' locally + ncbaserepos = [vrs[var] for var in depvars] + newrepo = "" + newrepos = [] + if variant in variants: + # first newrepo is the PUT repo for this variant, + # *if* it exists + newrepo = str(repotemp / variant) + newrepos.append(newrepo) + # additional repos are depended-on variant-split PUT + # repos that actually exist + # variants contains only variants we 'populated' + addrepos = [str(repotemp / var) for var in depvars if var in variants] + newrepos.extend(addrepos) + + baserc = get_base_repoclosure([baserepo], ncbaserepos, [], dnfargs) + basercs = f"{basercs}\n{baserc}" + + # get the modified rpmclosure output + sources = get_source_packages(newrepos, dnfargs) + modrc, newrc = get_modified_and_new_repoclosure( + [baserepo], ncbaserepos, [], newrepo, addrepos, sources, dnfargs + ) + modrcs = f"{modrcs}\n{modrc}" + if newrc: + newrcs = f"{newrcs}\n{newrc}" + + # output + parse_display_exit(basercs, modrcs, newrcs, "the tested packages", args.json, False, True) + + except KeyboardInterrupt: + sys.stderr.write("Interrupted, exiting...\n") + sys.exit(1) + + +# vim: set textwidth=100 ts=8 et sw=4: diff --git a/src/rmdepcheck/repos.py b/src/rmdepcheck/repos.py new file mode 100644 index 0000000..661c1a8 --- /dev/null +++ b/src/rmdepcheck/repos.py @@ -0,0 +1,204 @@ +# Copyright Red Hat +# +# This file is part of rmdepcheck. +# +# rmdepcheck is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Author(s): Adam Williamson + + +"""RPM package installability and reverse-dependency checks using a +repository modification strategy (hence 'rm'). This module contains +the rdc-repos CLI which operates against repositories. +""" + +# Standard libraries + +import argparse +import sys +import tempfile + +from rmdepcheck.shared import ( + get_dnf_args, + check_arch, + url_check, + check_utils, + get_source_packages, + get_base_repoclosure, + get_modified_and_new_repoclosure, + parse_display_exit, +) + + +def url_check_file(arg: str) -> str: + """Check arg is a file, http or https URL. Automatically converts + local paths to file:// URIs.""" + return url_check(arg, fileok=True) + + +def comma_url(arg: str) -> list[str]: + """Check arg is a comma-separated list of URLs and return them + all as a list. If arg is the empty string, return empty list. + """ + if arg == "": + return [] + split = arg.split(",") + for item in split: + try: + url_check_file(item) + except ValueError as err: + newerr = str(err) + f"from {arg}" + raise ValueError(newerr) from err + return split + + +def comma_list(arg: str) -> list[str]: + """Handle a comma-separated list, return as a list.""" + if arg == "": + return [] + return arg.split(",") + + +def parse_args() -> argparse.Namespace: + """Parse arguments with argparse.""" + parser = argparse.ArgumentParser( + description=("Reverse dependency check implemented as a repoclosure diff.") + ) + parser.add_argument( + "--addrepos", + type=comma_url, + default="", + help="The URL(s) of additional repositories containing new packages to be tested " + "(comma-separated). This is mainly intended for multilib cases: i.e. for testing " + "x86_64 package sets it should contain the matching i686 packages. It will be " + "available to the repoclosure check, but will be ignored by the installability check", + ) + parser.add_argument( + "--ncbaserepos", + type=comma_url, + default="", + help="The URL(s) of non-checked base repositories to compare against (comma-separated). " + "These repositories *will* be modified as part of testing, but they will not be checked " + "for repoclosure. They should be repositories whose packages would be replaced with those " + "from the new package repo(s), and which we want to be available to the dependency solver " + "when checking the repoclosure of other repositories, but which we are for some reason not " + "interested in checking the repoclosure of - e.g. the buildroot for Fedora ELN", + ) + parser.add_argument( + "--nmbaserepos", + type=comma_url, + default="", + help="The URL(s) of non-modified base repositories to compare against (comma-separated). " + "These repositories *will not* be modified as part of testing. They should be repositories " + "whose packages would *not* be replaced with those from the new package repo(s) - e.g. " + "the frozen release repository for a stable release, which is never changed", + ) + parser.add_argument( + "--json", + action="store_true", + help="Output results in JSON rather than human-readable format", + ) + parser.add_argument( + "--onlyerrors", + action="store_true", + help="Only print messages about problems caused, not about things that would be fixed", + ) + parser.add_argument( + "--removes", + action="store_true", + help="Alternative mode: test removal (only) of all binary packages in the baserepos built " + "from the source package(s) specified as the final argument (a comma-separated list)", + ) + parser.add_argument( + "--arch", + type=check_arch, + default="", + help="Arch to operate on. Must match arch of passed repositories. Defaults to host arch", + ) + parser.add_argument( + "baserepos", + type=comma_url, + help="The URL(s) of base repositories to compare against (comma-separated). " + "These repositories *will* be modified as part of testing. They should be " + "repositories whose packages would be replaced with those from the new package " + "repo(s) - e.g. the main repository for a development release, or the updates repository " + "for a stable release", + ) + # I wanted to do this with parse_known_args, but it messes up --help. aw + if "--removes" in sys.argv: + parser.add_argument( + "removes", + type=comma_list, + help="A comma-separated list of source packages to test the removal of", + ) + else: + parser.add_argument( + "repo", + metavar="repo_or_removes", + type=url_check_file, + help="The URL of the repo containing the main set of new packages to be tested, " + "or a comma-separated list of source packages to test the removal of (if --removes " + "is passed)", + ) + args = parser.parse_args() + if args.removes: + args.repo = "" + else: + args.removes = "" + return args + + +def main() -> None: + """Main loop.""" + try: + check_utils((("dnf", "--version"),)) + args = parse_args() + with tempfile.TemporaryDirectory(prefix="rdcrepos", dir="/var/tmp") as dnftemp: + dnfargs = get_dnf_args(dnftemp, args.arch) + if args.removes: + newrepo = "" + sources = args.removes + iut = "the specified source package removals" + else: + newrepo = args.repo + newrepos = [newrepo] + args.addrepos + # find source package(s) of our tested repo(s) + # whether to include addrepos is arguable, but should usually be moot + sources = get_source_packages(newrepos, dnfargs) + iut = "the tested packages" + + baseraw = get_base_repoclosure( + args.baserepos, args.ncbaserepos, args.nmbaserepos, dnfargs + ) + + # get the modified rpmclosure output + modraw, newraw = get_modified_and_new_repoclosure( + args.baserepos, + args.ncbaserepos, + args.nmbaserepos, + newrepo, + args.addrepos, + sources, + dnfargs, + ) + + # output + parse_display_exit(baseraw, modraw, newraw, iut, args.json, args.onlyerrors, False) + + except KeyboardInterrupt: + sys.stderr.write("Interrupted, exiting...\n") + sys.exit(1) + + +# vim: set textwidth=100 ts=8 et sw=4: diff --git a/src/rmdepcheck/shared.py b/src/rmdepcheck/shared.py new file mode 100644 index 0000000..888b9f0 --- /dev/null +++ b/src/rmdepcheck/shared.py @@ -0,0 +1,341 @@ +# Copyright Red Hat +# +# This file is part of rmdepcheck. +# +# rmdepcheck is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Author(s): Adam Williamson + + +"""RPM package installability and reverse-dependency checks using a +repository modification strategy (hence 'rm') This module contains +functions and constants shared between the two main scripts. +""" + +import hashlib +import json +import os +import platform +import subprocess +import sys +from functools import partial +from typing import Iterable +from urllib.parse import urlparse + +# type alias for the tuples produced by parse_repoclosure +# can't properly declare this because type statement was only added in +# 3.12, and TypeAlias is deprecated since 3.12 and wasn't in 3.9 +DepTuple = tuple[str, str, str] + +# use a fresh temporary cache for each run to avoid collisions between +# runs and polluting the 'real' cache +# pylint: disable-next=consider-using-with +SUBPCAPTURE = partial(subprocess.run, capture_output=True, text=True, check=False) +SUBPCAPTCHECK = partial(subprocess.run, capture_output=True, text=True, check=True) +SUBPCHECK = partial(subprocess.run, check=True) # pylint: disable=invalid-name +REPOHASHES: dict[str, str] = {} + + +def get_dnf_args(cachedir: str, arch: str) -> list[str]: + """Construct our basic dnf args.""" + return [ + "dnf", + "--setopt", + f"cachedir={cachedir}", + "-q", + "--disablerepo=*", + f"--forcearch={arch}", + ] + + +def check_arch(arg: str) -> str: + """Use host arch if no value passed.""" + if arg: + return arg + return platform.machine() + + +def url_check(arg: str, fileok: bool) -> str: + """Check arg is a file, http or https URL. Automatically converts + local paths to file:// URIs.""" + # If it's an existing local path, convert to file:// URI + if os.path.exists(arg): + if fileok: + return f"file://{os.path.abspath(arg)}" + raise ValueError("Value must be an HTTP or HTTPS URL") + + parsed = urlparse(arg) + schemes = ["http", "https"] + if fileok: + schemes.append("file") + if parsed.scheme in schemes: + return arg + if parsed.scheme: + raise ValueError(f"Unsupported URL scheme {parsed.scheme} in {arg}") + raise ValueError(f"No URL scheme in {arg}") + + +def check_utils(utils: tuple[tuple[str, ...], ...]) -> None: + """Check required utilities are installed.""" + missing = [] + for prog in utils: + try: + subprocess.run(prog, stdout=subprocess.DEVNULL, check=True) + except FileNotFoundError: + missing.append(prog[0]) + if missing: + sys.exit("Please install missing required utilities: " + " ".join(missing)) + + +def get_source_packages(repos: Iterable[str], dnfargs: list[str]) -> set[str]: + """Finds and returns the source package names for all packages in + the repositories specified, as a set. + """ + gspargs = list(dnfargs) + for repo in repos: + gspargs.extend(["--repofrompath", f"{hash_repo(repo)},{repo}"]) + gspargs.extend(["repoquery", "--qf", "%{sourcerpm} "]) + srpms = SUBPCAPTCHECK(gspargs).stdout.split() + return {srpm.rsplit("-", 2)[0] for srpm in srpms} + + +def hash_repo(repo: str) -> str: + """Generate a hash for the repo name, stash it in a dict so we can + map back out later, and return it. This is so we can show the repo + URLs in our final output, as opposed to non-useful made-up repo + names. Not security sensitive. + """ + gothash = hashlib.sha256(repo.encode(encoding="utf-8")).hexdigest()[:8] + REPOHASHES[gothash] = repo + return gothash + + +def parse_repoclosure(rc: str) -> list[DepTuple]: + """Given some `dnf repoclosure` output, parse it into a list of + 3-tuples each containing a package name, a repo URL (or generated + repo name if we can't look up the hash, should only happen in + tests) and an unresolved dependency for that package. + """ + out = [] + pkg = None + for line in rc.splitlines(): + if not line.strip(): + continue + if line.strip().startswith("package:"): + # package, repo + elems = line.split() + pkg = (elems[1], REPOHASHES.get(elems[3], elems[3])) + continue + if line.strip().startswith("unresolved deps (") or line.strip().startswith("Error:"): + continue + # anything else is an unresolved dep + if pkg: + out.append(pkg + (line.strip(),)) + return out + + +def format_rc_errors(errors: list[DepTuple], form: str = "pass") -> None: + """Format and print parse_repoclosure-style tuples for humans to + read. Used for final output after we do some diffing on the lists + of tuples. + """ + pkg = ("", "") + for error in errors: + if error[:2] != pkg: + pkg = error[:2] + if form == "split": + print(f"package: {error[0]} from {error[1].split('/')[-1]}") + elif form == "strip": + print(f"package: {error[0]}") + else: + print(f"package: {error[0]} from {error[1]}") + print(f" {error[2]}") + + +def get_base_repoclosure( + baserepos: Iterable[str], + ncbaserepos: Iterable[str], + nmbaserepos: Iterable[str], + dnfargs: list[str], +) -> str: + """Gets the reference repoclosure text. Base repos, non-checked + base repos and non-modified base repos are available to the + solver, but only the base repos are checked. + """ + cmdargs = dnfargs + ["repoclosure"] + for repo in list(baserepos) + list(nmbaserepos) + list(ncbaserepos): + cmdargs.extend(["--repofrompath", f"{hash_repo(repo)},{repo}"]) + cmdargs.append("--check") + # only check the repos that will be modified + cmdargs.append(",".join([hash_repo(baserepo) for baserepo in baserepos])) + return SUBPCAPTURE(cmdargs).stdout + + +# pylint: disable-next=too-many-arguments,too-many-locals,too-many-positional-arguments +def get_modified_and_new_repoclosure( + baserepos: list[str], + ncbaserepos: list[str], + nmbaserepos: list[str], + newrepo: str, + addrepos: list[str], + removes: Iterable[str], + dnfargs: list[str], +) -> tuple[str, str]: + """Runs repoclosure with new repo included and excludepkgs used + for modified base repos, and returns the modified repoclosure + text. Non-modified base repos, modified base repos and non-checked + base repos after modification, and new repos are available to + the solver; only the base repos are checked in the "modified" + check and only the first new repo is checked in the "new" check. + """ + queryargs = dnfargs + ["repoquery", "--queryformat", "%{source_name},%{full_nevra}\n"] + rcargs = dnfargs + ["repoclosure"] + for mrepo in baserepos + ncbaserepos: + # figure out what to exclude + excludes = [] + args = queryargs + ["--repofrompath", f"{hash_repo(mrepo)},{mrepo}"] + for line in SUBPCAPTURE(args).stdout.splitlines(): + # sname, nevr + elems = line.split(",") + if len(elems) != 2: + continue + if elems[0] in removes: + excludes.append(elems[1]) + # add each modified base repo with excludepkgs set to the + # list we discovered above, in the repoclosure args + rcargs.extend(["--repofrompath", f"{hash_repo(mrepo)},{mrepo}"]) + # there is a theoretical risk we might exceed MAX_ARG_STRLEN + # here, which is usually 131072: + # https://stackoverflow.com/a/29802900/4460661 + # still, 131072 is enough for 2621 50-character NEVRs... + rcargs.extend(["--setopt", f"{hash_repo(mrepo)}.excludepkgs={','.join(excludes)}"]) + + # now add the non-modified base repos and new package repos + for repo in nmbaserepos + [nr for nr in [newrepo] if nr] + addrepos: + rcargs.extend(["--repofrompath", f"{hash_repo(repo)},{repo}"]) + + # finally, add the check arg + rcargs.append("--check") + rcargs.append(",".join([hash_repo(baserepo) for baserepo in baserepos])) + + # get the modified repoclosure + mod = SUBPCAPTURE(rcargs).stdout + new = "" + if newrepo: + rcargs[-1] = hash_repo(newrepo) + # get the new repoclosure + new = SUBPCAPTURE(rcargs).stdout + return (mod, new) + + +def handle_preexisting(fixederrors: list[DepTuple], newrc: list[DepTuple]) -> list[DepTuple]: + """Catch cases where an error 'moved' from baserc to newrc - a + package in the set under test previously had a dependency issue, + and the new build does not fix it. We should not report this as a + fixed issue in the old repo and a new issue in the repo under + test. Note this modifies the passed lists in-place. See: + https://forge.fedoraproject.org/quality/rmdepcheck/issues/17 + """ + preexisting = [] + if fixederrors and newrc: + # iterate over copies so we can modify originals on the fly + fecopy = fixederrors.copy() + nrcopy = newrc.copy() + for fixeddep in fecopy: + # see if we can find a broken dep in newrc - the set of + # errors in the repository under test - that exactly + # matches this one, and is for the same package name + newmatch = [ + newdep + for newdep in nrcopy + if newdep[0].rsplit("-", 2)[0] == fixeddep[0].rsplit("-", 2)[0] + and newdep[2] == fixeddep[2] + ] + if len(newmatch) == 1: + # if so, remove the dep from both lists and add it + # to the new return list so we report it correctly + fixederrors.remove(fixeddep) + newrc.remove(newmatch[0]) + preexisting.append(newmatch[0]) + return preexisting + + +# pylint: disable-next=too-many-branches,too-many-arguments,too-many-positional-arguments +def parse_display_exit( + baseraw: str, + modraw: str, + newraw: str, + iut: str, + dojson: bool, + onlyerrors: bool, + splitrepo: bool, +) -> None: + """Take the raw rmdepcheck output strings, parse them, produce + human-readable or JSON output, and exit with an appropriate code. + """ + exitcode = 0 + baserc = parse_repoclosure(baseraw) + modrc = parse_repoclosure(modraw) + newrc = [] + if newraw: + newrc = parse_repoclosure(newraw) + + newerrors = [dep for dep in modrc if dep not in baserc] + fixederrors = [dep for dep in baserc if dep not in modrc] + preexisting = handle_preexisting(fixederrors, newrc) + + # output + if dojson: + jsonout = {} + if newerrors: + if dojson: + jsonout["newerrors"] = [list(err) for err in newerrors] + else: + print(f"Dependencies of other packages that would be BROKEN by {iut}:") + format_rc_errors(newerrors) + exitcode += 1 + if newrc: + if dojson: + jsonout["installability"] = [list(err) for err in newrc] + else: + print("") + print("New dependency problems in the tested packages themselves:") + if splitrepo: + format_rc_errors(newrc, form="split") + else: + format_rc_errors(newrc, form="strip") + exitcode += 2 + if preexisting: + if dojson: + jsonout["installability_preexisting"] = [list(err) for err in preexisting] + else: + print("") + print("Pre-existing dependency problems in the tested packages themselves:") + format_rc_errors(preexisting) + exitcode += 4 + if fixederrors: + if dojson: + jsonout["fixederrors"] = [list(err) for err in fixederrors] + elif not onlyerrors: + print("") + print(f"Dependencies of other packages that would be FIXED by {iut}:") + format_rc_errors(fixederrors) + if dojson: + json.dump(jsonout, sys.stdout, indent=4) + sys.stdout.write("\n") + + sys.exit(exitcode) + + +# vim: set textwidth=100 ts=8 et sw=4: diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..df26b1c --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,52 @@ +# Copyright Red Hat +# +# This file is part of rmdepcheck. +# +# rmdepcheck is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Author: Adam Williamson + +"""Test configuration and fixtures.""" + +import os +import subprocess +import time +from urllib.error import URLError, HTTPError +from urllib.request import urlopen + +import pytest + + +@pytest.yield_fixture(scope="session") +def http(request): # pylint: disable=unused-argument + """Run a SimpleHTTPServer that sits in front of our mock ELN + compose. We just do this with subprocess as we need it to run + parallel to the tests and this is really the easiest way. Note + we also stash override.conf in the compose dir, it's just + convenient that way. + """ + root = os.path.join(os.path.dirname(os.path.realpath(__file__)), "testdata", "repos", "eln") + args = ("python3", "-m", "http.server", "5001") + proc = subprocess.Popen(args, cwd=root) # pylint: disable=consider-using-with + # block until the server is actually running + resp = None + while not resp: + try: + resp = urlopen("http://localhost:5001/BaseOS") # pylint: disable=consider-using-with + except (ValueError, URLError, HTTPError): + time.sleep(0.1) + yield + + # teardown + proc.kill() diff --git a/tests/test_rmdepcheck.py b/tests/test_rmdepcheck.py index 0a0906e..b2ab741 100644 --- a/tests/test_rmdepcheck.py +++ b/tests/test_rmdepcheck.py @@ -23,296 +23,414 @@ """Tests for rmdepcheck.""" import os +import pathlib import sys +import tempfile from unittest import mock +from rmdepcheck.shared import ( + get_dnf_args, + check_arch, + url_check, + check_utils, + get_source_packages, + hash_repo, + parse_repoclosure, + format_rc_errors, + get_base_repoclosure, + get_modified_and_new_repoclosure, + handle_preexisting, +) +from rmdepcheck import repos, compose + import pytest -import rmdepcheck HERE = os.path.abspath(os.path.dirname(__file__)) TESTDATA = f"{HERE}/testdata" REPOS = f"{TESTDATA}/repos" -def test_parse_repoclosure(): - with open(f"{TESTDATA}/test_parse_repoclosure.txt", "r", encoding="utf-8") as fh: - rctext = fh.read() - assert rmdepcheck.parse_repoclosure(rctext) == [ - ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python(abi) = 3.13"), - ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python3.13dist(wxpython) >= 4"), - ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python3.13dist(xnat) >= 0.3.3"), - ("python3-x3dh-1.0.4-3.fc43.noarch", "baserepo1", "python3.14dist(pydantic) >= 1.7.4"), - ] +class TestShared: + """Unit tests for things from rmdepcheck.shared.""" + + def test_parse_repoclosure(self): + with open(f"{TESTDATA}/test_parse_repoclosure.txt", "r", encoding="utf-8") as fh: + rctext = fh.read() + assert parse_repoclosure(rctext) == [ + ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python(abi) = 3.13"), + ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python3.13dist(wxpython) >= 4"), + ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python3.13dist(xnat) >= 0.3.3"), + ("python3-x3dh-1.0.4-3.fc43.noarch", "baserepo1", "python3.14dist(pydantic) >= 1.7.4"), + ] + + def test_format_rc_errors(self, capsys): + errs = [ + ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python(abi) = 3.13"), + ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python3.13dist(wxpython) >= 4"), + ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python3.13dist(xnat) >= 0.3.3"), + ("python3-x3dh-1.0.4-3.fc43.noarch", "baserepo1", "python3.14dist(pydantic) >= 1.7.4"), + ] + format_rc_errors(errs) + captured = capsys.readouterr() + with open(f"{TESTDATA}/test_format_rc_errors.txt", "r", encoding="utf-8") as fh: + exptext = fh.read() + assert captured.out == exptext + + def test_get_base_repoclosure(self): + repo = f"file://{REPOS}/base" + with open(f"{TESTDATA}/test_get_base_repoclosure.txt", "r", encoding="utf-8") as testfh: + expected = testfh.read() + expected = expected.replace("{HASH}", hash_repo(repo)) + with tempfile.TemporaryDirectory(prefix="testrdc", dir="/var/tmp") as dnftemp: + dnfargs = get_dnf_args(dnftemp, "x86_64") + ret = get_base_repoclosure([repo], [], [], dnfargs) + assert ret == expected + + def test_get_modified_and_new_repoclosure(self): + brepo = f"file://{REPOS}/base" + nrepo = f"file://{REPOS}/new" + with open(f"{TESTDATA}/test_get_modified_repoclosure.txt", "r", encoding="utf-8") as testfh: + expectedmod = testfh.read() + expectedmod = expectedmod.replace("{HASH}", hash_repo(brepo)) + with open(f"{TESTDATA}/test_get_new_repoclosure.txt", "r", encoding="utf-8") as testfh: + expectednew = testfh.read() + expectednew = expectednew.replace("{HASH}", hash_repo(nrepo)) + with tempfile.TemporaryDirectory(prefix="testrdc", dir="/var/tmp") as dnftemp: + dnfargs = get_dnf_args(dnftemp, "x86_64") + ret = get_modified_and_new_repoclosure( + [brepo], [], [], nrepo, [], ["aaa", "ccc", "eee", "fff", "ggg"], dnfargs + ) + assert ret == (expectedmod, expectednew) + + def test_get_modified_and_new_repoclosure_commasafe(self): + """Check we survive repoquery output lines that are, precisely, + a string from 'removes'. This is a pretty unlikely scenario, but + hey. Any other line with no commas is actually safe because it + will fail the `if elems[0] in removes` check. + """ + qamock = mock.Mock() + qamock.stdout = "ccc\nbbb,bbb-0:1.0-1.x86_64\nccc,ccc-0:1.0-1.x86_64" + rcmock = mock.Mock() + rcmock.stdout = "" + with mock.patch("rmdepcheck.shared.SUBPCAPTURE", side_effect=[qamock, rcmock]): + with tempfile.TemporaryDirectory(prefix="testrdc", dir="/var/tmp") as dnftemp: + dnfargs = get_dnf_args(dnftemp, "x86_64") + # this shouldn't raise an exception + get_modified_and_new_repoclosure( + ["file:///foo/bar"], [], [], "", [], ["ccc"], dnfargs + ) + + def test_get_source_packages(self): + with tempfile.TemporaryDirectory(prefix="testrdc", dir="/var/tmp") as dnftemp: + dnfargs = get_dnf_args(dnftemp, "x86_64") + sources = get_source_packages([f"file://{REPOS}/new"], dnfargs) + assert sources == {"111", "222", "aaa", "ccc", "eee", "fff", "ggg"} + + def test_handle_preexisting(self): + fixederrors = [ + ("libreoffice-langpack-lv-1:26.2.2.1-0.1.eln155.x86_64", "ogrepo", "mythes-lv"), + ("libreoffice-langpack-nb-1:26.2.2.1-0.1.eln155.x86_64", "ogrepo", "mythes-nb"), + ("libreoffice-langpack-nn-1:26.2.2.1-0.1.eln155.x86_64", "ogrepo", "mythes-nn"), + ("someotherpackage-1.0-1.eln155.x86_64", "newrepo", "someotherdep"), + ] + newrc = [ + ("libreoffice-langpack-lv-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-lv"), + ("libreoffice-langpack-nb-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-nb"), + ("libreoffice-langpack-nn-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-nn"), + ("libreoffice-langpack-nn-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "foo"), + ("someotherpackage-1.0-1.eln155.x86_64", "newrepo", "mythes-lv"), + ] + # this should null out the 'matching' errors (the first three in + # each list), but leave the 'non-matching' ones (the others) + ret = handle_preexisting(fixederrors, newrc) + assert fixederrors == [ + ("someotherpackage-1.0-1.eln155.x86_64", "newrepo", "someotherdep"), + ] + assert newrc == [ + ("libreoffice-langpack-nn-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "foo"), + ("someotherpackage-1.0-1.eln155.x86_64", "newrepo", "mythes-lv"), + ] + # we should return the errors dropped from 'newrc' (so these can + # be reported separately) + assert ret == [ + ("libreoffice-langpack-lv-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-lv"), + ("libreoffice-langpack-nb-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-nb"), + ("libreoffice-langpack-nn-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-nn"), + ] + + def test_url_check(self): + url_check("file:///foo/bar", fileok=True) + with pytest.raises(ValueError): + url_check("file:///foo/bar", fileok=False) + url_check("https://www.some.where", fileok=True) + url_check("http://some.where.insecure", fileok=True) + # Test automatic conversion of existing local paths to file:// URIs + result = url_check(REPOS, fileok=True) + assert result == f"file://{REPOS}" + with pytest.raises(ValueError): + url_check(REPOS, fileok=False) + # Test with relative path that exists + result = url_check("tests", fileok=True) + assert result.startswith("file://") + assert result.endswith("/tests") + with pytest.raises(ValueError): + url_check("ftp://1997.called", fileok=True) + # Non-existent paths without scheme should still raise ValueError + with pytest.raises(ValueError): + url_check("whatisthis", fileok=True) + + @mock.patch("platform.machine", return_value="foobar") + def test_check_arch(self, _): + assert check_arch("x86_64") == "x86_64" + assert check_arch("") == "foobar" + + @mock.patch("subprocess.run", autospec=True) + def test_check_utils(self, mock_run): + check_utils((("dnf", "--version"),)) + mock_run.side_effect = FileNotFoundError + with pytest.raises(SystemExit) as excinfo: + check_utils((("dnf", "--version"),)) + assert excinfo.value.code == "Please install missing required utilities: dnf" -def test_format_rc_errors(capsys): - errs = [ - ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python(abi) = 3.13"), - ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python3.13dist(wxpython) >= 4"), - ("python3-wxnatpy-0.4.0-13.fc42.noarch", "baserepo0", "python3.13dist(xnat) >= 0.3.3"), - ("python3-x3dh-1.0.4-3.fc43.noarch", "baserepo1", "python3.14dist(pydantic) >= 1.7.4"), - ] - rmdepcheck.format_rc_errors(errs) - captured = capsys.readouterr() - with open(f"{TESTDATA}/test_format_rc_errors.txt", "r", encoding="utf-8") as fh: - exptext = fh.read() - assert captured.out == exptext +class TestRepos: + """Unit tests for things in rmdepcheck.repos.""" + + def test_comma_url(self): + assert repos.comma_url("https://www.some.where") == ["https://www.some.where"] + assert repos.comma_url("https://www.some.where,file:///foo/bar") == [ + "https://www.some.where", + "file:///foo/bar", + ] + with pytest.raises(ValueError): + repos.comma_url("https://www.some.where,ftp://1997.called") + with pytest.raises(ValueError): + repos.comma_url("ftp://1997.called") + with pytest.raises(ValueError): + repos.comma_url("https://www.some.where,whatisthis") + + def test_comma_list(self): + assert repos.comma_list("foo,bar") == ["foo", "bar"] + assert repos.comma_list("") == [] + + @mock.patch("rmdepcheck.repos.check_utils", side_effect=KeyboardInterrupt) + def test_ctrl_c(self, _, capsys): + with pytest.raises(SystemExit) as excinfo: + repos.main() + assert excinfo.value.code == 1 + captured = capsys.readouterr() + assert captured.err == "Interrupted, exiting...\n" -def test_get_base_repoclosure(): - repo = f"file://{REPOS}/base" - with open(f"{TESTDATA}/test_get_base_repoclosure.txt", "r", encoding="utf-8") as testfh: - expected = testfh.read() - expected = expected.replace("{HASH}", rmdepcheck.hash_repo(repo)) - ret = rmdepcheck.get_base_repoclosure([repo], [], []) - assert ret == expected +class TestCompose: + "Unit tests for things in rmdepcheck.compose." "" + + def test_split_put_error(self): + with pytest.raises(ValueError) as err: + compose.split_put( + pathlib.Path("/non/existent/place"), + pathlib.Path("/whatever"), + {"foo": "bar"}, + "x86_64", + ) + assert str(err.value) == "split_put: invalid put value /non/existent/place" + + def test_get_variant_repos_arch(self): + fakeci = { + "payload": { + "variants": { + "BaseOS": { + "id": "BaseOS", + "paths": { + "repository": { + "someotherarch": "somepath", + } + }, + } + } + } + } + # should not crash + assert not compose.get_variant_repos("somecompose", fakeci, "somearch") + + def test_pungi_config_url(self): + fakeci = { + "payload": { + "release": { + "version": "eln", + "short": "Fedora", + } + } + } + ret = compose.pungi_config_url(fakeci) + assert ret == ( + "https://forge.fedoraproject.org" + "/releng/pungi-fedora/raw/branch/eln/fedora/override.conf" + ) + fakeci["payload"]["release"]["short"] = "CentOS" + fakeci["payload"]["release"]["version"] = "10.1" + with pytest.raises(ValueError) as err: + compose.pungi_config_url(fakeci) + assert str(err.value) == "Don't know Pungi config URL for CentOS 10.1" + + def test_get_val_not_found(self): + fakeci = { + "payload": { + "release": { + "version": "eln", + "short": "Fedora", + } + } + } + fakesess = mock.MagicMock() + fakesess.get.return_value.text = "nope, not in here" + with pytest.raises(ValueError) as err: + compose.get_val(fakeci, fakesess) + assert str(err.value) == ( + "Could not find variant_as_lookaside in configuration at https://" + "forge.fedoraproject.org/releng/pungi-fedora/raw/branch/eln/fedora/override.conf" + ) + + @mock.patch("rmdepcheck.compose.check_utils", side_effect=KeyboardInterrupt) + def test_ctrl_c(self, _, capsys): + with pytest.raises(SystemExit) as excinfo: + compose.main() + assert excinfo.value.code == 1 + captured = capsys.readouterr() + assert captured.err == "Interrupted, exiting...\n" -def test_get_modified_and_new_repoclosure(): - brepo = f"file://{REPOS}/base" - nrepo = f"file://{REPOS}/new" - with open(f"{TESTDATA}/test_get_modified_repoclosure.txt", "r", encoding="utf-8") as testfh: - expectedmod = testfh.read() - expectedmod = expectedmod.replace("{HASH}", rmdepcheck.hash_repo(brepo)) - with open(f"{TESTDATA}/test_get_new_repoclosure.txt", "r", encoding="utf-8") as testfh: - expectednew = testfh.read() - expectednew = expectednew.replace("{HASH}", rmdepcheck.hash_repo(nrepo)) - ret = rmdepcheck.get_modified_and_new_repoclosure( - [brepo], [], [], [nrepo], ["aaa", "ccc", "eee", "fff", "ggg"] +class TestE2E: + """End-to-end functional tests for rmdepcheck and compose.""" + + def test_e2e_null(self, capsys): + """End-to-end test using an empty repository, to test what happens + when no changes are found. + """ + sys.argv = ["repos.py", f"file://{REPOS}/base", f"file://{REPOS}/empty"] + with pytest.raises(SystemExit) as excinfo: + repos.main() + assert excinfo.value.code == 0 + captured = capsys.readouterr() + assert captured.out == "" + + @pytest.mark.parametrize("output", ("human", "json", "onlyerrors")) + def test_e2e_devel(self, output, capsys): + """End-to-end test similar to a Rawhide or Branched case, with + a single modified base repo and a single check repo. Also tests + JSON output. + """ + sys.argv = ["repos.py", f"file://{REPOS}/base", f"file://{REPOS}/new"] + if output == "json": + sys.argv.insert(1, "--json") + if output == "onlyerrors": + sys.argv.insert(1, "--onlyerrors") + with pytest.raises(SystemExit) as excinfo: + repos.main() + assert excinfo.value.code == 3 + captured = capsys.readouterr() + if output == "human": + fname = "test_e2e_devel.txt" + elif output == "onlyerrors": + fname = "test_e2e_devel_onlyerrors.txt" + else: + fname = "test_e2e_devel_json.txt" + with open(f"{TESTDATA}/{fname}", "r", encoding="utf-8") as fh: + exptext = fh.read() + exptext = exptext.replace("{REPOS}", REPOS) + assert captured.out == exptext + + def test_e2e_updates(self, capsys): + """End-to-end test similar to a stable Fedora release, with one + non-modified 'frozen' base repo and one modified updates repo. + """ + sys.argv = [ + "repos.py", + "--nmbaserepos", + f"file://{REPOS}/base", + f"file://{REPOS}/updates", + f"file://{REPOS}/new", + ] + with pytest.raises(SystemExit) as excinfo: + repos.main() + assert excinfo.value.code == 3 + captured = capsys.readouterr() + with open(f"{TESTDATA}/test_e2e_updates.txt", "r", encoding="utf-8") as fh: + exptext = fh.read() + exptext = exptext.replace("{REPOS}", REPOS) + assert captured.out == exptext + + @mock.patch( + "rmdepcheck.compose.pungi_config_url", + autospec=True, + return_value="http://localhost:5001/override.conf", ) - assert ret == (expectedmod, expectednew) + def test_e2e_eln(self, _, capsys, http): # pylint: disable=unused-argument + """End-to-end test of the EL mode. This also exercises the non- + checked repository feature. The setup mimics "real" EL, more or + less. There are BaseOS, CRB, Extras and Buildroot repos. BaseOS + contains epa and epb. Extras contains epc. CRB contains epd and + epe. Buildroot contains epf. epe and epf both require epa = 1.0. + The "update" contains epa 2.0, an epb that requires epc, and an + epd that requires epa. + + This sets us several expectations. The update breaks both epe and + epf, but we should only see a report about epe, since epf is in + the buildroot and so should be ignored. epb requiring epc is + wrong because BaseOS cannot require packages in Extras; this + should be reported. It should only be reported *once*, though, + when we're checking BaseOS, even though the BaseOS repos will be + in scope for each run (testing non-checked base repos). epd + requiring epa is fine; no error should be reported. + """ + sys.argv = [ + "compose.py", + "--arch", + "x86_64", + "http://localhost:5001", + f"{REPOS}/elnnew", + ] + with pytest.raises(SystemExit) as excinfo: + compose.main() + assert excinfo.value.code == 3 + captured = capsys.readouterr() + with open(f"{TESTDATA}/test_e2e_eln.txt", "r", encoding="utf-8") as fh: + exptext = fh.read() + exptext = exptext.replace("{REPOS}", REPOS) + assert captured.out == exptext + + def test_e2e_removes(self, capsys): + """End-to-end test of the alternate --removes mode.""" + sys.argv = ["repos.py", "--removes", f"file://{REPOS}/base", "aaa,eee"] + with pytest.raises(SystemExit) as excinfo: + repos.main() + assert excinfo.value.code == 1 + captured = capsys.readouterr() + with open(f"{TESTDATA}/test_e2e_removes.txt", "r", encoding="utf-8") as fh: + exptext = fh.read() + exptext = exptext.replace("{REPOS}", REPOS) + assert captured.out == exptext + + @pytest.mark.parametrize("output", ("human", "json")) + def test_e2e_unfixed(self, output, capsys): + """End-to-end test where the new repository contains a package + with an unfixed pre-existing dependency issue. + """ + sys.argv = ["repos.py", f"file://{REPOS}/base", f"file://{REPOS}/unfixed"] + if output == "json": + sys.argv.insert(1, "--json") + with pytest.raises(SystemExit) as excinfo: + repos.main() + assert excinfo.value.code == 4 + captured = capsys.readouterr() + if output == "human": + fname = "test_e2e_unfixed.txt" + else: + fname = "test_e2e_unfixed_json.txt" + with open(f"{TESTDATA}/{fname}", "r", encoding="utf-8") as fh: + exptext = fh.read() + exptext = exptext.replace("{REPOS}", REPOS) + assert captured.out == exptext -def test_get_modified_and_new_repoclosure_commasafe(): - """Check we survive repoquery output lines that are, precisely, - a string from 'removes'. This is a pretty unlikely scenario, but - hey. Any other line with no commas is actually safe because it - will fail the `if elems[0] in removes` check. - """ - qamock = mock.Mock() - qamock.stdout = "ccc\nbbb,bbb-0:1.0-1.x86_64\nccc,ccc-0:1.0-1.x86_64" - rcmock = mock.Mock() - rcmock.stdout = "" - with mock.patch("rmdepcheck.SUBPCAPTURE", side_effect=[qamock, rcmock]): - # this shouldn't raise an exception - rmdepcheck.get_modified_and_new_repoclosure(["file:///foo/bar"], [], [], [], ["ccc"]) - - -def test_get_source_packages(): - sources = rmdepcheck.get_source_packages([f"file://{REPOS}/new"]) - assert sources == {"111", "222", "aaa", "ccc", "eee", "fff", "ggg"} - - -def test_handle_preexisting(): - fixederrors = [ - ("libreoffice-langpack-lv-1:26.2.2.1-0.1.eln155.x86_64", "ogrepo", "mythes-lv"), - ("libreoffice-langpack-nb-1:26.2.2.1-0.1.eln155.x86_64", "ogrepo", "mythes-nb"), - ("libreoffice-langpack-nn-1:26.2.2.1-0.1.eln155.x86_64", "ogrepo", "mythes-nn"), - ("someotherpackage-1.0-1.eln155.x86_64", "newrepo", "someotherdep"), - ] - newrc = [ - ("libreoffice-langpack-lv-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-lv"), - ("libreoffice-langpack-nb-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-nb"), - ("libreoffice-langpack-nn-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-nn"), - ("libreoffice-langpack-nn-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "foo"), - ("someotherpackage-1.0-1.eln155.x86_64", "newrepo", "mythes-lv"), - ] - # this should null out the 'matching' errors (the first three in - # each list), but leave the 'non-matching' ones (the others) - ret = rmdepcheck.handle_preexisting(fixederrors, newrc) - assert fixederrors == [ - ("someotherpackage-1.0-1.eln155.x86_64", "newrepo", "someotherdep"), - ] - assert newrc == [ - ("libreoffice-langpack-nn-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "foo"), - ("someotherpackage-1.0-1.eln155.x86_64", "newrepo", "mythes-lv"), - ] - # we should return the errors dropped from 'newrc' (so these can - # be reported separately) - assert ret == [ - ("libreoffice-langpack-lv-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-lv"), - ("libreoffice-langpack-nb-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-nb"), - ("libreoffice-langpack-nn-1:26.2.2.2-0.1.eln155.x86_64", "newrepo", "mythes-nn"), - ] - - -def test_url_check(): - rmdepcheck.url_check("file:///foo/bar") - rmdepcheck.url_check("https://www.some.where") - rmdepcheck.url_check("http://some.where.insecure") - # Test automatic conversion of existing local paths to file:// URIs - result = rmdepcheck.url_check(REPOS) - assert result == f"file://{REPOS}" - # Test with relative path that exists - result = rmdepcheck.url_check("tests") - assert result.startswith("file://") - assert result.endswith("/tests") - with pytest.raises(ValueError): - rmdepcheck.url_check("ftp://1997.called") - # Non-existent paths without scheme should still raise ValueError - with pytest.raises(ValueError): - rmdepcheck.url_check("whatisthis") - - -def test_comma_url(): - assert rmdepcheck.comma_url("https://www.some.where") == ["https://www.some.where"] - assert rmdepcheck.comma_url("https://www.some.where,file:///foo/bar") == [ - "https://www.some.where", - "file:///foo/bar", - ] - with pytest.raises(ValueError): - rmdepcheck.comma_url("https://www.some.where,ftp://1997.called") - with pytest.raises(ValueError): - rmdepcheck.comma_url("ftp://1997.called") - with pytest.raises(ValueError): - rmdepcheck.comma_url("https://www.some.where,whatisthis") - - -def test_comma_list(): - assert rmdepcheck.comma_list("foo,bar") == ["foo", "bar"] - assert rmdepcheck.comma_list("") == [] - - -@mock.patch("platform.machine", return_value="foobar") -def test_check_arch(_): - assert rmdepcheck.check_arch("x86_64") == "x86_64" - assert rmdepcheck.check_arch("") == "foobar" - - -@mock.patch("subprocess.run", autospec=True) -def test_check_dnf(mock_run): - rmdepcheck.check_dnf() - mock_run.side_effect = FileNotFoundError - with pytest.raises(SystemExit) as excinfo: - rmdepcheck.check_dnf() - assert excinfo.value.code == "Please install missing required utilities: dnf" - - -@mock.patch("rmdepcheck.check_dnf", side_effect=KeyboardInterrupt) -def test_ctrl_c(_, capsys): - with pytest.raises(SystemExit) as excinfo: - rmdepcheck.main() - assert excinfo.value.code == 1 - captured = capsys.readouterr() - assert captured.err == "Interrupted, exiting...\n" - - -def test_e2e_null(capsys): - """End-to-end test using an empty repository, to test what happens - when no changes are found. - """ - sys.argv = ["rmdepcheck.py", f"file://{REPOS}/base", f"file://{REPOS}/empty"] - with pytest.raises(SystemExit) as excinfo: - rmdepcheck.main() - assert excinfo.value.code == 0 - captured = capsys.readouterr() - assert captured.out == "" - - -@pytest.mark.parametrize("output", ("human", "json", "onlyerrors")) -def test_e2e_devel(output, capsys): - """End-to-end test similar to a Rawhide or Branched case, with - a single modified base repo and a single check repo. Also tests - JSON output. - """ - sys.argv = ["rmdepcheck.py", f"file://{REPOS}/base", f"file://{REPOS}/new"] - if output == "json": - sys.argv.insert(1, "--json") - if output == "onlyerrors": - sys.argv.insert(1, "--onlyerrors") - with pytest.raises(SystemExit) as excinfo: - rmdepcheck.main() - assert excinfo.value.code == 3 - captured = capsys.readouterr() - if output == "human": - fname = "test_e2e_devel.txt" - elif output == "onlyerrors": - fname = "test_e2e_devel_onlyerrors.txt" - else: - fname = "test_e2e_devel_json.txt" - with open(f"{TESTDATA}/{fname}", "r", encoding="utf-8") as fh: - exptext = fh.read() - exptext = exptext.replace("{REPOS}", REPOS) - assert captured.out == exptext - - -def test_e2e_updates(capsys): - """End-to-end test similar to a stable Fedora release, with one - non-modified 'frozen' base repo and one modified updates repo. - """ - sys.argv = [ - "rmdepcheck.py", - "--nmbaserepos", - f"file://{REPOS}/base", - f"file://{REPOS}/updates", - f"file://{REPOS}/new", - ] - with pytest.raises(SystemExit) as excinfo: - rmdepcheck.main() - assert excinfo.value.code == 3 - captured = capsys.readouterr() - with open(f"{TESTDATA}/test_e2e_updates.txt", "r", encoding="utf-8") as fh: - exptext = fh.read() - exptext = exptext.replace("{REPOS}", REPOS) - assert captured.out == exptext - - -def test_e2e_unchecked(capsys): - """End-to-end test with a smaller repo as the base repo and a - larger buildroot repo as a non-checked base repo. The new repo - contains a package that breaks the deps of one package in the base - repo and one package in the non-checked base repo, and itself - requires a package from the non-checked base repo. We expect to - see a failure for the broken base repo package, but no failure for - the broken non-checked base repo package or the new package itself. - """ - sys.argv = [ - "rmdepcheck.py", - "--ncbaserepos", - f"file://{REPOS}/elnroot", - f"file://{REPOS}/elnbase", - f"file://{REPOS}/elnnew", - ] - with pytest.raises(SystemExit) as excinfo: - rmdepcheck.main() - assert excinfo.value.code == 1 - captured = capsys.readouterr() - with open(f"{TESTDATA}/test_e2e_eln.txt", "r", encoding="utf-8") as fh: - exptext = fh.read() - exptext = exptext.replace("{REPOS}", REPOS) - assert captured.out == exptext - - -def test_e2e_removes(capsys): - """End-to-end test of the alternate --removes mode.""" - sys.argv = ["rmdepcheck.py", "--removes", f"file://{REPOS}/base", "aaa,eee"] - with pytest.raises(SystemExit) as excinfo: - rmdepcheck.main() - assert excinfo.value.code == 1 - captured = capsys.readouterr() - with open(f"{TESTDATA}/test_e2e_removes.txt", "r", encoding="utf-8") as fh: - exptext = fh.read() - exptext = exptext.replace("{REPOS}", REPOS) - assert captured.out == exptext - - -@pytest.mark.parametrize("output", ("human", "json")) -def test_e2e_unfixed(output, capsys): - """End-to-end test where the new repository contains a package - with an unfixed pre-existing dependency issue. - """ - sys.argv = ["rmdepcheck.py", f"file://{REPOS}/base", f"file://{REPOS}/unfixed"] - if output == "json": - sys.argv.insert(1, "--json") - with pytest.raises(SystemExit) as excinfo: - rmdepcheck.main() - assert excinfo.value.code == 4 - captured = capsys.readouterr() - if output == "human": - fname = "test_e2e_unfixed.txt" - else: - fname = "test_e2e_unfixed_json.txt" - with open(f"{TESTDATA}/{fname}", "r", encoding="utf-8") as fh: - exptext = fh.read() - exptext = exptext.replace("{REPOS}", REPOS) - assert captured.out == exptext +# vim: set textwidth=100 ts=8 et sw=4: diff --git a/tests/testdata/repos/base/aaa-1.0-1.x86_64.rpm b/tests/testdata/repos/base/aaa-1.0-1.x86_64.rpm index 4e10148d9e6a9b69b6bdde026a2cd56e5b9ee6bd..b812f3d00c5509fd001c9a1f4a842e9b60644ad9 100644 GIT binary patch delta 183 zcmdmKxYKaL!+JwYvn0zzW1~cKbBkm{3zM{DOG`^rHNhfeC%#dkZbDY>|R6|ok3loDx3)AF8qm)z&bB5GZ z(<-Z1a9mO(ubwxnIkgf6d_8!Meh9*H1^m$v?!;0stc|I)?xN delta 185 zcmX?Vc+_yhgL>1%WXmLrltgn&0|T?9c>t14~1rM6=|iq!b2I z1CumEOUu+`(-cz!1Ir}SL=$5pQ$rKOBvS*Eq@*M>gQS!cV?#^x#1vBtBSS+A3sbXH zWAmg`lSDI9W8*Xi5Mb9;U=*HyL*~Y-ty4VhI)WcDKG~eW_(6yz^HbH~%^@NwjO^wn lmKGLWOFmK{qcjUc3j;%Q6H8Nr6bl1mGs{F{GfUI7#FV6D%QRy%OA9k|6HDX7 zGz)W6!=%(CL!)E{5MWnS$iMN0WmZ&NZiLN;7h9(?+H6i>{2;`V#VY)0bBIU;BfEvU lp}Cov+2+lnnoI)cZ03AA@B8k_wN>_$Z&@%@O@1SO763szJVO8g delta 185 zcmWl`p>6^}5CBk)l3*KBg03Wp?(EL&?feIVI`+7k1QeKx8WO&M1c}0d!JI-h

R& z#S(&S(xwvC@ZJt~Fh5VprIHbAU}VujYMp@yqAVc-s;4}oK}vbWvd@4Z3Tsdk4OnYX zTx3NcipoT23_C&+@rdFqu_sZm#cEWN!CR_`EAsOfA3|{ ked;Ck6gdRoqG-0OkGE6#_WCgy&DWjH&tZ01e7C;-0W#k`;Q#;t diff --git a/tests/testdata/repos/base/ddd-1.0-1.x86_64.rpm b/tests/testdata/repos/base/ddd-1.0-1.x86_64.rpm index 7b8001d262e4378ed35df24168814738e73a557d..62558380c451aea9b3a840632195ecebac72cfed 100644 GIT binary patch delta 185 zcmX?Vc+_yhgL*S_V>5Fz%Oqn1Gc#jDb0d=!!xTf4WJA-mWTRxuRKwInLkk0Ab3+Dm z14GNyh9JRaz-)}5qv$T_Z7zrF*IzpLu*cT6`x^JFaeQjlC+F#^ k8nw$f!JLXhQ}zDPsini`?&t6K%lu8C@xOmsEq@+&H^81i=l}o! diff --git a/tests/testdata/repos/base/eee-1.0-1.x86_64.rpm b/tests/testdata/repos/base/eee-1.0-1.x86_64.rpm index 9dc4d3e88fb5aa0b3c042102063f9f54823769da..40a3a8a70d84710bcd4f1a9b4b1e33d1129ddff9 100644 GIT binary patch delta 185 zcmdmKxYKaLgL)H7izJg2!$c#aWE1m5W3wbfBgKG{Y2w#1z96 zV@m_WvjgS148q*OyQ3yU;UV>63n!z2b% zqokB%^VHNNBLiboLknZW#5BWXW79MP^Q1%r1M|dGO9RUk1Iv_D12aqGGz0V06eH6V zv*a`*a}z`Jv}AJz5MWn)=ltYo@792C_akrSJ{4HRsIobM@q-Xc=BKK|n?pn*7}?ED lEG;YyEjMo#)npRbYaGFB^L|_6%&Y|4Wa)qJC%+Lt3jpy7J<0$8 diff --git a/tests/testdata/repos/base/fff-1.0-1.x86_64.rpm b/tests/testdata/repos/base/fff-1.0-1.x86_64.rpm index 8820a745f2f132bfd794ffa730d2fa1816d4936b..3be561996c39c201bb3564bdd6f6a4503c2dd485 100644 GIT binary patch delta 185 zcmX?Vc+_yhgL)HV!?dL2v_u0#?@N8y+b{T0hzrGx>-3Spb{(Jr@7~ delta 185 zcmWl`p>6^}5CBk)kesO?1j;v5G`ZQ?o82)ORCO^pZuVvqJPJe5m?lmCq7C9S(4;~3 z9~u;{gfmET?;YU?Z+|QC3`)`ngdQS$=K|&;U^F-_GPZ=JX^9shkr=5ol9fS8!3a5Y z7%YQhkHLzC!YJm-EW`>08C8sm(X<-rbNzZfeJs}X<7W8%Ki(&ynkAQBXMSD&RFi(0 gq|UPUz|~>!)b3{WW&1GQot?gX#;?)&{Wko)18o*RlK=n! diff --git a/tests/testdata/repos/base/ggg-1.0-1.i686.rpm b/tests/testdata/repos/base/ggg-1.0-1.i686.rpm index ce786d62f0c5ccba5fa95bd5ab84ec4234b89853..2bfb68b4b65b1e271e3cf8f90b135a8298ed83a7 100644 GIT binary patch delta 380 zcmXZTKS%>H7zOZm+-Y5e+E&`Z!NIkVTrQUu6>;jUIJgL=mqe6Wgx1C75Cm}%;cyY0 z1n0taauEleiVm)Vg8y()5Jv?m&A0u&_uei&rbkb47||fmEDA)Oher8|1V#|XNu)Vb zQYj$`H-f-t)EMn^>2qp~R5VbkPECbqDRscLsfH}9a;E%9MOvwdRJ7E>XM)s)2^sn~ z{1;FET;9{t$#?C%(>nWd4%1bqmK|LHFb5z5c=Ks@?9PdI062iB`#Zpmt&R1bb;Ek! zy1&Z+?kRvQkWT=3fZG}5`5W8sTE74o0o)7g*Fit${@TaKpx_}X6lT1Qq5N~YR9JR0 z6+uN9iZmVXIl0O5X1mcUt99AXQG0f+xt+wtsodw=qM2CfU2Q$SAC#_}4?vO@Z~p;L CS6Ep9 delta 359 zcmXZUy-EW?6b0b3>|$($#63fc%ZX`+pdjd8KFuo4BW zR(t`)G@_+8f`x*?pb%d`!p`l!d(OQlbe|r*w>7m)6Kc8OQb{7Y6;y{(TFZq>V`F%n zu#~2VG)b%wj2j&rshB2OF%ubPxnY(G&YFf3D=kw|lf*iuQPQMRGG#*{xW;fsddbW0 z#bRS>?ebvmcJJ!V`^(q8h4R=efO!BVAehc?D$ibf1Aqqv>F^Hlx1Fu?j`NoDu5+t+ z;~xSj1Jw*b0QjdxUVU)=Gv^Ngqkwb%7 diff --git a/tests/testdata/repos/base/ggg-1.0-1.x86_64.rpm b/tests/testdata/repos/base/ggg-1.0-1.x86_64.rpm index ea25756c66fac3c1a7c4d0042844cf8598cb8bf9..3c4f65bb3ea0fc794ebf66e4ebf704153268c348 100644 GIT binary patch delta 185 zcmWl`F-`(O6aY|$U}(v*8=x@}Dk^67kAG$kzzr-Yng4fw!5K)XZH$Sr@e&pr3OoaL z9>BN-6cmJpQsa9&vop`%8%}7vNffLna#~6w02C8@YoUrdS++o!T9Jepb!7tSQZNZP zp^7CsP7uXm1Q4{6Jb}I!ZA$b)nu&=q1l#)8y~DSr9IfMGs6KA5kMHVIFV#8gtZw>E k{g5wI*E{17U0oN`c5lCZ`Z>&seEd2;PQHG#m($?$4+fe%fdBvi delta 185 zcmdmKxYKaLgL*@AQ?q1K<76`l5j zggUq>v`7&j|AJy2#NAaXxo7*F^W}7%OXuXh9Y!qREE1GZA($(DHzG2!i3q~j4QNQD zFJh?}BquIYo~<~coYGh-pK&5pz^LOX=`%*7Sa_UD&WRIvirStp0^g1}_W}}PJh}W$ z^W%5)GF-an*B66o!#L_SjCvt204$CJz*_0u&b%4zV*mzVDFBmz+0l-*Pqh>6Gws9d zjd=y20F+Vy7GOSP_tK;82ihY5Q-JxT{gw4aYg#Y9v%o5(_YTrdWxm*4uKf+WNoT{otFNB_tOIGk^7;>t-&G_4 delta 359 zcmXZUu}i~16bA6`NU$zKw3W_+AZ~f-U3v$Ki{Rv@o1n?%f`Wg56r>=Cx+xhIN{4PD zLad9U#YwE2xQK%yE)FhQQIOJm+wZ;ado4Pm!{@q6s!<$^kaHRFAeF*sEwok%Rgyq* zE@g#Bfr&xNL?TwCgb^fyM5m;cQYsPB@CxT4r$EJ#PEFPCH$w75X-F%IWh6Qno#_w#mg)-o&i9Y*;YTku8}0n7m?0PbvlG1_JIEdUH~O}_^?+t#V|j`gPXu61qj z#yJMy0mTe}3pl5Pd-2BR&#hko3Jl$8OsBJ6L6CnbEy{JYP`zpdoWU z)uLBj;Zgg961ys&Od9@hFhDE_01A>)Nh9)(W$1-iB#f0*XJxhfRofR)THONpZ?Z);s@gkyAj_r)zxEGqU{zZJu zAOI*}B$YHE9})2si=-rtg?@kt=izWT^3UGcgV;5Vt}>QWXwulxgtQ8q_sf|2ll^b{ zc*~F_+vAi{>N1(8-#sz%BGq?pbPStgY^9UQvZKXn?O<8C-s=1^(|_mx3sX0}7fq{V z&-B>I(EXSD>v~SaQnW3zQ!4lf^Ac-0vAa7uhp_|&5sAnH@{mVj+%c!MF0a`vnr>pF zGm6U5dvrb1lTNu`rmnd@S;ZV{E&mo47H}WSzp8xIs5we{oUoK-a^x~=o0^PLI%#~f zq}`@5dJ-MaX;kM`TFS93xm>0SqdtXEZx635@-H)9=C{0)+?VxHvOgLcAYh{ud_w{t zlo&W2poq{QGyoGrp(uX?yhcn15K+wW3Mg{`gpuixUE&MMIe>(X@HRtE*kwJvF&i_o H#b%+S&bS}c diff --git a/tests/testdata/repos/base/repodata/6868a9258bc5b257d087b3f926cbdbc014866cac98e1c7047bb0de5c8f4e8b63-other.xml.zst b/tests/testdata/repos/base/repodata/6868a9258bc5b257d087b3f926cbdbc014866cac98e1c7047bb0de5c8f4e8b63-other.xml.zst deleted file mode 100644 index 967e4ec2139c90bcdbf82ebbb5c460b72cdac9cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 710 zcmV;%0y+ICwJ-euVC@wECc2s-K#kgr)*A+VVThDT!}#h%sVhT2K}(yPlKr1ThE*p7 zBBcP80D=Gyw>Ws1$X6;)u^e=mhoeON!dMo7#!1RSv5LbyT!ojz%!hdiPnNS9vLgCt zmY8dOD>E@x{#B2bIknl6`iH!ZsJM#dzxLW0YqbvJ5C=rW!T@L-golxM2SYfHSk8hQ zc5Ys>nD8HXhzTF4n3zB!iv>YM(>x9%F^Nbj7H-%p|7a)-fQG?g0tpNahjC0GPH~f8 z4jRD2OeheE%2O;6NreF;ob9FNoHg5Y&Lw}Ve{-tCh+Zqjtmt+f{nfX0HskOneQ zSOgjeA%;|@E*|C^_T``e8o)(hDQFx45{eu6NQ8td{@^M8P|!pImZu;rlLuwtFcr$9 znc&4iiM(UN0gDuFS}7HKjUldUeoP5pE%%?CHeE#2Qjef1PPE^%T16T8xuAwGgE*a<13M-jb&PF`$v zdrz(8ywFPJl@e2HeU)+z)e#v&Di>PZm=JYy3iUE&T}9mdF|)b*bE$gn-0a)SS4=@1 z4##@Ms#vvlwi0930UanXLmABn5F!DSC_b6||Mx2hfCvpx2k=4{Vgw+D7J>W#HbOXn sDE#9?;Rlcr(j&VxK_LeS+XS@fMW$73Q}Lk{{V7RIv5ASQzvLi(4sUz8fS@~&hzO=>0lfVLV&UXQR?j@rGs&FH}Xt3M@k1o zG0#cX9? zzw_fn`bbN1PTx!4>eyGg#hNcM@lIjkf@pKSmwD11TQQEFLbv`*uP3@ zoF(e&C>&#zc!ou(xBV50j-X~qYO)4Z;wvoBWLGQ;n$%)aP8VZjm3YNs(=$t?xC`Sz z6nAl?bTE#negx+RuD-jakM@-Eoz@8*b&yfEs&$bWl#6jQ_?WF$n`?Y#u6~2o+W-Im z|DXJ#Z2P`sWE`nS`>$Fy+y83cDnE_yttBgqv0A&{&lg*K+|*M4e|L9xcb^c_xA@z2 zx7WEiPU`&2SEG|QYI*shbiziPy>ITCP3vZLN#$eiUTdwjK3Qv>%(;#9AA2&^+K!*s z_L!}cxv~GIF*1AWn5%Tz*X@lpp4GChwJtD`!Jl+DJL zGiw1zN9`RwV>rmGJ=Yp^uu5*RRqFaN+40rcoSX~F_RnQw5?aXaEk@a{RTz0Of7~p7 zQxru}l;;#hnez2N_Ge~q=_K=MWux{jX3_ei?3#6ykxpx2bl!1A);c;TVSN4+MS-wR zZq6*%f-J7slpQZRD_r!+*6p>`)1MimP3g1PpmlF5e_HmeB}tMb$z)K%B}tMN*<$fw zH`s7em(j_V^exEGMaQ7DQ!>9w``I~u80){QjW)B%EbB%slyFIs#9C{uwboX4F$RE= zpg{!=B#~f5L_~t5ASvk3BB2_ZHi{-PK*yDiHb7ldrKJM4G%U4ZK&EBbBDbVt#&nb;okIwW_S57I|+W`<2tfqHTz7viwm|plL&g>|a zacj{eP-k6KN&~~8ik5gnBtAM(kh|$m>Pd(5q6&bZUXg~UywvOD4Bk6M07Uglnh{-; zo89!6dYzuZd8Z11s9tFrp23ta^=6lJcFUWpN4QPzx^bJTl$)R^YPip`eC~)s1+l9^ ze-dZ*kEYE;6 zfP)m-gGJoELbXo|#t*hGW4Om>YSSd~X_xVOJy2X}cKdc_|GDN}hY3zG5#cQEoUl3X rWySOtb>xUlYHn+x^J+Wy*u|5M%(qA<HGo2oY9|zWz63KCzZ{Qz=PIv59{6DMd%(4sUz8fS@~7Fz`SndPyWa zNk!OLftUp(!Mb7%#Z*G!_c}vTOC=QRJf4n}4#x2!gg6@z#a=#AIv58tBhGMhq;x3^)R8`cIdR*-O}%qt3ba zza+GaD~r)epEkDD?QN~qIE*8}iwki!08k4Is05U-;*)ZQn?&J8jYHlGgL5B4!P%lp zbmK|A1)oYpmm?^7((qll-t3BTFwaHU3n9#N-QI-*8An4^I8KB_kfRs}g=k?|BD-kk zDlni$@jL{OXW`t$>Bbq1BY^@0h(nFrMInHB?vYYT2P9(VI?p^8fnW;@!4{ZVCEl-+ z8fS^vI*QkrN;t!!*vst-1xHY`Bt@HxD&Z9tD7Io*)TCsLlF2D0QwdirpPX4D#a$Q& zqPUAArGs%q)+0DKt4+wBQD*($U%f%@j{fRf%=ufC#*Zt;$71ESHU5H)(a7)r-`(Ba z-ML%k_Lebb&BoZi`q|nhp>^8J(&sE~(#baMtna96=+hm09b=^K-re2Z-P6M5>a;U5 z*dY6)3_`dpWvo`p>shi_*>`g{eZg8;bnlB@{rRlBt+m!#YwdfsK3A)>p=<`(Vv)M( z^PR8Qu4(^s4Z6l`cKz0xlWtKqnOXa4tz8J$Ai-T06a3a%Yps&jTG{i~=&I{iW6k*) zdm0Ew+#ES$yvUY=l};MjsV~W1aY>To|NsC0q5`l0f}Qlpjd$ z5maiSzQmaxCFR>(C?7Gfbqch+^hE-+aY$wQ=+{eK&X*40PN85@z9k%AAd$dJo#|0h zj%}hzOrN<$;%}EARH`sI83`Ljl*!$clYUdcds7NR10bfZNW)W3>V0ws?@bW^k$N@F zjxLI3C;dphDL8Mc{s`366fFIvAEwUXy_`}2Vg^)Hr{BazDCIhpD`t);R1muw^doVm zH_6$yH>HaN;HIuzI(=(9>T=sgJQYX>(r843fWjW;msKFu>;?+1!K&2Hb$>_4aGU5qJC0V2Xu+%aJ*-ph*V oFDeiuB&nyZh0d$(++!!6G-kd;HcCGuxeBxRjxnQq9lGES9{TIKRx9=9YK&?c=>qW^0!++pB+5 zx?_@SSJHw>@8CI<5I-umapY*FGgG_UQ8I;$QUwu-$OGb#$1_-w=DK-3;Ey0EZtp8HQpbI?yZhWM(9i>BgR<&>#}yqsH>(VscW zOnJQe+3fOH8$8vilsx&adzPiEO2X<^=G{^~+?D1z9kY*DQ0Z@U66M1Y86Z%jD6|7Z z0w6>Z13{+yL+pl(E`TIb2$639uaW5hL=fhE*p7 zBBTJ80D%Dec#D&ViFl>r6wATGJRT*&7sj#xG>%dSZ54-kyviNaX>^Y41mVLJdA`p7UFHhau(Zc zZ{w21MEih4O!Pp-!~_yqEC?c+=5ZK_NkmeyY_nbQM?+x%Gz?A?NML9)~>$KIZKy!bblV41mUhv5*Eb zQCI{T2eF|dlvWw{{PkpA!;i>-Ddyyv!k`$>WUR+ za)r+6E2^qg-hQl)3#HRl@9x`(7yZlJL{GIH`}aM>)^peRoJ!9jmKbWU@h6vhdGnO2 zRn>L3x3@5HdrfnpwccE=weY!2X1DmuQgMDGPt9>Lr>2cAG`dsdQDF zTdAe0#=K>Ek9;|QEOB~H*mN^eN!{`%MgbfsFhd#b91t1-!zQ0h{{MR`2!M#z07KaQdUsL91vt_oP8=X3 stOFQ@3=kvC0Ysq(uo30}a!kaK@QaieUR>>m@ndvIPp!@vXN%2SqrNm*w*UYD literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/base/repodata/repomd.xml b/tests/testdata/repos/base/repodata/repomd.xml index 9aa144c..5a317c1 100644 --- a/tests/testdata/repos/base/repodata/repomd.xml +++ b/tests/testdata/repos/base/repodata/repomd.xml @@ -1,27 +1,27 @@ - 1777498820 + 1778717667 - 6b696476761c56d8bceb3e8997d31ca6977aaf63901130fe94c708e7d0cf429d - 54c3435b6735114519dd995763d0a654a564872f34118ce620e7148d7488738e - - 1777498820 - 1281 + 725d5a8541dc6ac107257c1ccd264b53cfdfb601e10f1dffe1db40462fcab118 + 577f2cb77ecdf002fbcfc3d3d3d5972e9574d262a0a32068f5b795556d6a1bcf + + 1778717667 + 1278 10594 - 1acaeb6689285db3bfe681d374748eed2bc7cd9c1af87b32a27819f776ecacb6 - 05695974b3212a3e0a658e431c4c6eb1cf20b4346365b9a062c4469e7a85c6a1 - - 1777498820 - 621 + 934bc8a9464d6232eb2e22aea3275da638dd1d733d9af49f402ac5d0072b505c + 863daf657e56f2234c416ab3878b88305619ab38614dee37253281a6f38cd296 + + 1778717667 + 624 1722 - 6868a9258bc5b257d087b3f926cbdbc014866cac98e1c7047bb0de5c8f4e8b63 - 29e4f16b3e7312bdeecc87f41baa5f8200df3793aaab472e131dcc6e010130b8 - - 1777498820 + 9a69e354abcfd9f7de70b62321bab6263e340615e628cbf96518ffe4ab1bc376 + b62ee7d9a3bfa4aed63880cf15f0022c25930473ec0a5004388db138c165b285 + + 1778717667 710 2838 diff --git a/tests/testdata/repos/eln/AppStream/repodata/69a3730a283b85a4b3cff7d04bfde3b2b234f0607ebc17319d7a8d143a8e066e-primary.xml.zst b/tests/testdata/repos/eln/AppStream/repodata/69a3730a283b85a4b3cff7d04bfde3b2b234f0607ebc17319d7a8d143a8e066e-primary.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..ea97e2cc61c3a6eee091e502f6e24abd4327b3c4 GIT binary patch literal 123 zcmV->0EGW2wJ-euV3h*^f=3w|aJLQ+P{T+G)=_B+DggpI6AnvYSxEkW0}g9{+del+ z#L`05WMmVz(P&56Q5x#78#08H#)lK7okel?5HjMwLDlrvi`n0{&z*>Mr~oh^6jUMZ d8f4B!ixW`g&`rq)^LjZ_0}usukciny#2LF)Gx`7k literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/AppStream/repodata/6b37cc67608a24beaa81e1191d218f2ffd6b1191dceb5c100bac2e66249d518d-other.xml.zst b/tests/testdata/repos/eln/AppStream/repodata/6b37cc67608a24beaa81e1191d218f2ffd6b1191dceb5c100bac2e66249d518d-other.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..8cb24b4cfe8d1a63774839f56826c5f68bc62c65 GIT binary patch literal 117 zcmV-*0E+)8wJ-euU}XaULdO^yaJLQ!%6QLS`#~NxF#y8e9myMzEF}NG0SAhoJNkOK zh)`N+l8$h4uwr!ix%u7gY(JjNKFfTp?GBXxrAfZ#7Q@dSeLX~kGE@K{6bzb>#~L2b XjTR@M=|Lu=A53$LfdT;l*c4P0?xZsC literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/AppStream/repodata/9b07d97dc6ececed89aac0650b67bfb292647fe9fbaca48f629465be5f53f82b-filelists.xml.zst b/tests/testdata/repos/eln/AppStream/repodata/9b07d97dc6ececed89aac0650b67bfb292647fe9fbaca48f629465be5f53f82b-filelists.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..45f26d6df65480785986b4f223763712678dab38 GIT binary patch literal 118 zcmV-+0Ez!7wJ-euU~K~cLI)WeaA_UDj`BZ|vEZ9LuNp2V>w;_1!iw-;eJ}yb-?_Ir z(NwH7Qu!)uL0EHA*|Wxeox-+g7uZmQk6U%n{2x;JYZs5db8mB!igly_KqweeDUTb2 Yygg~4K&r>EBQ|l`#Ulj)0N5;46ne`v^Z)<= literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/AppStream/repodata/repomd.xml b/tests/testdata/repos/eln/AppStream/repodata/repomd.xml new file mode 100644 index 0000000..4b6e068 --- /dev/null +++ b/tests/testdata/repos/eln/AppStream/repodata/repomd.xml @@ -0,0 +1,28 @@ + + + 1778717670 + + 69a3730a283b85a4b3cff7d04bfde3b2b234f0607ebc17319d7a8d143a8e066e + e1e2ffd2fb1ee76f87b70750d00ca5677a252b397ab6c2389137a0c33e7b359f + + 1778717670 + 123 + 167 + + + 9b07d97dc6ececed89aac0650b67bfb292647fe9fbaca48f629465be5f53f82b + bf9808b81cb2dbc54b4b8e35adc584ddcaa73bd81f7088d73bf7dbbada961310 + + 1778717670 + 118 + 125 + + + 6b37cc67608a24beaa81e1191d218f2ffd6b1191dceb5c100bac2e66249d518d + e0ed5e0054194df036cf09c1a911e15bf2a4e7f26f2a788b6f47d53e80717ccc + + 1778717670 + 117 + 121 + + diff --git a/tests/testdata/repos/elnbase/epc-1.0-1.x86_64.rpm b/tests/testdata/repos/eln/BaseOS/epa-1.0-1.x86_64.rpm similarity index 90% rename from tests/testdata/repos/elnbase/epc-1.0-1.x86_64.rpm rename to tests/testdata/repos/eln/BaseOS/epa-1.0-1.x86_64.rpm index a1420290ab01a017a0001ae2ad8313b3d08ad1f9..65c0895644c2cf1f03f6ef0fa0e68a9db27b841b 100644 GIT binary patch delta 233 zcmdmKxYLmL?do^8nHfMJwIFdK@8x<6W79M3bzUt2Q2}=Y1GJe{ez_>?< zF>$i2h%rkRtMJpwAtK@8iMob*2D*lN#YM?_MFqJa$Aa+WLn5!(EzAwg&CDz}Zx+>L b5)i8F@p@A*X)WKzBX4-E_LWV3BYqYD1jb5{ delta 233 zcmdmKxYLmL?do^8nHfMJwIF#S@8x>4Buf)>Q%loiQ^Uj*6AM$L)D#N~3qvy#6ALp- z3quo2i)15H(-b2HW5ZMf^JLTHWJ5~>izEYM5X&^x(83@&%`z>`%)mU++|t}6%`nZ> zAl1@1$;jBqEZHE*C@D3`)Xc!#*aU1TyW;ct2|i65w#61*-M-`U6gI~6%?XTqgcy@2 z%ZeDYWPYkTHaSEjTs&FVP|rZuP_MWsS+A%d7vxwFo_t8;6}!2KrG*mDcrGk~aCchCs3joz*OtSz0 diff --git a/tests/testdata/repos/eln/BaseOS/epb-1.0-1.x86_64.rpm b/tests/testdata/repos/eln/BaseOS/epb-1.0-1.x86_64.rpm new file mode 100644 index 0000000000000000000000000000000000000000..922843aa8e6851359f0b3d56e79e9cab5667ddc2 GIT binary patch literal 6329 zcmeI0OK2Tc7{|Zcdz;2qB~rl$3P%*0K+ny*AJSCYq-i7CgeEnuU4%1d&fGh3X3ltK zZj%%jf?c@~i*5v=3w0qrXhBzQx{$hX3v9ytM=ft*IiCgCn_whU5 z_nkTCn-}~qynpeVCP=Y7zWRzO>~r5<`sj_f0N};-J*iczR;^mKYSpS$t5&UA zwQBt@)%QeJS65%FJPo+jH`xZz>H)wLm9NoaDklVhLDj7_pG5j78^tmJlD*u$Km*;N)pm|cUJg<^v zegmKtDSl6}^uJ{M1I5Rx>!B(4Hw3Wt_3HS|ud4Xgvnu~<#XnZ-X?~~pC)Ed}SY9uK z0IkO)k4rxg^tJ{%O!U%p1r@zCC1M5Ux^aQx0udDU$3s?75$9#hvo^ru#;re>oF{?o z5&%rHkPCul1YcydguOFQuOHf#=SfV7tS?4q1P^<(jE~0U3M6sXTZU!NS#YeI_GG&d zv@PV9(C)qMd^Mti2Pj@1WD(@AesVpvIlAxnZ6fw`B>L$`%*K>8( zaW&aidEXCK6{>F9KsZWDK1O;aM>vW|iIb9J9>~TQ2uEz0vi@l*5bhw{5sY#X;tr*_ zSc*&9Wd*`{oHK;yNs=HupK(linkOXA@RHzJ2PY)!AUw~6;9@M|A|)j*810F;TtRp~ z-;NJ1Oimw|o0>elFgtzl!1$i+cw*him|0~`EbM)HYWMh|LkqiRXZIYKo0{G~i*S)M zT8xeM3Nf0*!Kld7QNhA4Db)||5)rbDg_u$u;ixDHeIDn6myDKN;G&cZ{TK6)EaO3( z^`}8Nbu5HaB4~H4x}FeD%U;IDIxJ%%rU*x*SjlKt@Qn8g+{>2YEW{-V64^Gj44ROl zySA8^X9!0$x{cE^DR3B*gwb-WllA0T%Q)s~T;fQOl;NDmS;+*#>DqY0NOXG;XdZJo zR+J&=zPdwj)h67(Yj7v)L3!$3KJ@074?QEUoj-eH>1BD%^vVc(KrD^Ap=D9Svkb@A zN#y%B4Lr-!iQ~Dt6NaW87>4KTzG=J6Ws&V#ex&J|$Ml8y!C4hUQE6;K|POt7GABe8a+xY++5*aRgj*N*f(4s>+lnJND9)4Z;~% zm@r6C*ce%p%eG#(8E&H`CkN~wl&Z3UCJPG8HcE}LE?>X#E4FlBvxA_9cqhr@NGtxh z`+a%+EDd>}Lr!UhQ8dKwdG1+0dA{3wkoO)1+~`x(aA|{Z772;MZT!iu>k`dynoxlm z0aUV$r>=^#CwS=$0+RyJmj!A`5@91IrMX~@B=wQSQXlI!QjcN(pxZV|Ew9%`72)ht z0uE1h?4>D>2P*IIfm$mK@-OZ&kdn0an8&!bG-P@FO!tEeRp9dV|;y&Vn0 yIU1hkWF2V2+16lF5F`r#Ge8A^%_i2{gw3Rkg4fon!}P{y%X(%_Hf1KjW~-uV;-#(t literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/BaseOS/repodata/9daa049560d116a0c3e824db9385975140f68e97a03ae87214197284cbbbfad8-primary.xml.zst b/tests/testdata/repos/eln/BaseOS/repodata/9daa049560d116a0c3e824db9385975140f68e97a03ae87214197284cbbbfad8-primary.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..eaa73f98523522f4a4043ae72f3243c44e9463c9 GIT binary patch literal 676 zcmV;V0$cqkwJ-euVBHh|w(Ec+AZ_%+`tB>}Cw)ZP6(Xz}f%&Lkov9(BdTiT`H8ntp z6&C?^0CoU(0MPU~|HD^XkTfrTf9?r;u7PMC2$W`y&plx;;)ib|_1qJaJR)peB` zAa(1;HBbHYxhL#-#M-I=Msl>a((Jhzmndosor{H}%xtKOb3S$4lul#hL!+gcO@lF` z=%ibu^9%X2ImtLD84p|x1`i9O)ggg>H4G+7+E!X(zBJidRx?*uvj>sWy&GZ`#lng#tt)s2QuwUWM?(>ROsIL@-5pK9c9>z;BI zFz!g>e#@kkvN=!l^pR1UO?%=yi)%#9qBYlWjiot_aa{byobGX=<)Lj^FrxV^kutO~ z>7-4v$6kPI6wLzxSPKRV(vCPqzTQU4BY9J=pVr6Cm@US`Gz+5C`*Mxp7PNER+TTIN ztjJH}OYB*km6`1r<_s8rscW9&yr`Bv>q54eQMdl(#BP;EbgwU2v3}SZc KBS)B>MEEmdenX)E literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/BaseOS/repodata/e9b667b6a1059447627647ab73574fdee0a9c934cc7bfcf739f32edd1afae3d2-filelists.xml.zst b/tests/testdata/repos/eln/BaseOS/repodata/e9b667b6a1059447627647ab73574fdee0a9c934cc7bfcf739f32edd1afae3d2-filelists.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..d1752f7908aceba51c673eaf46e9513f86ef9e6c GIT binary patch literal 279 zcmV+y0qFiHwJ-euV08!pW|KT0U}y9I{Qjdqn1FUlE^a#@kU>B7*%J9DiF9T1pS_H%Y+^B`E0J8Lg*P;a+Ap;@|&?dm?hyYbZS66YB88S7DjJ~h>nli z6{YA=`ep@dF_^V&VSNbtg<7`o(23{OqLjfby8`#7g@=Zs+W7p!Z=$1?JGMF5;f)~D zk9N+n156}Ew0@;?$>-jmoU9#t@sq~NbO>Xtu+mt + + 1778717670 + + 9daa049560d116a0c3e824db9385975140f68e97a03ae87214197284cbbbfad8 + 3da88c933c481526801b2d09467c8e54e4edb8f54bf98422684c243650fdee96 + + 1778717670 + 676 + 2163 + + + e9b667b6a1059447627647ab73574fdee0a9c934cc7bfcf739f32edd1afae3d2 + de153bb5dc84de1eabec3de3762909234945d17228ca42b53cee3aa4b3da63f7 + + 1778717670 + 279 + 445 + + + 73c134c24423339ee3c1b12e215c925e853b58ade283876a72ca7b92fbf246c4 + a1a6a080f1db568019eee61e3b62d74f3dafcb40867b0f2faf218585b7059123 + + 1778717670 + 352 + 665 + + diff --git a/tests/testdata/repos/elnbase/epa-1.0-1.x86_64.rpm b/tests/testdata/repos/eln/Buildroot/epe-1.0-1.x86_64.rpm similarity index 89% rename from tests/testdata/repos/elnbase/epa-1.0-1.x86_64.rpm rename to tests/testdata/repos/eln/Buildroot/epe-1.0-1.x86_64.rpm index 999448a4dc87d46aad9e1f642ade7d5aef669c65..c286d78a8fde148759c0596c955996ecf23a662f 100644 GIT binary patch delta 266 zcmYk0u}i~16o-@6P!S5Eu`asXA>l6Xa_`;W;3O4XP43`~ZjDGMTJ`6x s#V`n#{>xQSf5a~xLWvs1*idOI|L8sbGqZAQO#6;!>?ufN z2jU!ZIQvVh^||&~;@X=9Rf?l7NUe!6?Nk!PEsR;(n&Pou#)%Xhq#GXfGt;3nQoiP% zb?$!_p+4~rp%N1zU%Xa8w0GlCXZ%b`Z+-FOYvCXV{s0692s|?RR*2?TUJ!=I3|%dK ZLE&c_zy$yq%gNfZo?VkonHgZSP*LT^X=DHZ literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/Buildroot/repodata/8d4fa97f0d4d6bdeca349744217b0e9d694aea2cef332765e97c2252c4df6431-primary.xml.zst b/tests/testdata/repos/eln/Buildroot/repodata/8d4fa97f0d4d6bdeca349744217b0e9d694aea2cef332765e97c2252c4df6431-primary.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..08eb50667f383b102f41a311115d35a48c5acf9b GIT binary patch literal 626 zcmV-&0*(DBwJ-euU`-PM)~9wQAdTn&P&Gn)Svk0mnq4#{dJQpm7%q`(`&#IOHwQ>+ zfDkJ#0%`zp0BZo%xiK%SIS<4WQ5*&THRgpiukL(4t1&OGXZ@DERxY>2b<>jd$dkZV zxo7=ZU!W~ICxwh%(HWOqk)d3ctQZrh_fjoctC|#k_r-U8w#5x}q&R4BXenaJNTKE2 z3#MtwqSC%kxSEuK77J@kqGt!WviRyb4_9-<+3aZED^WG2C&Y zN8@oA4G3y5pvfUmj1lxijstq4w}6iYBSIQ6I+{1Vhob>O9A|>h^Ki{z@X%6}5lQ8K z9E?ZVd07c`3bJlms{G$4+>4edNCOcXEuXNKpn%}qS`K9;FzYvF=EdDNpH8zr!!(Ko z(;#7bTe?go0G28tl4X~`=& zu}^uczgTnCUyXTT?Lv>BufXqV^aJ+W+xHn3>q^j>;M1& literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/Buildroot/repodata/f4ecf39d19149d8918b7485eea237aa87723615393e5f15408b577e2114818d7-other.xml.zst b/tests/testdata/repos/eln/Buildroot/repodata/f4ecf39d19149d8918b7485eea237aa87723615393e5f15408b577e2114818d7-other.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..14872e122f7fac3c2b8db9f016eb642a35aaf258 GIT binary patch literal 304 zcmV-00nh#@wJ-euU_A){7L`IFFiYkE%t{CBM@<{Dx72`n;B|)%VtNaXSoptB3L5fK zIXVD305$+l{eIOj`o|+MdSqCgsMZ3kd!?3%N>v&Ab$Y#Yty4S$9Sws7g_cpBsGaq> z-SJvhJ0-4fV5-UnoQe{g1S&|vFbTpye}I%m21aFJV01SdhtNYp>GB-%W=WWXqCgYE zrX`&sgvCzr^lO>;$Pv>m?&dePfU9H?T3%MVm~&*QkE%5K!%emkBmS1`0hMq$a`Hx?x*Gtznr+AuEJk9axPW6C|r=5!qB1p2lmVcdc zKf@i54Hmc&KxOCglvR251aB#Wz@-5A0|)>Kn@Jf3udP*w>5b2p^~{=V%1nUGRz(5t C@r{E3 literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/Buildroot/repodata/repomd.xml b/tests/testdata/repos/eln/Buildroot/repodata/repomd.xml new file mode 100644 index 0000000..8400bbc --- /dev/null +++ b/tests/testdata/repos/eln/Buildroot/repodata/repomd.xml @@ -0,0 +1,28 @@ + + + 1778717671 + + 8d4fa97f0d4d6bdeca349744217b0e9d694aea2cef332765e97c2252c4df6431 + 803c8426b401a9880c4f3e606fd7648a4d619ad1b9f64f029ba2edf0d922fcff + + 1778717671 + 626 + 1265 + + + 4c41bd6e67d5b8fc2da462e55f106fcdc729daf0e722ace44fbf1f0688f4cf68 + 69b6ea42561116fa83b8c836736c307693c9d425c6b5d8c9793c86bfa15069bd + + 1778717671 + 223 + 285 + + + f4ecf39d19149d8918b7485eea237aa87723615393e5f15408b577e2114818d7 + 6afc2f6d415b482a37ee91bb209367ff45b7f6f3434775ee219e73abf819ae72 + + 1778717671 + 304 + 393 + + diff --git a/tests/testdata/repos/elnroot/epd-1.0-1.x86_64.rpm b/tests/testdata/repos/eln/CRB/epd-1.0-1.x86_64.rpm similarity index 91% rename from tests/testdata/repos/elnroot/epd-1.0-1.x86_64.rpm rename to tests/testdata/repos/eln/CRB/epd-1.0-1.x86_64.rpm index f3395da5c6f364a5d515da5d5184c978fc12f639..4e4d859b86062623a607c3c62cc193277421cc51 100644 GIT binary patch delta 183 zcmdmKxYKaL!+LWQ6T`$rGb4-C)FcDbv{Xxrlr&RIQv*XwVo?WrqoWS@&h$V|v_}S(VkqAb13v)wr jGjoH@n?*I51P(Gh|NQv&q0PE+o-?hppO#L3BYqYDStmX{ delta 183 zcmdmKxYKaL!+JwAvy>FGL<{pYOJjpn1LG8P^JD{qL}RnWMAPJyREyM$Hb2CdbqZCs!qhy0*BO?Gy9cBA)+Z#*a!+1&fd);l8_^@2sVd> ziXw=vVuTddY9S6C7graCGtyNo!P~}poB9uBSjL}lYMbrw>7A96{CY1DtgIJ1H5ejI{?g*|4_Xk|0T~k^E!EnJOW?nncfoUNxJM0bXYV@M&a47>wt)fMPQv;w*-pZGm25Yz0^T}+8sL}i0NyiK_n%Y# zg>?k@pWTVPmlXKo8hDNT&DDFOX4CesD#z>6KiltrJ-4thmoN9eJB}WkEicsfO_@f} z6pf&{wAgAccIIu~-V@7d+=$hr3uAx*JO95;N0*=Kud8ViByl3vo(@m;)!uZ{Q`L*vWR*QCZ;y(9p?!58 delta 788 zcmZ9~J7^R^7zgnGX2;x#1TNf3P7Ad&5$~9t+1uR_)Z!opVv$18s6}>ncEJ$2ct!|m z4pBiZ#IRr*!9qbHjgSZyX?;{d5FcQppoNMS8XwJx?9Ep>unfQb9`iBGRp+rY@OAmy zTO0XGW~0S{7oEiMmF9u=T`vk9AsUX~kg;qu{8*|uRBq%XIt>HJ$mO9DN@x+Nglmy_ zlKWCBpNGnmsqZ#)80eTMN(kQ-T&AAz5>LA-N+X{14lUG*m+$@@?~I>c|FUJr>#?qN zdu7UMmIikN>;iy;015y*o2?Emb$$To2QUV}0_0CxcN0UcHazyPcQ*aWa`l<-a18Als`q@N2USU zDAnKW#XDffslk0S5u2of2jqwf)~KO2wwKBIwf6&do^JsxB|jw3kROp3%>CQX0hEpc z<;)CVzcUHtCsgo(obN@z{!IR8^4VVUClhBpcQb!=S+^{m)87}K&b3-I(R}Y+U^LOK zcDQSz-I`9~IUJfe{NJyvS=qBQsyTIDbL!{XalJizChwMi!}Ebx^W2f_dZlW`*}clk pg72yz5OU?>){(waYVF@>)~~!j@J4T}zdEs$tqt9>Ze){H{twJBgt7nt diff --git a/tests/testdata/repos/eln/CRB/repodata/63510d69370f860af7ae99ffd909ecee7358765b80abb684b7a38f70e2bd977a-other.xml.zst b/tests/testdata/repos/eln/CRB/repodata/63510d69370f860af7ae99ffd909ecee7358765b80abb684b7a38f70e2bd977a-other.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..a5c0c230062f45a6781c0a23bb4b4fa9f209a57a GIT binary patch literal 353 zcmV-n0iOOSwJ-euV8sdm_83hfKufj(V4~vCQA0p}My9v}C$%U|#SVnMTQqdsl14?> z1(-zuK>$MlEEOMhV)nIsbZzhY)v@q5KCy5kTUZly906CY5=(_eRoQlJ$6l(mIXD9x z5e5kgEF)`jI;~%BhGS{bNr8RCQdKt41Pd@`ETxI{vR}{gtG1RQe4Nto5hXz!j4t`- zo=1W2{*>0BPnc(x=P{nN?5ACwS@%0+j;Trv+iDD{!m(mdF)q#nb*VY#uCCcS=}-Gjpk z3{KZ}?4?SNcM*CX;j(+l0-ejDpwJs>AfgXUlqKO*UmFz-FtWH_4_@ literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/CRB/repodata/a939af998dafa1b5c771494f948ca1a12e7c8e0ba4b324f784caeca60580b944-filelists.xml.zst b/tests/testdata/repos/eln/CRB/repodata/a939af998dafa1b5c771494f948ca1a12e7c8e0ba4b324f784caeca60580b944-filelists.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..4ef0c305aa70f0790b6ee0b517b241e8c03a3982 GIT binary patch literal 279 zcmV+y0qFiHwJ-euV08!pW|KT0P-pZI0S}1dyhO{S&B)GABN~IBDFn+>7hQJMuzCnM z05JeF015xW9}+%TBpQ2_3UH#xz!PdNvq(?`+56Yl#83z<0R#pJcorJ#2-y&Y@Sf5;9%liQer6FctT(318pa< z>ZrY=XH+UN6vd3^{pWc_;>FWI5zeP1B}3r{3!q%^G|;CLyYoDs=_WCR3p*OVJDy`u zviFTG0SXjB_Wre1J(IP$gfV{8mQMOQ-fFDZTh`(#tqzHfdUV+`F0V-lC4?11*NAJb d0|)>EkN^PN$h^&1PS%$7?3!%K%mAB(iUOa}eX{@n literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/CRB/repodata/adce22870e107115797acfb5b60eb3ae16af020f137c2dd783447099c23683cb-primary.xml.zst b/tests/testdata/repos/eln/CRB/repodata/adce22870e107115797acfb5b60eb3ae16af020f137c2dd783447099c23683cb-primary.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..05e352d4c7cd150ca752205cfd5308e703be21ba GIT binary patch literal 704 zcmV;x0zdsIwJ-euV7(OpHY|c8AZ_)-T29CXHAaZd_6#Z4M1ka#f0Xm4;abzYF`@xAq0C)g+085juzxN;AlqOlR+HcsMIOsfx7eOW~UWeU@gVO%=)G^qdOpV&xq_>gW zFqsW9`M7Q0jz0_WThE+;ybS{&>ct<7|kPMrba{@MJt4SEUD5O2R^!yYi(?E+9 z2MrEQYG6~=h2@a$E@XS- z*?3wF6IN%o^G5sxA!n^VVYq_d@H&Z@#2Zv`|)NKI|!k! zTJw}~wH%D(`ItFovR(y;=VdLyWV3o3Rbu~eFhK!fdW?OXmjJaFc6TRJc6w_??OiMu zg|b)_(teYwzgA;)W{>r9n59Yom{z)l{)+7*G=>BqNU? z%3-4SqW7xz8fP?2i)G7tH8IQ5K?RfXZ*K z6u{F>orBvo0U(_kRjH(x0gk4@_7gY-1OqW*gu$RtBaK-gmVr5VC+2ZBKqSvOh%GRX zmj8eV{00#0WnuWk4vzuuc{SOBBzJ9@)Y}-CNxQiLS--3?7O>6<@5d`)N5Zvof6Y$6 mLr2<3YP|*)x@X#5WEU|yveJ?y%(g7WAZE8das;!Jh + + 1778717670 + + adce22870e107115797acfb5b60eb3ae16af020f137c2dd783447099c23683cb + d0ab817c34b063b3ff19b611f8e4ce132fa18fc1b5f41c424e5f8faa0bc52aa5 + + 1778717670 + 704 + 2235 + + + a939af998dafa1b5c771494f948ca1a12e7c8e0ba4b324f784caeca60580b944 + d4cbedeac0b70877906e01ff83afedde852c88d56f5bf4477e8f4ec80d02e9e5 + + 1778717670 + 279 + 445 + + + 63510d69370f860af7ae99ffd909ecee7358765b80abb684b7a38f70e2bd977a + df320cc37c560b6aa899b3344d87a701d307398f662dc4e7437a22adddc0c2b0 + + 1778717670 + 353 + 665 + + diff --git a/tests/testdata/repos/elnroot/epc-1.0-1.x86_64.rpm b/tests/testdata/repos/eln/Extras/epc-1.0-1.x86_64.rpm similarity index 93% rename from tests/testdata/repos/elnroot/epc-1.0-1.x86_64.rpm rename to tests/testdata/repos/eln/Extras/epc-1.0-1.x86_64.rpm index a1420290ab01a017a0001ae2ad8313b3d08ad1f9..8c20c48dd09009b382d90d5262aaa1c3e88f3f90 100644 GIT binary patch delta 185 zcmdmKxYKaLgZdQXR0H$mlr&@0q*T*nV*?AbWHX}_^ORJBG=mfqW0N#v%QQoylw<~T zbMur`%aoLqG}B~53sXx23(K@56SE{k3qw;2!!#q43#t%X)S**g(Hiw8rFtS^i l8=9M$8*JVzs>vk4c1~jXvyUl3(IQVhdb%V6CchCs3jpu`JhlJ; delta 185 zcmdmKxYKaLgL< z!&C$FWYgqiLrVjTBm-j*%QV%{!XP=#GA+%_z&z31(%dA?FwN8;)zUc0$k@m%*&xX% zDK*K|%)s2(gaHKD6`#*f@M+qxEwe%KGkqAb1a}!Go j3nQb=n?*I51U_7OoO7i4U4PciiN{L?D|bzPBYqYD*DyW0 diff --git a/tests/testdata/repos/eln/Extras/repodata/718eae20ba82ada746eb049df2e88a420766a22c0a835e3ac0d666d1e5acfbaa-filelists.xml.zst b/tests/testdata/repos/eln/Extras/repodata/718eae20ba82ada746eb049df2e88a420766a22c0a835e3ac0d666d1e5acfbaa-filelists.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..afa7de89f0cf58a61653190e812c2f4b10ac03ab GIT binary patch literal 224 zcmV<603ZJ-wJ-euV7&$ag3mA?P)FqfK-#}+|1V#W)q$IzMyQy+&@>!bcwsVT5(zaB zXI$;uN|hs^as*Vq{MnbJKeQYE99f9IT{i(eVFj#B{v0XAb{W0DhvIFgjFc=+MraA6 zGFjTf7;Ra|Az51vMOkgdKORBaQkqm6!z{*nzCo?MAWu-9p9E aAKF6Gzy$>W8OzDqvYuU&O_>>Bvrti@jBOPF literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/Extras/repodata/d852b0588e7a6b861bf02df7aff77fd692bc597986c9fa22323a36fdb2d73a06-primary.xml.zst b/tests/testdata/repos/eln/Extras/repodata/d852b0588e7a6b861bf02df7aff77fd692bc597986c9fa22323a36fdb2d73a06-primary.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..2e20e4086a7f9ddc9050c86b8cc1a651beee9fb3 GIT binary patch literal 606 zcmV-k0-^mVwJ-euV674WR_Ami5RK>omsm7O1iq$`R+l2^J0t;idDRa?6njtHlafRP z08phjX#j2jY5?83mDL;u!61p7;C-!ISq<8EKOb$~it}l&M{g&&o8p}D2tVXWz-Qa1 zz0+O+r*+N>*Q(+#FHyxsQc+2*C17)&Ji?Tkl79Kcmwz_J4LGDYXmIcdLS?Lwe*0o! zJfc-2d#ls%vfu4u)=qV}nPnoG(t>&m( zwQgm#3_qe?g?_ijKXA8OS#1gKs44-Qq~eUTh$Axk$y8E5EN-qd5%)RHVK>pf`KYxWPm|oMjAsPmVq6-GxL}Y zkjrxhViN{3`45V~Zvbg83&Wo~JO;Sq)wl&Ica53U+ZfoS-PVAtUe<&K%yYu~u}j!N sxEA-v?36on(#E9LYha;#rp-k*5u=lp)+7P9Wf6nSZe`>+W+xHi46KhKdH?_b literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/Extras/repodata/ef66a3ad019261b3603fddafbb1a8aafdc9ebb314370553c518be659d83b0ada-other.xml.zst b/tests/testdata/repos/eln/Extras/repodata/ef66a3ad019261b3603fddafbb1a8aafdc9ebb314370553c518be659d83b0ada-other.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..6d2e57ac532596f76ca3d5771de26fe47634c134 GIT binary patch literal 306 zcmV-20nPp>wJ-euU`+`C78OGxFlo#K%%lVMAqEZEEq#GF09G2RCG2K}0t+lPCj||8 zsT?{0Isi8SPW}GnH2TOVG>U9mtt{sNuzRVNifUaO`*oThmOa9!9mNZR@Bb= z+zIkpR$D2uU$Av;2PhB`87NK0iO!Qm=Pk;F(NUV_#pkd5vc%WK*~I605Hj>3B;^-L zf-Pw^B`}7Js9#IPPo9{LaXY^OR)8yI3tDEDx|;K3t)Hq>)Aegy-N)3G(=0!<`D3oyc3*<=Y3mr3r>>75D=P012B(83nJcRfp+~&zAMfnrzBUfX!A# E0fs$}%K!iX literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/eln/Extras/repodata/repomd.xml b/tests/testdata/repos/eln/Extras/repodata/repomd.xml new file mode 100644 index 0000000..16f677e --- /dev/null +++ b/tests/testdata/repos/eln/Extras/repodata/repomd.xml @@ -0,0 +1,28 @@ + + + 1778717670 + + d852b0588e7a6b861bf02df7aff77fd692bc597986c9fa22323a36fdb2d73a06 + 323a9591c1a344cf10d2c9c5f541f118eb922e3e1e8a2274072459699647eb50 + + 1778717670 + 606 + 1165 + + + 718eae20ba82ada746eb049df2e88a420766a22c0a835e3ac0d666d1e5acfbaa + dae4f03d98107c89b4af8380c4a6a7036b4809f7e68d60a3d2fa2a3a3429f010 + + 1778717670 + 224 + 285 + + + ef66a3ad019261b3603fddafbb1a8aafdc9ebb314370553c518be659d83b0ada + d890073321ddf2010162771341ea12e3de65d0a4ef40a4cafa696d4cea29fe23 + + 1778717670 + 306 + 393 + + diff --git a/tests/testdata/repos/eln/metadata/composeinfo.json b/tests/testdata/repos/eln/metadata/composeinfo.json new file mode 100644 index 0000000..ea0ecc8 --- /dev/null +++ b/tests/testdata/repos/eln/metadata/composeinfo.json @@ -0,0 +1,53 @@ +{ + "payload": { + "release": { + "internal": false, + "name": "Fedora", + "short": "Fedora", + "type": "ga", + "version": "eln" + }, + "variants": { + "AppStream": { + "id": "AppStream", + "paths": { + "repository": { + "x86_64": "AppStream" + } + } + }, + "BaseOS": { + "id": "BaseOS", + "paths": { + "repository": { + "x86_64": "BaseOS" + } + } + }, + "Buildroot": { + "id": "Buildroot", + "paths": { + "repository": { + "x86_64": "Buildroot" + } + } + }, + "CRB": { + "id": "CRB", + "paths": { + "repository": { + "x86_64": "CRB" + } + } + }, + "Extras": { + "id": "Extras", + "paths": { + "repository": { + "x86_64": "Extras" + } + } + } + } + } +} diff --git a/tests/testdata/repos/eln/override.conf b/tests/testdata/repos/eln/override.conf new file mode 100644 index 0000000..5553af4 --- /dev/null +++ b/tests/testdata/repos/eln/override.conf @@ -0,0 +1,91 @@ +# This files overrides default variables defined in the configs in +# the ../shared directory. + +from images import * + +# Fedora signing keys. +sigkeys = ['f577861e', '6d9f90a6'] + +# Architectures supported by Fedora ELN. +tree_arches = ['aarch64', 'ppc64le', 's390x', 'x86_64'] + +# For Fedora-ELN, we do not inherit builds from parent tags. +pkgset_koji_inherit = False + +# No jigdo needed in Fedora. +create_jigdo = False + +# We only build repositories, installer and images in Fedora so far. +skip_phases = [ + "createiso", + "live_media", + "live_images", + "ostree", + "osbs", +] + +# Enables macboot on x86_64 for all variants and disables upgrade image building +# everywhere. +# Use 4GB image size for all arches. +lorax_options = [ + ('^.*$', { + 'x86_64': { + 'nomacboot': True + }, + '*': { + 'rootfs_size': 4 + } + }) +] + +# Drop the variants we do not care about from the variant_as_lookaside. +variant_as_lookaside = [ + ("AppStream", "BaseOS"), + ("Extras", "BaseOS"), + ("Extras", "AppStream"), + ("Extras", "CRB"), + ("HighAvailability", "BaseOS"), + ("HighAvailability", "AppStream"), + ("RT", "BaseOS"), + ("RT", "AppStream"), + ("NFV", "BaseOS"), + ("NFV", "AppStream"), + ("CRB", "BaseOS"), + ("CRB", "AppStream"), + ("SAP", "BaseOS"), + ("SAP", "AppStream"), + ("SAP", "HighAvailability"), + ("SAPHANA", "BaseOS"), + ("SAPHANA", "AppStream"), + ("SAPHANA", "HighAvailability"), + ("Buildroot", "BaseOS"), + ("Buildroot", "AppStream"), + ("Buildroot", "CRB"), + ("Buildroot", "Extras"), + ("Buildroot", "HighAvailability"), + ("Buildroot", "NFV"), + ("Buildroot", "RT"), + ("Buildroot", "SAP"), + ("Buildroot", "SAPHANA"), +] + +# No product_id for Fedora. +product_id_allow_missing = False + +# These will be inherited by live_media, live_images and image_build +global_release = '!RELEASE_FROM_LABEL_DATE_TYPE_RESPIN' +global_version = 'ELN' +# live_images ignores this in favor of live_target +global_target = 'eln' + +# kiwi images need another target that uses old mock chroot +kiwibuild_target = 'eln-kiwi' + +# kiwi image global configuration +kiwibuild_description_scm = 'git+https://pagure.io/fedora-kiwi-descriptions.git?#HEAD' +kiwibuild_description_path = 'Fedora-ELN.kiwi' +kiwibuild_version = '11' +kiwibuild_repo_releasever = 'eln' + +# --. +kiwibuild_bundle_name_format = '%N-%v-%I.%A' diff --git a/tests/testdata/repos/elnbase/repodata/6212147882b929cefe09ce147e26e1020b738656c9517eac9a52a058d7793a31-other.xml.zst b/tests/testdata/repos/elnbase/repodata/6212147882b929cefe09ce147e26e1020b738656c9517eac9a52a058d7793a31-other.xml.zst deleted file mode 100644 index b812bc1972d7cada9d21d27c346aef73b4380d40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 351 zcmV-l0igaUwJ-euV6_SW_Lxi|Kuh&tQP1;tYO{>CKxU*w3e;JyA|+;lLtAlaRCHZ{ z2}S@w07C#R9lmkJ^ojfM>(uW@$AZ4`iUl>Qh4etjAu!$Rv~-Z5sA9iPsduhb5DP)W z#DT&>%SL*rozinJgSC|G<3RlbLs3Pb1Pl&VEuBd@w@=^lBbT@xQ96Dx?NkpT&7`PV5oODuzNf(LE` z5ZP%wG(}#0!CTrea3KJGYrv9Y6IxQ%xeMpULf=U4%%fRL=qc(SxK~SO+UZ$gMl9W2 zi(jYIJJ%l588hK@2(59oXZ67u;Aop4EAv`pHMU>TEAn2euGP7g`+75hku_S`p&*t+ x@#j7g0w#Km~x!Cf3`8&7_Qi*Vd}T^u}k)dS*>FWhTI8tD<)Wrh)(f diff --git a/tests/testdata/repos/elnbase/repodata/e66e2d334117944d094138fdc62fda05db2e252cd29aeffa765a71451a8856dc-filelists.xml.zst b/tests/testdata/repos/elnbase/repodata/e66e2d334117944d094138fdc62fda05db2e252cd29aeffa765a71451a8856dc-filelists.xml.zst deleted file mode 100644 index 2253c3af9e47915dd43028f75153334b66ac1f32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 279 zcmV+y0qFiHwJ-euV08!pW|KT0U}y9&*#4tGm=H?ZG_S*eKnDHPCB>*l66wrz#2TzQ z05SkF0E+1ZM<^y?p=fATO2CPt!%C>B%pyS%M5|Z&iJ=r00t^rotTZ%qCc5#oi@;Vk z2?{-akSen%BmptLckWo;MMhq`=JW9{4p|^<@9}}OU(FzNYvrT{gp(3O*<&T-21YbH zX%$C2IdVn?DlrtbY-RQ5@q@H$<)IUfrz9mq+2#x!T&z6w!)e*^mCkUJ)-8`9@E69< zb+5Qw^BD>hL9}|MubSD?u-!2~uIB6?>;N}gd;I0K$UZh-k^gwFy=&iVF|XGMjI7OP d0SEvCkN^PN$h^&1PS%$7?3!%K%mAB(iULx3fwKSr diff --git a/tests/testdata/repos/elnbase/repodata/f4ed4ad1632ef201cb823cb62f2408918097df27d66aaee819fc22ba37ab262c-primary.xml.zst b/tests/testdata/repos/elnbase/repodata/f4ed4ad1632ef201cb823cb62f2408918097df27d66aaee819fc22ba37ab262c-primary.xml.zst deleted file mode 100644 index d3994c41b6d9b690eea23fff346f37f1ddf17b56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 699 zcmV;s0z~~NwJ-euV3idBHf(|;AWh`~^yO(E&&?gJsQQF>F$42aKhy)M`@oI=Xe$Fk zSO5)p0C)g+01Jz%&-ok96c$nP;&ldS{uN7Q!LU}WgQ-OoN>Q}h(y4i z1%kr^ix^g&S6c5(Nfs7ax9a>2udIUr2D{2vgHn|*=#DhF1qxrT`PxYPPZg9-}?(rfEwtp+U4(A^!8cC`6Yi*u4J z3nf_=5kHIQXUeTxca*ns%)+8?R7&PJzpCQaR&};Gfybh+sG6Boy(VV@%=19bah!!k zUsdXFYf{{C#{ITQ**sE0Ok5`U$j3|yDef2QJW}9ICm*7d%EzXGyLLg8gaZ-^R>7{@fy(r2;)C{PALEYd)fD7s diff --git a/tests/testdata/repos/elnbase/repodata/repomd.xml b/tests/testdata/repos/elnbase/repodata/repomd.xml deleted file mode 100644 index 99dfb7b..0000000 --- a/tests/testdata/repos/elnbase/repodata/repomd.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - 1777498823 - - f4ed4ad1632ef201cb823cb62f2408918097df27d66aaee819fc22ba37ab262c - 12c7b2df4b3e597c8a412e6b187f0379f9024b0c19db0a6a22615dd1b5b09962 - - 1777498823 - 699 - 2263 - - - e66e2d334117944d094138fdc62fda05db2e252cd29aeffa765a71451a8856dc - 48d1e74e7b0cb3bf5286c6bf23c19000cb94afdf982c113b926688e51b100a36 - - 1777498823 - 279 - 445 - - - 6212147882b929cefe09ce147e26e1020b738656c9517eac9a52a058d7793a31 - c8b2793ecacedcdba8b304a308130a84ac2613447053514f1e0f040cf5220132 - - 1777498823 - 351 - 665 - - diff --git a/tests/testdata/repos/elnnew/epa-2.0-1.x86_64.rpm b/tests/testdata/repos/elnnew/epa-2.0-1.x86_64.rpm new file mode 100644 index 0000000000000000000000000000000000000000..0cefec80fa3278baef1612e7ca96fc3c3c53d25e GIT binary patch literal 6329 zcmeI0ONbmr7{|ZanIvnXuoA%s2o)5v3#r+DKO`GXcC*Q9NY?DeP0V4buCAWxwY#hB z>PdEkha7Sc52ASS5XeCxN)!|n4}t^~MFkH&KoCTUVtgbjf(9j7sqR{n>`A;jf0)Ow zzVEB4`ntLY{uj<%{Gtg`EGO7#Ygn)7KWfeDx+h;g-%w-g0ES)zfNcQP_vZm%2%vEj z0IXFx4S>eYibnt>H_rn=3jh+uKh^b+*Y(YxRs6V$|Dxh20EUq5c!BSGzG>NxZ&OP3 zAP7k4*@hPw#0YGY>b|Sl5D`tYZPT{R(DX^5TN*PXow`QoX{M&RBwzt!w&@bWoWKqY zQ>US$IgT4pjp|ypfpwccet+!ok3ReBfoDfvIC=Vvn*zXNt9#N{Uw!q}S6_Yg)mLAA z_0?Bjef=+0c_Pcp%TLvw23+f#YzAoc0N~!**Jv@769T}X>eh-+B7Kwr<%4{$d=xn* z<3A`~e~piF0|4Bp_yR!1cPPH7d=*cz^jYLwTNVGR;uDI0Q}Nx3e^)%G_z%U06<<=n zx1jj4il0z?Me!3gw{B7VwBlRU{-3M&+`3JzM|w;xfY$9Q{*Gd~uR(x@^p#|MxSp?} z*4vW%YymW;)%?E7pH+O1;zh-is(xjC2UYz^wVp#NU;11F0IfjfzoP2p^;-+jJf&D( zSIIKJ0nmyRzo=OHUo!rZ;$!uBXv+N!0c?Dx{{7~sb$sKyD*toE-_+}AeyR9d)d!?l zo|i#@*4>iFr5^}JTLT>?dTF|ZL@!NAu>`Z-SfE%Sg2HM%WP%oPUdB9Y11zlB_+80) z638wAz$6QKLC|!;7Z@#J*Yuv%L)-H_i7AowVsyITVUL#ak+@ufB+hz^u;@ASj&;?Z zY>R@ni#)9s$Z|5g=sDQ2MyjT*Z@|@8k*7%<43G0PFPIQ4oQxB;m!wRLfQreHiMYc= zd39`>EG3*&$znG-!lnxr#f$%xsPL3{Sd`%im~E|XVI8ctQ<=eZL`s~L9P>anULYK?MartnBoOW(+$k94MTk3; zVsSJsX_pCv^EhV+&ygfScrN3Z@-$CKoZ+Jd&pJ3ESqI@cRusG#i+GWe5(`FqMO-c+ zJeP052j(aD?Vp{RJTyPE@4)`?om=q4s*y3X&YYOvwP$L__`!qo+h=BW?w_67w|53% zkuxgBMth zLPU3EF)_~&j%aipr)45=7?Xt2a;%f}W^>u_0h}F sy|V!WJJxPE`{SGE(yxd9T+{e4-2l5D5|@@wz4z*tbpz1cd?{N!Zee8?u+S!43T;FSQ$_LzQYD3j8UmU+b~3wfV2ba(@4b05^NoFF1ApJ29JsJ6 z?dS$y9oX%1$%2rX)TAPAwM?M73Sz01uOr5dQ9KGGDYbyq?NCS^`KsOW6TwoS1wt94 z(j;I>82g%qG7`Sh#^_MD8S`b5w4+!W5o#s#V@newf3E$zy}Gtno__gwf2-uo_wGA4 zD`!^#Tm?`9yoKJz;FQyy0pI|h0^kA8UE&Bp8F20qUm<=@d;`E4zumiRfIh&R zC;tPnCjTS(Nx@zB9R<=N;MxK^kRe_tenh-M{H(Z#y9J;ERI_3L_pr!UH_87&{IeLy z{Z0HU_s_!{r@(O`c$Y0t+P?$OMrzD^*k3)$W@~pY=>~854c1&*jGK#{g*x9^bEBjC4^G~GdhzPZ N=i%w=r`hSy_y6vxYBm4> delta 587 zcmXYuziSjh6vw}tUCcHir@12pf+8XK1NWHO+1=T-5efbX2sS|t2xfNgEd=~=#wMol z5c~&ZKr1UPgrEqgU}2NOG$KT_i-koL6ts|724r{Nz%YE?eBPTkGaK@~9RI!kXWKNwIwLZwQRF`>@$xX?1DDAA_WLTD&OY1pG&^fD@vtW=qb%0h>f zBvGQs=)BBGh%$*op@>2ysmMqfN+X@ANY%%V1_$lGrwhCYwqE00cZgewrRlq*6dGgvcJPztv=xX zV*XzH2jQLIz|ThTM8$K}-$B|#ZRsulUE8z^?aQ+!kX;eT?wysQyVAc=E7UhfSJNa& zqGR>j`*y2+*Ogsi=Q~I2t1Vt?pBoHux6uI43c*CNFiDv*%gG%{1 zfI9$6fVa}y9eLz*X8<^WrvZ3?Ge;Z&xB@r}#1q6D#P{q{$|BLvj2;}}D zKJNS1;f+z_Um;(;J)PpFig3qdzVH D%?xE& delta 580 zcmYk3KWG#|6o-GCUA#j%av^u5F?Dj{9rI^*c18pXN#q)B0>)sG-JM-f6LPsUA+tuni(;j{ zHpb`;BGPXQOgb4-H#w3st zd-83`1NV>;X_;_~f?}YI_zm$I@mu1Z@*eIHfI2Xpmjk$8%k$}vL-Mp3T2CGM9H)-fhn18_k7E=o_tt9KLI|ChEt_mnKEm4Ch}xJ6rhk{C56t=JPo~ CQE1`- diff --git a/tests/testdata/repos/elnnew/repodata/029e08c67f723be4b217594371bb7f9f223cb866b934d857d9bddb4234e9c942-filelists.xml.zst b/tests/testdata/repos/elnnew/repodata/029e08c67f723be4b217594371bb7f9f223cb866b934d857d9bddb4234e9c942-filelists.xml.zst deleted file mode 100644 index add7236ba7b5257a8142d558d9079f71fd4bfe0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 226 zcmV<803H7*wJ-euV9f>q^3O3KKxgOy@CN=Vs$?iB*Z&4Q_abTKw4lGFAwfE$IMD?G z5ocWO+sdR@#Po`od^xlawJYOr2z{bmIV{Y>^ZmMu=u9b4T;#AYA=y5kcleIH?a8t* zmCONC%KCXM&At0a*1%ErYci(EMv*3$gS~XgYKvnMCSN80NNdy~t&QR7S43Y9@i)>i z<g8Ujd*M%&G={6sTor|Pb~T7+#e_8{Z;SajOfY|$&7 zQL$^U@ZT#p^=AFo?%u1-Cghc_7!VCY2+6XQ&IjJ0^2pDt-+k=l=<{ln=Ysr=7i*TD z+iN!~b|8f0ShaHb1=>_tD;Ix&Hmy8RMe_(jh>&b!1BQ*22O5dGRn|27}^K zI8y*h08s$$s)S8%vouI5K`8B-I{e}d)+N=4XTP5RITZJeZ%|xgp@16aI0B@cnWheq z^DLBSztb~0N)XCG%Y;FKLem9mZe*cXy$seAiW-OMAC&Vf29nL1IzOpiMr%6#gX-0k zv61vDQ3|2-g9}hDnlg5B)h>P0e;iU>nLGCOrhLu0C>@N^&1+w)Z(eNcWDxO-<^RR- zu~_j(zetQY7S<-=KiHhR_0TVNhs+%bLOBv|aswTxgwkut1zU3nYx>!*YL-|=Qwb%I z7l0?S#yisEizoQ#G6-Y`Kz&r8ASOa+Iz>!YxLP9T7swfV1d3=DvqwYHs2y|T?W^ElHCa(Hh<)& sFT_4{9W_E zJkRVnsY!7$bVU6+E`D-_^ozTB)E0EaEWHfp$yPsAr?U0ySUtw=5~U;d4Q|(wN_#y+ z%tzFWgW$ldBbAtQ%j-M7<(0dUB*q1iU!U01Ya4V#4LYI*Id!Q@z(~~2LFXvS(!7p; zeR4maxKqKhGWqJVJo|vRGvRQn0>2gD8V3Lgn@Jf3udP)lrZ=BilVh2=*ld*< DIjfL2 diff --git a/tests/testdata/repos/elnnew/repodata/e1fb8cbc0efa75785de59ffca8a3de5dd3928ab2075891beabbdedf2a74608b0-primary.xml.zst b/tests/testdata/repos/elnnew/repodata/e1fb8cbc0efa75785de59ffca8a3de5dd3928ab2075891beabbdedf2a74608b0-primary.xml.zst deleted file mode 100644 index 0167dc06bccadecf1ca0462cf71f1aa45e4dccbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 629 zcmV-*0*d`8wJ-euU}X~kX6Sb%5RK>omsk>2DfG3mu)7q^$0Ci{>0QELI>ZBQ$ebi1 z0D!8y0c!wo0Br!U+HcmqECw|o8WP1#@IKbPEC%hnpO3Qc#rd??+uKTRwm5gZ;g38C ze71esJM9&4TIZ~AttvkAk}5Kkib`rN0h{yW4O41T`sEj2{>c_M;F98?!NFUE%2*-& z_J(o1(JJx%NmG+DzyeI{*H|`|Q-h;bW-BkmA6fUZSXbt(3S8yBIV-#v`-btqh@$A6!QjDLlo5$-Z!n%W z;aOn`{0T01yitGK8|LwLf70G~n*xy<=}#6*P(W~x=|f2gOnX^(_u}%Kw?d}94C5#o z=21ZV-XMRcrd8$#D+N7{x1Y!f-WQ*uUdB|mJJ6!x?I$FTl&l`@i${_iP!vUux2Ghe zf67eVYB5LMighoGW%v>GD)hTG{(-yQ%VGiUCQ8;5UG@mxbZa9WDdh^J?CL zBzNtZ)XNxHNxQKDS-z|R3z+AG_v4kYBjMWIU$fKiP)Qq3t#4qVdZx|A*hSWsIpDVJ PVi2-h899#GNyIq=zOy%? diff --git a/tests/testdata/repos/elnnew/repodata/ec7341345e04def216d16e0db04b625570797b0142fe7150924d08f34acc1356-primary.xml.zst b/tests/testdata/repos/elnnew/repodata/ec7341345e04def216d16e0db04b625570797b0142fe7150924d08f34acc1356-primary.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..8e7edbfa0121380a36926d3e266c38dcc3fbc125 GIT binary patch literal 764 zcmV5N*l>rvuBAAm*J$+GZ)5k3|}@)4$@ruKTtOm^Bdr z017w|h5&{Dga8jrFDw!N5gSujRQ+w1G!_=!hcruA^oZ4d!|p|c?m@gKB0b`D*u7}b z?MqMHg53*=QF~eRmLfM?NQ_|-euqm$x6P=%)LsE*RZ44Y?ULVkiAy#jmo=-_1Z>U^ z7GbNRk@oD;^HaEx2H3+mXmDVW!2>zgGFg+*4K_&%g78X15AUoo+)<~21_oaZRc z<2VY7zM51&ow>SKgHm-b*u7{l$B(F2q5W3*2h#0cG}w^sjc4QeXppQrvz<5Mm#}-$ zU{g?f6-X4Hlbu+S`a1 zOVr+v_o}$T$W+yurHt#NL5e&fGsjETtI+VQtR;}_Rj;E;>mdy$C?H6Wt&g)3p!UM< z?uC?{-bzt>8x4h#G!};2XA$-H(N>+=W3Akxu;?N45wFXyD$m%O&7g&OEDDlmm!6+C zmr}|nIuj*7@z=QKJwoys=wY5od5n9B6CuSpP}00dX7XiGD9Z5#dKO1H7hfaeo!7+Q zX=0#hau~{CCT4*?HZGCMOQd@g3B7-dfAf$hP5igG_@?D~@7}^Vll*f@xj%)O8f-AY zJ;r+?0Bpg4McCmL)$FNTO>wjJI7c9GA~{H`0}%-{y&%ePsenfvAc1<6OC>IJLInoS@OA1s;IlUa_NIGmAfm1**kVcFQFeubWV-|>IU=QAz zdF%}k$#V{33k;;?KOh3X0R($l82+%sV}N^JO|~G(U0WvgHU@6eZf-! - 1777498823 + 1778717671 - e1fb8cbc0efa75785de59ffca8a3de5dd3928ab2075891beabbdedf2a74608b0 - edfd3c129d9db24508a6dcd38765281f02cdf98609587ce9ccc3885cd226237f - - 1777498823 - 629 - 1265 + ec7341345e04def216d16e0db04b625570797b0142fe7150924d08f34acc1356 + c09d2fb0e387f9b1d76bddbda53a17ff410e7376c32765e8c1883e8aa5125e10 + + 1778717671 + 764 + 3299 - 029e08c67f723be4b217594371bb7f9f223cb866b934d857d9bddb4234e9c942 - 8519cd36f5dcc309402aa70eb2463eebd439a134f410ee2b052afe51dddb6265 - - 1777498823 - 226 - 285 + 6f2f32cc8b75d194c83ef1075936ed263a468f298ce34bf64a112a510aed46f8 + d1edbf9e8bb2c6455b8b5ad6506b19b3d89bea5e0e4cc07eb3f675ab536a090a + + 1778717671 + 323 + 605 - c083429e71ea2c4bea418159abf7debbf79dd70f21731b1b4acc5195658e7890 - bd83ff93ecd4e37aa7dc35a1dfc61a5c8d560c14eea47fe443c86ca184853289 - - 1777498823 - 305 - 393 + b5d3790249f642dafa96a7b5ba61938b50e19cc4c57fe63d7e4206a869c10925 + 7246bec78e312d7765aa885c6e196cf347adf944323c9d7593d57ef92340f763 + + 1778717671 + 398 + 937 diff --git a/tests/testdata/repos/elnroot/repodata/081516c8122bf9e116d0314902b635ef595c121ba2e7a9d8d448de7e636c948b-filelists.xml.zst b/tests/testdata/repos/elnroot/repodata/081516c8122bf9e116d0314902b635ef595c121ba2e7a9d8d448de7e636c948b-filelists.xml.zst deleted file mode 100644 index 89eb180e2c48fb235a01474b2a0254c821bc7876..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 366 zcmV-!0g?VFwJ-euU@Z#(hTBgcP-)y4ZA?rt<|9N_O5g@?_V&6;8+qyFTG94o2B-H^ z07L*m0L>w>NJ@cGsTRl&oM>Job#TOyBUc;<(G8wJh=vBj(>TWwu!tgrTA;^KG!hg+ zjpI)9N`Vnj4q$+wKrM%-i3k07Qp>>9@*Fe}!xNIDXb30)2}v!rAo^h8NlB@|s8j=W z4YeSe!AbGL)#3_%l2Z6d;vO@@lE0ccr%Np{ zFMU1!wwtf{y%zJ@PTXS|pTWmkAIaq{KleRs=7{6X29b`x9C??&Wc)9a6Xp`+u~+B5 z+?pRsfjJaYi{lK22MiQJjpI)9M{Gy2HUl^_;01NU)PAnY<~|oANvd-07Ihi0|^i|atd%Watd&>QQl_cWNp^7 Mi)>0}fX#wM0b&HLng9R* diff --git a/tests/testdata/repos/elnroot/repodata/117a29ab84c4728bf8da3b0b942c823be18f4d190e710ed797182925cfad70ba-other.xml.zst b/tests/testdata/repos/elnroot/repodata/117a29ab84c4728bf8da3b0b942c823be18f4d190e710ed797182925cfad70ba-other.xml.zst deleted file mode 100644 index f3f39d0bd26f4248d85b6a0922b6b2d2025f5281..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 445 zcmV;u0Yd&LwJ-euV5JQJ7GYr`Kx_0ch%W5YVtiwgl;RGY)S`6tOG%NHH(vMh5F z00LhCSpZf5PLUAud)*YK>kLA-i)tyQqaMAE`x`UeFu9s^4R zFHHu43IV8>3RLt+2#cAdr#f0W67){gk0XmM2Ks6G2eo!Fk4ueLi&BVYv0HHPv6#oF zR;wGom}hjPmXlObAeF42bKkg*f5!Nzb4^kgTY2vI=W8kh`&@yM@uW;f=8h)3-$iJ~^dylDO>buM*_W*|MHllTDcku-U38;1ATn diff --git a/tests/testdata/repos/elnroot/repodata/5548c16c17c9999a288149e4c028529fea3de98d310a6f6b9aaf5f9913c7ac7b-primary.xml.zst b/tests/testdata/repos/elnroot/repodata/5548c16c17c9999a288149e4c028529fea3de98d310a6f6b9aaf5f9913c7ac7b-primary.xml.zst deleted file mode 100644 index a413f1d8fddbae9a1c13eb9c074e85a32dd715f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 830 zcmV-E1Ht?#wJ-euV67Pd=Jc5(5KrX+M}%iP-u(^Tv~5rc_c3C70lGEK^R?yRgdhL_ zAfRxS0FD5Z0B_Fd7}jtA!IqmH6VhT)LEM>iHBH!eY-5it&+q+@#T;848%e+FT8vg< zjEJ*>aqRZG7Nb>{o_Xz1U5mjmEp4{EWI?UUU>Ib}^bVh}E-j{|t))G{ph)Y;wpQJ5 z{6uvd6%~}9)&?Ysa@aCKkFHow`E}}bWiSM63LrQULLFS}TO8MCGPsZzYrk-83 z$~?QOYcX1->`O#@Vfl{kBQSd{Myrjxd`)>x*>PZ?C{t42cKTb_Vzjy}w5|*oi|txh zQ>(GTiZXHYTt;ghbrJrhRN@$s21n|Ov=RQ5j+>}7b3!Q{Q6P3U56Ag09YMZn)$UwT z{BAV>Mu9jh02spoTPBA;c(K z^> z!2ATg&Ch_Ac3o>N21B{t5!TXfG@gKKJOP)UE%>(+j8lG{dfo257kSabIcee~#O^hY zx_2kvoll9)ok$WdjE(*IoW$=4oqrK~5t(3^$mUwBOlv9Pud&lc}lH$g`Po_(VG>N@f`gQ4^ z!snPm=*pW)LIY4BfFdzR#5v3)5qj8^fu&^g1b{n(D5E@;q~`<^y%1#`H5(N$sT*)2 zz`aD&QKsUZx)^1cseqwQLm5Dn3guF6LWap(9eyl<)VMe~VDQVsEwKcUf`@@BVr0Oe zkRy#*AU*?g@J^V=Zh%alvmmx%AY1-JBCt1rzLzD#pF124aL23379?`llu5lF11o7a zYe2RyYwj4vn8(G(E@8)nYjS^>oqmUwv_Yx$8dxZwY3m}Bh|!Ui7D<9>%O(avcIzWY IV0IEA&dZmKJ^%m! diff --git a/tests/testdata/repos/elnroot/repodata/repomd.xml b/tests/testdata/repos/elnroot/repodata/repomd.xml deleted file mode 100644 index 8e9d54f..0000000 --- a/tests/testdata/repos/elnroot/repodata/repomd.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - 1777498823 - - 5548c16c17c9999a288149e4c028529fea3de98d310a6f6b9aaf5f9913c7ac7b - a1a05ef98f83ff3a3d3f9916306cd31ca7a948599849ec779a95d6f7e8a40214 - - 1777498823 - 830 - 4359 - - - 081516c8122bf9e116d0314902b635ef595c121ba2e7a9d8d448de7e636c948b - d25e63e1db6cb9a61a2a98c0ad43abda59e7826aa7551738079e02b16d75a912 - - 1777498823 - 366 - 765 - - - 117a29ab84c4728bf8da3b0b942c823be18f4d190e710ed797182925cfad70ba - a68bfd0ad8980ca8b2f26e4498cba5d9eb2c30885ca8fd1cac84f655687fe63f - - 1777498823 - 445 - 1209 - - diff --git a/tests/testdata/repos/empty/repodata/repomd.xml b/tests/testdata/repos/empty/repodata/repomd.xml index eb5dc0c..ab7abf7 100644 --- a/tests/testdata/repos/empty/repodata/repomd.xml +++ b/tests/testdata/repos/empty/repodata/repomd.xml @@ -1,11 +1,11 @@ - 1777498823 + 1778717671 69a3730a283b85a4b3cff7d04bfde3b2b234f0607ebc17319d7a8d143a8e066e e1e2ffd2fb1ee76f87b70750d00ca5677a252b397ab6c2389137a0c33e7b359f - 1777498823 + 1778717671 123 167 @@ -13,7 +13,7 @@ 9b07d97dc6ececed89aac0650b67bfb292647fe9fbaca48f629465be5f53f82b bf9808b81cb2dbc54b4b8e35adc584ddcaa73bd81f7088d73bf7dbbada961310 - 1777498823 + 1778717671 118 125 @@ -21,7 +21,7 @@ 6b37cc67608a24beaa81e1191d218f2ffd6b1191dceb5c100bac2e66249d518d e0ed5e0054194df036cf09c1a911e15bf2a4e7f26f2a788b6f47d53e80717ccc - 1777498823 + 1778717671 117 121 diff --git a/tests/testdata/repos/mkrepos.py b/tests/testdata/repos/mkrepos.py index 2df3938..de827f2 100755 --- a/tests/testdata/repos/mkrepos.py +++ b/tests/testdata/repos/mkrepos.py @@ -86,24 +86,34 @@ newddd = rpmfluff.SimpleRpmBuild("ddd", "3.0", "1", ["x86_64"]) newddd.add_requires("ccc = 3.0") unfixed = (newddd,) -# ELN scenario packages. The "shipped repo" will contain only -# epa and epc. The "buildroot repo" will contain all four +# ELN scenario packages epa = rpmfluff.SimpleRpmBuild("epa", "1.0", "1", ["x86_64"]) epb = rpmfluff.SimpleRpmBuild("epb", "1.0", "1", ["x86_64"]) epc = rpmfluff.SimpleRpmBuild("epc", "1.0", "1", ["x86_64"]) epd = rpmfluff.SimpleRpmBuild("epd", "1.0", "1", ["x86_64"]) -alleln = (epa, epb, epc, epd) -shipeln = (epa, epc) -newepc = rpmfluff.SimpleRpmBuild("epc", "2.0", "1", ["x86_64"]) -# these will both be broken by the new epc, but only epa is in the -# "shipped repo", epb is not -epa.add_requires("epc = 1.0") -epb.add_requires("epc = 1.0") -# this requirement can only be satisfied in the buildroot repo, we -# should not report that as an error -newepc.add_requires("epd = 1.0") +epe = rpmfluff.SimpleRpmBuild("epe", "1.0", "1", ["x86_64"]) +epf = rpmfluff.SimpleRpmBuild("epe", "1.0", "1", ["x86_64"]) +alleln = (epa, epb, epc, epd, epf) +baseeln = (epa, epb) +exteln = (epc,) +crbeln = (epd, epe) +rooteln = (epf,) -for pkg in allbase + allupd + allnew + unfixed + alleln + (newepc,): +newepa = rpmfluff.SimpleRpmBuild("epa", "2.0", "1", ["x86_64"]) +newepb = rpmfluff.SimpleRpmBuild("epb", "2.0", "1", ["x86_64"]) +newepd = rpmfluff.SimpleRpmBuild("epd", "2.0", "1", ["x86_64"]) +neweln = (newepa, newepb, newepd) + +# these will both be broken by the new epa, but epf should be ignored +# as it's buildroot-only +epe.add_requires("epa = 1.0") +epf.add_requires("epa = 1.0") +# this is invalid as baseos cannot depend on extras, should be caught +newepb.add_requires("epc") +# this is fine +newepd.add_requires("epa") + +for pkg in allbase + allupd + allnew + unfixed + alleln + neweln: pkg.addVendor("Fedora Project") pkg.addPackager("Fedora Project") @@ -115,16 +125,25 @@ unfixed = rpmfluff.yumrepobuild.YumRepoBuild(unfixed) unfixed.repoDir = "unfixed" updates = rpmfluff.yumrepobuild.YumRepoBuild(allupd) updates.repoDir = "updates" -elnbase = rpmfluff.yumrepobuild.YumRepoBuild(shipeln) -elnbase.repoDir = "elnbase" -elnroot = rpmfluff.yumrepobuild.YumRepoBuild(alleln) -elnroot.repoDir = "elnroot" -elnnew = rpmfluff.yumrepobuild.YumRepoBuild((newepc,)) +elnbase = rpmfluff.yumrepobuild.YumRepoBuild(baseeln) +elnbase.repoDir = "eln/BaseOS" +elnext = rpmfluff.yumrepobuild.YumRepoBuild(exteln) +elnext.repoDir = "eln/Extras" +elncrb = rpmfluff.yumrepobuild.YumRepoBuild(crbeln) +elncrb.repoDir = "eln/CRB" +elnapp = rpmfluff.yumrepobuild.YumRepoBuild([]) +elnapp.repoDir = "eln/AppStream" +elnroot = rpmfluff.yumrepobuild.YumRepoBuild(rooteln) +elnroot.repoDir = "eln/Buildroot" +elnnew = rpmfluff.yumrepobuild.YumRepoBuild(neweln) elnnew.repoDir = "elnnew" empty = rpmfluff.yumrepobuild.YumRepoBuild([]) empty.repoDir = "empty" -alldirs = [r.repoDir for r in (base, new, unfixed, updates, elnbase, elnroot, elnnew, empty)] +alldirs = [ + r.repoDir + for r in (base, new, unfixed, updates, elnbase, elnext, elncrb, elnapp, elnroot, elnnew, empty) +] def cleanup(repos=True): @@ -140,14 +159,18 @@ def cleanup(repos=True): cleanup() for _dir in alldirs: - os.mkdir(_dir) + os.makedirs(_dir) base.make("x86_64", "i686") new.make("x86_64") unfixed.make("x86_64") updates.make("x86_64") elnbase.make("x86_64") +elnext.make("x86_64") +elncrb.make("x86_64") +elnapp.make("x86_64") elnroot.make("x86_64") elnnew.make("x86_64") empty.make() + cleanup(repos=False) diff --git a/tests/testdata/repos/new/111-3.0-1.x86_64.rpm b/tests/testdata/repos/new/111-3.0-1.x86_64.rpm index 12aa4177676cf792e834ea86d03238d262fd8319..96cd37d48cbed117452f938e6533c82e2cd3eab0 100644 GIT binary patch delta 185 zcmX?Uc+zmfgL;z`6H{{oqa=gWG~+Z&^Az(WGXskh6Jt|j<3z*M6k`iB!z7bbQzHfw zV>2_u#H6%D^OTe{%ak;;R0C6E zlVk$}BZFj9L$hQC5MVdlf7X4%`VBnEyvt)MB!w**vo|L&eh^~GVikU}IYcCbk=?@F l(A><-V)J29O(ubtCuNR*wW>4c@jWD6q$^VDPp5MVdVkA1ay?%$ZxE7rV-pX#!k(SLIS;|C#@%uiKEH;0I1FtVGQ lSXx*Z8E!r-s>vjv=Y6ptdhxxFcFFPHr_2{_ocu@pEC4J(JpTXy diff --git a/tests/testdata/repos/new/222-3.0-1.x86_64.rpm b/tests/testdata/repos/new/222-3.0-1.x86_64.rpm index 1f3796c8748aeb9d1bf6d916287406df39057f82..6663fc865b8d058e2fd9d897ccda27e7e79a4aa1 100644 GIT binary patch delta 185 zcmX?Vc+_yhgL<=6Geb+$G&2*^q$ET0KM1j8u?j!g93qm!$Zlb7 kXl`a^v3b9!CX>MJ7YDnu)oR{oR;+X5Is0VFQ zNOUMPDv^lq+u;ru*GXt1t}RF4RxsrNG!ioq18S#LKp01wv@j_lNxL9GE6}-+F-cAt zLWNRt6EPqqBvTe*V-T4l2dySXU+S3I$nF5r0=~-nL*aS kC7p85%ZG#{B_&Cvo-T|Y`(m#B9$pT;^0(3Tm(S|)2P-){U;qFB delta 185 zcmdmKxYKaLgZkto<1{lv3v(ljBm)Dpq%?B_(=-DU69cnEBTMsS3k$O(qm)$hl;o6TOG6X0#MD#^b5r9a1LG76!xRGx;}m0aqvRwL(-f0rb3@D2 zq~t{Nlw{Ln3zI|!5MWn)e=t6+<=tYbY%BKpD{k#zJi0l7@q-Xc=BKJ7n?pn*7}?ED lEG;aI3^s2T)npRb|6oR~$Rvq5Yroyw($C>)HTjMBSpd`%J}UqK diff --git a/tests/testdata/repos/new/ccc-3.0-1.x86_64.rpm b/tests/testdata/repos/new/ccc-3.0-1.x86_64.rpm index 940afd37718180b1a27570cf45493264b0c9d455..5ce93b6f9ea583a64fc62224e886e73c7a901595 100644 GIT binary patch delta 185 zcmdmKxYKaLgZi{&Q*&cei&PU6BcoI^<21wML`$R8L{mf4L{k$(qr_CBG}FW+a{~qg z3xlL2^CWXqV`B?LOG5)gBLhQ2BV%(TlN3`kBU58j3o}b|^Tbqh)5O%fjAL&H>y zL<<9xM3WSQq~sI^5MWnyw3DvWI1{p=^WtjL7w>;CDsE0-{2;`V#VY({bBIU;BfEvU lp}Cov#pcbTnoI%`FIm_0R<*c&s`~RGpyuDq$#2BZ0sw%!J177E delta 185 zcmWl`J8D8f6aY}42zDZ3h^=KBxpU`tr*R7+SXg@J2iAh12<{*VDFRkONSo$W7IwCQ z^igmDB9avZ&)JK;*j&~C76TJliV}?xPJ3tBuyPTFH|#{rF4<6FLmpj5v_2=TRSH2v zj-ZhkWT3>LBt-~WFlkRZQ$mbRMu^G=t~}Jcjd^oBxV?9Fhu5(Em=(QpQrug$>EH5L kj@sj*Zj~cKD9fjpYO}wQ!{4vZ(OIm|i=Wl$?fU%v4;_6xcK`qY diff --git a/tests/testdata/repos/new/eee-3.0-1.x86_64.rpm b/tests/testdata/repos/new/eee-3.0-1.x86_64.rpm index a289fd6ba7cd03e44cf0450bb02987b27d748bbc..f1be63ba3f1795851ddb54f2d5d51d58efd3a327 100644 GIT binary patch delta 185 zcmdmKxYKaLgL>oCG;@n&V`DRuGz+7&6oV8KGfQLBRI}71Q_Cca6bp0XgQ<#6(LI z^W;R+R6~nIOAB)b5MWniDX=Vlpp}%oZbPb<9BVpb(B=fj4?--NpQ?^-4iSl9WH&dl kw6HKT+`L&-lSx30hyT*i9}b_kX!88A2$!8S`HlEl00KKXw*UYD diff --git a/tests/testdata/repos/new/fff-3.0-1.x86_64.rpm b/tests/testdata/repos/new/fff-3.0-1.x86_64.rpm index 8709ce17e73726218156f0ed8969e354d3423c34..83376e12ce26fd3a8de953f16898f35e6c58c327 100644 GIT binary patch delta 185 zcmX?Vc+_yhgZkv;#3TdDB$Fh|Br|ifBr|g(Q{!aIMDx^?6eAN0^JIfmqa+KXBvS@c zOJj?)w4@XxGXpaVqZA`Ui{wQxo$POG8UTi!{p= zixi_I^CXM3M9X9b5Mb9${?o`a{hHy71kL-0?|orqRNtJy_(6yzi&gl^<`9t-Ms^Ex kLvu4Ti_QB*HJJn?ryZ7i@kz|zExD#(ow>5*SN(NhZK)etK>H72kpz*csgF%w%aWIb9$Q9&S0 z!Zzj*DFHB&i45W}*eb+IoUo=+0&wf3d;2iio_`OY`orC9`PCj2@AYHx+wV;O=1o1m jh()&|tBO$nT;8;MtI^Bro7-HU-QR`vaq;mxc5 diff --git a/tests/testdata/repos/new/ggg-3.0-1.x86_64.rpm b/tests/testdata/repos/new/ggg-3.0-1.x86_64.rpm index e0082d2d4316e8db50f46bae113849996c6cf9cc..417c532f26251b2a59769826bbe5a8007f87eda6 100644 GIT binary patch delta 185 zcmdmKxYKaLgL)GSGeh$vb8~|fLo*Ab#3TcY6hjLG3v){oQ{!Yaa|;Voi!?LyG;;>S z3o~;IQ{&WB%alY@ zi)3SSqr^mW3xh-k5MWnil7HW&y=3+ZmEFwFu8!J__ckXmeh^~GVikU}IYcCak=?@F k(A><-V)JHEO(uaq;fFO&3e7F#a=8{=cyv<8)i)0g11A`=U15-;26LSM&%d|AJ)D&aGw8Ufsb8|~$GvibPQxk@y zBvVsULz7e^%hWU@%cN9u149E7V@q>O3xi~HQ?oR)lr#eiv&6JiOQYmOQ**<##Kc4k zLrb$n6BBb26Js+55MWnas;T#=u1V5uzI@}`XK&0H%Qh!4eh^~G{8V*xbBIU;BfGhY lrGwGAYN;dP&hx3JbTI0R5aL`Q3C~?q zIvABPhCI_vP3eFr=E>^#ry)x9fGDXB=#yUXev)FI%sg3uY8-}f+%OdP5x=0gh=rn2 z7Q+zmL{UN=P_r^e zHGu*I$V1J$vItMHe8Dp$T_twSku;X)j8SMzKFXv3!M;CKYHcRj7 z?uB68-CAp{N!nU#jJCUot#mA*dyuUK|9#U48%GAQN87AnXx(+$F70$!-YK2!@0Z3h zQ%96Lf>KCFeLH%_NRlK;k|arNyH_sgnq&E*WIkKkH`~H1r^Ed$-fLGw`<`_4d5pGQ zk89Z^NifD3V~nwE?QXMf;z*;r7do5nM(S>pj(W2>U(SBF%UhFeiT4A zb%j%G*k)Uoh5}-D4u&Y}JPnH!ETx_V;wWUmRUwUX%wl8?#^HnjU_J0GvMuT zkRo}ofUz9}+q7W#zIPeeJsyK?N#v+O7WIDgxUzKnW@P_abIfABDS9E?g*zu`%&~~FV(kb84*&Z(#Z;TQ)jNOBG!Dr|Dn%BOE zC#auP;uh!h4Ta>aGB0s~T(=OKVR3MVJd zZJxoX2^1he9%|l|MF8{Uno>#!Bx)u*n0Yb+!4ww4DKN&=fj=iw<0w(Pv%JRC@eE4B zbKhTs2E{eh?#oCgZCUzS`{pf9`kux%8)S4rpAxr6JSCnny5=NhkUEFyn)f4g zn6kwj>+XeM-Q8Mitx4KiYwW$)_(A%8+vSuIx8~DPzwla2Bc#_#CvB6=VL91+cCqKL z*U!gnY^@nJYCeLL#Wzlq6@`S)Mh)MRNs=TO8!6DgZ?FYEq{^+C&>qlr=LZw{&jHo2nBX)&USxshN^Z2>J`NoBpM5ZphAWd#92| z0d%KQCB+75ZQC*^M$n5RAj&!~!XkxAg~x$75*ZLsNTVF97?*);S@3t=kUF+l_W nG&sfWN^%6{H8-`;d9>ZRSj5ymTj(uX3yGMWnjvCwI*EX3t&#IW diff --git a/tests/testdata/repos/new/repodata/4f693bcdc44f61c53c77e39ee300085d9e54b731fb75a9b664a8e0b9f6516c09-other.xml.zst b/tests/testdata/repos/new/repodata/4f693bcdc44f61c53c77e39ee300085d9e54b731fb75a9b664a8e0b9f6516c09-other.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..5272993e1170a15ec430141cc82cf3f77e4ed171 GIT binary patch literal 580 zcmV-K0=xYvwJ-euVBHY_CN6&=Fm3CMYu`b(%YG3Q0kKuaCt+p>h6~3vm?8nj7tv7w{m%Ed&V^U;e zd4Qk=03&fyAb#lwZwN|BKP~(DM-m}l@edJFF%i);97!?&c^)Py5RKz8f%<6~dFF8z z0E~k41P~S&lCm@n>3H)fDTOAbaT*Yjmq3okM8P7i^>o^%yV$yBiz}VmIli4NA8+jM z=S~&?jAYS`r_m%J0Y*~lDYw=(P0BwlQBnb=SR{Z5o+aSnxZ)js;_*WZ$6&; zPr2^)CDo^F?ihSf;Zmonx_FtA)4jE04yD3&O}biFjtnZ@#w$Xp)>^QA-Hhy$+p?xg zwP)WjjDA{1o_U;PS(dn@WYu>0Wae1?HAnV3Hpy>izd9+S>J}N}h0L9cOS)4k&N+GY z$`$ub2i;29T;ECuS1w-Yt?xa*eviu6;?)SD)ArK6@y7rE)p}Kg&+$RU;?%i2ThG>a z%)L_inSvV?AOORm*~K&H(1|8U>BWSo0}@e~4v;Xy)B%YoOb199Vd{X1n3xXQjyPvBMsD-I8L z0A>JM0IeE#6I-a1Dqd%b(f=fEs+;g1WojoSWADR_Wtycm7zhzXaafo&i^LfVp;tsP zi8WbmP5hBqXpV4%g@$NYfHWM5L_lORIWUU^;&?PDl8L0@a7W`6hlPM)fB}L6voIiy zme3Ga%t4%4APEhLf-@+NM}vSONg?#=aC1%Q)ty6!h?%-Rlk(M8FRwmgGg94BW3M!+ z#uhEZJ@m`R$K@_u;E-O1_ofxaQ{p%NM>3DAyn=Sp5a21}DiRY~ez40A&w(i#FWTwbY zeNx%VRo+33>3doWrDbl6%JsDOGDrDqt@_5v%FkMhsYG;aR95LqkujY*sd<03KJT+C zLbU1v3&}*%aJZxK2?m4FI2BVe#8A7p#D z_qM!k3oS#mmetDC{9MoFdaLy6q`Pm5n$mULklpI3erh`I?&nT=zsrOTGZ7$g;}#Bs p2Jjl04oF0q10;-02PC4*0TM>0114fLACf8m*|ltnW`ND&M*+W;?&tsj diff --git a/tests/testdata/repos/new/repodata/cf45583b0c95946ca4ca3d567a3da5db1183158763f9b2dc006bc980a91f7393-filelists.xml.zst b/tests/testdata/repos/new/repodata/cf45583b0c95946ca4ca3d567a3da5db1183158763f9b2dc006bc980a91f7393-filelists.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..0581c189c82457df320e439359768029864f9261 GIT binary patch literal 499 zcmVcHyqes%u+`~$)V-W7o5dRpgovUzEKHh3@{C33jVLCu zll7haBeCF*c!UKeDY*lIgV#Zk5EpGGM0n6Y*0y;~*n|36ZThuJ49JBix`5+Fdsnb0u<8al!U p`3g*?0}xTp0T4!}0}@fp0T4!}114g0ACe*e+3jo!XMoLOL;)Lj>eT=M literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/new/repodata/d6dae028f2d94a20a5ada403a89d418b7d31c646d2350605999882725a5b0862-other.xml.zst b/tests/testdata/repos/new/repodata/d6dae028f2d94a20a5ada403a89d418b7d31c646d2350605999882725a5b0862-other.xml.zst deleted file mode 100644 index a2b6b67124fccf94eb7eafa37f4ff980ce2fe6c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 581 zcmV-L0=oSuwJ-euVC4}2cCLUSFm3CMYu_jex@x7}jBV$RC zjpYG?766Rok^=EdKX^k>O8RNp&p(m~`HFvtkcx?jrr}7E0m$<(Nr7k_j|tRI%g8g2 zvjAWeq$hx|z>t)sX-LPLM@cC(DUH*Bh`a=HJSGYj0SmfpGET@1%IKDh>vT=`^s%Uv zIcxQgY2;)9z(^L|cp6Ot5?~~yp5oorG%5eIL`emdVj%%U@GJoj#})5@JbK~{-jNOj zk0SuRbATGgQAkR}VV;Oai{tpEX~vVJNpXAxC8bzNiM#|#Dk+RRkVgxI02qmJ1HXx+ zFdk`?R0C7Bb#RqpZ1tVnzVH0yOu9SI$6n-(3TK1N;X|fs$;k6t_iFAv`4&Dae|Pa0 zo81mh`PhT6x;sL)`|HaOvWL8Hn?lw6x!KP1x%rsaE(f*2wI)SQk$ceQ)4S(C5NN|}3yZ9>&lr{pCew?4U19V_!>+|>WSQq|_GvbJ)W z<8?lJ_L5DXQ^)JEITRo;!=ddnIsn25Q3oKRFdcv}Lev3>C`1QH7$J24h?uAk36x2R Tg4Y)7#Q5ejYdIFr#b!IqJ6jx^ diff --git a/tests/testdata/repos/new/repodata/repomd.xml b/tests/testdata/repos/new/repodata/repomd.xml index 2ca5748..c369103 100644 --- a/tests/testdata/repos/new/repodata/repomd.xml +++ b/tests/testdata/repos/new/repodata/repomd.xml @@ -1,28 +1,28 @@ - 1777498821 + 1778717669 - 182e2add8c3d3069057852ed9944419578aa72b31eb9233b18b6ce68fa86ba05 - 4ffb8600b26cbe3f260b10f2f7c35e17c92839fe66e5f1f13e37ec170f4d0d16 - - 1777498821 - 1069 + 0a7860c188784cab59dcc483eea7c38d8e9da287f45492897b95bd1a425da7ce + 2ba4a2dbf3603d8fde7bd5d1595d18058f834b485a9611f49e18acca29b3cc61 + + 1778717669 + 1067 7430 - 8e6cd282fee67920e9fd5728c68c86ad8d8ca56f9e8db935bd9358e22f4b86a8 - 601f4c051e7fb1541e74b63516ad2f5fceecafae40b02a15bef878f1e941b159 - - 1777498821 + cf45583b0c95946ca4ca3d567a3da5db1183158763f9b2dc006bc980a91f7393 + 69839c5fe82af86f9d68cf88757f8886943d9d0ca5387636315eb27330670e7c + + 1778717669 499 1245 - d6dae028f2d94a20a5ada403a89d418b7d31c646d2350605999882725a5b0862 - bfbc10574abc73bf3586a122246953f8073cde56afb8b4470d856ffe0d7823b0 - - 1777498821 - 581 + 4f693bcdc44f61c53c77e39ee300085d9e54b731fb75a9b664a8e0b9f6516c09 + c5f2112ab0f5b051aa8dc39e900a07ac7ba66294f08f144708bba996cb5c7881 + + 1778717669 + 580 2025 diff --git a/tests/testdata/repos/unfixed/ddd-3.0-1.x86_64.rpm b/tests/testdata/repos/unfixed/ddd-3.0-1.x86_64.rpm index 005aac113a7ac76e50aeece70e4aa55cf65a6960..eee3a3c3cf8ed8044acf04611e2ae902d0997d06 100644 GIT binary patch delta 185 zcmX?Vc+_yhgZfkxQ_DmHL({ZmgVaO=%T&u`lhh>h6l0_0L`yRhW7Ficq@*-6Lo)_T z6EkzmLvjOnoI)Q#f$4JYsBWA_#oE2T42wG$v?!;0syXIId1>} delta 185 zcmX?Vc+_yhgL(r~lQiR0BV&Wal$5lTBtxT=WK%O^Gh-uj69e-k6HD_Ha|^>%i)4l* zOVeb-WJ6;E%M?R{WFrd`LqiKwGmBKCq!c3y6BC2fBoi~!)HH)6OXHN(B-3O=(_}-V zWFu1(OH0EflTviEuh;O>_M+eh2`A57LOk$p163MT!|EZ= zUOVa2*`#K?)Qp#UwWAMlt0QR#{eoMyJIKWI+?b8m%AjDtqIL%fL2h?%_YSPw5os8? zG*MZWE00cK67|X_1L<%vf?SL*M3E3dni!>GNL0^!xif2#%vC#|2E@b7c)i-$H$a4h z4|jqWI=t^Bh5zvgg&&ckPMT7{bMK*@t<;IwUOVa2*)-!7ngIw55VSMY=?Ph%TOF%i bO-u{@f~gY~S_A;eSpKtXvMDnIY!)gCSyN|Q diff --git a/tests/testdata/repos/unfixed/repodata/9d54f4c3d3ab7c943b7e15193e2544bcb82bf7b2e8408ee3167134b0a453255d-filelists.xml.zst b/tests/testdata/repos/unfixed/repodata/9d54f4c3d3ab7c943b7e15193e2544bcb82bf7b2e8408ee3167134b0a453255d-filelists.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..ec47fbcd8517a4d34c3dcb191f7c66f7ead74552 GIT binary patch literal 225 zcmV<703QD+wJ-euV8sRi@{cheU}y6%P>bViSP+|TS)8R-LhOcS@%_41NXYQ{sY+R=Bo)3Mq)f54sEA)umpZp_B(WHDIS(+&Y0=Z-P9d&VobCy6L> zDQrm)1tw84!&-!Y#gGuhm#7|ro|Iw%iChkudZrXy&{aZkLi~1d9uf^V85&!taA|B78PKuB~b1$Nut(1A#UOVa2DVy;M%>V`n3fdj&j0#wvI~}TB bRZQ#r0aNBFv;+XjSpKtXvMDnIY!)gCNe^c` literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/unfixed/repodata/a583ea09de5b85171eb9110dacfd240e527828cff25324ce894d3dd9c80cf961-other.xml.zst b/tests/testdata/repos/unfixed/repodata/a583ea09de5b85171eb9110dacfd240e527828cff25324ce894d3dd9c80cf961-other.xml.zst deleted file mode 100644 index 8d15cece3fb98c7e6765a3906d7e67b834ff2fd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305 zcmV-10nYv?wJ-euU_}W4hLuAiKxwuCj0u3IMhYY`BlG_McPn_87h0k4@73ge(iz1? z7X&*1IRG~RwY}?KPV+}zp*gZ?v$C86z-py9E~a&D+qFG=s#3^^0{A%y4iGp_vvMlu zFFyowoU~eGzp&P|1wa8zLRuK;&m})N%KPP&MtZ~NAfe+hS!5?kLXzZr66yWp(A|NI zeEf0rYEobe84*K{i=SE{8(VfA6gA+OQL1Xa6SaPtO-aX)qxISHLllnLFDyTfl%&`% zv};7XGzrbKainC{%kIwcub#_Nl5k{E*Y@nGN*!cG4l*JKbycfbut&u2J+Da;g@GKu zwlBluA<7<$sFUHM5_t=|dV7JVu7IePVV@4{3Bb?Gu4 z&Mb{Pt4@4B(iN2qw2N%mcs8C?!?WtlcHW3zwr+*Bo=|!fyvc=>UYNDXaYT{fm>xzW z89B*Dv|#@E1r#N0q(*Ea**H&xj^mi7$Vkq_yd)bbqlOVB$vkH;cyK4@17h1Dh65=~ zFARxKMdppW>Tf%q*8-g!yC~J`|(~C zvnH9UTJy`eQmjq#jLaM_S+4@av$B@p*{j|+ARs~lDJu{1QUO0gAT<}KJ^=8+Lnv_q zNWsHEM~rAND9lJ>3B)rn2Jgf?egnkvoPpScft37*MBq1ow3mh9&mArU-1BPQf+TnC znbgY|SV_CF0a?DR0SlPtg!ki>up{Bx++VZP?@&n_POWcXp?apx#n?sGmO0?I>|zkI MTNycy*-6AX19N0K_W%F@ diff --git a/tests/testdata/repos/unfixed/repodata/dd80d9c03852999e37b04db876c82b0483a6e906c5884b4561d83a97d7c341c7-primary.xml.zst b/tests/testdata/repos/unfixed/repodata/dd80d9c03852999e37b04db876c82b0483a6e906c5884b4561d83a97d7c341c7-primary.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..2e0a2b65df849cfcd52f93d1d8f8a84639987186 GIT binary patch literal 628 zcmV-)0*n19wJ-euU|kacR;YI*5N*l>Cj-lqAm&CpQeBFm?~nx8+B@J@rL;!IF8Rt&TvCBt)~pyCusKuiuvJk=!werJjNoqJw^v`H4O#>mxd=ufqFp|JCIWS7hOAHg82$?5>k^JWk2N3S$bWGTGh|xd_ z(+f|;ry_I4UG=wpQ5<*oAMJ}fDvm0xf3T*oknkQ`A7?c{?QPxN$;*)5I#GKSg;^|$ zvyf7{oBmR5)tO$)@8Z6MPq9YrRpP~u+WYZd z6|)9uRJG=paiv&`6MhyciD`S$KG)8gZ zbpbm7IRG~R*Qej7SYv+ji^fc@MwKSU0;+pyM@F5fi~ahvo?h!5Pog10aDdP;s?xNw zK6gu8$7&^p^$R>vSHcOr=j9exJ74IGX8AVeRZ>D=idUFl}EYNca-9zW(lkS#- zALe(QQnaYpIi7YM86WvVdd1B=)EacOEWHiq$W9+sr;@enIK9Q)lGoAt1@6|7N?ScU z%*WG9lhDAcBbAnO&pA6j<(1nTq%Z-GU!T^~YngLA%sC$BxOAmjz{u0B!PY3sV_e6- zKDiyzlE(-mZe*aWOn#~;zh2<&R6yLxz;6e*1_uBMn@Jf3udP)lrZ=BilVh2=*ld*< DK~9l^ literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/unfixed/repodata/repomd.xml b/tests/testdata/repos/unfixed/repodata/repomd.xml index 1d5c82a..7688873 100644 --- a/tests/testdata/repos/unfixed/repodata/repomd.xml +++ b/tests/testdata/repos/unfixed/repodata/repomd.xml @@ -1,27 +1,27 @@ - 1777498822 + 1778717669 - daa25dfd3c818ca6b5104612d827dac24e70a2050986ed49457124116013f4ef - ee07278548ed0fee3569e6b1aa00a4488ef82c0216d5fb835899edca81d00ebe - - 1777498822 - 626 + dd80d9c03852999e37b04db876c82b0483a6e906c5884b4561d83a97d7c341c7 + 291264d5bc3e5102ea3553e1f3a8017e7bed89c574fde750f0247c85c2003448 + + 1778717669 + 628 1265 - 77dfe7c593c3e37af3f924516b5aa25cc512a5b8070f75fbeb4b1e844973835b - 7e2dfb6357481ec47ff798fc40501850c014472d258cccc9ac49ec9c1d176acb - - 1777498822 + 9d54f4c3d3ab7c943b7e15193e2544bcb82bf7b2e8408ee3167134b0a453255d + 207660f59451194f04a8c198b5244310cf182ecdbaaae5e819f18ad3851acf1d + + 1778717669 225 285 - a583ea09de5b85171eb9110dacfd240e527828cff25324ce894d3dd9c80cf961 - 747fadb7b8374294f06c6ed1c48f21a25d7ac797625c574d13adf81377341014 - - 1777498822 + ef5302dc1a621cb60e1087af579f4e2bb66e668033b107b8706a39f2c37f8026 + 0e8c0475f1c246f3d2dbb831a437572872bb464a55e356b01808ad4009eec9ba + + 1778717669 305 393 diff --git a/tests/testdata/repos/updates/aaa-2.0-1.x86_64.rpm b/tests/testdata/repos/updates/aaa-2.0-1.x86_64.rpm index 942fadc6769a78c8595cc514b16e63b9ad23a101..7a9474ba1ce92b3f34f1a4f0736f1b6e3e22a08c 100644 GIT binary patch delta 185 zcmdmKxYKaLgZh+2;}i?SRI_BWWHS@9G!sh`L$g$KgA~gYv!q1JWRtYy#3WNAQwxS9 z!&I}BBn#sdOGATH3$s*nBXbjTgESK(gVaRJq+}BlW6NZtWWyvA%fvJ@V@p$$#57|g zV+#WV3**!zbK@ii5MWn4`Qg0!PPWx2g!hL1Keg`zBg^Il#t%X)S**fOH;0HsFtS^i l8=9M$S#I7es>vkqIdjVVnDsAx-R~SY@T}2QVe%XCvjDUTJ;DG0 delta 185 zcmWl`Jqtlm7y#gVrK}Q}jklZuVSlzU|rQbdQ(WAbyqd!}s`*^~(LY fU?f;8M3z;OT=8`N3@+VmJ?TX2X=B@2JgUbZ9Ex1UGm{%|tod>M}BT`_45jkUH z$g>odJqP715=(@@MG&#hJ4Z3|j=WJ+d1&;$fA*;~uea6UbH4uCCb}FY_vhNUo?grM jc1#-HDMyr*hfepY_0pf-h9ApGdTQ=|->Qqv-|P7wNo_jJ delta 185 zcmX?Vc+_yhgZdOpJGz$ZRL<7^b zv?R;K6myGYv*c6;5MbAB_@2AB??B|6La%8tYhQ^o3T{qd{2;`V`KjvI<`9t-Ms{-( lOA8Alqs{w8HJJqVD@ONrzkK)ew@v&lrTm`2$v?!;0s#FlKF9z7 diff --git a/tests/testdata/repos/updates/ccc-2.0-1.x86_64.rpm b/tests/testdata/repos/updates/ccc-2.0-1.x86_64.rpm index 5182af8ab95fb52a7f5493fa2c4abe83322b7a5f..193438695e1781c1ff6c981825422e191ad7f146 100644 GIT binary patch delta 185 zcmdmKxYKaLgZkt&i=-rDgA~g&bJIk#q{I}X6iYKh%d{kOV?zT|19M~3Br`)p3sVO3 z#N;$%b7RX?gS0fu6iZVBBa_rLGc!vgvlI&hb3=18^E6Wf0|Qe7Gc&V9Q*$Ge#Kh#} z6^}5CBlFA;mVN1dT+H?9R>3?D7rNA!fz^wACcot{`L9<;m+7|b jKffk5#^60bSvJ}aPap4x$+){8^nU8|<8J)6JT-SWZ;U-9 diff --git a/tests/testdata/repos/updates/ddd-2.0-1.x86_64.rpm b/tests/testdata/repos/updates/ddd-2.0-1.x86_64.rpm index 34a87175edad9757b4624e42a0cbb4e32bb360f2..3cd07d69dfae60e47d92619b35df25e24f470cf3 100644 GIT binary patch delta 185 zcmX?Vc+_yhgL<$M6*O=GmFF&GsD!>v+qCi(vA35p-rAhN_(6yzi&gmP<`9t-Ms^Ex lLvu4T%gy^mHJJo1ONSpmBQ_=P;Y0PlSts5^O#UH$764xvKOq1B delta 185 zcmX?Vc+_yhgL*?V!^Fgt6k|gZLsOGfL(`<>L?cU+M9Y-av_umVLsN6p6azzZ%QS|h z#6%M#b2Br`WFwPQ%T%LOQ-fqvLrVh#!_>5t6r&_d!gI#`cEW6vO&<93Adl zRRBf+L;#GUCy7Pl90~};P-H&Ai{{2b2siB9JOe@SH~a#@4G)ARQ4l1c(KHGanMGkd z4%0A+@=7uf1%v>400RUCC?=M~4|@57)R0hI4id)k2}fZ(1P%d64GKlaCmf_GD*B-D z=WtE|fmkzW?}4JC9efZoqxcM74oa-A{d$Qt-CyOO+QH}U)Ni)VU+>D$@%nOpxN1o@ zb(_Iu9S}k_|CO2w>h65!>((m6=~{x?Dy8iGRW?^rxl)44@|{xIrtdb$npBSIGqz7c zS6%I-Z>_e)>k^d6p@2Y8LQ#3g2?(ZP66KX-BJMtwGMFUKZM>GvUjORwy|LxiH}uzj znH_7M&Y(-_c~3Xtd@r@@?v<1Ft)DJ)GR8^_Rqe^0@{^ z5PSk)09XK6017%}3btGxy2j4z>oslM(P)6A1%jbW8;5UjLo+0)!jqlnKNN|-;u|Ec zm`EVUqbLE8IUQ{rpyx43JlP}f%xHmN4CqT3Bq(UpfE*q*^hsBtw1FarL*yUQ^Oy`Q z0?r^XAAs~xL4uqJL7PbAObMq(^n3$irxjJ&JReEAilt5DACj&%PDhYWi})haf~uI;z>B-@3Gk&WL*_w1Dgf}t$fF&)rBN-%WyZCh($lr}%v zld8ljR!Ss+*#LM%t@sD>;K>tw6bzp1k#}aKxI1&tm^n9>tfFcWMz-(Ndk)z`?$>Q$ z{?1yIil2hMb}>saak04F?Hhfal=3|n{g?4}>~Cg~+>ayUS}9jfwU50-=-W{71`Yr- pK*xgu3IQDt2si|E03d8)y-nCm$|!hktvWHi`OKOe%gn`QtIP-y&j$bi diff --git a/tests/testdata/repos/updates/repodata/63c56609259c2a5620e4da4ccf34898028efb88337163d5b44e75a95e684d91a-primary.xml.zst b/tests/testdata/repos/updates/repodata/63c56609259c2a5620e4da4ccf34898028efb88337163d5b44e75a95e684d91a-primary.xml.zst new file mode 100644 index 0000000000000000000000000000000000000000..ba1613eee40a7c3c9d44885a204fb172e0c778cb GIT binary patch literal 852 zcmV-a1FQTfwJ-euU|kvjmUf;b5N*l>rvp+ZmdP>A#3W7;o}5yYT~3wDJ>8RKz^n=Y zKoxKxnE;ajnE+Ep@24>sJT%8b4hf32MJD~I@Ks6pKioCgoai%auaPt-KZLc{oQF@; zGs@V)(YQb?P2_oaZpzrg(e8d8w?r9RJPlL1IZshoj4qxQn^V1`CA=xtFqJWt1)4Nr zJh^k1{l-gNwh_4`C~{7KvaCmQDk;Jd)>hlL9@E7$&>F@;gF|y15@aWrp0(G2&5&djVitV2=QEI$TdJG8@ z-^VDMI_-P%Ied*G-=ef+;H_0BymbIhCWM%i80X7)7?EuiiqCDO0Y= zCRv(erDrWZ8JlC}wkq}xsWT(L?SD9msod~fJ($Yx`I;(6BQ=^P>#?fo;V6X#K_JU7 zJ7on|K@mj}Jk&L1$7H34IGUh<@O&k`Ly-WcGG&ah#bY(j)5TP7G$7+O5=IA4TW#BV z>7bJ{-2$1m#8qx`?SsSvYUzC*T%^}*jT^JowsSAGuB#n zcXxM}Rlc^1Op?XAQd{XaZ>`-8^H-U3Cig!{ZZe;g_Zcf0MZTVwS>SyB+&x3r#OGRT zt(BRzRv2BreDNyqRRzNNx;~Sjw{V8K``(_ z4FG{^6sg0c?nwTS>>M1tjv4@B2B}7s)Neu}qsGO_4lq$fmUspXbR21niHD4H8}Lev zjS%2Q9TiefzneMQ61GX;R3I2=5hDx?3U{P21Y$F=2k*3b{02zLa|U7y4CLiMSOj(h z2==lt{AGvV0QY+}Z$T<|?U~fu7}%3`V*|2%Sz|0aFhNiX@d%Mogvd3wL5`r2Dox?A|L<& z6i_ai0FnTh0G=??X$=Put#RlvL9r&4gdvr^s)>F`y9Qem{blVnlGfahu=ZL5>4|zq z8DlsaWrSoZ97tcLj4>Q#X6G$Slre_WEOlG+l!e78!)dWK)jxQmnPSaS*HU+&Nt3lx zJ9qgve&X^*#U(+Ja|4uRL0VHuk*#2Cv9tA-G8}@&2p~8-wB{i}KDG3$y#{QJG(pw< z2#ah50S&Er{z8~EK^FHE#RRtIBM_u7`$rL5l?1Ui6NhZgUqF>d&{bJW5{8*^Sr*uu zkD!OWg{sGy#;k%^1wkAfX@V>Yx?R0f#u$z= z3u`X}$KtZJSLLWrIor|E6OWHSjASIgFC1rm>V(bkeRcRe3!FY9oc%a{E|Q%&RZd>y zdnuVGzBi%rNM>GLK7Os$QAY!!6p%~>Kw~&)P4(dDVeKtT%;H+oSMN|{x|C}QlgQS% z^sL3F#MW4st&06a;wy09`5}&4>NfgTj-~GRy{5|1iW*Im(loUf#BC>pTTrHnDga4fcWdMtGt4Jhy$i2ySP4qNPOy>$l( z?(XjH?s56Z(OLS#utHg9jqex8Fh1j(+)PVH^!F(11DS!-lb0w7RB96IbNBAU!z|VRMSflTTX8(x3|D1o2puj^er-pc{(3@wOH!Z7J-hot7scONYpr#ewN@Bm z1F7E6poGFz`YR0D)>0 zsl%l1NdA!Q92~rk8Xhr&RJckyHz5&F`A+^0olH+F&40$6W))zgdGUi%KbMx%^iBuhEr=cuuy%b Z-NhJ)tVQNv+OiOXoZae?2tz_3HGlzvg0v_c#uM6kl<<&gaT1uP@e8O~JOmH{2bGq_FQ9~JIp_q& zBLqT*MABuj+9NFo-B^@%H!Z(d2PJpQb<*m}_4#Y7t$k;!jvu@1O?>uzkEL^`>G~z_ z*jnFp)m94YOiz~Uxf6Dd?Q)SRes0?_bLzgbOpzT^v{iehu)>Kt#S+B!*~!Z-Tlj0W zr-&|%{NfOiO2CU%{R~2SPWbeJ!82h6xHutxZyzRCe3m_mvqVR*p)1a8+5pc`_By5zo P$&ml-BAenFV6zxe{9&+TpUy=!0u z!6#t=S^!r7&Ca|(@?x^l<=G;)*=cb{qXB{z2u5mYarj0z%!Z((bZzhY4@Kgy_y&n9 zCKAWdC`tgNRwgYDPV<a##F1`0J8keLKF}kv^y5&XrP5e%?lz zTFI1(+w$L9>8LZi*qmIi?YG8IM&IR~Y9Zrwtof-Zl?8&KEZR{W&H+j=(k@)L7Gsr` zuk9$Q#3~j_Ac5Kdcsx__4dl_2CkTwL?U85dqqsX=+oF<9*)`)vC;MNI@2;`OenyAx zx%;)*)LVQ?L7()|NFh}7%{f`}wmV+S`DC(LZ=_Oo!}pZM7#ICti>|oL^q=!%91Z|8 qKnDPX5d!J}Ktv&+0{~$Y>uthjQbxgRYt@PA&1cr+SY|FZTV)3Qj@+dH literal 0 HcmV?d00001 diff --git a/tests/testdata/repos/updates/repodata/repomd.xml b/tests/testdata/repos/updates/repodata/repomd.xml index caf3cd5..b217b79 100644 --- a/tests/testdata/repos/updates/repodata/repomd.xml +++ b/tests/testdata/repos/updates/repodata/repomd.xml @@ -1,28 +1,28 @@ - 1777498822 + 1778717669 - 736fcb107df83b5ae000865878a1f670603afb579fbb3179e2ce4d72c9586e48 - a301ab11789be905d36e3f1bf6aa8afe8f62be4dd888781f35f040cda6630ede - - 1777498822 - 847 + 63c56609259c2a5620e4da4ccf34898028efb88337163d5b44e75a95e684d91a + e4fdec66dc3b24723eb9411bdeaef01027f5ba2a7d2d65f0095ab9ddf1d53847 + + 1778717669 + 852 4359 - ca771b7fed377c578d3d9ffd1b856a9c1c0e5192ad31e2d111d1ae2ed978e34c - 92c0e6ce6d1a917a7d9104471513ad2d1699245864e08d8fcb5d78260bf0127c - - 1777498822 - 369 + 3126b56a66fb9df617bc7a7c1182bf8142d919f9852096bb6f61077a40e6ea2b + dfcdc6f2d5453c4a32947c10ef20c3bb4c2f8026e61d31e0615f15e029e8e32d + + 1778717669 + 372 765 - 5f112f5ba0bd830d4f7d2b42a6d57c1041d78b661a423c3e00b0b6072fe3d690 - 981a53e7a783d642baf951a1efc14237eb9f11473cae778d566cada8e1a65c54 - - 1777498822 - 447 + e07157006906a954f6b20bd3998d53515332d76c45c79661ca57763750c7b986 + 012806c92cd1914cdd5705f7e268ab930836875587eba1bc5377d25a55fa485b + + 1778717669 + 448 1209 diff --git a/tests/testdata/test_e2e_devel.txt b/tests/testdata/test_e2e_devel.txt index a6bdf38..79cd11f 100644 --- a/tests/testdata/test_e2e_devel.txt +++ b/tests/testdata/test_e2e_devel.txt @@ -5,9 +5,9 @@ package: hhh-1.0-1.i686 from file://{REPOS}/base ggg(x86-32) New dependency problems in the tested packages themselves: -package: 111-3.0-1.x86_64 from file://{REPOS}/new +package: 111-3.0-1.x86_64 nonexistent -package: 222-3.0-1.x86_64 from file://{REPOS}/new +package: 222-3.0-1.x86_64 aaa = 1.0 Dependencies of other packages that would be FIXED by the tested packages: diff --git a/tests/testdata/test_e2e_devel_onlyerrors.txt b/tests/testdata/test_e2e_devel_onlyerrors.txt index 5ae3407..eb07a99 100644 --- a/tests/testdata/test_e2e_devel_onlyerrors.txt +++ b/tests/testdata/test_e2e_devel_onlyerrors.txt @@ -5,7 +5,7 @@ package: hhh-1.0-1.i686 from file://{REPOS}/base ggg(x86-32) New dependency problems in the tested packages themselves: -package: 111-3.0-1.x86_64 from file://{REPOS}/new +package: 111-3.0-1.x86_64 nonexistent -package: 222-3.0-1.x86_64 from file://{REPOS}/new +package: 222-3.0-1.x86_64 aaa = 1.0 diff --git a/tests/testdata/test_e2e_eln.txt b/tests/testdata/test_e2e_eln.txt index de149e1..031660e 100644 --- a/tests/testdata/test_e2e_eln.txt +++ b/tests/testdata/test_e2e_eln.txt @@ -1,3 +1,7 @@ Dependencies of other packages that would be BROKEN by the tested packages: -package: epa-1.0-1.x86_64 from file://{REPOS}/elnbase - epc = 1.0 +package: epe-1.0-1.x86_64 from http://localhost:5001/CRB + epa = 1.0 + +New dependency problems in the tested packages themselves: +package: epb-2.0-1.x86_64 from BaseOS + epc diff --git a/tests/testdata/test_e2e_updates.txt b/tests/testdata/test_e2e_updates.txt index 224ef22..062ba52 100644 --- a/tests/testdata/test_e2e_updates.txt +++ b/tests/testdata/test_e2e_updates.txt @@ -3,5 +3,5 @@ package: bbb-2.0-1.x86_64 from file://{REPOS}/updates aaa = 2.0 New dependency problems in the tested packages themselves: -package: 111-3.0-1.x86_64 from file://{REPOS}/new +package: 111-3.0-1.x86_64 nonexistent diff --git a/tox.ini b/tox.ini index d96cc57..bc5a1a4 100644 --- a/tox.ini +++ b/tox.ini @@ -7,8 +7,6 @@ deps = -r{toxinidir}/tests.requires commands = coverage run -m pytest {posargs} -setenv = - PYTHONPATH = {toxinidir} [testenv:ci] sitepackages = false deps = @@ -16,11 +14,12 @@ deps = skip_install = true ignore_errors = true commands = - black --check rmdepcheck.py tests/test_rmdepcheck.py tests/testdata/repos/mkrepos.py + black --check rdc-repos rdc-compose src/rmdepcheck tests/test_rmdepcheck.py tests/testdata/repos/mkrepos.py coverage combine coverage report coverage xml diff-cover coverage.xml --fail-under=100 diff-quality --violations=pylint --fail-under=100 - mypy rmdepcheck.py - + mypy src/rmdepcheck +setenv = + PYTHONPATH = {toxinidir}/src diff --git a/tox.requires b/tox.requires index 70d78d6..c25f561 100644 --- a/tox.requires +++ b/tox.requires @@ -4,3 +4,6 @@ diff-cover mypy pylint pytest-cov +requests +types-requests +urllib3