- MAVEN VERSION COMPATIBILITY
- LICENSE AND COPYRIGHT
Java::Maven::Artifact::Version - a perl module for comparing Artifact versions exactly like Maven does.
Note that this documentation is intended as a reference to the module.
use Java::Maven::Artifact::Version qw/version_compare version_parse/; my $y = version_compare('1-alpha', '1-beta'); # $y = -1 my $x = version_compare('1.0', '1-0.alpha'); # $x = 0 my $z = version_parse('1-1.2-alpha'); # $z = '(1,(1,2,alpha))' my @l = version_parse('1-1.2-alpha'); # @l = (1,[1,2,'alpha'])
Apache Maven has a peculiar way to compare Artifact versions. The aim of this module is to exactly reproduce this way in hope that it could be usefull to someone that wants to write utils like SCM hooks. It may quickly ensure an Artifact version respect a grow order without to have to install Java and Maven on the system in charge of this checking.
The official Apache document that describes it is here http://docs.codehaus.org/display/MAVEN/Versioning. But don't blindly believe everything. Take the red pill, and I show you how deep the rabbit-hole goes. Because there is a gap between the truth coded in
org.apache.maven.artifact.versioning.ComparableVersion.java that can be found here and that Maven official document.
Lucky for you this module cares about the real comparison differences hard coded in
ComparableVersion and reproduces it.
see "FAQ" for details.
version_compare compares a version string to another one exactly like Maven does.
See http://docs.codehaus.org/display/MAVEN/Versioning for general comparison description, and "DESCRIPTION" for more details about mechanisms not described in that official Maven doc but occur during Maven Artifact versions comparison in Java.
This function will return :
0if versions compared are equal
1if version is greater than version that is compared to
-1if version is lower than version that is compared to
$v = version_compare('1.0', '1.1'); # $v = -1
version_compare can go further. You can set
max_depth to stop comparison before the whole version comparison has processed.
Suppose you have to code SCM hook which enforce that pushed artifact source must always begin by the same two version items and new version must be greater than the old one.
my ($old, $new) = ('1.1.12', '1.1.13'); my $common = version_compare($old, $new, 2); # returns 0 here die "you did not respect the version policy" if $common; die "you must increment artifact version" if version_compare($old, $new) >= 0;
max_depth cares about sub
$v = '1-1.0.sp; # normalized to (1,(1,0,'sp')) $o = '1-1-SNAPSHOT'; # normalized to (1,(1,'SNAPSHOT')) $x = version_compare($v, $o, 3); # will compare '0' to 'SNAPSHOT' and will return 1
Of course understand that this computation is done after normalization.
$x = version_compare('1-1.0-1-ga-0-1.2', '1-1.0-1-ga-0-1.3', 4); #only last item will be ignored during this comparison # ^ ^ ^ ^ ^ ^ ^ ^
Note that set negative
max_depth will always return 0, because no comparison will be done at all
$x = version_compare(1, 2, -1); # $x = 0
will return normalized version representation (see "Normalization").
In scalar context, it will return string representation :
$s = version_parse('1.0-final-1'); # $s = '(1,(,1))'
You would have the same string if you had call
org.apache.maven.artifact.versioning.ComparableVersion.ListItem.toString() private method of
org.apache.maven.artifact.versioning.ComparableVersion.java on the main
In list context, it will return the data structure representation :
@l = version_parse('1.0-final-1'); # [1,['',1]]
What are differences between actual Maven comparison algo and that described in the official Maven doc ?
0') will be appended on each blank separator char (dot '.' or dash '-') During parsing if separator char is encountered and it was not preceded by
listitem, zero char ('
0') is automatically appended. Then version that begins with separator is automatically prefixed by zero.
-1' will be internally moved to '
1....1' will be internally moved to '
The dash separator "-" will create
listitem only if it is preceeded by an
integeritem and it is followed by digit.
Then when they say
1-alpha10-SNAPSHOT => [1,["alpha",10,["SNAPSHOT"]]] understand that it's wrong.
1-alpha10-SNAPSHOT is internally represented by
[1,"alpha",10,"SNAPSHOT"]. Which has a fully different comparison behavior because no sub
listitem is created.
Please note that "zero appending on blank separator" has been done after
Then understand that '
-1--1' will NOT be internally represented by '
(0,(1,(0,(1))', but by '
Normalization is one of the most important part of version comparison but it is not described at all in the official Maven document. So what is normalization ? It's kind of reducing version components function. Its aim is to shoot useless version components in artifact version. To simplify it, understand that
1.0 must be internally represented by
1 during comparison. But normalization appends in specific times during artifact version parsing.
- 1. each time a dash '
-' separator is preceded by digit but before any alias substitution (except when any of these digits is a zero appended, because
listitemsplitting is done before 'zero appending').
- 2. at the end of each parsed
listitem, then after all alias substitution
And normalization process current parsed
listitem from current position when normalization is called, back to the beginning of this current
nullitem will be shot until a non
nullitem is encountered or until the begining of this
listitem is reached if all its items are
nullitems. In this last case precisely, the empty
listitem will be shot except if it is the main one.
Then understand that :
(1,0,alpha)#because when main
listitemparsing has ended, normalization has been called. Last item was 0, 0 is the
integeritem, then it has been shooted. Next last item was
alphathat is not
nullitemthen normalization process stopped.
(1,,1)#because a dash has been encoutered during parsing. Then normalization has been called because it was preceded by a digit and last item in the current
listitemis 0. Then it has been shot.
finalhas been substituted by
''but when next normalization has been called, at the end of the parsing, the last item was not
nullitem, then normalization did not meet
()# because 'ga' has been substituted by
listitemhas been normalized at the end, all items where
final-0.1 becomes(,0,1) # because normalization has not been called after first dash because it was not been preceded by digit.
If you told me WTF ?, I would answer I am not responsible of drug consumption...
org.apache.maven.artifact.versioning.ComparableVersion.java, the representation of normalized version is only displayable with the call of
org.apache.maven.artifact.versioning.ComparableVersion.ListItem.toString() private method on the main
," is used as items separator, and enclosing braces are used to represent
For example: in Java world
"version_parse" function reproduces this algo for the whole set
$v = version_parse('1-0.1'); # $v = '(1,(O,1))'
It is not very clear in the official Maven doc.
nullitem will just compare first
item of the
This version is fully compatible with the
org.apache.maven.artifact.versioning.ComparableVersion.java algo of
org.apache.maven:maven-artifact embedded with :
All Test::More tests are also available with Java Junit tests to ensure comparison results are similars.
See "SOURCE" if you want to check them.
I will do my best to check the Maven compatibility on each Maven new release.
<pandragon at cpan.org>
The source code repository for
Java::Maven::Artifact::Version can be found at https://github.com/apendragon/Java-Maven-Artifact-Version/
Please report any bugs or feature requests to https://github.com/apendragon/Java-Maven-Artifact-Version/issues.
You can find documentation for this module with the perldoc command.
You can also look for information at:
github repository issues tracker (report bugs here)
AnnoCPAN: Annotated CPAN documentation
Copyright 2014 Thomas Cazali.
This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:
Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.
If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.
This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.
This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.
Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.