Last active
August 21, 2018 23:04
-
-
Save samcv/dabc73a4a0a93d80058c5485c4ca2802 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl6 | |
use v6; | |
=TITLE Git::Log | |
=SUBTITLE Gets the git log as a Perl 6 object | |
=DESCRIPTION | |
=para | |
The first argument is the command line args wanted to be passed into C<git log>. | |
Optionally you can also get the files changes as well as the number of lines | |
added or deleted. | |
=para | |
Returns an array of hashes in the following format: | |
C<commit => "df0c229ad6ba293c67724379bcd3d55af6ea47a0", | |
AuthorName => "Author's Name", AuthorEmail => "[email protected]" ...> | |
If the option :get-changes is used it will also add a 'changes' key in the | |
following format: C<<changes => { $[ { filename => 'myfile.txt', added => 10, deleted => 5 }, ... ] }>> | |
=para | |
If there is a field that you need that is not offered, then you can supply an | |
array, :@fields. Format is an array of pairs: C<<commit => '%H', AuthorName => '%an' ...>> | |
you can look for more L<here|https://git-scm.com/docs/pretty-formats>. | |
my @fields-default = | |
'commit' => '%H', | |
'AuthorName' => '%an', | |
'AuthorEmail' => '%ae', | |
'AuthorDate' => '%aI', | |
'Subject' => '%s', | |
'Body' => '%b' | |
; | |
# Private use characters which let us separate fields. | |
my $column-sep = 0x102B7C.chr; | |
my $commit-sep = 0x102B7D.chr; | |
sub git-log (@args, :@fields = @fields-default, IO::Path :$path, Bool:D :$get-changes = False, Bool:D :$date-time = False) is export { | |
my @log-arg = 'log'; | |
@log-arg.prepend('--git-dir', $path.child(".git").absolute) if $path; | |
my $format = '--pretty=format:' ~ @fields».value.join($column-sep) ~ $commit-sep; | |
my $cmd = run 'git', @log-arg, @args, $format, :out, :err; | |
if $cmd.exitcode != 0 { | |
die "git log returned code $cmd.exitcode(). Message: $cmd.err.slurp()"; | |
} | |
my $text = $cmd.out.slurp; | |
# Remove extra from end: we only want the separator | |
# to be *between* entries, not at the end of each one. | |
$text ~~ s/$commit-sep$//; | |
# Remove the trailing newlines git adds | |
$text ~~ s:g/$commit-sep\n/$commit-sep/; | |
my @commits; | |
for $text.split($commit-sep) -> $entry { | |
my %thing = %( @fields».key Z=> $entry.split($column-sep) ); | |
if $date-time { | |
for %thing.keys.grep(*.ends-with("Date")) -> $key { | |
%thing{$key} = DateTime.new(%thing{$key}); | |
} | |
} | |
@commits.push: %thing; | |
} | |
if $get-changes { | |
my $stat-proc = run 'git', @log-arg, '--numstat', "--format=$commit-sep%H", @args, :out; | |
my $stat-text = $stat-proc.out.slurp; | |
if $stat-proc.exitcode != 0 { | |
die "git log returned code $stat-proc.exitcode(). Message: $stat-proc.err.slurp()"; | |
} | |
# remove leading separator | |
$stat-text ~~ s/^$commit-sep//; | |
my %commit-data; | |
$stat-text.split($commit-sep).map({ get-data($_, %commit-data) }); | |
for @commits -> $commit { | |
$commit<changes> = %commit-data{$commit<commit>}; | |
} | |
} | |
#say @commits.map(*.perl).join("\n\n"); | |
@commits; | |
} | |
sub get-data (Str:D $str, %commit-data) { | |
my @lines = $str.lines.grep({ $_ ne ""}); | |
my $commit = @lines.shift; | |
for @lines -> $line { | |
# Make sure it's only three fields, in case there are tabs in the filename | |
my ($added, $removed, $filename) = $line.split("\t", 3); | |
$added = $added.Int unless $added eq '-'; | |
$removed = $removed.Int unless $removed eq '-'; | |
push %commit-data{$commit}, %(added => $added, removed => $removed, filename => $filename); | |
} | |
} | |
sub MAIN (Str :$path, *@args) { | |
if $path { | |
say git-log(:get-changes, :path($path.IO), @args).map(*.perl).join("\n\n"); | |
} | |
else { | |
say git-log(:get-changes, @args).map(*.perl).join("\n\n");; | |
} | |
} | |
=AUTHOR Samantha McVey (samcv) [email protected] | |
=LICENSE | |
This is free software; you can redistribute it and/or modify it under | |
the Artistic License 2.0. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment