SlideShare una empresa de Scribd logo
1 de 226
Descargar para leer sin conexión
Dist::Zilla
                             raaaaaaaaar!




Tuesday, December 14, 2010
What is Dist::Zilla?


Tuesday, December 14, 2010
This talk is about your life as a CPAN author.
AWESOME

Tuesday, December 14, 2010
Any
            Questions?
Tuesday, December 14, 2010
RJBS

Tuesday, December 14, 2010
ME!!!

also awesome!

I give away almost all my useful software on CPAN
RJBS
                   - cake and pie (and doughnuts)




Tuesday, December 14, 2010
ME!!!

also awesome!

I give away almost all my useful software on CPAN
RJBS
                   - cake and pie (and doughnuts)
                   - cocktails and beer



Tuesday, December 14, 2010
ME!!!

also awesome!

I give away almost all my useful software on CPAN
RJBS
                   - cake and pie (and doughnuts)
                   - cocktails and beer
                   - shooting zombies


Tuesday, December 14, 2010
ME!!!

also awesome!

I give away almost all my useful software on CPAN
RJBS
                   - cake and pie (and doughnuts)
                   - cocktails and beer
                   - shooting zombies
                   - giving away useful software

Tuesday, December 14, 2010
ME!!!

also awesome!

I give away almost all my useful software on CPAN
CPAN!
Tuesday, December 14, 2010
CPAN is awesome, too. We all know that.
being a CPAN author is hard!
                                            let’s go gemming!




Tuesday, December 14, 2010
who here is a CPAN author?

what makes it a pain? let’s talk about it
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
this is all the crap in your working copy where you write this dist
making all these is a boring pain in the butt
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
and a bunch of semi-structured data is in Makefile.PL
ExtUtils::MakeMaker



Tuesday, December 14, 2010
WriteMakefile(
               NAME          => ‘YourApp’,
               AUTHOR        => ‘You <rjbs@cpan.org>’,
               VERSION_FROM => ‘lib/YourApp.pm’,
               ABSTRACT_FROM => ‘lib/YourApp.pm’,
               LICENSE       => ‘perl’,
               PREREQ_PM => {
                 ‘Lingua::EN::Inflect’ => 1.86,
                 ‘Sub::Override’       => 0.07,
                 ‘Test::More’          => 0,
               },
             );




Tuesday, December 14, 2010
Then you have to put a bunch more information describing your distribution into Makefile.PL, if you’re using
ExtUtils::MakeMaker.
WriteMakefile(
               NAME          => ‘YourApp’,
               AUTHOR        => ‘You <rjbs@cpan.org>’,
               VERSION_FROM => ‘lib/YourApp.pm’,
               ABSTRACT_FROM => ‘lib/YourApp.pm’,
               LICENSE       => ‘perl’,
               PREREQ_PM => {
                 ‘Lingua::EN::Inflect’ => 1.86,
                 ‘Sub::Override’       => 0.07,
                 ‘Test::More’          => 0,
               },
               (eval { ExtUtils::MakeMaker->VERSION(6.46) }
               ? (META_MERGE => {
                   resources => { Repository => ‘...’ }
                  })
               : ()),
             );



Tuesday, December 14, 2010
If you want to add more metadata, you start having to use really gross constructions, trying to avoid backcompat issues. In part,
this is because even the data only needed for installing the dist (like your respository) is present and executed on the installing
user’s computer.
Module::Install



Tuesday, December 14, 2010
use inc::Module::Install;
             all_from(‘lib/YourApp.pm’);

             requires(‘Lingua::EN::Inflect’ => 1.86);
             requires(‘Sub::Override’       => 0.07);
             requires(‘Test::More’          => 0);

             repository(...);

             WriteAll();




Tuesday, December 14, 2010
Module::Install lets you write this, instead. It does a lot more auto-detection by reading your Pod and trying to parse its
meaning. Then it runs on the installer’s machine and uses the machinery of ExtUtils::MakeMaker to build a plain old Makefile for
installation. So, it bundles itself with each dist that uses it, and it’s still beholden to the version of EUMM installed on the user’s
machine. Still, it saves quite a lot of time in dealing with stupid crap in Makefile.PL.

It just means you need to write a bunch of other stuff for it to scan, like:
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
You need to have your author in the main module to be detected, and the license. Then, because you want to keep the data in
each library, you have to keep that same data in each Perl module. Copy and paste!
Module::Starter



Tuesday, December 14, 2010
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/boilerplate.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
It can create all these files, Pod and all, *for* you so you don’t have to go through this drudgery. Unfortunately, some of these
files include stuff that you’re going to need to customize, replace, or delete immediately upon starting the dist. So many people
used Module::Starter and then left in garbage data that we added a test to help stop them from doing so...
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/boilerplate.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
It looks for the stock content you should get rid of. Once this test passes, you are expected to delete it. Why have that
boilerplate crap at all?

Worse, what if one of your boilerplate files has a typo? Or what if you want to change your default pod-coverage setup? You
need to go update every file in all of your distributions, because that file actually exists in your source repository.
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
Dist::Zilla tries to solve all these problems: don’t repeat yourself; don’t store what you can compute; rely on the installing user
having only the bare minimum of tools needed to install, and don’t bundle more if you can help it.

It also tries hard to be easy to test, so that when you write extensions to DZ, they’re easy to write and easy to test. EUMM, M:I,
and Starter are not.

I’m going to show you how to eliminate as much of this as you can so there’s less to write, less to update, less to diff, and less
to think about in general.
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files we can get rid of entirely)
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files from which we can prune lots of non-essential content)

...and it can do more than just reduce the on-disk content...
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files from which we can prune lots of non-essential content)

...and it can do more than just reduce the on-disk content...
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files from which we can prune lots of non-essential content)

...and it can do more than just reduce the on-disk content...
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files from which we can prune lots of non-essential content)

...and it can do more than just reduce the on-disk content...
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files from which we can prune lots of non-essential content)

...and it can do more than just reduce the on-disk content...
./Changes
             ./LICENSE
             ./MANIFEST.SKIP
             ./Makefile.PL
             ./README
             ./lib/YourApp.pm
             ./lib/YourApp/Reticulator.pm
             ./lib/YourApp/Util/mtfnpy.pm
             ./lib/YourApp/Xyzzy.pm
             ./t/unit-tests.t
             ./t/pod-coverage.t
             ./t/pod.t



Tuesday, December 14, 2010
(files from which we can prune lots of non-essential content)

...and it can do more than just reduce the on-disk content...
Tuesday, December 14, 2010



...and that’s why
- updating version numbers




Tuesday, December 14, 2010



...and that’s why
- updating version numbers
                   - uploading to CPAN




Tuesday, December 14, 2010



...and that’s why
- updating version numbers
                   - uploading to CPAN
                   - committing, tagging releases in Git (VCS)




Tuesday, December 14, 2010



...and that’s why
- updating version numbers
                   - uploading to CPAN
                   - committing, tagging releases in Git (VCS)
                   - determine prerequisites


Tuesday, December 14, 2010



...and that’s why
- updating version numbers
                   - uploading to CPAN
                   - committing, tagging releases in Git (VCS)
                   - determine prerequisites
                   - other stuff that is totally boring

Tuesday, December 14, 2010



...and that’s why
Dist::Zilla is
                             AWESOME

Tuesday, December 14, 2010
...because it frees you up to do things that are much more interesting than distribution building, like...
Tuesday, December 14, 2010
- eating cake and pie (and donuts)




Tuesday, December 14, 2010
- eating cake and pie (and donuts)
                   - drinking cocktails and beer



Tuesday, December 14, 2010
- eating cake and pie (and donuts)
                   - drinking cocktails and beer
                   - shooting zombies


Tuesday, December 14, 2010
- eating cake and pie (and donuts)
                   - drinking cocktails and beer
                   - shooting zombies
                   - giving away useful software

Tuesday, December 14, 2010
Dist::Zilla is
                               HUGE

Tuesday, December 14, 2010
106 prereqs

Tuesday, December 14, 2010
106 prereqs
                               (and counting)



Tuesday, December 14, 2010
Tuesday, December 14, 2010
- Dist::Zilla only handles “make dist”




Tuesday, December 14, 2010
- Dist::Zilla only handles “make dist”
                   - it doesn’t handle “make install”




Tuesday, December 14, 2010
- Dist::Zilla only handles “make dist”
                   - it doesn’t handle “make install”
                   - only authors need to install the 106 prereqs




Tuesday, December 14, 2010
- Dist::Zilla only handles “make dist”
                   - it doesn’t handle “make install”
                   - only authors need to install the 106 prereqs
                   - your users don’t see Dist::Zilla



Tuesday, December 14, 2010
- Dist::Zilla only handles “make dist”
                   - it doesn’t handle “make install”
                   - only authors need to install the 106 prereqs
                   - your users don’t see Dist::Zilla
                   - they just see MakeMaker or Module::Build


Tuesday, December 14, 2010
Dist::Zilla is also Stupid



Tuesday, December 14, 2010
like me!
It keeps its brains in
                                   plugins.


Tuesday, December 14, 2010
Almost all of the remainder of this talk is going to be about DZ plugins, because they do all the work. DZ itself just orchestrates
the interaction of plugins. When you use Dist::Zilla, you provide it with a configuration file that sets up your plugins.
dist.ini



Tuesday, December 14, 2010
It’s almost always an INI file. INI is a nice simple format, and I’m going to just assume everybody understands it. Here’s a
sample dist.ini:
name    = Your-Dist
             license = Perl_5
             copyright_holder = J.builds a dist:
             # How Dist::Zilla Fred Bloggs
             [GatherDir]
             prepare;
             include_dotfiles = 1
             gather_files;
             prune_files;
             [PruneCruft]
             munge_files;
             [MetaYAML]
             [MakeMaker]
             register_prereqs;
             [TestRelease]
             setup_installer;
             [ConfirmRelease]
             write_files;
             finish;
             [UploadToCPAN]
             user = JFB
             password = QwardRules


Tuesday, December 14, 2010
You can do lots of different things in really varied ways, and there are people who use Dist::Zilla with very different workflows to
mine.

But I’m going to talk about how I use Dist::Zilla, which by grand coincidence is the one reflected in the tutorial and is probably
the most common workflow.
name    = Your-Dist
             license = Perl_5
             copyright_holder = J.builds a dist:
             # How Dist::Zilla Fred Bloggs
             [GatherDir]
             prepare;
             include_dotfiles = 1
             gather_files;
             prune_files;
             [PruneCruft]
             munge_files;
             [MetaYAML]
             [MakeMaker]
             register_prereqs;
             [TestRelease]
             setup_installer;
             [ConfirmRelease]
             write_files;
             finish;
             [UploadToCPAN]
             user = JFB
             password = QwardRules


Tuesday, December 14, 2010
the root section generally describes the dist itself, and is pretty short
name    = Your-Dist
             license = Perl_5
             copyright_holder = J.builds a dist:
             # How Dist::Zilla Fred Bloggs
             [GatherDir]
             prepare;
             include_dotfiles = 1
             gather_files;
             prune_files;
             [PruneCruft]
             munge_files;
             [MetaYAML]
             [MakeMaker]
             register_prereqs;
             [TestRelease]
             setup_installer;
             [ConfirmRelease]
             write_files;
             finish;
             [UploadToCPAN]
             user = JFB
             password = QwardRules


Tuesday, December 14, 2010
here’s a section that defined a plugin, with one option set
name    = Your-Dist
             license = Perl_5
             copyright_holder = J.builds a dist:
             # How Dist::Zilla Fred Bloggs
             [GatherDir]
             prepare;
             include_dotfiles = 1
             gather_files;
             prune_files;
             [PruneCruft]
             munge_files;
             [MetaYAML]
             [MakeMaker]
             register_prereqs;
             [TestRelease]
             setup_installer;
             [ConfirmRelease]
             write_files;
             finish;
             [UploadToCPAN]
             user = JFB
             password = QwardRules


