pub struct UploadPack<'a> { /* private fields */ }Expand description
The server side of git-upload-pack.
One of these serves one connection. That matters for Self::fetch,
which a v2 client calls once per negotiation round: the haves a client has
already been answered about are memoised here rather than re-resolved
against the object store every round. The memo holds no decisions, only
facts about the store (see negotiate::HaveMemo), so a shared or reused
instance answers the same, only slower.
Implementations§
Source§impl<'a> UploadPack<'a>
impl<'a> UploadPack<'a>
Sourcepub fn new(git: &'a dyn GitServe, hash_kind: Kind) -> Self
pub fn new(git: &'a dyn GitServe, hash_kind: Kind) -> Self
Serve objects/refs with default configuration.
Sourcepub fn with_config(self, config: Config) -> Self
pub fn with_config(self, config: Config) -> Self
Replace the configuration.
The have memo is rebuilt, because its ceiling is derived from
Config::limits — a configuration that lifted the request ceiling and
left a memo capped at the old one would be honouring a limit nobody set.
Sourcepub fn hash_kind(&self) -> Kind
pub fn hash_kind(&self) -> Kind
The repository’s hash kind, and the only source of object-format.
Sourcepub fn serve(
&self,
version: ProtocolVersion,
input: &mut dyn BufRead,
out: &mut dyn Write,
) -> Result<UploadSummary>
pub fn serve( &self, version: ProtocolVersion, input: &mut dyn BufRead, out: &mut dyn Write, ) -> Result<UploadSummary>
Serve one connection at the given protocol version.
Sourcepub fn serve_session(
&self,
version: ProtocolVersion,
session: Session,
input: &mut dyn BufRead,
out: &mut dyn Write,
) -> Result<UploadSummary>
pub fn serve_session( &self, version: ProtocolVersion, session: Session, input: &mut dyn BufRead, out: &mut dyn Write, ) -> Result<UploadSummary>
Serve one call at the given protocol version and Session.
Session::Connected is what serve does and what SSH
uses. Session::StatelessRpc is one smart-HTTP POST: no
advertisement is written (it was a separate GET), and the call answers
one round and returns.
Sourcepub fn advertise(
&self,
version: ProtocolVersion,
out: &mut dyn Write,
) -> Result<()>
pub fn advertise( &self, version: ProtocolVersion, out: &mut dyn Write, ) -> Result<()>
The advertisement a smart-HTTP GET /info/refs?service=git-upload-pack
answers with, for either protocol version.
The # service=git-upload-pack preamble is not written here: it is
an HTTP framing detail (and one protocol v2 does not use at all), so it
belongs to gunnar-http and not to a state machine that also runs over
SSH, where no such line exists.
Sourcepub fn capability_advertisement(&self) -> Result<Vec<u8>>
pub fn capability_advertisement(&self) -> Result<Vec<u8>>
The v2 capability advertisement, as bytes.
Sent before the client says anything, exactly as git-upload-pack does.
Sourcepub fn write_capability_advertisement(&self, out: &mut dyn Write) -> Result<()>
pub fn write_capability_advertisement(&self, out: &mut dyn Write) -> Result<()>
Write the v2 capability advertisement.
Sourcepub fn serve_v2(
&self,
input: &mut dyn BufRead,
out: &mut dyn Write,
) -> Result<UploadSummary>
pub fn serve_v2( &self, input: &mut dyn BufRead, out: &mut dyn Write, ) -> Result<UploadSummary>
The whole v2 session: advertisement, then commands until the client stops.
Sourcepub fn serve_v2_session(
&self,
session: Session,
input: &mut dyn BufRead,
out: &mut dyn Write,
) -> Result<UploadSummary>
pub fn serve_v2_session( &self, session: Session, input: &mut dyn BufRead, out: &mut dyn Write, ) -> Result<UploadSummary>
The v2 session, for either Session.
Under Session::StatelessRpc the advertisement is skipped and the
call returns after one command, because that is what one HTTP POST
carries. Returning after one is not merely equivalent to hitting EOF: a
body carrying a second command would otherwise be served on a
negotiation state the next POST cannot see, which is the shape of a
clone that loops.
Sourcepub fn ls_refs(
&self,
request: &LsRefsRequest,
out: &mut dyn Write,
) -> Result<()>
pub fn ls_refs( &self, request: &LsRefsRequest, out: &mut dyn Write, ) -> Result<()>
command=ls-refs.
Sourcepub fn fetch(
&self,
request: &FetchRequest,
out: &mut dyn Write,
) -> Result<FetchOutcome>
pub fn fetch( &self, request: &FetchRequest, out: &mut dyn Write, ) -> Result<FetchOutcome>
command=fetch, one round.
Returns without a packfile when negotiation is not finished; the client
then sends another command=fetch with more haves.
Sourcepub fn write_ref_advertisement(&self, out: &mut dyn Write) -> Result<()>
pub fn write_ref_advertisement(&self, out: &mut dyn Write) -> Result<()>
The v0 reference advertisement.
Sourcepub fn serve_v0(
&self,
input: &mut dyn BufRead,
out: &mut dyn Write,
) -> Result<UploadSummary>
pub fn serve_v0( &self, input: &mut dyn BufRead, out: &mut dyn Write, ) -> Result<UploadSummary>
The whole v0 session.
Sourcepub fn serve_v0_session(
&self,
session: Session,
input: &mut dyn BufRead,
out: &mut dyn Write,
) -> Result<UploadSummary>
pub fn serve_v0_session( &self, session: Session, input: &mut dyn BufRead, out: &mut dyn Write, ) -> Result<UploadSummary>
The v0 session, for either Session.
§What stateless-rpc changes here, and it is one branch
v0 has no command= boundary, so a stateless round is delimited by the
client’s flush-pkt after its have list. Under
Session::StatelessRpc that flush ends the call: the server
answers ACK/NAK and returns, and the client opens a new POST
carrying its whole want list again plus the haves it has since
decided to send. Under Session::Connected the same flush ends only a
round and the loop keeps reading, which is what SSH needs.
Getting this wrong is not a subtle bug: a server that kept reading would block on a body that has already ended, and the client would sit waiting for a response that is waiting for it.