Refactor IndexPack to not require local filesystem
By moving the logic that parses a pack stream from the network (or a bundle) into a type that can be constructed by an ObjectInserter, repository implementations have a chance to inject their own logic for storing object data received into the destination repository. The API isn't completely generic yet, there are still quite a few assumptions that the PackParser subclass is storing the data onto the local filesystem as a single file. But its about the simplest split of IndexPack I can come up with without completely ripping the code apart. Change-Id: I5b167c9cc6d7a7c56d0197c62c0fd0036a83ec6c Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
This commit is contained in:
parent
51dedfdc31
commit
1bf0c3cdb1
|
@ -45,12 +45,12 @@
|
|||
package org.eclipse.jgit.pgm;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
|
||||
import org.kohsuke.args4j.Argument;
|
||||
import org.kohsuke.args4j.Option;
|
||||
import org.eclipse.jgit.lib.CoreConfig;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.TextProgressMonitor;
|
||||
import org.eclipse.jgit.storage.file.ObjectDirectoryPackParser;
|
||||
import org.eclipse.jgit.transport.PackParser;
|
||||
import org.kohsuke.args4j.Option;
|
||||
|
||||
class IndexPack extends TextBuiltin {
|
||||
@Option(name = "--fix-thin", usage = "usage_fixAThinPackToBeComplete")
|
||||
|
@ -59,20 +59,21 @@ class IndexPack extends TextBuiltin {
|
|||
@Option(name = "--index-version", usage = "usage_indexFileFormatToCreate")
|
||||
private int indexVersion = -1;
|
||||
|
||||
@Argument(index = 0, required = true, metaVar = "metaVar_base")
|
||||
private File base;
|
||||
|
||||
@Override
|
||||
protected void run() throws Exception {
|
||||
if (indexVersion == -1)
|
||||
indexVersion = db.getConfig().get(CoreConfig.KEY)
|
||||
.getPackIndexVersion();
|
||||
final BufferedInputStream in;
|
||||
final org.eclipse.jgit.transport.IndexPack ip;
|
||||
in = new BufferedInputStream(System.in);
|
||||
ip = new org.eclipse.jgit.transport.IndexPack(db, in, base);
|
||||
ip.setFixThin(fixThin);
|
||||
ip.setIndexVersion(indexVersion);
|
||||
ip.index(new TextProgressMonitor());
|
||||
BufferedInputStream in = new BufferedInputStream(System.in);
|
||||
ObjectInserter inserter = db.newObjectInserter();
|
||||
try {
|
||||
PackParser p = inserter.newPackParser(in);
|
||||
p.setAllowThin(fixThin);
|
||||
if (indexVersion != -1 && p instanceof ObjectDirectoryPackParser) {
|
||||
ObjectDirectoryPackParser imp = (ObjectDirectoryPackParser) p;
|
||||
imp.setIndexVersion(indexVersion);
|
||||
}
|
||||
p.parse(new TextProgressMonitor());
|
||||
inserter.flush();
|
||||
} finally {
|
||||
inserter.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
import org.eclipse.jgit.lib.ObjectStream;
|
||||
import org.eclipse.jgit.revwalk.RevBlob;
|
||||
import org.eclipse.jgit.storage.pack.DeltaEncoder;
|
||||
import org.eclipse.jgit.transport.IndexPack;
|
||||
import org.eclipse.jgit.transport.PackParser;
|
||||
import org.eclipse.jgit.util.IO;
|
||||
import org.eclipse.jgit.util.NB;
|
||||
import org.eclipse.jgit.util.TemporaryBuffer;
|
||||
|
@ -212,11 +212,9 @@ public void testDelta_SmallObjectChain() throws Exception {
|
|||
deflate(pack, delta3);
|
||||
|
||||
digest(pack);
|
||||
final byte[] raw = pack.toByteArray();
|
||||
IndexPack ip = IndexPack.create(repo, new ByteArrayInputStream(raw));
|
||||
ip.setFixThin(true);
|
||||
ip.index(NullProgressMonitor.INSTANCE);
|
||||
ip.renameAndOpenPack();
|
||||
PackParser ip = index(pack.toByteArray());
|
||||
ip.setAllowThin(true);
|
||||
ip.parse(NullProgressMonitor.INSTANCE);
|
||||
|
||||
assertTrue("has blob", wc.has(id3));
|
||||
|
||||
|
@ -273,11 +271,9 @@ public void testDelta_LargeObjectChain() throws Exception {
|
|||
deflate(pack, delta3);
|
||||
|
||||
digest(pack);
|
||||
final byte[] raw = pack.toByteArray();
|
||||
IndexPack ip = IndexPack.create(repo, new ByteArrayInputStream(raw));
|
||||
ip.setFixThin(true);
|
||||
ip.index(NullProgressMonitor.INSTANCE);
|
||||
ip.renameAndOpenPack();
|
||||
PackParser ip = index(pack.toByteArray());
|
||||
ip.setAllowThin(true);
|
||||
ip.parse(NullProgressMonitor.INSTANCE);
|
||||
|
||||
assertTrue("has blob", wc.has(id3));
|
||||
|
||||
|
@ -364,4 +360,18 @@ private void digest(TemporaryBuffer.Heap buf) throws IOException {
|
|||
md.update(buf.toByteArray());
|
||||
buf.write(md.digest());
|
||||
}
|
||||
|
||||
private ObjectInserter inserter;
|
||||
|
||||
@After
|
||||
public void release() {
|
||||
if (inserter != null)
|
||||
inserter.release();
|
||||
}
|
||||
|
||||
private PackParser index(byte[] raw) throws IOException {
|
||||
if (inserter == null)
|
||||
inserter = repo.newObjectInserter();
|
||||
return inserter.newPackParser(new ByteArrayInputStream(raw));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
package org.eclipse.jgit.storage.file;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
|
@ -52,7 +53,6 @@
|
|||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -66,14 +66,14 @@
|
|||
import org.eclipse.jgit.junit.JGitTestUtil;
|
||||
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.SampleDataRepositoryTestCase;
|
||||
import org.eclipse.jgit.lib.TextProgressMonitor;
|
||||
import org.eclipse.jgit.revwalk.RevObject;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.storage.file.PackIndex.MutableEntry;
|
||||
import org.eclipse.jgit.storage.pack.PackConfig;
|
||||
import org.eclipse.jgit.storage.pack.PackWriter;
|
||||
import org.eclipse.jgit.transport.IndexPack;
|
||||
import org.eclipse.jgit.transport.PackParser;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -92,28 +92,34 @@ public class PackWriterTest extends SampleDataRepositoryTestCase {
|
|||
|
||||
private ByteArrayOutputStream os;
|
||||
|
||||
private File packBase;
|
||||
|
||||
private File packFile;
|
||||
|
||||
private File indexFile;
|
||||
|
||||
private PackFile pack;
|
||||
|
||||
private ObjectInserter inserter;
|
||||
|
||||
private FileRepository dst;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
os = new ByteArrayOutputStream();
|
||||
packBase = new File(trash, "tmp_pack");
|
||||
packFile = new File(trash, "tmp_pack.pack");
|
||||
indexFile = new File(trash, "tmp_pack.idx");
|
||||
config = new PackConfig(db);
|
||||
|
||||
dst = createBareRepository();
|
||||
File alt = new File(dst.getObjectDatabase().getDirectory(), "info/alternates");
|
||||
alt.getParentFile().mkdirs();
|
||||
write(alt, db.getObjectDatabase().getDirectory().getAbsolutePath() + "\n");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (writer != null)
|
||||
if (writer != null) {
|
||||
writer.release();
|
||||
writer = null;
|
||||
}
|
||||
if (inserter != null) {
|
||||
inserter.release();
|
||||
inserter = null;
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
|
@ -408,6 +414,11 @@ public void testWriteIndex() throws Exception {
|
|||
config.setIndexVersion(2);
|
||||
writeVerifyPack4(false);
|
||||
|
||||
File packFile = pack.getPackFile();
|
||||
String name = packFile.getName();
|
||||
String base = name.substring(0, name.lastIndexOf('.'));
|
||||
File indexFile = new File(packFile.getParentFile(), base + ".idx");
|
||||
|
||||
// Validate that IndexPack came up with the right CRC32 value.
|
||||
final PackIndex idx1 = PackIndex.open(indexFile);
|
||||
assertTrue(idx1 instanceof PackIndexV2);
|
||||
|
@ -544,23 +555,31 @@ private void createVerifyOpenPack(final Iterator<RevObject> objectSource)
|
|||
}
|
||||
|
||||
private void verifyOpenPack(final boolean thin) throws IOException {
|
||||
final byte[] packData = os.toByteArray();
|
||||
|
||||
if (thin) {
|
||||
final InputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||
final IndexPack indexer = new IndexPack(db, is, packBase);
|
||||
PackParser p = index(packData);
|
||||
try {
|
||||
indexer.index(new TextProgressMonitor());
|
||||
p.parse(NullProgressMonitor.INSTANCE);
|
||||
fail("indexer should grumble about missing object");
|
||||
} catch (IOException x) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
final InputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||
final IndexPack indexer = new IndexPack(db, is, packBase);
|
||||
indexer.setKeepEmpty(true);
|
||||
indexer.setFixThin(thin);
|
||||
indexer.setIndexVersion(2);
|
||||
indexer.index(new TextProgressMonitor());
|
||||
pack = new PackFile(indexFile, packFile);
|
||||
|
||||
ObjectDirectoryPackParser p = (ObjectDirectoryPackParser) index(packData);
|
||||
p.setKeepEmpty(true);
|
||||
p.setAllowThin(thin);
|
||||
p.setIndexVersion(2);
|
||||
p.parse(NullProgressMonitor.INSTANCE);
|
||||
pack = p.getPackFile();
|
||||
assertNotNull("have PackFile after parsing", pack);
|
||||
}
|
||||
|
||||
private PackParser index(final byte[] packData) throws IOException {
|
||||
if (inserter == null)
|
||||
inserter = dst.newObjectInserter();
|
||||
return inserter.newPackParser(new ByteArrayInputStream(packData));
|
||||
}
|
||||
|
||||
private void verifyObjectsOrder(final ObjectId objectsOrder[]) {
|
||||
|
|
|
@ -61,13 +61,15 @@
|
|||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.lib.RepositoryTestCase;
|
||||
import org.eclipse.jgit.lib.TextProgressMonitor;
|
||||
import org.eclipse.jgit.revwalk.RevBlob;
|
||||
import org.eclipse.jgit.storage.file.ObjectDirectoryPackParser;
|
||||
import org.eclipse.jgit.storage.file.PackFile;
|
||||
import org.eclipse.jgit.util.NB;
|
||||
import org.eclipse.jgit.util.TemporaryBuffer;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
|
@ -76,8 +78,7 @@
|
|||
* to make sure they contain the expected objects (well we don't test
|
||||
* for all of them unless the packs are very small).
|
||||
*/
|
||||
public class IndexPackTest extends RepositoryTestCase {
|
||||
|
||||
public class PackParserTest extends RepositoryTestCase {
|
||||
/**
|
||||
* Test indexing one of the test packs in the egit repo. It has deltas.
|
||||
*
|
||||
|
@ -88,9 +89,10 @@ public void test1() throws IOException {
|
|||
File packFile = JGitTestUtil.getTestResourceFile("pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.pack");
|
||||
final InputStream is = new FileInputStream(packFile);
|
||||
try {
|
||||
IndexPack pack = new IndexPack(db, is, new File(trash, "tmp_pack1"));
|
||||
pack.index(new TextProgressMonitor());
|
||||
PackFile file = new PackFile(new File(trash, "tmp_pack1.idx"), new File(trash, "tmp_pack1.pack"));
|
||||
ObjectDirectoryPackParser p = (ObjectDirectoryPackParser) index(is);
|
||||
p.parse(NullProgressMonitor.INSTANCE);
|
||||
PackFile file = p.getPackFile();
|
||||
|
||||
assertTrue(file.hasObject(ObjectId.fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904")));
|
||||
assertTrue(file.hasObject(ObjectId.fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab")));
|
||||
assertTrue(file.hasObject(ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259")));
|
||||
|
@ -115,9 +117,10 @@ public void test2() throws IOException {
|
|||
File packFile = JGitTestUtil.getTestResourceFile("pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.pack");
|
||||
final InputStream is = new FileInputStream(packFile);
|
||||
try {
|
||||
IndexPack pack = new IndexPack(db, is, new File(trash, "tmp_pack2"));
|
||||
pack.index(new TextProgressMonitor());
|
||||
PackFile file = new PackFile(new File(trash, "tmp_pack2.idx"), new File(trash, "tmp_pack2.pack"));
|
||||
ObjectDirectoryPackParser p = (ObjectDirectoryPackParser) index(is);
|
||||
p.parse(NullProgressMonitor.INSTANCE);
|
||||
PackFile file = p.getPackFile();
|
||||
|
||||
assertTrue(file.hasObject(ObjectId.fromString("02ba32d3649e510002c21651936b7077aa75ffa9")));
|
||||
assertTrue(file.hasObject(ObjectId.fromString("0966a434eb1a025db6b71485ab63a3bfbea520b6")));
|
||||
assertTrue(file.hasObject(ObjectId.fromString("09efc7e59a839528ac7bda9fa020dc9101278680")));
|
||||
|
@ -151,11 +154,9 @@ public void testTinyThinPack() throws Exception {
|
|||
|
||||
digest(pack);
|
||||
|
||||
final byte[] raw = pack.toByteArray();
|
||||
IndexPack ip = IndexPack.create(db, new ByteArrayInputStream(raw));
|
||||
ip.setFixThin(true);
|
||||
ip.index(NullProgressMonitor.INSTANCE);
|
||||
ip.renameAndOpenPack();
|
||||
PackParser p = index(new ByteArrayInputStream(pack.toByteArray()));
|
||||
p.setAllowThin(true);
|
||||
p.parse(NullProgressMonitor.INSTANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -171,10 +172,9 @@ public void testPackWithDuplicateBlob() throws Exception {
|
|||
deflate(pack, data);
|
||||
digest(pack);
|
||||
|
||||
final byte[] raw = pack.toByteArray();
|
||||
IndexPack ip = IndexPack.create(db, new ByteArrayInputStream(raw));
|
||||
ip.index(NullProgressMonitor.INSTANCE);
|
||||
ip.renameAndOpenPack();
|
||||
PackParser p = index(new ByteArrayInputStream(pack.toByteArray()));
|
||||
p.setAllowThin(false);
|
||||
p.parse(NullProgressMonitor.INSTANCE);
|
||||
}
|
||||
|
||||
private void packHeader(TemporaryBuffer.Heap tinyPack, int cnt)
|
||||
|
@ -205,4 +205,18 @@ private void digest(TemporaryBuffer.Heap buf) throws IOException {
|
|||
md.update(buf.toByteArray());
|
||||
buf.write(md.digest());
|
||||
}
|
||||
|
||||
private ObjectInserter inserter;
|
||||
|
||||
@After
|
||||
public void release() {
|
||||
if (inserter != null)
|
||||
inserter.release();
|
||||
}
|
||||
|
||||
private PackParser index(InputStream in) throws IOException {
|
||||
if (inserter == null)
|
||||
inserter = db.newObjectInserter();
|
||||
return inserter.newPackParser(in);
|
||||
}
|
||||
}
|
|
@ -67,6 +67,7 @@
|
|||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.ObjectLoader;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
|
@ -536,12 +537,22 @@ private void digest(TemporaryBuffer.Heap buf) throws IOException {
|
|||
buf.write(md.digest());
|
||||
}
|
||||
|
||||
private ObjectInserter inserter;
|
||||
|
||||
@After
|
||||
public void release() {
|
||||
if (inserter != null)
|
||||
inserter.release();
|
||||
}
|
||||
|
||||
private void openPack(TemporaryBuffer.Heap buf) throws IOException {
|
||||
if (inserter == null)
|
||||
inserter = src.newObjectInserter();
|
||||
|
||||
final byte[] raw = buf.toByteArray();
|
||||
IndexPack ip = IndexPack.create(src, new ByteArrayInputStream(raw));
|
||||
ip.setFixThin(true);
|
||||
ip.index(PM);
|
||||
ip.renameAndOpenPack();
|
||||
PackParser p = inserter.newPackParser(new ByteArrayInputStream(raw));
|
||||
p.setAllowThin(true);
|
||||
p.parse(PM);
|
||||
}
|
||||
|
||||
private static PacketLineIn asPacketLineIn(TemporaryBuffer.Heap buf)
|
||||
|
|
|
@ -95,7 +95,6 @@ public int getCompression() {
|
|||
|
||||
/**
|
||||
* @return the preferred pack index file format; 0 for oldest possible.
|
||||
* @see org.eclipse.jgit.transport.IndexPack
|
||||
*/
|
||||
public int getPackIndexVersion() {
|
||||
return packIndexVersion;
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
import java.io.InputStream;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import org.eclipse.jgit.transport.PackParser;
|
||||
|
||||
/**
|
||||
* Inserts objects into an existing {@code ObjectDatabase}.
|
||||
* <p>
|
||||
|
@ -73,6 +75,11 @@ public ObjectId insert(int objectType, long length, InputStream in)
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackParser newPackParser(InputStream in) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
// Do nothing.
|
||||
|
@ -282,6 +289,19 @@ public ObjectId insert(int type, byte[] data, int off, int len)
|
|||
public abstract ObjectId insert(int objectType, long length, InputStream in)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Initialize a parser to read from a pack formatted stream.
|
||||
*
|
||||
* @param in
|
||||
* the input stream. The stream is not closed by the parser, and
|
||||
* must instead be closed by the caller once parsing is complete.
|
||||
* @return the pack parser.
|
||||
* @throws IOException
|
||||
* the parser instance, which can be configured and then used to
|
||||
* parse objects into the ObjectDatabase.
|
||||
*/
|
||||
public abstract PackParser newPackParser(InputStream in) throws IOException;
|
||||
|
||||
/**
|
||||
* Make all inserted objects visible.
|
||||
* <p>
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
import org.eclipse.jgit.lib.ObjectLoader;
|
||||
import org.eclipse.jgit.storage.pack.ObjectToPack;
|
||||
import org.eclipse.jgit.storage.pack.PackWriter;
|
||||
import org.eclipse.jgit.util.FS;
|
||||
|
||||
/**
|
||||
* The cached instance of an {@link ObjectDirectory}.
|
||||
|
@ -132,6 +133,11 @@ Config getConfig() {
|
|||
return wrapped.getConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
FS getFS() {
|
||||
return wrapped.getFS();
|
||||
}
|
||||
|
||||
@Override
|
||||
AlternateHandle[] myAlternates() {
|
||||
if (alts == null) {
|
||||
|
@ -233,6 +239,11 @@ InsertLooseObjectResult insertUnpackedObject(File tmp, ObjectId objectId,
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
PackFile openPack(File pack, File idx) throws IOException {
|
||||
return wrapped.openPack(pack, idx);
|
||||
}
|
||||
|
||||
@Override
|
||||
void selectObjectRepresentation(PackWriter packer, ObjectToPack otp,
|
||||
WindowCursor curs) throws IOException {
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
import org.eclipse.jgit.lib.ObjectReader;
|
||||
import org.eclipse.jgit.storage.pack.ObjectToPack;
|
||||
import org.eclipse.jgit.storage.pack.PackWriter;
|
||||
import org.eclipse.jgit.util.FS;
|
||||
|
||||
abstract class FileObjectDatabase extends ObjectDatabase {
|
||||
static enum InsertLooseObjectResult {
|
||||
|
@ -132,6 +133,8 @@ abstract void resolve(Set<ObjectId> matches, AbbreviatedObjectId id)
|
|||
|
||||
abstract Config getConfig();
|
||||
|
||||
abstract FS getFS();
|
||||
|
||||
/**
|
||||
* Open an object from this database.
|
||||
* <p>
|
||||
|
@ -278,6 +281,8 @@ abstract long getObjectSize2(WindowCursor curs, String objectName,
|
|||
abstract InsertLooseObjectResult insertUnpackedObject(File tmp,
|
||||
ObjectId id, boolean createDuplicate) throws IOException;
|
||||
|
||||
abstract PackFile openPack(File pack, File idx) throws IOException;
|
||||
|
||||
abstract FileObjectDatabase newCachedFileObjectDatabase();
|
||||
|
||||
static class AlternateHandle {
|
||||
|
|
|
@ -233,11 +233,13 @@ public Collection<PackFile> getPacks() {
|
|||
* path of the pack file to open.
|
||||
* @param idx
|
||||
* path of the corresponding index file.
|
||||
* @return the pack that was opened and added to the database.
|
||||
* @throws IOException
|
||||
* index file could not be opened, read, or is not recognized as
|
||||
* a Git pack file index.
|
||||
*/
|
||||
public void openPack(final File pack, final File idx) throws IOException {
|
||||
public PackFile openPack(final File pack, final File idx)
|
||||
throws IOException {
|
||||
final String p = pack.getName();
|
||||
final String i = idx.getName();
|
||||
|
||||
|
@ -250,7 +252,9 @@ public void openPack(final File pack, final File idx) throws IOException {
|
|||
if (!p.substring(0, 45).equals(i.substring(0, 45)))
|
||||
throw new IOException(MessageFormat.format(JGitText.get().packDoesNotMatchIndex, pack));
|
||||
|
||||
insertPack(new PackFile(idx, pack));
|
||||
PackFile res = new PackFile(idx, pack);
|
||||
insertPack(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -519,6 +523,11 @@ Config getConfig() {
|
|||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
FS getFS() {
|
||||
return fs;
|
||||
}
|
||||
|
||||
private void insertPack(final PackFile pf) {
|
||||
PackList o, n;
|
||||
do {
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.transport.PackParser;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
|
||||
/** Creates loose objects in a {@link ObjectDirectory}. */
|
||||
|
@ -100,6 +101,11 @@ public ObjectId insert(final int type, long len, final InputStream is)
|
|||
throw new ObjectWritingException("Unable to create new object: " + dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackParser newPackParser(InputStream in) throws IOException {
|
||||
return new ObjectDirectoryPackParser(db, in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
// Do nothing. Objects are immediately visible.
|
||||
|
|
|
@ -0,0 +1,480 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2011, Google Inc.
|
||||
* Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com>
|
||||
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
|
||||
* and other copyright owners as documented in the project's IP log.
|
||||
*
|
||||
* This program and the accompanying materials are made available
|
||||
* under the terms of the Eclipse Distribution License v1.0 which
|
||||
* accompanies this distribution, is reproduced below, and is
|
||||
* available at http://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* - Neither the name of the Eclipse Foundation, Inc. nor the
|
||||
* names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.eclipse.jgit.storage.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.security.MessageDigest;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import org.eclipse.jgit.JGitText;
|
||||
import org.eclipse.jgit.lib.AnyObjectId;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.CoreConfig;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.ProgressMonitor;
|
||||
import org.eclipse.jgit.transport.PackParser;
|
||||
import org.eclipse.jgit.transport.PackedObjectInfo;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.eclipse.jgit.util.NB;
|
||||
|
||||
/**
|
||||
* Consumes a pack stream and stores as a pack file in {@link ObjectDirectory}.
|
||||
* <p>
|
||||
* To obtain an instance of a parser, applications should use
|
||||
* {@link ObjectInserter#newPackParser(InputStream)}.
|
||||
*/
|
||||
public class ObjectDirectoryPackParser extends PackParser {
|
||||
private final FileObjectDatabase db;
|
||||
|
||||
/** CRC-32 computation for objects that are appended onto the pack. */
|
||||
private final CRC32 crc;
|
||||
|
||||
/** Running SHA-1 of any base objects appended after {@link #origEnd}. */
|
||||
private final MessageDigest tailDigest;
|
||||
|
||||
/** Preferred format version of the pack-*.idx file to generate. */
|
||||
private int indexVersion;
|
||||
|
||||
/** If true, pack with 0 objects will be stored. Usually these are deleted. */
|
||||
private boolean keepEmpty;
|
||||
|
||||
/** Path of the temporary file holding the pack data. */
|
||||
private File tmpPack;
|
||||
|
||||
/**
|
||||
* Path of the index created for the pack, to find objects quickly at read
|
||||
* time.
|
||||
*/
|
||||
private File tmpIdx;
|
||||
|
||||
/** Read/write handle to {@link #tmpPack} while it is being parsed. */
|
||||
private RandomAccessFile out;
|
||||
|
||||
/** Length of the original pack stream, before missing bases were appended. */
|
||||
private long origEnd;
|
||||
|
||||
/** The original checksum of data up to {@link #origEnd}. */
|
||||
private byte[] origHash;
|
||||
|
||||
/** Current end of the pack file. */
|
||||
private long packEnd;
|
||||
|
||||
/** Checksum of the entire pack file. */
|
||||
private byte[] packHash;
|
||||
|
||||
/** Compresses delta bases when completing a thin pack. */
|
||||
private Deflater def;
|
||||
|
||||
/** The pack that was created, if parsing was successful. */
|
||||
private PackFile newPack;
|
||||
|
||||
ObjectDirectoryPackParser(FileObjectDatabase odb, InputStream src) {
|
||||
super(odb, src);
|
||||
this.db = odb;
|
||||
this.crc = new CRC32();
|
||||
this.tailDigest = Constants.newMessageDigest();
|
||||
|
||||
indexVersion = db.getConfig().get(CoreConfig.KEY).getPackIndexVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pack index file format version this instance will create.
|
||||
*
|
||||
* @param version
|
||||
* the version to write. The special version 0 designates the
|
||||
* oldest (most compatible) format available for the objects.
|
||||
* @see PackIndexWriter
|
||||
*/
|
||||
public void setIndexVersion(int version) {
|
||||
indexVersion = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure this index pack instance to keep an empty pack.
|
||||
* <p>
|
||||
* By default an empty pack (a pack with no objects) is not kept, as doi so
|
||||
* is completely pointless. With no objects in the pack there is no d stored
|
||||
* by it, so the pack is unnecessary.
|
||||
*
|
||||
* @param empty
|
||||
* true to enable keeping an empty pack.
|
||||
*/
|
||||
public void setKeepEmpty(final boolean empty) {
|
||||
keepEmpty = empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the imported {@link PackFile}.
|
||||
* <p>
|
||||
* This method is supplied only to support testing; applications shouldn't
|
||||
* be using it directly to access the imported data.
|
||||
*
|
||||
* @return the imported PackFile, if parsing was successful.
|
||||
*/
|
||||
public PackFile getPackFile() {
|
||||
return newPack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackLock parse(ProgressMonitor progress) throws IOException {
|
||||
tmpPack = File.createTempFile("incoming_", ".pack", db.getDirectory());
|
||||
tmpIdx = new File(db.getDirectory(), baseName(tmpPack) + ".idx");
|
||||
try {
|
||||
out = new RandomAccessFile(tmpPack, "rw");
|
||||
|
||||
super.parse(progress);
|
||||
|
||||
out.seek(packEnd);
|
||||
out.write(packHash);
|
||||
out.getChannel().force(true);
|
||||
out.close();
|
||||
|
||||
writeIdx();
|
||||
|
||||
tmpPack.setReadOnly();
|
||||
tmpIdx.setReadOnly();
|
||||
|
||||
return renameAndOpenPack(getLockMessage());
|
||||
} finally {
|
||||
if (def != null)
|
||||
def.end();
|
||||
try {
|
||||
if (out != null && out.getChannel().isOpen())
|
||||
out.close();
|
||||
} catch (IOException closeError) {
|
||||
// Ignored. We want to delete the file.
|
||||
}
|
||||
cleanupTemporaryFiles();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBeginWholeObject(long streamPosition, int type,
|
||||
long inflatedSize) throws IOException {
|
||||
crc.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onEndWholeObject(PackedObjectInfo info) throws IOException {
|
||||
info.setCRC((int) crc.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBeginOfsDelta(long streamPosition,
|
||||
long baseStreamPosition, long inflatedSize) throws IOException {
|
||||
crc.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBeginRefDelta(long streamPosition, AnyObjectId baseId,
|
||||
long inflatedSize) throws IOException {
|
||||
crc.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UnresolvedDelta onEndDelta() throws IOException {
|
||||
UnresolvedDelta delta = new UnresolvedDelta();
|
||||
delta.setCRC((int) crc.getValue());
|
||||
return delta;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onObjectHeader(Source src, byte[] raw, int pos, int len)
|
||||
throws IOException {
|
||||
crc.update(raw, pos, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onObjectData(Source src, byte[] raw, int pos, int len)
|
||||
throws IOException {
|
||||
crc.update(raw, pos, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStoreStream(byte[] raw, int pos, int len)
|
||||
throws IOException {
|
||||
out.write(raw, pos, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPackFooter(byte[] hash) throws IOException {
|
||||
packEnd = out.getFilePointer();
|
||||
origEnd = packEnd;
|
||||
origHash = hash;
|
||||
packHash = hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectTypeAndSize seekDatabase(UnresolvedDelta delta,
|
||||
ObjectTypeAndSize info) throws IOException {
|
||||
out.seek(delta.getOffset());
|
||||
crc.reset();
|
||||
return readObjectHeader(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectTypeAndSize seekDatabase(PackedObjectInfo obj,
|
||||
ObjectTypeAndSize info) throws IOException {
|
||||
out.seek(obj.getOffset());
|
||||
crc.reset();
|
||||
return readObjectHeader(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int readDatabase(byte[] dst, int pos, int cnt) throws IOException {
|
||||
return out.read(dst, pos, cnt);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkCRC(int oldCRC) {
|
||||
return oldCRC == (int) crc.getValue();
|
||||
}
|
||||
|
||||
private static String baseName(File tmpPack) {
|
||||
String name = tmpPack.getName();
|
||||
return name.substring(0, name.lastIndexOf('.'));
|
||||
}
|
||||
|
||||
private void cleanupTemporaryFiles() {
|
||||
if (tmpIdx != null && !tmpIdx.delete() && tmpIdx.exists())
|
||||
tmpIdx.deleteOnExit();
|
||||
if (tmpPack != null && !tmpPack.delete() && tmpPack.exists())
|
||||
tmpPack.deleteOnExit();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAppendBase(final int typeCode, final byte[] data,
|
||||
final PackedObjectInfo info) throws IOException {
|
||||
info.setOffset(packEnd);
|
||||
|
||||
final byte[] buf = buffer();
|
||||
int sz = data.length;
|
||||
int len = 0;
|
||||
buf[len++] = (byte) ((typeCode << 4) | sz & 15);
|
||||
sz >>>= 4;
|
||||
while (sz > 0) {
|
||||
buf[len - 1] |= 0x80;
|
||||
buf[len++] = (byte) (sz & 0x7f);
|
||||
sz >>>= 7;
|
||||
}
|
||||
|
||||
tailDigest.update(buf, 0, len);
|
||||
crc.reset();
|
||||
crc.update(buf, 0, len);
|
||||
out.seek(packEnd);
|
||||
out.write(buf, 0, len);
|
||||
packEnd += len;
|
||||
|
||||
if (def == null)
|
||||
def = new Deflater(Deflater.DEFAULT_COMPRESSION, false);
|
||||
else
|
||||
def.reset();
|
||||
def.setInput(data);
|
||||
def.finish();
|
||||
|
||||
while (!def.finished()) {
|
||||
len = def.deflate(buf);
|
||||
tailDigest.update(buf, 0, len);
|
||||
crc.update(buf, 0, len);
|
||||
out.write(buf, 0, len);
|
||||
packEnd += len;
|
||||
}
|
||||
|
||||
info.setCRC((int) crc.getValue());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onEndThinPack() throws IOException {
|
||||
final byte[] tailHash = this.tailDigest.digest();
|
||||
final byte[] buf = buffer();
|
||||
|
||||
final MessageDigest origDigest = Constants.newMessageDigest();
|
||||
final MessageDigest tailDigest = Constants.newMessageDigest();
|
||||
final MessageDigest packDigest = Constants.newMessageDigest();
|
||||
|
||||
long origRemaining = origEnd;
|
||||
out.seek(0);
|
||||
out.readFully(buf, 0, 12);
|
||||
origDigest.update(buf, 0, 12);
|
||||
origRemaining -= 12;
|
||||
|
||||
NB.encodeInt32(buf, 8, getObjectCount());
|
||||
out.seek(0);
|
||||
out.write(buf, 0, 12);
|
||||
packDigest.update(buf, 0, 12);
|
||||
|
||||
for (;;) {
|
||||
final int n = out.read(buf);
|
||||
if (n < 0)
|
||||
break;
|
||||
if (origRemaining != 0) {
|
||||
final int origCnt = (int) Math.min(n, origRemaining);
|
||||
origDigest.update(buf, 0, origCnt);
|
||||
origRemaining -= origCnt;
|
||||
if (origRemaining == 0)
|
||||
tailDigest.update(buf, origCnt, n - origCnt);
|
||||
} else
|
||||
tailDigest.update(buf, 0, n);
|
||||
|
||||
packDigest.update(buf, 0, n);
|
||||
}
|
||||
|
||||
if (!Arrays.equals(origDigest.digest(), origHash)
|
||||
|| !Arrays.equals(tailDigest.digest(), tailHash))
|
||||
throw new IOException(
|
||||
JGitText.get().packCorruptedWhileWritingToFilesystem);
|
||||
|
||||
packHash = packDigest.digest();
|
||||
}
|
||||
|
||||
private void writeIdx() throws IOException {
|
||||
List<PackedObjectInfo> list = getSortedObjectList(null /* by ObjectId */);
|
||||
final FileOutputStream os = new FileOutputStream(tmpIdx);
|
||||
try {
|
||||
final PackIndexWriter iw;
|
||||
if (indexVersion <= 0)
|
||||
iw = PackIndexWriter.createOldestPossible(os, list);
|
||||
else
|
||||
iw = PackIndexWriter.createVersion(os, indexVersion);
|
||||
iw.write(list, packHash);
|
||||
os.getChannel().force(true);
|
||||
} finally {
|
||||
os.close();
|
||||
}
|
||||
}
|
||||
|
||||
private PackLock renameAndOpenPack(final String lockMessage)
|
||||
throws IOException {
|
||||
if (!keepEmpty && getObjectCount() == 0) {
|
||||
cleanupTemporaryFiles();
|
||||
return null;
|
||||
}
|
||||
|
||||
final MessageDigest d = Constants.newMessageDigest();
|
||||
final byte[] oeBytes = new byte[Constants.OBJECT_ID_LENGTH];
|
||||
for (int i = 0; i < getObjectCount(); i++) {
|
||||
final PackedObjectInfo oe = getObject(i);
|
||||
oe.copyRawTo(oeBytes, 0);
|
||||
d.update(oeBytes);
|
||||
}
|
||||
|
||||
final String name = ObjectId.fromRaw(d.digest()).name();
|
||||
final File packDir = new File(db.getDirectory(), "pack");
|
||||
final File finalPack = new File(packDir, "pack-" + name + ".pack");
|
||||
final File finalIdx = new File(packDir, "pack-" + name + ".idx");
|
||||
final PackLock keep = new PackLock(finalPack, db.getFS());
|
||||
|
||||
if (!packDir.exists() && !packDir.mkdir() && !packDir.exists()) {
|
||||
// The objects/pack directory isn't present, and we are unable
|
||||
// to create it. There is no way to move this pack in.
|
||||
//
|
||||
cleanupTemporaryFiles();
|
||||
throw new IOException(MessageFormat.format(
|
||||
JGitText.get().cannotCreateDirectory, packDir
|
||||
.getAbsolutePath()));
|
||||
}
|
||||
|
||||
if (finalPack.exists()) {
|
||||
// If the pack is already present we should never replace it.
|
||||
//
|
||||
cleanupTemporaryFiles();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (lockMessage != null) {
|
||||
// If we have a reason to create a keep file for this pack, do
|
||||
// so, or fail fast and don't put the pack in place.
|
||||
//
|
||||
try {
|
||||
if (!keep.lock(lockMessage))
|
||||
throw new IOException(MessageFormat.format(
|
||||
JGitText.get().cannotLockPackIn, finalPack));
|
||||
} catch (IOException e) {
|
||||
cleanupTemporaryFiles();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tmpPack.renameTo(finalPack)) {
|
||||
cleanupTemporaryFiles();
|
||||
keep.unlock();
|
||||
throw new IOException(MessageFormat.format(
|
||||
JGitText.get().cannotMovePackTo, finalPack));
|
||||
}
|
||||
|
||||
if (!tmpIdx.renameTo(finalIdx)) {
|
||||
cleanupTemporaryFiles();
|
||||
keep.unlock();
|
||||
if (!finalPack.delete())
|
||||
finalPack.deleteOnExit();
|
||||
throw new IOException(MessageFormat.format(
|
||||
JGitText.get().cannotMoveIndexTo, finalIdx));
|
||||
}
|
||||
|
||||
try {
|
||||
newPack = db.openPack(finalPack, finalIdx);
|
||||
} catch (IOException err) {
|
||||
keep.unlock();
|
||||
if (finalPack.exists())
|
||||
FileUtils.delete(finalPack);
|
||||
if (finalIdx.exists())
|
||||
FileUtils.delete(finalIdx);
|
||||
throw err;
|
||||
}
|
||||
|
||||
return lockMessage != null ? keep : null;
|
||||
}
|
||||
}
|
|
@ -61,6 +61,7 @@
|
|||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.MutableObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.ProgressMonitor;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Config.SectionParser;
|
||||
|
@ -635,17 +636,21 @@ private void markCommon(final RevObject obj, final AckNackResult anr)
|
|||
}
|
||||
|
||||
private void receivePack(final ProgressMonitor monitor) throws IOException {
|
||||
final IndexPack ip;
|
||||
|
||||
InputStream input = in;
|
||||
if (sideband)
|
||||
input = new SideBandInputStream(input, monitor, getMessageWriter());
|
||||
|
||||
ip = IndexPack.create(local, input);
|
||||
ip.setFixThin(thinPack);
|
||||
ip.setObjectChecking(transport.isCheckFetchedObjects());
|
||||
ip.index(monitor);
|
||||
packLock = ip.renameAndOpenPack(lockMessage);
|
||||
ObjectInserter ins = local.newObjectInserter();
|
||||
try {
|
||||
PackParser parser = ins.newPackParser(input);
|
||||
parser.setAllowThin(thinPack);
|
||||
parser.setObjectChecking(transport.isCheckFetchedObjects());
|
||||
parser.setLockMessage(lockMessage);
|
||||
packLock = parser.parse(monitor);
|
||||
ins.flush();
|
||||
} finally {
|
||||
ins.release();
|
||||
}
|
||||
}
|
||||
|
||||
private static class CancelledException extends Exception {
|
||||
|
|
|
@ -66,8 +66,10 @@
|
|||
import org.eclipse.jgit.errors.PackProtocolException;
|
||||
import org.eclipse.jgit.errors.TransportException;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectIdRef;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.ProgressMonitor;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
|
@ -96,7 +98,7 @@ class BundleFetchConnection extends BaseFetchConnection {
|
|||
|
||||
BundleFetchConnection(Transport transportBundle, final InputStream src) throws TransportException {
|
||||
transport = transportBundle;
|
||||
bin = new BufferedInputStream(src, IndexPack.BUFFER_SIZE);
|
||||
bin = new BufferedInputStream(src);
|
||||
try {
|
||||
switch (readSignature()) {
|
||||
case 2:
|
||||
|
@ -179,9 +181,17 @@ protected void doFetch(final ProgressMonitor monitor,
|
|||
throws TransportException {
|
||||
verifyPrerequisites();
|
||||
try {
|
||||
final IndexPack ip = newIndexPack();
|
||||
ip.index(monitor);
|
||||
packLock = ip.renameAndOpenPack(lockMessage);
|
||||
ObjectInserter ins = transport.local.newObjectInserter();
|
||||
try {
|
||||
PackParser parser = ins.newPackParser(bin);
|
||||
parser.setAllowThin(true);
|
||||
parser.setObjectChecking(transport.isCheckFetchedObjects());
|
||||
parser.setLockMessage(lockMessage);
|
||||
packLock = parser.parse(NullProgressMonitor.INSTANCE);
|
||||
ins.flush();
|
||||
} finally {
|
||||
ins.release();
|
||||
}
|
||||
} catch (IOException err) {
|
||||
close();
|
||||
throw new TransportException(transport.uri, err.getMessage(), err);
|
||||
|
@ -201,13 +211,6 @@ public Collection<PackLock> getPackLocks() {
|
|||
return Collections.<PackLock> emptyList();
|
||||
}
|
||||
|
||||
private IndexPack newIndexPack() throws IOException {
|
||||
final IndexPack ip = IndexPack.create(transport.local, bin);
|
||||
ip.setFixThin(true);
|
||||
ip.setObjectChecking(transport.isCheckFetchedObjects());
|
||||
return ip;
|
||||
}
|
||||
|
||||
private void verifyPrerequisites() throws TransportException {
|
||||
if (prereqs.isEmpty())
|
||||
return;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -44,7 +44,7 @@
|
|||
package org.eclipse.jgit.transport;
|
||||
|
||||
/**
|
||||
* Simple Map<long,Object> helper for {@link IndexPack}.
|
||||
* Simple Map<long,Object> helper for {@link PackParser}.
|
||||
*
|
||||
* @param <V>
|
||||
* type of the value instance.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -70,15 +70,16 @@
|
|||
import org.eclipse.jgit.errors.PackProtocolException;
|
||||
import org.eclipse.jgit.errors.UnpackException;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.eclipse.jgit.lib.Config.SectionParser;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectIdSubclassMap;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.RefUpdate;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.lib.Config.SectionParser;
|
||||
import org.eclipse.jgit.revwalk.ObjectWalk;
|
||||
import org.eclipse.jgit.revwalk.RevBlob;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
|
@ -161,7 +162,7 @@ public class ReceivePack {
|
|||
|
||||
private Writer msgs;
|
||||
|
||||
private IndexPack ip;
|
||||
private PackParser parser;
|
||||
|
||||
/** The refs we advertised as existing at the start of the connection. */
|
||||
private Map<String, Ref> refs;
|
||||
|
@ -630,7 +631,7 @@ private void service() throws IOException {
|
|||
receivePack();
|
||||
if (needCheckConnectivity())
|
||||
checkConnectivity();
|
||||
ip = null;
|
||||
parser = null;
|
||||
unpackError = null;
|
||||
} catch (IOException err) {
|
||||
unpackError = err;
|
||||
|
@ -779,17 +780,23 @@ private void receivePack() throws IOException {
|
|||
if (timeoutIn != null)
|
||||
timeoutIn.setTimeout(10 * timeout * 1000);
|
||||
|
||||
ip = IndexPack.create(db, rawIn);
|
||||
ip.setFixThin(true);
|
||||
ip.setNeedNewObjectIds(checkReferencedIsReachable);
|
||||
ip.setNeedBaseObjectIds(checkReferencedIsReachable);
|
||||
ip.setObjectChecking(isCheckReceivedObjects());
|
||||
ip.index(NullProgressMonitor.INSTANCE);
|
||||
ObjectInserter ins = db.newObjectInserter();
|
||||
try {
|
||||
String lockMsg = "jgit receive-pack";
|
||||
if (getRefLogIdent() != null)
|
||||
lockMsg += " from " + getRefLogIdent().toExternalString();
|
||||
|
||||
String lockMsg = "jgit receive-pack";
|
||||
if (getRefLogIdent() != null)
|
||||
lockMsg += " from " + getRefLogIdent().toExternalString();
|
||||
packLock = ip.renameAndOpenPack(lockMsg);
|
||||
parser = ins.newPackParser(rawIn);
|
||||
parser.setAllowThin(true);
|
||||
parser.setNeedNewObjectIds(checkReferencedIsReachable);
|
||||
parser.setNeedBaseObjectIds(checkReferencedIsReachable);
|
||||
parser.setObjectChecking(isCheckReceivedObjects());
|
||||
parser.setLockMessage(lockMsg);
|
||||
packLock = parser.parse(NullProgressMonitor.INSTANCE);
|
||||
ins.flush();
|
||||
} finally {
|
||||
ins.release();
|
||||
}
|
||||
|
||||
if (timeoutIn != null)
|
||||
timeoutIn.setTimeout(timeout * 1000);
|
||||
|
@ -805,10 +812,10 @@ private void checkConnectivity() throws IOException {
|
|||
ObjectIdSubclassMap<ObjectId> providedObjects = null;
|
||||
|
||||
if (checkReferencedIsReachable) {
|
||||
baseObjects = ip.getBaseObjectIds();
|
||||
providedObjects = ip.getNewObjectIds();
|
||||
baseObjects = parser.getBaseObjectIds();
|
||||
providedObjects = parser.getNewObjectIds();
|
||||
}
|
||||
ip = null;
|
||||
parser = null;
|
||||
|
||||
final ObjectWalk ow = new ObjectWalk(db);
|
||||
ow.setRetainBody(false);
|
||||
|
|
|
@ -856,17 +856,16 @@ else if (tmpIdx.isFile()) {
|
|||
}
|
||||
|
||||
void downloadPack(final ProgressMonitor monitor) throws IOException {
|
||||
final WalkRemoteObjectDatabase.FileStream s;
|
||||
final IndexPack ip;
|
||||
|
||||
s = connection.open("pack/" + packName);
|
||||
ip = IndexPack.create(local, s.in);
|
||||
ip.setFixThin(false);
|
||||
ip.setObjectChecker(objCheck);
|
||||
ip.index(monitor);
|
||||
final PackLock keep = ip.renameAndOpenPack(lockMessage);
|
||||
if (keep != null)
|
||||
packLocks.add(keep);
|
||||
String name = "pack/" + packName;
|
||||
WalkRemoteObjectDatabase.FileStream s = connection.open(name);
|
||||
PackParser parser = inserter.newPackParser(s.in);
|
||||
parser.setAllowThin(false);
|
||||
parser.setObjectChecker(objCheck);
|
||||
parser.setLockMessage(lockMessage);
|
||||
PackLock lock = parser.parse(monitor);
|
||||
if (lock != null)
|
||||
packLocks.add(lock);
|
||||
inserter.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue