#!/usr/bin/perl
use strict;
use warnings;

our $VERSION = 0.3;

=pod

=head1 NAME
 
eachgit - Run git commands on multiple repos at once.
 
=head1 USAGE

  eachgit <parent_dir> <git_args ...>

=head1 SYNOPSIS

  # Run 'git grep "Some String"' for all repos under '/path/to/repos':
  eachgit /path/to/repos grep \"Some String\"
  
  # Show git status for all repos in the current dir:
  eachgit . status

=head1 DESCRIPTION

Very simple script lets you run a git command multiple on repos at once. 
See the SYNOPSIS for usage.

I wrote this specifically so I could run C<git grep> on all my repos at once, but
any git command works, too.


=head1 AUTHOR

Henry Van Styn <vanstyn@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2014 by IntelliTree Solutions llc.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut

#####################################################
#
use Path::Class qw( dir );

my ($start, @args) = @ARGV;
shift @args if ($args[0] && $args[0] eq 'git');
die "Usage: ./eachgit.pl START_DIR GIT_OPTIONS\n" unless (scalar @args > 0);

my $start_dir = dir( $start )->absolute->resolve;
die "bad start directory '$start'\n" unless (-d $start_dir);

my @repos = &_find_repos($start_dir);
die "Found no git repos under '$start_dir'\n" unless (scalar @repos > 0);

&_run_git_commands(
  join(" ",'git',@args),
  @repos
);

exit;
#
#####################################################

sub _find_repos {
  my $dir = shift;
  my @repo_dirs = ();
  $dir->recurse(
    preorder => 1, depthfirst => 1,
    callback => sub {
      my $child = shift;
      if($child->is_dir) {
        if(-d $child->subdir('.git')) {
          push @repo_dirs, $child;
          return $child->PRUNE;
        }
      }
    }
  );
  return @repo_dirs;
}

sub _run_git_commands {
  my ($cmd,@repos) = @_;
  
  # Send all STDERR output to STDOUT (needed for backtics below)
  open(STDERR, ">&STDOUT");
  
  for my $dir (@repos) {
    local $ENV{GIT_PAGER}     = '';
    local $ENV{GIT_DIR}       = $dir->subdir('.git')->stringify;
    local $ENV{GIT_WORK_TREE} = $dir->stringify;
    
    print "\n##[$dir]: $cmd\n";
    qx/$cmd 1>&2/;
  }
}