#   ---------------------------------------------------------------------- copyright and license ---
#
#   file: lib/Dist/Zilla/Plugin/Manifes/Write/Manual.pod
#
#   Copyright © 2015, 2016 Van de Bugger.
#
#   This file is part of perl-Dist-Zilla-Plugin-Manifest-Write.
#
#   perl-Dist-Zilla-Plugin-Manifest-Write is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by the Free Software
#   Foundation, either version 3 of the License, or (at your option) any later version.
#
#   perl-Dist-Zilla-Plugin-Manifest-Write is distributed in the hope that it will be useful, but
#   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
#   PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License along with
#   perl-Dist-Zilla-Plugin-Manifest-Write. If not, see <http://www.gnu.org/licenses/>.
#
#   ---------------------------------------------------------------------- copyright and license ---

# PODNAME: Dist::Zilla::Plugin::Manifest::Write::Manual
# ABSTRACT: C<Manifest::Write> plugin user manual

#pod =for :this This is C<Manifest::Write> plugin user manual. Read this if you want to
#pod have annotated distribution manifest.
#pod
#pod =for :those If you are going to hack or extend C<Manifest::Write>, read the L<module
#pod documentation|Dist::Zilla::Plugin::Manifest::Write>. General topics like getting source, building, installing, bug
#pod reporting and some others are covered in the F<README>.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =for test_synopsis BEGIN { die "SKIP: Not Perl code.\n" };
#pod
#pod =head1 SYNOPSIS
#pod
#pod In your F<dist.ini>:
#pod
#pod     ...
#pod     [GatherDir]         ; Plugin which adds source files to distribution.
#pod                         ; You may use other plugins, like GatherFromManifest
#pod                         ; or Manifest::Read.
#pod     [Manifest::Write]
#pod         source_provider = GatherDir
#pod         exclude_files   = :ExtraTestFiles
#pod     ...
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =head1 DESCRIPTION
#pod
#pod C<Manifest::Write> is a replacement for standard plugin C<Manifest>. To use C<Manifest::Write>, you
#pod should replace line
#pod
#pod     [Manifest]
#pod
#pod with
#pod
#pod     [Manifest::Write]
#pod
#pod in your F<dist.ini> file, and specify one or more source providers, e. g.:
#pod
#pod     [Manifest::Write]
#pod         source_provider = GatherDir
#pod
#pod (See C<source_provider> option below for details.)
#pod
#pod =head2 Manifest File
#pod
#pod Manifest file enlists files which should be included into the distribution. Usually manifest file
#pod itself is also included into the distribution.
#pod
#pod The name of manifest file written by the C<Manifest::Write> is specified by C<manifest> option.
#pod Default value is F<MANIFEST>, a conventional name for the manifest file.
#pod
#pod =head2 Manifest File Format
#pod
#pod Manifest file generated by C<Manifest::Write> follows the format defined in
#pod L<ExtUtils::Manifest/"MANIFEST">. However, I<comments> generated by the C<Manifest::Write> have
#pod internal structure, see below.
#pod
#pod If the first non-whitespace character of a line is hash character (C<#>), such line is a comment.
#pod
#pod Other lines in annotated manifest follows the format:
#pod
#pod     NAME # DEED file BREED by ADDER [ and munged by MUNGER,… ]
#pod
#pod Square brackets denote optional part, ellipsis denotes repeatable part, hash (C<#>), C<file>,
#pod C<by>, C<and munged by> are literals.
#pod
#pod =over
#pod
#pod =item I<NAME>
#pod
#pod Just a file name. If file name contains spaces, apostrophes (C<'>), backslashes (C<\>), or hashes
#pod (C<#>) it is formatted as Perl single-quoted string literal, otherwise it is written as-is.
#pod
#pod =item C<#>
#pod
#pod Technically, hash character is not required because everything after a file name is a comment, hash
#pod just visually emphasises it.
#pod
#pod =item I<DEED>
#pod
#pod File "deed" is file ownership: if the file (1) belongs to the project, is (2) meta information, or
#pod (3) third-party file. In the first case "deed" is project (distribution) name, in the second —
#pod C<metainfo>, in the third — C<3rd party>. (So, do not name your project "metainfo" to avoid
#pod confusion.)
#pod
#pod =item I<BREED>
#pod
#pod File "breed" explains how the file appeared in the distribution — was it C<added> (copied as-is
#pod from the project sources) or C<built> (generated).
#pod
#pod =item I<ADDER>
#pod
#pod File "adder" is a I<moniker> of plugin (see L</"Plugin moniker">) brought (either C<added> or
#pod C<built>, see L</"BREED">) the file into the distribution.
#pod
#pod Plugins bringing files to distribution do C<FileInjector> or C<FileGatherer> roles. Some plugins
#pod add existing files to distribution (e. g. C<GatherDir>, C<Manifest::Read>), others generate new
#pod files (e. g. C<Test::EOL>, C<Test::NoTabs>).
#pod
#pod =item I<MUNGER>
#pod
#pod File "munger" is a plugin changed the file during build.
#pod
#pod Plugins modifying files in distribution do C<FileMunger> role. Some plugins may touch files
#pod slightly (for example, C<PkgVersion> changes a single line in Perl modules), others may rewrite
#pod them heavily (C<PodWeaver> removes or comments out all existing POD and generates new POD at the
#pod end).
#pod
#pod The same file may be changed several times during build. For example, Perl module may be processed
#pod by both C<PkgVersion> and C<PodWeaver>.
#pod
#pod Quite often the same plugin appears as both adder and munger. Many plugins add a generic template
#pod to the distribution first, then tune the template to meet the distribution needs.
#pod
#pod If a file was not changed after its addition to the distribution, annotation will not show any
#pod mungers for this file, obviously. Also, all munger may be forcibly hidden by C<show_mungers>
#pod option.
#pod
#pod =back
#pod
#pod =head2 Skip File
#pod
#pod Skip file defines files which should I<not> be included into distribution. See
#pod L<ExtUtils::Manifest/"MANIFEST.SKIP"> for more details.
#pod
#pod C<Manifest::Write> generates skip file. Skip file name is set by C<manifest_skip> option. Default
#pod name is F<MANIFEST.SKIP>. Empty name disables generating skip file.
#pod
#pod Skip file generated by the C<Manifest::Write> consists of list of excluded files (see
#pod L</exclude_files>) and copy of content of F<MANIFEST.SKIP> file from currently installed
#pod C<ExtUtils::Manifest> distribution (content is copied at the distribution build time). "#!include"
#pod and "#!include_default" are not used (because they are not recognized by C<Module::Manifest>).
#pod
#pod Skip file could be necessary to let C<Test::DistManifest> pass — the tests checks the every file is
#pod either listed in F<MANIFEST> or skipped.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =option exclude_files
#pod
#pod This option excludes files from the manifest (and from the distribution archive).
#pod
#pod Option value should be a name of file finder. Default value is C<:NoFiles> (i. e. no files are
#pod excluded, all the built files are packed to the distribution archive).
#pod
#pod This is a multi-value option, i. e. it could be specified several times. Files found by any of the
#pod specified finders are excluded from the distribution archive.
#pod
#pod     [Manifest::Write]
#pod         exclude_files = :ExtraTestFiles
#pod
#pod See also L</"Excluding Files">.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =option manifest
#pod
#pod Name of manifest file to write. Default value is F<MANIFEST>. It is unlikely you will need to
#pod change the default value.
#pod
#pod It could be used, though, to generate both standard and annotated manifests (for testing,
#pod comparison, etc):
#pod
#pod     [Manifest]          ; Writes 'MANIFEST'.
#pod     [Manifest::Write]   ; Writes 'Manifest.annotated'.
#pod         manifest = Manifest.annotated
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =option manifest_skip
#pod
#pod Name of skip file to write. Default value is F<MANIFEST.SKIP>. It is unlikely you will need to
#pod change the default value. However, empty value disables generating F<MANIFEST.SKIP>:
#pod
#pod     [Manifest::Write]
#pod         manifest_skip = ; Disable writing 'MANIFEST.SKIP'.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =option source_provider
#pod
#pod This is a multi-value option, i. e. option may be specified several times. Every option value is a
#pod name of plugin (see L</"Plugin name">) which adds I<source files> to distribution.
#pod
#pod     source_provider = GatherDir
#pod     source_provider = GatherDir::Template
#pod     source_provider = GenerateFile
#pod
#pod There are no default source file providers. You will likely want to specify C<GatherDir>,
#pod C<GatherFromManifest> and similar plugins as source providers.
#pod
#pod Note: I<source files> term does I<not> mean exactly Perl sources. Source files are I<your> files
#pod (usually hand-crafted), in contrast to metainfo and 3rd party files generated by various
#pod C<Dist::Zilla> plugins. Sources may include Perl modules, scripts, POD files, tests, and any other
#pod files composing your software.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =option source_providers
#pod
#pod The option splits its value into plugin names using whitespaces as separators, so
#pod
#pod     source_providers = GatherDir GatherDir::Template GenerateFile
#pod
#pod is just a shortcut for
#pod
#pod     source_provider = GatherDir
#pod     source_provider = GatherDir::Template
#pod     source_provider = GenerateFile
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =option metainfo_provider
#pod
#pod This is multi-value option too. Every value is a name of plugin (see L</"Plugin name">) which adds
#pod I<meta information files> to the distribution:
#pod
#pod     metainfo_provider = MetaYAML
#pod     metainfo_provider = MetaJSON
#pod     metainfo_provider = Manifest
#pod
#pod Default meta info providers are C<CPANFile>, C<Manifest>, C<MetaYAML>, C<MetaJSON>, and the
#pod C<Manifest::Write> plugin itself. It seems these metainfo providers should satisfy most of the
#pod users.
#pod
#pod Specifying any C<metainfo_provider> or C<metainfo_providers> option (even with empty value) cancels
#pod all the default metainfo providers:
#pod
#pod     metainfo_provider =     ; Cancel default metainfo providers.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =option metainfo_providers
#pod
#pod The option allows to specify several source providers in single line:
#pod
#pod     metainfo_providers = MetaYAML MetaJSON Manifest
#pod
#pod The option splits its value to separate plugin names, using whitespaces as separators. If plugin
#pod names contain spaces, use C<metainfo_provider> option.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =option strict
#pod
#pod Let us consider an example:
#pod
#pod     [Manifest::Write]
#pod         metainfo_provider = MetaYML
#pod
#pod At the first glance it may look ok, but there is a mistake: correct plugin name is C<MetaYAML>, not
#pod C<MetaYML> (assumed the plugin was not explicitly (re)named). Left unnoticed, such a typo may cause
#pod bad manifest: files may have incorrect "deed" classification.
#pod
#pod To avoid such mistakes C<Manifest::Write> checks plugin names specified in C<source_provider> and
#pod C<metainfo_provider> options. Any name specified in these options must be a name of C<Dist::Zilla>
#pod plugin consumed C<FileInjector> role (or C<FileGatherer>, which is a kind of C<FileInjector>). If
#pod not, C<Manifest::Write> issues error message and aborts build process.
#pod
#pod This behaviour may be modified by C<strict> option, which sets the level of strictness. Level 1
#pod behaviour is described above (strict checks, any mistake is fatal), this is default. At level -1
#pod C<Manifest::Write> does not check provider names at all. At level 0 some mistakes are fatal, some
#pod are not. Using a plugin which does not do C<FileInjector> role is fatal error. Using a string which
#pod is not a (loaded) plugin name is not fatal (because it I<may be> a name proper plugin which is not
#pod loaded, e. g. commented out):
#pod
#pod     ; [MetaYAML]
#pod     [Manifest::Write]
#pod         metainfo_provider = MetaYAML
#pod         ;   MetaYAML is a correct name of not loaded plugin,
#pod         ;   but Manifest::Write cannot verify it easily.
#pod         strict = 0
#pod         ;   Print a message but do not abort build.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =option show_mungers
#pod
#pod If set to C<1>, information about file mungers (if any) is included into file annotation. If C<0>,
#pod file mungers is not shown completely. Default value is C<0>. See L</"File Mungers">.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =note Plugin Identification
#pod
#pod Every C<Dist:Zilla> plugin has (at least) two attributes: I<moniker> and I<name>. Both are used for
#pod plugin identification, but these terms are not explained well in C<Dist::Zilla> documentation.
#pod Often plugin moniker equals to the plugin name (and so they are interchangeable), but sometimes
#pod not. The difference is important enough to be explained.
#pod
#pod =over
#pod
#pod =item Plugin moniker
#pod
#pod In order to load plugin, C<Dist::Zilla> should know plugin package. Great majority of plugin
#pod packages start with C<Dist::Zilla::Plugin::> prefix. Using full package names in F<dist.ini> file
#pod looks ugly:
#pod
#pod     [Dist::Zilla::Plugin::GatherDir]
#pod     [Dist::Zilla::Plugin::PruneCruft]
#pod     [Dist::Zilla::Plugin::Manifest]
#pod     [Dist::Zilla::Plugin::MetaYAML]
#pod     [Dist::Zilla::Plugin::MetaJSON]
#pod
#pod So C<Dist::Zilla> uses plugin I<monikers> instead of plugin package names. Moniker is a plugin
#pod package name with the common prefix stripped down:
#pod
#pod     [GatherDir]
#pod     [PruneCruft]
#pod     [Manifest]
#pod     [MetaYAML]
#pod     [MetaJSON]
#pod
#pod C<Dist::Zilla> prepends a plugin moniker with the common prefix to get plugin package name.
#pod
#pod In rare cases when plugin package does not start with the common prefix, plugin moniker must start
#pod with C<=> to let C<Dist::Zilla> know the common prefix should not be used:
#pod
#pod     [=MyPrivatePlugin]
#pod
#pod C<Dist::Zilla> drops equal sign and uses the rest as package name.
#pod
#pod Since moniker is a part of package name, it cannot include characters not valid for package names
#pod (equal sign in the first position is an exception).
#pod
#pod =item Plugin name
#pod
#pod Someone may want to use the same plugin more than once. To differentiate plugins with the same
#pod moniker, C<Dist::Zilla> introduces plugin I<names>. Name is unique string that identifies plugin in
#pod F<dist.ini>. Plugin name is specified in F<dist.ini> after plugin moniker and separated from
#pod the moniker by slash:
#pod
#pod     [GenerateFile/Copying]
#pod         filename = COPYING
#pod         content  = ...
#pod     [GenerateFile/ReadMe]
#pod         filename = README
#pod         content  = ...
#pod
#pod If plugin name is not specified explicitly, the plugin gets automatically assigned name, which is
#pod the same as the plugin moniker:
#pod
#pod     [Manifest]  ; plugin named "Manifest"
#pod
#pod Actually, it is just short form of
#pod
#pod     [Manifest/Manifest]  ; plugin named "Manifest"
#pod
#pod All the plugins in F<dist.ini> must have I<unique> names.
#pod
#pod Since name is just a string, it may include arbitrary characters, probably with few exceptions like
#pod square brackets and newlines.
#pod
#pod =back
#pod
#pod Thus, a plugin I<name> is a string identifier assigned to the plugin by distribution author. Plugin
#pod names are unique within F<dist.ini>, but they are also "local" within F<dist.ini> because nobody
#pod except the distribution author takes care about plugin names used in the F<dist.ini>. (F<dist.ini>
#pod file may even be excluded from distribution.)
#pod
#pod In contrast, a plugin I<moniker> is (part of) the plugin package name, and so "assigned" by plugin
#pod author. If plugin is published on CPAN (which is quite common), plugin moniker becomes a "global"
#pod entity.
#pod
#pod So, in F<dist.ini> file, C<source_provider> and C<metainfo_provider> options accept plugin names
#pod because names unambiguously identify plugins in F<dist.ini>. However, in manifest file, plugin
#pod monikers are used because plugin names have little or no meaning for distribution users, while
#pod plugin monikers are still valuable.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =note File Mungers
#pod
#pod C<Dist::Zilla> records each file operation (adding, content modification, etc) in a history log
#pod attached to every file (see C<added_by> attribute declared in C<Dist::Zilla::Role::File>).
#pod
#pod File adder is recorded properly.
#pod
#pod Unfortunately, (in C<Dist::Zilla> 5.039) subsequent file modifications are recorded not too
#pod accurate: C<Dist::Zilla> I<guesses> the plugin that changed the file. When guessing, it uses
#pod heuristic which works correctly only in trivial cases. In non-trivial cases recorded information is
#pod not fully correct (this is a soft form to say "incorrect"). "Non-trivial case" does not mean
#pod something overcomplicated: consuming a role or extending a class are non-trivial cases. So, file
#pod history log may have records that file was modified by a role (actually the file was modified by
#pod the plugin consumed the role) or a plugin's parent class (actual modifier was the plugin itself).
#pod
#pod Thus, all but the first records in file history log are unreliable.
#pod
#pod C<Manifest::Write> uses file history logs to generate file annotations. So file annotations in
#pod manifest are inaccurate too. A file adder is quite reliable, but file mungers are not.
#pod
#pod This is reason why C<show_mungers> option is set to C<0> by default.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =note Excluding Files
#pod
#pod =head3 Rationale
#pod
#pod Excluding files from the distribution archive looks like pruning, but there is a big difference.
#pod Pruned files are excluded from C<Dist::Zilla> attention before build (and so, such files are not
#pod built), while C<exclude_files> option excludes files from the distribution tarball. Excluded files
#pod are built anyway, but not included into the archive. What is the reason for such strange action?
#pod
#pod Many distributions built by C<Dist::Zilla> have number of author and/or release tests, collectively
#pod called "extra tests". Most of these tests are not written by the distribution author but generated
#pod by various C<Dist::Zilla> plugins. These generated tests should be built (in order to run them
#pod before making a release) and all these tests are included into the distribution archive (just
#pod because C<Dist::Zilla> packs all built files).
#pod
#pod But extra tests have little sense for distribution users. By their nature extra tests are intended
#pod to be run either by the distribution author (author tests) or the releaser (release tests); neither
#pod C<cpan> nor C<cpanp> nor C<cpanm> run extra tests before installing a distribution.
#pod
#pod Thus, extra test should be built, but there is no point to include them into the distribution. As
#pod far as I know C<Dist::Zilla> does not have "official" way to do it. C<Manifest::Write> fulfills
#pod this lack.
#pod
#pod =head3 Why C<Manifest::Write>?
#pod
#pod Ok, excluding extra tests from the distribution archive seems to be a good idea, but why
#pod C<Manifets::Write> does it? C<Manifest::Write>'s job is writing the manifest, excluding files from
#pod the archive looks like a task for a dedicated plugin, doesn't it?
#pod
#pod Yes, it does. Writing such a plugin would be a trivial work. However, there is a problem. Such a
#pod plugin would work just before creating the archive, when all the files (including the F<MANIFEST>)
#pod are built already, so excluding files from the archive makes the F<MANIFEST> incorrect. (I thought
#pod out few ways to workaround the problem, but not a good one.)
#pod
#pod Wait a moment. Let us treat the manifest not as "the list of I<packed> files" but as "the list of
#pod files I<to> pack". Excluding a file from the manifest automatically causes disappearing the file
#pod from the distribution archive. It sounds logical, doesn't it?
#pod
#pod Thus, C<Manifest::Write>'s C<exclude_file> option excludes the files from the manifest, and
#pod disappearing the files from the distribution archive is just a (desirable) side effect.
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =head1 SEE ALSO
#pod
#pod =for :list
#pod = L<Dist::Zilla>
#pod = L<Dist::Zilla::Plugin::Manifest>
#pod = L<Dist::Zilla::Role::FileInjector>
#pod = L<Dist::Zilla::Role::FileGatherer>
#pod = L<Dist::Zilla::Role::FilePruner>
#pod = L<ExtUtils::Manifest/"MANIFEST.SKIP">
#pod = L<Dist::Zilla::Plugin::Manifest::Write>
#pod
#pod =for comment ---------------------------------------------------------------------------------------
#pod
#pod =head1 COPYRIGHT AND LICENSE
#pod
#pod Copyright (C) 2015, 2016 Van de Bugger
#pod
#pod License GPLv3+: The GNU General Public License version 3 or later
#pod <http://www.gnu.org/licenses/gpl-3.0.txt>.
#pod
#pod This is free software: you are free to change and redistribute it. There is
#pod NO WARRANTY, to the extent permitted by law.
#pod
#pod
#pod =cut

