line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Git::PurePerl::Pack::WithoutIndex; |
2
|
4
|
|
|
4
|
|
16
|
use Moose; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
25
|
|
3
|
4
|
|
|
4
|
|
16445
|
use MooseX::StrictConstructor; |
|
4
|
|
|
|
|
4
|
|
|
4
|
|
|
|
|
29
|
|
4
|
4
|
|
|
4
|
|
7756
|
use namespace::autoclean; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
26
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
extends 'Git::PurePerl::Pack'; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
has 'offsets' => ( is => 'rw', isa => 'HashRef', required => 0 ); |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
my @TYPES = ( 'none', 'commit', 'tree', 'blob', 'tag', '', 'ofs_delta', |
11
|
|
|
|
|
|
|
'ref_delta' ); |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
sub create_index { |
14
|
1
|
|
|
1
|
0
|
3
|
my ($self) = @_; |
15
|
1
|
|
|
|
|
33
|
my $index_filename = $self->filename; |
16
|
1
|
|
|
|
|
4
|
$index_filename =~ s/\.pack/.idx/; |
17
|
1
|
|
50
|
|
|
47
|
my $index_fh = IO::File->new("> $index_filename") || die $!; |
18
|
|
|
|
|
|
|
|
19
|
1
|
|
|
|
|
130
|
my $iod = IO::Digest->new( $index_fh, 'SHA' ); |
20
|
|
|
|
|
|
|
|
21
|
1
|
|
|
|
|
3397
|
my $offsets = $self->create_index_offsets; |
22
|
1
|
|
|
|
|
2
|
my @fan_out_table; |
23
|
1
|
|
|
|
|
343
|
foreach my $sha1 ( sort keys %$offsets ) { |
24
|
752
|
|
|
|
|
499
|
my $offset = $offsets->{$sha1}; |
25
|
752
|
|
|
|
|
811
|
my $slot = unpack( 'C', pack( 'H*', $sha1 ) ); |
26
|
752
|
|
|
|
|
517
|
$fan_out_table[$slot]++; |
27
|
|
|
|
|
|
|
} |
28
|
1
|
|
|
|
|
20
|
foreach my $i ( 0 .. 255 ) { |
29
|
256
|
50
|
50
|
|
|
710
|
$index_fh->print( pack( 'N', $fan_out_table[$i] || 0 ) ) || die $!; |
30
|
256
|
|
50
|
|
|
7637
|
$fan_out_table[ $i + 1 ] += $fan_out_table[$i] || 0; |
31
|
|
|
|
|
|
|
} |
32
|
1
|
|
|
|
|
285
|
foreach my $sha1 ( sort keys %$offsets ) { |
33
|
752
|
|
|
|
|
21482
|
my $offset = $offsets->{$sha1}; |
34
|
752
|
50
|
|
|
|
1686
|
$index_fh->print( pack( 'N', $offset ) ) || die $!; |
35
|
752
|
50
|
|
|
|
22139
|
$index_fh->print( pack( 'H*', $sha1 ) ) || die $!; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# read the pack checksum from the end of the pack file |
39
|
1
|
|
|
|
|
151
|
my $size = -s $self->filename; |
40
|
1
|
|
|
|
|
159
|
my $fh = $self->fh; |
41
|
1
|
50
|
|
|
|
8
|
$fh->seek( $size - 20, 0 ) || die $!; |
42
|
1
|
|
50
|
|
|
18
|
my $read = $fh->read( my $pack_sha1, 20 ) || die $!; |
43
|
|
|
|
|
|
|
|
44
|
1
|
50
|
|
|
|
21
|
$index_fh->print($pack_sha1) || die $!; |
45
|
1
|
50
|
|
|
|
51
|
$index_fh->print( $iod->digest ) || die $!; |
46
|
|
|
|
|
|
|
|
47
|
1
|
50
|
|
|
|
34
|
$index_fh->close() || die $!; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub create_index_offsets { |
51
|
1
|
|
|
1
|
0
|
2
|
my ($self) = @_; |
52
|
1
|
|
|
|
|
36
|
my $fh = $self->fh; |
53
|
|
|
|
|
|
|
|
54
|
1
|
|
|
|
|
7
|
$fh->read( my $signature, 4 ); |
55
|
1
|
|
|
|
|
12
|
$fh->read( my $version, 4 ); |
56
|
1
|
|
|
|
|
8
|
$version = unpack( 'N', $version ); |
57
|
1
|
|
|
|
|
3
|
$fh->read( my $objects, 4 ); |
58
|
1
|
|
|
|
|
3
|
$objects = unpack( 'N', $objects ); |
59
|
|
|
|
|
|
|
|
60
|
1
|
|
|
|
|
2
|
my %offsets; |
61
|
1
|
|
|
|
|
31
|
$self->offsets( \%offsets ); |
62
|
|
|
|
|
|
|
|
63
|
1
|
|
|
|
|
3
|
foreach my $i ( 1 .. $objects ) { |
64
|
752
|
|
50
|
|
|
1656
|
my $offset = $fh->tell || die "Error telling filehandle: $!"; |
65
|
752
|
|
|
|
|
2926
|
my $obj_offset = $offset; |
66
|
752
|
50
|
|
|
|
1238
|
$fh->read( my $c, 1 ) || die "Error reading from pack: $!"; |
67
|
752
|
|
50
|
|
|
6326
|
$c = unpack( 'C', $c ) || die $!; |
68
|
752
|
|
|
|
|
600
|
$offset++; |
69
|
|
|
|
|
|
|
|
70
|
752
|
|
|
|
|
741
|
my $size = ( $c & 0xf ); |
71
|
752
|
|
|
|
|
734
|
my $type_number = ( $c >> 4 ) & 7; |
72
|
752
|
|
33
|
|
|
1378
|
my $type = $TYPES[$type_number] |
73
|
|
|
|
|
|
|
|| confess |
74
|
|
|
|
|
|
|
"invalid type $type_number at offset $offset, size $size"; |
75
|
|
|
|
|
|
|
|
76
|
752
|
|
|
|
|
634
|
my $shift = 4; |
77
|
|
|
|
|
|
|
|
78
|
752
|
|
|
|
|
1364
|
while ( ( $c & 0x80 ) != 0 ) { |
79
|
676
|
50
|
|
|
|
1038
|
$fh->read( $c, 1 ) || die $!; |
80
|
676
|
|
50
|
|
|
3163
|
$c = unpack( 'C', $c ) || die $!; |
81
|
676
|
|
|
|
|
516
|
$offset++; |
82
|
676
|
|
|
|
|
664
|
$size |= ( ( $c & 0x7f ) << $shift ); |
83
|
676
|
|
|
|
|
1159
|
$shift += 7; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
752
|
|
|
|
|
481
|
my $content; |
87
|
|
|
|
|
|
|
|
88
|
752
|
100
|
66
|
|
|
3971
|
if ( $type eq 'ofs_delta' || $type eq 'ref_delta' ) { |
|
|
50
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
89
|
375
|
|
|
|
|
1027
|
( $type, $size, $content ) |
90
|
|
|
|
|
|
|
= $self->unpack_deltified( $type, $offset, $obj_offset, $size, |
91
|
|
|
|
|
|
|
\%offsets ); |
92
|
|
|
|
|
|
|
} elsif ( $type eq 'commit' |
93
|
|
|
|
|
|
|
|| $type eq 'tree' |
94
|
|
|
|
|
|
|
|| $type eq 'blob' |
95
|
|
|
|
|
|
|
|| $type eq 'tag' ) |
96
|
|
|
|
|
|
|
{ |
97
|
377
|
|
|
|
|
765
|
$content = $self->read_compressed( $offset, $size ); |
98
|
|
|
|
|
|
|
} else { |
99
|
0
|
|
|
|
|
0
|
confess "invalid type $type"; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
752
|
|
|
|
|
2210
|
my $raw = $type . ' ' . $size . "\0" . $content; |
103
|
752
|
|
|
|
|
2070
|
my $sha1 = Digest::SHA->new; |
104
|
752
|
|
|
|
|
11594
|
$sha1->add($raw); |
105
|
752
|
|
|
|
|
2429
|
my $sha1_hex = $sha1->hexdigest; |
106
|
752
|
|
|
|
|
2987
|
$offsets{$sha1_hex} = $obj_offset; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
1
|
|
|
|
|
3
|
return \%offsets; |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub get_object { |
113
|
1484
|
|
|
1484
|
0
|
1387
|
my ( $self, $want_sha1 ) = @_; |
114
|
1484
|
|
|
|
|
39204
|
my $offset = $self->offsets->{$want_sha1}; |
115
|
1484
|
50
|
|
|
|
2029
|
return unless $offset; |
116
|
1484
|
|
|
|
|
2865
|
return $self->unpack_object($offset); |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
120
|
|
|
|
|
|
|
|