133 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
			
		
		
	
	
			133 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
| #!/usr/bin/perl
 | |
| #
 | |
| # Example implementation for the Git filter protocol version 2
 | |
| # See Documentation/gitattributes.txt, section "Filter Protocol"
 | |
| #
 | |
| # Please note, this pass-thru filter is a minimal skeleton. No proper
 | |
| # error handling was implemented.
 | |
| #
 | |
| 
 | |
| use strict;
 | |
| use warnings;
 | |
| 
 | |
| my $MAX_PACKET_CONTENT_SIZE = 65516;
 | |
| 
 | |
| sub packet_bin_read {
 | |
| 	my $buffer;
 | |
| 	my $bytes_read = read STDIN, $buffer, 4;
 | |
| 	if ( $bytes_read == 0 ) {
 | |
| 
 | |
| 		# EOF - Git stopped talking to us!
 | |
| 		exit();
 | |
| 	}
 | |
| 	elsif ( $bytes_read != 4 ) {
 | |
| 		die "invalid packet: '$buffer'";
 | |
| 	}
 | |
| 	my $pkt_size = hex($buffer);
 | |
| 	if ( $pkt_size == 0 ) {
 | |
| 		return ( 1, "" );
 | |
| 	}
 | |
| 	elsif ( $pkt_size > 4 ) {
 | |
| 		my $content_size = $pkt_size - 4;
 | |
| 		$bytes_read = read STDIN, $buffer, $content_size;
 | |
| 		if ( $bytes_read != $content_size ) {
 | |
| 			die "invalid packet ($content_size bytes expected; $bytes_read bytes read)";
 | |
| 		}
 | |
| 		return ( 0, $buffer );
 | |
| 	}
 | |
| 	else {
 | |
| 		die "invalid packet size: $pkt_size";
 | |
| 	}
 | |
| }
 | |
| 
 | |
| sub packet_txt_read {
 | |
| 	my ( $res, $buf ) = packet_bin_read();
 | |
| 	unless ( $buf =~ s/\n$// ) {
 | |
| 		die "A non-binary line MUST be terminated by an LF.";
 | |
| 	}
 | |
| 	return ( $res, $buf );
 | |
| }
 | |
| 
 | |
| sub packet_bin_write {
 | |
| 	my $buf = shift;
 | |
| 	print STDOUT sprintf( "%04x", length($buf) + 4 );
 | |
| 	print STDOUT $buf;
 | |
| 	STDOUT->flush();
 | |
| }
 | |
| 
 | |
| sub packet_txt_write {
 | |
| 	packet_bin_write( $_[0] . "\n" );
 | |
| }
 | |
| 
 | |
| sub packet_flush {
 | |
| 	print STDOUT sprintf( "%04x", 0 );
 | |
| 	STDOUT->flush();
 | |
| }
 | |
| 
 | |
| ( packet_txt_read() eq ( 0, "git-filter-client" ) ) || die "bad initialize";
 | |
| ( packet_txt_read() eq ( 0, "version=2" ) )         || die "bad version";
 | |
| ( packet_bin_read() eq ( 1, "" ) )                  || die "bad version end";
 | |
| 
 | |
| packet_txt_write("git-filter-server");
 | |
| packet_txt_write("version=2");
 | |
| packet_flush();
 | |
| 
 | |
| ( packet_txt_read() eq ( 0, "capability=clean" ) )  || die "bad capability";
 | |
| ( packet_txt_read() eq ( 0, "capability=smudge" ) ) || die "bad capability";
 | |
| ( packet_bin_read() eq ( 1, "" ) )                  || die "bad capability end";
 | |
| 
 | |
| packet_txt_write("capability=clean");
 | |
| packet_txt_write("capability=smudge");
 | |
| packet_flush();
 | |
| 
 | |
| while (1) {
 | |
| 	my ($command)  = packet_txt_read() =~ /^command=(.+)$/;
 | |
| 	my ($pathname) = packet_txt_read() =~ /^pathname=(.+)$/;
 | |
| 
 | |
| 	if ( $pathname eq "" ) {
 | |
| 		die "bad pathname '$pathname'";
 | |
| 	}
 | |
| 
 | |
| 	packet_bin_read();
 | |
| 
 | |
| 	my $input = "";
 | |
| 	{
 | |
| 		binmode(STDIN);
 | |
| 		my $buffer;
 | |
| 		my $done = 0;
 | |
| 		while ( !$done ) {
 | |
| 			( $done, $buffer ) = packet_bin_read();
 | |
| 			$input .= $buffer;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	my $output;
 | |
| 	if ( $command eq "clean" ) {
 | |
| 		### Perform clean here ###
 | |
| 		$output = $input;
 | |
| 	}
 | |
| 	elsif ( $command eq "smudge" ) {
 | |
| 		### Perform smudge here ###
 | |
| 		$output = $input;
 | |
| 	}
 | |
| 	else {
 | |
| 		die "bad command '$command'";
 | |
| 	}
 | |
| 
 | |
| 	packet_txt_write("status=success");
 | |
| 	packet_flush();
 | |
| 	while ( length($output) > 0 ) {
 | |
| 		my $packet = substr( $output, 0, $MAX_PACKET_CONTENT_SIZE );
 | |
| 		packet_bin_write($packet);
 | |
| 		if ( length($output) > $MAX_PACKET_CONTENT_SIZE ) {
 | |
| 			$output = substr( $output, $MAX_PACKET_CONTENT_SIZE );
 | |
| 		}
 | |
| 		else {
 | |
| 			$output = "";
 | |
| 		}
 | |
| 	}
 | |
| 	packet_flush();    # flush content!
 | |
| 	packet_flush();    # empty list, keep "status=success" unchanged!
 | |
| 
 | |
| }
 |