_prereq() is better implemented as attrs/methods
[app-cpan2pkg.git] / lib / App / CPAN2Pkg.pm
blob8b9641d366711dc8bee1dc41538c2d5d20d5e100
2 # This file is part of App::CPAN2Pkg.
3 # Copyright (c) 2009 Jerome Quelin, all rights reserved.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the same terms as Perl itself.
10 package App::CPAN2Pkg;
12 use strict;
13 use warnings;
15 use App::CPAN2Pkg::Module;
16 use App::CPAN2Pkg::Worker;
17 use Class::XSAccessor
18 constructor => '_new',
19 accessors => {
20 _module => '_module',
22 use POE;
24 our $VERSION = '0.5.0';
26 sub spawn {
27 my ($class, $opts) = @_;
29 # create the heap object
30 my $obj = App::CPAN2Pkg->_new(
31 _module => {}, # {name}=obj store the objects
34 # create the main session
35 my $session = POE::Session->create(
36 inline_states => {
37 # public events
38 available_on_bs => \&available_on_bs,
39 cpan2dist_status => \&cpan2dist_status,
40 upstream_status => \&upstream_status,
41 local_install => \&local_install,
42 local_status => \&local_status,
43 module_spawned => \&module_spawned,
44 package => \&package,
45 prereqs => \&prereqs,
46 upstream_import => \&upstream_import,
47 upstream_install => \&upstream_install,
48 # poe inline states
49 _start => \&_start,
50 #_stop => sub { warn "stop app\n"; },
52 args => $opts,
53 heap => $obj,
55 return $session->ID;
60 #--
61 # SUBS
64 # if ( not available in cooker ) is_in_dist
65 # then
66 # compute dependencies find_prereqs
67 # repeat with each dep
68 # cpan2dist cpan2dist
69 # install local install_from_local
70 # while ( not available locally ) is_installed
71 # do
72 # prompt user to fix manually
73 # done
74 # import import_local_to_dist
75 # submit (included above)
76 # ack available (manual?)
78 # else
79 # urpmi --auto perl(module::to::install) install_from_dist
80 # fi
82 # -- public events
84 sub available_on_bs {
85 # FIXME: start submitting upstream what depends on this
89 sub cpan2dist_status {
90 my ($k, $h, $module, $status) = @_[KERNEL, HEAP, ARG0, ARG1];
91 # FIXME: what if $status is false
93 $k->post($module, 'install_from_local');
97 sub local_install {
98 my ($k, $h, $module, $success) = @_[KERNEL, HEAP, ARG0, ARG1];
100 if ( not $success ) {
101 # module has not been installed locally.
102 # FIXME: ask user
103 return;
106 # module has been installed locally.
107 $k->post('ui', 'module_available', $module);
109 # module available: nothing depends on it anymore.
110 my $name = $module->name;
111 $module->is_local(1);
112 my @depends = $module->blocking_list;
113 $module->blocking_clear;
115 # update all modules that were depending on it
116 foreach my $m ( @depends ) {
117 # remove dependency on module
118 my $mobj = $h->_module->{$m};
119 $mobj->missing_del($name);
120 my @missing = $mobj->missing_list;
121 $k->post('ui', 'prereqs', $mobj, @missing);
123 if ( scalar @missing == 0 ) {
124 # huzzah! no more missing prereqs - let's create a
125 # native package for it.
126 $k->post($mobj, 'cpan2dist');
130 $k->post($module, 'import_upstream');
134 sub local_status {
135 my ($k, $h, $module, $is_installed) = @_[KERNEL, HEAP, ARG0, ARG1];
137 if ( not $is_installed ) {
138 # module is not installed locally, check if
139 # it's available upstream.
140 $k->post($module, 'is_in_dist');
141 return;
144 # module is already installed locally.
145 $k->post('ui', 'module_available', $module);
146 $k->post('ui', 'prereqs', $module);
148 # module available: nothing depends on it anymore.
149 my $name = $module->name;
150 $module->is_local(1);
151 my @depends = $module->blocking_list;
152 $module->blocking_clear;
154 # update all modules that were depending on it
155 foreach my $m ( @depends ) {
156 # remove dependency on module
157 my $mobj = $h->_module->{$m};
158 $mobj->missing_del($name);
159 my @missing = $mobj->missing_list;
160 $k->post('ui', 'prereqs', $mobj, @missing);
162 if ( scalar @missing == 0 ) {
163 # huzzah! no more missing prereqs - let's create a
164 # native package for it.
165 $k->post($mobj, 'cpan2dist');
170 sub module_spawned {
171 my ($k, $h, $module) = @_[KERNEL, HEAP, ARG0];
172 my $name = $module->name;
173 $h->_module->{$name} = $module;
174 $k->post($module, 'is_installed');
177 sub package {
178 my ($k, $h, $module) = @_[KERNEL, HEAP, ARG0];
179 App::CPAN2Pkg::Worker->spawn($module);
182 sub prereqs {
183 my ($k, $h, $module, @prereqs) = @_[KERNEL, HEAP, ARG0..$#_];
185 my @missing;
186 foreach my $m ( @prereqs ) {
187 # check if module is new. in which case, let's treat it.
188 if ( ! exists $h->_module->{$m} ) {
189 my $mobj = App::CPAN2Pkg::Module->new( name => $m );
190 $k->yield('package', $mobj);
191 $h->_module->{$m} = $mobj;
194 # store missing module.
195 push @missing, $m unless $h->_module->{$m}->is_local;
198 $k->post('ui', 'prereqs', $module, @missing);
199 if ( @missing ) {
200 # module misses some prereqs - wait for them.
201 my $name = $module->name;
202 $module->missing_add($_) for @missing;
203 $h->_module->{$_}->blocking_add($name) for @missing;
205 } else {
206 # no prereqs, move on
207 $k->post($module, 'cpan2dist');
208 return;
212 sub upstream_install {
213 my ($k, $module, $success) = @_[KERNEL, ARG0, ARG1];
214 #$h->_module->{$name}->is_local(1);
215 #FIXME: update prereqs
219 sub upstream_import {
220 my ($k, $module, $success) = @_[KERNEL, ARG0, ARG1];
221 # FIXME: what if wrong
222 # FIXME: don't submit if missing deps on bs
223 $k->post($module, 'build_upstream');
227 sub upstream_status {
228 my ($k, $module, $is_available) = @_[KERNEL, ARG0, ARG1];
229 my $event = $is_available ? 'install_from_dist' : 'find_prereqs';
230 $k->post($module, $event);
234 # -- poe inline states
236 sub _start {
237 my ($k, $opts) = @_[KERNEL, ARG0];
238 $k->alias_set('app');
240 # start packaging some modules
241 my $modules = $opts->{modules};
242 foreach my $name ( @$modules ) {
243 my $module = App::CPAN2Pkg::Module->new( name => $name );
244 $k->yield('package', $module);
250 __END__
252 =head1 NAME
254 App::CPAN2Pkg - generating native linux packages from cpan
258 =head1 SYNOPSIS
260 $ cpan2pkg
261 $ cpan2pkg Module::Foo Module::Bar ...
265 =head1 DESCRIPTION
267 Don't use this module directly, refer to the C<cpan2pkg> script instead.
269 C<App::CPAN2Pkg> is the controller for the C<cpan2pkg> application. It
270 implements a POE session, responsible to schedule and advance module
271 packagement.
273 It is spawned by the poe session responsible for the user interface.
277 =head1 PUBLIC PACKAGE METHODS
279 =head2 my $id = App::CPAN2Pkg->spawn( \%params )
281 This method will create a POE session responsible for coordinating the
282 package(s) creation.
284 It will return the POE id of the session newly created.
286 You can tune the session by passing some arguments as a hash
287 reference, where the hash keys are:
289 =over 4
291 =item * modules => \@list_of_modules
293 A list of modules to start packaging.
296 =back
300 =head1 PUBLIC EVENTS ACCEPTED
302 The following events are the module's API.
305 =head2 available_on_bs()
307 Sent when module is available on upstream build system.
310 =head2 cpan2dist_status( $module, $success )
312 Sent when C<$module> has been C<cpan2dist>-ed, with C<$success> being true
313 if everything went fine.
316 =head2 local_install( $module, $success )
318 Sent when C<$module> has been installed locally, with C<$success> return value.
321 =head2 local_status( $module, $is_installed )
323 Sent when C<$module> knows whether it is installed locally (C<$is_installed>
324 set to true) or not.
327 =head2 module_spawned( $module )
329 Sent when C<$module> has been spawned successfully.
332 =head2 package( $module )
334 Request the application to package (if needed) a C<$module> (an
335 C<App::CPAN2Pkg::Module> object).
338 =head2 prereqs( $module, @prereqs )
340 Inform main application that C<$module> needs some C<@prereqs> (possibly
341 empty).
344 =head2 upstream_import( $module, $success )
346 Sent when C<$module> package has been imported in upstream repository.
349 =head2 upstream_install( $module, $success )
351 Sent after trying to install C<$module> from upstream dist. Result is passed
352 along with C<$success>.
355 =head2 upstream_status( $module, $is_available )
357 Sent when C<$module> knows whether it is available upstream (C<$is_available>
358 set to true) or not.
362 =head1 BUGS
364 Please report any bugs or feature requests to C<app-cpan2pkg at
365 rt.cpan.org>, or through the web interface at
366 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=App-CPAN2Pkg>. I will
367 be notified, and then you'll automatically be notified of progress on
368 your bug as I make changes.
372 =head1 SEE ALSO
374 Our git repository is located at L<git://repo.or.cz/app-cpan2pkg.git>,
375 and can be browsed at L<http://repo.or.cz/w/app-cpan2pkg.git>.
378 You can also look for information on this module at:
380 =over 4
382 =item * AnnoCPAN: Annotated CPAN documentation
384 L<http://annocpan.org/dist/App-CPAN2Pkg>
386 =item * CPAN Ratings
388 L<http://cpanratings.perl.org/d/App-CPAN2Pkg>
390 =item * Open bugs
392 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=App-CPAN2Pkg>
394 =back
398 =head1 AUTHOR
400 Jerome Quelin, C<< <jquelin@cpan.org> >>
404 =head1 COPYRIGHT & LICENSE
406 Copyright (c) 2009 Jerome Quelin, all rights reserved.
408 This program is free software; you can redistribute it and/or modify
409 it under the same terms as Perl itself.
411 =cut