#   ------------------------------------------------------------------------------------------------
#
#   file: doc/what.pod
#
#   This file is part of perl-Dist-Zilla-Plugin-Manifest-Write.
#
#   ------------------------------------------------------------------------------------------------

#pod =encoding UTF-8
#pod
#pod =head1 WHAT?
#pod
#pod C<Dist-Zilla-Plugin-Manifest-Write> (or C<Manifest::Write> for brevity) is a plugin for C<Dist::Zilla>, a replacement
#pod for standard plugin C<Manifest>. C<Manifest::Write> writes I<annotated> distribution manifest: each
#pod filename is followed by a comment explaining origin of the file: if it is a part of software, meta
#pod information, or 3rd-party file. Also it can B<I<exclude> built files from distribution>, e. g.
#pod extra tests have to be built (to run) but need not be distributed.
#pod
#pod =cut

# end of file #
#   ------------------------------------------------------------------------------------------------
#
#   file: doc/why.pod
#
#   This file is part of perl-Dist-Zilla-Plugin-Manifest-Write.
#
#   ------------------------------------------------------------------------------------------------

#pod =encoding UTF-8
#pod
#pod =head1 WHY?
#pod
#pod F<MANIFEST> is a metainfo file, a part of every distribution. It is a plain list of files included
#pod into the distribution. Typical F<MANIFEST> looks like:
#pod
#pod
#pod     Build.PL
#pod     COPYING
#pod     Changes
#pod     MANIFEST
#pod     META.yml
#pod     README
#pod     dist.ini
#pod     lib/Dummy.pm
#pod     t/00-compile.t
#pod
#pod
#pod Format of manifest allows comments, but comments are rarely used.
#pod
#pod As it noted before, manifest is a plain list of files. However, files included into a distribution
#pod differ:
#pod
#pod =over
#pod
#pod =item 1.
#pod
#pod Some files are created by software author (in the example above, F<lib/Dummy.pm> I<could> be such
#pod file). Some of these files may be processed by various filters (like C<PkgVersion> or
#pod C<PodWeaver>).
#pod
#pod =item 2.
#pod
#pod Some files contain distribution meta information (F<META.yml> and F<MANIFEST> itself).
#pod
#pod =item 3.
#pod
#pod Some files may be generated by a tool from third party templates (C<Dist-Zilla> and its plugins can
#pod generate a lot of various files, in the example above all the tests I<could> be generated, as well
#pod as F<Build.PL>, F<COPYING>, F<Changes>, and F<README>).
#pod
#pod =back
#pod
#pod Sometimes you may want (or have) to trace origin of files: whether this or that file was created by
#pod author or automatically generated, if the file was processed or added as-is. With a standard
#pod manifest (built by C<Manifest> plugin) you have to I<guess> this or study the distribution build
#pod process: look into F<dist.ini> file, used plugins and plugin bundles. In contrast to standard
#pod C<Manifest> plugin, C<Manifest::Write> writes I<annotated> manifest:
#pod
#pod     # This file was generated with Dist::Zilla::Plugin::Manifest::Write v0.9.6.
#pod     Build.PL       # 3rd party file built by ModuleBuildTiny
#pod     COPYING        #     Dummy file added by GatherDir
#pod     Changes        #     Dummy file added by GatherDir
#pod     MANIFEST       #  metainfo file built by Manifest::Write
#pod     META.yml       #  metainfo file built by MetaYAML
#pod     README         #     Dummy file added by GatherDir
#pod     dist.ini       #     Dummy file added by GatherDir
#pod     lib/Dummy.pm   #     Dummy file added by GatherDir
#pod     t/00-compile.t # 3rd party file built by Test::Compile
#pod
#pod
#pod (In the example above "Dummy" is name of manifested distribution.)
#pod
#pod Having such annotated manifest there is no need to I<guess> origin of files. (However, see L<File
#pod Mungers|Dist::Zilla::Plugin::Manifest::Write::Manual/"File Mungers">.)
#pod
#pod =cut

