summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2009-10-06 19:23:33 -0700
committerShawn O. Pearce <spearce@spearce.org>2010-01-12 11:56:56 -0800
commit7ed6805425d69826ad19c96b352a6fd533ee4cb4 (patch)
tree930671a14c78a9823d8bed1fdc7e084cdb9e71e5 /org.eclipse.jgit
parente187618b6bc098f367d36c945f8518e4b2aeb63f (diff)
downloadjgit-7ed6805425d69826ad19c96b352a6fd533ee4cb4.tar.gz
jgit-7ed6805425d69826ad19c96b352a6fd533ee4cb4.zip
Expose RefAdvertiser for reuse outside of the transport package
By making this class and its methods public, and the actual writing abstract, we can reuse this code for other formats like writing an info/refs file for HTTP transports. Change-Id: Id0e349c30a0f5a8c1527e0e7383b80243819d9c5 Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
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 {