1 package Git::PurePerl::Protocol;
3 use MooseX::StrictConstructor;
4 use Moose::Util::TypeConstraints;
5 use namespace::autoclean;
7 has 'hostname' => ( is => 'ro', isa => 'Str', required => 1 );
8 has 'port' => ( is => 'ro', isa => 'Int', required => 0, default => 9418 );
9 has 'project' => ( is => 'ro', isa => 'Str', required => 1 );
10 has 'socket' => ( is => 'rw', isa => 'IO::Socket', required => 0 );
15 my $socket = IO::Socket::INET->new(
16 PeerAddr => $self->hostname,
17 PeerPort => $self->port,
19 ) || die $! . ' ' . $self->hostname . ':' . $self->port;
20 $socket->autoflush(1) || die $!;
21 $self->socket($socket);
23 $self->send_line( "git-upload-pack "
30 while ( my $line = $self->read_line() ) {
33 my ( $sha1, $name ) = $line =~ /^([a-z0-9]+) ([^\0\n]+)/;
35 #use YAML; warn Dump $line;
36 $sha1s{$name} = $sha1;
42 my ( $self, $sha1 ) = @_;
43 $self->send_line("want $sha1 side-band-64k\n");
46 # "want 0c7b3d23c0f821e58cd20e60d5e63f5ed12ef391 multi_ack side-band-64k ofs-delta\n"
49 $self->send_line('done');
53 while ( my $line = $self->read_line() ) {
54 if ( $line =~ s/^\x02// ) {
56 } elsif ( $line =~ /^NAK\n/ ) {
57 } elsif ( $line =~ s/^\x01// ) {
60 die "Unknown line: $line";
69 my ( $self, $line ) = @_;
70 my $length = length($line);
76 #warn "length $length";
77 my $prefix = sprintf( "%04X", $length );
78 my $text = $prefix . $line;
81 $self->socket->print($text) || die $!;
86 my $socket = $self->socket;
88 my $ret = $socket->read( my $prefix, 4 );
89 if ( not defined $ret ) {
91 } elsif ( $ret == 0 ) {
95 return if $prefix eq '0000';
97 # warn "read prefix [$prefix]";
100 foreach my $n ( 0 .. 3 ) {
101 my $c = substr( $prefix, $n, 1 );
104 if ( $c ge '0' && $c le '9' ) {
105 $len += ord($c) - ord('0');
106 } elsif ( $c ge 'a' && $c le 'f' ) {
107 $len += ord($c) - ord('a') + 10;
108 } elsif ( $c ge 'A' && $c le 'F' ) {
109 $len += ord($c) - ord('A') + 10;
114 $socket->read( my $data, $len - 4 ) || die $!;
118 __PACKAGE__->meta->make_immutable;