Tuesday, December 14, 2010
and this line sets up a plugin with no args -- the next line is just another plugin
name    = Dist-Zilla
             author = Ricardo SIGNES <rjbs@cpan.org>
             license = Perl_5
             copyright_holder = Ricardo SIGNES

             [@Basic]
             [AutoPrereq]
             [AutoVersion]
             [PkgVersion]
             [MetaConfig]
             [MetaJSON]
             [NextRelease]
             [PodSyntaxTests]
             [Repository]
             [PodWeaver]
             [@Git]


Tuesday, December 14, 2010
RJBS: THESE THREE SLIDES ARE A SPEED RUN; detailed version to follow immediately
name    = Dist-Zilla
             author = Ricardo SIGNES <rjbs@cpan.org>
             license = Perl_5
             copyright_holder = Ricardo SIGNES

             [@Basic]
             [AutoPrereq]
             [AutoVersion]
             [PkgVersion]
             [MetaConfig]
             [MetaJSON]
             [NextRelease]
             [PodSyntaxTests]
             [Repository]
             [PodWeaver]
             [@Git]


Tuesday, December 14, 2010
@Basic means a bundle, and that bundle expands to this:
[GatherDir]
             [PruneCruft]
             [ManifestSkip]
             [MetaYAML]
             [License]
             [Readme]
             [ExtraTests]
             [ExecDir]
             [ShareDir]
             [MakeMaker]
             [Manifest]
             [TestRelease]
             [ConfirmRelease]
             [UploadToCPAN]



Tuesday, December 14, 2010
name    = Dist-Zilla
             author = Ricardo SIGNES <rjbs@cpan.org>
             license = Perl_5
             copyright_holder = Ricardo SIGNES

             [@Basic]
             [AutoPrereq]
             [AutoVersion]
             [PkgVersion]
             [MetaConfig]
             [MetaJSON]
             [NextRelease]
             [PodSyntaxTests]
             [Repository]
             [PodWeaver]
             [@Git]


Tuesday, December 14, 2010
Too much!



Tuesday, December 14, 2010
Tuesday, December 14, 2010
test is just build then “make test”
install is just build then “cpan .”
release is just build, then cpan-upload (mostly)
dzil build




Tuesday, December 14, 2010
test is just build then “make test”
install is just build then “cpan .”
release is just build, then cpan-upload (mostly)
dzil build

             dzil test




Tuesday, December 14, 2010
test is just build then “make test”
install is just build then “cpan .”
release is just build, then cpan-upload (mostly)
dzil build

             dzil test

             dzil install




Tuesday, December 14, 2010
test is just build then “make test”
install is just build then “cpan .”
release is just build, then cpan-upload (mostly)
dzil build

             dzil test

             dzil install

             dzil release



Tuesday, December 14, 2010
test is just build then “make test”
install is just build then “cpan .”
release is just build, then cpan-upload (mostly)
How Dist::Zilla Builds




Tuesday, December 14, 2010
this is, obviously, a simplification -- but not as great a simplification as you might think

to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
How Dist::Zilla Builds
             sub build {




Tuesday, December 14, 2010
this is, obviously, a simplification -- but not as great a simplification as you might think

to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
How Dist::Zilla Builds
             sub build {
               my ($self) = @_;




Tuesday, December 14, 2010
this is, obviously, a simplification -- but not as great a simplification as you might think

to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
How Dist::Zilla Builds
             sub build {
               my ($self) = @_;

                    my @files = $self->gather_files;




Tuesday, December 14, 2010
this is, obviously, a simplification -- but not as great a simplification as you might think

to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
How Dist::Zilla Builds
             sub build {
               my ($self) = @_;

                    my @files = $self->gather_files;

                    $self->munge_files( @files );




Tuesday, December 14, 2010
this is, obviously, a simplification -- but not as great a simplification as you might think

to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
How Dist::Zilla Builds
             sub build {
               my ($self) = @_;

                    my @files = $self->gather_files;

                    $self->munge_files( @files );

                    $self->collect_metadata;




Tuesday, December 14, 2010
this is, obviously, a simplification -- but not as great a simplification as you might think

to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
How Dist::Zilla Builds
             sub build {
               my ($self) = @_;

                    my @files = $self->gather_files;

                    $self->munge_files( @files );

                    $self->collect_metadata;

                    $self->write_out( @files );



Tuesday, December 14, 2010
this is, obviously, a simplification -- but not as great a simplification as you might think

to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
How Dist::Zilla Builds
             sub build {
               my ($self) = @_;

                    my @files = $self->gather_files;

                    $self->munge_files( @files );

                    $self->collect_metadata;

                    $self->write_out( @files );
             }


Tuesday, December 14, 2010
this is, obviously, a simplification -- but not as great a simplification as you might think

to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
How do you pick
                                plugins?


Tuesday, December 14, 2010
There is no default config.



Tuesday, December 14, 2010
@Basic



Tuesday, December 14, 2010
...but don’t just rush to use @Basic without understanding it. You should understand what DZ is doing so that you can
understand what goes wrong, if anything goes wrong -- and something will go wrong.

There is *no* default configuration for Dist::Zilla. The @Basic bundle exists as a useful starting point, but I doubt anybody
would use only @Basic. There’s just too much that you can gain by adding on top of it.
The Basics
             [GatherDir]
             [PruneCruft]
             [Manifest]
             [ManifestSkip]
             [MakeMaker]
             [License]
             [Readme]
             [MetaYAML]
             [ExtraTests]
             [ExecDir]
             [ShareDir]
             [TestRelease]
             [ConfirmRelease]
             [UploadToCPAN]


Tuesday, December 14, 2010
@Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch
any of your files on disk.
The Basics
             [GatherDir]
             [PruneCruft]
             [Manifest]
             [ManifestSkip]
             [MakeMaker]
                                                                                                     MANIFEST
             [License]
             [Readme]
             [MetaYAML]
             [ExtraTests]
             [ExecDir]
             [ShareDir]
             [TestRelease]
             [ConfirmRelease]
             [UploadToCPAN]


Tuesday, December 14, 2010
@Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch
any of your files on disk.
The Basics
             [GatherDir]
             [PruneCruft]
             [Manifest]
             [ManifestSkip]
             [MakeMaker]
                                                                                                MANIFEST
             [License]
                                                                                             Makefile.PL
             [Readme]
             [MetaYAML]
             [ExtraTests]
             [ExecDir]
             [ShareDir]
             [TestRelease]
             [ConfirmRelease]
             [UploadToCPAN]


Tuesday, December 14, 2010
@Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch
any of your files on disk.
The Basics
             [GatherDir]
             [PruneCruft]
             [Manifest]
             [ManifestSkip]
             [MakeMaker]
                                                                                                MANIFEST
             [License]
                                                                                             Makefile.PL
             [Readme]
                                                                                                 LICENSE
             [MetaYAML]
             [ExtraTests]
             [ExecDir]
             [ShareDir]
             [TestRelease]
             [ConfirmRelease]
             [UploadToCPAN]


Tuesday, December 14, 2010
@Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch
any of your files on disk.
The Basics
             [GatherDir]
             [PruneCruft]
             [Manifest]
             [ManifestSkip]
             [MakeMaker]
                                                                                                MANIFEST
             [License]
                                                                                             Makefile.PL
             [Readme]
                                                                                                 LICENSE
             [MetaYAML]
                                                                                                  README
             [ExtraTests]
             [ExecDir]
             [ShareDir]
             [TestRelease]
             [ConfirmRelease]
             [UploadToCPAN]


Tuesday, December 14, 2010
@Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch
any of your files on disk.
The Basics
             [GatherDir]
             [PruneCruft]
             [Manifest]
             [ManifestSkip]
             [MakeMaker]
                                                                                                MANIFEST
             [License]
                                                                                             Makefile.PL
             [Readme]
                                                                                                 LICENSE
             [MetaYAML]
                                                                                                  README
             [ExtraTests]
                                                                                                META.yml
             [ExecDir]
             [ShareDir]
             [TestRelease]
             [ConfirmRelease]
             [UploadToCPAN]


Tuesday, December 14, 2010
@Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch
any of your files on disk.
Cruft Minimizers




Tuesday, December 14, 2010
Cruft Minimizers

             [PkgVersion]




Tuesday, December 14, 2010
Cruft Minimizers

             [PkgVersion]
             [PodSyntaxTests]




Tuesday, December 14, 2010
Cruft Minimizers

             [PkgVersion]
             [PodSyntaxTests]
             [PodCoverageTests]




Tuesday, December 14, 2010
Cruft Minimizers

             [PkgVersion]
             [PodSyntaxTests]
             [PodCoverageTests]
             [AutoPrereq]




Tuesday, December 14, 2010
Cruft Minimizers

             [PkgVersion]
             [PodSyntaxTests]
             [PodCoverageTests]
             [AutoPrereq]
             [AutoVersion]




Tuesday, December 14, 2010
Cruft Minimizers

             [PkgVersion]
             [PodSyntaxTests]
             [PodCoverageTests]
             [AutoPrereq]
             [AutoVersion]
             [NextRelease]




Tuesday, December 14, 2010
Version Control

             [@Git]

             [@Subversion]

             [@Mercurial]

             [@SVK]




Tuesday, December 14, 2010
this is a place where it *might* be reasonable to use a bundle when you start
Pod::Weaver


Tuesday, December 14, 2010
package YourApp;

             =head1 NAME

             YourApp - my awesome app

             =head1 VERSION

             version 1.001

             =cut

             our $VERSION = 0.001;

             =head1 DESCRIPTION

             This app is awesome.

             =head1 METHODS

             =head2 this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =head2 that_method

             Also stuff.

             =cut

             method that_method { ... }

             =head1 AUTHOR

             Margo Yapp <myapp@example.com>

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
Here’s a .pm file
package YourApp;

             =head1 NAME

             YourApp - my awesome app

             =head1 VERSION

             version 1.001

             =cut

             our $VERSION = 0.001;

             =head1 DESCRIPTION

             This app is awesome.

             =head1 METHODS

             =head2 this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =head2 that_method

             Also stuff.

             =cut

             method that_method { ... }

             =head1 AUTHOR

             Margo Yapp <myapp@example.com>

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
Here’s a .pm file
package YourApp;

             =head1 NAME

             YourApp - my awesome app

             =head1 VERSION

             version 1.001

             =cut

             our $VERSION = 0.001;

             =head1 DESCRIPTION

             This app is awesome.

             =head1 METHODS

             =head2 this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =head2 that_method

             Also stuff.

             =cut

             method that_method { ... }

             =head1 AUTHOR

             Margo Yapp <myapp@example.com>

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
The =name section is annoying.
package YourApp;
             # ABSTRACT: my awesome app

             =head1 VERSION

             version 1.001

             =cut

             our $VERSION = 0.001;

             =head1 DESCRIPTION

             This app is awesome.

             =head1 METHODS

             =head2 this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =head2 that_method

             Also stuff.

             =cut

             method that_method { ... }

             =head1 AUTHOR

             Margo Yapp <myapp@example.com>

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
We’ll replace it with a comment.
package YourApp;
             # ABSTRACT: my awesome app

             =head1 VERSION

             version 1.001

             =cut

             our $VERSION = 0.001;

             =head1 DESCRIPTION

             This app is awesome.

             =head1 METHODS

             =head2 this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =head2 that_method

             Also stuff.

             =cut

             method that_method { ... }

             =head1 AUTHOR

             Margo Yapp <myapp@example.com>

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
The =version section is redundant.
package YourApp;
             # ABSTRACT: my awesome app

             our $VERSION = 0.001;

             =head1 DESCRIPTION

             This app is awesome.

             =head1 METHODS

             =head2 this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =head2 that_method

             Also stuff.

             =cut

             method that_method { ... }

             =head1 AUTHOR

             Margo Yapp <myapp@example.com>

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
Drop it.
package YourApp;
             # ABSTRACT: my awesome app

             our $VERSION = 0.001;

             =head1 DESCRIPTION

             This app is awesome.

             =head1 METHODS

             =head2 this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =head2 that_method

             Also stuff.

             =cut

             method that_method { ... }

             =head1 AUTHOR

             Margo Yapp <myapp@example.com>

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
Even the $VERSION is redundant, since we want it constant across the dist.
package YourApp;
             # ABSTRACT: my awesome app

             =head1 DESCRIPTION

             This app is awesome.

             =head1 METHODS

             =head2 this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =head2 that_method

             Also stuff.

             =cut

             method that_method { ... }

             =head1 AUTHOR

             Margo Yapp <myapp@example.com>

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
our overarching METHOD section is dumb
package YourApp;
             # ABSTRACT: my awesome app

             =head1 DESCRIPTION

             This app is awesome.

             =method this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =method that_method

             Also stuff.

             =cut

             method that_method { ... }

             =head1 AUTHOR

             Margo Yapp <myapp@example.com>

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
let’s just use =method for them all
package YourApp;
             # ABSTRACT: my awesome app

             =head1 DESCRIPTION

             This app is awesome.

             =method this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =method that_method

             Also stuff.

             =cut

             method that_method { ... }

             =head1 AUTHOR

             Margo Yapp <myapp@example.com>

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
Repeating the author everywhere is annoying, too.
package YourApp;
             # ABSTRACT: my awesome app

             =head1 DESCRIPTION

             This app is awesome.

             =method this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =method that_method

             Also stuff.

             =cut

             method that_method { ... }

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
Drop it, use author info found in DZ config.
package YourApp;
             # ABSTRACT: my awesome app

             =head1 DESCRIPTION

             This app is awesome.

             =method this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =method that_method

             Also stuff.

             method that_method { ... }

             =head1 LICENSE

             Copyright (C) 2008, Margo Yapp.

             This is distributed under the terms of the accidental death and
             dismemberment license and if you redistribuet this document you
             will be “accidentally” deathed or dismembered. You have been
             told.

             =cut

             1;




Tuesday, December 14, 2010
The license is gigantic! Ugh!
package YourApp;
             # ABSTRACT: my awesome app

             =head1 DESCRIPTION

             This app is awesome.

             =method this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =method that_method

             Also stuff.

             =cut

             method that_method { ... }

             =cut
             1;




Tuesday, December 14, 2010
Drop it.
package YourApp;
             # ABSTRACT: my awesome app

             =head1 DESCRIPTION

             This app is awesome.

             =method this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =method that_method

             Also stuff.

             =cut

             method that_method { ... }

             1;



Tuesday, December 14, 2010
Now our file is simple, just the unique docs and code it needs. It fits on one legible slide!
package YourApp;
             # ABSTRACT: my awesome app

             =head1 DESCRIPTION

             This app is awesome.

             =method this_method

             This method does stuff.

             =cut

             method this_method { ... }

             =method that_method

             Also stuff.

             =cut

             method that_method { ... }

             1;



Tuesday, December 14, 2010
And is about half Perl.

and you get all of that stuff autogenerated by adding this to your dist.ini
[PodWeaver]




Tuesday, December 14, 2010
Converting Your Dist




Tuesday, December 14, 2010
Converting Your Dist
                   - create dist.ini




Tuesday, December 14, 2010
Converting Your Dist
                   - create dist.ini
                   - remove a bunch of files




Tuesday, December 14, 2010
Converting Your Dist
                   - create dist.ini
                   - remove a bunch of files
                   - delete a bunch of stuff from leftover files



Tuesday, December 14, 2010
Converting Your Dist
                   - create dist.ini
                   - remove a bunch of files
                   - delete a bunch of stuff from leftover files

                   - and Dist::Zooky, too

Tuesday, December 14, 2010
Questions
                 so far?
Tuesday, December 14, 2010
Creating New Dists



Tuesday, December 14, 2010
dzil            build
             dzil            test
             dzil            install
             dzil            release




Tuesday, December 14, 2010
so, we already talked about these commands, which all operate on an existing distribution directory to build a fleshed-out CPAN
distribution. to mint a brand-new dist, we use...
dzil              build
             dzil              test
             dzil              install
             dzil              release

             dzil new




Tuesday, December 14, 2010
dzil new!

the big difference is that the first set of commands work on an existing dist, so there’s a dist.ini

we don’t have a dist.ini yet, because there’s no dist dir yet. we need a...
profile.ini



Tuesday, December 14, 2010
this file sets up the plugins that you’ll use to mint a new dist

(don’t worry, if you don’t make one, there *is* default behavior -- but it’s so incredibly simple that you probably don’t want it)
Tuesday, December 14, 2010
to understand how this works, we need to look at how minting works
[GatherDir::Template]




Tuesday, December 14, 2010
to understand how this works, we need to look at how minting works
[GatherDir::Template]
             root = files




Tuesday, December 14, 2010
to understand how this works, we need to look at how minting works
[GatherDir::Template]
             root = files

             [DistINI]




Tuesday, December 14, 2010
to understand how this works, we need to look at how minting works
[GatherDir::Template]
             root = files

             [DistINI]

             [Git::Init]




Tuesday, December 14, 2010
to understand how this works, we need to look at how minting works
How Dist::Zilla Mints




Tuesday, December 14, 2010
How Dist::Zilla Mints
             sub mint {




Tuesday, December 14, 2010
How Dist::Zilla Mints
             sub mint {
               my ($self) = @_;




Tuesday, December 14, 2010
How Dist::Zilla Mints
             sub mint {
               my ($self) = @_;

                    my @files = $self->gather_files;




Tuesday, December 14, 2010
How Dist::Zilla Mints
             sub mint {
               my ($self) = @_;

                    my @files = $self->gather_files;

                    $self->munge_files( @files );




Tuesday, December 14, 2010
How Dist::Zilla Mints
             sub mint {
               my ($self) = @_;

                    my @files = $self->gather_files;

                    $self->munge_files( @files );

                    $self->make_module( $module );




Tuesday, December 14, 2010
How Dist::Zilla Mints
             sub mint {
               my ($self) = @_;

                    my @files = $self->gather_files;

                    $self->munge_files( @files );

                    $self->make_module( $module );

                    $self->write_out( @files );



Tuesday, December 14, 2010
How Dist::Zilla Mints
             sub mint {
               my ($self) = @_;

                    my @files = $self->gather_files;

                    $self->munge_files( @files );

                    $self->make_module( $module );

                    $self->write_out( @files );
             }


Tuesday, December 14, 2010
Tuesday, December 14, 2010
see how there’s no root section? We *could* add one, but it would probably be the same across multiple profiles we set up, so
we can put this stuff in another location:
[GatherDir::Template]




Tuesday, December 14, 2010
see how there’s no root section? We *could* add one, but it would probably be the same across multiple profiles we set up, so
we can put this stuff in another location:
[GatherDir::Template]
             root = files




Tuesday, December 14, 2010
see how there’s no root section? We *could* add one, but it would probably be the same across multiple profiles we set up, so
we can put this stuff in another location:
[GatherDir::Template]
             root = files

             [DistINI]




Tuesday, December 14, 2010
see how there’s no root section? We *could* add one, but it would probably be the same across multiple profiles we set up, so
we can put this stuff in another location:
[GatherDir::Template]
             root = files

             [DistINI]

             [Git::Init]




Tuesday, December 14, 2010
see how there’s no root section? We *could* add one, but it would probably be the same across multiple profiles we set up, so
we can put this stuff in another location:
config.ini



Tuesday, December 14, 2010
global (per-user) configuration
~/.dzil/config.ini



Tuesday, December 14, 2010
[%User]
             name = Ricardo Signes
             email = rjbs@example.org

             [%Rights]
             license_class    = Perl_5
             copyright_holder = Ricardo Signes

             [%PAUSE]
             username = RJBS
             password = PeasAreDelicious




Tuesday, December 14, 2010
these aren’t plugins; global configuration is loaded before we have a Dist::Zilla object to plug into

instead, these are stashes; basically, hunks of data for plugins to look up; they can be shared, generic, referenced by name, etc
etc etc

here we see our default author, our default license/legal info, and default PAUSE upload credentials
dzil setup




Tuesday, December 14, 2010
Minting a New Dist

                   - create config.ini (in ~/.dzil)
                   - maybe configure or install a profile
                   - run dzil new


Tuesday, December 14, 2010
Questions
                 so far?
Tuesday, December 14, 2010
Writing Plugins!



Tuesday, December 14, 2010
Writing Plugins is Easy!



Tuesday, December 14, 2010
Writing Plugins is Easy!
                             (and awesome)



Tuesday, December 14, 2010
How Dist::Zilla Builds
             sub build {
               my ($self) = @_;

                    my @files = $self->gather_files;

                    $self->munge_files( @files );

                    $self->collect_metadata;

                    $self->write_out( @files );
             }


Tuesday, December 14, 2010
This is what I showed, earlier, as a simplified example of how Dist::Zilla builds stuff. To understand how plugins work, we need
to de-simplify a little.
How Dist::Zilla Builds


                    $self->munge_files( @files );




Tuesday, December 14, 2010
Take this line... what happens is a bit more like this:
How Dist::Zilla Builds

             my @mungers =
               grep { $_->does(‘FileMunger’) }
               $self->plugins;

             for my $plugin (@mungers) {
               $plugin->munge_files( @files );
             }




Tuesday, December 14, 2010
we call a method on a bunch of delegates, where the delegates are all of the (undifferentiated) plugins that perform a given rol
$obj->does( $role )



             package Some::Class;
             use Moose;
             with ‘Some::Role’;




Tuesday, December 14, 2010
LEARN MOOSE
Roles to Make Plugins Go




Tuesday, December 14, 2010
Roles to Make Plugins Go
             BeforeBuild




Tuesday, December 14, 2010
Roles to Make Plugins Go
             BeforeBuild
             FileGatherer




Tuesday, December 14, 2010
Roles to Make Plugins Go
             BeforeBuild
             FileGatherer
             FilePruner




Tuesday, December 14, 2010
Roles to Make Plugins Go
             BeforeBuild
             FileGatherer
             FilePruner
             FileMunger




Tuesday, December 14, 2010
Roles to Make Plugins Go
             BeforeBuild
             FileGatherer
             FilePruner
             FileMunger
             PrereqSource




Tuesday, December 14, 2010
Roles to Make Plugins Go
             BeforeBuild
             FileGatherer
             FilePruner
             FileMunger
             PrereqSource
             MetaProvider




Tuesday, December 14, 2010
Roles to Make Plugins Go
             BeforeBuild
             FileGatherer
             FilePruner
             FileMunger
             PrereqSource
             MetaProvider
             AfterBuild




Tuesday, December 14, 2010
Roles to Make Plugins Go
             BeforeBuild
             FileGatherer
             FilePruner
             FileMunger
             PrereqSource
             MetaProvider
             AfterBuild

             BeforeArchive




Tuesday, December 14, 2010
Roles to Make Plugins Go
             BeforeBuild
             FileGatherer
             FilePruner
             FileMunger
             PrereqSource
             MetaProvider
             AfterBuild

             BeforeArchive
             BeforeRelease




Tuesday, December 14, 2010
Roles to Make Plugins Go
             BeforeBuild
             FileGatherer
             FilePruner
             FileMunger
             PrereqSource
             MetaProvider
             AfterBuild

             BeforeArchive
             BeforeRelease
             Releaser



Tuesday, December 14, 2010
Roles to Make Plugins Go
             BeforeBuild
             FileGatherer
             FilePruner
             FileMunger
             PrereqSource
             MetaProvider
             AfterBuild

             BeforeArchive
             BeforeRelease
             Releaser
             AfterRelease


Tuesday, December 14, 2010
Let’s write a plugin!



Tuesday, December 14, 2010
BuiltOn




Tuesday, December 14, 2010
BuiltOn
             package Dist::Zilla::Plugin::BuiltOn;




Tuesday, December 14, 2010
BuiltOn
             package Dist::Zilla::Plugin::BuiltOn;
             use Moose;




Tuesday, December 14, 2010
BuiltOn
             package Dist::Zilla::Plugin::BuiltOn;
             use Moose;
             with ‘Dist::Zilla::Role::FileGatherer’;




Tuesday, December 14, 2010
BuiltOn
             package Dist::Zilla::Plugin::BuiltOn;
             use Moose;
             with ‘Dist::Zilla::Role::FileGatherer’;

             sub gather_files {




Tuesday, December 14, 2010
BuiltOn
             package Dist::Zilla::Plugin::BuiltOn;
             use Moose;
             with ‘Dist::Zilla::Role::FileGatherer’;

             sub gather_files {
               my ($self) = @_;




Tuesday, December 14, 2010
BuiltOn
             package Dist::Zilla::Plugin::BuiltOn;
             use Moose;
             with ‘Dist::Zilla::Role::FileGatherer’;

             sub gather_files {
               my ($self) = @_;
               my $file = Dist::Zilla::File::InMemory->new({




Tuesday, December 14, 2010
BuiltOn
             package Dist::Zilla::Plugin::BuiltOn;
             use Moose;
             with ‘Dist::Zilla::Role::FileGatherer’;

             sub gather_files {
               my ($self) = @_;
               my $file = Dist::Zilla::File::InMemory->new({
                 name    => ‘built-on.txt’,




Tuesday, December 14, 2010
BuiltOn
             package Dist::Zilla::Plugin::BuiltOn;
             use Moose;
             with ‘Dist::Zilla::Role::FileGatherer’;

             sub gather_files {
               my ($self) = @_;
               my $file = Dist::Zilla::File::InMemory->new({
                 name    => ‘built-on.txt’,
                 content => scalar `uname -a`,




Tuesday, December 14, 2010
BuiltOn
             package Dist::Zilla::Plugin::BuiltOn;
             use Moose;
             with ‘Dist::Zilla::Role::FileGatherer’;

             sub gather_files {
               my ($self) = @_;
               my $file = Dist::Zilla::File::InMemory->new({
                 name    => ‘built-on.txt’,
                 content => scalar `uname -a`,
               });




Tuesday, December 14, 2010
BuiltOn
             package Dist::Zilla::Plugin::BuiltOn;
             use Moose;
             with ‘Dist::Zilla::Role::FileGatherer’;

             sub gather_files {
               my ($self) = @_;
               my $file = Dist::Zilla::File::InMemory->new({
                 name    => ‘built-on.txt’,
                 content => scalar `uname -a`,
               });

                   $self->add_file( $file );




Tuesday, December 14, 2010
BuiltOn
             package Dist::Zilla::Plugin::BuiltOn;
             use Moose;
             with ‘Dist::Zilla::Role::FileGatherer’;

             sub gather_files {
               my ($self) = @_;
               my $file = Dist::Zilla::File::InMemory->new({
                 name    => ‘built-on.txt’,
                 content => scalar `uname -a`,
               });

                   $self->add_file( $file );
             }




Tuesday, December 14, 2010
BuiltOn


             [BuiltOn]




Tuesday, December 14, 2010
package Dist::Zilla::Plugin::BuiltOn;
             use Moose;
             with ‘Dist::Zilla::Role::FileGatherer’;

             has filename => (
               is      => ‘ro’,
               default => ‘built-on.txt’,
             );

             sub gather_files {
               my ($self) = @_;
               my $file = Dist::Zilla::File::InMemory->new({
                 name    => $self->filename,
                 content => scalar `uname -a`,
               });

                   $self->add_file( $file );
             }



Tuesday, December 14, 2010
BuiltOn


             [BuiltOn]
             filename = build-host.txt




Tuesday, December 14, 2010
BuiltOn


             [BuiltOn]




Tuesday, December 14, 2010
Let’s write a another!



Tuesday, December 14, 2010
(this will talk about plugin ordering)
AddShebangs




Tuesday, December 14, 2010




...and then just one more...
AddShebangs
             package Dist::Zilla::Plugin::AddShebangs;




Tuesday, December 14, 2010




...and then just one more...
AddShebangs
             package Dist::Zilla::Plugin::AddShebangs;
             use Moose;




Tuesday, December 14, 2010




...and then just one more...
AddShebangs
             package Dist::Zilla::Plugin::AddShebangs;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;




Tuesday, December 14, 2010




...and then just one more...
AddShebangs
             package Dist::Zilla::Plugin::AddShebangs;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {




Tuesday, December 14, 2010




...and then just one more...
AddShebangs
             package Dist::Zilla::Plugin::AddShebangs;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;




Tuesday, December 14, 2010




...and then just one more...
AddShebangs
             package Dist::Zilla::Plugin::AddShebangs;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;
               next unless $file->name =~ /.pl$/;




Tuesday, December 14, 2010




...and then just one more...
AddShebangs
             package Dist::Zilla::Plugin::AddShebangs;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;
               next unless $file->name =~ /.pl$/;

                   my $content = “#!$^Xn”




Tuesday, December 14, 2010




...and then just one more...
AddShebangs
             package Dist::Zilla::Plugin::AddShebangs;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;
               next unless $file->name =~ /.pl$/;

                   my $content = “#!$^Xn”
                               . $file->content;




Tuesday, December 14, 2010




...and then just one more...
AddShebangs
             package Dist::Zilla::Plugin::AddShebangs;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;
               next unless $file->name =~ /.pl$/;

                   my $content = “#!$^Xn”
                               . $file->content;

                   $file->content( $content );




Tuesday, December 14, 2010




...and then just one more...
AddShebangs
             package Dist::Zilla::Plugin::AddShebangs;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;
               next unless $file->name =~ /.pl$/;

                   my $content = “#!$^Xn”
                               . $file->content;

                   $file->content( $content );
             }




Tuesday, December 14, 2010




...and then just one more...
AddBlame




Tuesday, December 14, 2010
AddBlame
             package Dist::Zilla::Plugin::AddBlame;




Tuesday, December 14, 2010
AddBlame
             package Dist::Zilla::Plugin::AddBlame;
             use Moose;




Tuesday, December 14, 2010
AddBlame
             package Dist::Zilla::Plugin::AddBlame;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;




Tuesday, December 14, 2010
AddBlame
             package Dist::Zilla::Plugin::AddBlame;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {




Tuesday, December 14, 2010
AddBlame
             package Dist::Zilla::Plugin::AddBlame;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;




Tuesday, December 14, 2010
AddBlame
             package Dist::Zilla::Plugin::AddBlame;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;
               next unless $file->name =~ /.p[lm]$/;




Tuesday, December 14, 2010
AddBlame
             package Dist::Zilla::Plugin::AddBlame;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;
               next unless $file->name =~ /.p[lm]$/;

                   my $content = “# BUILD BY $ENV{USER}n”




Tuesday, December 14, 2010
AddBlame
             package Dist::Zilla::Plugin::AddBlame;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;
               next unless $file->name =~ /.p[lm]$/;

                   my $content = “# BUILD BY $ENV{USER}n”
                               . $file->content;




Tuesday, December 14, 2010
AddBlame
             package Dist::Zilla::Plugin::AddBlame;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;
               next unless $file->name =~ /.p[lm]$/;

                   my $content = “# BUILD BY $ENV{USER}n”
                               . $file->content;

                   $file->content( $content );




Tuesday, December 14, 2010
AddBlame
             package Dist::Zilla::Plugin::AddBlame;
             use Moose;
             with ‘Dist::Zilla::Role::FileMunger’;

             sub munge_file {
               my ($self, $file) = @_;
               next unless $file->name =~ /.p[lm]$/;

                   my $content = “# BUILD BY $ENV{USER}n”
                               . $file->content;

                   $file->content( $content );
             }




Tuesday, December 14, 2010
[GatherDir]
             [PruneCruft]




Tuesday, December 14, 2010
[GatherDir]
             [PruneCruft]
             [AddShebangs]
             [AddBlame]




Tuesday, December 14, 2010
this is actually a problem
[GatherDir]
             [PruneCruft]
             [AddShebangs]
             [AddBlame]

                                                          print “Hello.n”;



Tuesday, December 14, 2010
If we start with this extremely powerful library file...
[GatherDir]
             [PruneCruft]
             [AddShebangs]
             [AddBlame]

                                               #!/usr/bin/perl
                                               print “Hello.n”;


Tuesday, December 14, 2010
The shebang gets added, just like we wanted.
[GatherDir]
             [PruneCruft]
             [AddShebangs]
             [AddBlame]
                                                        # built by rjbs
                                                        #!/usr/bin/perl
                                                        print “Hello.n”;


Tuesday, December 14, 2010
then the comment -- meaning the shebang is no good, because it doesn’t start the file
[GatherDir]
             [PruneCruft]
             [AddBlame]
             [AddShebangs]
                                                        #!/usr/bin/perl
                                                        # built by rjbs
                                                        print “Hello.n”;


Tuesday, December 14, 2010
then the comment -- meaning the shebang is no good, because it doesn’t start the file
In Conclusion...

Tuesday, December 14, 2010
Dist::Zilla is..?

Tuesday, December 14, 2010
Dist::Zilla is:
                   - judges will accept:
                     - awesome
                     - huge
                     - stupid

Tuesday, December 14, 2010
We are Friendly
                   - irc.perl.org #distzilla
                   - http://dzil.org/
                   - mailing list
                   - http://rt.cpan.org/

Tuesday, December 14, 2010
we will try to answer your questions
Any
            Questions?
Tuesday, December 14, 2010
Thank you!           raaaaaaaaar!




Tuesday, December 14, 2010

Más contenido relacionado

Similar a Dist::Zilla: Eliminate Boilerplate for Easier CPAN Authoring

Mothra - A FreeBSD send-pr tool for bugzilla system
Mothra - A FreeBSD send-pr tool for bugzilla systemMothra - A FreeBSD send-pr tool for bugzilla system
Mothra - A FreeBSD send-pr tool for bugzilla systemDaniel Lin
 
Dist::Zilla - A very brief introduction
Dist::Zilla - A very brief introductionDist::Zilla - A very brief introduction
Dist::Zilla - A very brief introductionDean Hamstead
 
Boxen: How to Manage an Army of Laptops and Live to Talk About It
Boxen: How to Manage an Army of Laptops and Live to Talk About ItBoxen: How to Manage an Army of Laptops and Live to Talk About It
Boxen: How to Manage an Army of Laptops and Live to Talk About ItPuppet
 
Puppet 3: Present and Future Tense
Puppet 3: Present and Future TensePuppet 3: Present and Future Tense
Puppet 3: Present and Future TenseEric Sorenson
 
Puppet 3: Present and Future Tense
Puppet 3: Present and Future TensePuppet 3: Present and Future Tense
Puppet 3: Present and Future TensePuppet
 
Deploying and maintaining your software with RPM/APT
Deploying and maintaining your software with RPM/APTDeploying and maintaining your software with RPM/APT
Deploying and maintaining your software with RPM/APTJoshua Thijssen
 
4Developers 2015: Under the dome (of failure driven pipeline) - Maciej Lasyk
4Developers 2015: Under the dome (of failure driven pipeline) - Maciej Lasyk4Developers 2015: Under the dome (of failure driven pipeline) - Maciej Lasyk
4Developers 2015: Under the dome (of failure driven pipeline) - Maciej LasykPROIDEA
 
Under the Dome (of failure driven pipeline)
Under the Dome (of failure driven pipeline)Under the Dome (of failure driven pipeline)
Under the Dome (of failure driven pipeline)Maciej Lasyk
 
Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010Matt Aimonetti
 
Intro To Linux
Intro To LinuxIntro To Linux
Intro To Linuxtechlug
 
Real Developer Tools for WordPress by Stefan Didak
Real Developer Tools for WordPress by Stefan DidakReal Developer Tools for WordPress by Stefan Didak
Real Developer Tools for WordPress by Stefan DidakEast Bay WordPress Meetup
 
TinyOS installation Guide And Manual
TinyOS installation Guide And ManualTinyOS installation Guide And Manual
TinyOS installation Guide And ManualAnkit Singh
 
Design and Evolution of cyber-dojo
Design and Evolution of cyber-dojoDesign and Evolution of cyber-dojo
Design and Evolution of cyber-dojoJon Jagger
 
Culture And Aesthetic Revisited
Culture And Aesthetic RevisitedCulture And Aesthetic Revisited
Culture And Aesthetic RevisitedAdam Keys
 
Using MongoDB and a Relational Database at MongoDB Day
Using MongoDB and a Relational Database at MongoDB DayUsing MongoDB and a Relational Database at MongoDB Day
Using MongoDB and a Relational Database at MongoDB Dayhayesdavis
 
Iz Pack
Iz PackIz Pack
Iz PackInria
 
Trusting files (and their formats)
Trusting files (and their formats)Trusting files (and their formats)
Trusting files (and their formats)Ange Albertini
 

Similar a Dist::Zilla: Eliminate Boilerplate for Easier CPAN Authoring (20)

Mothra - A FreeBSD send-pr tool for bugzilla system
Mothra - A FreeBSD send-pr tool for bugzilla systemMothra - A FreeBSD send-pr tool for bugzilla system
Mothra - A FreeBSD send-pr tool for bugzilla system
 
Drupal Devministration
Drupal DevministrationDrupal Devministration
Drupal Devministration
 
A false digital alibi on mac os x
A false digital alibi on mac os xA false digital alibi on mac os x
A false digital alibi on mac os x
 
Dist::Zilla - A very brief introduction
Dist::Zilla - A very brief introductionDist::Zilla - A very brief introduction
Dist::Zilla - A very brief introduction
 
Boxen: How to Manage an Army of Laptops and Live to Talk About It
Boxen: How to Manage an Army of Laptops and Live to Talk About ItBoxen: How to Manage an Army of Laptops and Live to Talk About It
Boxen: How to Manage an Army of Laptops and Live to Talk About It
 
Puppet 3: Present and Future Tense
Puppet 3: Present and Future TensePuppet 3: Present and Future Tense
Puppet 3: Present and Future Tense
 
Puppet 3: Present and Future Tense
Puppet 3: Present and Future TensePuppet 3: Present and Future Tense
Puppet 3: Present and Future Tense
 
Deploying and maintaining your software with RPM/APT
Deploying and maintaining your software with RPM/APTDeploying and maintaining your software with RPM/APT
Deploying and maintaining your software with RPM/APT
 
4Developers 2015: Under the dome (of failure driven pipeline) - Maciej Lasyk
4Developers 2015: Under the dome (of failure driven pipeline) - Maciej Lasyk4Developers 2015: Under the dome (of failure driven pipeline) - Maciej Lasyk
4Developers 2015: Under the dome (of failure driven pipeline) - Maciej Lasyk
 
Under the Dome (of failure driven pipeline)
Under the Dome (of failure driven pipeline)Under the Dome (of failure driven pipeline)
Under the Dome (of failure driven pipeline)
 
Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010
 
Intro To Linux
Intro To LinuxIntro To Linux
Intro To Linux
 
Real Developer Tools for WordPress by Stefan Didak
Real Developer Tools for WordPress by Stefan DidakReal Developer Tools for WordPress by Stefan Didak
Real Developer Tools for WordPress by Stefan Didak
 
Automate Yo' Self
Automate Yo' SelfAutomate Yo' Self
Automate Yo' Self
 
TinyOS installation Guide And Manual
TinyOS installation Guide And ManualTinyOS installation Guide And Manual
TinyOS installation Guide And Manual
 
Design and Evolution of cyber-dojo
Design and Evolution of cyber-dojoDesign and Evolution of cyber-dojo
Design and Evolution of cyber-dojo
 
Culture And Aesthetic Revisited
Culture And Aesthetic RevisitedCulture And Aesthetic Revisited
Culture And Aesthetic Revisited
 
Using MongoDB and a Relational Database at MongoDB Day
Using MongoDB and a Relational Database at MongoDB DayUsing MongoDB and a Relational Database at MongoDB Day
Using MongoDB and a Relational Database at MongoDB Day
 
Iz Pack
Iz PackIz Pack
Iz Pack
 
Trusting files (and their formats)
Trusting files (and their formats)Trusting files (and their formats)
Trusting files (and their formats)
 

Más de Ricardo Signes

Perl 5.14 for Pragmatists
Perl 5.14 for PragmatistsPerl 5.14 for Pragmatists
Perl 5.14 for PragmatistsRicardo Signes
 
Antediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix FundamentalsAntediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix FundamentalsRicardo Signes
 
Perl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally InsanePerl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally InsaneRicardo Signes
 
Writing Modular Command-line Apps with App::Cmd
Writing Modular Command-line Apps with App::CmdWriting Modular Command-line Apps with App::Cmd
Writing Modular Command-line Apps with App::CmdRicardo Signes
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterRicardo Signes
 
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!Ricardo Signes
 

Más de Ricardo Signes (8)

Perl 5.14 for Pragmatists
Perl 5.14 for PragmatistsPerl 5.14 for Pragmatists
Perl 5.14 for Pragmatists
 
i &lt;3 email
i &lt;3 emaili &lt;3 email
i &lt;3 email
 
Dist::Zilla
Dist::ZillaDist::Zilla
Dist::Zilla
 
Antediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix FundamentalsAntediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix Fundamentals
 
Perl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally InsanePerl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally Insane
 
Writing Modular Command-line Apps with App::Cmd
Writing Modular Command-line Apps with App::CmdWriting Modular Command-line Apps with App::Cmd
Writing Modular Command-line Apps with App::Cmd
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::Exporter
 
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
 

Dist::Zilla: Eliminate Boilerplate for Easier CPAN Authoring

  • 1. Dist::Zilla raaaaaaaaar! Tuesday, December 14, 2010
  • 2. What is Dist::Zilla? Tuesday, December 14, 2010 This talk is about your life as a CPAN author.
  • 4. Any Questions? Tuesday, December 14, 2010
  • 5. RJBS Tuesday, December 14, 2010 ME!!! also awesome! I give away almost all my useful software on CPAN
  • 6. RJBS - cake and pie (and doughnuts) Tuesday, December 14, 2010 ME!!! also awesome! I give away almost all my useful software on CPAN
  • 7. RJBS - cake and pie (and doughnuts) - cocktails and beer Tuesday, December 14, 2010 ME!!! also awesome! I give away almost all my useful software on CPAN
  • 8. RJBS - cake and pie (and doughnuts) - cocktails and beer - shooting zombies Tuesday, December 14, 2010 ME!!! also awesome! I give away almost all my useful software on CPAN
  • 9. RJBS - cake and pie (and doughnuts) - cocktails and beer - shooting zombies - giving away useful software Tuesday, December 14, 2010 ME!!! also awesome! I give away almost all my useful software on CPAN
  • 10. CPAN! Tuesday, December 14, 2010 CPAN is awesome, too. We all know that.
  • 11. being a CPAN author is hard! let’s go gemming! Tuesday, December 14, 2010 who here is a CPAN author? what makes it a pain? let’s talk about it
  • 12. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 this is all the crap in your working copy where you write this dist making all these is a boring pain in the butt
  • 13. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 and a bunch of semi-structured data is in Makefile.PL
  • 15. WriteMakefile( NAME => ‘YourApp’, AUTHOR => ‘You <rjbs@cpan.org>’, VERSION_FROM => ‘lib/YourApp.pm’, ABSTRACT_FROM => ‘lib/YourApp.pm’, LICENSE => ‘perl’, PREREQ_PM => { ‘Lingua::EN::Inflect’ => 1.86, ‘Sub::Override’ => 0.07, ‘Test::More’ => 0, }, ); Tuesday, December 14, 2010 Then you have to put a bunch more information describing your distribution into Makefile.PL, if you’re using ExtUtils::MakeMaker.
  • 16. WriteMakefile( NAME => ‘YourApp’, AUTHOR => ‘You <rjbs@cpan.org>’, VERSION_FROM => ‘lib/YourApp.pm’, ABSTRACT_FROM => ‘lib/YourApp.pm’, LICENSE => ‘perl’, PREREQ_PM => { ‘Lingua::EN::Inflect’ => 1.86, ‘Sub::Override’ => 0.07, ‘Test::More’ => 0, }, (eval { ExtUtils::MakeMaker->VERSION(6.46) } ? (META_MERGE => { resources => { Repository => ‘...’ } }) : ()), ); Tuesday, December 14, 2010 If you want to add more metadata, you start having to use really gross constructions, trying to avoid backcompat issues. In part, this is because even the data only needed for installing the dist (like your respository) is present and executed on the installing user’s computer.
  • 18. use inc::Module::Install; all_from(‘lib/YourApp.pm’); requires(‘Lingua::EN::Inflect’ => 1.86); requires(‘Sub::Override’ => 0.07); requires(‘Test::More’ => 0); repository(...); WriteAll(); Tuesday, December 14, 2010 Module::Install lets you write this, instead. It does a lot more auto-detection by reading your Pod and trying to parse its meaning. Then it runs on the installer’s machine and uses the machinery of ExtUtils::MakeMaker to build a plain old Makefile for installation. So, it bundles itself with each dist that uses it, and it’s still beholden to the version of EUMM installed on the user’s machine. Still, it saves quite a lot of time in dealing with stupid crap in Makefile.PL. It just means you need to write a bunch of other stuff for it to scan, like:
  • 19. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 You need to have your author in the main module to be detected, and the license. Then, because you want to keep the data in each library, you have to keep that same data in each Perl module. Copy and paste!
  • 21. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/boilerplate.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 It can create all these files, Pod and all, *for* you so you don’t have to go through this drudgery. Unfortunately, some of these files include stuff that you’re going to need to customize, replace, or delete immediately upon starting the dist. So many people used Module::Starter and then left in garbage data that we added a test to help stop them from doing so...
  • 22. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/boilerplate.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 It looks for the stock content you should get rid of. Once this test passes, you are expected to delete it. Why have that boilerplate crap at all? Worse, what if one of your boilerplate files has a typo? Or what if you want to change your default pod-coverage setup? You need to go update every file in all of your distributions, because that file actually exists in your source repository.
  • 23. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 Dist::Zilla tries to solve all these problems: don’t repeat yourself; don’t store what you can compute; rely on the installing user having only the bare minimum of tools needed to install, and don’t bundle more if you can help it. It also tries hard to be easy to test, so that when you write extensions to DZ, they’re easy to write and easy to test. EUMM, M:I, and Starter are not. I’m going to show you how to eliminate as much of this as you can so there’s less to write, less to update, less to diff, and less to think about in general.
  • 24. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 25. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 26. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 27. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 28. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 29. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 30. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 31. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 32. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 33. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 34. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 35. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files we can get rid of entirely)
  • 36. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files from which we can prune lots of non-essential content) ...and it can do more than just reduce the on-disk content...
  • 37. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files from which we can prune lots of non-essential content) ...and it can do more than just reduce the on-disk content...
  • 38. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files from which we can prune lots of non-essential content) ...and it can do more than just reduce the on-disk content...
  • 39. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files from which we can prune lots of non-essential content) ...and it can do more than just reduce the on-disk content...
  • 40. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files from which we can prune lots of non-essential content) ...and it can do more than just reduce the on-disk content...
  • 41. ./Changes ./LICENSE ./MANIFEST.SKIP ./Makefile.PL ./README ./lib/YourApp.pm ./lib/YourApp/Reticulator.pm ./lib/YourApp/Util/mtfnpy.pm ./lib/YourApp/Xyzzy.pm ./t/unit-tests.t ./t/pod-coverage.t ./t/pod.t Tuesday, December 14, 2010 (files from which we can prune lots of non-essential content) ...and it can do more than just reduce the on-disk content...
  • 42. Tuesday, December 14, 2010 ...and that’s why
  • 43. - updating version numbers Tuesday, December 14, 2010 ...and that’s why
  • 44. - updating version numbers - uploading to CPAN Tuesday, December 14, 2010 ...and that’s why
  • 45. - updating version numbers - uploading to CPAN - committing, tagging releases in Git (VCS) Tuesday, December 14, 2010 ...and that’s why
  • 46. - updating version numbers - uploading to CPAN - committing, tagging releases in Git (VCS) - determine prerequisites Tuesday, December 14, 2010 ...and that’s why
  • 47. - updating version numbers - uploading to CPAN - committing, tagging releases in Git (VCS) - determine prerequisites - other stuff that is totally boring Tuesday, December 14, 2010 ...and that’s why
  • 48. Dist::Zilla is AWESOME Tuesday, December 14, 2010 ...because it frees you up to do things that are much more interesting than distribution building, like...
  • 50. - eating cake and pie (and donuts) Tuesday, December 14, 2010
  • 51. - eating cake and pie (and donuts) - drinking cocktails and beer Tuesday, December 14, 2010
  • 52. - eating cake and pie (and donuts) - drinking cocktails and beer - shooting zombies Tuesday, December 14, 2010
  • 53. - eating cake and pie (and donuts) - drinking cocktails and beer - shooting zombies - giving away useful software Tuesday, December 14, 2010
  • 54. Dist::Zilla is HUGE Tuesday, December 14, 2010
  • 56. 106 prereqs (and counting) Tuesday, December 14, 2010
  • 58. - Dist::Zilla only handles “make dist” Tuesday, December 14, 2010
  • 59. - Dist::Zilla only handles “make dist” - it doesn’t handle “make install” Tuesday, December 14, 2010
  • 60. - Dist::Zilla only handles “make dist” - it doesn’t handle “make install” - only authors need to install the 106 prereqs Tuesday, December 14, 2010
  • 61. - Dist::Zilla only handles “make dist” - it doesn’t handle “make install” - only authors need to install the 106 prereqs - your users don’t see Dist::Zilla Tuesday, December 14, 2010
  • 62. - Dist::Zilla only handles “make dist” - it doesn’t handle “make install” - only authors need to install the 106 prereqs - your users don’t see Dist::Zilla - they just see MakeMaker or Module::Build Tuesday, December 14, 2010
  • 63. Dist::Zilla is also Stupid Tuesday, December 14, 2010 like me!
  • 64. It keeps its brains in plugins. Tuesday, December 14, 2010 Almost all of the remainder of this talk is going to be about DZ plugins, because they do all the work. DZ itself just orchestrates the interaction of plugins. When you use Dist::Zilla, you provide it with a configuration file that sets up your plugins.
  • 65. dist.ini Tuesday, December 14, 2010 It’s almost always an INI file. INI is a nice simple format, and I’m going to just assume everybody understands it. Here’s a sample dist.ini:
  • 66. name = Your-Dist license = Perl_5 copyright_holder = J.builds a dist: # How Dist::Zilla Fred Bloggs [GatherDir] prepare; include_dotfiles = 1 gather_files; prune_files; [PruneCruft] munge_files; [MetaYAML] [MakeMaker] register_prereqs; [TestRelease] setup_installer; [ConfirmRelease] write_files; finish; [UploadToCPAN] user = JFB password = QwardRules Tuesday, December 14, 2010 You can do lots of different things in really varied ways, and there are people who use Dist::Zilla with very different workflows to mine. But I’m going to talk about how I use Dist::Zilla, which by grand coincidence is the one reflected in the tutorial and is probably the most common workflow.
  • 67. name = Your-Dist license = Perl_5 copyright_holder = J.builds a dist: # How Dist::Zilla Fred Bloggs [GatherDir] prepare; include_dotfiles = 1 gather_files; prune_files; [PruneCruft] munge_files; [MetaYAML] [MakeMaker] register_prereqs; [TestRelease] setup_installer; [ConfirmRelease] write_files; finish; [UploadToCPAN] user = JFB password = QwardRules Tuesday, December 14, 2010 the root section generally describes the dist itself, and is pretty short
  • 68. name = Your-Dist license = Perl_5 copyright_holder = J.builds a dist: # How Dist::Zilla Fred Bloggs [GatherDir] prepare; include_dotfiles = 1 gather_files; prune_files; [PruneCruft] munge_files; [MetaYAML] [MakeMaker] register_prereqs; [TestRelease] setup_installer; [ConfirmRelease] write_files; finish; [UploadToCPAN] user = JFB password = QwardRules Tuesday, December 14, 2010 here’s a section that defined a plugin, with one option set
  • 69. name = Your-Dist license = Perl_5 copyright_holder = J.builds a dist: # How Dist::Zilla Fred Bloggs [GatherDir] prepare; include_dotfiles = 1 gather_files; prune_files; [PruneCruft] munge_files; [MetaYAML] [MakeMaker] register_prereqs; [TestRelease] setup_installer; [ConfirmRelease] write_files; finish; [UploadToCPAN] user = JFB password = QwardRules Tuesday, December 14, 2010 and this line sets up a plugin with no args -- the next line is just another plugin
  • 70. name = Dist-Zilla author = Ricardo SIGNES <rjbs@cpan.org> license = Perl_5 copyright_holder = Ricardo SIGNES [@Basic] [AutoPrereq] [AutoVersion] [PkgVersion] [MetaConfig] [MetaJSON] [NextRelease] [PodSyntaxTests] [Repository] [PodWeaver] [@Git] Tuesday, December 14, 2010 RJBS: THESE THREE SLIDES ARE A SPEED RUN; detailed version to follow immediately
  • 71. name = Dist-Zilla author = Ricardo SIGNES <rjbs@cpan.org> license = Perl_5 copyright_holder = Ricardo SIGNES [@Basic] [AutoPrereq] [AutoVersion] [PkgVersion] [MetaConfig] [MetaJSON] [NextRelease] [PodSyntaxTests] [Repository] [PodWeaver] [@Git] Tuesday, December 14, 2010 @Basic means a bundle, and that bundle expands to this:
  • 72. [GatherDir] [PruneCruft] [ManifestSkip] [MetaYAML] [License] [Readme] [ExtraTests] [ExecDir] [ShareDir] [MakeMaker] [Manifest] [TestRelease] [ConfirmRelease] [UploadToCPAN] Tuesday, December 14, 2010
  • 73. name = Dist-Zilla author = Ricardo SIGNES <rjbs@cpan.org> license = Perl_5 copyright_holder = Ricardo SIGNES [@Basic] [AutoPrereq] [AutoVersion] [PkgVersion] [MetaConfig] [MetaJSON] [NextRelease] [PodSyntaxTests] [Repository] [PodWeaver] [@Git] Tuesday, December 14, 2010
  • 75. Tuesday, December 14, 2010 test is just build then “make test” install is just build then “cpan .” release is just build, then cpan-upload (mostly)
  • 76. dzil build Tuesday, December 14, 2010 test is just build then “make test” install is just build then “cpan .” release is just build, then cpan-upload (mostly)
  • 77. dzil build dzil test Tuesday, December 14, 2010 test is just build then “make test” install is just build then “cpan .” release is just build, then cpan-upload (mostly)
  • 78. dzil build dzil test dzil install Tuesday, December 14, 2010 test is just build then “make test” install is just build then “cpan .” release is just build, then cpan-upload (mostly)
  • 79. dzil build dzil test dzil install dzil release Tuesday, December 14, 2010 test is just build then “make test” install is just build then “cpan .” release is just build, then cpan-upload (mostly)
  • 80. How Dist::Zilla Builds Tuesday, December 14, 2010 this is, obviously, a simplification -- but not as great a simplification as you might think to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
  • 81. How Dist::Zilla Builds sub build { Tuesday, December 14, 2010 this is, obviously, a simplification -- but not as great a simplification as you might think to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
  • 82. How Dist::Zilla Builds sub build { my ($self) = @_; Tuesday, December 14, 2010 this is, obviously, a simplification -- but not as great a simplification as you might think to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
  • 83. How Dist::Zilla Builds sub build { my ($self) = @_; my @files = $self->gather_files; Tuesday, December 14, 2010 this is, obviously, a simplification -- but not as great a simplification as you might think to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
  • 84. How Dist::Zilla Builds sub build { my ($self) = @_; my @files = $self->gather_files; $self->munge_files( @files ); Tuesday, December 14, 2010 this is, obviously, a simplification -- but not as great a simplification as you might think to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
  • 85. How Dist::Zilla Builds sub build { my ($self) = @_; my @files = $self->gather_files; $self->munge_files( @files ); $self->collect_metadata; Tuesday, December 14, 2010 this is, obviously, a simplification -- but not as great a simplification as you might think to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
  • 86. How Dist::Zilla Builds sub build { my ($self) = @_; my @files = $self->gather_files; $self->munge_files( @files ); $self->collect_metadata; $self->write_out( @files ); Tuesday, December 14, 2010 this is, obviously, a simplification -- but not as great a simplification as you might think to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
  • 87. How Dist::Zilla Builds sub build { my ($self) = @_; my @files = $self->gather_files; $self->munge_files( @files ); $self->collect_metadata; $self->write_out( @files ); } Tuesday, December 14, 2010 this is, obviously, a simplification -- but not as great a simplification as you might think to make any of these lines do anything useful, you need plugins; plugins contribute to these activities
  • 88. How do you pick plugins? Tuesday, December 14, 2010
  • 89. There is no default config. Tuesday, December 14, 2010
  • 90. @Basic Tuesday, December 14, 2010 ...but don’t just rush to use @Basic without understanding it. You should understand what DZ is doing so that you can understand what goes wrong, if anything goes wrong -- and something will go wrong. There is *no* default configuration for Dist::Zilla. The @Basic bundle exists as a useful starting point, but I doubt anybody would use only @Basic. There’s just too much that you can gain by adding on top of it.
  • 91. The Basics [GatherDir] [PruneCruft] [Manifest] [ManifestSkip] [MakeMaker] [License] [Readme] [MetaYAML] [ExtraTests] [ExecDir] [ShareDir] [TestRelease] [ConfirmRelease] [UploadToCPAN] Tuesday, December 14, 2010 @Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch any of your files on disk.
  • 92. The Basics [GatherDir] [PruneCruft] [Manifest] [ManifestSkip] [MakeMaker] MANIFEST [License] [Readme] [MetaYAML] [ExtraTests] [ExecDir] [ShareDir] [TestRelease] [ConfirmRelease] [UploadToCPAN] Tuesday, December 14, 2010 @Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch any of your files on disk.
  • 93. The Basics [GatherDir] [PruneCruft] [Manifest] [ManifestSkip] [MakeMaker] MANIFEST [License] Makefile.PL [Readme] [MetaYAML] [ExtraTests] [ExecDir] [ShareDir] [TestRelease] [ConfirmRelease] [UploadToCPAN] Tuesday, December 14, 2010 @Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch any of your files on disk.
  • 94. The Basics [GatherDir] [PruneCruft] [Manifest] [ManifestSkip] [MakeMaker] MANIFEST [License] Makefile.PL [Readme] LICENSE [MetaYAML] [ExtraTests] [ExecDir] [ShareDir] [TestRelease] [ConfirmRelease] [UploadToCPAN] Tuesday, December 14, 2010 @Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch any of your files on disk.
  • 95. The Basics [GatherDir] [PruneCruft] [Manifest] [ManifestSkip] [MakeMaker] MANIFEST [License] Makefile.PL [Readme] LICENSE [MetaYAML] README [ExtraTests] [ExecDir] [ShareDir] [TestRelease] [ConfirmRelease] [UploadToCPAN] Tuesday, December 14, 2010 @Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch any of your files on disk.
  • 96. The Basics [GatherDir] [PruneCruft] [Manifest] [ManifestSkip] [MakeMaker] MANIFEST [License] Makefile.PL [Readme] LICENSE [MetaYAML] README [ExtraTests] META.yml [ExecDir] [ShareDir] [TestRelease] [ConfirmRelease] [UploadToCPAN] Tuesday, December 14, 2010 @Basic’s goal is to do all the stuff almost everyone wants, and to let you delete files you don’t need, but @Basic will *not* touch any of your files on disk.
  • 98. Cruft Minimizers [PkgVersion] Tuesday, December 14, 2010
  • 99. Cruft Minimizers [PkgVersion] [PodSyntaxTests] Tuesday, December 14, 2010
  • 100. Cruft Minimizers [PkgVersion] [PodSyntaxTests] [PodCoverageTests] Tuesday, December 14, 2010
  • 101. Cruft Minimizers [PkgVersion] [PodSyntaxTests] [PodCoverageTests] [AutoPrereq] Tuesday, December 14, 2010
  • 102. Cruft Minimizers [PkgVersion] [PodSyntaxTests] [PodCoverageTests] [AutoPrereq] [AutoVersion] Tuesday, December 14, 2010
  • 103. Cruft Minimizers [PkgVersion] [PodSyntaxTests] [PodCoverageTests] [AutoPrereq] [AutoVersion] [NextRelease] Tuesday, December 14, 2010
  • 104. Version Control [@Git] [@Subversion] [@Mercurial] [@SVK] Tuesday, December 14, 2010 this is a place where it *might* be reasonable to use a bundle when you start
  • 106. package YourApp; =head1 NAME YourApp - my awesome app =head1 VERSION version 1.001 =cut our $VERSION = 0.001; =head1 DESCRIPTION This app is awesome. =head1 METHODS =head2 this_method This method does stuff. =cut method this_method { ... } =head2 that_method Also stuff. =cut method that_method { ... } =head1 AUTHOR Margo Yapp <myapp@example.com> =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 Here’s a .pm file
  • 107. package YourApp; =head1 NAME YourApp - my awesome app =head1 VERSION version 1.001 =cut our $VERSION = 0.001; =head1 DESCRIPTION This app is awesome. =head1 METHODS =head2 this_method This method does stuff. =cut method this_method { ... } =head2 that_method Also stuff. =cut method that_method { ... } =head1 AUTHOR Margo Yapp <myapp@example.com> =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 Here’s a .pm file
  • 108. package YourApp; =head1 NAME YourApp - my awesome app =head1 VERSION version 1.001 =cut our $VERSION = 0.001; =head1 DESCRIPTION This app is awesome. =head1 METHODS =head2 this_method This method does stuff. =cut method this_method { ... } =head2 that_method Also stuff. =cut method that_method { ... } =head1 AUTHOR Margo Yapp <myapp@example.com> =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 The =name section is annoying.
  • 109. package YourApp; # ABSTRACT: my awesome app =head1 VERSION version 1.001 =cut our $VERSION = 0.001; =head1 DESCRIPTION This app is awesome. =head1 METHODS =head2 this_method This method does stuff. =cut method this_method { ... } =head2 that_method Also stuff. =cut method that_method { ... } =head1 AUTHOR Margo Yapp <myapp@example.com> =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 We’ll replace it with a comment.
  • 110. package YourApp; # ABSTRACT: my awesome app =head1 VERSION version 1.001 =cut our $VERSION = 0.001; =head1 DESCRIPTION This app is awesome. =head1 METHODS =head2 this_method This method does stuff. =cut method this_method { ... } =head2 that_method Also stuff. =cut method that_method { ... } =head1 AUTHOR Margo Yapp <myapp@example.com> =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 The =version section is redundant.
  • 111. package YourApp; # ABSTRACT: my awesome app our $VERSION = 0.001; =head1 DESCRIPTION This app is awesome. =head1 METHODS =head2 this_method This method does stuff. =cut method this_method { ... } =head2 that_method Also stuff. =cut method that_method { ... } =head1 AUTHOR Margo Yapp <myapp@example.com> =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 Drop it.
  • 112. package YourApp; # ABSTRACT: my awesome app our $VERSION = 0.001; =head1 DESCRIPTION This app is awesome. =head1 METHODS =head2 this_method This method does stuff. =cut method this_method { ... } =head2 that_method Also stuff. =cut method that_method { ... } =head1 AUTHOR Margo Yapp <myapp@example.com> =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 Even the $VERSION is redundant, since we want it constant across the dist.
  • 113. package YourApp; # ABSTRACT: my awesome app =head1 DESCRIPTION This app is awesome. =head1 METHODS =head2 this_method This method does stuff. =cut method this_method { ... } =head2 that_method Also stuff. =cut method that_method { ... } =head1 AUTHOR Margo Yapp <myapp@example.com> =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 our overarching METHOD section is dumb
  • 114. package YourApp; # ABSTRACT: my awesome app =head1 DESCRIPTION This app is awesome. =method this_method This method does stuff. =cut method this_method { ... } =method that_method Also stuff. =cut method that_method { ... } =head1 AUTHOR Margo Yapp <myapp@example.com> =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 let’s just use =method for them all
  • 115. package YourApp; # ABSTRACT: my awesome app =head1 DESCRIPTION This app is awesome. =method this_method This method does stuff. =cut method this_method { ... } =method that_method Also stuff. =cut method that_method { ... } =head1 AUTHOR Margo Yapp <myapp@example.com> =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 Repeating the author everywhere is annoying, too.
  • 116. package YourApp; # ABSTRACT: my awesome app =head1 DESCRIPTION This app is awesome. =method this_method This method does stuff. =cut method this_method { ... } =method that_method Also stuff. =cut method that_method { ... } =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 Drop it, use author info found in DZ config.
  • 117. package YourApp; # ABSTRACT: my awesome app =head1 DESCRIPTION This app is awesome. =method this_method This method does stuff. =cut method this_method { ... } =method that_method Also stuff. method that_method { ... } =head1 LICENSE Copyright (C) 2008, Margo Yapp. This is distributed under the terms of the accidental death and dismemberment license and if you redistribuet this document you will be “accidentally” deathed or dismembered. You have been told. =cut 1; Tuesday, December 14, 2010 The license is gigantic! Ugh!
  • 118. package YourApp; # ABSTRACT: my awesome app =head1 DESCRIPTION This app is awesome. =method this_method This method does stuff. =cut method this_method { ... } =method that_method Also stuff. =cut method that_method { ... } =cut 1; Tuesday, December 14, 2010 Drop it.
  • 119. package YourApp; # ABSTRACT: my awesome app =head1 DESCRIPTION This app is awesome. =method this_method This method does stuff. =cut method this_method { ... } =method that_method Also stuff. =cut method that_method { ... } 1; Tuesday, December 14, 2010 Now our file is simple, just the unique docs and code it needs. It fits on one legible slide!
  • 120. package YourApp; # ABSTRACT: my awesome app =head1 DESCRIPTION This app is awesome. =method this_method This method does stuff. =cut method this_method { ... } =method that_method Also stuff. =cut method that_method { ... } 1; Tuesday, December 14, 2010 And is about half Perl. and you get all of that stuff autogenerated by adding this to your dist.ini
  • 122. Converting Your Dist Tuesday, December 14, 2010
  • 123. Converting Your Dist - create dist.ini Tuesday, December 14, 2010
  • 124. Converting Your Dist - create dist.ini - remove a bunch of files Tuesday, December 14, 2010
  • 125. Converting Your Dist - create dist.ini - remove a bunch of files - delete a bunch of stuff from leftover files Tuesday, December 14, 2010
  • 126. Converting Your Dist - create dist.ini - remove a bunch of files - delete a bunch of stuff from leftover files - and Dist::Zooky, too Tuesday, December 14, 2010
  • 127. Questions so far? Tuesday, December 14, 2010
  • 128. Creating New Dists Tuesday, December 14, 2010
  • 129. dzil build dzil test dzil install dzil release Tuesday, December 14, 2010 so, we already talked about these commands, which all operate on an existing distribution directory to build a fleshed-out CPAN distribution. to mint a brand-new dist, we use...
  • 130. dzil build dzil test dzil install dzil release dzil new Tuesday, December 14, 2010 dzil new! the big difference is that the first set of commands work on an existing dist, so there’s a dist.ini we don’t have a dist.ini yet, because there’s no dist dir yet. we need a...
  • 131. profile.ini Tuesday, December 14, 2010 this file sets up the plugins that you’ll use to mint a new dist (don’t worry, if you don’t make one, there *is* default behavior -- but it’s so incredibly simple that you probably don’t want it)
  • 132. Tuesday, December 14, 2010 to understand how this works, we need to look at how minting works
  • 133. [GatherDir::Template] Tuesday, December 14, 2010 to understand how this works, we need to look at how minting works
  • 134. [GatherDir::Template] root = files Tuesday, December 14, 2010 to understand how this works, we need to look at how minting works
  • 135. [GatherDir::Template] root = files [DistINI] Tuesday, December 14, 2010 to understand how this works, we need to look at how minting works
  • 136. [GatherDir::Template] root = files [DistINI] [Git::Init] Tuesday, December 14, 2010 to understand how this works, we need to look at how minting works
  • 137. How Dist::Zilla Mints Tuesday, December 14, 2010
  • 138. How Dist::Zilla Mints sub mint { Tuesday, December 14, 2010
  • 139. How Dist::Zilla Mints sub mint { my ($self) = @_; Tuesday, December 14, 2010
  • 140. How Dist::Zilla Mints sub mint { my ($self) = @_; my @files = $self->gather_files; Tuesday, December 14, 2010
  • 141. How Dist::Zilla Mints sub mint { my ($self) = @_; my @files = $self->gather_files; $self->munge_files( @files ); Tuesday, December 14, 2010
  • 142. How Dist::Zilla Mints sub mint { my ($self) = @_; my @files = $self->gather_files; $self->munge_files( @files ); $self->make_module( $module ); Tuesday, December 14, 2010
  • 143. How Dist::Zilla Mints sub mint { my ($self) = @_; my @files = $self->gather_files; $self->munge_files( @files ); $self->make_module( $module ); $self->write_out( @files ); Tuesday, December 14, 2010
  • 144. How Dist::Zilla Mints sub mint { my ($self) = @_; my @files = $self->gather_files; $self->munge_files( @files ); $self->make_module( $module ); $self->write_out( @files ); } Tuesday, December 14, 2010
  • 145. Tuesday, December 14, 2010 see how there’s no root section? We *could* add one, but it would probably be the same across multiple profiles we set up, so we can put this stuff in another location:
  • 146. [GatherDir::Template] Tuesday, December 14, 2010 see how there’s no root section? We *could* add one, but it would probably be the same across multiple profiles we set up, so we can put this stuff in another location:
  • 147. [GatherDir::Template] root = files Tuesday, December 14, 2010 see how there’s no root section? We *could* add one, but it would probably be the same across multiple profiles we set up, so we can put this stuff in another location:
  • 148. [GatherDir::Template] root = files [DistINI] Tuesday, December 14, 2010 see how there’s no root section? We *could* add one, but it would probably be the same across multiple profiles we set up, so we can put this stuff in another location:
  • 149. [GatherDir::Template] root = files [DistINI] [Git::Init] Tuesday, December 14, 2010 see how there’s no root section? We *could* add one, but it would probably be the same across multiple profiles we set up, so we can put this stuff in another location:
  • 150. config.ini Tuesday, December 14, 2010 global (per-user) configuration
  • 152. [%User] name = Ricardo Signes email = rjbs@example.org [%Rights] license_class = Perl_5 copyright_holder = Ricardo Signes [%PAUSE] username = RJBS password = PeasAreDelicious Tuesday, December 14, 2010 these aren’t plugins; global configuration is loaded before we have a Dist::Zilla object to plug into instead, these are stashes; basically, hunks of data for plugins to look up; they can be shared, generic, referenced by name, etc etc etc here we see our default author, our default license/legal info, and default PAUSE upload credentials
  • 154. Minting a New Dist - create config.ini (in ~/.dzil) - maybe configure or install a profile - run dzil new Tuesday, December 14, 2010
  • 155. Questions so far? Tuesday, December 14, 2010
  • 157. Writing Plugins is Easy! Tuesday, December 14, 2010
  • 158. Writing Plugins is Easy! (and awesome) Tuesday, December 14, 2010
  • 159. How Dist::Zilla Builds sub build { my ($self) = @_; my @files = $self->gather_files; $self->munge_files( @files ); $self->collect_metadata; $self->write_out( @files ); } Tuesday, December 14, 2010 This is what I showed, earlier, as a simplified example of how Dist::Zilla builds stuff. To understand how plugins work, we need to de-simplify a little.
  • 160. How Dist::Zilla Builds $self->munge_files( @files ); Tuesday, December 14, 2010 Take this line... what happens is a bit more like this:
  • 161. How Dist::Zilla Builds my @mungers = grep { $_->does(‘FileMunger’) } $self->plugins; for my $plugin (@mungers) { $plugin->munge_files( @files ); } Tuesday, December 14, 2010 we call a method on a bunch of delegates, where the delegates are all of the (undifferentiated) plugins that perform a given rol
  • 162. $obj->does( $role ) package Some::Class; use Moose; with ‘Some::Role’; Tuesday, December 14, 2010 LEARN MOOSE
  • 163. Roles to Make Plugins Go Tuesday, December 14, 2010
  • 164. Roles to Make Plugins Go BeforeBuild Tuesday, December 14, 2010
  • 165. Roles to Make Plugins Go BeforeBuild FileGatherer Tuesday, December 14, 2010
  • 166. Roles to Make Plugins Go BeforeBuild FileGatherer FilePruner Tuesday, December 14, 2010
  • 167. Roles to Make Plugins Go BeforeBuild FileGatherer FilePruner FileMunger Tuesday, December 14, 2010
  • 168. Roles to Make Plugins Go BeforeBuild FileGatherer FilePruner FileMunger PrereqSource Tuesday, December 14, 2010
  • 169. Roles to Make Plugins Go BeforeBuild FileGatherer FilePruner FileMunger PrereqSource MetaProvider Tuesday, December 14, 2010
  • 170. Roles to Make Plugins Go BeforeBuild FileGatherer FilePruner FileMunger PrereqSource MetaProvider AfterBuild Tuesday, December 14, 2010
  • 171. Roles to Make Plugins Go BeforeBuild FileGatherer FilePruner FileMunger PrereqSource MetaProvider AfterBuild BeforeArchive Tuesday, December 14, 2010
  • 172. Roles to Make Plugins Go BeforeBuild FileGatherer FilePruner FileMunger PrereqSource MetaProvider AfterBuild BeforeArchive BeforeRelease Tuesday, December 14, 2010
  • 173. Roles to Make Plugins Go BeforeBuild FileGatherer FilePruner FileMunger PrereqSource MetaProvider AfterBuild BeforeArchive BeforeRelease Releaser Tuesday, December 14, 2010
  • 174. Roles to Make Plugins Go BeforeBuild FileGatherer FilePruner FileMunger PrereqSource MetaProvider AfterBuild BeforeArchive BeforeRelease Releaser AfterRelease Tuesday, December 14, 2010
  • 175. Let’s write a plugin! Tuesday, December 14, 2010
  • 177. BuiltOn package Dist::Zilla::Plugin::BuiltOn; Tuesday, December 14, 2010
  • 178. BuiltOn package Dist::Zilla::Plugin::BuiltOn; use Moose; Tuesday, December 14, 2010
  • 179. BuiltOn package Dist::Zilla::Plugin::BuiltOn; use Moose; with ‘Dist::Zilla::Role::FileGatherer’; Tuesday, December 14, 2010
  • 180. BuiltOn package Dist::Zilla::Plugin::BuiltOn; use Moose; with ‘Dist::Zilla::Role::FileGatherer’; sub gather_files { Tuesday, December 14, 2010
  • 181. BuiltOn package Dist::Zilla::Plugin::BuiltOn; use Moose; with ‘Dist::Zilla::Role::FileGatherer’; sub gather_files { my ($self) = @_; Tuesday, December 14, 2010
  • 182. BuiltOn package Dist::Zilla::Plugin::BuiltOn; use Moose; with ‘Dist::Zilla::Role::FileGatherer’; sub gather_files { my ($self) = @_; my $file = Dist::Zilla::File::InMemory->new({ Tuesday, December 14, 2010
  • 183. BuiltOn package Dist::Zilla::Plugin::BuiltOn; use Moose; with ‘Dist::Zilla::Role::FileGatherer’; sub gather_files { my ($self) = @_; my $file = Dist::Zilla::File::InMemory->new({ name => ‘built-on.txt’, Tuesday, December 14, 2010
  • 184. BuiltOn package Dist::Zilla::Plugin::BuiltOn; use Moose; with ‘Dist::Zilla::Role::FileGatherer’; sub gather_files { my ($self) = @_; my $file = Dist::Zilla::File::InMemory->new({ name => ‘built-on.txt’, content => scalar `uname -a`, Tuesday, December 14, 2010
  • 185. BuiltOn package Dist::Zilla::Plugin::BuiltOn; use Moose; with ‘Dist::Zilla::Role::FileGatherer’; sub gather_files { my ($self) = @_; my $file = Dist::Zilla::File::InMemory->new({ name => ‘built-on.txt’, content => scalar `uname -a`, }); Tuesday, December 14, 2010
  • 186. BuiltOn package Dist::Zilla::Plugin::BuiltOn; use Moose; with ‘Dist::Zilla::Role::FileGatherer’; sub gather_files { my ($self) = @_; my $file = Dist::Zilla::File::InMemory->new({ name => ‘built-on.txt’, content => scalar `uname -a`, }); $self->add_file( $file ); Tuesday, December 14, 2010
  • 187. BuiltOn package Dist::Zilla::Plugin::BuiltOn; use Moose; with ‘Dist::Zilla::Role::FileGatherer’; sub gather_files { my ($self) = @_; my $file = Dist::Zilla::File::InMemory->new({ name => ‘built-on.txt’, content => scalar `uname -a`, }); $self->add_file( $file ); } Tuesday, December 14, 2010
  • 188. BuiltOn [BuiltOn] Tuesday, December 14, 2010
  • 189. package Dist::Zilla::Plugin::BuiltOn; use Moose; with ‘Dist::Zilla::Role::FileGatherer’; has filename => ( is => ‘ro’, default => ‘built-on.txt’, ); sub gather_files { my ($self) = @_; my $file = Dist::Zilla::File::InMemory->new({ name => $self->filename, content => scalar `uname -a`, }); $self->add_file( $file ); } Tuesday, December 14, 2010
  • 190. BuiltOn [BuiltOn] filename = build-host.txt Tuesday, December 14, 2010
  • 191. BuiltOn [BuiltOn] Tuesday, December 14, 2010
  • 192. Let’s write a another! Tuesday, December 14, 2010 (this will talk about plugin ordering)
  • 193. AddShebangs Tuesday, December 14, 2010 ...and then just one more...
  • 194. AddShebangs package Dist::Zilla::Plugin::AddShebangs; Tuesday, December 14, 2010 ...and then just one more...
  • 195. AddShebangs package Dist::Zilla::Plugin::AddShebangs; use Moose; Tuesday, December 14, 2010 ...and then just one more...
  • 196. AddShebangs package Dist::Zilla::Plugin::AddShebangs; use Moose; with ‘Dist::Zilla::Role::FileMunger’; Tuesday, December 14, 2010 ...and then just one more...
  • 197. AddShebangs package Dist::Zilla::Plugin::AddShebangs; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { Tuesday, December 14, 2010 ...and then just one more...
  • 198. AddShebangs package Dist::Zilla::Plugin::AddShebangs; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; Tuesday, December 14, 2010 ...and then just one more...
  • 199. AddShebangs package Dist::Zilla::Plugin::AddShebangs; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; next unless $file->name =~ /.pl$/; Tuesday, December 14, 2010 ...and then just one more...
  • 200. AddShebangs package Dist::Zilla::Plugin::AddShebangs; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; next unless $file->name =~ /.pl$/; my $content = “#!$^Xn” Tuesday, December 14, 2010 ...and then just one more...
  • 201. AddShebangs package Dist::Zilla::Plugin::AddShebangs; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; next unless $file->name =~ /.pl$/; my $content = “#!$^Xn” . $file->content; Tuesday, December 14, 2010 ...and then just one more...
  • 202. AddShebangs package Dist::Zilla::Plugin::AddShebangs; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; next unless $file->name =~ /.pl$/; my $content = “#!$^Xn” . $file->content; $file->content( $content ); Tuesday, December 14, 2010 ...and then just one more...
  • 203. AddShebangs package Dist::Zilla::Plugin::AddShebangs; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; next unless $file->name =~ /.pl$/; my $content = “#!$^Xn” . $file->content; $file->content( $content ); } Tuesday, December 14, 2010 ...and then just one more...
  • 205. AddBlame package Dist::Zilla::Plugin::AddBlame; Tuesday, December 14, 2010
  • 206. AddBlame package Dist::Zilla::Plugin::AddBlame; use Moose; Tuesday, December 14, 2010
  • 207. AddBlame package Dist::Zilla::Plugin::AddBlame; use Moose; with ‘Dist::Zilla::Role::FileMunger’; Tuesday, December 14, 2010
  • 208. AddBlame package Dist::Zilla::Plugin::AddBlame; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { Tuesday, December 14, 2010
  • 209. AddBlame package Dist::Zilla::Plugin::AddBlame; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; Tuesday, December 14, 2010
  • 210. AddBlame package Dist::Zilla::Plugin::AddBlame; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; next unless $file->name =~ /.p[lm]$/; Tuesday, December 14, 2010
  • 211. AddBlame package Dist::Zilla::Plugin::AddBlame; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; next unless $file->name =~ /.p[lm]$/; my $content = “# BUILD BY $ENV{USER}n” Tuesday, December 14, 2010
  • 212. AddBlame package Dist::Zilla::Plugin::AddBlame; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; next unless $file->name =~ /.p[lm]$/; my $content = “# BUILD BY $ENV{USER}n” . $file->content; Tuesday, December 14, 2010
  • 213. AddBlame package Dist::Zilla::Plugin::AddBlame; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; next unless $file->name =~ /.p[lm]$/; my $content = “# BUILD BY $ENV{USER}n” . $file->content; $file->content( $content ); Tuesday, December 14, 2010
  • 214. AddBlame package Dist::Zilla::Plugin::AddBlame; use Moose; with ‘Dist::Zilla::Role::FileMunger’; sub munge_file { my ($self, $file) = @_; next unless $file->name =~ /.p[lm]$/; my $content = “# BUILD BY $ENV{USER}n” . $file->content; $file->content( $content ); } Tuesday, December 14, 2010
  • 215. [GatherDir] [PruneCruft] Tuesday, December 14, 2010
  • 216. [GatherDir] [PruneCruft] [AddShebangs] [AddBlame] Tuesday, December 14, 2010 this is actually a problem
  • 217. [GatherDir] [PruneCruft] [AddShebangs] [AddBlame] print “Hello.n”; Tuesday, December 14, 2010 If we start with this extremely powerful library file...
  • 218. [GatherDir] [PruneCruft] [AddShebangs] [AddBlame] #!/usr/bin/perl print “Hello.n”; Tuesday, December 14, 2010 The shebang gets added, just like we wanted.
  • 219. [GatherDir] [PruneCruft] [AddShebangs] [AddBlame] # built by rjbs #!/usr/bin/perl print “Hello.n”; Tuesday, December 14, 2010 then the comment -- meaning the shebang is no good, because it doesn’t start the file
  • 220. [GatherDir] [PruneCruft] [AddBlame] [AddShebangs] #!/usr/bin/perl # built by rjbs print “Hello.n”; Tuesday, December 14, 2010 then the comment -- meaning the shebang is no good, because it doesn’t start the file
  • 223. Dist::Zilla is: - judges will accept: - awesome - huge - stupid Tuesday, December 14, 2010
  • 224. We are Friendly - irc.perl.org #distzilla - http://dzil.org/ - mailing list - http://rt.cpan.org/ Tuesday, December 14, 2010 we will try to answer your questions
  • 225. Any Questions? Tuesday, December 14, 2010
  • 226. Thank you! raaaaaaaaar! Tuesday, December 14, 2010