Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Module-Starter CPAN distribution.

Report information
The Basics
Id: 53539
Status: resolved
Priority: 0/
Queue: Module-Starter

People
Owner: XSAWYERX [...] cpan.org
Requestors: bdfoy [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Refactor Module::Starter::App and Module::Starter::Simple to allow easier subclassing
The Module::Starter::App process puts a lot of obstacles in the way of a subclass. The ::App class calls a class method (create_distro) in the implementing class, and it can't very well extend it unless it wants to let Module::Starter::Simple::create_distro call new(). Anyone could override it, but that's a lot of work to do if you want only a small tweak. The current setup doesn't give a reasonable subclass the chance to interact with the object until it's already in create_distro, and that's too late. Instead of all of that, I've modified the process to give subclasses more hooks into the process. To the end user, nothing should look or act differently. Current subclasses should still work. New subclasses can do much more using the hooks before and after ::App calls create_distro. With these fixes, which introduces a post_create_distro hook, create_distro only has to create the files it has to create. Anything later, such as creating MANIFEST, META.yml, or any other sort of post-processing, is a different step. Plugins don't have to override large chunks of code to do something extra. This would be a first step in solving my previous bug report about MANIFEST creation. Although the patch is from git, it's against the stuff I cloned from Google Code.
Subject: 0001--Refactor-Module-Starter-App-Module-Starter-Si.patch
From 26e4d06c8249a95d49d02e71290607fc1f88ac51 Mon Sep 17 00:00:00 2001 From: brian d foy <brian.d.foy@gmail.com> Date: Sat, 9 Jan 2010 16:05:30 +0100 Subject: [PATCH] * Refactor Module::Starter::App, Module::Starter::Simple for better access There shouldn't be any feature changes in this commit. I only refactored the stuff in Module::Starter::App and adjust the process to handle the refactoring. This allows much better control of the process for any subclasses. --- .gitignore | 4 ++ lib/Module/Starter.pm | 4 +- lib/Module/Starter/App.pm | 81 ++++++++++++++++++++++----------- lib/Module/Starter/BuilderSet.pm | 4 +- lib/Module/Starter/Plugin/Template.pm | 4 +- lib/Module/Starter/Simple.pm | 71 +++++++++++++++++++++------- t/starter-new.t | 22 +++++++++ 7 files changed, 139 insertions(+), 51 deletions(-) create mode 100644 .gitignore create mode 100644 t/starter-new.t diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2c0318 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +Makefile +blib +pm_to_blib diff --git a/lib/Module/Starter.pm b/lib/Module/Starter.pm index 516dcd4..9fa3446 100644 --- a/lib/Module/Starter.pm +++ b/lib/Module/Starter.pm @@ -10,11 +10,11 @@ Module::Starter - a simple starter kit for any module =head1 VERSION -version 1.54 +version 1.54_01 =cut -our $VERSION = '1.54'; +our $VERSION = '1.54_01'; =head1 SYNOPSIS diff --git a/lib/Module/Starter/App.pm b/lib/Module/Starter/App.pm index f2e711d..cfb04fe 100644 --- a/lib/Module/Starter/App.pm +++ b/lib/Module/Starter/App.pm @@ -9,15 +9,29 @@ Module::Starter::App - the code behind the command line program use warnings; use strict; -our $VERSION = '1.54'; +our $VERSION = '1.54_01'; +use File::Spec::Functions; use Getopt::Long; use Pod::Usage; use Carp qw( croak ); +sub _config_file { + my( $class ) = @_; + + my $configdir = $ENV{MODULE_STARTER_DIR} || ''; + if ( !$configdir && $ENV{HOME} ) { + $configdir = catfile( $ENV{HOME}, '.module-starter' ); + } + + + return catfile( $configdir, 'config' ); +} + sub _config_read { - my $filename = shift; + my( $class ) = @_; + my $filename = $class->_config_file; return unless -e $filename; open( my $config_file, '<', $filename ) @@ -29,30 +43,9 @@ sub _config_read { next if /\A\s*\Z/sm; if (/\A(\w+):\s*(.+)\Z/sm) { $config{$1} = $2; } } - return %config; -} - -=head2 run - - Module::Starter::App->run; - -This is equivalent to runnint F<module-starter>. Its behavior is still subject -to change. - -=cut - -sub run { - - my $configdir = $ENV{MODULE_STARTER_DIR} || ''; - if ( !$configdir && $ENV{HOME} ) { - $configdir = "$ENV{HOME}/.module-starter"; - } - - my %config = _config_read( "$configdir/config" ); # The options that accept multiple arguments must be set to an # arrayref - $config{plugins} = [ split /(?:\s*,\s*|\s+)/, $config{plugins} ] if $config{plugins}; $config{builder} = [ split /(?:\s*,\s*|\s+)/, $config{builder} ] if $config{builder}; @@ -60,6 +53,14 @@ sub run { $config{$key} = [] unless exists $config{$key}; } + return %config; +} + +sub _process_command_line { + my( $self, %config ) = @_; + + $config{argv} = [ @ARGV ]; + pod2usage(2) unless @ARGV; GetOptions( @@ -96,14 +97,40 @@ sub run { $config{class} ||= 'Module::Starter'; $config{builder} = ['ExtUtils::MakeMaker'] unless @{$config{builder}}; + + return %config; +} + +=head2 run + + Module::Starter::App->run; + +This is equivalent to running F<module-starter>. Its behavior is still subject +to change. + +=cut + +sub run { + my $class = shift; + + my %config = $class->_config_read; + + %config = $class->_process_command_line( %config ); eval "require $config{class};"; - croak "invalid starter class $config{class}: $@" if $@; - $config{class}->import(@{$config{plugins}}); + print "Class is $config{class}\n"; + croak "Could not load starter class $config{class}: $@" if $@; + + $config{class}->import( @{$config{plugins}} ); - $config{class}->create_distro( %config ); + my $starter = $config{class}->new( %config ); + $starter->postprocess_config; + $starter->pre_create_distro; + $starter->create_distro; + $starter->post_create_distro; + $starter->pre_exit; - print "Created starter directories and files\n"; + return 1; } 1; diff --git a/lib/Module/Starter/BuilderSet.pm b/lib/Module/Starter/BuilderSet.pm index 488898d..32df6f0 100644 --- a/lib/Module/Starter/BuilderSet.pm +++ b/lib/Module/Starter/BuilderSet.pm @@ -11,11 +11,11 @@ Module::Starter::BuilderSet - determine builder metadata =head1 VERSION -Version 1.54 +Version 1.54_01 =cut -our $VERSION = '1.54'; +our $VERSION = '1.54_01'; =head1 SYNOPSIS diff --git a/lib/Module/Starter/Plugin/Template.pm b/lib/Module/Starter/Plugin/Template.pm index 791b814..a5b86aa 100644 --- a/lib/Module/Starter/Plugin/Template.pm +++ b/lib/Module/Starter/Plugin/Template.pm @@ -10,11 +10,11 @@ Module::Starter::Plugin::Template - module starter with templates =head1 VERSION -Version 1.54 +Version 1.54_01 =cut -our $VERSION = '1.54'; +our $VERSION = '1.54_01'; =head1 SYNOPSIS diff --git a/lib/Module/Starter/Simple.pm b/lib/Module/Starter/Simple.pm index bb942cc..be4ed44 100644 --- a/lib/Module/Starter/Simple.pm +++ b/lib/Module/Starter/Simple.pm @@ -15,11 +15,11 @@ Module::Starter::Simple - a simple, comprehensive Module::Starter plugin =head1 VERSION -Version 1.54 +Version 1.54_01 =cut -our $VERSION = '1.54'; +our $VERSION = '1.54_01'; =head1 SYNOPSIS @@ -36,6 +36,42 @@ the directories with the required files. =head1 CLASS METHODS +=head2 C<< new(%args) >> + +This method is called to construct and initialize a new Module::Starter object. +It is never called by the end user, only internally by C<create_distro>, which +creates ephemeral Module::Starter objects. It's documented only to call it to +the attention of subclass authors. + +=cut + +sub new { + my $class = shift; + return bless { @_ } => $class; +} + +=head1 OBJECT METHODS + +All the methods documented below are object methods, meant to be called +internally by the ephemperal objects created during the execution of the class +method C<create_distro> above. + +=head2 postprocess_config + +A hook to do any work after the configuration is initially processed. + +=cut + +sub postprocess_config { 1 }; + +=head2 pre_create_distro + +A hook to do any work right before the distro is created. + +=cut + +sub pre_create_distro { 1 }; + =head2 C<< create_distro(%args) >> This method works as advertised in L<Module::Starter>. @@ -43,10 +79,11 @@ This method works as advertised in L<Module::Starter>. =cut sub create_distro { - my $class = shift; - - my $self = $class->new( @_ ); + my $either = shift; + $either = $either->new( @_ ) unless( ref $either ); + my $self = $either; + my $modules = $self->{modules} || []; my @modules = map { split /,/ } @{$modules}; croak "No modules specified.\n" unless @modules; @@ -86,25 +123,23 @@ sub create_distro { return; } -=head2 C<< new(%args) >> +=head2 post_create_distro -This method is called to construct and initialize a new Module::Starter object. -It is never called by the end user, only internally by C<create_distro>, which -creates ephemeral Module::Starter objects. It's documented only to call it to -the attention of subclass authors. +A hook to do any work after creating the distribution. =cut -sub new { - my $class = shift; - return bless { @_ } => $class; -} +sub post_create_distro { 1 }; -=head1 OBJECT METHODS +=head2 pre_exit -All the methods documented below are object methods, meant to be called -internally by the ephemperal objects created during the execution of the class -method C<create_distro> above. +A hook to do any work right before exit time. + +=cut + +sub pre_exit { + print "Created starter directories and files\n"; +} =head2 create_basedir diff --git a/t/starter-new.t b/t/starter-new.t new file mode 100644 index 0000000..8f65502 --- /dev/null +++ b/t/starter-new.t @@ -0,0 +1,22 @@ +#!perl + +use strict; +use warnings; + +use Test::More 'no_plan'; + +my $class = 'Module::Starter'; +my $method = 'new'; + +use_ok( $class ); +ok( grep /Module::Starter::Simple/, get_isa( $class ) ); +can_ok( $class, $method ); + +my $object = $class->$method(); +isa_ok( $object, $class ); + +sub get_isa { + my $class = shift; + no strict 'refs'; + @{ "${class}::ISA" }; +} -- 1.6.2.5
Hey I've implemented the code in the patch manually in my local git clone. The tests are good. Once it'll be in the trunk (hopefully tomorrow), I'll resolve the ticket. Kodus, Brian, and thanks for the patch! :) Sawyer.
Subject: Re: [rt.cpan.org #53539] Refactor Module::Starter::App and Module::Starter::Simple to allow easier subclassing
Date: Thu, 14 Jan 2010 00:22:40 +0100
To: bug-Module-Starter [...] rt.cpan.org
From: brian d foy <bdfoy [...] cpan.org>
On Thu, Jan 14, 2010 at 12:04 AM, Sawyer X via RT <bug-Module-Starter@rt.cpan.org> wrote: Show quoted text
> I've implemented the code in the patch manually in my local git clone.
If we're using Git, maybe we should start using Github. That would make things easier :) -- brian d foy <brian.d.foy@gmail.com> http://www.pair.com/~comdog/
On Wed Jan 13 18:23:19 2010, BDFOY wrote: Show quoted text
> On Thu, Jan 14, 2010 at 12:04 AM, Sawyer X via RT > <bug-Module-Starter@rt.cpan.org> wrote: >
> > I've implemented the code in the patch manually in my local git clone.
> > If we're using Git, maybe we should start using Github. That would > make things easier :)
Agreed. I prefer Github as well. I'll check into moving module-starter codebase there.
On Wed Jan 13 18:04:34 2010, xsawyerx wrote: Show quoted text
> I've implemented the code in the patch manually in my local git clone. > The tests are good.
http://code.google.com/p/module-starter/source/detail?r=83 It's in the trunk. I decided to resolve it only once there's a new version out with it.
Show quoted text
> I decided to resolve it only once there's a new version out with it.
Any ETA on where there will be a new version?
Already out for a while. Resolving the ticket.