public abstract class BasePackFetchConnection extends BasePackConnection implements FetchConnection
This is the canonical implementation for transferring objects from the remote repository to the local repository by talking to the 'git-upload-pack' service. Objects are packed on the remote side into a pack file and then sent down the pipe to us.
This connection requires only a bi-directional pipe or socket, and thus is easily wrapped up into a local process pipe, anonymous TCP socket, or a command executed through an SSH tunnel.
If BasePackConnection.statelessRPC
is
true
, this connection can be tunneled over a request-response style
RPC system like HTTP. The RPC call boundary is determined by this class
switching from writing to the OutputStream to reading from the InputStream.
Concrete implementations should just call
BasePackConnection.init(java.io.InputStream, java.io.OutputStream)
and
BasePackConnection.readAdvertisedRefs()
methods in constructor or before any use. They
should also handle resources releasing in close()
method if needed.
Modifier and Type | Class and Description |
---|---|
private static class |
BasePackFetchConnection.CancelledException |
(package private) static class |
BasePackFetchConnection.FetchConfig |
Modifier and Type | Field and Description |
---|---|
(package private) RevFlag |
ADVERTISED
Marks a commit listed in the advertised refs.
|
private boolean |
allowOfsDelta |
(package private) RevFlag |
COMMON
Marks a commit known to both sides of the connection.
|
private FilterSpec |
filterSpec
Either FilterSpec.NO_FILTER for a filter that doesn't filter
anything, or a filter that indicates what and what not to send to the
server.
|
private boolean |
includeTags |
private java.lang.String |
lockMessage |
private static int |
MAX_HAVES
Maximum number of 'have' lines to send before giving up.
|
private int |
maxHaves |
protected static int |
MIN_CLIENT_BUFFER
Amount of data the client sends before starting to read.
|
private GitProtocolConstants.MultiAck |
multiAck |
private boolean |
noDone |
private boolean |
noProgress |
static java.lang.String |
OPTION_ALLOW_REACHABLE_SHA1_IN_WANT
The client supports fetching objects that are reachable from a tip of a
ref that is allowed to fetch.
|
static java.lang.String |
OPTION_ALLOW_TIP_SHA1_IN_WANT
The client supports fetching objects at the tip of any ref, even if not
advertised.
|
static java.lang.String |
OPTION_FILTER
The client specified a filter expression.
|
static java.lang.String |
OPTION_INCLUDE_TAG
Include tags if we are also including the referenced objects.
|
static java.lang.String |
OPTION_MULTI_ACK
Mutli-ACK support for improved negotiation.
|
static java.lang.String |
OPTION_MULTI_ACK_DETAILED
Mutli-ACK detailed support for improved negotiation.
|
static java.lang.String |
OPTION_NO_DONE
The client supports receiving a pack before it has sent "done".
|
static java.lang.String |
OPTION_NO_PROGRESS
The client does not want progress messages and will ignore them.
|
static java.lang.String |
OPTION_OFS_DELTA
The client supports packs with OFS deltas.
|
static java.lang.String |
OPTION_SHALLOW
The client supports shallow fetches.
|
static java.lang.String |
OPTION_SIDE_BAND
The client supports using the side-band for progress messages.
|
static java.lang.String |
OPTION_SIDE_BAND_64K
The client supports using the 64K side-band for progress messages.
|
static java.lang.String |
OPTION_THIN_PACK
The client supports packs with deltas but not their bases.
|
private PackLock |
packLock |
private PacketLineOut |
pckState |
(package private) RevFlag |
REACHABLE
Marks an object as having all its dependencies.
|
private RevCommitList<RevCommit> |
reachableCommits
All commits that are immediately reachable by a local ref.
|
private boolean |
sideband |
private TemporaryBuffer.Heap |
state
RPC state, if
BasePackConnection.statelessRPC is true. |
private RevFlag |
STATE
|
private boolean |
thinPack |
private RevWalk |
walk |
additionalHaves, in, local, out, outNeedsEnd, pckIn, pckOut, statelessRPC, timeoutIn, timeoutOut, transport, uri
Constructor and Description |
---|
BasePackFetchConnection(PackTransport packTransport)
Create a new connection to fetch using the native git transport.
|
Modifier and Type | Method and Description |
---|---|
void |
close() |
boolean |
didFetchIncludeTags()
Did the last
FetchConnection.fetch(ProgressMonitor, Collection, Set) get tags? |
boolean |
didFetchTestConnectivity()
Did the last
FetchConnection.fetch(ProgressMonitor, Collection, Set) validate
graph? |
protected void |
doFetch(ProgressMonitor monitor,
java.util.Collection<Ref> want,
java.util.Set<ObjectId> have,
java.io.OutputStream outputStream)
Execute common ancestor negotiation and fetch the objects.
|
private java.lang.String |
enableCapabilities() |
void |
fetch(ProgressMonitor monitor,
java.util.Collection<Ref> want,
java.util.Set<ObjectId> have)
Fetch objects we don't have but that are reachable from advertised refs.
|
void |
fetch(ProgressMonitor monitor,
java.util.Collection<Ref> want,
java.util.Set<ObjectId> have,
java.io.OutputStream outputStream)
Fetch objects we don't have but that are reachable from advertised refs.
|
(package private) BasePackFetchConnection.FetchConfig |
getFetchConfig() |
java.util.Collection<PackLock> |
getPackLocks()
All locks created by the last
FetchConnection.fetch(ProgressMonitor, Collection, Set) call. |
private void |
markAdvertised(AnyObjectId id) |
private void |
markCommon(RevObject obj,
PacketLineIn.AckNackResult anr) |
private void |
markReachable(java.util.Set<ObjectId> have,
int maxTime) |
private void |
markRefsAdvertised() |
private int |
maxTimeWanted(java.util.Collection<Ref> wants) |
private void |
negotiate(ProgressMonitor monitor) |
private void |
negotiateBegin() |
protected void |
onReceivePack()
Notification event delivered just before the pack is received from the
network.
|
private void |
parseReachable(ObjectId id) |
private void |
receivePack(ProgressMonitor monitor,
java.io.OutputStream outputStream) |
private boolean |
sendWants(java.util.Collection<Ref> want) |
void |
setPackLockMessage(java.lang.String message)
Set the lock message used when holding a pack out of garbage collection.
|
addUserAgentCapability, endOut, getPeerUserAgent, init, isCapableOf, noRepository, readAdvertisedRefs, wantCapability
available, getMessages, getMessageWriter, getRef, getRefs, getRefsMap, markStartedOperation, setMessageWriter, setPeerUserAgent
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
getMessages, getPeerUserAgent, getRef, getRefs, getRefsMap
private static final int MAX_HAVES
During negotiate(ProgressMonitor)
we send at most this many
commits to the remote peer as 'have' lines without an ACK response before
we give up.
protected static final int MIN_CLIENT_BUFFER
Any output stream given to the client must be able to buffer this many bytes before the client will stop writing and start reading from the input stream. If the output stream blocks before this many bytes are in the send queue, the system will deadlock.
public static final java.lang.String OPTION_INCLUDE_TAG
public static final java.lang.String OPTION_MULTI_ACK
public static final java.lang.String OPTION_MULTI_ACK_DETAILED
public static final java.lang.String OPTION_THIN_PACK
public static final java.lang.String OPTION_SIDE_BAND
public static final java.lang.String OPTION_SIDE_BAND_64K
public static final java.lang.String OPTION_OFS_DELTA
public static final java.lang.String OPTION_SHALLOW
public static final java.lang.String OPTION_NO_PROGRESS
public static final java.lang.String OPTION_NO_DONE
public static final java.lang.String OPTION_ALLOW_TIP_SHA1_IN_WANT
public static final java.lang.String OPTION_ALLOW_REACHABLE_SHA1_IN_WANT
public static final java.lang.String OPTION_FILTER
private final RevWalk walk
private RevCommitList<RevCommit> reachableCommits
final RevFlag REACHABLE
final RevFlag COMMON
private final RevFlag STATE
final RevFlag ADVERTISED
private GitProtocolConstants.MultiAck multiAck
private boolean thinPack
private boolean sideband
private boolean includeTags
private boolean allowOfsDelta
private boolean noDone
private boolean noProgress
private java.lang.String lockMessage
private PackLock packLock
private int maxHaves
private TemporaryBuffer.Heap state
BasePackConnection.statelessRPC
is true.private PacketLineOut pckState
private final FilterSpec filterSpec
public BasePackFetchConnection(PackTransport packTransport)
packTransport
- the transport.public final void fetch(ProgressMonitor monitor, java.util.Collection<Ref> want, java.util.Set<ObjectId> have) throws TransportException
Only one call per connection is allowed. Subsequent calls will result in
TransportException
.
Implementations are free to use network connections as necessary to
efficiently (for both client and server) transfer objects from the remote
repository into this repository. When possible implementations should
avoid replacing/overwriting/duplicating an object already available in
the local destination repository. Locally available objects and packs
should always be preferred over remotely available objects and packs.
Transport.isFetchThin()
should be
honored if applicable.
fetch
in interface FetchConnection
monitor
- progress monitor to inform the end-user about the amount of
work completed, or to indicate cancellation. Implementations
should poll the monitor at regular intervals to look for
cancellation requests from the user.want
- one or more refs advertised by this connection that the caller
wants to store locally.have
- additional objects known to exist in the destination
repository, especially if they aren't yet reachable by the ref
database. Connections should take this set as an addition to
what is reachable through all Refs, not in replace of it.TransportException
- objects could not be copied due to a network failure,
protocol error, or error on remote side, or connection was
already used for fetch.public final void fetch(ProgressMonitor monitor, java.util.Collection<Ref> want, java.util.Set<ObjectId> have, java.io.OutputStream outputStream) throws TransportException
Only one call per connection is allowed. Subsequent calls will result in
TransportException
.
Implementations are free to use network connections as necessary to
efficiently (for both client and server) transfer objects from the remote
repository into this repository. When possible implementations should
avoid replacing/overwriting/duplicating an object already available in
the local destination repository. Locally available objects and packs
should always be preferred over remotely available objects and packs.
Transport.isFetchThin()
should be
honored if applicable.
fetch
in interface FetchConnection
monitor
- progress monitor to inform the end-user about the amount of
work completed, or to indicate cancellation. Implementations
should poll the monitor at regular intervals to look for
cancellation requests from the user.want
- one or more refs advertised by this connection that the caller
wants to store locally.have
- additional objects known to exist in the destination
repository, especially if they aren't yet reachable by the ref
database. Connections should take this set as an addition to
what is reachable through all Refs, not in replace of it.outputStream
- OutputStream to write sideband messages toTransportException
- objects could not be copied due to a network failure,
protocol error, or error on remote side, or connection was
already used for fetch.public boolean didFetchIncludeTags()
FetchConnection.fetch(ProgressMonitor, Collection, Set)
get tags?
Some Git aware transports are able to implicitly grab an annotated tag if
TagOpt.AUTO_FOLLOW
or
TagOpt.FETCH_TAGS
was selected and the
object the tag peels to (references) was transferred as part of the last
FetchConnection.fetch(ProgressMonitor, Collection, Set)
call. If it is possible
for such tags to have been included in the transfer this method returns
true, allowing the caller to attempt tag discovery.
By returning only true/false (and not the actual list of tags obtained) the transport itself does not need to be aware of whether or not tags were included in the transfer.
didFetchIncludeTags
in interface FetchConnection
public boolean didFetchTestConnectivity()
FetchConnection.fetch(ProgressMonitor, Collection, Set)
validate
graph?
Some transports walk the object graph on the client side, with the client looking for what objects it is missing and requesting them individually from the remote peer. By virtue of completing the fetch call the client implicitly tested the object connectivity, as every object in the graph was either already local or was requested successfully from the peer. In such transports this method returns true.
Some transports assume the remote peer knows the Git object graph and is able to supply a fully connected graph to the client (although it may only be transferring the parts the client does not yet have). Its faster to assume such remote peers are well behaved and send the correct response to the client. In such transports this method returns false.
didFetchTestConnectivity
in interface FetchConnection
public void setPackLockMessage(java.lang.String message)
Callers that set a lock message must ensure they call
FetchConnection.getPackLocks()
after
FetchConnection.fetch(ProgressMonitor, Collection, Set)
, even if an exception
was thrown, and release the locks that are held.
setPackLockMessage
in interface FetchConnection
message
- message to use when holding a pack in place.public java.util.Collection<PackLock> getPackLocks()
FetchConnection.fetch(ProgressMonitor, Collection, Set)
call.getPackLocks
in interface FetchConnection
protected void doFetch(ProgressMonitor monitor, java.util.Collection<Ref> want, java.util.Set<ObjectId> have, java.io.OutputStream outputStream) throws TransportException
monitor
- progress monitor to receive status updates. If the monitor is
the NullProgressMonitor.INSTANCE
, then the no-progress
option enabled.want
- the advertised remote references the caller wants to fetch.have
- additional objects to assume that already exist locally. This
will be added to the set of objects reachable from the
destination repository's references.outputStream
- ouputStream to write sideband messages toTransportException
- if any exception occurs.public void close()
Close any resources used by this connection.
If the remote repository is contacted by a network socket this method must close that network socket, disconnecting the two peers. If the remote repository is actually local (same system) this method must close any open file handles used to read the "remote" repository.
If additional messages were produced by the remote peer, these should
still be retained in the connection instance for Connection.getMessages()
.
AutoClosable.close()
declares that it throws Exception
.
Implementers shouldn't throw checked exceptions. This override narrows
the signature to prevent them from doing so.
close
in interface java.lang.AutoCloseable
close
in interface Connection
close
in class BasePackConnection
BasePackFetchConnection.FetchConfig getFetchConfig()
private int maxTimeWanted(java.util.Collection<Ref> wants)
private void markReachable(java.util.Set<ObjectId> have, int maxTime) throws java.io.IOException
java.io.IOException
private void parseReachable(ObjectId id)
private boolean sendWants(java.util.Collection<Ref> want) throws java.io.IOException
java.io.IOException
private java.lang.String enableCapabilities() throws TransportException
TransportException
private void negotiate(ProgressMonitor monitor) throws java.io.IOException, BasePackFetchConnection.CancelledException
java.io.IOException
BasePackFetchConnection.CancelledException
private void negotiateBegin() throws java.io.IOException
java.io.IOException
private void markRefsAdvertised()
private void markAdvertised(AnyObjectId id)
private void markCommon(RevObject obj, PacketLineIn.AckNackResult anr) throws java.io.IOException
java.io.IOException
private void receivePack(ProgressMonitor monitor, java.io.OutputStream outputStream) throws java.io.IOException
java.io.IOException
protected void onReceivePack()
TransportHttp
to
disable its request magic and ensure the pack stream is read correctly.