Initial commit
[git-chart] / git-chart
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use POSIX qw(ceil);
6 use Getopt::Long;
7
8 sub usage() {
9         print "Usage: git chart\n";
10 }
11
12 sub gather_data($) {
13         my $options = shift;
14         my @dataset;
15
16         print "Gathering data ...\n";
17
18         my $day=$options->{from};
19         my $to =$options->{to};
20         my $step=$options->{step};
21         my $max=$options->{max} || 0;
22
23         while ($day < $to) {
24                 my $next = $day + $step;
25                 my $val = `git log --pretty=%s --since="$next days ago" --until="$day days ago" | wc -l`;
26                 chomp $val;
27                 push @dataset, $val;
28                 $max = $val if $max < $val;
29                 $day = $next;
30         }
31
32         $options->{max} = $max;
33
34         print "...done\n";
35
36         return \@dataset;
37 }
38
39 # plot the dataset with google chart. the function can be called with either one or two parameters.
40 # when called with two parameters, the first is assumed to be the dataset, and the second the options
41 # (array and hash ref respectively).
42 # when called with a single parameter, it is assumed to be an options hash ref, and the dataset is 
43 # created by calling gather_data with the passed options.
44 sub google_chart($;$) {
45         my $dataset = shift;
46         my $options = shift;
47         if (! defined $options) {
48                 $options = $dataset;
49                 $dataset = gather_data($options);
50         }
51
52         my $height=$options->{chart_height};
53         my $max = $options->{max};
54         my $from = $options->{from};
55         my $to = $options->{to};
56         my $step = $options->{step};
57         my $width=($step < 20 ? 20 : $step)*@$dataset;
58
59         my $url="https://chart.googleapis.com/chart?chs=${width}x${height}&cht=bvg&chd=t:%s&chds=0,$max&chbh=a&chxt=y,x&chxr=0,0,$max|1,$to,$from,-$step";
60
61         my $launch = sprintf $url, join(",",reverse @$dataset);
62         # print $launch, "\n";
63         `git web--browse "$launch"`
64 }
65
66 sub parse_from($) {
67         my $from = shift;
68         if ($from =~/^\d+$/) {
69                 return 0 + $from;
70         } else {
71                 # TODO
72                 warn "non-numeric from not supported yet\n";
73         }
74 }
75
76 sub parse_to($) {
77         my $to = shift;
78         if ($to =~/^\d+$/) {
79                 return 0 + $to;
80         } else {
81                 # TODO
82                 warn "non-numeric to not supported yet\n";
83         }
84 }
85
86 sub parse_step($) {
87         my $step = shift;
88         if ($step =~/^\d+$/) {
89                 return 0 + $step;
90         } else {
91                 return 1 if $step eq 'daily';
92                 return 7 if $step eq 'weekly';
93                 return 30 if $step eq 'monthly';
94         }
95 }
96
97 # some defaults
98 my %options = (
99         from => 0,
100         to => 31,
101         step => 1,
102         chart_height => 144,
103 );
104
105 my $daily=0;
106 my $weekly=0;
107 my $monthly=0;
108
109 my $from=0;
110 my $to=0;
111 my $step=0;
112
113 GetOptions(
114         daily => \$daily,
115         weekly => \$weekly,
116         monthly => \$monthly,
117         'from=s' => \$from,
118         'to=s' => \$to,
119         'step=s' => \$step,
120 );
121
122 $options{from} = parse_from($from) if $from;
123
124 if ($monthly) {
125         $options{to} = $options{from} + 365;
126         $options{step} = 30;
127 } elsif ($weekly) {
128         $options{to} = $options{from} + 6*30;
129         $options{step} = 30;
130 } elsif ($daily) {
131         $options{to} = $options{from} + 31;
132         $options{step} = 1;
133 }
134
135 $options{to} = parse_to($to) if $to;
136 $options{step} = parse_step($step) if $step;
137
138 die "step must be strictly positive!" unless $options{step} > 0;
139
140 google_chart(\%options);