Use a correct EVR sort#4136
Conversation
53934f7 to
5b6a3be
Compare
| curr_vers.get_content(Package.objects) | ||
| .order_by( | ||
| "name", "epoch", "version", "release", "arch" | ||
| ) # why sort by all of these values? lexicographical sort is not "accurate" |
There was a problem hiding this comment.
I have been doing experiments with the "CREATE COLLATION" feature in postgresql.
I think it could be tailored to define a proper "lexicographical" order for these version components.
related pr: pulp/pulp_deb#1335
There was a problem hiding this comment.
RPM versioning has a special ~ and ^ character behavior - is collation flexible enough to handle that?
see:
https://slashterix.wordpress.com/2016/08/06/rpm-version-comparison/
https://github.com/pulp/pulp_rpm/blob/main/pulp_rpm/app/rpm_version.py
There was a problem hiding this comment.
I have been doing experiments with the "CREATE COLLATION" feature in postgresql. I think it could be tailored to define a proper "lexicographical" order for these version components.
related pr: pulp/pulp_deb#1335
Isn't that also dependent on pgres-16?
There was a problem hiding this comment.
Yes it is pg 16 and for the special ~ handling (sorting even before the end of the segment) i needed to trick a little.
I'd love to do a little less of that. But i found no way to either add a custom normalize function to the collation or a way to provide a search_key function to a text field.
2486a36 to
cb6241a
Compare
9c5de07 to
ef509ef
Compare
ef509ef to
2b656f4
Compare
8899d12 to
561b378
Compare
561b378 to
6056f17
Compare
75788be to
5f13c10
Compare
| return "pulp_evr_t" | ||
|
|
||
|
|
||
| class PackageManager(ContentManager): |
There was a problem hiding this comment.
The rationale for getting rid of this is that different implementations of with_age() are not stable when applying additional filters to the queryset. You want the annotation to be the very last thing you do post-filtering to guarantee correctness.
There was a problem hiding this comment.
Also I recall running into issues because we didn't inherit from the Pulpcore-overridden content manager properly. Easier to avoid conflicts this way.
|
|
||
| when_clauses = [When(pk=pk, then=age) for pk, age in age_mapping.items()] | ||
|
|
||
| return qs.annotate(age=Case(*when_clauses, output_field=IntegerField())) |
There was a problem hiding this comment.
As mentioned previously I don't really love this, but it should be "fine" and hopefully it's just a temporary implementation
There was a problem hiding this comment.
Remind us again why this is a temporary implementation?
There was a problem hiding this comment.
Because ideally we have a fix in the database layer that can be shared with Katello. But that's not backportable.
| self.assertEqual(packages[2].release, "1.el8") # age=3 | ||
| self.assertEqual(packages[2].age, 3) | ||
|
|
||
| @skip("The implementation of package age is broken w/r/t '^' and '~' characters") |
There was a problem hiding this comment.
This test passes now
| self.assertIn("4_0", remaining_versions) | ||
| self.assertIn("4+0", remaining_versions) | ||
|
|
||
| @skip("Non-ASCII character handling do not work correctly with current implementation") |
There was a problem hiding this comment.
This test passes now
There was a problem hiding this comment.
Pull Request Overview
This PR fixes a bug in RPM package version comparison by replacing PostgreSQL's built-in EVR (Epoch-Version-Release) sorting with a proper Python-based implementation using the RpmVersion class.
- Removes the PostgreSQL window function approach from
PackageManager.with_age() - Implements a new
annotate_with_age()function inshared_utils.pythat uses proper RPM version sorting - Updates all code locations to use the new annotation function instead of the manager method
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pulp_rpm/app/shared_utils.py | Adds new annotate_with_age() function with proper EVR sorting using RpmVersion |
| pulp_rpm/app/models/package.py | Removes the broken PackageManager.with_age() method and custom manager |
| pulp_rpm/tests/unit/test_package_age.py | Updates all test calls to use new annotation function and removes skip decorators |
| pulp_rpm/app/tasks/prune.py | Updates to use new annotation function |
| pulp_rpm/app/tasks/copy.py | Updates to use new annotation function |
| pulp_rpm/app/models/repository.py | Updates to use new annotation function |
| CHANGES/4124.bugfix | Adds changelog entry describing the bug fix |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| newest age=2, and so on. | ||
|
|
||
| A second partition by architecture is important because there can be packages with | ||
| the same name and verison numbers but they are not interchangeable because they have |
There was a problem hiding this comment.
Corrected spelling of 'verison' to 'version'.
| the same name and verison numbers but they are not interchangeable because they have | |
| the same name and version numbers but they are not interchangeable because they have |
ggainey
left a comment
There was a problem hiding this comment.
Looks like this should address the issue(s) - great work!
Backport to 3.26: 💔 cherry-picking failed — conflicts found❌ Failed to cleanly apply c7bbe48 on top of patchback/backports/3.26/c7bbe48ba247518fe0cd5e840ec2357811fe49bb/pr-4136 Backporting merged PR #4136 into main
🤖 @patchback |
Backport to 3.29: 💚 backport PR created✅ Backport PR branch: Backported as #4166 🤖 @patchback |
Backport to 3.27: 💚 backport PR created✅ Backport PR branch: Backported as #4167 🤖 @patchback |
Backport to 3.32: 💚 backport PR created✅ Backport PR branch: Backported as #4168 🤖 @patchback |
No description provided.