#!/usr/bin/env perl
my
(
$mydir
,
$myname
);
BEGIN {
my
$location
= (-l $0) ? abs_path($0) : $0;
$location
=~ /(.*?)([^\/]+)\z/s or
die
"?"
;
(
$mydir
,
$myname
) = ($1, $2);
}
sub
usage {
print
STDERR
map
{
"$_\n"
}
@_
if
@_
;
print
"
$myname
This is meant to be symlinked to \`.git/hooks\`. It gets all paths
from git status which are perl files and runs \`perltidy\` on them.
";
exit
(
@_
? 1 : 0);
}
sub
xopen_sender {
my
(
@cmd
) =
@_
;
open
my
$in
,
"-|"
,
@cmd
or
die
"can't open input pipe to @cmd: $!"
;
$in
}
my
$top
= `git rev-parse --show-toplevel`;
$? == 0 or
die
"error from cmd"
;
chomp
$top
;
chdir
$top
or
die
"can't chdir to Git working dir top '$top': $!"
;
sub
git_status () {
local
$/ =
"\0"
;
my
$in
= xopen_sender
qw(git status -z)
;
my
@items
;
while
(
defined
(
my
$item
= <
$in
>)) {
chomp
$item
;
my
(
$X
,
$Y
,
$path
) =
$item
=~ /(.)(.) (.*)/s
or
die
"invalid git-status -z item '$item'"
;
push
@items
, [
$X
,
$Y
,
$path
]
}
close
$in
or
die
"git status -z: $!"
;
$? == 0 or
die
"git status -z failed"
;
\
@items
}
sub
filter_status (
$items
) {
my
%indicating_modification
=
map
{
$_
=> 1 }
qw(A M R C)
;
my
@paths
;
for
my
$item
(
@$items
) {
my
(
$X
,
$Y
,
$path
) =
@$item
;
my
$x
=
$indicating_modification
{
$X
};
my
$y
=
$indicating_modification
{
$Y
};
next
unless
(
$x
or
$y
);
if
(is_perl_file(
$path
)) {
if
(
$x
and
$y
) {
warn
"$path: can't perltidy only part, thus skipped\n"
;
}
else
{
push
@paths
,
$path
;
}
}
}
\
@paths
}
my
$paths
= filter_status git_status;
if
(
@$paths
) {
my
@cmd
= (
"perltidy"
,
@$paths
);
warn
"running @cmd...\n"
;
system
@cmd
;
$? == 0 or
die
"perltidy failed"
;
system
"git"
,
"add"
,
"--"
,
@$paths
;
$? == 0 or
die
"git add failed"
;
my
$items
= git_status;
if
(!
@$items
) {
warn
"Nothing to commit after perltidy, aborting commit.\n"
;
exit
1
}
}