AcademySoftwareFoundation / rez

An integrated package configuration, build and deployment system for software
https://rez.readthedocs.io
Apache License 2.0
949 stars 337 forks source link

custom versioning definition per meta-package #302

Open maxnbk opened 8 years ago

maxnbk commented 8 years ago

Would it be possible to allow a meta-package (for lack of a word for a packages versionless presence) to specify a custom versioning algorithm, so that rez-env's don't pull in things that aren't actually correct per the general rez algorithm? Example being Foundry products, where 9.0v1b8 is considered newer than 9.0v1, when the b8 is the beta token for the version-that-will-be-9.0v1-in-the-future.

I'm not sure how one would represent that honestly, but a feature request nonetheless.

nerdvegas commented 8 years ago

Hey,

So this turns out to be pretty tricky. I've attempted in the past to add support for this, so that you can add custom version ordering for some packages. The trouble with this is it hugely complicates the version submodule and it breaks all of the nice mathematical properties that it currently has. There ends up being a bunch of odd edge cases that make no sense. It causes another problem - where does this custom ordering info go? If it's config data, then we've introduced a feature that would actually hinder studio's abilities to share code - not that I see that happening anytime soon, but I'm very reluctant to add a feature that would hinder this in future (especially since the future of any OS project isn't really known right?).

However I think there's another approach that may give most of what we need with a lot less of the pain. The idea is to introduce another character to the valid version regex - let's call it '$' (as in, end-of-string in regex). It would affect ordering such that:

9.0.v1$ > 9.0.v1b8

Also, by default, the '$' character would be hidden from output. So to the user it would appear that Nuke's versioning is behaving the way it should - and you'd only ever see the $ when looking at the package.py.

Thoughts? A

On Wed, Mar 2, 2016 at 2:42 PM, maxnbk notifications@github.com wrote:

Would it be possible to allow a meta-package (for lack of a word for a packages versionless presence) to specify a custom versioning algorithm, so that rez-env's don't pull in things that aren't actually correct per the general rez algorithm? Example being Foundry products, where 9.0v1b8 is considered newer than 9.0v1, when the b8 is the beta token for the version-that-will-be-9.0v1-in-the-future.

I'm not sure how one would represent that honestly, but a feature request nonetheless.

— Reply to this email directly or view it on GitHub https://github.com/nerdvegas/rez/issues/302.

maxnbk commented 8 years ago

Are the mathematical properties spoken-of broken if alphanumerics are broken up into operators, where they are defined as either precedent or antecedent operators (inferior/superior if you like), where one being specified into inferior group means that it is numerically less than the version specified without it? This wouldn't allow for zany things like completely inverted schemes or reversed orderings but on a single-level by single-level approach allows an alpha or beta or release candidate to be considered inferior to the version lacking it.

Alternately perhaps package.py's could simply have an "evaluative version" number and a different display name, so 9.0v1b8 can have an "evaluate as version" value of 9.0v0b8 which perfectly describes both it's relationship between 9.0v0 (superior) and 9.0v1 (inferior) and in theory any other versions that released relative to it in a similar manner.

But failing that, yeah, I think something simple like the $ solution could deal with the request perfectly well for the vast majority of practical intents and purposes.

nerdvegas commented 8 years ago

I want to avoid placing special importance on strings such as alpha, beta etc. And having this configurable still causes issues when you consider sharing packages across studios.

In any case - I like your 'evaluative version' idea, I think that solves the problem fairly neatly. It's a nice way of having control over the version priority without having to store anything out to config settings.

Although I think in your example you may have meant "9.0v01b8" right?

A

On Thu, Mar 3, 2016 at 11:39 AM, maxnbk notifications@github.com wrote:

Are the mathematical properties spoken-of broken if alphanumerics are broken up into operators, where they are defined as either precedent or antecedent operators (inferior/superior if you like), where one being specified into inferior group means that it is numerically less than the version specified without it? This wouldn't allow for zany things like completely inverted schemes or reversed orderings but one a single-level by single-level approach allows an alpha or beta or release candidate to be considered inferior to the version lacking it.

Alternately perhaps package.py's could simply have an "evaluative version" number and a different display name, so 9.0v1b8 can have an "evaluate as version" value of 9.0v0b8 which perfectly describes both it's relationship between 9.0v0 (superior) and 9.0v1 (inferior) and in theory any other versions that released relative to it in a similar manner.

But failing that, yeah, I think something simple like the $ solution could deal with the request perfectly well for the vast majority of practical intents and purposes.

— Reply to this email directly or view it on GitHub https://github.com/nerdvegas/rez/issues/302#issuecomment-191929847.

maxnbk commented 8 years ago

