2 package VCS
::Git
::Torrent
::PWP
::Message
::Play
;
6 VCS::Git::Torrent::PWP::Message::Play
10 Implements the Play message from the RFC.
11 L<http://gittorrent.utsl.gen.nz/rfc.html#pwp-play>
15 use IO
::Plumbing
qw(hose vent);
17 with
"VCS::Git::Torrent::PWP::Message";
19 use VCS
::Git
::Torrent
::PWP
qw(:pwp_constants unpack_hex pack_hex pack_num unpack_num);
33 has
'reel_sha1_pair' =>
41 $payload .= join('', map { pack_hex
($_ ) } @
{ $self->reel_sha1_pair });
42 $payload .= pack_num
($self->offset);
43 $payload .= pack_num
($self->data_len) if ( $self->data_len );
44 $payload .= $self->data if ( $self->data );
53 my @sha1_pair = map { unpack_hex
($_) } (
54 substr($payload, 0, 20),
55 substr($payload, 20, 20)
57 $self->reel_sha1_pair(\
@sha1_pair);
59 my $offset = unpack_num
(substr($payload, 40, 4));
60 $self->offset($offset);
62 if ( length($payload) > 44 ) {
63 my $data_len = unpack_num
(substr($payload, 44, 4));
64 $self->data_len($data_len);
66 my $data = substr($payload, 48, $data_len);
76 if ( ref($_[0]) eq 'VCS::Git::Torrent::CommitReel' ) {
78 $reel_sha1_pair = $reel->reel_id;
81 $reel_sha1_pair = [ shift, shift ];
90 $args{'data'} = $data if ( $data );
91 $args{'data_len'} = $data_len if ( $data_len );
92 $args{'offset'} = $offset;
93 $args{'reel_sha1_pair'} = $reel_sha1_pair;
100 my $local_peer = shift;
101 my $connection = shift;
103 my ($start, $end) = @
{ $self->reel_sha1_pair };
105 if ( $self->data_len && $self->data ) { # we got data
108 my $unpack = $local_peer->torrent->plumb(
109 [ 'unpack-objects', '-q' ],
115 $hose->print($self->data);
119 my $pack_name = $local_peer->torrent->state_dir .
120 '/commit-' . $self->offset . '.pack';
121 open(PACK
, '>', $pack_name)
122 || die 'failed to save pack file';
123 syswrite PACK
, $self->data, $self->data_len;
126 else { # it was a request for data
129 foreach( @
{ $local_peer->torrent->reels } ) {
133 $reel->reel_id->[0] eq $start &&
134 $reel->reel_id->[1] eq $end
139 my $commit = $reel->commit_info->[$self->offset];
142 my $pack_name = $local_peer->torrent->state_dir .
143 '/commit-' . $commit->{'objectid'} . '.pack';
144 my $alt_pack_name = $local_peer->torrent->state_dir .
145 '/commit-' . $self->offset . '.pack';
147 if ( -e
$pack_name ) {
148 open(PACK
, '<', $pack_name)
149 || die 'failed to open pack file';
150 read PACK
, $pack, -s
$pack_name;
152 } elsif ( -e
$alt_pack_name ) {
153 open(PACK
, '<', $alt_pack_name)
154 || die 'failed to open pack file';
155 read PACK
, $pack, -s
$alt_pack_name;
159 $commit->{'parents'} &&
160 scalar(@
{ $commit->{'parents'} })
163 } @
{ $commit->{'parents'} }
167 my @cmd = ( 'rev-list', '--objects-edge' );
168 push @cmd, @parents if ( @parents );
169 push @cmd, ( $commit->{'objectid'} );
171 my $rev_list = $local_peer->torrent->plumb(
176 $rev_list->output($local_peer->torrent->plumb(
177 [ 'pack-objects', '--stdout', '-q' ],
181 $pack = $rev_list->terminus->contents;
183 open(PACK
, '>', $pack_name)
184 || die 'failed to save pack data';
185 syswrite PACK
, $pack;
189 $local_peer->send_message(
190 $connection->remote, GTP_PWP_PLAY
,
191 $start, $end, $self->offset,
193 ) if ( length($pack) );