…into async-io, as usual.
Showing the changes to git-protocol/src/fetch/blocking_io/delegate.rs (1 of 12 files). Show all
Unified · Split
| @@ -0,0 +1,100 @@ | ||
| 1 | +use crate::fetch::{Arguments, Ref, Response}; | |
| 2 | +use bstr::BString; | |
| 3 | +use git_features::progress::Progress; | |
| 4 | +use git_transport::client::Capabilities; | |
| 5 | +use std::io; | |
| 6 | + | |
| 7 | +/// Defines what to do next after certain [`Delegate`] operations. | |
| 8 | +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] | |
| 9 | +pub enum Action { | |
| 10 | + /// Continue the typical flow of operations in this flow. | |
| 11 | + Continue, | |
| 12 | + /// Close the connection without making any further requests. | |
| 13 | + Close, | |
| 14 | +} | |
| 15 | + | |
| 16 | +/// The protocol delegate is the bare minimal interface needed to fully control the [`fetch`][crate::fetch()] operation. | |
| 17 | +/// | |
| 18 | +/// Implementations of this trait are controlled by code with intricate knowledge about how fetching works in protocol version V1 and V2, | |
| 19 | +/// so you don't have to. | |
| 20 | +/// Everything is tucked away behind type-safety so 'nothing can go wrong'©. Runtime assertions assure invalid | |
| 21 | +/// features or arguments don't make it to the server in the first place. | |
| 22 | +/// Please note that this trait mostly corresponds to what V2 would look like, even though V1 is supported as well. | |
| 23 | +pub trait Delegate { | |
| 24 | + /// Called before invoking 'ls-refs' on the server to allow providing it with additional `arguments` and to enable `features`. | |
| 25 | + /// | |
| 26 | + /// Note that some arguments are preset based on typical use, and `features` are preset to maximize options. | |
| 27 | + /// The `server` capabilities can be used to see which additional capabilities the server supports as per the handshake which happened prior. | |
| 28 | + /// Note that this is called only if we are using protocol version 2. | |
| 29 | + fn prepare_ls_refs( | |
| 30 | + &mut self, | |
| 31 | + _server: &Capabilities, | |
| 32 | + _arguments: &mut Vec<BString>, | |
| 33 | + _features: &mut Vec<(&str, Option<&str>)>, | |
| 34 | + ) { | |
| 35 | + } | |
| 36 | + | |
| 37 | + /// Called before invoking the 'fetch' interaction with `features` pre-filled for typical use | |
| 38 | + /// and to maximize capabilities to allow aborting an interaction early. | |
| 39 | + /// | |
| 40 | + /// `refs` is a list of known references on the remote based on the handshake or a prior call to ls_refs. | |
| 41 | + /// These can be used to abort early in case the refs are already known here. | |
| 42 | + /// | |
| 43 | + /// As there will be another call allowing to post arguments conveniently in the correct format, i.e. `want hex-oid`, | |
| 44 | + /// there is no way to set arguments at this time. | |
| 45 | + /// | |
| 46 | + /// `version` is the actually supported version as reported by the server, which is relevant in case the server requested a downgrade. | |
| 47 | + /// `server` capabilities is a list of features the server supports for your information, along with enabled `features` that the server knows about. | |
| 48 | + fn prepare_fetch( | |
| 49 | + &mut self, | |
| 50 | + _version: git_transport::Protocol, | |
| 51 | + _server: &Capabilities, | |
| 52 | + _features: &mut Vec<(&str, Option<&str>)>, | |
| 53 | + _refs: &[Ref], | |
| 54 | + ) -> Action { | |
| 55 | + Action::Continue | |
| 56 | + } | |
| 57 | + | |
| 58 | + /// A method called repeatedly to negotiate the objects to receive in [`receive_pack(…)`][Delegate::receive_pack()]. | |
| 59 | + /// | |
| 60 | + /// The first call has `previous` set to `None` as there was no previous response. Every call that follows `previous` | |
| 61 | + /// will be set to `Some`. | |
| 62 | + /// | |
| 63 | + /// ### If `previous` is `None`… | |
| 64 | + /// | |
| 65 | + /// Given a list of `arguments` to populate with wants, shallows, filters and other contextual information to be | |
| 66 | + /// sent to the server. This method is called once. | |
| 67 | + /// Send the objects you `have` have afterwards based on the tips of your refs, in preparation to walk down their parents | |
| 68 | + /// with each call to `negotiate` to find the common base(s). | |
| 69 | + /// | |
| 70 | + /// Note that you should not `want` and object that you already have. | |
| 71 | + /// `refs` are the the tips of on the server side, effectively the latest objects _they_ have. | |
| 72 | + /// | |
| 73 | + /// Return `Action::Close` if you know that there are no `haves` on your end to allow the server to send all of its objects | |
| 74 | + /// as is the case during initial clones. | |
| 75 | + /// | |
| 76 | + /// ### If `previous` is `Some`… | |
| 77 | + /// | |
| 78 | + /// Populate `arguments` with the objects you `have` starting from the tips of _your_ refs, taking into consideration | |
| 79 | + /// the `previous` response of the server to see which objects they acknowledged to have. You have to maintain | |
| 80 | + /// enough state to be able to walk down from your tips on each call, if they are not in common, and keep setting `have` | |
| 81 | + /// for those which are in common if that helps teaching the server about our state and to acknowledge their existence on _their_ end. | |
| 82 | + /// This method is called until the other side signals they are ready to send a pack. | |
| 83 | + /// Return `Action::Close` if you want to give up before finding a common base. This can happen if the remote repository | |
| 84 | + /// has radically changed so there are no bases, or they are very far in the past, causing all objects to be sent. | |
| 85 | + fn negotiate(&mut self, refs: &[Ref], arguments: &mut Arguments, previous: Option<&Response>) -> Action; | |
| 86 | + | |
| 87 | + /// Receive a pack provided from the given `input`. | |
| 88 | + /// | |
| 89 | + /// Use `progress` to emit your own progress messages when decoding the pack. | |
| 90 | + /// | |
| 91 | + /// `refs` of the remote side are provided for convenience, along with the parsed `previous` response in case you want | |
| 92 | + /// to check additional acks. | |
| 93 | + fn receive_pack( | |
| 94 | + &mut self, | |
| 95 | + input: impl io::BufRead, | |
| 96 | + progress: impl Progress, | |
| 97 | + refs: &[Ref], | |
| 98 | + previous: &Response, | |
| 99 | + ) -> io::Result<()>; | |
| 100 | +} | |