]> git.vpit.fr Git - perl/modules/CPANPLUS-Dist-Gentoo.git/blob - lib/CPANPLUS/Dist/Gentoo.pm
Importing CPANPLUS-Dist-Gentoo-0.02_01.tar.gz
[perl/modules/CPANPLUS-Dist-Gentoo.git] / lib / CPANPLUS / Dist / Gentoo.pm
1 package CPANPLUS::Dist::Gentoo;
2
3 use strict;
4 use warnings;
5
6 use File::Copy qw/copy/;
7 use File::Path qw/mkpath/;
8 use File::Spec::Functions qw/catdir catfile/;
9
10 use IPC::Cmd qw/run can_run/;
11
12 use CPANPLUS::Error;
13
14 use base qw/CPANPLUS::Dist::Base/;
15
16 =head1 NAME
17
18 CPANPLUS::Dist::Gentoo - CPANPLUS backend generating Gentoo ebuilds.
19
20 =head1 VERSION
21
22 Version 0.02_01
23
24 =cut
25
26 our $VERSION = '0.02_01';
27
28 =head1 SYNOPSIS
29
30     cpan2dist --format=CPANPLUS::Dist::Gentoo \
31               --dist-opts overlay=/usr/local/portage \
32               --dist-opts distdir=/usr/portage/distfiles \
33               --dist-opts manifest=yes \
34               --dist-opts keywords=x86 \
35               Any::Module You::Like
36
37 =head1 DESCRPITON
38
39 This module is a CPANPLUS backend that recursively generates Gentoo ebuilds for a given package in the specified overlay (defaults to C</usr/local/portage>), update the manifest, and even emerge it (together with its dependencies) if the user requires it. You need write permissions on the directory where Gentoo fetches its source files (usually C</usr/portage/distfiles>).
40
41 The generated ebuilds are placed into the section C<perl-gcpanp>. They favour depending on C<perl-core> or C<dev-perl> rather than C<perl-gcpanp>.
42
43 =head1 METHODS
44
45 All the methods are inherited from L<CPANPLUS::Dist::Base>. Please refer to its perldoc for precise information on what's done at each step.
46
47 =cut
48
49 use constant CATEGORY => 'perl-gcpanp';
50
51 sub format_available {
52  for my $prog (qw/emerge ebuild/) {
53   unless (can_run($prog)) {
54    error "$prog is required to write ebuilds -- aborting";
55    return 0;
56   }
57  }
58  return 1;
59 }
60
61 sub init {
62  my ($self) = @_;
63  my $stat = $self->status;
64  $stat->mk_accessors(qw/name version dist desc uri src license deps
65                         eb_name eb_version eb_dir eb_file distdir fetched_arch
66                         keywords do_manifest/);
67
68  return 1;
69 }
70
71 my %gentooism = (
72  'Digest'          => 'digest-base',
73  'Locale-Maketext' => 'locale-maketext',
74  'Net-Ping'        => 'net-ping',
75  'PathTools'       => 'File-Spec',
76  'PodParser'       => 'Pod-Parser',
77 );
78
79 sub prepare {
80  my $self = shift;
81  my $mod  = $self->parent;
82  my $stat = $self->status;
83  my $int  = $mod->parent;
84  my $conf = $int->configure_object;
85
86  my %opts = @_;
87
88  my $keywords = delete $opts{'keywords'};
89  $keywords = 'x86' unless defined $keywords;
90  $keywords = [ split ' ', $keywords ];
91  $stat->keywords($keywords);
92
93  my $manifest = delete $opts{'manifest'};
94  $manifest = 1 unless defined $manifest;
95  $manifest = 0 if $manifest =~ /^\s*no?\s*$/i;
96  $stat->do_manifest($manifest);
97
98  my $overlay = catdir(delete($opts{'overlay'}) || '/usr/local/portage',
99                       CATEGORY);
100
101  $stat->distdir(delete($opts{'distdir'}) || '/usr/portage/distfiles');
102  if ($stat->do_manifest && !-w $stat->distdir) {
103   error 'distdir isn\'t writable -- aborting';
104   return 0;
105  }
106  $stat->fetched_arch($mod->status->fetch);
107
108  my $name = $mod->package_name;
109  $stat->name($name);
110
111  my $version = $mod->package_version;
112  $stat->version($version);
113  $stat->dist($name . '-' . $version);
114  my $f = 1;
115  $version =~ s/_+/$f ? do { $f = 0; '_p' } : ''/ge;
116  1 while $version =~ s/(_p[^.]*)\.+/$1/;
117  $stat->eb_version($version);
118
119  $stat->eb_name($gentooism{$stat->name} || $stat->name);
120  $stat->eb_dir(catdir($overlay, $stat->eb_name));
121  $stat->eb_file(catfile($stat->eb_dir,
122                         $stat->eb_name . '-' . $stat->eb_version . '.ebuild'));
123  if (-r $stat->eb_file) {
124   msg 'Ebuild already generated for ' . $stat->dist . ' -- skipping';
125   $stat->prepared(1);
126   $stat->created(1);
127   return 1;
128  }
129
130  $self->SUPER::prepare(%opts);
131
132  my $desc = $mod->description;
133  ($desc = $name) =~ s/-+/::/g unless $desc;
134  $stat->desc($desc);
135  $stat->uri('http://search.cpan.org/dist/' . $name);
136  unless ($name =~ /^([^-]+)/) {
137   error 'Wrong distribution name -- aborting';
138   return 0;
139  }
140  $stat->src('mirror://cpan/modules/by-module/' . $1 . '/' . $mod->package);
141  $stat->license([ qw/Artistic GPL-2/ ]);
142
143  my $prereqs = $mod->status->prereqs;
144  my @depends;
145  for my $prereq (sort keys %$prereqs) {
146   my $obj = $int->module_tree($prereq);
147   unless ($obj) {
148    error 'Wrong module object -- aborting';
149    return 0;
150   }
151   next if $obj->package_is_perl_core;
152   {
153    my $version;
154    if ($prereqs->{$prereq}) {
155     if ($obj->installed_version && $obj->installed_version < $obj->version) {
156      $version = $obj->installed_version;
157     } else {
158      $version = $obj->package_version;
159     }
160    }
161    push @depends, [ $obj , $version ];
162   }
163  }
164  $stat->deps(\@depends);
165
166  return 1;
167 }
168
169 sub create {
170  my $self = shift;
171  my $stat = $self->status;
172
173  unless ($stat->prepared) {
174   error 'Can\'t create ' . $stat->dist . ' since it was never prepared -- aborting';
175   return 0;
176  }
177
178  if ($stat->created) {
179   msg $stat->dist . ' was already created -- skipping';
180   return 1;
181  }
182
183  $self->SUPER::create(@_);
184
185  my $dir = $stat->eb_dir;
186  unless (-d $dir) {
187   eval { mkpath $dir };
188   if ($@) {
189    error "mkpath($dir): $@";
190    return 0;
191   }
192  }
193
194  my $d = "# Generated by CPANPLUS::Dist::Gentoo\n\ninherit perl-module\n\n";
195  $d   .= 'S="${WORKDIR}/' . $stat->dist . "\"\n";
196  $d   .= 'DESCRIPTION="' . $stat->desc . "\"\n";
197  $d   .= 'HOMEPAGE="' . $stat->uri . "\"\n";
198  $d   .= 'SRC_URI="' . $stat->src . "\"\n";
199  $d   .= "SLOT=\"0\"\n";
200  $d   .= 'LICENSE="|| ( ' . join(' ', sort @{$stat->license}) . " )\"\n";
201  $d   .= 'KEYWORDS="' . join(' ', sort @{$stat->keywords}) . "\"\n";
202  $d   .= 'DEPEND="' . join "\n",
203   'dev-lang/perl',
204   map {
205    my $a = $_->[0]->package_name;
206    my $x = '';
207    if (defined $_->[1]) {
208     $x  = '>=';
209     $a .= '-' . $_->[1];
210    }
211    '|| ( ' . join(' ', map "$x$_/$a",
212                            qw/perl-core dev-perl/, CATEGORY) # perl-gcpan ?
213            . ' )';
214   } @{$stat->deps};
215  $d   .= "\"\n";
216
217  my $file = $stat->eb_file;
218  open my $eb, '>', $file or do {
219   error "open($file): $! -- aborting";
220   return 0;
221  };
222  print $eb $d;
223  close $eb;
224
225  if ($stat->do_manifest) {
226   unless (copy $stat->fetched_arch, $stat->distdir) {
227    error "Couldn\'t copy the distribution file to distdir ($!) -- aborting";
228    1 while unlink $file;
229    return 0;
230   }
231
232   msg 'Adding Manifest entry for ' . $stat->dist;
233   unless (scalar run command => [ 'ebuild', $file, 'manifest' ], verbose => 0) {
234    error 'ebuild manifest failed -- aborting';
235    1 while unlink $file;
236    return 0;
237   }
238  }
239
240  return 1;
241 }
242
243 sub install {
244  my $self = shift;
245  my $stat = $self->status;
246  my $conf = $self->parent->parent->configure_object;
247
248  my $sudo = $conf->get_program('sudo');
249  my @cmd = ('emerge', '=' . $stat->eb_name . '-' . $stat->eb_version);
250  unshift @cmd, $sudo if $sudo;
251
252  unless (run command => \@cmd, verbose => 1) {
253   error 'emerge failed -- aborting';
254   return 0;
255  }
256
257  return 1;
258 }
259
260 sub uninstall {
261  my $self = shift;
262  my $stat = $self->status;
263  my $conf = $self->parent->parent->configure_object;
264
265  my $sudo = $conf->get_program('sudo');
266  my @cmd = ('emerge', '-C', '=' . $stat->eb_name . '-' . $stat->eb_version);
267  unshift @cmd, $sudo if $sudo;
268
269  unless (run command => \@cmd, verbose => 1) {
270   error 'emerge -C failed -- aborting';
271   return 0;
272  }
273
274  return 1;
275 }
276
277 =head1 DEPENDENCIES
278
279 Gentoo (L<http://gentoo.org>).
280
281 L<CPANPLUS>, L<IPC::Cmd> (core modules since 5.9.5).
282
283 L<File::Path> (since 5.001), L<File::Copy> (5.002), L<File::Spec::Functions> (5.00504).
284
285 =head1 SEE ALSO
286
287 L<cpan2dist>.
288
289 L<CPANPLUS::Dist::Base>, L<CPANPLUS::Dist::Deb>, L<CPANPLUS::Dist::Mdv>.
290
291 =head1 AUTHOR
292
293 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
294
295 =head1 BUGS
296
297 Please report any bugs or feature requests to C<bug-cpanplus-dist-gentoo at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CPANPLUS-Dist-Gentoo>.  I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
298
299 =head1 SUPPORT
300
301 You can find documentation for this module with the perldoc command.
302
303     perldoc CPANPLUS::Dist::Gentoo
304
305 =head1 ACKNOWLEDGEMENTS
306
307 The module is to some extend cargo-culted from L<CPANPLUS::Dist::Deb> and L<CPANPLUS::Dist::Mdv>.
308
309 =head1 COPYRIGHT & LICENSE
310
311 Copyright 2008 Vincent Pit, all rights reserved.
312
313 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
314
315 =cut
316
317 1; # End of CPANPLUS::Dist::Gentoo