@@ -23,13 +23,29 @@ pub enum Error {
23
23
}
24
24
25
25
/// A structure to represent multiple [capabilities][Capability] or features supported by the server.
26
- #[ derive( Debug , Clone , Default ) ]
26
+ ///
27
+ /// ### Deviation
28
+ ///
29
+ /// As a *shortcoming*, we are unable to parse `V1` as emitted from `git-upload-pack` without a `git-daemon` or server,
30
+ /// as it will not emit any capabilities for some reason. Only `V2` and `V0` work in that context.
31
+ #[ derive( Debug , Clone ) ]
27
32
#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
28
33
pub struct Capabilities {
29
34
data : BString ,
30
35
value_sep : u8 ,
31
36
}
32
37
38
+ /// This implementation yields exactly those minimal capabilities that are required for `gix` to work, nothing more and nothing less.
39
+ ///
40
+ /// This is a bit of a hack just get tests with Protocol V0 to work, which is a good way to enforce stateful transports.
41
+ /// Of course, V1 would also do that but when calling `git-upload-pack` directly, it advertises so badly that this is easier to implement.
42
+ impl Default for Capabilities {
43
+ fn default ( ) -> Self {
44
+ Capabilities :: from_lines ( "version 2\n multi_ack_detailed\n side-band-64k\n " . into ( ) )
45
+ . expect ( "valid format, known at compile time" )
46
+ }
47
+ }
48
+
33
49
/// The name of a single capability.
34
50
pub struct Capability < ' a > ( & ' a BStr ) ;
35
51
@@ -185,44 +201,50 @@ pub mod recv {
185
201
// format looks like, thus there is no binary blob that could ever look like an ERR line by accident.
186
202
rd. fail_on_err_lines ( true ) ;
187
203
188
- let line = rd
189
- . peek_line ( )
190
- . ok_or ( client:: Error :: ExpectedLine ( "capabilities or version" ) ) ???;
191
- let line = line. as_text ( ) . ok_or ( client:: Error :: ExpectedLine ( "text" ) ) ?;
192
-
193
- let version = Capabilities :: extract_protocol ( line) ?;
194
- match version {
195
- Protocol :: V1 => {
196
- let ( capabilities, delimiter_position) = Capabilities :: from_bytes ( line. 0 ) ?;
197
- rd. peek_buffer_replace_and_truncate ( delimiter_position, b'\n' ) ;
198
- Ok ( Outcome {
199
- capabilities,
200
- refs : Some ( Box :: new ( rd. as_read ( ) ) ) ,
201
- protocol : Protocol :: V1 ,
202
- } )
203
- }
204
- Protocol :: V2 => Ok ( Outcome {
205
- capabilities : {
206
- let mut rd = rd. as_read ( ) ;
207
- let mut buf = Vec :: new ( ) ;
208
- while let Some ( line) = rd. read_data_line ( ) {
209
- let line = line??;
210
- match line. as_bstr ( ) {
211
- Some ( line) => {
212
- buf. push_str ( line) ;
213
- if buf. last ( ) != Some ( & b'\n' ) {
214
- buf. push ( b'\n' ) ;
215
- }
216
- }
217
- None => break ,
204
+ Ok ( match rd. peek_line ( ) {
205
+ Some ( line) => {
206
+ let line = line??. as_text ( ) . ok_or ( client:: Error :: ExpectedLine ( "text" ) ) ?;
207
+ let version = Capabilities :: extract_protocol ( line) ?;
208
+ match version {
209
+ Protocol :: V0 => unreachable ! ( "already handled in `None` case" ) ,
210
+ Protocol :: V1 => {
211
+ let ( capabilities, delimiter_position) = Capabilities :: from_bytes ( line. 0 ) ?;
212
+ rd. peek_buffer_replace_and_truncate ( delimiter_position, b'\n' ) ;
213
+ Outcome {
214
+ capabilities,
215
+ refs : Some ( Box :: new ( rd. as_read ( ) ) ) ,
216
+ protocol : Protocol :: V1 ,
218
217
}
219
218
}
220
- Capabilities :: from_lines ( buf. into ( ) ) ?
221
- } ,
222
- refs : None ,
223
- protocol : Protocol :: V2 ,
224
- } ) ,
225
- }
219
+ Protocol :: V2 => Outcome {
220
+ capabilities : {
221
+ let mut rd = rd. as_read ( ) ;
222
+ let mut buf = Vec :: new ( ) ;
223
+ while let Some ( line) = rd. read_data_line ( ) {
224
+ let line = line??;
225
+ match line. as_bstr ( ) {
226
+ Some ( line) => {
227
+ buf. push_str ( line) ;
228
+ if buf. last ( ) != Some ( & b'\n' ) {
229
+ buf. push ( b'\n' ) ;
230
+ }
231
+ }
232
+ None => break ,
233
+ }
234
+ }
235
+ Capabilities :: from_lines ( buf. into ( ) ) ?
236
+ } ,
237
+ refs : None ,
238
+ protocol : Protocol :: V2 ,
239
+ } ,
240
+ }
241
+ }
242
+ None => Outcome {
243
+ capabilities : Capabilities :: default ( ) ,
244
+ refs : Some ( Box :: new ( rd. as_read ( ) ) ) ,
245
+ protocol : Protocol :: V0 ,
246
+ } ,
247
+ } )
226
248
}
227
249
}
228
250
}
@@ -263,45 +285,50 @@ pub mod recv {
263
285
// format looks like, thus there is no binary blob that could ever look like an ERR line by accident.
264
286
rd. fail_on_err_lines ( true ) ;
265
287
266
- let line = rd
267
- . peek_line ( )
268
- . await
269
- . ok_or ( client:: Error :: ExpectedLine ( "capabilities or version" ) ) ???;
270
- let line = line. as_text ( ) . ok_or ( client:: Error :: ExpectedLine ( "text" ) ) ?;
271
-
272
- let version = Capabilities :: extract_protocol ( line) ?;
273
- match version {
274
- Protocol :: V1 => {
275
- let ( capabilities, delimiter_position) = Capabilities :: from_bytes ( line. 0 ) ?;
276
- rd. peek_buffer_replace_and_truncate ( delimiter_position, b'\n' ) ;
277
- Ok ( Outcome {
278
- capabilities,
279
- refs : Some ( Box :: new ( rd. as_read ( ) ) ) ,
280
- protocol : Protocol :: V1 ,
281
- } )
282
- }
283
- Protocol :: V2 => Ok ( Outcome {
284
- capabilities : {
285
- let mut rd = rd. as_read ( ) ;
286
- let mut buf = Vec :: new ( ) ;
287
- while let Some ( line) = rd. read_data_line ( ) . await {
288
- let line = line??;
289
- match line. as_bstr ( ) {
290
- Some ( line) => {
291
- buf. push_str ( line) ;
292
- if buf. last ( ) != Some ( & b'\n' ) {
293
- buf. push ( b'\n' ) ;
294
- }
295
- }
296
- None => break ,
288
+ Ok ( match rd. peek_line ( ) . await {
289
+ Some ( line) => {
290
+ let line = line??. as_text ( ) . ok_or ( client:: Error :: ExpectedLine ( "text" ) ) ?;
291
+ let version = Capabilities :: extract_protocol ( line) ?;
292
+ match version {
293
+ Protocol :: V0 => unreachable ! ( "already handled in `None` case" ) ,
294
+ Protocol :: V1 => {
295
+ let ( capabilities, delimiter_position) = Capabilities :: from_bytes ( line. 0 ) ?;
296
+ rd. peek_buffer_replace_and_truncate ( delimiter_position, b'\n' ) ;
297
+ Outcome {
298
+ capabilities,
299
+ refs : Some ( Box :: new ( rd. as_read ( ) ) ) ,
300
+ protocol : Protocol :: V1 ,
297
301
}
298
302
}
299
- Capabilities :: from_lines ( buf. into ( ) ) ?
300
- } ,
301
- refs : None ,
302
- protocol : Protocol :: V2 ,
303
- } ) ,
304
- }
303
+ Protocol :: V2 => Outcome {
304
+ capabilities : {
305
+ let mut rd = rd. as_read ( ) ;
306
+ let mut buf = Vec :: new ( ) ;
307
+ while let Some ( line) = rd. read_data_line ( ) . await {
308
+ let line = line??;
309
+ match line. as_bstr ( ) {
310
+ Some ( line) => {
311
+ buf. push_str ( line) ;
312
+ if buf. last ( ) != Some ( & b'\n' ) {
313
+ buf. push ( b'\n' ) ;
314
+ }
315
+ }
316
+ None => break ,
317
+ }
318
+ }
319
+ Capabilities :: from_lines ( buf. into ( ) ) ?
320
+ } ,
321
+ refs : None ,
322
+ protocol : Protocol :: V2 ,
323
+ } ,
324
+ }
325
+ }
326
+ None => Outcome {
327
+ capabilities : Capabilities :: default ( ) ,
328
+ refs : Some ( Box :: new ( rd. as_read ( ) ) ) ,
329
+ protocol : Protocol :: V0 ,
330
+ } ,
331
+ } )
305
332
}
306
333
}
307
334
}
0 commit comments