summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorMatthias Sohn <matthias.sohn@sap.com>2018-12-25 23:58:53 +0100
committerMatthias Sohn <matthias.sohn@sap.com>2018-12-25 23:58:53 +0100
commit25deb304600242e4bffda53b9e41d46bcb301414 (patch)
tree0eb236acb820d1c537dbfcb7cf91839f1257a7f2 /org.eclipse.jgit
parentf4fc6404baac5a6a5db34f71e62fb62fd8f1b8ef (diff)
parent8eecb4f8b746bc01f09df02870e89d4bc4e118b9 (diff)
downloadjgit-25deb304600242e4bffda53b9e41d46bcb301414.tar.gz
jgit-25deb304600242e4bffda53b9e41d46bcb301414.zip
Merge branch 'stable-5.0' into stable-5.1
* stable-5.0: Call AdvertiseRefsHook for protocol v2 Prepare 4.11.7-SNAPSHOT builds JGit v4.11.6.201812241910-r Prepare 4.9.9-SNAPSHOT builds JGit v4.9.8.201812241815-r UploadPack: Test filtering by AdvertiseRefsHook in stateless transports Prepare 4.7.8-SNAPSHOT builds JGit v4.7.7.201812240805-r Fix feature versions imported by feature org.eclipse.jgit.pgm Prepare 4.5.6-SNAPSHOT builds JGit v4.5.5.201812240535-r Call AdvertiseRefsHook before validating wants Change-Id: Icdc212bf5be2485d0f8028acf6c62fb8531d0e3c Signed-off-by: Jonathan Nieder <jrn@google.com> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java79
1 files changed, 54 insertions, 25 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
index cd7290edcd..c753bcdc7a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -43,8 +43,9 @@
package org.eclipse.jgit.transport;
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toMap;
import static org.eclipse.jgit.lib.Constants.R_TAGS;
-import static org.eclipse.jgit.lib.RefDatabase.ALL;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_REF_IN_WANT;
import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_FETCH;
import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_LS_REFS;
@@ -262,7 +263,10 @@ public class UploadPack {
private OutputStream msgOut = NullOutputStream.INSTANCE;
- /** The refs we advertised as existing at the start of the connection. */
+ /**
+ * Refs eligible for advertising to the client, set using
+ * {@link #setAdvertisedRefs}.
+ */
private Map<String, Ref> refs;
/** Hook used while processing Git protocol v2 requests. */
@@ -271,6 +275,9 @@ public class UploadPack {
/** Hook used while advertising the refs to the client. */
private AdvertiseRefsHook advertiseRefsHook = AdvertiseRefsHook.DEFAULT;
+ /** Whether the {@link #advertiseRefsHook} has been invoked. */
+ private boolean advertiseRefsHookCalled;
+
/** Filter used while advertising the refs to the client. */
private RefFilter refFilter = RefFilter.DEFAULT;
@@ -793,11 +800,52 @@ public class UploadPack {
}
private Map<String, Ref> getAdvertisedOrDefaultRefs() throws IOException {
- if (refs == null)
- setAdvertisedRefs(db.getRefDatabase().getRefs(ALL));
+ if (refs != null) {
+ return refs;
+ }
+
+ advertiseRefsHook.advertiseRefs(this);
+ advertiseRefsHookCalled = true;
+ if (refs == null) {
+ // Fall back to all refs.
+ setAdvertisedRefs(
+ db.getRefDatabase().getRefs().stream()
+ .collect(toMap(Ref::getName, identity())));
+ }
return refs;
}
+ private Map<String, Ref> getFilteredRefs(Collection<String> refPrefixes)
+ throws IOException {
+ if (refPrefixes.isEmpty()) {
+ return getAdvertisedOrDefaultRefs();
+ }
+ if (refs == null && !advertiseRefsHookCalled) {
+ advertiseRefsHook.advertiseRefs(this);
+ advertiseRefsHookCalled = true;
+ }
+ if (refs == null) {
+ // Fast path: the advertised refs hook did not set advertised refs.
+ Map<String, Ref> rs = new HashMap<>();
+ for (String p : refPrefixes) {
+ for (Ref r : db.getRefDatabase().getRefsByPrefix(p)) {
+ rs.put(r.getName(), r);
+ }
+ }
+ if (refFilter != RefFilter.DEFAULT) {
+ return refFilter.filter(rs);
+ }
+ return transferConfig.getRefFilter().filter(rs);
+ }
+
+ // Slow path: filter the refs provided by the advertised refs hook.
+ // refFilter has already been applied to refs.
+ return refs.values().stream()
+ .filter(ref -> refPrefixes.stream()
+ .anyMatch(ref.getName()::startsWith))
+ .collect(toMap(Ref::getName, identity()));
+ }
+
private void service() throws IOException {
boolean sendPack = false;
// If it's a non-bidi request, we need to read the entire request before
@@ -923,17 +971,7 @@ public class UploadPack {
if (req.getPeel()) {
adv.setDerefTags(true);
}
- Map<String, Ref> refsToSend;
- if (req.getRefPrefixes().isEmpty()) {
- refsToSend = getAdvertisedOrDefaultRefs();
- } else {
- refsToSend = new HashMap<>();
- for (String refPrefix : req.getRefPrefixes()) {
- for (Ref ref : db.getRefDatabase().getRefsByPrefix(refPrefix)) {
- refsToSend.put(ref.getName(), ref);
- }
- }
- }
+ Map<String, Ref> refsToSend = getFilteredRefs(req.getRefPrefixes());
if (req.getSymrefs()) {
findSymrefs(adv, refsToSend);
}
@@ -1281,15 +1319,7 @@ public class UploadPack {
return;
}
- try {
- advertiseRefsHook.advertiseRefs(this);
- } catch (ServiceMayNotContinueException fail) {
- if (fail.getMessage() != null) {
- adv.writeOne("ERR " + fail.getMessage()); //$NON-NLS-1$
- fail.setOutput();
- }
- throw fail;
- }
+ Map<String, Ref> advertisedOrDefaultRefs = getAdvertisedOrDefaultRefs();
if (serviceName != null) {
adv.writeOne("# service=" + serviceName + '\n'); //$NON-NLS-1$
@@ -1321,7 +1351,6 @@ public class UploadPack {
adv.advertiseCapability(OPTION_FILTER);
}
adv.setDerefTags(true);
- Map<String, Ref> advertisedOrDefaultRefs = getAdvertisedOrDefaultRefs();
findSymrefs(adv, advertisedOrDefaultRefs);
advertised = adv.send(advertisedOrDefaultRefs);
if (adv.isEmpty())