Module-Starter-Smart-0.0.9/000755 000765 000024 00000000000 13205771516 016616 5ustar00rueychengstaff000000 000000 Module-Starter-Smart-0.0.9/Changes000644 000765 000024 00000001513 13205770205 020103 0ustar00rueychengstaff000000 000000 Revision history for Module-Starter-Smart 0.0.9 Nov 24, 2017 * Bug fixes 0.0.8 Jun 4, 2017 * Bug fixes for tests 0.0.7 Jun 1, 2017 * Fix inconsistencies with more recent releases of Module::Starter::Simple (Markus Böhme) * Some more bug fixes 0.0.6 Jan 30, 2015 * Some amendments to the code for clarity and a new test for basic function (Andrew Kirkpatrick) 0.0.5 Jan 18, 2014 * Fix typos and update CPAN metadata (David Steinbrunner) 0.0.4 Mar 29, 2012 * Fix broken dependency 0.0.3 Mar 28, 2012 * Fix RT 72565: Revise use cases * Rewrite create_distro() according to the latest version of Module::Starter::Simple (1.58) * Explicitly subclass Module::Starter::Simple, thanks to brian d foy's suggestion. 0.0.2 Apr 3, 2007 * Add use cases 0.0.1 May 7, 2006 * Initial release Module-Starter-Smart-0.0.9/lib/000755 000765 000024 00000000000 13205771516 017364 5ustar00rueychengstaff000000 000000 Module-Starter-Smart-0.0.9/Makefile.PL000644 000765 000024 00000002555 13205770040 020566 0ustar00rueychengstaff000000 000000 use strict; use warnings; use ExtUtils::MakeMaker; WriteMakefile( NAME => 'Module::Starter::Smart', AUTHOR => 'Ruey-Cheng Chen ', VERSION_FROM => 'lib/Module/Starter/Smart.pm', ABSTRACT_FROM => 'lib/Module/Starter/Smart.pm', MIN_PERL_VERSION => 5.6.0, PL_FILES => {}, LICENSE => 'perl', BUILD_REQUIRES => { 'ExtUtils::MakeMaker' => 6.48, 'File::Spec' => 0, 'parent' => 0, 'Module::Starter' => 1.58, 'Test::More' => 0, 'Test::TempDir::Tiny' => 0, }, PREREQ_PM => { 'ExtUtils::Command' => 0, 'File::Spec' => 0, 'parent' => 0, 'Module::Starter' => 1.58, 'Test::More' => 0, 'Test::TempDir::Tiny' => 0, }, META_MERGE => { 'meta-spec' => { version => 2 }, resources => { repository => { type => 'git', url => 'https://github.com/rueycheng/Module-Starter-Smart.git', web => 'https://github.com/rueycheng/Module-Starter-Smart', }, }, }, dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, clean => { FILES => 'Module-Starter-Smart-*' }, ); Module-Starter-Smart-0.0.9/MANIFEST000644 000765 000024 00000000450 13205771516 017746 0ustar00rueychengstaff000000 000000 Changes MANIFEST META.yml # Will be created by "make dist" Makefile.PL README lib/Module/Starter/Smart.pm t/00.load.t t/01.create_distro.t t/02.create_t.t t/03.create_distro_with_build.t t/pod-coverage.t t/pod.t META.json Module JSON meta-data (added by MakeMaker) Module-Starter-Smart-0.0.9/META.json000644 000765 000024 00000003116 13205771516 020240 0ustar00rueychengstaff000000 000000 { "abstract" : "A Module::Starter plugin for adding new modules into an existing distribution", "author" : [ "Ruey-Cheng Chen " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Module-Starter-Smart", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "6.48", "File::Spec" : "0", "Module::Starter" : "1.58", "Test::More" : "0", "Test::TempDir::Tiny" : "0", "parent" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "ExtUtils::Command" : "0", "File::Spec" : "0", "Module::Starter" : "1.58", "Test::More" : "0", "Test::TempDir::Tiny" : "0", "parent" : "0", "perl" : "5.006000" } } }, "release_status" : "stable", "resources" : { "repository" : { "type" : "git", "url" : "https://github.com/rueycheng/Module-Starter-Smart.git", "web" : "https://github.com/rueycheng/Module-Starter-Smart" } }, "version" : "v0.0.9", "x_serialization_backend" : "JSON::PP version 2.27400_02" } Module-Starter-Smart-0.0.9/META.yml000644 000765 000024 00000001643 13205771516 020073 0ustar00rueychengstaff000000 000000 --- abstract: 'A Module::Starter plugin for adding new modules into an existing distribution' author: - 'Ruey-Cheng Chen ' build_requires: ExtUtils::MakeMaker: '6.48' File::Spec: '0' Module::Starter: '1.58' Test::More: '0' Test::TempDir::Tiny: '0' parent: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Module-Starter-Smart no_index: directory: - t - inc requires: ExtUtils::Command: '0' File::Spec: '0' Module::Starter: '1.58' Test::More: '0' Test::TempDir::Tiny: '0' parent: '0' perl: '5.006000' resources: repository: https://github.com/rueycheng/Module-Starter-Smart.git version: v0.0.9 x_serialization_backend: 'CPAN::Meta::YAML version 0.018' Module-Starter-Smart-0.0.9/README000644 000765 000024 00000001076 13205770464 017503 0ustar00rueychengstaff000000 000000 Module-Starter-Smart version 0.0.9 INSTALLATION To install this module, run the following commands: perl Makefile.PL make && make test && make install DEPENDENCIES ExtUtils::Command File::Spec Module::Starter::Simple Test::More Test::TempDir::Tiny parent CONTRIBUTORS * Ruey-Cheng Chen * David Messina * David Steinbrunner * Andrew Kirkpatrick * Markus Böhme * Lisa Hare COPYRIGHT AND LICENCE Copyright (C) 2006, 2011, 2012, 2017 Ruey-Cheng Chen This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Module-Starter-Smart-0.0.9/t/000755 000765 000024 00000000000 13205771516 017061 5ustar00rueychengstaff000000 000000 Module-Starter-Smart-0.0.9/t/00.load.t000644 000765 000024 00000000232 13205764301 020372 0ustar00rueychengstaff000000 000000 use Test::More tests => 1; BEGIN { use_ok( 'Module::Starter::Smart' ); } diag( "Testing Module::Starter::Smart $Module::Starter::Smart::VERSION" ); Module-Starter-Smart-0.0.9/t/01.create_distro.t000644 000765 000024 00000002335 13205764301 022311 0ustar00rueychengstaff000000 000000 use Test::More tests => 5; use Test::TempDir::Tiny; use Module::Starter qw/Module::Starter::Smart/; use File::Spec; my $tempdir = tempdir(); my $root = File::Spec->catdir($tempdir, 'Modern-Mo'); { local $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /^Added to MANIFEST/; }; Module::Starter->create_distro( author => 'me', builder => 'ExtUtils::MakeMaker', modules => ['Modern::Mo'], email => 'me@there.com', dir => $root, ); } ok(-d $root, 'Module root exists'); my $file = File::Spec->catfile($root, qw(lib Modern Mo.pm)); ok(-f $file, 'Module file exists'); push @INC, File::Spec->catdir($root, 'lib'); require_ok('Modern::Mo'); { local $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /^Added to MANIFEST/; }; Module::Starter->create_distro( author => 'me', builder => 'ExtUtils::MakeMaker', modules => ['Modern::Mumu'], email => 'me@there.com', dir => $root, ); } # ok(-d $root, 'Module root exists'); my $file = File::Spec->catfile($root, qw(lib Modern Mumu.pm)); ok(-f $file, 'Additional module file exists'); # push @INC, File::Spec->catdir($root, 'lib'); require_ok('Modern::Mumu'); Module-Starter-Smart-0.0.9/t/02.create_t.t000644 000765 000024 00000003323 13205764301 021247 0ustar00rueychengstaff000000 000000 use strict; use warnings; use Test::More; use Test::TempDir::Tiny; use File::Spec::Functions qw(catdir catfile); use Module::Starter qw(Module::Starter::Smart); my $content = <<"EOF"; I think that I shall never see, a test as concise as this in ./t! EOF test_old_interface(); test_new_interface(); done_testing(); sub test_old_interface { my $tempdir = tempdir(); my $tdir = catdir($tempdir, 't'); my $testfile = '01.test_old_interface.t'; my $starter = Module::Starter::Smart->new(); $starter->{basedir} = $tempdir; Module::Starter::Smart::_create_t($starter, $testfile, $content); file_contains_ok(catfile($tdir, $testfile), $content); } sub test_new_interface { my $tempdir = tempdir(); my $tdir = catdir($tempdir, 't'); my $xtdir = catdir($tempdir, 'xt'); my $testfile1 = '01.test_new_interface.t'; my $testfile2 = '02.test_new_interface.t'; my $starter = Module::Starter::Smart->new(); $starter->{basedir} = $tempdir; Module::Starter::Smart::_create_t($starter, 't', $testfile1, $content); Module::Starter::Smart::_create_t($starter, 'xt', $testfile2, $content); file_contains_ok(catfile($tdir, $testfile1), $content); file_contains_ok(catfile($xtdir, $testfile2), $content); } sub file_contains_ok { my $file = shift; my $expected_content = shift; SKIP: { skip "File '$file' does not exist or is unreadable", 1 unless ok(-f -r $file, "File '$file' exists and is readable"); open my $fh, '<', $file or die "Cannot open $file: $!\n"; my $real_content = do { local $/; <$fh> }; close $fh; ok($expected_content eq $real_content, "File '$file' has correct content"); } } Module-Starter-Smart-0.0.9/t/03.create_distro_with_build.t000644 000765 000024 00000001356 13205770040 024524 0ustar00rueychengstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Test::More tests => 3; use Test::TempDir::Tiny; use Module::Starter qw/Module::Starter::Smart/; use File::Spec; my $tempdir = tempdir(); my $root = File::Spec->catdir($tempdir, 'Foo-Bar'); { local $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /^Added to MANIFEST/; }; Module::Starter->create_distro( author => 'me', builder => 'Module::Build', modules => ['Foo::Bar'], email => 'me@there.com', dir => $root, ); } ok(-d $root, 'Module root exists'); my $file = File::Spec->catfile($root, qw(lib Foo Bar.pm)); ok(-f $file, 'Module file exists'); push @INC, File::Spec->catdir($root, 'lib'); require_ok('Foo::Bar'); Module-Starter-Smart-0.0.9/t/pod-coverage.t000644 000765 000024 00000000410 13205764301 021606 0ustar00rueychengstaff000000 000000 #!perl -T use Test::More; eval "use Test::Pod::Coverage 1.04"; plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@; plan tests => 1; my $trustme = { trustme => [qr/^create_/] }; pod_coverage_ok('Module::Starter::Smart', $trustme); Module-Starter-Smart-0.0.9/t/pod.t000644 000765 000024 00000000214 13205764301 020017 0ustar00rueychengstaff000000 000000 #!perl -T use Test::More; eval "use Test::Pod 1.14"; plan skip_all => "Test::Pod 1.14 required for testing POD" if $@; all_pod_files_ok(); Module-Starter-Smart-0.0.9/lib/Module/000755 000765 000024 00000000000 13205771516 020611 5ustar00rueychengstaff000000 000000 Module-Starter-Smart-0.0.9/lib/Module/Starter/000755 000765 000024 00000000000 13205771516 022235 5ustar00rueychengstaff000000 000000 Module-Starter-Smart-0.0.9/lib/Module/Starter/Smart.pm000644 000765 000024 00000025206 13205770555 023670 0ustar00rueychengstaff000000 000000 package Module::Starter::Smart; use warnings; use strict; =encoding utf8 =head1 NAME Module::Starter::Smart - A Module::Starter plugin for adding new modules into an existing distribution =head1 VERSION version 0.0.9 =cut our $VERSION = '0.0.9'; =head1 SYNOPSIS use Module::Starter qw/Module::Starter::Smart/; Module::Starter->create_distro(%args); # or in ~/.module-starter/config plugin: Module::Starter::Smart # create a new distribution named 'Foo-Bar' $ module-starter --module=Foo::Bar # ... then add a new module $ module-starter --module=Foo::Bar::Me --distro=Foo-Bar =head1 DESCRIPTION Module::Starter::Smart is a simple helper plugin for L. It subclasses L and provides its own implementation for several file creation subroutines, such as C, C, C, and so on. These new implementations were designed to work with existing distributions. When invoked, the plugin checks if the distribution is already created. If so, the plugin would bypass C) and go ahead pull in all the existing modules and test files; these information would be used later in the corresponding file creation subroutines for skipping already-created files. B: This plugin only covers the simplest use cases. For advanced usage, check out L. =head2 Example Say you have an existing distro, Goof-Ball, and you want to add a new module, Goof::Troop. % ls -R Goof-Ball Build.PL Changes MANIFEST README lib/ t/ Goof-Ball/lib: Goof/ Goof-Ball/lib/Goof: Ball.pm Goof-Ball/t: 00.load.t perlcritic.t pod-coverage.t pod.t Go to the directory containing your existing distribution and run module-starter, giving it the names of the existing distribution and the new module: % module-starter --distro=Goof-Ball --module=Goof::Troop Created starter directories and files % ls -R Goof-Ball Build.PL Changes MANIFEST README lib/ t/ Goof-Ball/lib: Goof/ Goof-Ball/lib/Goof: Ball.pm Troop.pm Goof-Ball/t: 00.load.t perlcritic.t pod-coverage.t pod.t Troop.pm has been added to Goof-Ball/lib/Goof. =cut use parent qw(Module::Starter::Simple); use ExtUtils::Command qw/mkpath/; use File::Spec; # Module implementation here use subs qw/_unique_sort _pull_modules _list_modules _pull_t _list_t/; =head1 INTERFACE No public methods. The module works by subclassing Module::Starter::Simple and rewiring its internal behaviors. =cut sub create_distro { my $class = shift; my $self = ref $class? $class: $class->new(@_); my $basedir = $self->{dir} || $self->{distro} || do { (my $first = $self->{modules}[0]) =~ s/::/-/g; $first; }; $self->{modules} = [ _unique_sort _pull_modules($basedir), @{$self->{modules}} ]; $self->SUPER::create_distro; } sub create_basedir { my $self = shift; return $self->SUPER::create_basedir(@_) unless -e $self->{basedir} && !$self->{force}; $self->progress( "Found $self->{basedir}. Use --force if you want to stomp on it." ); } sub create_modules { my $self = shift; $self->SUPER::create_modules(@_); } sub _create_module { my $self = shift; my $module = shift; my $rtname = shift; my @parts = split( /::/, $module ); my $filepart = (pop @parts) . ".pm"; my @dirparts = ( $self->{basedir}, 'lib', @parts ); my $manifest_file = join( "/", "lib", @parts, $filepart ); if ( @dirparts ) { my $dir = File::Spec->catdir( @dirparts ); if ( not -d $dir ) { local @ARGV = $dir; mkpath @ARGV; $self->progress( "Created $dir" ); } } my $module_file = File::Spec->catfile( @dirparts, $filepart ); $self->{module_file}{$module} = File::Spec->catfile('lib', @parts, $filepart); if (-e $module_file) { $self->progress( "Skipped $module_file" ); } else { open( my $fh, ">", $module_file ) or die "Can't create $module_file: $!\n"; print $fh $self->module_guts( $module, $rtname ); close $fh; $self->progress( "Created $module_file" ); } return $manifest_file; } sub create_t { my $self = shift; _unique_sort $self->SUPER::create_t(@_), _pull_t $self->{basedir}; } sub _create_t { my $self = shift; my $testdir = @_ == 2 ? 't' : shift; my $filename = shift; my $content = shift; my @dirparts = ( $self->{basedir}, $testdir ); my $tdir = File::Spec->catdir( @dirparts ); if ( not -d $tdir ) { local @ARGV = $tdir; mkpath(); $self->progress( "Created $tdir" ); } my $fname = File::Spec->catfile( @dirparts, $filename ); if (-e $fname) { $self->progress( "Skipped $fname" ); } else { open( my $fh, ">", $fname ) or die "Can't create $fname: $!\n"; print $fh $content; close $fh; $self->progress( "Created $fname" ); } return File::Spec->catfile( $testdir, $filename ); } sub create_Makefile_PL { my $self = shift; my $main_module = shift; my @parts = split( /::/, $main_module ); my $pm = pop @parts; my $main_pm_file = File::Spec->catfile( "lib", @parts, "${pm}.pm" ); $main_pm_file =~ s{\\}{/}g; # even on Win32, use forward slash my $fname = File::Spec->catfile( $self->{basedir}, "Makefile.PL" ); if (-e $fname) { $self->progress( "Skipped $fname" ); } else { open( my $fh, ">", $fname ) or die "Can't create $fname: $!\n"; print $fh $self->Makefile_PL_guts($main_module, $main_pm_file); close $fh; $self->progress( "Created $fname" ); } return "Makefile.PL"; } sub create_Build_PL { my $self = shift; my $main_module = shift; my @parts = split( /::/, $main_module ); my $pm = pop @parts; my $main_pm_file = File::Spec->catfile( "lib", @parts, "${pm}.pm" ); $main_pm_file =~ s{\\}{/}g; # even on Win32, use forward slash my $fname = File::Spec->catfile( $self->{basedir}, "Build.PL" ); if (-e $fname) { $self->progress( "Skipped $fname" ); } else { open( my $fh, ">", $fname ) or die "Can't create $fname: $!\n"; print $fh $self->Build_PL_guts($main_module, $main_pm_file); close $fh; $self->progress( "Created $fname" ); } return "Build.PL"; } sub create_Changes { my $self = shift; my $fname = File::Spec->catfile( $self->{basedir}, "Changes" ); if (-e $fname) { $self->progress( "Skipped $fname" ); } else { open( my $fh, ">", $fname ) or die "Can't create $fname: $!\n"; print $fh $self->Changes_guts(); close $fh; $self->progress( "Created $fname" ); } return "Changes"; } sub create_README { my $self = shift; my $build_instructions = shift; my $fname = File::Spec->catfile( $self->{basedir}, "README" ); if (-e $fname) { $self->progress( "Skipped $fname" ); } else { open( my $fh, ">", $fname ) or die "Can't create $fname: $!\n"; print $fh $self->README_guts($build_instructions); close $fh; $self->progress( "Created $fname" ); } return "README"; } # Utility functions sub _pull_modules { my $basedir = shift; return unless $basedir; my $libdir = File::Spec->catdir($basedir, "lib"); return unless $libdir && -d $libdir; return _list_modules($libdir); } sub _list_modules { my $dir = shift; my $prefix = shift || ''; opendir my $dh, $dir or die "Cannot opendir $dir: $!"; my @entries = grep { !/^\.{1,2}/ } readdir $dh; close $dh; my @modules = (); for (@entries) { my $name = File::Spec->catfile($dir, $_); push @modules, _list_modules($name, $prefix ? "$prefix\:\:$_": $_) and next if -d $name; $_ =~ s/\.pm$// and push @modules, $prefix ? "$prefix\:\:$_": $_ if $name =~ /\.pm$/; } return sort @modules; } sub _pull_t { my $basedir = shift; return unless $basedir; my $tdir = File::Spec->catdir($basedir, "t"); return unless $tdir && -d $tdir; return _list_t($tdir); } sub _list_t { my $dir = shift; opendir my $dh, $dir or die "Cannot opendir $dir: $!"; my @entries = grep { !/^\.{1,2}/ && /\.t$/ } readdir $dh; close $dh; map { "t/$_" } @entries; } # Remove duplicated entries sub _unique_sort { my %bag = map { $_ => 1 } @_; sort keys %bag; } # Magic true value required at end of module 1; __END__ =head1 DEPENDENCIES Module::Starter::Smart subclasses L. =head1 INCOMPATIBILITIES The plugin works perfectly with other template plugins, i.e. L (I started using it to develop this module) =head1 BUGS AND LIMITATIONS Please report any bugs or feature requests to C, or through the web interface at L. =head1 ACKNOWLEDGEMENT Special thanks to the following contributors: =over 4 =item * David Messina =item * David Steinbrunner =item * Andrew Kirkpatrick =item * Markus Böhme =item * Lisa Hare =back =head1 AUTHOR Ruey-Cheng Chen C<< >> =head1 LICENCE AND COPYRIGHT Copyright (c) 2006, 2012, 2017 Ruey-Cheng Chen C<< >>. All rights reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.