aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java105
1 files changed, 67 insertions, 38 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
index 8909380176..be0d37b96e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
@@ -12,10 +12,10 @@
package org.eclipse.jgit.transport;
-import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DELIM;
import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DEEPEN;
import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DEEPEN_NOT;
import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DEEPEN_SINCE;
+import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DELIM;
import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DONE;
import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_END;
import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_ERR;
@@ -32,10 +32,11 @@ import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -334,7 +335,6 @@ public abstract class BasePackFetchConnection extends BasePackConnection
}
}
- /** {@inheritDoc} */
@Override
public final void fetch(final ProgressMonitor monitor,
final Collection<Ref> want, final Set<ObjectId> have)
@@ -342,7 +342,6 @@ public abstract class BasePackFetchConnection extends BasePackConnection
fetch(monitor, want, have, null);
}
- /** {@inheritDoc} */
@Override
public final void fetch(final ProgressMonitor monitor,
final Collection<Ref> want, final Set<ObjectId> have,
@@ -351,25 +350,21 @@ public abstract class BasePackFetchConnection extends BasePackConnection
doFetch(monitor, want, have, outputStream);
}
- /** {@inheritDoc} */
@Override
public boolean didFetchIncludeTags() {
return false;
}
- /** {@inheritDoc} */
@Override
public boolean didFetchTestConnectivity() {
return false;
}
- /** {@inheritDoc} */
@Override
public void setPackLockMessage(String message) {
lockMessage = message;
}
- /** {@inheritDoc} */
@Override
public Collection<PackLock> getPackLocks() {
if (packLock != null)
@@ -406,11 +401,14 @@ public abstract class BasePackFetchConnection extends BasePackConnection
protected void doFetch(final ProgressMonitor monitor,
final Collection<Ref> want, final Set<ObjectId> have,
OutputStream outputStream) throws TransportException {
+ boolean hasObjects = !have.isEmpty();
try {
noProgress = monitor == NullProgressMonitor.INSTANCE;
- markRefsAdvertised();
- markReachable(want, have, maxTimeWanted(want));
+ if (hasObjects) {
+ markRefsAdvertised();
+ }
+ markReachable(want, have, maxTimeWanted(want, hasObjects));
if (TransferConfig.ProtocolVersion.V2
.equals(getProtocolVersion())) {
@@ -422,7 +420,7 @@ public abstract class BasePackFetchConnection extends BasePackConnection
state = new TemporaryBuffer.Heap(Integer.MAX_VALUE);
pckState = new PacketLineOut(state);
try {
- doFetchV2(monitor, want, outputStream);
+ doFetchV2(monitor, want, outputStream, hasObjects);
} finally {
clearState();
}
@@ -434,7 +432,7 @@ public abstract class BasePackFetchConnection extends BasePackConnection
pckState = new PacketLineOut(state);
}
PacketLineOut output = statelessRPC ? pckState : pckOut;
- if (sendWants(want, output)) {
+ if (sendWants(want, output, hasObjects)) {
boolean mayHaveShallow = depth != null || deepenSince != null || !deepenNots.isEmpty();
Set<ObjectId> shallowCommits = local.getObjectDatabase().getShallowCommits();
if (isCapableOf(GitProtocolConstants.CAPABILITY_SHALLOW)) {
@@ -461,7 +459,8 @@ public abstract class BasePackFetchConnection extends BasePackConnection
}
private void doFetchV2(ProgressMonitor monitor, Collection<Ref> want,
- OutputStream outputStream) throws IOException, CancelledException {
+ OutputStream outputStream, boolean hasObjects)
+ throws IOException, CancelledException {
sideband = true;
negotiateBegin();
@@ -483,7 +482,7 @@ public abstract class BasePackFetchConnection extends BasePackConnection
pckState.writeString(capability);
}
- if (!sendWants(want, pckState)) {
+ if (!sendWants(want, pckState, hasObjects)) {
// We already have everything we wanted.
return;
}
@@ -659,7 +658,6 @@ public abstract class BasePackFetchConnection extends BasePackConnection
return gotReady;
}
- /** {@inheritDoc} */
@Override
public void close() {
if (walk != null)
@@ -671,8 +669,12 @@ public abstract class BasePackFetchConnection extends BasePackConnection
return local.getConfig().get(FetchConfig::new);
}
- private int maxTimeWanted(Collection<Ref> wants) {
+ private int maxTimeWanted(Collection<Ref> wants, boolean hasObjects) {
int maxTime = 0;
+ if (!hasObjects) {
+ // we don't have any objects locally, we can immediately bail out
+ return maxTime;
+ }
for (Ref r : wants) {
try {
final RevObject obj = walk.parseAny(r.getObjectId());
@@ -689,36 +691,30 @@ public abstract class BasePackFetchConnection extends BasePackConnection
}
private void markReachable(Collection<Ref> want, Set<ObjectId> have,
- int maxTime)
- throws IOException {
- Set<String> wantRefs = want.stream().map(Ref::getName)
- .collect(Collectors.toSet());
-
- for (Ref r : local.getRefDatabase().getRefs()) {
- if (useNegotiationTip && !wantRefs.contains(r.getName())) {
- continue;
+ int maxTime) throws IOException {
+ Collection<Ref> refsToMark;
+ if (useNegotiationTip) {
+ refsToMark = translateToLocalTips(want);
+ if (refsToMark.size() < want.size()) {
+ refsToMark.addAll(local.getRefDatabase().getRefs());
}
-
- ObjectId id = r.getPeeledObjectId();
- if (id == null)
- id = r.getObjectId();
- if (id == null)
- continue;
- parseReachable(id);
+ } else {
+ refsToMark = local.getRefDatabase().getRefs();
}
+ markReachableRefTips(refsToMark);
for (ObjectId id : local.getAdditionalHaves())
- parseReachable(id);
+ markReachable(id);
for (ObjectId id : have)
- parseReachable(id);
+ markReachable(id);
if (maxTime > 0) {
// Mark reachable commits until we reach maxTime. These may
// wind up later matching up against things we want and we
// can avoid asking for something we already happen to have.
//
- final Date maxWhen = new Date(maxTime * 1000L);
+ Instant maxWhen = Instant.ofEpochSecond(maxTime);
walk.sort(RevSort.COMMIT_TIME_DESC);
walk.markStart(reachableCommits);
walk.setRevFilter(CommitTimeRevFilter.after(maxWhen));
@@ -738,7 +734,37 @@ public abstract class BasePackFetchConnection extends BasePackConnection
}
}
- private void parseReachable(ObjectId id) {
+ private Collection<Ref> translateToLocalTips(Collection<Ref> want)
+ throws IOException {
+ String[] refs = want.stream().map(Ref::getName)
+ .collect(Collectors.toSet()).toArray(String[]::new);
+ Map<String, Ref> wantRefMap = local.getRefDatabase().exactRef(refs);
+ return wantRefMap.values().stream()
+ .filter(r -> getRefObjectId(r) != null)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Marks commits reachable.
+ *
+ * @param refsToMark
+ * references that client is requesting to be marked.
+ */
+ private void markReachableRefTips(Collection<Ref> refsToMark) {
+ refsToMark.stream().map(BasePackFetchConnection::getRefObjectId)
+ .filter(Objects::nonNull)
+ .forEach(oid -> markReachable(oid));
+ }
+
+ private static ObjectId getRefObjectId(Ref ref) {
+ ObjectId id = ref.getPeeledObjectId();
+ if (id == null) {
+ id = ref.getObjectId();
+ }
+ return id;
+ }
+
+ private void markReachable(ObjectId id) {
try {
RevCommit o = walk.parseCommit(id);
if (!o.has(REACHABLE)) {
@@ -750,7 +776,8 @@ public abstract class BasePackFetchConnection extends BasePackConnection
}
}
- private boolean sendWants(Collection<Ref> want, PacketLineOut p)
+ private boolean sendWants(Collection<Ref> want, PacketLineOut p,
+ boolean hasObjects)
throws IOException {
boolean first = true;
for (Ref r : want) {
@@ -759,7 +786,9 @@ public abstract class BasePackFetchConnection extends BasePackConnection
continue;
}
// if depth is set we need to fetch the objects even if they are already available
- if (transport.getDepth() == null) {
+ if (transport.getDepth() == null
+ // only check reachable objects when we have objects
+ && hasObjects) {
try {
if (walk.parseAny(objectId).has(REACHABLE)) {
// We already have this object. Asking for it is
@@ -845,7 +874,7 @@ public abstract class BasePackFetchConnection extends BasePackConnection
if (statelessRPC && multiAck != MultiAck.DETAILED) {
// Our stateless RPC implementation relies upon the detailed
// ACK status to tell us common objects for reuse in future
- // requests. If its not enabled, we can't talk to the peer.
+ // requests. If its not enabled, we can't talk to the peer.
//
throw new PackProtocolException(uri, MessageFormat.format(
JGitText.get().statelessRPCRequiresOptionToBeEnabled,