-
Notifications
You must be signed in to change notification settings - Fork 181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix: handle special deb package versions (bsc#1150113) #1412
Conversation
Added JUnit should cover the Java part
|
138fc18
to
4f57ae0
Compare
I do not like this solution. Why do we need to replace - with ~? That will cause trouble, as - is valid in package name and version number but ~ is only valid in version number |
We currently have one solver that is targeting RPM packages. To handle these special Debian packages that have '-' in their version, we replace '-' with a ~ just in the comparing algorithm; for RPM packages, tilde is allowed and is treated as special. |
99% of Debian packages have "-" in their version (e. g. git 1:2.23.0-1). The exception is Debian-native software (e. g. dpkg 1.19.7). I guess you meant "special Debian packages that have '-' in their name". But the fact that you have a '-' in the name or in the version does not mean it's a pre-release version. Furthermore, the \d-\d{8} pattern is completely arbitrary and cannot be relied upon. A few examples of packages which IMHO this PR may fail:
I am attaching to this issue:
If you now run This is what the Debian Policy says: upstream_version This is the main part of the version number. It is usually the version number of the original (“upstream”) package from which the .deb file has been made, if this is applicable. Usually this will be in the same format as that specified by the upstream author(s); however, it may need to be reformatted to fit into the package management system’s format and comparison scheme. The comparison behavior of the package management system with respect to the upstream_version is described below. The upstream_version portion of the version number is mandatory. The upstream_version may contain only alphanumerics [6] and the characters . + - ~ (full stop, plus, hyphen, tilde) and should start with a digit. If there is no debian_revision then hyphens are not allowed. https://www.debian.org/doc/debian-policy/ch-controlfields.html#version It does not say '-' and '~' are equivalent or can be intercharged. By replacing "-" with "~" for some arbitrary pattern, we are making sure we will fail in some corner cases. Please, do not do this. The 0.7% of the cases this PR may fail are enough to give us a lot of headaches and upset customers. Debian packages have their own version comparison algorithm, which is documented in the dpkg manpage: Sorting algorithm The upstream-version and debian-revision parts are compared by the package management system using the same algorithm: The strings are compared from left to right. First the initial part of each string consisting entirely of non-digit characters is determined. These two parts (one of which may be empty) are compared lexically. If a difference is found it is returned. The lexical comparison is a comparison of ASCII values modified so that all the letters sort earlier than all the non-letters and so that a tilde sorts before anything, even the end of a part. For example, the following parts are in sorted order: ‘~~’, ‘~~a’, ‘~’, the empty part, ‘a’. Then the initial part of the remainder of each string which consists entirely of digit characters is determined. The numerical values of these two parts are compared, and any difference found is returned as the result of the comparison. For these purposes an empty string (which can only occur at the end of one or both version strings being compared) counts as zero. These two steps (comparing and removing initial non-digit strings and initial digit strings) are repeated until a difference is found or both strings are exhausted. Note that the purpose of epochs is to allow us to leave behind mistakes in version numbering, and to cope with situations where the version numbering scheme changes. It is not intended to cope with version numbers containing strings of letters which the package management system cannot interpret (such as ‘ALPHA’ or ‘pre-’), or with silly orderings. https://dyn.manpages.debian.org/buster/dpkg-dev/deb-version.7.en.html debversiontrouble-packages.txt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid this will not work, see my comment here: #1412 (comment)
I think correct would be to split at every "-" dash and compare the parts until we find one which is not equal. For RPM there are by definition only 2 (version and release) while debian can have more. |
The latest push fixes everything: I just have to deal with:
This is different from RPM: in Deb "The lexical comparison is a comparison of ASCII values modified so that all the letters sort earlier than all the non-letters" |
354999d
to
b29b792
Compare
This case cannot be handled without knowing if the version is related to an RPM or a deb package. |
@mcalmer please review the algorithm I implemented here: I couldn't find any version that breaks mine and works with your version (and vice-versa). What I propose: let's adopt one of the two solutions, test it with a PTF and stop the fire. Then, create an issue to address the fact that we need a DebVersionComparator as per #1412 (comment) Still to be done:
|
I agree that we should try yours. But you need to adapt also the database compare mechanism. |
14e7b63
to
35f4703
Compare
c2014ca
to
50e2e6f
Compare
This is the test set a fully-compliant implementation must pass: |
Also, will a more complete comparison algorithm require re-importing all the packages in the database? |
50e2e6f
to
a5724e6
Compare
I think that re-importing will not be required. This algorithm is used when comparing packages (e.g. installed vs proposed updates).
I collected all the 43 tests published here and added in our JUnit tests, stripping the epoch from the versions (the comparator of this PR just compares versions, not epoch - that is done before this comparator). My proposal: |
@mbologna have you tested the PSQL version somehow manually ? That would be good to see if both have the same result |
@paususe I have no idea how we could implement a second algorythm. For java it might be possible, but for PSQL we have no identifier which algorithm should be used. We would need to have an extra flag in the EVR type and this would require to change all the existing types . If we have the case that a Debian and a RPM package share the same EVR, we need to split them in 2 with types and re-assign one package. A lot of errors can happen when we try this. |
Unfortunately, a lot of errors will happen if we do not do this. We will need to add some flag in there. Also: why is the version comparison implementation split in a Java part and a DB part? |
For our case, yes: #1412 (comment) Details: grep for
|
AFAIK it was only in PSQL because the algorithm was needed in java, python and perl in the good old times of spacewalk. perl went away and I am not sure if python code use it. Some new code was added which just need that calculation in Java and the Java implementation was born. |
The SP is still also used in the Java part - db queries: https://github.com/uyuni-project/uyuni/blob/master/java/code/src/com/redhat/rhn/common/db/datasource/xml/Package_queries.xml#L1407 |
Oh, this is calling it explicite, but we have also these cases: |
@paususe - I consulted with @mcalmer This PR improves the current situation where we have a problem and an L3 with a customer. The complete solution (that fixes all the cases) would require multiple sprints as we need to research around the following topics:
This is something that targets 4.1 as it involves a lot of research and development. What I suggest:
|
987b78e
to
7c1fa05
Compare
I guess yes, it's defined in here:
See above, I'd say no.
But that does not seem too difficult if we get the package type (deb vs rpm) in evr_t:
A PL/SQL type, comparison operator, etc is available from Debian itself: Specifically:
We will need to do that even after the PTF (in fact, we should do it before the PTF, as this may introduce many new problems).
In light of my comments above, do you think it would be possible to implement the right solution now? |
Changing it for a new installation is easy, but in a running system with thousends of enties converting it without loosing data is the challenge. And I am not sure of postgresql allows to "alter" a type.
Hmm, the C++ part if the important one. We would need to build an extension package but that should be possible.
Hmm, It could still become a nightmare. So the question is: what is more important - CaaSP 4 or this? |
Who can enlighten us on this?
C++ part in Uyuni? There is also an implementation of the comparison in C in dpkg:
Let's proceed with Michele's proposed fix and the CaaSP4 RFC for now but also do the complete fix in 4.0. Each case our version comparison algorithm is not 100% exact is a potential nightmare. |
Package version for RPM does not contain any '-': ``` susemanager=# select count(*) from rhnpackage; count -------- 217621 (1 row) susemanager=# select * from rhnpackageevr where version like '%-%'; id | epoch | version | release | evr ----+-------+---------+---------+----- (0 rows) ``` For Debian packages, some packages are named with a '-' in their version, e.g.: ``` gcc-8-base-8-20180414-1ubuntu2.amd64-deb gcc-8-base-8.2.0-1ubuntu2~18.04.amd64-deb lib32gcc1-8-20180414-1ubuntu2:1.amd64-deb lib32gcc1-8.2.0-1ubuntu2~18.04:1.amd64-deb libatomic1-8-20180414-1ubuntu2.amd64-deb libatomic1-8.2.0-1ubuntu2~18.04.amd64-deb libcc1-0-8-20180414-1ubuntu2.amd64-deb libcc1-0-8.2.0-1ubuntu2~18.04.amd64-deb libgcc1-8-20180414-1ubuntu2:1.amd64-deb libgcc1-8.2.0-1ubuntu2~18.04:1.amd64-deb libgomp1-8-20180414-1ubuntu2.amd64-deb libgomp1-8.2.0-1ubuntu2~18.04.amd64-deb libitm1-8-20180414-1ubuntu2.amd64-deb libitm1-8.2.0-1ubuntu2~18.04.amd64-deb liblsan0-8-20180414-1ubuntu2.amd64-deb liblsan0-8.2.0-1ubuntu2~18.04.amd64-deb libmpx2-8-20180414-1ubuntu2.amd64-deb libmpx2-8.2.0-1ubuntu2~18.04.amd64-deb libquadmath0-8-20180414-1ubuntu2.amd64-deb libquadmath0-8.2.0-1ubuntu2~18.04.amd64-deb libstdc++6-8-20180414-1ubuntu2.amd64-deb libstdc++6-8.2.0-1ubuntu2~18.04.amd64-deb libtsan0-8-20180414-1ubuntu2.amd64-deb libtsan0-8.2.0-1ubuntu2~18.04.amd64-deb ``` The version is correctly parsed: ``` susemanager=# select * from rhnpackageevr where id in (select evr_id from rhnpackage where name_id in (select id from rhnpackagename where name like '%gcc-8-base%')); id | epoch | version | release | evr ------+-------+------------+------------------+--------------------------- 316 | | 8-20180414 | 1ubuntu2 | (,8-20180414,1ubuntu2) 1835 | | 8.3.0 | 6ubuntu1~18.04.1 | (,8.3.0,6ubuntu1~18.04.1) (2 rows) ``` This PR adds a special check in the version compare algorithm: if it contains a '-', then we need to check for the `upstream_version` of the Debian package. If the `upstream_version` is equal, then we need to compare for the second part of the string (the part after the '-') and compare the `debian_revision`.
7c1fa05
to
31f34ab
Compare
What does this PR change?
Package version for RPM does not contain any '-':
For Debian packages, some packages are named with a '-' in their
version, e.g.:
The version is correctly parsed:
This PR adds a special check in the version compare algorithm: if it contains a '-', then we need to check for the
upstream_version
of the Debian package. If theupstream_version
is equal, then we need to compare for the second part of the string (the part after the '-') and compare thedebian_revision
.Test coverage
Unit tests were added
DONE
Links
Fixes https://github.com/SUSE/spacewalk/issues/9382
Ports:
Manager-4.0: https://github.com/SUSE/spacewalk/pull/9657
Manager-3.2: https://github.com/SUSE/spacewalk/pull/9656
DONE
Re-run a test
If you need to re-run a test, please mark the related checkbox, it will be unchecked automatically once it has re-run: