1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
package App::ArchLinux::PackagerTools::Pacman;
use strictures;
use autodie;
use Function::Parameters;
use Log::Any qw($log);
=head1 NAME
App::ArchLinux::PackagerTools::Pacman - Methods to interact with pacman
=head1 SYNOPSIS
use App::ArchLinux::PackagerTools::Pacman;
# synopsis...
=head1 DESCRIPTION
This module allows to query pacman for a list of packages in the repository and
extract a list of CPAN distributions that are part of the repository.
=head1 METHODS
=head2 Constructors
=head3 new
my $pacman = App::ArchLinux::PackagerTools::Pacman->new();
Returns a new instance.
=cut
method new($class: $deps = {}) {
$deps->{cpan} //= App::ArchLinux::PackagerTools::CPAN->new();
$deps->{pkgname_cpan_name_map} //= {
# pkgname => cpan_name
'perl-critic' => 'Perl::Critic',
'perl-libintl-perl' => 'libintl-perl',
};
return $class->new_no_defaults($deps);
}
method new_no_defaults($class: $deps = {}) {
my $self = {};
bless $self, $class;
$self->{deps} = $deps;
return $self;
}
=head2 Public Methods
=head3 get_packages
my $packages = $pacman->get_packages();
Returns an arrayref of package hashes. Each package hash contains at least the
pkgname and pkgver keys.
=cut
method get_packages() {
my @packages;
open my $fh, '-|', 'expac -S \'%n %v\'';
my %seen;
while (<$fh>) {
if (m/^(?<pkgname>[^\s]+) (?<pkgver>.*)$/) {
push @packages, {%+};
}
}
return \@packages;
}
=head3 get_perl_packages
my $packages = $pacman->get_perl_packages();
Similar to get_packages(), but returns a list filtered to perl packages.
=cut
method get_perl_packages() {
my @packages = grep {$_->{pkgname} =~ /^perl-/} $self->get_packages->@*;
$log->debugf("Found %d perl packages", scalar(@packages));
return \@packages;
}
=head3 get_perl_distributions
my $dists = $pacman->get_perl_distributions();
Returns a list of CPAN distributions that are in the pacman repo. Returns an
arrayref of hashrefs that contain dist_name and version keys.
=cut
method get_perl_distributions() {
my @distributions;
for my $package ($self->get_perl_packages()->@*) {
my $cleaned_name = $package->{pkgname} =~ s/^perl-//r;
my $dist;
if (defined $self->{deps}->{pkgname_cpan_name_map}->{$package->{pkgname}}) {
$dist = $self->{deps}->{cpan}->get_dist($self->{deps}->{pkgname_cpan_name_map}->{$package->{pkgname}});
} else {
$dist = $self->{deps}->{cpan}->search_dist($cleaned_name);
}
push @distributions, $dist if defined $dist;
$log->warningf("Failed to find distribution for package '%s'", $package) if !defined $dist;
}
return \@distributions;
}
=head3 get_package_version
my $version = $pacman->get_package_version($pkgname);
Return the version of a package in the pacman package repositories.
=cut
method get_package_version($pkgname) {
# TODO do not fork expac for each package here! works for now, but it's sloooow
my $version = `expac -S -1 '%v' -- '$pkgname'`;
chomp $version;
return $version;
}
=head3 get_perl_pkgname
my $pkgname = $pacman->get_perl_pkgname($dist_name);
Return the pacman package name for a CPAN distribution. In most cases, this
prefixes the distribution with "perl-" and replaces "::" with "-", but it may
also return other names if they are mapped differently.
=cut
method get_perl_pkgname($dist_name) {
# TODO implement mapping
my $pkgname = lc($dist_name);
$pkgname =~ s/::/-/g;
$pkgname = "perl-$pkgname";
return $pkgname;
}
=head3 get_perl_distribution_version
my $version = $pacman->get_perl_distribution_version($dist_name);
Return the version of a CPAN distribution's pacman package. This removes
pacman-specific information from the pacman's package version.
=cut
method get_perl_distribution_version($dist_name) {
my $pkgname = $self->get_perl_pkgname($dist_name);
my $version = $self->get_package_version($pkgname);
# remove pkgrel
$version =~ s/-\d+(\.\d+)?$//;
# remove epoch
$version =~ s/^\d+://;
$log->tracef("Found version '%s' for package '%s'", $version, $pkgname);
return $version;
}
1;
__END__
|