NAME

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

PACKAGE VARS

 %BEHAVIOUR

    This holds configuration set by options passed to the mg script itself.

    Observe that mg [options] command [command-options] will pass options
    to mg, and command-options to mg-command. It is those options that will
    affect %BEHAVIOUR.

    Scripts may also therefore change %BEHAVIOUR themselves, but it is
    probably badly behaved to do so.

  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 App::Multigit::Repo::report, this will be
    honoured by default.

    Controlled by the MG_REPORT_ON_NO_OUTPUT environment variable.

  ignore_stdout, ignore_stderr

    These default to false, and will black-hole these streams wherever we
    have control to do so.

    Controlled by the MG_IGNORE_{STDOUT,STDERR} environment variables.

  concurrent_processes

    Number of processes to run in parallel. Defaults to 20.

    Controlled by the MG_CONCURRENT_PROCESSES environment variable.

  skip_readonly

    Do nothing to repositories that have readonly = 1 set in .mgconfig.

    Controlled by the MG_SKIP_READONLY environment variable.

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;

 mg_each

    This is the exported name of each

        use App::Multigit qw/mg_each/;

 loop

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

 init($workdir)

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

 base_branch

    Returns the branch that the base repository is on; i.e. the repository
    that contains the .mgconfig or equivalent.

    The purpose of this is to switch the entire project onto a feature
    branch; scripts can use this as the cue to work against a branch other
    than master.

    This will die if the base repository is not on a branch, because if
    you've asked for it, giving you a default will more likely be a
    hindrance than a help.

 set_base_branch($branch)

    Checks out the provided branch name on the parent repository

AUTHOR

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

ACKNOWLEDGEMENTS

    This module could have been a lot simpler but I wanted it to be a foray
    into the world of Futures. Shout outs go to those cats in
    irc.freenode.net#perl who basically architectured this for me.

    tm604 (TEAM) - for actually understanding Future architecture, and not
    being mad at me.

    LeoNerd (PEVANS) - also for not being irritated by my inane questions
    about IO::Async and Future.

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

