]> git.deb.at Git - deb/packages.git/blob - lib/Deb/Versions.pm
Initial Polish translation of sections file.
[deb/packages.git] / lib / Deb / Versions.pm
1 #
2 # Deb::Versions
3 #
4 # Copyright 2003, 2004 Frank Lichtenheld <frank@lichtenheld.de>
5 #
6 #    This program is free software; you can redistribute it and/or modify
7 #    it under the terms of the GNU General Public License as published by
8 #    the Free Software Foundation; either version 2 of the License, or
9 #    (at your option) any later version.
10 #
11 #    This program is distributed in the hope that it will be useful,
12 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #    GNU General Public License for more details.
15 #
16 #    You should have received a copy of the GNU General Public License
17 #    along with this program; if not, write to the Free Software
18 #    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #
20
21 =head1 NAME
22
23 Deb::Versions - compare Versions of Debian packages
24
25 =head1 SYNOPSIS
26
27     use Deb::Versions
28
29     my $res = version_cmp( "1:0.2.2-2woody1", "1:0.2.3-7" );
30     
31     my @sorted = version_sort( "1:0.2.2-2woody1", "1:0.2.3-7", "2:0.1.1" );
32
33 =head1 DESCRIPTION
34
35 This module allows you to compare version numbers like defined
36 in the Debian policy, section 5.6.11 (L<SEE ALSO>).
37
38 It provides two functions:
39
40 =over 4
41
42 =item *
43
44 version_cmp() gets two version strings as parameters and returns
45 -1, if the first is lower than the second, 0 if equal, 1 if greater.
46 You can use this function as first parameter for the sort() function.
47
48 =item *
49
50 version_sort() is just an usefull abbrevation for 
51
52     sort { version_cmp( $b, $a ) } @_;
53
54 =back
55
56 =head1 EXPORTS
57
58 By default, Deb::Versions exports version_cmp() and version_sort().
59
60 =cut
61
62 package Deb::Versions;
63
64 use strict;
65 use Exporter;
66 use Carp qw(cluck);
67
68 our @ISA = qw( Exporter );
69 our @EXPORT = qw( version_cmp version_sort suites_cmp suites_sort );
70
71 our $VERSION = v1.0.0;
72
73 my $re = qr/^(?:(\d+):)?([\w.+:~-]+?)(?:-([\w+.~]+))?$/;
74 sub version_cmp_pp {
75     return 0 if $_[0] eq $_[1];
76     my ( $ver1, $ver2 ) = @_;
77
78     my ( $e1, $e2, $u1, $u2, $d1, $d2 );
79     if ( $ver1 =~ $re ) {
80         ( $e1, $u1, $d1 ) = ( $1, $2, $3 );
81         $e1 ||= 0;
82     } else {
83         cluck "This seems not to be a valid version number:"
84             . "<$ver1>\n";
85         return -1;
86     }
87     if ( $ver2 =~ $re ) {
88         ( $e2, $u2, $d2 ) = ( $1, $2, $3 );
89         $e2 ||= 0;
90     } else {
91         cluck "This seems not to be a valid version number:"
92             . "<$ver2>\n";
93         return 1;
94     }
95
96 #    warn "D: <$e1><$u1><$d1> <=> <$e2><$u2><$d2>\n";
97
98     my $res = ($e1 <=> $e2);
99     return $res if $res;
100     $res = _cmp_part ( $u1, $u2 );
101     return $res if $res;
102     $res = _cmp_part ( $d1, $d2 );
103     return $res;
104 }
105
106 *version_cmp = \&version_cmp_pp;
107 eval {
108     require AptPkg::Config;
109     require AptPkg::System;
110     require AptPkg::Version;
111     
112     $AptPkg::Config::_config->init;
113     $AptPkg::System::_system = $AptPkg::Config::_config->system;
114     my $apt_ver = $AptPkg::System::_system->versioning;
115     *version_cmp = sub { return $apt_ver->compare(@_) };
116 };
117
118 sub version_sort {
119     return sort { version_cmp( $b, $a ) } @_;
120 }
121
122 sub _cmp_part {
123     my ( $v1, $v2 ) = @_;
124     my $r;
125
126     while ( $v1 || $v2 ) {
127         $v1 =~ s/^(\D*)//o;
128         my $sp1 = $1;
129         $v2 =~ s/^(\D*)//o;
130         my $sp2 = $1;
131 #       warn "$sp1 cmp $sp2 = "._lcmp( $sp1,$sp2)."\n";
132         if ( $r = _lcmp( $sp1, $sp2 ) ) {
133             return $r;
134         }
135         $v1 =~ s/^(\d*)//o;
136         my $np1 = $1 || 0;
137         $v2 =~ s/^(\d*)//o;
138         my $np2 = $1 || 0;
139 #       warn "$np1 <=> $np2 = ".($np1 <=> $np2)."\n";
140         if ( $r = ($np1 <=> $np2) ) {
141             return $r;
142         }
143     }
144     if ( $v1 || $v2 ) {
145         return $v1 ? 1 : -1;
146     }
147
148     return 0;
149 }
150
151 sub _lcmp {
152     my ( $v1, $v2 ) = @_;
153    
154     for ( my $i = 0; $i <= length( $v1 ); $i++ ) {
155         my ( $n1, $n2 ) = ( ord( substr( $v1, $i, 1 ) ), 
156                             ord( substr( $v2, $i, 1 ) ) );
157         $n1 += 256 if $n1 && $n1 < 65; # letters sort earlier than non-letters
158         $n1 = -1 if $n1 == 126; # '~' sorts earlier than everything else
159         $n2 += 256 if $n2 && $n2 < 65;
160         $n2 = -1 if $n2 == 126;
161         if ( my $r = ($n1 <=> $n2) ) {
162             return $r;
163         }
164     }
165     return length( $v1 ) <=> length( $v2 );
166 }
167
168 our @SUITES_SORT = qw(  
169                         bo
170                         hamm
171                         slink
172                         potato
173                         woody
174                         sarge
175                         oldstable
176                         etch etch-m68k
177                         stable stable-proposed-updates
178                         lenny
179                         testing testing-proposed-updates
180                         squeeze
181                         sid unstable experimental
182                         warty hoary breezy dapper edgy feisty gutsy hardy
183                         intrepid jaunty karmic lucid maverick);
184 our @ARCHIVE_SORT = qw( non-US security updates volatile backports );
185 our @PRIORITY_SORT = qw( required important standard optional extra );
186 my $i = 1000;
187 our %suites_sort = map { $_ => ($i-=10) } @SUITES_SORT;
188 our %priority_sort = map { $_ => $i-- } @PRIORITY_SORT;
189 $i = 0;
190 our %archive_sort = map { $_ => $i++ } @ARCHIVE_SORT;
191
192 sub suites_cmp {
193     my ($s_a, $s_b) = @_;
194     my $cmp_a = $suites_sort{$s_a};
195     unless ($cmp_a) {
196         $cmp_a = $suites_sort{$1} - $archive_sort{$2}
197         if $s_a =~ m;^(.+?)[/-](.*)$;o;
198     }
199     my $cmp_b = $suites_sort{$s_b};
200     unless ($cmp_b) {
201         $cmp_b = $suites_sort{$1} - $archive_sort{$2}
202         if $s_b =~ m;^(.+?)[/-](.*)$;o;
203     }
204     return ($cmp_b <=> $cmp_a);
205 }
206
207 sub suites_sort {
208     return sort { suites_cmp( $a, $b ) } @_;
209 }
210
211 sub priority_cmp {
212     return ($priority_sort{$_[0]} <=> $priority_sort{$_[1]});
213 }
214
215 sub priority_sort {
216     return sort { priority_cmp( $b, $a ) } @_;
217 }
218
219
220 1;
221 __END__
222
223 =head1 COPYRIGHT
224
225 Copyright 2003, 2004 Frank Lichtenheld <frank@lichtenheld.de>
226
227 This file is distributed under the terms of the GNU Public
228 License, Version 2. See the source code for more details.
229
230 =head1 SEE ALSO
231
232 Debian policy <URL:http://www.debian.org/doc/debian-policy/>