File rpmsort of Package rpm
xxxxxxxxxx
1
#! /usr/bin/perl -w
2
3
# This program is free software; you can redistribute it and/or
4
# modify it under the terms of the GNU General Public License
5
# as published by the Free Software Foundation; either version 2
6
# of the License, or (at your option) any later version.
7
#
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.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16
# USA.
17
18
use Getopt::Long qw(:config gnu_getopt);
19
20
sub do_rpm_cmp_versions {
21
my ($evr1, $evr2) = @_;
22
23
sub _rpm_cmp {
24
my ($s1, $s2) = @_;
25
26
return defined $s1 <=> defined $s2
27
unless defined $s1 && defined $s2;
28
29
my ($r, $x1, $x2);
30
do {
31
$s1 =~ s/^[^a-zA-Z0-9]+//;
32
$s2 =~ s/^[^a-zA-Z0-9]+//;
33
if ($s1 =~ /^\d/ || $s2 =~ /^\d/) {
34
$s1 =~ s/^(0*(\d*))//; $x1 = $2;
35
return -1 if $1 eq '';
36
$s2 =~ s/^(0*(\d*))//; $x2 = $2;
37
return 1 if $1 eq '';
38
$r = length $x1 <=> length $x2 || $x1 cmp $x2;
39
} else {
40
$s1 =~ s/^([a-zA-Z]*)//; $x1 = $1;
41
$s2 =~ s/^([a-zA-Z]*)//; $x2 = $1;
42
return 0
43
if $x1 eq '' && $x2 eq '';
44
$r = $x1 cmp $x2;
45
}
46
} until $r;
47
return $r;
48
}
49
50
my ($e1, $v1, $r1) = $evr1 =~ /^(?:(\d*):)?(.*?)(?:-([^-]*))?$/;
51
my ($e2, $v2, $r2) = $evr2 =~ /^(?:(\d*):)?(.*?)(?:-([^-]*))?$/;
52
my $r = _rpm_cmp($e1 || 0, $e2 || 0);
53
$r = _rpm_cmp($v1, $v2)
54
unless $r;
55
$r = _rpm_cmp($r1, $r2)
56
unless $r;
57
return $r;
58
}
59
60
my $reorder = sub { return @_ };
61
my $key = 0;
62
my $test = 0;
63
64
sub rpm_cmp_versions {
65
my ($evr1, $evr2) = @_;
66
67
chomp($evr1, $evr2);
68
my $res1 = do_rpm_cmp_versions($evr1, $evr2);
69
if ($test) {
70
open(my $fd, '-|', 'zypper', '--terse', 'versioncmp',
71
$evr1, $evr2) or die "zypper: $!\n";
72
my $res2 = <$fd>;
73
close($fd) or die "zypper: $!\n";
74
chomp $res2;
75
if ($res1 != $res2) {
76
my @operators = qw(< == >);
77
my $op1 = $operators[$res1 + 1];
78
my $op2 = $operators[$res2 + 1];
79
80
print STDERR "BUG: $evr1 $op1 $evr2 vs. zypper: $evr1 $op2 $evr2\n";
81
}
82
}
83
return $res1;
84
}
85
86
GetOptions ("r|reverse" => sub { $reorder = sub { return reverse @_ } },
87
"k|key=i" => \$key,
88
"test" => \$test)
89
or do {
90
print STDERR "Usage $0 [-r, --reverse] [-k N, --key=N] [--test]\n";
91
exit 1;
92
};
93
94
if ($key == 0) {
95
# Sort by entire lines
96
map { print } &$reorder(sort { rpm_cmp_versions($a, $b) } <>);
97
} else {
98
# Sort by field $key
99
my @data = map { [(split)[$key-1], $_] } <>;
100
map { print } &$reorder(map { $_->[1] }
101
sort { rpm_cmp_versions($a->[0], $b->[0]) } @data);
102
}
103