History

[protocol] Allow both preparation delegate methods to fail

Related to #114

Sebastian Thiel committed 5 years ago

Commit d89393b1 parent 660b9dc4 files · +137 −49Browse files

Showing the changes to git-protocol/src/fetch/function.rs (1 of 4 files). Show all

Unified · Split

git-protocol/src/fetch/function.rs+48−31
@@ -114,45 +114,50 @@ where · 113 unmodified lines
114114 let ls_refs = Command::LsRefs;
115115 let mut ls_features = ls_refs.default_features(protocol_version, &capabilities);
116116 let mut ls_args = ls_refs.initial_arguments(&ls_features);
117− let next = delegate.prepare_ls_refs(&capabilities, &mut ls_args, &mut ls_features);
118− // User has requested to skip ls-refs, perhaps because they're using want-ref
119− if next == LsRefsAction::Skip {
120− vec![]
121− } else {
122− ls_refs.validate_argument_prefixes_or_panic(protocol_version, &capabilities, &ls_args, &ls_features);
117+ match delegate.prepare_ls_refs(&capabilities, &mut ls_args, &mut ls_features) {
118+ Ok(LsRefsAction::Skip) => Vec::new(),
119+ Ok(LsRefsAction::Continue) => {
120+ ls_refs.validate_argument_prefixes_or_panic(
121+ protocol_version,
122+ &capabilities,
123+ &ls_args,
124+ &ls_features,
125+ );
123126
124− progress.step();
125− progress.set_name("list refs");
126− let mut remote_refs = transport
127− .invoke(
128− ls_refs.as_str(),
129− ls_features.into_iter(),
130− if ls_args.is_empty() {
131− None
132− } else {
133− Some(ls_args.into_iter())
134− },
135− )
136− .await?;
137− refs::from_v2_refs(&mut remote_refs).await?
127+ progress.step();
128+ progress.set_name("list refs");
129+ let mut remote_refs = transport
130+ .invoke(
131+ ls_refs.as_str(),
132+ ls_features.into_iter(),
133+ if ls_args.is_empty() {
134+ None
135+ } else {
136+ Some(ls_args.into_iter())
137+ },
138+ )
139+ .await?;
140+ refs::from_v2_refs(&mut remote_refs).await?
141+ }
142+ Err(err) => {
143+ indicate_end_of_interaction(transport)?;
144+ return Err(err.into());
145+ }
138146 }
139147 }
140148 };
141149
142150 let fetch = Command::Fetch;
143151 let mut fetch_features = fetch.default_features(protocol_version, &capabilities);
144− let next = delegate.prepare_fetch(protocol_version, &capabilities, &mut fetch_features, &parsed_refs);
145− fetch.validate_argument_prefixes_or_panic(protocol_version, &capabilities, &[], &fetch_features);
146−
147− if next == Action::Cancel {
148− // An empty request marks the (early) end of the interaction. Only relevant in stateful transports though.
149− if transport.is_stateful() {
150− transport
151− .request(client::WriteMode::Binary, client::MessageKind::Flush)?
152− .into_read()
153− .await?;
152+ match delegate.prepare_fetch(protocol_version, &capabilities, &mut fetch_features, &parsed_refs) {
153+ Ok(Action::Cancel) => return indicate_end_of_interaction(transport),
154+ Ok(Action::Continue) => {
155+ fetch.validate_argument_prefixes_or_panic(protocol_version, &capabilities, &[], &fetch_features);
156+ }
157+ Err(err) => {
158+ indicate_end_of_interaction(transport)?;
159+ return Err(err.into());
154160 }
155− return Ok(());
156161 }
157162
158163 Response::check_required_features(protocol_version, &fetch_features)?;
@@ -188,6 +193,18 @@ where · 29 unmodified lines
188193 Ok(())
189194 }
190195
196+#[maybe_async]
197+async fn indicate_end_of_interaction(mut transport: impl client::Transport) -> Result<(), Error> {
198+ // An empty request marks the (early) end of the interaction. Only relevant in stateful transports though.
199+ if transport.is_stateful() {
200+ transport
201+ .request(client::WriteMode::Binary, client::MessageKind::Flush)?
202+ .into_read()
203+ .await?;
204+ }
205+ return Ok(());
206+}
207+
191208 fn setup_remote_progress(
192209 progress: &mut impl Progress,
193210 reader: &mut Box<dyn git_transport::client::ExtendedBufRead + Unpin + '_>,