#! perl

use strict;
use warnings;
use App::ModuleBuildTiny;
use File::Basename 'basename';

our $VERSION = '0.049';

print_help() if ($ARGV[0] // 'help') eq 'help';

modulebuildtiny(@ARGV);

sub print_help {
	my $program = basename($0);
	print "Usage: $program <command> [arguments ...]\n\nAvailable commands:\n\n";
	App::ModuleBuildTiny::Help->filter(__FILE__);
	print "\n";
	exit !@ARGV;
}

package App::ModuleBuildTiny::Help;

use parent qw(Pod::Simple::Methody);

sub start_head1 {
	my ($self, $attrs) = @_;
	$self->{_mbth_head1_content} = '';
}

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

	$self->{_mbth_in_subcommands} = delete($self->{_mbth_head1_content}) eq 'SUBCOMMANDS';
}

sub start_head2 {
	my ($self, $attrs) = @_;

	return unless $self->{_mbth_in_subcommands};
	$self->{_mbth_subcommand_name} = '';
}

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

	if (my $cmd = delete $self->{_mbth_subcommand_name}) {
		$self->output_fh->printf("    %-10s - ", $1) if $cmd =~ /(^\w+)/;
		$self->{_mbth_print_desc} = 1;
	}
}

sub handle_text {
	my ($self, $text) = @_;

	if (defined $self->{_mbth_head1_content}) {
		$self->{_mbth_head1_content} .= $text;
		return;
	}

	if (defined $self->{_mbth_subcommand_name}) {
		$self->{_mbth_subcommand_name} .= $text;
		return;
	}

	if (delete $self->{_mbth_print_desc}) {
		$self->output_fh->say($1) if $text =~ /^([^.(]+)/;
	}
}

__END__

=head1 NAME

mbtiny - A standalone authoring script for Module::Build::Tiny

=head1 SYNOPSIS

 mbtiny listdeps | cpanm
 mbtiny test --release
 mytiny regenerate
 mbtiny upload

=head1 DESCRIPTION

C<mbtiny> is a tool to help assemble your CPAN distributions. It's a minimalist tool that tries to come with as few surprises as possible, and thus provide a gentle learning curve for its users.

=head1 SUBCOMMANDS

=head2 regenerate [--bump] [--version=<version] [--verbose] [--dry-run] [--scan] <files>...

Regenerate the specified files. If no files are given, defaults to all six files it can regenerate. You usually want to do this when bumping the version of a module. Takes the following options:

=over 4

=item * bump

Bump the version of the distribution before regenerating. The default for this when regenerating all files can be set in the configuration.

=item * version = <new-version>

Set the version of the distribution before regenerating.

=item * scan

Scan for dependencies to include in the metafiles. The default for this can be set in the configuration.

=item * trial

Make the new version a trial version.

=item * commit

Create a git commit for the version bump. The default for this when regenerating all files can be set in the configuration.

=item * verbose

This will make regeneration more verbose.

=item * dry-run

This will cause it to not write anything to disk, this is only ever useful when combined with the verbose option.

=back

The following files can be generated:

=over 4

=item * Build.PL

The code needed to build the dist using L<Module::Build::Tiny|Module::Build::Tiny> or L<Dist::Build|Dist::Build>.

It will use the former unless a C<planner/> directory is present.

=item * MANIFEST

The list of files in this distribution, and optionally descriptions.

=item * META.json

Most meta information about this distributions. Useful for both presenting information to the user as for installing the distribution.

=item * META.yml

The legacy meta file. This is mainly useful for bootstrapping on CPAN clients too old to support META.json but recent enough to support configure_requires.

=item * README

A description of the project, based on the documentation of the main module.

=item * LICENSE

The license of the distribution.

=back

=head2 upload [--silent] [--config=<config_file>] [--tag] [--push]

Assemble a tarball and upload it to CPAN.

Using a L<Config::Identity|Config::Identity> compatible F<.pause> file in your home directory is recommended, but if it's absent or incomplete your credentials will be asked on the console. Takes the following options:

=over 4

=item * tag

Tag the current release with the current version. The default for this can be set in the configuration.

=item * push

Push the current commit, and tag it C<--tag> is also specified. The default for this can be set in the configuration.

=item * silent

This will enable silent mode

=item * config=<config-file>

The location of your pause credentials

=back

=head2 test [--no-author] [--release]

Run all of the tests of a distribution. Takes two negatable options:

=over 4

=item * release

Run release tests. Defaults to false.

=item * author

Run author tests. Defaults to true.

=back

=head2 scan [--omit-core=<version>] [--omit=<module>]

Scan the C<lib/>, C<script/> and C<t/> directories for dependencies and write them to C<prereqs.json>. Accepts the following option:

=over 4

=item * omit_core = version

Set a minimum perl version (e.g. C<5.008001> or C<v5.8.1>) whose core-provided dependencies will not be explicitly included.

=item * omit = module

Omit a specific module from the dependencies. Can be specified multiple times.

=back

=head2 mint [--<option>=<value>]...  <distribution>

Create a new distribution. Takes one mandatory positional argument, the name of the new distribution, and the following optional named arguments:

=over 4

=item * abstract

The abstract of this new distribution. Defaults to an empty string.

=item * author

The name of the author of this distribution. The default value is set in the configuration file.

=item * dirname

The directory name for the new distribution. Defaults to the distribution name.

=item * email

The email address of the author. The default value is set in the configuration file.

=item * license

The license of the new distribution. The default value is set in the configuration file, this is usually C<Perl_5>.

=item * version

The initial version of the new distribution. Defaults to C<0.001>.

=item * init-git

Initialize a git repository on minting.

=back

=head2 setup <type>

Create or update your global configuration file (at F<~/.mbtiny/config>). Takes one optional positional argument that can take any of the following values:

=over 4

=item * update

Ask about all configuration items that are currently empty. This is the default.

=item * minimal

Like update, but only asks questions that do not have a default (The author's name and email address).

=item * all

Ask about all configuration items, even if they currently have a value.

=item * get <config_key>

This shows the value of the given key.

=item * set <config_key> <config_value>

This sets the given key to the specified value.

=item * list

List your current configuration.

=item * reset

Remove the current configuration file.

=back

=head2 config <type>

Update your distribution's configuration file. Takes one optional positional argument that can take any of the following values:

=over 4

=item * update

Ask about all configuration items that are currently empty. This is the default.

=item * all

Ask about all configuration items, even if they currently have a value.

=item * get <config_key>

This shows the value of the given key.

=item * set <config_key> <config_value>

This sets the given key to the specified value.

=item * copy

This copies the values from the global configuration into the distribution's configuration.

=item * list

List your current configuration.

=item * reset

Remove the current configuration file.

=back

=head2 listdeps [--versions] [--json] [--missing] [--omit-core=<version>]

List all dependencies of this distribution. By default it prints just a list of module names.

=over 4

=item * versions

Print the required versions along with the modules.

=item * json

Output the dependencies in JSON format

=item * missing

List only modules whose requirement isn't met.

=item * author

Include development-time dependencies, such as C<App::ModuleBuildTiny> itself.

=item * omit-core=<perl-version>

Exclude any prerequisites that are provided by that specific perl version.

=back

=head2 run [--no-build] <command>

Run the specified command in an assembled distribution. It takes one boolean argument:

=over 4

=item * no-build

Do not build the distribution (run C<Build.PL> and C<Build>) before running the command.

=back

=head2 shell [--build]

Run a shell in the assembled distribution. This is equivalent to C<mbtiny run --no-build $SHELL>. It takes one argument.

=over 4

=item * build

Build the distribution before running the shell.

=back

=head2 dist

Create a distribution tarball.

=head2 distdir

Create a directory containing all of the files of the distribution.

=head2 version

This prints the version of C<mbtiny>.

=head1 INPUTS

The metadata for the distribution is gathered from various sources.

=over 4

=item *

The distribution name is taken from the local directory name.

=item *

The version, abstract and author are taken from the main module of the distribution.

=item *

The license is extracted from the POD, unless a metamerge file overrides this

=item *

Prerequisites are mostly taken from C<prereqs.json>, C<prereqs.yml> and (discouraged) L<cpanfile>, except when injected explicitly (e.g. a configure dependency on L<Module::Build::Tiny|Module::Build::Tiny>).

 # prereqs.yml
 runtime:
   requires:
     perl: '5.012'
     Path::Tiny: 0
   recommends:
     Term::ReadLine::Gnu: 0
 test:
   requires:
     Test::More: '0.88'

=item *

A C<metamerge.json> or C<metamerge.yml> file can be used to merge any additional meta information you want (including dependencies). It is assumed to be in L<meta-spec 2 format|https://metacpan.org/pod/CPAN::Meta::Spec> unless otherwise specified.

 # metamerge.yml
 resources:
   bugtracker:
     web: https://github.com/leont/App-ModuleBuildTiny/issues
   homepage: http://example.org/
   x_IRC: irc://irc.perl.org/#toolchain

=back