automake: Don't rely on List::Util to provide 'none'
[automake.git] / lib / Automake / Version.pm
blob3d5c22bc24522583d897a603c2c1acf8b7fd4c03
1 # Copyright (C) 2001-2018 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2, or (at your option)
6 # any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <https://www.gnu.org/licenses/>.
16 package Automake::Version;
18 use 5.006;
19 use strict;
20 use Automake::ChannelDefs;
22 =head1 NAME
24 Automake::Version - version comparison
26 =head1 SYNOPSIS
28 use Automake::Version;
30 print "Version $version is older than required version $required\n"
31 if Automake::Version::check ($version, $required);
33 =head1 DESCRIPTION
35 This module provides support for comparing versions string
36 as they are used in Automake.
38 A version is a string that looks like
39 C<MAJOR.MINOR[.MICRO][ALPHA][-FORK]> where C<MAJOR>, C<MINOR>, and
40 C<MICRO> are digits, C<ALPHA> is a character, and C<FORK> any
41 alphanumeric word.
43 Usually, C<ALPHA> is used to label alpha releases or intermediate
44 snapshots, C<FORK> is used for git branches or patched releases, and
45 C<MICRO> is used for bug fixes releases on the C<MAJOR.MINOR> branch.
47 For the purpose of ordering, C<1.4> is the same as C<1.4.0>, but
48 C<1.4g> is the same as C<1.4.99g>. The C<FORK> identifier is ignored
49 in the ordering, except when it looks like C<-pMINOR[ALPHA]>: some
50 versions were labeled like C<1.4-p3a>, this is the same as an alpha
51 release labeled C<1.4.3a>. Yes, it's horrible, but Automake did not
52 support two-dot versions in the past.
54 =head2 FUNCTIONS
56 =over 4
58 =item C<split ($version)>
60 Split the string C<$version> into the corresponding C<(MAJOR, MINOR,
61 MICRO, ALPHA, FORK)> tuple. For instance C<'1.4g'> would be split
62 into C<(1, 4, 99, 'g', '')>. Return C<()> on error.
64 =cut
66 sub split ($)
68 my ($ver) = @_;
70 # Special case for versions like 1.4-p2a.
71 if ($ver =~ /^(\d+)\.(\d+)(?:-p(\d+)([a-z]+)?)$/)
73 return ($1, $2, $3, $4 || '', '');
75 # Common case.
76 elsif ($ver =~ /^(\d+)\.(\d+)(?:\.(\d+))?([a-z])?(?:-([A-Za-z0-9]+))?$/)
78 return ($1, $2, $3 || (defined $4 ? 99 : 0), $4 || '', $5 || '');
80 return ();
83 =item C<compare (\@LVERSION, \@RVERSION)>
85 Compare two version tuples, as returned by C<split>.
87 Return 1, 0, or -1, if C<LVERSION> is found to be respectively
88 greater than, equal to, or less than C<RVERSION>.
90 =cut
92 sub compare (\@\@)
94 my @l = @{$_[0]};
95 my @r = @{$_[1]};
97 for my $i (0, 1, 2)
99 return 1 if ($l[$i] > $r[$i]);
100 return -1 if ($l[$i] < $r[$i]);
102 for my $i (3, 4)
104 return 1 if ($l[$i] gt $r[$i]);
105 return -1 if ($l[$i] lt $r[$i]);
107 return 0;
110 =item C<check($VERSION, $REQUIRED)>
112 Handles the logic of requiring a version number in Automake.
113 C<$VERSION> should be Automake's version, while C<$REQUIRED>
114 is the version required by the user input.
116 Return 0 if the required version is satisfied, 1 otherwise.
118 =cut
120 sub check ($$)
122 my ($version, $required) = @_;
123 my @version = Automake::Version::split ($version);
124 my @required = Automake::Version::split ($required);
126 prog_error "version is incorrect: $version"
127 if $#version == -1;
129 # This should not happen, because process_option_list and split_version
130 # use similar regexes.
131 prog_error "required version is incorrect: $required"
132 if $#required == -1;
134 # If we require 3.4n-foo then we require something
135 # >= 3.4n, with the 'foo' fork identifier.
136 return 1
137 if ($required[4] ne '' && $required[4] ne $version[4]);
139 return 0 > compare (@version, @required);