Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
行末のスペースの削除以外の修正を git addする
#!/usr/bin/env perl
use strict;
use warnings;
use File::Which ();
use File::Copy ();
my $GIT = File::Which::which('git');
die "Error: can't find 'git' command\n" unless defined $GIT;
main() unless caller;
sub main {
my $is_modified = 0;
for my $file (@ARGV) {
my $diff_str = get_diff_ignore_eol_space($file);
my $backup = backup_orig($file);
revert_changing($file);
apply_patch($diff_str);
check($file);
print "OK[y/n] >> ";
my $answer = <STDIN>;
if ($answer =~ m{^[yY]}) {
add_file($file);
$is_modified = 1;
} else {
rename $backup, $file or die "Can't rename $backup $file: $!\n";
}
}
warn "Please check 'git diff --cached @ARGV'\n" if $is_modified;
}
sub check {
my $file = shift;
my $pid = fork;
die "Error: fork $!\n" unless defined $pid;
if ($pid == 0) {
my @cmd = ($GIT, 'diff', $file);
exec { $GIT } @cmd or die "Can't exec '@cmd': $!\n";
}
my $pid = waitpid $pid, 0;
die "Error: waitpid $!\n" unless defined $pid || $pid > 0;
}
sub get_diff_ignore_eol_space {
my $file = shift;
my @cmd = ($GIT, 'diff', '--ignore-space-at-eol', $file);
open my $fh, "-|", @cmd or die "Can't exec '@cmd' $!\n";
my $diff_str = do { local $/; <$fh>; };
close $fh;
return $diff_str;
}
sub backup_orig {
my $file = shift;
my $backup = "${file}.orig";
File::Copy::copy($file, $backup) or die "Copy failed: $!\n";
return $backup;
}
sub revert_changing {
my $file = shift;
my @cmd = ($GIT, 'checkout', $file);
my $status = system(@cmd);
die "Error: '@cmd' : $!\n" if $status != 0;
}
sub apply_patch {
my $diff_str = shift;
my @cmd = ($GIT, 'apply', '-'); # read from stdin
open my $fh, "|-", @cmd or die "Can't exec '@cmd' $!\n";
print $fh $diff_str or die "Error: '@cmd' $!\n";
close $fh;
}
sub add_file {
my $file = shift;
my @cmd = ($GIT, 'add', $file);
my $status = system(@cmd);
die "Error: '@cmd' : $!\n" if $status != 0;
}
#!/bin/sh
tmp_patch=$(tempfile) || exit 1
is_modified=0
for file in $@
do
$(git diff --ignore-space-at-eol $file > $tmp_patch) || exit 1
backup=${file}.orig
cp -n $file $backup || exit 1
git checkout $file || exit 1
git apply $tmp_patch || exit 1
git diff $file || exit 1
echo -n "OK? [y/n] >> "
read answer
case $answer in
[yY]*)
echo "git add $file"
git add $file || exit 1
is_modified=1
;;
*)
mv $backup $file
;;
esac
done
if [ "$is_modified" = "1" ]
then
echo "Please check 'git diff --cached' before commit"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment