On 2024-07-22 at 23:14:03, rsbecker@xxxxxxxxxxxxx wrote: > On Monday, July 22, 2024 5:31 PM, brian m. carlson wrote: > >Assuming we add such a feature, how does sorting by SemVer differ from the > >current version sorting? That is, where is the current version sorting deficient for > >SemVer? Also, what do you want to happen when a tag doesn't meet SemVer > >requirements (note that the "v" prefix is not allowed in SemVer, although it's > >customary in tags)? > > Currently, tags would be sorted as follows (simple example): > 1.10.0 > 1.2.0 > 1.9.1 I agree that this happens without any --sort option. > With semver, the tags would be: > 1.2.0 > 1.9.1 > 1.10.0 > > My take is that this, if implemented, would need to be more general, and include prefix and suffix handling, so: > v1.2.0 > v1.9.0 > v1.10.0 > > should sort as appropriate. We might need something like v({semver}), or a more general regex-like (prefix){0,1}(semver){1}(suffix){0,1}. However, this is the behaviour I see with --sort=version:refname (or v:refname). For example, the command I provided below running in the Git repository sorts v2.9.5 before v2.10.0, which I believe is how this was supposed to work. Of course, I could be totally off base, which is why I'm asking for clarification so I can understand better. I think it's also worth asking what happens for tags that don't match that still. For example, let's assume for the moment that Git used SemVer. I have added tags in my Git repo for when I send a series, like so: 7a9ba024ccdc440095537cf53ce69a5749798165 commit refs/tags/sent/credential-alwaysauth/v1 a74efc1699038e898960c2c55185f32aade6a88a commit refs/tags/sent/credential-alwaysauth/v2 ac45947b34d003f827d15a8623c0125fb12ec261 commit refs/tags/sent/credential-alwaysauth/v3 Those clearly don't meet SemVer and will need to be sorted _somehow_ (before or after SemVer tags?), and users will want to know how. > While at it, having a reverse sort would also be useful. For platforms that have semver-util, this can be trivially scripted. For exotics, no such luck, as semver-util is not especially portable, not for lack of trying. I think we have this by using the `-` prefix, such as `--sort=-version:refname`. I agree this is very useful, though, since it's an O(n) operation to reverse the list, which, as you mention below, might be large. If we add SemVer sorting, we'll definitely want it to work nicely with reverse sorting. > >As for the special range syntax, I think the typical suggestion is to filter the output of > >ls-remote or for-each-ref by piping it to a suitable program. Perl or Ruby are > >common choices here, and both could easily parse SemVer tags. For example: > > > > git for-each-ref --sort=v:refname refs/tags/ | > > ruby -ne 'if %r[\trefs/tags/v(\d+)\.(\d+)\.(\d+)$]; ver = > >Regexp.last_match[1..3].map(&:to_i); puts $_ if [[2, 6, 3], ver, [2, 15, 2]].sort[1] == > >ver; end' > > > >Git is intentionally designed to support this kind of shell scripting. > > I think implementing both wrapped semver and reverse sort in git tag might be useful for large projects, like git and OpenSSL where the number of tags is large. It would make finding time-ordered releases somewhat easier. My worry is that a special range syntax isn't going to cover all the possible needs. For example, I might know that [v2.5.1, v4.0.0) will work (despite the incompatible version at v3, my code isn't affected), but it's very difficult to express that via a range, since what I want is basically a tuple sort on [2, 5, 1] <= ver < [4, 0, 0]. That's easy in Ruby (well, it's not pretty[0], but I did it above), but you can't simply specify a range in any one field, because v2.6.0 and v3.0.5 would both match the pattern. This kind of thing is very common with lots of Ruby gems, which, while they have a backwards incompatible change, don't change all that much, so several major versions might be acceptable. In that context, it's likely that some sort of external filtering might be more general and robust and meet people's needs better. However, I'm open to being convinced otherwise if some compelling syntax comes up. I'm just asking questions here because I'm not super sure what the use cases are and I think more information about the proposal might help people decide better. [0] That's because Ruby supports comparisons on Array via <=> (and thus sorting), but it doesn't implement < and > themselves (although == is implemented). Therefore, I had to sort the three versions, and if the given version was still in the middle afterwards, then it was in range. Another, less pretty (in my view) option is to call <=> directly and compare against -1 or 1. If there are any Rubyists on the list with better ideas, I'm open to hear them. -- brian m. carlson (they/them or he/him) Toronto, Ontario, CA
Attachment:
signature.asc
Description: PGP signature