@@ -90,9 +90,10 @@ mod with_io {
90
90
}
91
91
}
92
92
93
- /// Compute initial arguments based on the given `features`. They are typically provided by the `default_features(…)` method.
94
- /// Only useful for V2
95
- pub ( crate ) fn initial_arguments ( & self , features : & [ Feature ] ) -> Vec < BString > {
93
+ /// Provide the initial arguments based on the given `features`.
94
+ /// They are typically provided by the [`Self::default_features`] method.
95
+ /// Only useful for V2, and based on heuristics/experimentation.
96
+ pub fn initial_v2_arguments ( & self , features : & [ Feature ] ) -> Vec < BString > {
96
97
match self {
97
98
Command :: Fetch => [ "thin-pack" , "ofs-delta" ]
98
99
. iter ( )
@@ -157,20 +158,24 @@ mod with_io {
157
158
Command :: LsRefs => vec ! [ ] ,
158
159
}
159
160
}
160
- /// Panics if the given arguments and features don't match what's statically known. It's considered a bug in the delegate .
161
- pub ( crate ) fn validate_argument_prefixes_or_panic (
161
+ /// Return an error if the given ` arguments` and ` features` don't match what's statically known.
162
+ pub fn validate_argument_prefixes (
162
163
& self ,
163
164
version : gix_transport:: Protocol ,
164
165
server : & Capabilities ,
165
166
arguments : & [ BString ] ,
166
167
features : & [ Feature ] ,
167
- ) {
168
+ ) -> Result < ( ) , validate_argument_prefixes:: Error > {
169
+ use validate_argument_prefixes:: Error ;
168
170
let allowed = self . all_argument_prefixes ( ) ;
169
171
for arg in arguments {
170
172
if allowed. iter ( ) . any ( |allowed| arg. starts_with ( allowed. as_bytes ( ) ) ) {
171
173
continue ;
172
174
}
173
- panic ! ( "{}: argument {} is not known or allowed" , self . as_str( ) , arg) ;
175
+ return Err ( Error :: UnsupportedArgument {
176
+ command : self . as_str ( ) ,
177
+ argument : arg. clone ( ) ,
178
+ } ) ;
174
179
}
175
180
match version {
176
181
gix_transport:: Protocol :: V0 | gix_transport:: Protocol :: V1 => {
@@ -181,14 +186,17 @@ mod with_io {
181
186
{
182
187
continue ;
183
188
}
184
- panic ! ( "{}: capability {} is not supported" , self . as_str( ) , feature) ;
189
+ return Err ( Error :: UnsupportedCapability {
190
+ command : self . as_str ( ) ,
191
+ feature : feature. to_string ( ) ,
192
+ } ) ;
185
193
}
186
194
}
187
195
gix_transport:: Protocol :: V2 => {
188
196
let allowed = server
189
197
. iter ( )
190
198
. find_map ( |c| {
191
- if c. name ( ) == self . as_str ( ) . as_bytes ( ) . as_bstr ( ) {
199
+ if c. name ( ) == self . as_str ( ) {
192
200
c. values ( ) . map ( |v| v. map ( ToString :: to_string) . collect :: < Vec < _ > > ( ) )
193
201
} else {
194
202
None
@@ -201,14 +209,34 @@ mod with_io {
201
209
}
202
210
match * feature {
203
211
"agent" => { }
204
- _ => panic ! ( "{}: V2 feature/capability {} is not supported" , self . as_str( ) , feature) ,
212
+ _ => {
213
+ return Err ( Error :: UnsupportedCapability {
214
+ command : self . as_str ( ) ,
215
+ feature : feature. to_string ( ) ,
216
+ } )
217
+ }
205
218
}
206
219
}
207
220
}
208
221
}
222
+ Ok ( ( ) )
209
223
}
210
224
}
211
- }
212
225
213
- #[ cfg( test) ]
214
- mod tests;
226
+ ///
227
+ pub mod validate_argument_prefixes {
228
+ use bstr:: BString ;
229
+
230
+ /// The error returned by [Command::validate_argument_prefixes()](super::Command::validate_argument_prefixes()).
231
+ #[ derive( Debug , thiserror:: Error ) ]
232
+ #[ allow( missing_docs) ]
233
+ pub enum Error {
234
+ #[ error( "{command}: argument {argument} is not known or allowed" ) ]
235
+ UnsupportedArgument { command : & ' static str , argument : BString } ,
236
+ #[ error( "{command}: capability {feature} is not supported" ) ]
237
+ UnsupportedCapability { command : & ' static str , feature : String } ,
238
+ }
239
+ }
240
+ }
241
+ #[ cfg( any( test, feature = "async-client" , feature = "blocking-client" ) ) ]
242
+ pub use with_io:: validate_argument_prefixes;
0 commit comments