From 3ec92dc2111e52ee605e504974748df6905fd380 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 13 Oct 2008 10:36:40 -0700 Subject: [PATCH] Check object connectivity during fetch if fsck is enabled If we are fetching over a pack oriented connection and we are doing object-level fsck validation we need to also verify the graph is fully connected after the fetch is complete. This additional check is necessary to ensure the peer didn't omit objects that we don't have, but which are listed as needing to be present. On the walk style fetch connection we can bypass this check, as the connectivity was implicitly verified by the walker as it downloaded objects and built its queue of things to fetch. Native pack and bundle transports however do not have this check built into them, and require that we execute the work ourselves. Signed-off-by: Shawn O. Pearce Signed-off-by: Robin Rosenberg --- .../jgit/transport/BasePackFetchConnection.java | 4 ++++ .../spearce/jgit/transport/FetchConnection.java | 22 ++++++++++++++++++++++ .../org/spearce/jgit/transport/FetchProcess.java | 13 +++++++++++-- .../spearce/jgit/transport/TransportBundle.java | 4 ++++ .../jgit/transport/WalkFetchConnection.java | 4 ++++ 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackFetchConnection.java b/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackFetchConnection.java index a542eb75..542a8a94 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackFetchConnection.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackFetchConnection.java @@ -146,6 +146,10 @@ abstract class BasePackFetchConnection extends BasePackConnection implements return false; } + public boolean didFetchTestConnectivity() { + return false; + } + protected void doFetch(final ProgressMonitor monitor, final Collection want) throws TransportException { try { diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/FetchConnection.java b/org.spearce.jgit/src/org/spearce/jgit/transport/FetchConnection.java index 9d25b0db..461ad711 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/FetchConnection.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/FetchConnection.java @@ -111,4 +111,26 @@ public interface FetchConnection extends Connection { * false if tags were not implicitly obtained. */ public boolean didFetchIncludeTags(); + + /** + * Did the last {@link #fetch(ProgressMonitor, Collection)} 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 tranports this method returns false. + * + * @return true if the last fetch had to perform a connectivity check on the + * client side in order to succeed; false if the last fetch assumed + * the remote peer supplied a complete graph. + */ + public boolean didFetchTestConnectivity(); } \ No newline at end of file diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java b/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java index 654572db..bb2d0518 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java @@ -118,7 +118,7 @@ class FetchProcess { final boolean includedTags; if (!askFor.isEmpty() && !askForIsComplete()) { - conn.fetch(monitor, askFor.values()); + fetchObjects(monitor); includedTags = conn.didFetchIncludeTags(); // Connection was used for object transfer. If we @@ -143,7 +143,7 @@ class FetchProcess { if (!askFor.isEmpty() && (!includedTags || !askForIsComplete())) { reopenConnection(); if (!askFor.isEmpty()) - conn.fetch(monitor, askFor.values()); + fetchObjects(monitor); } } } finally { @@ -171,6 +171,15 @@ class FetchProcess { } } + private void fetchObjects(final ProgressMonitor monitor) + throws TransportException { + conn.fetch(monitor, askFor.values()); + if (transport.isCheckFetchedObjects() + && !conn.didFetchTestConnectivity() && !askForIsComplete()) + throw new TransportException(transport.getURI(), + "peer did not supply a complete object graph"); + } + private void closeConnection() { if (conn != null) { conn.close(); diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportBundle.java b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportBundle.java index 5b321a0d..7d38b026 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportBundle.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportBundle.java @@ -165,6 +165,10 @@ abstract class TransportBundle extends PackTransport { return RawParseUtils.decode(Constants.CHARSET, hdrbuf, 0, lf); } + public boolean didFetchTestConnectivity() { + return false; + } + @Override protected void doFetch(final ProgressMonitor monitor, final Collection want) throws TransportException { diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkFetchConnection.java b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkFetchConnection.java index 56384546..d089f7b0 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkFetchConnection.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkFetchConnection.java @@ -189,6 +189,10 @@ class WalkFetchConnection extends BaseFetchConnection { workQueue = new LinkedList(); } + public boolean didFetchTestConnectivity() { + return true; + } + @Override protected void doFetch(final ProgressMonitor monitor, final Collection want) throws TransportException { -- 2.11.4.GIT