NAME
Dist::Zilla::Plugin::Manifest::Write::Manual - Manifest::Write
plugin user manual
VERSION
Version v0.9.7, released on 2016-12-14 22:51 UTC.
WHAT?
Dist-Zilla-Plugin-Manifest-Write
(or Manifest::Write
for brevity) is a plugin for Dist::Zilla
, a replacement for standard plugin Manifest
. Manifest::Write
writes 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 exclude built files from distribution, e. g. extra tests have to be built (to run) but need not be distributed.
This is Manifest::Write
plugin user manual. Read this if you want to have annotated distribution manifest.
If you are going to hack or extend Manifest::Write
, read the module documentation. General topics like getting source, building, installing, bug reporting and some others are covered in the README.
SYNOPSIS
In your 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
...
DESCRIPTION
Manifest::Write
is a replacement for standard plugin Manifest
. To use Manifest::Write
, you should replace line
[Manifest]
with
[Manifest::Write]
in your dist.ini file, and specify one or more source providers, e. g.:
[Manifest::Write]
source_provider = GatherDir
(See source_provider
option below for details.)
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 Manifest::Write
is specified by manifest
option. Default value is MANIFEST, a conventional name for the manifest file.
Manifest File Format
Manifest file generated by Manifest::Write
follows the format defined in "MANIFEST" in ExtUtils::Manifest. However, comments generated by the Manifest::Write
have internal structure, see below.
If the first non-whitespace character of a line is hash character (#
), 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 (#
), file
, by
, and munged by
are literals.
- NAME
-
Just a file name. If file name contains spaces, apostrophes (
'
), backslashes (\
), or hashes (#
) it is formatted as Perl single-quoted string literal, otherwise it is written as-is. #
-
Technically, hash character is not required because everything after a file name is a comment, hash just visually emphasises it.
- 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 —
metainfo
, in the third —3rd party
. (So, do not name your project "metainfo" to avoid confusion.) - BREED
-
File "breed" explains how the file appeared in the distribution — was it
added
(copied as-is from the project sources) orbuilt
(generated). - ADDER
-
File "adder" is a moniker of plugin (see "Plugin moniker") brought (either
added
orbuilt
, see "BREED") the file into the distribution.Plugins bringing files to distribution do
FileInjector
orFileGatherer
roles. Some plugins add existing files to distribution (e. g.GatherDir
,Manifest::Read
), others generate new files (e. g.Test::EOL
,Test::NoTabs
). - MUNGER
-
File "munger" is a plugin changed the file during build.
Plugins modifying files in distribution do
FileMunger
role. Some plugins may touch files slightly (for example,PkgVersion
changes a single line in Perl modules), others may rewrite them heavily (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
PkgVersion
andPodWeaver
.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
show_mungers
option.
Skip File
Skip file defines files which should not be included into distribution. See "MANIFEST.SKIP" in ExtUtils::Manifest for more details.
Manifest::Write
generates skip file. Skip file name is set by manifest_skip
option. Default name is MANIFEST.SKIP. Empty name disables generating skip file.
Skip file generated by the Manifest::Write
consists of list of excluded files (see "exclude_files") and copy of content of MANIFEST.SKIP file from currently installed ExtUtils::Manifest
distribution (content is copied at the distribution build time). "#!include" and "#!include_default" are not used (because they are not recognized by Module::Manifest
).
Skip file could be necessary to let Test::DistManifest
pass — the tests checks the every file is either listed in MANIFEST or skipped.
OPTIONS
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 :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 "Excluding Files".
manifest
Name of manifest file to write. Default value is 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
manifest_skip
Name of skip file to write. Default value is MANIFEST.SKIP. It is unlikely you will need to change the default value. However, empty value disables generating MANIFEST.SKIP:
[Manifest::Write]
manifest_skip = ; Disable writing 'MANIFEST.SKIP'.
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 "Plugin name") which adds 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 GatherDir
, GatherFromManifest
and similar plugins as source providers.
Note: source files term does not mean exactly Perl sources. Source files are your files (usually hand-crafted), in contrast to metainfo and 3rd party files generated by various Dist::Zilla
plugins. Sources may include Perl modules, scripts, POD files, tests, and any other files composing your software.
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
metainfo_provider
This is multi-value option too. Every value is a name of plugin (see "Plugin name") which adds meta information files to the distribution:
metainfo_provider = MetaYAML
metainfo_provider = MetaJSON
metainfo_provider = Manifest
Default meta info providers are CPANFile
, Manifest
, MetaYAML
, MetaJSON
, and the Manifest::Write
plugin itself. It seems these metainfo providers should satisfy most of the users.
Specifying any metainfo_provider
or metainfo_providers
option (even with empty value) cancels all the default metainfo providers:
metainfo_provider = ; Cancel default metainfo providers.
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 metainfo_provider
option.
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 MetaYAML
, not 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 Manifest::Write
checks plugin names specified in source_provider
and metainfo_provider
options. Any name specified in these options must be a name of Dist::Zilla
plugin consumed FileInjector
role (or FileGatherer
, which is a kind of FileInjector
). If not, Manifest::Write
issues error message and aborts build process.
This behaviour may be modified by 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 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 FileInjector
role is fatal error. Using a string which is not a (loaded) plugin name is not fatal (because it 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.
show_mungers
If set to 1
, information about file mungers (if any) is included into file annotation. If 0
, file mungers is not shown completely. Default value is 0
. See "File Mungers".
NOTES
Plugin Identification
Every Dist:Zilla
plugin has (at least) two attributes: moniker and name. Both are used for plugin identification, but these terms are not explained well in 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.
- Plugin moniker
-
In order to load plugin,
Dist::Zilla
should know plugin package. Great majority of plugin packages start withDist::Zilla::Plugin::
prefix. Using full package names in 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
Dist::Zilla
uses plugin monikers instead of plugin package names. Moniker is a plugin package name with the common prefix stripped down:[GatherDir] [PruneCruft] [Manifest] [MetaYAML] [MetaJSON]
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
=
to letDist::Zilla
know the common prefix should not be used:[=MyPrivatePlugin]
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).
- Plugin name
-
Someone may want to use the same plugin more than once. To differentiate plugins with the same moniker,
Dist::Zilla
introduces plugin names. Name is unique string that identifies plugin in dist.ini. Plugin name is specified in 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 dist.ini must have unique names.
Since name is just a string, it may include arbitrary characters, probably with few exceptions like square brackets and newlines.
Thus, a plugin name is a string identifier assigned to the plugin by distribution author. Plugin names are unique within dist.ini, but they are also "local" within dist.ini because nobody except the distribution author takes care about plugin names used in the dist.ini. (dist.ini file may even be excluded from distribution.)
In contrast, a plugin 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 dist.ini file, source_provider
and metainfo_provider
options accept plugin names because names unambiguously identify plugins in 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.
File Mungers
Dist::Zilla
records each file operation (adding, content modification, etc) in a history log attached to every file (see added_by
attribute declared in Dist::Zilla::Role::File
).
File adder is recorded properly.
Unfortunately, (in Dist::Zilla
5.039) subsequent file modifications are recorded not too accurate: Dist::Zilla
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.
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 show_mungers
option is set to 0
by default.
Excluding Files
Rationale
Excluding files from the distribution archive looks like pruning, but there is a big difference. Pruned files are excluded from Dist::Zilla
attention before build (and so, such files are not built), while 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 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 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 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 cpan
nor cpanp
nor 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 Dist::Zilla
does not have "official" way to do it. Manifest::Write
fulfills this lack.
Why Manifest::Write
?
Ok, excluding extra tests from the distribution archive seems to be a good idea, but why Manifets::Write
does it? 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 MANIFEST) are built already, so excluding files from the archive makes the 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 packed files" but as "the list of files to pack". Excluding a file from the manifest automatically causes disappearing the file from the distribution archive. It sounds logical, doesn't it?
Thus, Manifest::Write
's exclude_file
option excludes the files from the manifest, and disappearing the files from the distribution archive is just a (desirable) side effect.
WHY?
MANIFEST is a metainfo file, a part of every distribution. It is a plain list of files included into the distribution. Typical 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:
Some files are created by software author (in the example above, lib/Dummy.pm could be such file). Some of these files may be processed by various filters (like
PkgVersion
orPodWeaver
).Some files contain distribution meta information (META.yml and MANIFEST itself).
Some files may be generated by a tool from third party templates (
Dist-Zilla
and its plugins can generate a lot of various files, in the example above all the tests could be generated, as well as Build.PL, COPYING, Changes, and README).
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 Manifest
plugin) you have to guess this or study the distribution build process: look into dist.ini file, used plugins and plugin bundles. In contrast to standard Manifest
plugin, Manifest::Write
writes 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 guess origin of files. (However, see File Mungers.)
SEE ALSO
- Dist::Zilla
- Dist::Zilla::Plugin::Manifest
- Dist::Zilla::Role::FileInjector
- Dist::Zilla::Role::FileGatherer
- Dist::Zilla::Role::FilePruner
- "MANIFEST.SKIP" in ExtUtils::Manifest
- Dist::Zilla::Plugin::Manifest::Write
AUTHOR
Van de Bugger <van.de.bugger@gmail.com>
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.