contrib / long-running-filter / example.plon commit Merge branch 'master' of https://github.com/Softcatala/git-po (63d919d)
   1#!/usr/bin/perl
   2#
   3# Example implementation for the Git filter protocol version 2
   4# See Documentation/gitattributes.txt, section "Filter Protocol"
   5#
   6# Please note, this pass-thru filter is a minimal skeleton. No proper
   7# error handling was implemented.
   8#
   9
  10use strict;
  11use warnings;
  12
  13my $MAX_PACKET_CONTENT_SIZE = 65516;
  14
  15sub packet_bin_read {
  16        my $buffer;
  17        my $bytes_read = read STDIN, $buffer, 4;
  18        if ( $bytes_read == 0 ) {
  19
  20                # EOF - Git stopped talking to us!
  21                exit();
  22        }
  23        elsif ( $bytes_read != 4 ) {
  24                die "invalid packet: '$buffer'";
  25        }
  26        my $pkt_size = hex($buffer);
  27        if ( $pkt_size == 0 ) {
  28                return ( 1, "" );
  29        }
  30        elsif ( $pkt_size > 4 ) {
  31                my $content_size = $pkt_size - 4;
  32                $bytes_read = read STDIN, $buffer, $content_size;
  33                if ( $bytes_read != $content_size ) {
  34                        die "invalid packet ($content_size bytes expected; $bytes_read bytes read)";
  35                }
  36                return ( 0, $buffer );
  37        }
  38        else {
  39                die "invalid packet size: $pkt_size";
  40        }
  41}
  42
  43sub packet_txt_read {
  44        my ( $res, $buf ) = packet_bin_read();
  45        unless ( $buf =~ s/\n$// ) {
  46                die "A non-binary line MUST be terminated by an LF.";
  47        }
  48        return ( $res, $buf );
  49}
  50
  51sub packet_bin_write {
  52        my $buf = shift;
  53        print STDOUT sprintf( "%04x", length($buf) + 4 );
  54        print STDOUT $buf;
  55        STDOUT->flush();
  56}
  57
  58sub packet_txt_write {
  59        packet_bin_write( $_[0] . "\n" );
  60}
  61
  62sub packet_flush {
  63        print STDOUT sprintf( "%04x", 0 );
  64        STDOUT->flush();
  65}
  66
  67( packet_txt_read() eq ( 0, "git-filter-client" ) ) || die "bad initialize";
  68( packet_txt_read() eq ( 0, "version=2" ) )         || die "bad version";
  69( packet_bin_read() eq ( 1, "" ) )                  || die "bad version end";
  70
  71packet_txt_write("git-filter-server");
  72packet_txt_write("version=2");
  73packet_flush();
  74
  75( packet_txt_read() eq ( 0, "capability=clean" ) )  || die "bad capability";
  76( packet_txt_read() eq ( 0, "capability=smudge" ) ) || die "bad capability";
  77( packet_bin_read() eq ( 1, "" ) )                  || die "bad capability end";
  78
  79packet_txt_write("capability=clean");
  80packet_txt_write("capability=smudge");
  81packet_flush();
  82
  83while (1) {
  84        my ($command)  = packet_txt_read() =~ /^command=([^=]+)$/;
  85        my ($pathname) = packet_txt_read() =~ /^pathname=([^=]+)$/;
  86
  87        packet_bin_read();
  88
  89        my $input = "";
  90        {
  91                binmode(STDIN);
  92                my $buffer;
  93                my $done = 0;
  94                while ( !$done ) {
  95                        ( $done, $buffer ) = packet_bin_read();
  96                        $input .= $buffer;
  97                }
  98        }
  99
 100        my $output;
 101        if ( $command eq "clean" ) {
 102                ### Perform clean here ###
 103                $output = $input;
 104        }
 105        elsif ( $command eq "smudge" ) {
 106                ### Perform smudge here ###
 107                $output = $input;
 108        }
 109        else {
 110                die "bad command '$command'";
 111        }
 112
 113        packet_txt_write("status=success");
 114        packet_flush();
 115        while ( length($output) > 0 ) {
 116                my $packet = substr( $output, 0, $MAX_PACKET_CONTENT_SIZE );
 117                packet_bin_write($packet);
 118                if ( length($output) > $MAX_PACKET_CONTENT_SIZE ) {
 119                        $output = substr( $output, $MAX_PACKET_CONTENT_SIZE );
 120                }
 121                else {
 122                        $output = "";
 123                }
 124        }
 125        packet_flush();    # flush content!
 126        packet_flush();    # empty list, keep "status=success" unchanged!
 127
 128}