#!/usr/bin/env perl

use strict;
use warnings;
use 5.014;

use Getopt::Long qw(:config gnu_getopt require_order);
use App::Multigit qw(mg_each);
use App::Multigit::Script;
use Path::Class;
use Future;

our %TESTS = (
    stdout => sub {
        my %data = @_;
        return $data{stdout};
    },
    exitcode => sub {
        my %data = @_;
        return ! $data{exitcode};
    },
);

%options = (
    %options,
    absolute => 1
);

GetOptions(
    \%options,
    'absolute!',
    'debug|d!',
    'exitcode|e!',
    'invert|v!',
);

my $future = mg_each(sub {
    my $repo = shift;
    $repo->run(\@ARGV)
        ->then($options{debug} ? $repo->curry::report : filter($repo))
});

say for $future->get;

sub filter {
    my $repo = shift;
    sub {
        my %data = @_;
        my $test = $TESTS{$options{exitcode} ? 'exitcode' : 'stdout'};
        my $pass = $test->(%data);

        $pass = !$pass if $options{invert};

        if ($pass) {
            my $dir = $repo->config->{dir};
            if ($options{absolute}) {
                $dir = dir($dir)->absolute;
            }
            Future->done($dir);
        }
        else {
            Future->done
        }
    }
}

=head1 SYNOPSIS

    mg-grep COMMAND

Runs COMMAND in each repository and reports the path to the repository if
COMMAND returned data on STDOUT.

=head1 OPTIONS

=over

=item --absolute 

=item --no-absolute

By default, the paths are output as absolute paths so it doesn't matter where in
the project you are. With --no-absolute, paths are output relative to the mg
root.

=item --debug, -d

If you're getting info you didn't expect, use debug mode to mimic `mg each`,
i.e. to just report the results without filtering. Note that this is subject to
the -q and -v options to mg itself.

=item --exitcode, -e

Instead of STDOUT, use the exit code of the process to determine success.
Repositories with a zero exit code are reported.

=item --invert, -v

Invert the logic so it reports the opposite set of repositories.

=back
