Closed andreabedini closed 1 year ago
preferred-versions is a package level property (of course). Perhaps we need to have a package-level metadata file? (i.e. _sources/pkg-name/meta.toml
).
I think deprecated versions is implemented by marking those versions as not preferred, see https://hackage.haskell.org/packages/preferred
... is it? I would have thought it was the aggregation of whether each individual version was preferred/deprecated?
... is it? I would have thought it was the aggregation of whether each individual version was preferred/deprecated?
At least in hackage, it looks like preferred versions is a package level property. Eg see https://hackage.haskell.org/package/GPipe-GLFW/preferred/edit
That said, there is no difference between a version outside the preferred range and one that is deprecated. I think I will just support deprecating versions. It's left to understand how that enters in the index since I believe this information can change multiple times. I need to do some digging.
I thought about this today and I wrote down these notes.
Hackage index has a per package preferred-versions
metadata file, with its own timestamp and last one wins semantic (just like a cabal file revision).
AFAIK what hackage server shows as “deprecated versions” are just versions that are un-preferred. I’d be happy if someone could investigate this a bit better (e.g. how does affect the solver really?).
The biggest work here is to figure out how to encode preferred-versions
into meta.toml (note that our meta.json
is per package version not per package).
Maybe as a list of timestamp and version ranges. I am leaning over making the whole preferred version range explicit rather than trying to figure out deltas between them (as it becomes hard to figure out what the current state).
Note that 1) we can reuse cabal parsers and logic to manipulate versions 2) hackage ends up “normalising” version ranges but I don’t think it’s necessary. So “not version 1” could work and be easy enough to type by hand.
Other thought. We could just mark versions as deprecated and/or preferred. E.g. deprecated-on: timestamp
, preferred-on: timestamp
; but that always only change one version at the time. Is that desiderabile? Is this going to put us in a corner?
I think it makes sense for the user-facing interface to be "is this version deprecated/preferred or not?". I think the fact that cabal turns it into a full-on constraint is juts more power than we need. We do need to do the timestamps, though... I guess in principle something can be deprecated and then later un-deprecated etc? So it's a bit like revisions, they can stack up.
I guess in principle something can be deprecated and then later un-deprecated etc?
Yes, so deprecated-on: timestamp
would not work. Maybe we can repeat it?
deprecated-on: t1
undeprecated-on: t2
preferred-on: t3
undeprecated-on: t4
I am afraid this gets confusing quickly. What if you deprecate a version twice? Should that be an error? The preferred-versions
file would not change so it should not reappear in the the index. Also (AFAIU) there are preferred versions which semantic is "deprecate the rest"; this means a the deprecated/preferred state of a version cannot be determined by looking at a single meta.toml
.
I was thinking a bit about it, and I would vote for a prefered-version
field in <package>/<version>/meta.toml
file. This would be handled transitively, I mean if:
foobar/X/meta.toml
→ prefered-version: Y
foobar/Y/meta.toml
→ prefered-version: Z
Then trying to resolve version X
of foobar
would warn user and suggest version Z
(and error or use implicitly the right version?).What your thoughts about it? Does it make sense, is there any case where this simple system fails to encode correctly “preferred version”? I was syncing about if the user wrote unintentionally a cycle of preferred versions …
I'm actually unsure we want preferred versions. Deprecating versions is something people actually want to do, preferring versions is a bit weird.
Does hackage even expose the ability to use them or are they just an implementation method for deprecated versions?
I'm actually unsure we want preferred versions. Deprecating versions is something people actually want to do, preferring versions is a bit weird.
I agree this sounds like an internal mechanism since I've not yet heard of any other package index giving this kind of front-facing option to the user… But I could rather understand it as a mechanism to customize the depreciation message like “please update to X version”, or maybe offering a soft-depreciation mechanism “please update to X version, as it will soon be depreciated”?
Does hackage even expose the ability to use them or are they just an implementation method for deprecated versions?
I should investigate … Unrelated, but could preferred-version
go backward in time or semver ordering? e.g., could version 5.0.3 be preferred over 5.1.0?
To sum up, you suggest closing this issue in favor of just implementing https://github.com/andreabedini/foliage/issues/18 right?
Plenty of examples here https://hackage.haskell.org/packages/preferred
E.g. this is a package with both preferred and deprecated versions https://hackage.haskell.org/package/composition-prelude/preferred
I just notice that whole package deprecation (e.g. https://hackage.haskell.org/package/2captcha) does not seem to be reflected anywhere in the index (there's no 2captcha/preferred-versions
in the index).
I... guess I just don't know what they're trying to do with preferred-versions? It's quite strong: it adds a constraint to the solver, so if you prefer version X.Y, then if you release X.(Y+1), you either need to also prefer X.(Y+1) or un-prefer X.Y otherwise X.(Y+1) will never get used. It seems hard to use well.
Unrelated, but could preferred-version go backward in time or semver ordering? e.g., could version 5.0.3 be preferred over 5.1.0?
I think it can be literally anything.
I am leaning over making the whole preferred version range explicit rather than trying to figure out deltas between them (as it becomes hard to figure out what the current state).
I am also wondering whether this would be simpler. I do think it would be nice to support what I think it is likely to be the most common use case: deprecate a single package version straightforwardly (it has a bug, was a mistaken release, or whatever).
I do think it would be nice to support what I think it is likely to be the most common use case: deprecate a single package version straightforwardly (it has a bug, was a mistaken release, or whatever).
I think this is a reasonable pragmatic choice: in the metadata, we only support deprecating versions and not preferring versions. Preferring some versions could still be done by manually deprecating all the other ones. As you say, this covers most of the use cases and it has minimal implementation cost bacause it is still metadata scoped to the package-version, i.e. we don't have to implement a new per-package metadata file.
If there's consensus, I proposed we close this one and move the discussion of the implementation to #18.
I think this is a reasonable pragmatic choice: in the metadata, we only support deprecating versions and not preferring versions. Preferring some versions could still be done by manually deprecating all the other ones. As you say, this covers most of the use cases and it has minimal implementation cost bacause it is still metadata scoped to the package-version, i.e. we don't have to implement a new per-package metadata file.
If there's consensus, I proposed we close this one and move the discussion of the implementation to #18.
I agree đź‘Ť
I think we could probably do this nicely with a field in the metadata file.
Also for deprecated versions.