# end of file #


# end of file #

__END__

=pod

=encoding UTF-8

=head1 NAME

Dist::Zilla::Plugin::Manifest::Write::Manual - C<Manifest::Write> plugin user manual

=head1 VERSION

Version v0.9.7, released on 2016-12-14 22:51 UTC.

=head1 WHAT?

C<Dist-Zilla-Plugin-Manifest-Write> (or C<Manifest::Write> for brevity) is a plugin for C<Dist::Zilla>, a replacement
for standard plugin C<Manifest>. C<Manifest::Write> writes I<annotated> distribution manifest: each
filename is followed by a comment explaining origin of the file: if it is a part of software, meta
information, or 3rd-party file. Also it can B<I<exclude> built files from distribution>, e. g.
extra tests have to be built (to run) but need not be distributed.

This is C<Manifest::Write> plugin user manual. Read this if you want to
have annotated distribution manifest.

If you are going to hack or extend C<Manifest::Write>, read the L<module
documentation|Dist::Zilla::Plugin::Manifest::Write>. General topics like getting source, building, installing, bug
reporting and some others are covered in the F<README>.

=for test_synopsis BEGIN { die "SKIP: Not Perl code.\n" };

=head1 SYNOPSIS

In your F<dist.ini>:

    ...
    [GatherDir]         ; Plugin which adds source files to distribution.
                        ; You may use other plugins, like GatherFromManifest
                        ; or Manifest::Read.
    [Manifest::Write]
        source_provider = GatherDir
        exclude_files   = :ExtraTestFiles
    ...

