]>
Commit | Line | Data |
---|---|---|
edcc8581 LS |
1 | # |
2 | # Example implementation for the Git filter protocol version 2 | |
3 | # See Documentation/gitattributes.txt, section "Filter Protocol" | |
4 | # | |
e1ec4721 LS |
5 | # The first argument defines a debug log file that the script write to. |
6 | # All remaining arguments define a list of supported protocol | |
7 | # capabilities ("clean", "smudge", etc). | |
edcc8581 LS |
8 | # |
9 | # This implementation supports special test cases: | |
10 | # (1) If data with the pathname "clean-write-fail.r" is processed with | |
11 | # a "clean" operation then the write operation will die. | |
12 | # (2) If data with the pathname "smudge-write-fail.r" is processed with | |
13 | # a "smudge" operation then the write operation will die. | |
14 | # (3) If data with the pathname "error.r" is processed with any | |
15 | # operation then the filter signals that it cannot or does not want | |
16 | # to process the file. | |
17 | # (4) If data with the pathname "abort.r" is processed with any | |
18 | # operation then the filter signals that it cannot or does not want | |
19 | # to process the file and any file after that is processed with the | |
20 | # same command. | |
2841e8f8 LS |
21 | # (5) If data with a pathname that is a key in the DELAY hash is |
22 | # requested (e.g. "test-delay10.a") then the filter responds with | |
23 | # a "delay" status and sets the "requested" field in the DELAY hash. | |
24 | # The filter will signal the availability of this object after | |
25 | # "count" (field in DELAY hash) "list_available_blobs" commands. | |
26 | # (6) If data with the pathname "missing-delay.a" is processed that the | |
27 | # filter will drop the path from the "list_available_blobs" response. | |
28 | # (7) If data with the pathname "invalid-delay.a" is processed that the | |
29 | # filter will add the path "unfiltered" which was not delayed before | |
30 | # to the "list_available_blobs" response. | |
edcc8581 LS |
31 | # |
32 | ||
0fe8d516 CC |
33 | use 5.008; |
34 | use lib (split(/:/, $ENV{GITPERLLIB})); | |
edcc8581 LS |
35 | use strict; |
36 | use warnings; | |
4821494e | 37 | use IO::File; |
0fe8d516 | 38 | use Git::Packet; |
edcc8581 LS |
39 | |
40 | my $MAX_PACKET_CONTENT_SIZE = 65516; | |
e1ec4721 | 41 | my $log_file = shift @ARGV; |
edcc8581 LS |
42 | my @capabilities = @ARGV; |
43 | ||
e1ec4721 | 44 | open my $debug, ">>", $log_file or die "cannot open log file: $!"; |
edcc8581 | 45 | |
2841e8f8 LS |
46 | my %DELAY = ( |
47 | 'test-delay10.a' => { "requested" => 0, "count" => 1 }, | |
48 | 'test-delay11.a' => { "requested" => 0, "count" => 1 }, | |
49 | 'test-delay20.a' => { "requested" => 0, "count" => 2 }, | |
50 | 'test-delay10.b' => { "requested" => 0, "count" => 1 }, | |
51 | 'missing-delay.a' => { "requested" => 0, "count" => 1 }, | |
52 | 'invalid-delay.a' => { "requested" => 0, "count" => 1 }, | |
53 | ); | |
54 | ||
edcc8581 LS |
55 | sub rot13 { |
56 | my $str = shift; | |
57 | $str =~ y/A-Za-z/N-ZA-Mn-za-m/; | |
58 | return $str; | |
59 | } | |
60 | ||
edcc8581 LS |
61 | print $debug "START\n"; |
62 | $debug->flush(); | |
63 | ||
25cbfe34 | 64 | packet_initialize("git-filter", 2); |
edcc8581 | 65 | |
f11c8ce1 CC |
66 | my %remote_caps = packet_read_and_check_capabilities("clean", "smudge", "delay"); |
67 | packet_check_and_write_capabilities(\%remote_caps, @capabilities); | |
68 | ||
edcc8581 LS |
69 | print $debug "init handshake complete\n"; |
70 | $debug->flush(); | |
71 | ||
72 | while (1) { | |
2c9ea595 CC |
73 | my ( $res, $command ) = packet_required_key_val_read("command"); |
74 | if ( $res == -1 ) { | |
75 | print $debug "STOP\n"; | |
76 | exit(); | |
77 | } | |
edcc8581 LS |
78 | print $debug "IN: $command"; |
79 | $debug->flush(); | |
80 | ||
2841e8f8 LS |
81 | if ( $command eq "list_available_blobs" ) { |
82 | # Flush | |
2c9ea595 CC |
83 | packet_compare_lists([1, ""], packet_bin_read()) || |
84 | die "bad list_available_blobs end"; | |
c6b0831c | 85 | |
2841e8f8 LS |
86 | foreach my $pathname ( sort keys %DELAY ) { |
87 | if ( $DELAY{$pathname}{"requested"} >= 1 ) { | |
88 | $DELAY{$pathname}{"count"} = $DELAY{$pathname}{"count"} - 1; | |
89 | if ( $pathname eq "invalid-delay.a" ) { | |
90 | # Send Git a pathname that was not delayed earlier | |
91 | packet_txt_write("pathname=unfiltered"); | |
92 | } | |
93 | if ( $pathname eq "missing-delay.a" ) { | |
94 | # Do not signal Git that this file is available | |
95 | } elsif ( $DELAY{$pathname}{"count"} == 0 ) { | |
96 | print $debug " $pathname"; | |
97 | packet_txt_write("pathname=$pathname"); | |
98 | } | |
99 | } | |
edcc8581 | 100 | } |
edcc8581 | 101 | |
edcc8581 | 102 | packet_flush(); |
2841e8f8 LS |
103 | |
104 | print $debug " [OK]\n"; | |
edcc8581 | 105 | $debug->flush(); |
2841e8f8 | 106 | packet_txt_write("status=success"); |
edcc8581 | 107 | packet_flush(); |
ed17d262 | 108 | } else { |
2c9ea595 CC |
109 | my ( $res, $pathname ) = packet_required_key_val_read("pathname"); |
110 | if ( $res == -1 ) { | |
111 | die "unexpected EOF while expecting pathname"; | |
112 | } | |
2841e8f8 LS |
113 | print $debug " $pathname"; |
114 | $debug->flush(); | |
115 | ||
2841e8f8 LS |
116 | # Read until flush |
117 | my ( $done, $buffer ) = packet_txt_read(); | |
118 | while ( $buffer ne '' ) { | |
119 | if ( $buffer eq "can-delay=1" ) { | |
120 | if ( exists $DELAY{$pathname} and $DELAY{$pathname}{"requested"} == 0 ) { | |
121 | $DELAY{$pathname}{"requested"} = 1; | |
122 | } | |
123 | } else { | |
124 | die "Unknown message '$buffer'"; | |
125 | } | |
edcc8581 | 126 | |
2841e8f8 LS |
127 | ( $done, $buffer ) = packet_txt_read(); |
128 | } | |
2c9ea595 CC |
129 | if ( $done == -1 ) { |
130 | die "unexpected EOF after pathname '$pathname'"; | |
131 | } | |
2841e8f8 LS |
132 | |
133 | my $input = ""; | |
134 | { | |
135 | binmode(STDIN); | |
136 | my $buffer; | |
137 | my $done = 0; | |
138 | while ( !$done ) { | |
139 | ( $done, $buffer ) = packet_bin_read(); | |
140 | $input .= $buffer; | |
141 | } | |
2c9ea595 CC |
142 | if ( $done == -1 ) { |
143 | die "unexpected EOF while reading input for '$pathname'"; | |
144 | } | |
2841e8f8 | 145 | print $debug " " . length($input) . " [OK] -- "; |
edcc8581 | 146 | $debug->flush(); |
edcc8581 LS |
147 | } |
148 | ||
2841e8f8 LS |
149 | my $output; |
150 | if ( exists $DELAY{$pathname} and exists $DELAY{$pathname}{"output"} ) { | |
151 | $output = $DELAY{$pathname}{"output"} | |
ed17d262 | 152 | } elsif ( $pathname eq "error.r" or $pathname eq "abort.r" ) { |
2841e8f8 | 153 | $output = ""; |
ed17d262 | 154 | } elsif ( $command eq "clean" and grep( /^clean$/, @capabilities ) ) { |
2841e8f8 | 155 | $output = rot13($input); |
ed17d262 | 156 | } elsif ( $command eq "smudge" and grep( /^smudge$/, @capabilities ) ) { |
2841e8f8 | 157 | $output = rot13($input); |
ed17d262 | 158 | } else { |
2841e8f8 LS |
159 | die "bad command '$command'"; |
160 | } | |
161 | ||
162 | if ( $pathname eq "error.r" ) { | |
163 | print $debug "[ERROR]\n"; | |
164 | $debug->flush(); | |
165 | packet_txt_write("status=error"); | |
166 | packet_flush(); | |
ed17d262 | 167 | } elsif ( $pathname eq "abort.r" ) { |
2841e8f8 LS |
168 | print $debug "[ABORT]\n"; |
169 | $debug->flush(); | |
170 | packet_txt_write("status=abort"); | |
171 | packet_flush(); | |
ed17d262 | 172 | } elsif ( $command eq "smudge" and |
2841e8f8 | 173 | exists $DELAY{$pathname} and |
ed17d262 | 174 | $DELAY{$pathname}{"requested"} == 1 ) { |
2841e8f8 LS |
175 | print $debug "[DELAYED]\n"; |
176 | $debug->flush(); | |
177 | packet_txt_write("status=delayed"); | |
178 | packet_flush(); | |
179 | $DELAY{$pathname}{"requested"} = 2; | |
180 | $DELAY{$pathname}{"output"} = $output; | |
ed17d262 | 181 | } else { |
2841e8f8 LS |
182 | packet_txt_write("status=success"); |
183 | packet_flush(); | |
17573334 | 184 | |
2841e8f8 LS |
185 | if ( $pathname eq "${command}-write-fail.r" ) { |
186 | print $debug "[WRITE FAIL]\n"; | |
187 | $debug->flush(); | |
188 | die "${command} write error"; | |
edcc8581 | 189 | } |
2841e8f8 LS |
190 | |
191 | print $debug "OUT: " . length($output) . " "; | |
192 | $debug->flush(); | |
193 | ||
194 | while ( length($output) > 0 ) { | |
195 | my $packet = substr( $output, 0, $MAX_PACKET_CONTENT_SIZE ); | |
196 | packet_bin_write($packet); | |
197 | # dots represent the number of packets | |
198 | print $debug "."; | |
199 | if ( length($output) > $MAX_PACKET_CONTENT_SIZE ) { | |
200 | $output = substr( $output, $MAX_PACKET_CONTENT_SIZE ); | |
ed17d262 | 201 | } else { |
2841e8f8 LS |
202 | $output = ""; |
203 | } | |
edcc8581 | 204 | } |
2841e8f8 LS |
205 | packet_flush(); |
206 | print $debug " [OK]\n"; | |
207 | $debug->flush(); | |
208 | packet_flush(); | |
edcc8581 | 209 | } |
edcc8581 LS |
210 | } |
211 | } |