| #!/usr/bin/env perl |
| |
| use strict; |
| use warnings; |
| use Cwd; |
| |
| my (@data, @authors, @repos, @changed) = ((), (), (), ()); |
| # Syntax: git-hist [author (default: whoami)] [number of weeks (default 10 / all 0)]"; |
| my $author = `whoami`; |
| my $weeks = 10; |
| my $rootdir = getcwd; |
| my $totalcommits = 0; |
| if (scalar @ARGV) { |
| foreach my $arg (@ARGV) { |
| if ($arg =~ /^\d+$/) { |
| $weeks = $arg; |
| } else { |
| $author = $arg; |
| } |
| } |
| } |
| chomp($author); |
| |
| # Make sure there are repositories to use |
| if (-d ".git") { |
| push @repos, "."; |
| } else { |
| opendir(my $dh, ".") || die "can't open local dir: $!"; |
| @repos = grep { /^[^\.]/ && -d "$_/.git" } readdir($dh); |
| closedir $dh; |
| } |
| die "Directory (or subs) not git repo\n" unless (scalar @repos); |
| &main(); |
| exit; |
| |
| ##################################################### |
| sub main() { |
| # Each week |
| my $week = 0; |
| while ($week <= $weeks) { |
| # Adjust for non-zero week list |
| $week++ if ($weeks != 0 and $week == 0); |
| print "\rParsing week: $week" if $week; |
| my $commits = 0; |
| # For each repo |
| for my $repo (@repos) { |
| #print "REPO: $repo\n"; |
| my $log = &get_weeklog($repo, $author, $week); |
| #print "LOG: [$log]\n"; |
| my $this = &get_commits($log); |
| #print "COMMITS: $this\n"; |
| if ($this and ! &find($repo, \@changed)) { |
| #print "ADDING REPO\n"; |
| push @changed, $repo; |
| } |
| &get_authors($log); |
| $commits += $this; |
| } |
| push @data, $commits; |
| last if ($weeks == 0); |
| $week++; |
| } |
| print "\n\n"; |
| |
| # Log |
| &print_report(); |
| } |
| |
| ###################### |
| sub print_report() { |
| return if ($weeks > 0 && scalar @data != $weeks); |
| |
| # Weekly histogram |
| for my $week (0..$weeks-1) { |
| printf("%02d week [%02d]: ", $week, $data[$week]); |
| for (1..$data[$week]) { |
| print "*"; |
| } |
| print "\n"; |
| } |
| |
| # Summary |
| print "\nTotal commits: "; |
| printf("%3d", $totalcommits); |
| print "\n Repositories: "; |
| printf("%3d ", scalar @changed); |
| &dump(\@changed); |
| print "\n Authors: "; |
| printf("%3d ", scalar @authors); |
| &dump(\@authors); |
| print "\n"; |
| } |
| |
| ###################### |
| sub get_weeklog() { |
| my ($repo, $author, $week) = @_; |
| # Author |
| my $cmd = "git shortlog -s -n ". |
| "--author='$author' "; |
| # And week (if available) |
| if ($week) { |
| my $prev = $week-1; |
| $cmd .= "--since='$week.week' ". |
| "--until='$prev.week'"; |
| } |
| # Run command |
| chdir($repo); |
| my $log = `$cmd`; |
| chdir($rootdir); |
| return $log; |
| } |
| |
| ###################### |
| sub get_commits() { |
| my ($log) = @_; |
| my $commits = 0; |
| foreach my $line (split(/\n/, $log)) { |
| my ($this) = ($line =~ /(\d+)/); |
| $commits += $this; |
| } |
| $totalcommits += $commits; |
| return $commits; |
| } |
| |
| ###################### |
| sub get_authors() { |
| my ($log) = @_; |
| foreach my $line (split(/\n/, $log)) { |
| my ($author) = ($line =~ /\d+\s+(\w.*)/); |
| if (!&find($author, \@authors)) { |
| push @authors, $author; |
| } |
| } |
| } |
| |
| ###################### |
| sub find() { |
| my ($elm, $array) = @_; |
| foreach my $e (@$array) { |
| return 1 if ($e eq $elm); |
| } |
| return 0; |
| } |
| |
| ###################### |
| sub dump() { |
| my ($array) = @_; |
| return if (!scalar @{$array}); |
| my $out = ""; |
| foreach my $i (@$array) { |
| $out .= "$i, "; |
| } |
| $out =~ s/, $//; |
| print $out; |
| } |