| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Cogit::Pack::WithoutIndex; |
|
2
|
|
|
|
|
|
|
$Cogit::Pack::WithoutIndex::VERSION = '0.001001'; |
|
3
|
4
|
|
|
4
|
|
18
|
use Moo; |
|
|
4
|
|
|
|
|
3
|
|
|
|
4
|
|
|
|
|
23
|
|
|
4
|
4
|
|
|
4
|
|
9321
|
use IO::Digest; |
|
|
4
|
|
|
|
|
9445
|
|
|
|
4
|
|
|
|
|
102
|
|
|
5
|
4
|
|
|
4
|
|
22
|
use MooX::Types::MooseLike::Base 'HashRef'; |
|
|
4
|
|
|
|
|
7
|
|
|
|
4
|
|
|
|
|
177
|
|
|
6
|
4
|
|
|
4
|
|
16
|
use Carp 'confess'; |
|
|
4
|
|
|
|
|
4
|
|
|
|
4
|
|
|
|
|
139
|
|
|
7
|
4
|
|
|
4
|
|
17
|
use namespace::clean; |
|
|
4
|
|
|
|
|
5
|
|
|
|
4
|
|
|
|
|
31
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
extends 'Cogit::Pack'; |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
has offsets => ( |
|
12
|
|
|
|
|
|
|
is => 'rw', |
|
13
|
|
|
|
|
|
|
isa => HashRef, |
|
14
|
|
|
|
|
|
|
); |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
my @TYPES = (qw(none commit tree blob tag), '', 'ofs_delta', 'ref_delta' ); |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub create_index { |
|
19
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
|
20
|
0
|
|
|
|
|
|
my $index_filename = $self->filename; |
|
21
|
0
|
|
|
|
|
|
$index_filename =~ s/\.pack/.idx/; |
|
22
|
0
|
|
0
|
|
|
|
my $index_fh = IO::File->new("> $index_filename") || die $!; |
|
23
|
|
|
|
|
|
|
|
|
24
|
0
|
|
|
|
|
|
my $iod = IO::Digest->new( $index_fh, 'SHA' ); |
|
25
|
|
|
|
|
|
|
|
|
26
|
0
|
|
|
|
|
|
my $offsets = $self->create_index_offsets; |
|
27
|
0
|
|
|
|
|
|
my @fan_out_table; |
|
28
|
0
|
|
|
|
|
|
for my $sha1 ( sort keys %$offsets ) { |
|
29
|
0
|
|
|
|
|
|
my $offset = $offsets->{$sha1}; |
|
30
|
0
|
|
|
|
|
|
my $slot = unpack( 'C', pack( 'H*', $sha1 ) ); |
|
31
|
0
|
|
|
|
|
|
$fan_out_table[$slot]++; |
|
32
|
|
|
|
|
|
|
} |
|
33
|
0
|
|
|
|
|
|
for my $i ( 0 .. 255 ) { |
|
34
|
0
|
0
|
0
|
|
|
|
$index_fh->print( pack( 'N', $fan_out_table[$i] || 0 ) ) || die $!; |
|
35
|
0
|
|
0
|
|
|
|
$fan_out_table[ $i + 1 ] += $fan_out_table[$i] || 0; |
|
36
|
|
|
|
|
|
|
} |
|
37
|
0
|
|
|
|
|
|
for my $sha1 ( sort keys %$offsets ) { |
|
38
|
0
|
|
|
|
|
|
my $offset = $offsets->{$sha1}; |
|
39
|
0
|
0
|
|
|
|
|
$index_fh->print( pack( 'N', $offset ) ) || die $!; |
|
40
|
0
|
0
|
|
|
|
|
$index_fh->print( pack( 'H*', $sha1 ) ) || die $!; |
|
41
|
|
|
|
|
|
|
} |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# read the pack checksum from the end of the pack file |
|
44
|
0
|
|
|
|
|
|
my $size = -s $self->filename; |
|
45
|
0
|
|
|
|
|
|
my $fh = $self->fh; |
|
46
|
0
|
0
|
|
|
|
|
$fh->seek( $size - 20, 0 ) || die $!; |
|
47
|
0
|
|
0
|
|
|
|
my $read = $fh->read( my $pack_sha1, 20 ) || die $!; |
|
48
|
|
|
|
|
|
|
|
|
49
|
0
|
0
|
|
|
|
|
$index_fh->print($pack_sha1) || die $!; |
|
50
|
0
|
0
|
|
|
|
|
$index_fh->print( $iod->digest ) || die $!; |
|
51
|
|
|
|
|
|
|
|
|
52
|
0
|
0
|
|
|
|
|
$index_fh->close() || die $!; |
|
53
|
|
|
|
|
|
|
} |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub create_index_offsets { |
|
56
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
|
57
|
0
|
|
|
|
|
|
my $fh = $self->fh; |
|
58
|
|
|
|
|
|
|
|
|
59
|
0
|
|
|
|
|
|
$fh->read( my $signature, 4 ); |
|
60
|
0
|
|
|
|
|
|
$fh->read( my $version, 4 ); |
|
61
|
0
|
|
|
|
|
|
$version = unpack( 'N', $version ); |
|
62
|
0
|
|
|
|
|
|
$fh->read( my $objects, 4 ); |
|
63
|
0
|
|
|
|
|
|
$objects = unpack( 'N', $objects ); |
|
64
|
|
|
|
|
|
|
|
|
65
|
0
|
|
|
|
|
|
my %offsets; |
|
66
|
0
|
|
|
|
|
|
$self->offsets( \%offsets ); |
|
67
|
|
|
|
|
|
|
|
|
68
|
0
|
|
|
|
|
|
for my $i ( 1 .. $objects ) { |
|
69
|
0
|
|
0
|
|
|
|
my $offset = $fh->tell || die "Error telling filehandle: $!"; |
|
70
|
0
|
|
|
|
|
|
my $obj_offset = $offset; |
|
71
|
0
|
0
|
|
|
|
|
$fh->read( my $c, 1 ) || die "Error reading from pack: $!"; |
|
72
|
0
|
|
0
|
|
|
|
$c = unpack( 'C', $c ) || die $!; |
|
73
|
0
|
|
|
|
|
|
$offset++; |
|
74
|
|
|
|
|
|
|
|
|
75
|
0
|
|
|
|
|
|
my $size = ( $c & 0xf ); |
|
76
|
0
|
|
|
|
|
|
my $type_number = ( $c >> 4 ) & 7; |
|
77
|
0
|
|
0
|
|
|
|
my $type = $TYPES[$type_number] |
|
78
|
|
|
|
|
|
|
|| confess |
|
79
|
|
|
|
|
|
|
"invalid type $type_number at offset $offset, size $size"; |
|
80
|
|
|
|
|
|
|
|
|
81
|
0
|
|
|
|
|
|
my $shift = 4; |
|
82
|
|
|
|
|
|
|
|
|
83
|
0
|
|
|
|
|
|
while ( ( $c & 0x80 ) != 0 ) { |
|
84
|
0
|
0
|
|
|
|
|
$fh->read( $c, 1 ) || die $!; |
|
85
|
0
|
|
0
|
|
|
|
$c = unpack( 'C', $c ) || die $!; |
|
86
|
0
|
|
|
|
|
|
$offset++; |
|
87
|
0
|
|
|
|
|
|
$size |= ( ( $c & 0x7f ) << $shift ); |
|
88
|
0
|
|
|
|
|
|
$shift += 7; |
|
89
|
|
|
|
|
|
|
} |
|
90
|
|
|
|
|
|
|
|
|
91
|
0
|
|
|
|
|
|
my $content; |
|
92
|
|
|
|
|
|
|
|
|
93
|
0
|
0
|
0
|
|
|
|
if ( $type eq 'ofs_delta' || $type eq 'ref_delta' ) { |
|
|
|
0
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
94
|
0
|
|
|
|
|
|
( $type, $size, $content ) |
|
95
|
|
|
|
|
|
|
= $self->unpack_deltified( $type, $offset, $obj_offset, $size, |
|
96
|
|
|
|
|
|
|
\%offsets ); |
|
97
|
|
|
|
|
|
|
} elsif ( $type eq 'commit' |
|
98
|
|
|
|
|
|
|
|| $type eq 'tree' |
|
99
|
|
|
|
|
|
|
|| $type eq 'blob' |
|
100
|
|
|
|
|
|
|
|| $type eq 'tag' ) |
|
101
|
|
|
|
|
|
|
{ |
|
102
|
0
|
|
|
|
|
|
$content = $self->read_compressed( $offset, $size ); |
|
103
|
|
|
|
|
|
|
} else { |
|
104
|
0
|
|
|
|
|
|
confess "invalid type $type"; |
|
105
|
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
|
my $raw = $type . ' ' . $size . "\0" . $content; |
|
108
|
0
|
|
|
|
|
|
my $sha1 = Digest::SHA->new; |
|
109
|
0
|
|
|
|
|
|
$sha1->add($raw); |
|
110
|
0
|
|
|
|
|
|
my $sha1_hex = $sha1->hexdigest; |
|
111
|
0
|
|
|
|
|
|
$offsets{$sha1_hex} = $obj_offset; |
|
112
|
|
|
|
|
|
|
} |
|
113
|
|
|
|
|
|
|
|
|
114
|
0
|
|
|
|
|
|
return \%offsets; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub get_object { |
|
118
|
0
|
|
|
0
|
0
|
|
my ( $self, $want_sha1 ) = @_; |
|
119
|
0
|
|
|
|
|
|
my $offset = $self->offsets->{$want_sha1}; |
|
120
|
0
|
0
|
|
|
|
|
return unless $offset; |
|
121
|
0
|
|
|
|
|
|
return $self->unpack_object($offset); |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
1; |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
__END__ |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=pod |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=encoding UTF-8 |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=head1 NAME |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
Cogit::Pack::WithoutIndex |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head1 VERSION |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
version 0.001001 |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=head1 AUTHOR |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Arthur Axel "fREW" Schmidt <cogit@afoolishmanifesto.com> |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
This software is copyright (c) 2017 by Arthur Axel "fREW" Schmidt. |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
|
149
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=cut |