NAME

App::Multigit - Run commands on a bunch of git repositories without having to deal with git subrepositories.

VERSION

Version 0.01

FUNCTIONS

These are not currently exported.

mgconfig

Returns .mgconfig. This is a stub to be later configurable, but also to stop me typoing it all the time.

mg_parent

Tries to find the closest directory with an mgconfig in it. Dies if there is no mgconfig here.

all_repositories

Returns a hashref of all repositories under mg_parent.

The keys are the repository directories relative to mg_parent, and the values are the hashrefs from the config, if any.

each($command)

For each configured repository, $command will be run. Each command is run in a separate process which chdirs into the repository first.

It returns a convergent Future that represents all tasks. When this Future completes, all tasks are complete.

In the arrayref form, the $command is passed directly to run in App::Multigit::Repo. The Futures returned thus are collated and the list of return values is thus collated. The list will be an alternating list of STDOUT and STDERRs from the commands thus run.

my $future = App::Multigit::each([qw/git reset --hard HEAD/]);
my @stdios = $future->get;

The subref form is more useful. The subref is run with the Repo object, allowing you to chain functionality thus.

use curry;
my $future = App::Multigit::each(sub {
    my $repo = shift;
    $repo
        ->run(\&do_a_thing)
        ->then($repo->curry::run(\&do_another_thing))
    ;
});

In this case, the subref given to run is passed the STDOUT and STDERR from the previous command; for convenience, they start out as the empty strings, rather than undef.

sub do_a_thing {
    my ($repo_obj, $stdout, $stderr) = @_;
    ...
}

Thus you can chain them in any order.

Observe also that the interface to run allows for the arrayref form as well:

use curry;
my $future = App::Multigit::each(sub {
    my $repo = shift;
    $repo
        ->run([qw/git checkout master/])
        ->then($repo->curry::run(\&do_another_thing))
    ;
});

Notably, the returned Future will gather the return values of all the other Futures. This means your final ->then can be something other than a curried run. The helper function report produces a pair whose first value is the repo name and the second value is STDOUT concatenated with STDERR.

use curry;
my $future = App::Multigit::each(sub {
    my $repo = shift;
    $repo
        ->run([qw/git checkout master/])
        ->then($repo->curry::run(\&do_another_thing))
        ->then(App::Multigit::report($repo))
    ;
});

my %results = $future->get;

loop

Returns the IO::Async::Loop object. This is essentially a singleton.

init($workdir)

Scans $workdir for git directories and registers each in .mgconfig

report

This adapts a ->then chain using run in App::Multigit::Repo to return the name of the repository and the output.

Returns a Future that yields a two-element list of the directory - from the config - and the STDOUT from the command, indented with tabs.

Intended for use as a hash constructor.

my %report = Future->wait_all(@futures)->get;

for my $dir (sort keys %report) {
    say for $dir, $report{$dir};
}

indent

Returns a copy of the first argument indented by the number of tabs in the second argument

AUTHOR

Alastair McGowan-Douglas, <altreus at perl.org>

BUGS

Please report bugs on the github repository https://github.com/Altreus/App-Multigit.

LICENSE

Copyright 2015 Alastair McGowan-Douglas.

This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:

http://www.perlfoundation.org/artistic_license_2_0