Hmm, no, I think that.. 9.0v0 -> actual name 9.0v1b8 -> evaluate as 9.0v0b8 9.0v1 -> actual name would eval to the ascending order of 9.0v0 -> 9.0v1b8 [evaluate as 9.0v0b8 is greater than 9.0v0] -> 9.0v1 And if a subsequent "9.0v1b12" [evaluate as 9.0v0b12] shows up, it slots in between entry 2 and 3 perfectly. Am I wrong?

nerdvegas commented 8 years ago

What would the 9.0v2b8 evaluative version be? I would think:

9.0v0b8 --> evaluative 9.0v00b8 9.0v1b8 --> evaluative 9.0v01b8 9.0v2b8 --> evaluative 9.0v02b8

Order is still correct in this scheme, because '01' < '1' in rez. Dropping back to 9.0v0b8 evaluative would get confusing because there may also be a readable (and unrelated) version 9.0v0b8, and it's kinda of like you're switching version scheme in the evaluative version. Just adding the extra '0' in the evaluative version to retain order seems less confusing, and the schema isn't changed as much.

A

On Thu, Mar 3, 2016 at 12:53 PM, maxnbk notifications@github.com wrote:

Hmm, no, I think that.. 9.0v0 -> actual name 9.0v1b8 -> evaluate as 9.0v0b8 9.0v1 -> actual name would eval to the ascending order of 9.0v0 -> 9.0v1b8 [evaluate as 9.0v0b8 is greater than 9.0v0] -> 9.0v1 And if a subsequent "9.0v1b12" [evaluate as 9.0v0b12] shows up, it slots in between entry 2 and 3 perfectly. Am I wrong?

— Reply to this email directly or view it on GitHub https://github.com/nerdvegas/rez/issues/302#issuecomment-191957676.

maxnbk commented 8 years ago

I was thinking that the evaluative name would always be 9.0v[n-1]b8, but yes, given the 0, 00, 000 way of rez, that perhaps works as well. Either way, having an ability to "pretend" that a package is a different version is not necessarily a bad idea, it's more likely that humans will screw it up than that the system is wrong. The number of packages this is an issue with are few and far between, but the inconsistency of it makes it such an eyesore when rez is otherwise so calculating and orderly about everything.

maxnbk commented 8 years ago

Another example of this being helpful: packages which concatenate strings like "sp1", "ext1" etc. Since release order of a software vendor is not always consistent, people don't know in advance which order to string certain attributes together. Doh.

maxnbk commented 7 years ago

Any further thoughts on this? Having either an evaluative version to employ to fix minor naming inconsistencies or deal with a vendors not-rez-friendly version naming scheme would be an excellent addition to the rez toolset in my mind.

bpabel commented 7 years ago

I know of two somewhat common standards:

The semantic versioning way, which denotes prerelease information with a dash (-) and then compares it alphabetically/numerically just like the main version

Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0

And the python PEP-440 versions, which are a lot less flexible, since they only allow specific prerelease identifiers.

[N!]N(.N)*[{a|b|rc}N][.postN][.devN]

The nuke version is like a looser version of the python prerelease versioning

Both versioning schemes work by separating the version from the pre-release version, which I think is less error prone than treating them all as primary version elements and trying to munge the previous item in the version list.

In this case, you'd have to agree to special case b characters at the end of versions, so 9.0v1b8 would be split into

version: [9, 0, 'v', 1]
prerelease: ['b', 8]

The other option is to just force users to manually convert non-standard numbering schemes, so when adding nuke as a rez package, they would manually convert the version to 9.0.1-b8 or 9.0.1b8. You'd still need to update rez to understand pre-release information, but at least you're enforcing some type of standard.

Nuke is probably a bad example for building a version parsing system around since it doesn't really comply with any standards and I don't know of any major software packages that number software they way they do with a v on the patch version.

pmolodo commented 7 years ago

In general, I think the simplest solution is to not try to have every rez-version EXACTLY match the vendor's version. ie, make your versions:

9.0.1.0
9.0.1.b8

..which will sort correctly (since rez sorts all letters before all numbers, precisely because of situations like this).

Then, in your commands, just create an env var which contains the nuke version string, ie:

nuke_version_str = "{version[0]}.{version[1]}v{version[2]}"
if version[3] != "0":
    nuke_version_str += "{version[3]}"
env.NUKE_VERSION_STR = nuke_version_str

[EDIT: I had mentioned a PR of mine here (https://github.com/nerdvegas/rez/pull/355), but on further thought, I realized these are two separate issues - this issue is dealing with version-ordering: ie, is version "Foo" considered <= version "Bar". That pull request deals with version-prioritization: ie, even if Foo < Bar, do we want to preferentially choose version Foo over version Bar.]