Renato Golin | 94cc104 | 2016-04-26 11:02:23 +0100 | [diff] [blame] | 1 | #!/usr/bin/env perl |
| 2 | |
| 3 | use strict; |
| 4 | use warnings; |
| 5 | use Cwd; |
| 6 | |
| 7 | my (@data, @authors, @repos, @changed) = ((), (), (), ()); |
| 8 | # Syntax: git-hist [author (default: whoami)] [number of weeks (default 10 / all 0)]"; |
| 9 | my $author = `whoami`; |
| 10 | my $weeks = 10; |
| 11 | my $rootdir = getcwd; |
| 12 | my $totalcommits = 0; |
| 13 | if (scalar @ARGV) { |
| 14 | foreach my $arg (@ARGV) { |
| 15 | if ($arg =~ /^\d+$/) { |
| 16 | $weeks = $arg; |
| 17 | } else { |
| 18 | $author = $arg; |
| 19 | } |
| 20 | } |
| 21 | } |
| 22 | chomp($author); |
| 23 | |
| 24 | # Make sure there are repositories to use |
| 25 | if (-d ".git") { |
| 26 | push @repos, "."; |
| 27 | } else { |
| 28 | opendir(my $dh, ".") || die "can't open local dir: $!"; |
| 29 | @repos = grep { /^[^\.]/ && -d "$_/.git" } readdir($dh); |
| 30 | closedir $dh; |
| 31 | } |
| 32 | die "Directory (or subs) not git repo\n" unless (scalar @repos); |
| 33 | &main(); |
| 34 | exit; |
| 35 | |
| 36 | ##################################################### |
| 37 | sub main() { |
| 38 | # Each week |
| 39 | my $week = 0; |
| 40 | while ($week <= $weeks) { |
| 41 | # Adjust for non-zero week list |
| 42 | $week++ if ($weeks != 0 and $week == 0); |
| 43 | print "\rParsing week: $week" if $week; |
| 44 | my $commits = 0; |
| 45 | # For each repo |
| 46 | for my $repo (@repos) { |
| 47 | #print "REPO: $repo\n"; |
| 48 | my $log = &get_weeklog($repo, $author, $week); |
| 49 | #print "LOG: [$log]\n"; |
| 50 | my $this = &get_commits($log); |
| 51 | #print "COMMITS: $this\n"; |
| 52 | if ($this and ! &find($repo, \@changed)) { |
| 53 | #print "ADDING REPO\n"; |
| 54 | push @changed, $repo; |
| 55 | } |
| 56 | &get_authors($log); |
| 57 | $commits += $this; |
| 58 | } |
| 59 | push @data, $commits; |
| 60 | last if ($weeks == 0); |
| 61 | $week++; |
| 62 | } |
| 63 | print "\n\n"; |
| 64 | |
| 65 | # Log |
| 66 | &print_report(); |
| 67 | } |
| 68 | |
| 69 | ###################### |
| 70 | sub print_report() { |
| 71 | return if ($weeks > 0 && scalar @data != $weeks); |
| 72 | |
| 73 | # Weekly histogram |
| 74 | for my $week (0..$weeks-1) { |
| 75 | printf("%02d week [%02d]: ", $week, $data[$week]); |
| 76 | for (1..$data[$week]) { |
| 77 | print "*"; |
| 78 | } |
| 79 | print "\n"; |
| 80 | } |
| 81 | |
| 82 | # Summary |
| 83 | print "\nTotal commits: "; |
| 84 | printf("%3d", $totalcommits); |
| 85 | print "\n Repositories: "; |
| 86 | printf("%3d ", scalar @changed); |
| 87 | &dump(\@changed); |
| 88 | print "\n Authors: "; |
| 89 | printf("%3d ", scalar @authors); |
| 90 | &dump(\@authors); |
| 91 | print "\n"; |
| 92 | } |
| 93 | |
| 94 | ###################### |
| 95 | sub get_weeklog() { |
| 96 | my ($repo, $author, $week) = @_; |
| 97 | # Author |
| 98 | my $cmd = "git shortlog -s -n ". |
| 99 | "--author='$author' "; |
| 100 | # And week (if available) |
| 101 | if ($week) { |
| 102 | my $prev = $week-1; |
| 103 | $cmd .= "--since='$week.week' ". |
| 104 | "--until='$prev.week'"; |
| 105 | } |
| 106 | # Run command |
| 107 | chdir($repo); |
| 108 | my $log = `$cmd`; |
| 109 | chdir($rootdir); |
| 110 | return $log; |
| 111 | } |
| 112 | |
| 113 | ###################### |
| 114 | sub get_commits() { |
| 115 | my ($log) = @_; |
| 116 | my $commits = 0; |
| 117 | foreach my $line (split(/\n/, $log)) { |
| 118 | my ($this) = ($line =~ /(\d+)/); |
| 119 | $commits += $this; |
| 120 | } |
| 121 | $totalcommits += $commits; |
| 122 | return $commits; |
| 123 | } |
| 124 | |
| 125 | ###################### |
| 126 | sub get_authors() { |
| 127 | my ($log) = @_; |
| 128 | foreach my $line (split(/\n/, $log)) { |
| 129 | my ($author) = ($line =~ /\d+\s+(\w.*)/); |
| 130 | if (!&find($author, \@authors)) { |
| 131 | push @authors, $author; |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | ###################### |
| 137 | sub find() { |
| 138 | my ($elm, $array) = @_; |
| 139 | foreach my $e (@$array) { |
| 140 | return 1 if ($e eq $elm); |
| 141 | } |
| 142 | return 0; |
| 143 | } |
| 144 | |
| 145 | ###################### |
| 146 | sub dump() { |
| 147 | my ($array) = @_; |
| 148 | return if (!scalar @{$array}); |
| 149 | my $out = ""; |
| 150 | foreach my $i (@$array) { |
| 151 | $out .= "$i, "; |
| 152 | } |
| 153 | $out =~ s/, $//; |
| 154 | print $out; |
| 155 | } |