#!/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; }