App-Multigit
view release on metacpan or search on metacpan
lib/App/Multigit.pm view on Meta::CPAN
package App::Multigit;
use 5.014;
use strict;
use warnings FATAL => 'all';
use List::UtilsBy qw(sort_by);
use Capture::Tiny qw(capture);
use File::Find::Rule;
use Future::Utils qw(fmap);
use Path::Class;
use Config::INI::Reader;
use Config::INI::Writer;
use IPC::Run;
use Try::Tiny;
use App::Multigit::Future;
use App::Multigit::Repo;
use App::Multigit::Loop qw(loop);
use Exporter 'import';
our @EXPORT_OK = qw/
mgconfig mg_parent
all_repositories selected_repositories
base_branch set_base_branch mg_each
write_config
/;
=head1 NAME
App::Multigit - Run commands on a bunch of git repositories without having to
deal with git subrepositories.
=cut
our $VERSION = '0.18';
=head1 PACKAGE VARS
=head2 %BEHAVIOUR
This holds configuration set by options passed to the C<mg> script itself.
Observe that C<mg [options] command [command-options]> will pass C<options> to
C<mg>, and C<command-options> to C<mg-command>. It is those C<options> that will
affect C<%BEHAVIOUR>.
Scripts may also therefore change C<%BEHAVIOUR> themselves, but it is probably
badly behaved to do so.
=head3 report_on_no_output
Defaults to true; this should be used by scripts to determine whether to bother
mentioning repositories that gave no output at all for the given task. If you
use C<App::Multigit::Repo::report>, this will be honoured by default.
Controlled by the C<MG_REPORT_ON_NO_OUTPUT> environment variable.
=head3 ignore_stdout
=head3 ignore_stderr
These default to false, and will black-hole these streams wherever we have
control to do so.
Controlled by the C<MG_IGNORE_{STDOUT,STDERR}> environment variables.
=head3 concurrent_processes
Number of processes to run in parallel. Defaults to 20.
Controlled by the C<MG_CONCURRENT_PROCESSES> environment variable.
=head3 skip_readonly
Do nothing to repositories that have C<readonly = 1> set in C<.mgconfig>.
Controlled by the C<MG_SKIP_READONLY> environment variable.
=cut
our %BEHAVIOUR = (
report_on_no_output => $ENV{MG_REPORT_ON_NO_OUTPUT} // 1,
ignore_stdout => !!$ENV{MG_IGNORE_STDOUT},
ignore_stderr => !!$ENV{MG_IGNORE_STDERR},
concurrent => $ENV{MG_CONCURRENT_PROCESSES} // 20,
skip_readonly => !!$ENV{MG_SKIP_READONLY},
output_only => !!$ENV{MG_OUTPUT_ONLY},
);
=head2 @SELECTED_REPOS
If this is not empty, it should contain paths to repositories. Relative paths
will be determined relative to L<C<<mg_root>>|/mg_root>.
Instead of using the C<.mgconfig>, the directories in here will be used as the
list of repositories on which to work.
Each repository's C<origin> remote will be interrogated. If this exists in the
C<.mgconfig> then it will be used as normal; otherwise, it will be treated as
though it had the default configuration.
=cut
our @SELECTED_REPOS;
=head1 FUNCTIONS
These are not currently exported.
=head2 mgconfig
Returns C<.mgconfig>. This is a stub to be later configurable, but also
to stop me typoing it all the time.
=cut
sub mgconfig() {
return '.mgconfig';
}
=head2 mg_parent
Tries to find the closest directory with an C<mgconfig> in it. Dies if there is
no mgconfig here. Optionally accepts the directory to start with.
=cut
sub mg_parent {
my $pwd;
if (@_) {
$pwd = dir(shift);
}
else {
$pwd = dir;
}
$pwd = $pwd->absolute;
PARENT: {
do {
return $pwd if -e $pwd->file(mgconfig);
last PARENT if $pwd eq $pwd->parent;
}
while ($pwd = $pwd->parent);
}
die "Could not find .mgconfig in any parent directory";
}
( run in 1.326 second using v1.01-cache-2.11-cpan-13bb782fe5a )