Java::Maven::Artifact::Version - a perl module for comparing Artifact versions exactly like Maven does.
Version 1.000001
see "MAVEN VERSION COMPATIBILITY".
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.
org.apache.maven.artifact.versioning.ComparableVersion.java
Lucky for you this module cares about the real comparison differences hard coded in ComparableVersion and reproduces it.
ComparableVersion
see "FAQ" for details.
By default version_compare compares a version string to another one exactly like Maven does.
version_compare
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 :
0 if versions compared are equal
0
1 if version is greater than version that is compared to
1
-1 if version is lower than version that is compared to
-1
$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.
max_depth
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;
Note that max_depth cares about sub listitems.
listitems
$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 ListItem.
org.apache.maven.artifact.versioning.ComparableVersion.ListItem.toString()
ListItem
In list context, it will return the data structure representation :
@l = version_parse('1.0-final-1'); # [1,['',1]]
zero ('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 stringitem or listitem, zero char ('0') is automatically appended. Then version that begins with separator is automatically prefixed by zero.
stringitem
listitem
'-1' will be internally moved to '0-1'.
0-1
'1....1' will be internally moved to '1.0.0.0.1'.
1....1
1.0.0.0.1
The dash separator "-" will create listitem only if it is preceeded by an integeritem and it is followed by digit.
integeritem
Then when they say 1-alpha10-SNAPSHOT => [1,["alpha",10,["SNAPSHOT"]]] understand that it's wrong.
1-alpha10-SNAPSHOT => [1,["alpha",10,["SNAPSHOT"]]]
1-alpha10-SNAPSHOT is internally represented by [1,"alpha",10,"SNAPSHOT"]. Which has a fully different comparison behavior because no sub listitem is created.
1-alpha10-SNAPSHOT
[1,"alpha",10,"SNAPSHOT"]
Please note that "zero appending on blank separator" has been done after listitem splitting.
Then understand that '-1--1' will NOT be internally represented by '(0,(1,(0,(1))', but by '(0,1,0,1)'.
-1--1
(0,(1,(0,(1))
(0,1,0,1)
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.0
It appends:
-
And normalization process current parsed listitem from current position when normalization is called, back to the beginning of this current listitem.
Each encountered 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.
nullitem
nullitems
Then understand that :
1.0.alpha.0 becomes (1,0,alpha) #because when main listitem parsing has ended, normalization has been called. Last item was 0, 0 is the nullitem of integeritem, then it has been shooted. Next last item was alpha that is not nullitem then normalization process stopped.
1.0.alpha.0
(1,0,alpha)
alpha
1.0-final-1 becomes (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 listitem is 0. Then it has been shot. final has 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 ''.
1.0-final-1
(1,,1)
final
''
0.0.ga becomes () # because 'ga' has been substituted by '' and when listitem has been normalized at the end, all items where nullitems
0.0.ga
()
final-0.1 becomes (,0,1) # because normalization has not been called after first dash because it was not been preceded by digit.
final-0.1 becomes
If you told me WTF ?, I would answer I am not responsible of drug consumption...
In 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 ListItem.
Comma "," is used as items separator, and enclosing braces are used to represent ListItem.
,
For example: in Java world org.apache.maven.artifact.versioning.ComparableVersion.ListItem.toString() on "1-0.1" gives "(1,(0,1))".
"1-0.1"
"(1,(0,1))"
"version_parse" function reproduces this algo for the whole set Java::Maven::Artifact::Version.
Java::Maven::Artifact::Version
$v = version_parse('1-0.1'); # $v = '(1,(O,1))'
It is not very clear in the official Maven doc.
Comparing listitem with nullitem will just compare first item of the listitem with nullitem.
item
This version is fully compatible with the org.apache.maven.artifact.versioning.ComparableVersion.java algo of org.apache.maven:maven-artifact embedded with :
org.apache.maven:maven-artifact
Maven 3.2.3
Maven 3.2.2
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.
Thomas Cazali, <pandragon at cpan.org>
<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.
perldoc Java::Maven::Artifact::Version
You can also look for information at:
https://github.com/apendragon/Java-Maven-Artifact-Version/wiki
github repository issues tracker (report bugs here)
https://github.com/apendragon/Java-Maven-Artifact-Version/issues
AnnoCPAN: Annotated CPAN documentation
http://annocpan.org/dist/Java-Maven-Artifact-Version
CPAN Ratings
http://cpanratings.perl.org/d/Java-Maven-Artifact-Version
Search CPAN
http://search.cpan.org/dist/Java-Maven-Artifact-Version/
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:
http://www.perlfoundation.org/artistic_license_2_0
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.
To install Java::Maven::Artifact::Version, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Java::Maven::Artifact::Version
CPAN shell
perl -MCPAN -e shell install Java::Maven::Artifact::Version
For more information on module installation, please visit the detailed CPAN module installation guide.