diff options
author | Jonathan Tan <jonathantanmy@google.com> | 2018-07-24 08:41:17 -0700 |
---|---|---|
committer | Jonathan Nieder <jrn@google.com> | 2018-08-10 18:44:49 -0400 |
commit | c477b0ddcb68ac0b1c26270187d82fccc70802c6 (patch) | |
tree | 7609991fe05b4fd48b0b14709dc58d2ec1811ead /org.eclipse.jgit.test | |
parent | bd1a82502680b5de5bf86f6c4470185fd1602386 (diff) | |
download | jgit-c477b0ddcb68ac0b1c26270187d82fccc70802c6.tar.gz jgit-c477b0ddcb68ac0b1c26270187d82fccc70802c6.zip |
Support protocol v2 want-ref in UploadPack
UploadPack already allows the client to send wanted OIDs as "want"
lines. Extend UploadPack to also allow the client to send wanted ref
names as "want-ref" lines when the fetch is done using protocol v2.
The corresponding Git commit is 516e2b76bd ("upload-pack: implement
ref-in-want", 2018-06-28).
To support a two-stage rollout, two configuration variables are
provided: uploadpack.allowrefinwant (default "false") allows clients to
specify "want-ref" in their requests, and uploadpack.advertiserefinwant
(default "true") makes UploadPack advertise this capability. If
uploadpack.allowrefinwant is true but uploadpack.advertiserefinwant is
false, UploadPack will not advertise that it supports "want-ref", but it
will support it.
Change-Id: I3c24077949640d453af90d81a7f48ce4b8ac9833
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Diffstat (limited to 'org.eclipse.jgit.test')
-rw-r--r-- | org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java index 9f49073eae..7ef713bf45 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java @@ -1,11 +1,13 @@ package org.eclipse.jgit.transport; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.theInstance; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.Arrays; import java.util.Collections; @@ -505,6 +507,51 @@ public class UploadPackTest { } @Test + public void testV2CapabilitiesRefInWant() throws Exception { + server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true); + ByteArrayInputStream recvStream = + uploadPackV2Setup(null, null, PacketLineIn.END); + PacketLineIn pckIn = new PacketLineIn(recvStream); + + assertThat(pckIn.readString(), is("version 2")); + assertThat( + Arrays.asList(pckIn.readString(), pckIn.readString()), + // TODO(jonathantanmy) This check overspecifies the + // order of the capabilities of "fetch". + hasItems("ls-refs", "fetch=ref-in-want shallow")); + assertTrue(pckIn.readString() == PacketLineIn.END); + } + + @Test + public void testV2CapabilitiesRefInWantNotAdvertisedIfUnallowed() throws Exception { + server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", false); + ByteArrayInputStream recvStream = + uploadPackV2Setup(null, null, PacketLineIn.END); + PacketLineIn pckIn = new PacketLineIn(recvStream); + + assertThat(pckIn.readString(), is("version 2")); + assertThat( + Arrays.asList(pckIn.readString(), pckIn.readString()), + hasItems("ls-refs", "fetch=shallow")); + assertTrue(pckIn.readString() == PacketLineIn.END); + } + + @Test + public void testV2CapabilitiesRefInWantNotAdvertisedIfAdvertisingForbidden() throws Exception { + server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true); + server.getConfig().setBoolean("uploadpack", null, "advertiserefinwant", false); + ByteArrayInputStream recvStream = + uploadPackV2Setup(null, null, PacketLineIn.END); + PacketLineIn pckIn = new PacketLineIn(recvStream); + + assertThat(pckIn.readString(), is("version 2")); + assertThat( + Arrays.asList(pckIn.readString(), pckIn.readString()), + hasItems("ls-refs", "fetch=shallow")); + assertTrue(pckIn.readString() == PacketLineIn.END); + } + + @Test @SuppressWarnings("boxing") public void testV2EmptyRequest() throws Exception { ByteArrayInputStream recvStream = uploadPackV2(PacketLineIn.END); @@ -1161,6 +1208,178 @@ public class UploadPackTest { PacketLineIn.END); } + @Test + public void testV2FetchWantRefIfNotAllowed() throws Exception { + RevCommit one = remote.commit().message("1").create(); + remote.update("one", one); + + try { + uploadPackV2( + "command=fetch\n", + PacketLineIn.DELIM, + "want-ref refs/heads/one\n", + "done\n", + PacketLineIn.END); + } catch (PackProtocolException e) { + assertThat( + e.getMessage(), + containsString("unexpected want-ref refs/heads/one")); + return; + } + fail("expected PackProtocolException"); + } + + @Test + public void testV2FetchWantRef() throws Exception { + RevCommit one = remote.commit().message("1").create(); + RevCommit two = remote.commit().message("2").create(); + RevCommit three = remote.commit().message("3").create(); + remote.update("one", one); + remote.update("two", two); + remote.update("three", three); + + server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true); + + ByteArrayInputStream recvStream = uploadPackV2( + "command=fetch\n", + PacketLineIn.DELIM, + "want-ref refs/heads/one\n", + "want-ref refs/heads/two\n", + "done\n", + PacketLineIn.END); + PacketLineIn pckIn = new PacketLineIn(recvStream); + assertThat(pckIn.readString(), is("wanted-refs")); + assertThat( + Arrays.asList(pckIn.readString(), pckIn.readString()), + hasItems( + one.toObjectId().getName() + " refs/heads/one", + two.toObjectId().getName() + " refs/heads/two")); + assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM)); + assertThat(pckIn.readString(), is("packfile")); + parsePack(recvStream); + + assertTrue(client.hasObject(one.toObjectId())); + assertTrue(client.hasObject(two.toObjectId())); + assertFalse(client.hasObject(three.toObjectId())); + } + + @Test + public void testV2FetchBadWantRef() throws Exception { + RevCommit one = remote.commit().message("1").create(); + remote.update("one", one); + + server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true); + + try { + uploadPackV2( + "command=fetch\n", + PacketLineIn.DELIM, + "want-ref refs/heads/one\n", + "want-ref refs/heads/nonExistentRef\n", + "done\n", + PacketLineIn.END); + } catch (PackProtocolException e) { + assertThat( + e.getMessage(), + containsString("Invalid ref name: refs/heads/nonExistentRef")); + return; + } + fail("expected PackProtocolException"); + } + + @Test + public void testV2FetchMixedWantRef() throws Exception { + RevCommit one = remote.commit().message("1").create(); + RevCommit two = remote.commit().message("2").create(); + RevCommit three = remote.commit().message("3").create(); + remote.update("one", one); + remote.update("two", two); + remote.update("three", three); + + server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true); + + ByteArrayInputStream recvStream = uploadPackV2( + "command=fetch\n", + PacketLineIn.DELIM, + "want-ref refs/heads/one\n", + "want " + two.toObjectId().getName() + "\n", + "done\n", + PacketLineIn.END); + PacketLineIn pckIn = new PacketLineIn(recvStream); + assertThat(pckIn.readString(), is("wanted-refs")); + assertThat( + pckIn.readString(), + is(one.toObjectId().getName() + " refs/heads/one")); + assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM)); + assertThat(pckIn.readString(), is("packfile")); + parsePack(recvStream); + + assertTrue(client.hasObject(one.toObjectId())); + assertTrue(client.hasObject(two.toObjectId())); + assertFalse(client.hasObject(three.toObjectId())); + } + + @Test + public void testV2FetchWantRefWeAlreadyHave() throws Exception { + RevCommit one = remote.commit().message("1").create(); + remote.update("one", one); + + server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true); + + ByteArrayInputStream recvStream = uploadPackV2( + "command=fetch\n", + PacketLineIn.DELIM, + "want-ref refs/heads/one\n", + "have " + one.toObjectId().getName(), + "done\n", + PacketLineIn.END); + PacketLineIn pckIn = new PacketLineIn(recvStream); + + // The client still needs to know the hash of the object that + // refs/heads/one points to, even though it already has the + // object ... + assertThat(pckIn.readString(), is("wanted-refs")); + assertThat( + pckIn.readString(), + is(one.toObjectId().getName() + " refs/heads/one")); + assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM)); + + // ... but the client does not need the object itself. + assertThat(pckIn.readString(), is("packfile")); + parsePack(recvStream); + assertFalse(client.hasObject(one.toObjectId())); + } + + @Test + public void testV2FetchWantRefAndDeepen() throws Exception { + RevCommit parent = remote.commit().message("parent").create(); + RevCommit child = remote.commit().message("x").parent(parent).create(); + remote.update("branch1", child); + + server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true); + + ByteArrayInputStream recvStream = uploadPackV2( + "command=fetch\n", + PacketLineIn.DELIM, + "want-ref refs/heads/branch1\n", + "deepen 1\n", + "done\n", + PacketLineIn.END); + PacketLineIn pckIn = new PacketLineIn(recvStream); + + // wanted-refs appears first, then shallow-info. + assertThat(pckIn.readString(), is("wanted-refs")); + assertThat(pckIn.readString(), is(child.toObjectId().getName() + " refs/heads/branch1")); + assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM)); + assertThat(pckIn.readString(), is("shallow-info")); + assertThat(pckIn.readString(), is("shallow " + child.toObjectId().getName())); + assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM)); + assertThat(pckIn.readString(), is("packfile")); + parsePack(recvStream); + assertTrue(client.hasObject(child.toObjectId())); + assertFalse(client.hasObject(parent.toObjectId())); + } + private static class RejectAllRefFilter implements RefFilter { @Override public Map<String, Ref> filter(Map<String, Ref> refs) { |