Skip to content

Instantly share code, notes, and snippets.

@okura3
Created November 25, 2012 07:03
Show Gist options
  • Save okura3/4142691 to your computer and use it in GitHub Desktop.
Save okura3/4142691 to your computer and use it in GitHub Desktop.
find git commit of specified file
use strict;
use warnings;
use Getopt::Long;
use File::Spec;
use lib qw/lib/;
use GitFindCommit;
my $repo = File::Spec->curdir();
my $all = 0;
GetOptions(
"repo|r=s" => \$repo,
"all|a" => \$all,
);
die if ! -d $repo;
my $git_find_commit = GitFindCommit->new(repo => $repo);
my $commits = $git_find_commit->find( $ARGV[0], $all );
foreach my $commit ( @$commits ) {
print $commit, "\n";
}
exit;
__END__
package GitFindCommit;
use strict;
use warnings;
use autodie;
use File::Spec;
our $VERSION = '0.01';
sub new {
my ($class, %args) = @_;
my $git_repo = $args{repo};
die if !-d $git_repo;
return bless { git_repo => File::Spec->rel2abs($git_repo), }, $class;
}
sub find {
my ($self, $file, $all) = @_;
die if !-f $file;
my $hash_object = $self->git_hash_object($file);
my (undef, undef, $leaf) = File::Spec->splitpath($file);
my $commit_logs = $self->git_log($leaf);
my $commits = [];
foreach my $commit_log (@$commit_logs) {
my ($commit, ) = split /\s+/, $commit_log, 2;
my $hash = $self->git_ls_tree($commit, $leaf);
if ( $hash_object =~ /^$hash/ ) {
push @$commits, $commit_log;
last if !$all;
}
}
return $commits;
}
sub git_hash_object {
my ($self, $file) = @_;
my @git_hash_object = qw/git hash-object/;
open my $git, '-|', "@git_hash_object $file";
my $hash = <$git>;
chomp $hash;
close $git;
return $hash;
}
sub git_log {
my ($self, $file) = @_;
my @git_log = qw/git log --all --oneline/;
my $dir = File::Spec->curdir();
chdir $self->{git_repo};
open my $git, "-|", "@git_log -- $file";
my $commit_logs = [];
while (my $line = <$git> ) {
chomp $line;
push @$commit_logs, $line;
}
close $git;
chdir $dir;
return $commit_logs;
}
sub git_ls_tree {
my ($self, $commit, $file) = @_;
my @git_ls_tree = qw/git ls-tree/;
my $dir = File::Spec->curdir();
chdir $self->{git_repo};
open my $git, "-|", "@git_ls_tree $commit -- $file";
my $line = <$git>;
chomp $line;
my ($mode, $type, $hash, $object) = split /\s+/, $line, 4;
close $git;
chdir $dir;
return $hash;
}
1;
__END__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment