#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#
#   file: lib/Dist/Zilla/PluginBundle/Author/VDB.pm


#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


package Dist::Zilla::PluginBundle::Author::VDB;

use Moose;
use namespace::autoclean;
use version 0.77;

# PODNAME: Dist::Zilla::PluginBundle::Author::VDB
# ABSTRACT: VDB's plugin bundle
our $VERSION = '0.002'; # VERSION

with 'Dist::Zilla::Role::PluginBundle::Easy';

use Dist::Zilla::Plugin::Hook 0.005;    # We need Hook::PrereqSource.

has minimum_perl => (
    is          => 'ro',
    isa         => 'Str',
    lazy        => 1,
    default     => sub {
        my ( $self ) = @_;
        return $self->payload->{ minimum_perl } // '5.006';
    },
);

has fake_release => (
    is          => 'ro',
    isa         => 'Bool',
    lazy        => 1,
    default     => sub {
        my ( $self ) = @_;
        return $self->payload->{ fake_release } // $ENV{ FAKE_RELEASE };
    },
);

sub configure {

    my ( $self ) = @_;

    $self->add_plugins(

        [ 'Hook' => 'prologue' => { # DOES NOT WORK.
            'hook' => [
                q| use autodie ':all';                     |,
                q| use IPC::System::Simple qw{ capture };  |,
                q| use Path::Tiny;                         |,
            ],
        } ],

        [ 'Hook::VersionProvider' => {
            'hook' => [
                q| use Path::Tiny;                          |,
                q| path( 'VERSION' )->slurp =~ s{\s+\z}{}r; |,
            ],
        } ],

        [ 'Hook::Init' => 'my vars' => {
            'hook' => [
                q|  package MY {                                                                              |,
                q|      our $name           = $dist->name;                                                    |,
                q|      our $package        = $name =~ s{-}{::}gr;                                            |,
                q|      our $version        = $dist->version;                                                 |,
                q|      our $Abstract       = $dist->abstract;                                                |,
                q|      our $abstract       = lcfirst( $Abstract );                                           |,
                q|      our $author         = $dist->authors->[ -1 ];                                         |,
                q|      our $metacpan       = "https://metacpan.org/release/$name";                           |,
                q|      our $cpan_rt_mailto = "mailto:bug-$name\@rt.cpan.org";                                |,
                q|      our $cpan_rt_browse = "https://rt.cpan.org/Public/Dist/Display.html?Name=$name";      |,
                q|      our $cpan_rt_report = "https://rt.cpan.org/Public/Bug/Report.html?Queue=$name";       |,
                q|      our $repo_type      = "hg";                                                           |,
                q|      our $repo_host      = "fedorapeople.org";                                             |,
                q|      our $repo_url       = "https://vandebugger.$repo_host/hg/perl-$name";                 |,
                q|      our $repo_web       = undef;                                                          |,
                q|      our $repo_clone     = "$repo_type clone $repo_url" .                                  |,
                q|          ( $repo_url =~ m{/\Qperl-$name\E\z} ? '' : " \\\n        perl-$name" );           |,
                q|  };                                                                                        |,
                q| $ENV{ 'TEST_FIX' . 'ME_FORMAT' } = 'perl';                                                 |,
            ],
        } ],

        #
        #   Files to include
        #

        [ 'GatherFromManifest' ],

        #
        #   Generated files
        #

        [ 'Manifest::Write' => {
            'source_providers' => [
                'GatherFromManifest',
                'GenerateFile',
            ],
        } ],

        #
        #   File mungers
        #

        [ 'OurPkgVersion' ],
        [ 'SurgicalPodWeaver' => {
            'replacer' => 'replace_with_comment',
        } ],

        #
        #   Update sources
        #

        [ 'Hook::AfterBuild' => {
            'hook' => [
                q| #   Copy built files back to source directory.          |,
                q| use Path::Tiny;                                         |,
                q| my @files = qw{ COPYING README };   # Files to copy.    |,
                q| my $build = path( $arg->{ build_root } );               |,
                q| my $root  = path( $dist->root );                        |,
                q| for my $file ( @files ) {                               |,
                q|     my $nfile = $build->child( $file );                 |,
                q|     my $ofile = $root->child( $file );                  |,
                q|     my $new = $nfile->slurp;                            |,
                q|     my $old = $ofile->exists ? $ofile->slurp : undef;   |,
                q|     if ( not defined( $old ) or $new ne $old ) {        |,
                q|         $self->log( [ 'Updating %s...', $file ] );      |,
                q|         $ofile->spew( $new );                           |,
                q|     };                                                  |,
                q| };                                                      |,
            ],
        } ],

        #
        #   Tests
        #

        # Files

        [ 'Test::EOL' => {
            'finder' => ':AllFiles',
        } ],

        [ 'Test::NoTabs' => {
            'finder' => ':AllFiles',
        } ],

        [ 'MojibakeTests' ],

        # Code

        [ 'Test::Compile' ],
            #fake_home => 1 ???

        [ 'Test::Version' => {          # All modules have version.
            #~ 'is_strict' => 1,        # Does not work for trial releases.
        } ],

        [ 'Test::NewVersion' ],         # This is not a version already uploaded to CPAN.
        [ 'Test::MinimumVersion' => {
            'max_target_perl' => $self->minimum_perl,
        } ],

        [ 'Test::Fix' . 'me' ],

        [ 'Test::Perl::Critic' => {
            'critic_config' => 'xt/perlcritic.ini',
                #   The test does not check tests. TODO: How to fix?
        } ],

        # POD

        [ 'PodSyntaxTests'   ],     # `Dist-Zilla`-bundled test, uses `Test::pod`.

        [ 'PodCoverageTests' ],     # `Dist-Zilla`-bundled test, uses `Pod::Coverage::TrustPod`.

        [ 'Test::PodSpelling' => {
            'spell_cmd' => 'aspell list -l en -p ./xt/aspell.en.pws',
                #   Leading dot (in `./xt/aspell.en.pws`) is important! Whitout the dot `aspell` fails to
                #   find the dictionary.
        } ],

        [ 'Test::Pod::No404s' ],    # No dead URLs.

        # Metadata

        [ 'MetaTests' ],                # `Dist-Zilla`-bundled test, uses `Test::CPAN::Meta`, checks `META.yml`.

        [ 'Test::CPAN::Meta::JSON' ],   # Uses `Test::CPAN::Meta::JSON`.

        [ 'Test::CPAN::Changes' ],
            #   Does not check that `Changes` has a record for current version, see
            #   <https://github.com/doherty/Dist-Zilla-Plugin-Test-CPAN-Changes/issues/6>.

        [ 'Test::DistManifest' ],

        # Overall

        [ 'Test::Kwalitee' ],

        #
        #   Metainfo
        #

        [ 'MinimumPerl' ],

        [ 'AutoPrereqs' ],
        # [Prereqs::AuthorDeps]

        [ 'Hook::PrereqSource' => {
            'hook' => [
                #   `use autodie ':all';` implicitly requires `IPC::System::Simple` module, but
                #    this dependency is not detected by `AutoPrereqs`. If there is dependency on
                #   `autodie`, let us add dependency on `IPC::System::Simple`.
                q| my $prereqs = $dist->prereqs->as_string_hash;                              |,
                q| for my $phase ( keys( %$prereqs ) ) {                                      |,
                q|     for my $type ( keys( %{ $prereqs->{ $phase } } ) ) {                   |,
                q|         if ( exists( $prereqs->{ $phase }->{ $type }->{ autodie } ) ) {    |,
                q|             $self->log_debug( [ 'phase %s type %s', $phase, $type ] );     |,
                q|             $zilla->register_prereqs(                                      |,
                q|                 { phase => $phase, type => $type },                        |,
                q|                 'IPC::System::Simple' => 0,                                |,
                q|             );                                                             |,
                q|         };                                                                 |,
                q|     };                                                                     |,
                q| };                                                                         |,
            ],
        } ],

        [ 'CheckPrereqsIndexed'   ],    # Make sure all prereqs are published in CPAN.

        [ 'MetaProvides::Package' ],

        [ 'MetaResources::Template' => {
            'delimiters'          => '{ }',
            'homepage'            => '{$MY::metacpan}',
            'license'             => '{$dist->license->url}',
            'repository.type'     => '{$MY::repo_type}',
            'repository.url'      => '{$MY::repo_url}',
            'repository.web'      => '{$MY::repo_web}',
            'bugtracker.mailto'   => '{$MY::cpan_rt_mailto}',
            'bugtracker.web'      => '{$MY::cpan_rt_browse}',
        } ],

        [ 'MetaYAML' ],                 # Generate `META.yml`.

        [ 'MetaJSON' ],                 # Generate `META.json`.

        #
        #   Installer
        #

        [ 'ModuleBuildTiny' ],

        #
        #   Release
        #

        #~ [ 'RunExtraTests' ],          ; Does not work for me, see <https://github.com/dagolden/Dist-Zilla-Plugin-CheckExtraTests/issues/26>.

        [ 'CheckExtraTests' ],          # So use CheckExtraTest meanwhile.
        #~ [CheckChangesHasContent]

        [ 'TestRelease'     ],          # Unpack tarball and run tests.

        [ 'Hook::BeforeRelease' => 'check prereqs' => {
            'hook' => [
                q| #   Make sure the distro does not depend on unwanted modules.                    |,
                q| #   Unwanted module, for example, is `Data::Printer`.                            |,
                q| #   I use it often for debugging purposes and forget to remove debugging code.   |,
                q| my @modules = qw{ DDP Data::Printer };                                           |, # TODO: Parameter
                q| my $prereqs = $dist->distmeta->{ prereqs };                                      |,
                q| for my $module ( @modules ) {                                                    |,
                q|     for my $stage ( qw{ configure develop runtime test } ) {                     |,
                q|         if ( exists( $prereqs->{ $stage }->{ requires }->{ $module } ) ) {       |,
                q|             $self->log_error( [ '%s found in %s prereqs ', $module, $stage ] );  |,
                q|         };                                                                       |,
                q|     };                                                                           |,
                q| };                                                                               |,
                q| $self->abort_if_error();                                                         |,
            ]
        } ],

        [ 'Hook::BeforeRelease' => 'hg stat' => {
            'hook' => [
                q| #   Make sure all the files committed.           |,
                q| use IPC::System::Simple 'capture';               |,
                q| my @stdout = capture( 'hg', 'status' );          |,
                q| if ( @stdout ) {                                 |,
                q|     chomp( @stdout );                            |,
                q|     $self->log_error( 'hg status:' );            |,
                q|     $self->log_error( "    $_" ) for @stdout;    |,
                q|     $self->abort( 'hg status is not clean' );    |,
                q| };                                               |,
            ],
        } ],

        [ 'Hook::BeforeRelease' => 'hg tag' => {
            'hook' => [
                q| #   Make sure there is no such tag yet.                          |,
                q| use Path::Tiny;                                                  |,
                q| if ( path( '.hgtags' )->slurp_utf8 =~ m{ \Q$MY::version\E$}m ) { |,
                q|     $self->abort( [ 'tag %s already exists', $MY::version ] );   |,
                q| };                                                               |,
            ],
        } ],

        [ 'ConfirmRelease' ],       # Ask confirmation before uploading the release.

        [ $self->fake_release ? 'FakeRelease' : 'UploadToCPAN' ],

        [ 'Hook::AfterRelease' => 'hg add tag' => {
            'hook' => [
                q| use IPC::System::Simple 'capture';                                    |,
                q| my @stdout = capture( 'hg', 'id', '--debug' );                        |,
                q| chomp( @stdout );                                                     |,
                q| @stdout == 1 and $stdout[ 0 ] =~ m{^([0-9a-f]{40})(\+?) tip$} or do { |,
                q|     $self->log_error( 'fail to parse "hg id" output:' );              |,
                q|     $self->log_error( "    $_" ) for @stdout;                         |,
                q|     $self->abort();                                                   |,
                q| };                                                                    |,
                q| my ( $id, $dirty ) = ( $1, $2 );                                      |,
                q| if ( $dirty ) {                                                       |,
                q|     $self->abort( 'hg status is not clean' );                         |,
                q| };                                                                    |,
                q| path( '.hgtags' )->append( "$id $MY::version\n" );                    |,
            ],
        } ],

        $self->fake_release ? (
        ) : (
            [ 'ArchiveRelease' => {
                'directory'   => '.releases',
            } ],
        ),

        [ 'NextRelease' => {
            'format'      => '%V @ %{yyyy-MM-dd HH:mm zzz}d',
            'time_zone'   => 'UTC',
        } ],

        [ 'Hook::AfterRelease' => 'bump version' => {
            'hook' => [
                q| use Path::Tiny;                                                          |,
                q| my $next = ( eval( $dist->version ) + 0.000001 ) =~ s{(\d{3})\z}{_$1}r;  |,
                q| path( 'VERSION' )->spew( $next );                                        |,
                q| $self->log( [ 'Next release will be %s', $next ] );                      |,
            ],
        } ],

        [ 'Hook::AfterRelease' => 'hg post commit' => {
            'hook' => [
                q| use autodie ':all';                                                                     |,
                q| system( 'hg', 'commit', '-m', 'Post-release commit', '.hgtags', 'VERSION', 'Changes' ); |,
            ],
        } ],

        [ 'Hook::AfterRelease' => 'hg push' => {
            'hook' => [
                $self->fake_release ? (
                    q| $self->log( 'Fake release, skipping "hg push"...' ); |,
                ) : (
                    q| use IPC::System::Simple 'capture';    |,
                    q| my @stdout = capture( 'hg', 'push' ); |,
                    q| chomp( @stdout );                     |,
                    q| $self->log( "    $_" ) for @stdout;   |,
                ),
            ],
        } ],

        [ 'Hook::AfterRelease' => 'clean' => {
            'hook' => [
                q| $zilla->clean(); |,
            ],
        } ],

    );

    return;

};

