summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java17
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java154
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java17
3 files changed, 165 insertions, 23 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
index 4ba446edbe..f85c22ddb5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
@@ -76,6 +76,7 @@ import org.eclipse.jgit.revwalk.RevFlag;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand.Result;
+import org.eclipse.jgit.transport.RefAdvertiser.PacketLineOutRefAdvertiser;
import org.eclipse.jgit.util.io.InterruptTimer;
import org.eclipse.jgit.util.io.TimeoutInputStream;
import org.eclipse.jgit.util.io.TimeoutOutputStream;
@@ -519,7 +520,7 @@ public class ReceivePack {
private void service() throws IOException {
if (biDirectionalPipe)
- sendAdvertisedRefs();
+ sendAdvertisedRefs(new PacketLineOutRefAdvertiser(pckOut));
else
refs = db.getAllRefs();
recvCommands();
@@ -574,9 +575,17 @@ public class ReceivePack {
}
}
- private void sendAdvertisedRefs() throws IOException {
+ /**
+ * Generate an advertisement of available refs and capabilities.
+ *
+ * @param adv
+ * the advertisement formatter.
+ * @throws IOException
+ * the formatter failed to write an advertisement.
+ */
+ public void sendAdvertisedRefs(final RefAdvertiser adv) throws IOException {
final RevFlag advertised = walk.newFlag("ADVERTISED");
- final RefAdvertiser adv = new RefAdvertiser(pckOut, walk, advertised);
+ adv.init(walk, advertised);
adv.advertiseCapability(CAPABILITY_DELETE_REFS);
adv.advertiseCapability(CAPABILITY_REPORT_STATUS);
if (allowOfsDelta)
@@ -589,7 +598,7 @@ public class ReceivePack {
adv.includeAdditionalHaves();
if (adv.isEmpty())
adv.advertiseId(ObjectId.zeroId(), "capabilities^{}");
- pckOut.end();
+ adv.end();
}
private void recvCommands() throws IOException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java
index 6a6053d941..2a06ed889e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java
@@ -61,12 +61,28 @@ import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;
/** Support for the start of {@link UploadPack} and {@link ReceivePack}. */
-class RefAdvertiser {
- private final PacketLineOut pckOut;
+public abstract class RefAdvertiser {
+ static class PacketLineOutRefAdvertiser extends RefAdvertiser {
+ private final PacketLineOut pckOut;
- private final RevWalk walk;
+ PacketLineOutRefAdvertiser(PacketLineOut out) {
+ pckOut = out;
+ }
+
+ @Override
+ protected void writeOne(final CharSequence line) throws IOException {
+ pckOut.writeString(line.toString());
+ }
- private final RevFlag ADVERTISED;
+ @Override
+ protected void end() throws IOException {
+ pckOut.end();
+ }
+ }
+
+ private RevWalk walk;
+
+ private RevFlag ADVERTISED;
private final StringBuilder tmpLine = new StringBuilder(100);
@@ -78,22 +94,72 @@ class RefAdvertiser {
private boolean first = true;
- RefAdvertiser(final PacketLineOut out, final RevWalk protoWalk,
- final RevFlag advertisedFlag) {
- pckOut = out;
+ /**
+ * Initialize a new advertisement formatter.
+ *
+ * @param protoWalk
+ * the RevWalk used to parse objects that are advertised.
+ * @param advertisedFlag
+ * flag marked on any advertised objects parsed out of the
+ * {@code protoWalk}'s object pool, permitting the caller to
+ * later quickly determine if an object was advertised (or not).
+ */
+ public void init(final RevWalk protoWalk, final RevFlag advertisedFlag) {
walk = protoWalk;
ADVERTISED = advertisedFlag;
}
- void setDerefTags(final boolean deref) {
+ /**
+ * Toggle tag peeling.
+ * <p>
+ * <p>
+ * This method must be invoked prior to any of the following:
+ * <ul>
+ * <li>{@link #send(Collection)}
+ * <li>{@link #advertiseHave(AnyObjectId)}
+ * <li>{@link #includeAdditionalHaves()}
+ * </ul>
+ *
+ * @param deref
+ * true to show the dereferenced value of a tag as the special
+ * ref <code>$tag^{}</code> ; false to omit it from the output.
+ */
+ public void setDerefTags(final boolean deref) {
derefTags = deref;
}
- void advertiseCapability(String name) {
+ /**
+ * Add one protocol capability to the initial advertisement.
+ * <p>
+ * This method must be invoked prior to any of the following:
+ * <ul>
+ * <li>{@link #send(Collection)}
+ * <li>{@link #advertiseHave(AnyObjectId)}
+ * <li>{@link #includeAdditionalHaves()}
+ * </ul>
+ *
+ * @param name
+ * the name of a single protocol capability supported by the
+ * caller. The set of capabilities are sent to the client in the
+ * advertisement, allowing the client to later selectively enable
+ * features it recognizes.
+ */
+ public void advertiseCapability(String name) {
capablities.add(name);
}
- void send(final Collection<Ref> refs) throws IOException {
+ /**
+ * Format an advertisement for the supplied refs.
+ *
+ * @param refs
+ * zero or more refs to format for the client. The collection is
+ * copied and sorted before display and therefore may appear in
+ * any order.
+ * @throws IOException
+ * the underlying output stream failed to write out an
+ * advertisement record.
+ */
+ public void send(final Collection<Ref> refs) throws IOException {
for (final Ref r : RefComparator.sort(refs)) {
final RevObject obj = parseAnyOrNull(r.getObjectId());
if (obj != null) {
@@ -104,7 +170,21 @@ class RefAdvertiser {
}
}
- void advertiseHave(AnyObjectId id) throws IOException {
+ /**
+ * Advertise one object is available using the magic {@code .have}.
+ * <p>
+ * The magic {@code .have} advertisement is not available for fetching by a
+ * client, but can be used by a client when considering a delta base
+ * candidate before transferring data in a push. Within the record created
+ * by this method the ref name is simply the invalid string {@code .have}.
+ *
+ * @param id
+ * identity of the object that is assumed to exist.
+ * @throws IOException
+ * the underlying output stream failed to write out an
+ * advertisement record.
+ */
+ public void advertiseHave(AnyObjectId id) throws IOException {
RevObject obj = parseAnyOrNull(id);
if (obj != null) {
advertiseAnyOnce(obj, ".have");
@@ -113,7 +193,14 @@ class RefAdvertiser {
}
}
- void includeAdditionalHaves() throws IOException {
+ /**
+ * Include references of alternate repositories as {@code .have} lines.
+ *
+ * @throws IOException
+ * the underlying output stream failed to write out an
+ * advertisement record.
+ */
+ public void includeAdditionalHaves() throws IOException {
additionalHaves(walk.getRepository().getObjectDatabase());
}
@@ -129,7 +216,8 @@ class RefAdvertiser {
advertiseHave(r.getObjectId());
}
- boolean isEmpty() {
+ /** @return true if no advertisements have been sent yet. */
+ public boolean isEmpty() {
return first;
}
@@ -172,7 +260,22 @@ class RefAdvertiser {
advertiseAny(tag.getObject(), refName);
}
- void advertiseId(final AnyObjectId id, final String refName)
+ /**
+ * Advertise one object under a specific name.
+ * <p>
+ * If the advertised object is a tag, this method does not advertise the
+ * peeled version of it.
+ *
+ * @param id
+ * the object to advertise.
+ * @param refName
+ * name of the reference to advertise the object as, can be any
+ * string not including the NUL byte.
+ * @throws IOException
+ * the underlying output stream failed to write out an
+ * advertisement record.
+ */
+ public void advertiseId(final AnyObjectId id, final String refName)
throws IOException {
tmpLine.setLength(0);
id.copyTo(tmpId, tmpLine);
@@ -190,6 +293,27 @@ class RefAdvertiser {
}
}
tmpLine.append('\n');
- pckOut.writeString(tmpLine.toString());
+ writeOne(tmpLine);
}
+
+ /**
+ * Write a single advertisement line.
+ *
+ * @param line
+ * the advertisement line to be written. The line always ends
+ * with LF. Never null or the empty string.
+ * @throws IOException
+ * the underlying output stream failed to write out an
+ * advertisement record.
+ */
+ protected abstract void writeOne(CharSequence line) throws IOException;
+
+ /**
+ * Mark the end of the advertisements.
+ *
+ * @throws IOException
+ * the underlying output stream failed to write out an
+ * advertisement record.
+ */
+ protected abstract void end() throws IOException;
}
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 fe2afbe9b7..6b81bc4925 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -70,6 +70,7 @@ import org.eclipse.jgit.revwalk.RevFlagSet;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.RefAdvertiser.PacketLineOutRefAdvertiser;
import org.eclipse.jgit.util.io.InterruptTimer;
import org.eclipse.jgit.util.io.TimeoutInputStream;
import org.eclipse.jgit.util.io.TimeoutOutputStream;
@@ -282,7 +283,7 @@ public class UploadPack {
private void service() throws IOException {
if (biDirectionalPipe)
- sendAdvertisedRefs();
+ sendAdvertisedRefs(new PacketLineOutRefAdvertiser(pckOut));
else {
refs = db.getAllRefs();
for (Ref r : refs.values()) {
@@ -309,8 +310,16 @@ public class UploadPack {
sendPack();
}
- private void sendAdvertisedRefs() throws IOException {
- final RefAdvertiser adv = new RefAdvertiser(pckOut, walk, ADVERTISED);
+ /**
+ * Generate an advertisement of available refs and capabilities.
+ *
+ * @param adv
+ * the advertisement formatter.
+ * @throws IOException
+ * the formatter failed to write an advertisement.
+ */
+ public void sendAdvertisedRefs(final RefAdvertiser adv) throws IOException {
+ adv.init(walk, ADVERTISED);
adv.advertiseCapability(OPTION_INCLUDE_TAG);
adv.advertiseCapability(OPTION_MULTI_ACK_DETAILED);
adv.advertiseCapability(OPTION_MULTI_ACK);
@@ -322,7 +331,7 @@ public class UploadPack {
adv.setDerefTags(true);
refs = db.getAllRefs();
adv.send(refs.values());
- pckOut.end();
+ adv.end();
}
private void recvWants() throws IOException {