diff options
author | Arne Georg Gleditsch <argggh@lxr.linpro.no> | 2007-07-05 00:51:08 +0200 |
---|---|---|
committer | Arne Georg Gleditsch <argggh@lxr.linpro.no> | 2007-07-05 00:51:08 +0200 |
commit | e9fa4c98bb5f084739d3418ade3f0c51e34a0aa1 (patch) | |
tree | fec1d635625e031cde7cba1b0a1d95ee92ac760b /lib/LXRng/Repo/Git.pm |
Rebase tree.
Diffstat (limited to 'lib/LXRng/Repo/Git.pm')
-rw-r--r-- | lib/LXRng/Repo/Git.pm | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/lib/LXRng/Repo/Git.pm b/lib/LXRng/Repo/Git.pm new file mode 100644 index 0000000..2d6ea33 --- /dev/null +++ b/lib/LXRng/Repo/Git.pm @@ -0,0 +1,111 @@ +package LXRng::Repo::Git; + +use strict; +use Memoize; +use LXRng::Cached; +use LXRng::Repo::Git::Iterator; +use LXRng::Repo::Git::File; +use LXRng::Repo::Git::Directory; + +sub _git_cmd { + my ($self, $cmd, @args) = @_; + + my $git; + my $pid = open($git, "-|"); + die $! unless defined $pid; + if ($pid == 0) { + $ENV{'GIT_DIR'} = $$self{'root'}; + exec('git', $cmd, @args); + warn $!; + kill(9, $$); + } + return $git; +} + +sub new { + my ($class, $root, %args) = @_; + + memoize('_release_timestamp'); + + return bless({root => $root, %args}, $class); +} + +sub _release_timestamp { + my ($self, $release) = @_; + + my $cinfo = $self->_git_cmd('cat-file', 'commit', $release); + + my $time; + while (<$cinfo>) { + $time = $1 if /^author .*? (\d+(?: [-+]\d+|))$/ ; + $time ||= $1 if /^committer .*? (\d+(?: [-+]\d+|))$/ ; + } + + return $time; +} + +sub _use_author_timestamp { + my ($self) = @_; + + return $$self{'author_timestamp'}; +} + +sub _sort_key { + my ($v) = @_; + + $v =~ s/(\d+)/sprintf("%05d", $1)/ge; + return $v; +} + +sub allversions { + my ($self) = @_; + + cached { + my @tags; + my $tags = $self->_git_cmd('tag', '-l'); + while (<$tags>) { + chomp; + next if $$self{'release_re'} and $_ !~ $$self{'release_re'}; + push(@tags, $_); + } + + return (sort {_sort_key($b) cmp _sort_key($a) } @tags); + }; +} + +sub node { + my ($self, $path, $release) = @_; + + $path =~ s,^/+,,; + $path =~ s,/+$,,; + + if ($path eq '') { + open(my $tag, '<', $$self{'root'}.'/refs/tags/'.$release) + or return undef; + my $ref = <$tag>; + close($tag); + chomp($ref); + return LXRng::Repo::Git::Directory->new($self, '', $ref); + } + + my $git = $self->_git_cmd('ls-tree', $release, $path); + my ($mode, $type, $ref, $gitpath) = split(" ", <$git>); + + if ($type eq 'tree') { + return LXRng::Repo::Git::Directory->new($self, $path, $ref, $release); + } + elsif ($type eq 'blob') { + return LXRng::Repo::Git::File->new($self, $path, $ref, $release); + } + else { + return undef; + } +} + +sub iterator { + my ($self, $release) = @_; + + return LXRng::Repo::Git::Iterator->new($self, $release); +} + +1; |