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
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...
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...
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
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:
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.
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
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
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
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
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:
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
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
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
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