=head1 DESCRIPTION

C<Manifest::Write> is a replacement for standard plugin C<Manifest>. To use C<Manifest::Write>, you
should replace line

    [Manifest]

with

    [Manifest::Write]

in your F<dist.ini> file, and specify one or more source providers, e. g.:

    [Manifest::Write]
        source_provider = GatherDir

(See C<source_provider> option below for details.)

=head2 Manifest File

Manifest file enlists files which should be included into the distribution. Usually manifest file
itself is also included into the distribution.

The name of manifest file written by the C<Manifest::Write> is specified by C<manifest> option.
Default value is F<MANIFEST>, a conventional name for the manifest file.

=head2 Manifest File Format

Manifest file generated by C<Manifest::Write> follows the format defined in
L<ExtUtils::Manifest/"MANIFEST">. However, I<comments> generated by the C<Manifest::Write> have
internal structure, see below.

If the first non-whitespace character of a line is hash character (C<#>), such line is a comment.

Other lines in annotated manifest follows the format:

    NAME # DEED file BREED by ADDER [ and munged by MUNGER,… ]

Square brackets denote optional part, ellipsis denotes repeatable part, hash (C<#>), C<file>,
C<by>, C<and munged by> are literals.

=over

=item I<NAME>

Just a file name. If file name contains spaces, apostrophes (C<'>), backslashes (C<\>), or hashes
(C<#>) it is formatted as Perl single-quoted string literal, otherwise it is written as-is.

=item C<#>

Technically, hash character is not required because everything after a file name is a comment, hash
just visually emphasises it.

=item I<DEED>

File "deed" is file ownership: if the file (1) belongs to the project, is (2) meta information, or
(3) third-party file. In the first case "deed" is project (distribution) name, in the second —
C<metainfo>, in the third — C<3rd party>. (So, do not name your project "metainfo" to avoid
confusion.)

=item I<BREED>

File "breed" explains how the file appeared in the distribution — was it C<added> (copied as-is
from the project sources) or C<built> (generated).

=item I<ADDER>

File "adder" is a I<moniker> of plugin (see L</"Plugin moniker">) brought (either C<added> or
C<built>, see L</"BREED">) the file into the distribution.

Plugins bringing files to distribution do C<FileInjector> or C<FileGatherer> roles. Some plugins
add existing files to distribution (e. g. C<GatherDir>, C<Manifest::Read>), others generate new
files (e. g. C<Test::EOL>, C<Test::NoTabs>).

=item I<MUNGER>

File "munger" is a plugin changed the file during build.

Plugins modifying files in distribution do C<FileMunger> role. Some plugins may touch files
slightly (for example, C<PkgVersion> changes a single line in Perl modules), others may rewrite
them heavily (C<PodWeaver> removes or comments out all existing POD and generates new POD at the
end).

The same file may be changed several times during build. For example, Perl module may be processed
by both C<PkgVersion> and C<PodWeaver>.

Quite often the same plugin appears as both adder and munger. Many plugins add a generic template
to the distribution first, then tune the template to meet the distribution needs.

If a file was not changed after its addition to the distribution, annotation will not show any
mungers for this file, obviously. Also, all munger may be forcibly hidden by C<show_mungers>
option.

=back

=head2 Skip File

Skip file defines files which should I<not> be included into distribution. See
L<ExtUtils::Manifest/"MANIFEST.SKIP"> for more details.

C<Manifest::Write> generates skip file. Skip file name is set by C<manifest_skip> option. Default
name is F<MANIFEST.SKIP>. Empty name disables generating skip file.

Skip file generated by the C<Manifest::Write> consists of list of excluded files (see
L</exclude_files>) and copy of content of F<MANIFEST.SKIP> file from currently installed
C<ExtUtils::Manifest> distribution (content is copied at the distribution build time). "#!include"
and "#!include_default" are not used (because they are not recognized by C<Module::Manifest>).

Skip file could be necessary to let C<Test::DistManifest> pass — the tests checks the every file is
either listed in F<MANIFEST> or skipped.

=head1 OPTIONS

=head2 exclude_files

This option excludes files from the manifest (and from the distribution archive).

Option value should be a name of file finder. Default value is C<:NoFiles> (i. e. no files are
excluded, all the built files are packed to the distribution archive).

This is a multi-value option, i. e. it could be specified several times. Files found by any of the
specified finders are excluded from the distribution archive.

    [Manifest::Write]
        exclude_files = :ExtraTestFiles

See also L</"Excluding Files">.

=head2 manifest

Name of manifest file to write. Default value is F<MANIFEST>. It is unlikely you will need to
change the default value.

It could be used, though, to generate both standard and annotated manifests (for testing,
comparison, etc):

    [Manifest]          ; Writes 'MANIFEST'.
    [Manifest::Write]   ; Writes 'Manifest.annotated'.
        manifest = Manifest.annotated

=head2 manifest_skip

Name of skip file to write. Default value is F<MANIFEST.SKIP>. It is unlikely you will need to
change the default value. However, empty value disables generating F<MANIFEST.SKIP>:

    [Manifest::Write]
        manifest_skip = ; Disable writing 'MANIFEST.SKIP'.

=head2 source_provider

This is a multi-value option, i. e. option may be specified several times. Every option value is a
name of plugin (see L</"Plugin name">) which adds I<source files> to distribution.

    source_provider = GatherDir
    source_provider = GatherDir::Template
    source_provider = GenerateFile

There are no default source file providers. You will likely want to specify C<GatherDir>,
C<GatherFromManifest> and similar plugins as source providers.

Note: I<source files> term does I<not> mean exactly Perl sources. Source files are I<your> files
(usually hand-crafted), in contrast to metainfo and 3rd party files generated by various
C<Dist::Zilla> plugins. Sources may include Perl modules, scripts, POD files, tests, and any other
files composing your software.

=head2 source_providers

The option splits its value into plugin names using whitespaces as separators, so

    source_providers = GatherDir GatherDir::Template GenerateFile

is just a shortcut for

    source_provider = GatherDir
    source_provider = GatherDir::Template
    source_provider = GenerateFile

=head2 metainfo_provider

This is multi-value option too. Every value is a name of plugin (see L</"Plugin name">) which adds
I<meta information files> to the distribution:

    metainfo_provider = MetaYAML
    metainfo_provider = MetaJSON
    metainfo_provider = Manifest

Default meta info providers are C<CPANFile>, C<Manifest>, C<MetaYAML>, C<MetaJSON>, and the
C<Manifest::Write> plugin itself. It seems these metainfo providers should satisfy most of the
users.

Specifying any C<metainfo_provider> or C<metainfo_providers> option (even with empty value) cancels
all the default metainfo providers:

    metainfo_provider =     ; Cancel default metainfo providers.

=head2 metainfo_providers

The option allows to specify several source providers in single line:

    metainfo_providers = MetaYAML MetaJSON Manifest

The option splits its value to separate plugin names, using whitespaces as separators. If plugin
names contain spaces, use C<metainfo_provider> option.

=head2 strict

Let us consider an example:

    [Manifest::Write]
        metainfo_provider = MetaYML

At the first glance it may look ok, but there is a mistake: correct plugin name is C<MetaYAML>, not
C<MetaYML> (assumed the plugin was not explicitly (re)named). Left unnoticed, such a typo may cause
bad manifest: files may have incorrect "deed" classification.

To avoid such mistakes C<Manifest::Write> checks plugin names specified in C<source_provider> and
C<metainfo_provider> options. Any name specified in these options must be a name of C<Dist::Zilla>
plugin consumed C<FileInjector> role (or C<FileGatherer>, which is a kind of C<FileInjector>). If
not, C<Manifest::Write> issues error message and aborts build process.

This behaviour may be modified by C<strict> option, which sets the level of strictness. Level 1
behaviour is described above (strict checks, any mistake is fatal), this is default. At level -1
C<Manifest::Write> does not check provider names at all. At level 0 some mistakes are fatal, some
are not. Using a plugin which does not do C<FileInjector> role is fatal error. Using a string which
is not a (loaded) plugin name is not fatal (because it I<may be> a name proper plugin which is not
loaded, e. g. commented out):

    ; [MetaYAML]
    [Manifest::Write]
        metainfo_provider = MetaYAML
        ;   MetaYAML is a correct name of not loaded plugin,
        ;   but Manifest::Write cannot verify it easily.
        strict = 0
        ;   Print a message but do not abort build.

=head2 show_mungers

If set to C<1>, information about file mungers (if any) is included into file annotation. If C<0>,
file mungers is not shown completely. Default value is C<0>. See L</"File Mungers">.

=head1 NOTES

=head2 Plugin Identification

Every C<Dist:Zilla> plugin has (at least) two attributes: I<moniker> and I<name>. Both are used for
plugin identification, but these terms are not explained well in C<Dist::Zilla> documentation.
Often plugin moniker equals to the plugin name (and so they are interchangeable), but sometimes
not. The difference is important enough to be explained.

=over

=item Plugin moniker

In order to load plugin, C<Dist::Zilla> should know plugin package. Great majority of plugin
packages start with C<Dist::Zilla::Plugin::> prefix. Using full package names in F<dist.ini> file
looks ugly:

    [Dist::Zilla::Plugin::GatherDir]
    [Dist::Zilla::Plugin::PruneCruft]
    [Dist::Zilla::Plugin::Manifest]
    [Dist::Zilla::Plugin::MetaYAML]
    [Dist::Zilla::Plugin::MetaJSON]

So C<Dist::Zilla> uses plugin I<monikers> instead of plugin package names. Moniker is a plugin
package name with the common prefix stripped down:

    [GatherDir]
    [PruneCruft]
    [Manifest]
    [MetaYAML]
    [MetaJSON]

C<Dist::Zilla> prepends a plugin moniker with the common prefix to get plugin package name.

In rare cases when plugin package does not start with the common prefix, plugin moniker must start
with C<=> to let C<Dist::Zilla> know the common prefix should not be used:

    [=MyPrivatePlugin]

C<Dist::Zilla> drops equal sign and uses the rest as package name.

Since moniker is a part of package name, it cannot include characters not valid for package names
(equal sign in the first position is an exception).

=item Plugin name

Someone may want to use the same plugin more than once. To differentiate plugins with the same
moniker, C<Dist::Zilla> introduces plugin I<names>. Name is unique string that identifies plugin in
F<dist.ini>. Plugin name is specified in F<dist.ini> after plugin moniker and separated from
the moniker by slash:

    [GenerateFile/Copying]
        filename = COPYING
        content  = ...
    [GenerateFile/ReadMe]
        filename = README
        content  = ...

If plugin name is not specified explicitly, the plugin gets automatically assigned name, which is
the same as the plugin moniker:

    [Manifest]  ; plugin named "Manifest"

Actually, it is just short form of

    [Manifest/Manifest]  ; plugin named "Manifest"

All the plugins in F<dist.ini> must have I<unique> names.

Since name is just a string, it may include arbitrary characters, probably with few exceptions like
square brackets and newlines.

=back

Thus, a plugin I<name> is a string identifier assigned to the plugin by distribution author. Plugin
names are unique within F<dist.ini>, but they are also "local" within F<dist.ini> because nobody
except the distribution author takes care about plugin names used in the F<dist.ini>. (F<dist.ini>
file may even be excluded from distribution.)

In contrast, a plugin I<moniker> is (part of) the plugin package name, and so "assigned" by plugin
author. If plugin is published on CPAN (which is quite common), plugin moniker becomes a "global"
entity.

So, in F<dist.ini> file, C<source_provider> and C<metainfo_provider> options accept plugin names
because names unambiguously identify plugins in F<dist.ini>. However, in manifest file, plugin
monikers are used because plugin names have little or no meaning for distribution users, while
plugin monikers are still valuable.

=head2 File Mungers

C<Dist::Zilla> records each file operation (adding, content modification, etc) in a history log
attached to every file (see C<added_by> attribute declared in C<Dist::Zilla::Role::File>).

File adder is recorded properly.

Unfortunately, (in C<Dist::Zilla> 5.039) subsequent file modifications are recorded not too
accurate: C<Dist::Zilla> I<guesses> the plugin that changed the file. When guessing, it uses
heuristic which works correctly only in trivial cases. In non-trivial cases recorded information is
not fully correct (this is a soft form to say "incorrect"). "Non-trivial case" does not mean
something overcomplicated: consuming a role or extending a class are non-trivial cases. So, file
history log may have records that file was modified by a role (actually the file was modified by
the plugin consumed the role) or a plugin's parent class (actual modifier was the plugin itself).

Thus, all but the first records in file history log are unreliable.

C<Manifest::Write> uses file history logs to generate file annotations. So file annotations in
manifest are inaccurate too. A file adder is quite reliable, but file mungers are not.

This is reason why C<show_mungers> option is set to C<0> by default.

=head2 Excluding Files

=head3 Rationale

Excluding files from the distribution archive looks like pruning, but there is a big difference.
Pruned files are excluded from C<Dist::Zilla> attention before build (and so, such files are not
built), while C<exclude_files> option excludes files from the distribution tarball. Excluded files
are built anyway, but not included into the archive. What is the reason for such strange action?

Many distributions built by C<Dist::Zilla> have number of author and/or release tests, collectively
called "extra tests". Most of these tests are not written by the distribution author but generated
by various C<Dist::Zilla> plugins. These generated tests should be built (in order to run them
before making a release) and all these tests are included into the distribution archive (just
because C<Dist::Zilla> packs all built files).

But extra tests have little sense for distribution users. By their nature extra tests are intended
to be run either by the distribution author (author tests) or the releaser (release tests); neither
C<cpan> nor C<cpanp> nor C<cpanm> run extra tests before installing a distribution.

Thus, extra test should be built, but there is no point to include them into the distribution. As
far as I know C<Dist::Zilla> does not have "official" way to do it. C<Manifest::Write> fulfills
this lack.

=head3 Why C<Manifest::Write>?

Ok, excluding extra tests from the distribution archive seems to be a good idea, but why
C<Manifets::Write> does it? C<Manifest::Write>'s job is writing the manifest, excluding files from
the archive looks like a task for a dedicated plugin, doesn't it?

Yes, it does. Writing such a plugin would be a trivial work. However, there is a problem. Such a
plugin would work just before creating the archive, when all the files (including the F<MANIFEST>)
are built already, so excluding files from the archive makes the F<MANIFEST> incorrect. (I thought
out few ways to workaround the problem, but not a good one.)

Wait a moment. Let us treat the manifest not as "the list of I<packed> files" but as "the list of
files I<to> pack". Excluding a file from the manifest automatically causes disappearing the file
from the distribution archive. It sounds logical, doesn't it?

Thus, C<Manifest::Write>'s C<exclude_file> option excludes the files from the manifest, and
disappearing the files from the distribution archive is just a (desirable) side effect.

=head1 WHY?

F<MANIFEST> is a metainfo file, a part of every distribution. It is a plain list of files included
into the distribution. Typical F<MANIFEST> looks like:

    Build.PL
    COPYING
    Changes
    MANIFEST
    META.yml
    README
    dist.ini
    lib/Dummy.pm
    t/00-compile.t

Format of manifest allows comments, but comments are rarely used.

As it noted before, manifest is a plain list of files. However, files included into a distribution
differ:

=over

=item 1.

Some files are created by software author (in the example above, F<lib/Dummy.pm> I<could> be such
file). Some of these files may be processed by various filters (like C<PkgVersion> or
C<PodWeaver>).

=item 2.

Some files contain distribution meta information (F<META.yml> and F<MANIFEST> itself).

=item 3.

Some files may be generated by a tool from third party templates (C<Dist-Zilla> and its plugins can
generate a lot of various files, in the example above all the tests I<could> be generated, as well
as F<Build.PL>, F<COPYING>, F<Changes>, and F<README>).

=back

Sometimes you may want (or have) to trace origin of files: whether this or that file was created by
author or automatically generated, if the file was processed or added as-is. With a standard
manifest (built by C<Manifest> plugin) you have to I<guess> this or study the distribution build
process: look into F<dist.ini> file, used plugins and plugin bundles. In contrast to standard
C<Manifest> plugin, C<Manifest::Write> writes I<annotated> manifest:

    # This file was generated with Dist::Zilla::Plugin::Manifest::Write v0.9.6.
    Build.PL       # 3rd party file built by ModuleBuildTiny
    COPYING        #     Dummy file added by GatherDir
    Changes        #     Dummy file added by GatherDir
    MANIFEST       #  metainfo file built by Manifest::Write
    META.yml       #  metainfo file built by MetaYAML
    README         #     Dummy file added by GatherDir
    dist.ini       #     Dummy file added by GatherDir
    lib/Dummy.pm   #     Dummy file added by GatherDir
    t/00-compile.t # 3rd party file built by Test::Compile

(In the example above "Dummy" is name of manifested distribution.)

Having such annotated manifest there is no need to I<guess> origin of files. (However, see L<File
Mungers|Dist::Zilla::Plugin::Manifest::Write::Manual/"File Mungers">.)

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=for comment ---------------------------------------------------------------------------------------

=head1 SEE ALSO

=over 4

=item L<Dist::Zilla>

=item L<Dist::Zilla::Plugin::Manifest>

=item L<Dist::Zilla::Role::FileInjector>

=item L<Dist::Zilla::Role::FileGatherer>

=item L<Dist::Zilla::Role::FilePruner>

=item L<ExtUtils::Manifest/"MANIFEST.SKIP">

=item L<Dist::Zilla::Plugin::Manifest::Write>

=back

=head1 AUTHOR

Van de Bugger <van.de.bugger@gmail.com>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2015, 2016 Van de Bugger

License GPLv3+: The GNU General Public License version 3 or later
<http://www.gnu.org/licenses/gpl-3.0.txt>.

This is free software: you are free to change and redistribute it. There is
NO WARRANTY, to the extent permitted by law.

=cut
