1package Git::PurePerl::PackIndex::Version2; 2use Moose; 3use MooseX::StrictConstructor; 4use namespace::autoclean; 5 6extends 'Git::PurePerl::PackIndex'; 7 8my $FanOutCount = 256; 9my $SHA1Size = 20; 10my $IdxOffsetSize = 4; 11my $OffsetSize = 4; 12my $CrcSize = 4; 13my $OffsetStart = $FanOutCount * $IdxOffsetSize; 14my $SHA1Start = $OffsetStart + $OffsetSize; 15my $EntrySize = $OffsetSize + $SHA1Size; 16my $EntrySizeV2 = $SHA1Size + $CrcSize + $OffsetSize; 17 18sub global_offset { 19 return 8; 20} 21 22sub all_sha1s { 23 my ( $self, $want_sha1 ) = @_; 24 my $fh = $self->fh; 25 my @sha1s; 26 my @data; 27 28 my $pos = $OffsetStart; 29 $fh->seek( $pos + $self->global_offset, 0 ) || die $!; 30 foreach my $i ( 0 .. $self->size - 1 ) { 31 $fh->read( my $sha1, $SHA1Size ) || die $!; 32 $data[$i] = [ unpack( 'H*', $sha1 ), 0, 0 ]; 33 $pos += $SHA1Size; 34 } 35 $fh->seek( $pos + $self->global_offset, 0 ) || die $!; 36 foreach my $i ( 0 .. $self->size - 1 ) { 37 $fh->read( my $crc, $CrcSize ) || die $!; 38 $data[$i]->[1] = unpack( 'H*', $crc ); 39 $pos += $CrcSize; 40 } 41 $fh->seek( $pos + $self->global_offset, 0 ) || die $!; 42 foreach my $i ( 0 .. $self->size - 1 ) { 43 $fh->read( my $offset, $OffsetSize ) || die $!; 44 $data[$i]->[2] = unpack( 'N', $offset ); 45 $pos += $OffsetSize; 46 } 47 foreach my $data (@data) { 48 my ( $sha1, $crc, $offset ) = @$data; 49 push @sha1s, $sha1; 50 } 51 52 return @sha1s; 53} 54 55sub get_object_offset { 56 my ( $self, $want_sha1 ) = @_; 57 my @offsets = $self->offsets; 58 my $fh = $self->fh; 59 60 my $slot = unpack( 'C', pack( 'H*', $want_sha1 ) ); 61 return unless defined $slot; 62 63 my ( $first, $last ) = @offsets[ $slot, $slot + 1 ]; 64 65 while ( $first < $last ) { 66 my $mid = int( ( $first + $last ) / 2 ); 67 68 $fh->seek( $self->global_offset + $OffsetStart + ( $mid * $SHA1Size ), 69 0 ) 70 || die $!; 71 $fh->read( my $data, $SHA1Size ) || die $!; 72 my $midsha1 = unpack( 'H*', $data ); 73 if ( $midsha1 lt $want_sha1 ) { 74 $first = $mid + 1; 75 } elsif ( $midsha1 gt $want_sha1 ) { 76 $last = $mid; 77 } else { 78 my $pos 79 = $self->global_offset 80 + $OffsetStart 81 + ( $self->size * ( $SHA1Size + $CrcSize ) ) 82 + ( $mid * $OffsetSize ); 83 $fh->seek( $pos, 0 ) || die $!; 84 $fh->read( my $data, $OffsetSize ) || die $!; 85 my $offset = unpack( 'N', $data ); 86 return $offset; 87 } 88 } 89 return; 90} 91 92__PACKAGE__->meta->make_immutable; 93 94