summaryrefslogtreecommitdiffstats
path: root/lib/App/ArchLinux/PackagerTools/Pacman.pm
blob: ec4f9916af1b2537395813d194e4471e15a5f48e (plain)
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
175
176
package App::ArchLinux::PackagerTools::Pacman;
use strictures;

use autodie;
use Function::Parameters;
use Log::Any qw($log);

use App::ArchLinux::PackagerTools::CPAN;

=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__