{"thread":{"id":"16098","subject":"[JGIT PATCH 0/3] Improved object validation","startedAt":"2008-10-30T17:46:22Z","lastAt":"2008-10-31T14:55:01Z","messageCount":6,"participants":["Shawn O. Pearce","Robin Rosenberg"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"94323","messageId":"1225388785-26818-1-git-send-email-spearce@spearce.org","threadId":"16098","inReplyTo":null,"subject":"[JGIT PATCH 0/3] Improved object validation","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-10-30T17:46:22Z","receivedAt":"2008-10-30T17:46:22Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"This is mostly a resend as I haven't heard anything on the series.\nOne new patch at the end, to handle '.' and '..' cases.\n\nShawn O. Pearce (3):\n  Check object connectivity during fetch if fsck is enabled\n  Add --[no-]thin and --[no-]fsck optiosn to fetch command line tool\n  Don't permit '.' or '..' in tree entries\n\n .../src/org/spearce/jgit/pgm/Fetch.java            |   20 +++++++++++++\n .../org/spearce/jgit/lib/ObjectCheckerTest.java    |   31 ++++++++++++++++++++\n .../src/org/spearce/jgit/lib/ObjectChecker.java    |    7 ++++\n .../jgit/transport/BasePackFetchConnection.java    |    4 ++\n .../spearce/jgit/transport/FetchConnection.java    |   22 ++++++++++++++\n .../org/spearce/jgit/transport/FetchProcess.java   |   13 +++++++-\n .../spearce/jgit/transport/TransportBundle.java    |    4 ++\n .../jgit/transport/WalkFetchConnection.java        |    4 ++\n 8 files changed, 103 insertions(+), 2 deletions(-)\n"},{"id":"94324","messageId":"1225388785-26818-2-git-send-email-spearce@spearce.org","threadId":"16098","inReplyTo":"1225388785-26818-1-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 1/3] Check object connectivity during fetch if fsck is enabled","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-10-30T17:46:23Z","receivedAt":"2008-10-30T17:46:23Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"If we are fetching over a pack oriented connection and we are doing\nobject-level fsck validation we need to also verify the graph is\nfully connected after the fetch is complete.  This additional check\nis necessary to ensure the peer didn't omit objects that we don't\nhave, but which are listed as needing to be present.\n\nOn the walk style fetch connection we can bypass this check, as the\nconnectivity was implicitly verified by the walker as it downloaded\nobjects and built its queue of things to fetch.  Native pack and\nbundle transports however do not have this check built into them,\nand require that we execute the work ourselves.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../jgit/transport/BasePackFetchConnection.java    |    4 +++\n .../spearce/jgit/transport/FetchConnection.java    |   22 ++++++++++++++++++++\n .../org/spearce/jgit/transport/FetchProcess.java   |   13 ++++++++++-\n .../spearce/jgit/transport/TransportBundle.java    |    4 +++\n .../jgit/transport/WalkFetchConnection.java        |    4 +++\n 5 files changed, 45 insertions(+), 2 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackFetchConnection.java b/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackFetchConnection.java\nindex a542eb7..542a8a9 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackFetchConnection.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackFetchConnection.java\n@@ -146,6 +146,10 @@ public boolean didFetchIncludeTags() {\n \t\treturn false;\n \t}\n \n+\tpublic boolean didFetchTestConnectivity() {\n+\t\treturn false;\n+\t}\n+\n \tprotected void doFetch(final ProgressMonitor monitor,\n \t\t\tfinal Collection<Ref> want) throws TransportException {\n \t\ttry {\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/FetchConnection.java b/org.spearce.jgit/src/org/spearce/jgit/transport/FetchConnection.java\nindex 9d25b0d..d93972d 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/FetchConnection.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/FetchConnection.java\n@@ -111,4 +111,26 @@ public void fetch(final ProgressMonitor monitor, final Collection<Ref> want)\n \t *         false if tags were not implicitly obtained.\n \t */\n \tpublic boolean didFetchIncludeTags();\n+\n+\t/**\n+\t * Did the last {@link #fetch(ProgressMonitor, Collection)} validate graph?\n+\t * <p>\n+\t * Some transports walk the object graph on the client side, with the client\n+\t * looking for what objects it is missing and requesting them individually\n+\t * from the remote peer. By virtue of completing the fetch call the client\n+\t * implicitly tested the object connectivity, as every object in the graph\n+\t * was either already local or was requested successfully from the peer. In\n+\t * such transports this method returns true.\n+\t * <p>\n+\t * Some transports assume the remote peer knows the Git object graph and is\n+\t * able to supply a fully connected graph to the client (although it may\n+\t * only be transferring the parts the client does not yet have). Its faster\n+\t * to assume such remote peers are well behaved and send the correct\n+\t * response to the client. In such tranports this method returns false.\n+\t * \n+\t * @return true if the last fetch had to perform a connectivity check on the\n+\t *         client side in order to succeed; false if the last fetch assumed\n+\t *         the remote peer supplied a complete graph.\n+\t */\n+\tpublic boolean didFetchTestConnectivity();\n }\n\\ No newline at end of file\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java b/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java\nindex 654572d..bb2d051 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/FetchProcess.java\n@@ -118,7 +118,7 @@ else if (tagopt == TagOpt.FETCH_TAGS)\n \n \t\t\tfinal boolean includedTags;\n \t\t\tif (!askFor.isEmpty() && !askForIsComplete()) {\n-\t\t\t\tconn.fetch(monitor, askFor.values());\n+\t\t\t\tfetchObjects(monitor);\n \t\t\t\tincludedTags = conn.didFetchIncludeTags();\n \n \t\t\t\t// Connection was used for object transfer. If we\n@@ -143,7 +143,7 @@ else if (tagopt == TagOpt.FETCH_TAGS)\n \t\t\t\tif (!askFor.isEmpty() && (!includedTags || !askForIsComplete())) {\n \t\t\t\t\treopenConnection();\n \t\t\t\t\tif (!askFor.isEmpty())\n-\t\t\t\t\t\tconn.fetch(monitor, askFor.values());\n+\t\t\t\t\t\tfetchObjects(monitor);\n \t\t\t\t}\n \t\t\t}\n \t\t} finally {\n@@ -171,6 +171,15 @@ else if (tagopt == TagOpt.FETCH_TAGS)\n \t\t}\n \t}\n \n+\tprivate void fetchObjects(final ProgressMonitor monitor)\n+\t\t\tthrows TransportException {\n+\t\tconn.fetch(monitor, askFor.values());\n+\t\tif (transport.isCheckFetchedObjects()\n+\t\t\t\t&& !conn.didFetchTestConnectivity() && !askForIsComplete())\n+\t\t\tthrow new TransportException(transport.getURI(),\n+\t\t\t\t\t\"peer did not supply a complete object graph\");\n+\t}\n+\n \tprivate void closeConnection() {\n \t\tif (conn != null) {\n \t\t\tconn.close();\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportBundle.java b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportBundle.java\nindex 5b321a0..7d38b02 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportBundle.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportBundle.java\n@@ -165,6 +165,10 @@ private String readLine(final byte[] hdrbuf) throws IOException {\n \t\t\treturn RawParseUtils.decode(Constants.CHARSET, hdrbuf, 0, lf);\n \t\t}\n \n+\t\tpublic boolean didFetchTestConnectivity() {\n+\t\t\treturn false;\n+\t\t}\n+\n \t\t@Override\n \t\tprotected void doFetch(final ProgressMonitor monitor,\n \t\t\t\tfinal Collection<Ref> want) throws TransportException {\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkFetchConnection.java b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkFetchConnection.java\nindex 5638454..d089f7b 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkFetchConnection.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkFetchConnection.java\n@@ -189,6 +189,10 @@ WalkFetchConnection(final WalkTransport wt, final WalkRemoteObjectDatabase w) {\n \t\tworkQueue = new LinkedList<ObjectId>();\n \t}\n \n+\tpublic boolean didFetchTestConnectivity() {\n+\t\treturn true;\n+\t}\n+\n \t@Override\n \tprotected void doFetch(final ProgressMonitor monitor,\n \t\t\tfinal Collection<Ref> want) throws TransportException {\n-- \n1.6.0.3.756.gb776d\n"},{"id":"94325","messageId":"1225388785-26818-3-git-send-email-spearce@spearce.org","threadId":"16098","inReplyTo":"1225388785-26818-2-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 2/3] Add --[no-]thin and --[no-]fsck optiosn to fetch command line tool","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-10-30T17:46:24Z","receivedAt":"2008-10-30T17:46:24Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"This way users can force verification on the fly, such as when\nfetching from an untrusted URL pasted on the command line.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/pgm/Fetch.java            |   20 ++++++++++++++++++++\n 1 files changed, 20 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java\nindex e14e213..ad7e08f 100644\n--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java\n+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java\n@@ -54,6 +54,22 @@\n \t@Option(name = \"--verbose\", aliases = { \"-v\" }, usage = \"be more verbose\")\n \tprivate boolean verbose;\n \n+\t@Option(name = \"--fsck\", usage = \"perform fsck style checks on receive\")\n+\tprivate Boolean fsck;\n+\n+\t@Option(name = \"--no-fsck\")\n+\tvoid nofsck(final boolean ignored) {\n+\t\tfsck = Boolean.FALSE;\n+\t}\n+\n+\t@Option(name = \"--thin\", usage = \"fetch thin pack\")\n+\tprivate Boolean thin;\n+\n+\t@Option(name = \"--no-thin\")\n+\tvoid nothin(final boolean ignored) {\n+\t\tthin = Boolean.FALSE;\n+\t}\n+\n \t@Argument(index = 0, metaVar = \"uri-ish\")\n \tprivate String remote = \"origin\";\n \n@@ -63,6 +79,10 @@\n \t@Override\n \tprotected void run() throws Exception {\n \t\tfinal Transport tn = Transport.open(db, remote);\n+\t\tif (fsck != null)\n+\t\t\ttn.setCheckFetchedObjects(fsck.booleanValue());\n+\t\tif (thin != null)\n+\t\t\ttn.setFetchThin(thin.booleanValue());\n \t\tfinal FetchResult r;\n \t\ttry {\n \t\t\tr = tn.fetch(new TextProgressMonitor(), toget);\n-- \n1.6.0.3.756.gb776d\n"},{"id":"94326","messageId":"1225388785-26818-4-git-send-email-spearce@spearce.org","threadId":"16098","inReplyTo":"1225388785-26818-3-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 3/3] Don't permit '.' or '..' in tree entries","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-10-30T17:46:25Z","receivedAt":"2008-10-30T17:46:25Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"A Git tree must not have '.' or '..' within the structure as these\nnames are reserved in every directory by the client operating system.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../org/spearce/jgit/lib/ObjectCheckerTest.java    |   31 ++++++++++++++++++++\n .../src/org/spearce/jgit/lib/ObjectChecker.java    |    7 ++++\n 2 files changed, 38 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ObjectCheckerTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ObjectCheckerTest.java\nindex fa37fb5..7befde8 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ObjectCheckerTest.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ObjectCheckerTest.java\n@@ -980,6 +980,13 @@ public void testValidTree5() throws CorruptObjectException {\n \t\tchecker.checkTree(data);\n \t}\n \n+\tpublic void testValidTree6() throws CorruptObjectException {\n+\t\tfinal StringBuilder b = new StringBuilder();\n+\t\tentry(b, \"100644 .a\");\n+\t\tfinal byte[] data = Constants.encodeASCII(b.toString());\n+\t\tchecker.checkTree(data);\n+\t}\n+\n \tpublic void testValidTreeSorting1() throws CorruptObjectException {\n \t\tfinal StringBuilder b = new StringBuilder();\n \t\tentry(b, \"100644 fooaaa\");\n@@ -1166,6 +1173,30 @@ public void testInvalidTreeNameIsEmpty() {\n \t\t}\n \t}\n \n+\tpublic void testInvalidTreeNameIsDot() {\n+\t\tfinal StringBuilder b = new StringBuilder();\n+\t\tentry(b, \"100644 .\");\n+\t\tfinal byte[] data = Constants.encodeASCII(b.toString());\n+\t\ttry {\n+\t\t\tchecker.checkTree(data);\n+\t\t\tfail(\"incorrectly accepted an invalid tree\");\n+\t\t} catch (CorruptObjectException e) {\n+\t\t\tassertEquals(\"invalid name '.'\", e.getMessage());\n+\t\t}\n+\t}\n+\n+\tpublic void testInvalidTreeNameIsDotDot() {\n+\t\tfinal StringBuilder b = new StringBuilder();\n+\t\tentry(b, \"100644 ..\");\n+\t\tfinal byte[] data = Constants.encodeASCII(b.toString());\n+\t\ttry {\n+\t\t\tchecker.checkTree(data);\n+\t\t\tfail(\"incorrectly accepted an invalid tree\");\n+\t\t} catch (CorruptObjectException e) {\n+\t\t\tassertEquals(\"invalid name '..'\", e.getMessage());\n+\t\t}\n+\t}\n+\n \tpublic void testInvalidTreeTruncatedInName() {\n \t\tfinal StringBuilder b = new StringBuilder();\n \t\tb.append(\"100644 b\");\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectChecker.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectChecker.java\nindex d403119..b303d6f 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectChecker.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectChecker.java\n@@ -318,6 +318,13 @@ public void checkTree(final byte[] raw) throws CorruptObjectException {\n \t\t\t}\n \t\t\tif (thisNameB + 1 == ptr)\n \t\t\t\tthrow new CorruptObjectException(\"zero length name\");\n+\t\t\tif (raw[thisNameB] == '.') {\n+\t\t\t\tfinal int nameLen = (ptr - 1) - thisNameB;\n+\t\t\t\tif (nameLen == 1)\n+\t\t\t\t\tthrow new CorruptObjectException(\"invalid name '.'\");\n+\t\t\t\tif (nameLen == 2 && raw[thisNameB + 1] == '.')\n+\t\t\t\t\tthrow new CorruptObjectException(\"invalid name '..'\");\n+\t\t\t}\n \t\t\tif (duplicateName(raw, thisNameB, ptr - 1))\n \t\t\t\tthrow new CorruptObjectException(\"duplicate entry names\");\n \n-- \n1.6.0.3.756.gb776d\n"},{"id":"94354","messageId":"200810310101.12241.robin.rosenberg@dewire.com","threadId":"16098","inReplyTo":"1225388785-26818-1-git-send-email-spearce@spearce.org","subject":"Re: [JGIT PATCH 0/3] Improved object validation","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-10-31T00:01:12Z","receivedAt":"2008-10-31T00:01:12Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"torsdagen den 30 oktober 2008 18.46.22 skrev Shawn O. Pearce:\n> This is mostly a resend as I haven't heard anything on the series.\n> One new patch at the end, to handle '.' and '..' cases.\nAck, pushed now.  I never got to the push action, because I wanted\nto do some testing on the bundlewriter (which you did not resubmit) and\nthe I went to a warmer place for a few days.\n\nThese patches and the bundlewrite + a small unit test for it now pushed.\n\n-- robin\n"},{"id":"94408","messageId":"20081031145501.GT14786@spearce.org","threadId":"16098","inReplyTo":"200810310101.12241.robin.rosenberg@dewire.com","subject":"Re: [JGIT PATCH 0/3] Improved object validation","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-10-31T14:55:01Z","receivedAt":"2008-10-31T14:55:01Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> torsdagen den 30 oktober 2008 18.46.22 skrev Shawn O. Pearce:\n> > This is mostly a resend as I haven't heard anything on the series.\n> > One new patch at the end, to handle '.' and '..' cases.\n> Ack, pushed now.  I never got to the push action, because I wanted\n> to do some testing on the bundlewriter (which you did not resubmit) and\n> the I went to a warmer place for a few days.\n> \n> These patches and the bundlewrite + a small unit test for it now pushed.\n\nThanks for putting together the bundle writer test.  I had to fix\nit a bit to avoid the /home/me path it had hardcoded in there.\nThis patch was applied on top of master and pushed out.\n\nI meant to work on a test for BundleWriter myself, but I got too busy\nwith other stuff and totally forgot about it.  I wasn't pushing to\nget the BundleWriter included as it was non-critical to my current\nneeds, but I had it written so I posted it in case someone else\ncared about it.\n\n--8<--\n[PATCH] Fix BundleWriter unit test to work for people who are not 'me'\n\nMy system lacks a /home/me as I do not call myself me.  My login is\nusually based upon my email address, and nobody else on my system is\n'me'.  So we cannot use hardcoded paths like /home/me in a test case.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../spearce/jgit/transport/BundleWriterTest.java   |   68 ++++++++++----------\n 1 files changed, 34 insertions(+), 34 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/transport/BundleWriterTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/transport/BundleWriterTest.java\nindex 4e33108..3cfb8b1 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/transport/BundleWriterTest.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/transport/BundleWriterTest.java\n@@ -37,11 +37,13 @@\n \n package org.spearce.jgit.transport;\n \n+import java.io.ByteArrayInputStream;\n+import java.io.ByteArrayOutputStream;\n import java.io.FileNotFoundException;\n-import java.io.FileOutputStream;\n import java.io.IOException;\n import java.net.URISyntaxException;\n import java.util.Collections;\n+import java.util.Set;\n \n import org.spearce.jgit.errors.MissingBundlePrerequisiteException;\n import org.spearce.jgit.errors.NotSupportedException;\n@@ -58,15 +60,14 @@\n \n \tpublic void testWrite0() throws Exception {\n \t\t// Create a tiny bundle, (well one of) the first commits only\n-\t\tURIish bundleURI = new URIish(\"file:///home/me/tmp/foo\");\n-\t\tmakeBundle(\"refs/heads/firstcommit\",\n-\t\t\t\t\"42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\", bundleURI, null);\n+\t\tfinal byte[] bundle = makeBundle(\"refs/heads/firstcommit\",\n+\t\t\t\t\"42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\", null);\n \n \t\t// Then we clone a new repo from that bundle and do a simple test. This\n \t\t// makes sure\n \t\t// we could read the bundle we created.\n \t\tRepository newRepo = createNewEmptyRepo();\n-\t\tFetchResult fetchResult = fetchFromBundle(newRepo, bundleURI);\n+\t\tFetchResult fetchResult = fetchFromBundle(newRepo, bundle);\n \t\tRef advertisedRef = fetchResult\n \t\t\t\t.getAdvertisedRef(\"refs/heads/firstcommit\");\n \n@@ -80,19 +81,20 @@ assertEquals(\"42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\", newRepo\n \n \t/**\n \t * Incremental bundle test\n-\t *\n+\t * \n \t * @throws Exception\n \t */\n \tpublic void testWrite1() throws Exception {\n+\t\tbyte[] bundle;\n+\n \t\t// Create a small bundle, an early commit\n-\t\tURIish bundleURI = new URIish(\"file:///home/me/tmp/foo\");\n-\t\tmakeBundle(\"refs/heads/aa\", db.resolve(\"a\").name(), bundleURI, null);\n+\t\tbundle = makeBundle(\"refs/heads/aa\", db.resolve(\"a\").name(), null);\n \n \t\t// Then we clone a new repo from that bundle and do a simple test. This\n \t\t// makes sure\n \t\t// we could read the bundle we created.\n \t\tRepository newRepo = createNewEmptyRepo();\n-\t\tFetchResult fetchResult = fetchFromBundle(newRepo, bundleURI);\n+\t\tFetchResult fetchResult = fetchFromBundle(newRepo, bundle);\n \t\tRef advertisedRef = fetchResult.getAdvertisedRef(\"refs/heads/aa\");\n \n \t\tassertEquals(db.resolve(\"a\").name(), advertisedRef.getObjectId().name());\n@@ -101,9 +103,9 @@ assertEquals(db.resolve(\"a\").name(), newRepo.resolve(\"refs/heads/aa\")\n \t\tassertNull(newRepo.resolve(\"refs/heads/a\"));\n \n \t\t// Next an incremental bundle\n-\t\tmakeBundle(\"refs/heads/cc\", db.resolve(\"c\").name(), bundleURI,\n+\t\tbundle = makeBundle(\"refs/heads/cc\", db.resolve(\"c\").name(),\n \t\t\t\tnew RevWalk(db).parseCommit(db.resolve(\"a\").toObjectId()));\n-\t\tfetchResult = fetchFromBundle(newRepo, bundleURI);\n+\t\tfetchResult = fetchFromBundle(newRepo, bundle);\n \t\tadvertisedRef = fetchResult.getAdvertisedRef(\"refs/heads/cc\");\n \t\tassertEquals(db.resolve(\"c\").name(), advertisedRef.getObjectId().name());\n \t\tassertEquals(db.resolve(\"c\").name(), newRepo.resolve(\"refs/heads/cc\")\n@@ -114,7 +116,7 @@ assertEquals(db.resolve(\"c\").name(), newRepo.resolve(\"refs/heads/cc\")\n \t\ttry {\n \t\t\t// Check that we actually needed the first bundle\n \t\t\tRepository newRepo2 = createNewEmptyRepo();\n-\t\t\tfetchResult = fetchFromBundle(newRepo2, bundleURI);\n+\t\t\tfetchResult = fetchFromBundle(newRepo2, bundle);\n \t\t\tfail(\"We should not be able to fetch from bundle with prerequisistes that are not fulfilled\");\n \t\t} catch (MissingBundlePrerequisiteException e) {\n \t\t\tassertTrue(e.getMessage()\n@@ -122,31 +124,29 @@ assertTrue(e.getMessage()\n \t\t}\n \t}\n \n-\tprivate FetchResult fetchFromBundle(Repository newRepo, URIish uriish)\n-\t\t\tthrows URISyntaxException, NotSupportedException,\n-\t\t\tTransportException {\n-\t\tRemoteConfig remoteConfig = new RemoteConfig(newRepo.getConfig(),\n-\t\t\t\t\"origin\");\n-\t\tremoteConfig.addURI(uriish);\n-\t\tRefSpec theRefSpec = new RefSpec(\"refs/heads/*:refs/heads/*\");\n-\t\tremoteConfig.addFetchRefSpec(theRefSpec);\n-\t\tTransport transport = Transport.open(newRepo, remoteConfig);\n-\t\tFetchResult fetch = transport.fetch(new NullProgressMonitor(),\n-\t\t\t\tCollections.singleton(theRefSpec));\n-\t\treturn fetch;\n+\tprivate FetchResult fetchFromBundle(final Repository newRepo,\n+\t\t\tfinal byte[] bundle) throws URISyntaxException,\n+\t\t\tNotSupportedException, TransportException {\n+\t\tfinal URIish uri = new URIish(\"in-memory://\");\n+\t\tfinal ByteArrayInputStream in = new ByteArrayInputStream(bundle);\n+\t\tfinal RefSpec rs = new RefSpec(\"refs/heads/*:refs/heads/*\");\n+\t\tfinal Set<RefSpec> refs = Collections.singleton(rs);\n+\t\treturn new TransportBundleStream(newRepo, uri, in).fetch(\n+\t\t\t\tNullProgressMonitor.INSTANCE, refs);\n \t}\n \n-\tprivate void makeBundle(String name, String anObjectToInclude,\n-\t\t\tURIish bundleName, RevCommit assume) throws FileNotFoundException,\n-\t\t\tIOException {\n-\t\tBundleWriter bundleWriter = new BundleWriter(db,\n-\t\t\t\tnew NullProgressMonitor());\n-\t\tbundleWriter.include(name, ObjectId.fromString(anObjectToInclude));\n+\tprivate byte[] makeBundle(final String name,\n+\t\t\tfinal String anObjectToInclude, final RevCommit assume)\n+\t\t\tthrows FileNotFoundException, IOException {\n+\t\tfinal BundleWriter bw;\n+\n+\t\tbw = new BundleWriter(db, NullProgressMonitor.INSTANCE);\n+\t\tbw.include(name, ObjectId.fromString(anObjectToInclude));\n \t\tif (assume != null)\n-\t\t\tbundleWriter.assume(assume);\n-\t\tFileOutputStream os = new FileOutputStream(bundleName.getPath());\n-\t\tbundleWriter.writeBundle(os);\n-\t\tos.close();\n+\t\t\tbw.assume(assume);\n+\t\tfinal ByteArrayOutputStream out = new ByteArrayOutputStream();\n+\t\tbw.writeBundle(out);\n+\t\treturn out.toByteArray();\n \t}\n \n }\n-- \n1.6.0.3.756.gb776d\n\n-- \nShawn.\n"}]}