__PACKAGE__->meta->make_immutable();

1;

# doc/what.pod #


# end of file #
# doc/why.pod #


# end of file #


# end of file #

__END__

=pod

=encoding UTF-8

=head1 NAME

Dist::Zilla::PluginBundle::Author::VDB - VDB's plugin bundle

=head1 VERSION

Version 0.002, released on 2015-08-08 17:03 UTC.

=head1 WHAT?

C<Dist-Zilla-PluginBundle-Author-VDB> (or just C<@Author::VDB>) is a C<Dist-Zilla> plugin bundle used by VDB.

=head1 DESCRIPTION

It is unlikely that someone else will want to use it, so I will not bother with documenting it, at
least for now.

=head1 OPTIONS

=head2 minimum_perl

=head2 fake_release

If true (C<1>), release will be a fake one, i. e. no external operations will be done:
C<UploadToCPAN> plugin will be replaced with C<FakeRelease> (which does nothing), C<ArchiveRelease>
will be skipped, and C<hg push> will not be performed.

Option can be set trough F<dist.ini> file or with C<FAKE_RELEASE> environment variable.

C<Bool>, optional, default value is C<0>.

=head1 WHY?

I have published few distributions on CPAN. Every distribution have F<dist.ini> file. All the
F<dist.ini> files are very similar. Maintaining multiple very similar F<dist.ini> files is boring.
Plugin bundle solves the problem.

=for Pod::Coverage configure

=head1 AUTHOR

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

=head1 COPYRIGHT AND LICENSE

Copyright © 2015 Van de Bugger

This file is part of perl-Dist-Zilla-PluginBundle-Author-VDB.

perl-Dist-Zilla-PluginBundle-Author-VDB 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-PluginBundle-Author-VDB 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-PluginBundle-Author-VDB. If not, see <http://www.gnu.org/licenses/>.

=cut
