Skip to content

tarsius/vcomp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

61 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Compare version strings

This package provides functions for comparing version strings. Similar functionality is available in Emacs; see version< and related functions defined in subr.el.

Historic context

I created this package for the benefit of the Emacsmirror, around the time package.el was also created. Emacs already provided version comparison functions but package.el did not use them initially. Shortly after it was merged into Emacs, it started using them.

Neither the implementation in Emacs nor the one in early package.el, satisfied the requirements of the Emacsmirror, which had to deal with all the crazy version strings found in the wild. Nowadays, version strings tend to be less crazy. Because Emacs and thus package.el, does not support them, many package maintainers adjusted, which is a good thing.

But back in the days, I had to write this package to cope. It is based on the implementation initially used by package.el.

Differences to version< et al.

Support for Post-Releases

The main difference is that this package also supports “post-releases”, not just “pre-releases”.

;; "1-alpha" is a "preview" of what will eventually be released as "1".
(version< "1-alpha" "1")      => t
(vcomp<   "1-alpha" "1")      => t

;; "1" has already been released and this is a snaphot of a commit that follows that release.
(version< "1" "1-p20230407")  => error
(vcomp<   "1" "1-p20230407")  => t

I intend to port that feature to Emacs’ implementation, so that the could be used by MELPA, GNU-devel ELPA and NonGNU-devel ELPA. Vcomp only supports -p as a prefix for post-releases. I would have liked to also support, e.g., -git and -snapshot, but since Emacs already (ab)uses them as pre-releases, that won’t work. -dev and -elpa are still available though.

Other differences

There are other difference. In some cases this package is more flexible, in other cases Emacs’ implementation is. I don’t think Emacs’ implementation should be changed.

  • Vcomp supports only one post-release part. 1-alpha-beta, for example, is not valid.
  • Vcomp does however support an additional -rN part.
  • Vcomp supports an additional alphabetic version part, while version-to-list produces the same result for 1.1 and 1A.
  • (version= "1" "1.0") but by default (vcomp< "1" "1.0").

Internal format

What is a valid version string, is defined jointly by the regular expression stored in variable vcomp--regexp and the function vcomp--intern, and best explained with an example.

Function vcomp--intern converts a string to the internal format as follows:

0.11a_rc3-r1 => ((0 11) (97 103 3 1))

0.11         => (0 11)  valid separators are ._-
    a        => 97      either 0 or the ascii code of the lower
                        case letter (A is equal to a)
     _rc     => 103     100 alpha
                        101 beta
                        102 pre
                        103 rc
                        104 --
                        105 p
                        _ is optional, - is also valid
        3    => 3       if missing 0 is used
         -r1 => 1       there are no variations of -rN

A less crazy version string would be converted like this:

1.0.3 => ((1 0 3) (0 104 0 0))

The internal format is only intended for … internal use, but if you are wondering why a flat list does not do, here is one example:

1.97 => (1 97)
1a   => (1 97)

There are other ways of dealing with this and similar problems. E.g., the built-in functions treat 1 and 1.0 as equal, and only support pre-releases of sorts but not patches (-pN) like this library does.

Functions vcomp-compare and vcomp--compare-interned can be used to compare two versions using any predicate that can compare integers.

When comparing two versions whose numeric parts have different lengths, vcomp--compare-interned fills in -1.

1.0    => ((1 0) ...)   => ((1 0 -1) ...)
1.0.0  => ((1 0 0) ...) => ((1 0  0) ...)

So 1.0.0 is greater than 1.0, and 1.0 is greater than 1. If you don’t want that, set vcomp--fill-number to 0.

This filling has to happen in vcomp--compare-interned, because we don’t know the length of the other versions, when vcomp--intern is called.

Function vcomp-normalize can be used to normalize a version string.

0-11A-Alpha0-r1 => 0.11a_alpha-r1
2.3d-BETA5      => 2.3d_beta5