Include supported extensions in PackFile constructor.

Previously a PackFile class was assumed to only support a .pack and .idx
file. Update the constructor to enumerate the supported extensions for
the pack file. This will allow the bitmap code to only be executed if
the bitmap extension file is known to exist.

Change-Id: Ie59041dffec5f60d7ea2771026ffd945106bd4bf
This commit is contained in:
Colby Ranger 2013-01-28 11:49:01 -08:00
parent 212fb3071c
commit 4a317a1790
4 changed files with 88 additions and 25 deletions

View File

@ -46,6 +46,8 @@
package org.eclipse.jgit.storage.file;
import static org.eclipse.jgit.storage.pack.PackExt.INDEX;
import static org.eclipse.jgit.storage.pack.PackExt.PACK;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@ -70,7 +72,7 @@ public void test003_lookupCompressedObject() throws IOException {
final ObjectLoader or;
id = ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327");
pr = new PackFile(TEST_PACK);
pr = new PackFile(TEST_PACK, PACK.getBit() | INDEX.getBit());
or = pr.get(new WindowCursor(null), id);
assertNotNull(or);
assertEquals(Constants.OBJ_TREE, or.getType());

View File

@ -43,6 +43,9 @@
package org.eclipse.jgit.storage.file;
import static org.eclipse.jgit.storage.pack.PackExt.INDEX;
import static org.eclipse.jgit.storage.pack.PackExt.PACK;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@ -74,6 +77,7 @@
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.storage.pack.CachedPack;
import org.eclipse.jgit.storage.pack.ObjectToPack;
import org.eclipse.jgit.storage.pack.PackExt;
import org.eclipse.jgit.storage.pack.PackWriter;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
@ -335,10 +339,23 @@ private CachedPackList scanCachedPacks(CachedPackList old)
public PackFile openPack(final File pack)
throws IOException {
final String p = pack.getName();
if (p.length() != 50 || !p.startsWith("pack-") || !p.endsWith(".pack")) //$NON-NLS-1$
if (p.length() != 50 || !p.startsWith("pack-") || !p.endsWith(".pack")) //$NON-NLS-1$ //$NON-NLS-2$
throw new IOException(MessageFormat.format(JGitText.get().notAValidPack, pack));
PackFile res = new PackFile(pack);
// The pack and index are assumed to exist. The existence of other
// extensions needs to be explicitly checked.
//
int extensions = PACK.getBit() | INDEX.getBit();
final String base = p.substring(0, p.length() - 4);
for (PackExt ext : PackExt.values()) {
if ((extensions & ext.getBit()) == 0) {
final String name = base + ext.getExtension();
if (new File(pack.getParentFile(), name).exists())
extensions |= ext.getBit();
}
}
PackFile res = new PackFile(pack, extensions);
insertPack(res);
return res;
}
@ -720,9 +737,14 @@ private PackList scanPacksImpl(final PackList old) {
if (indexName.length() != 49 || !indexName.endsWith(".idx")) //$NON-NLS-1$
continue;
final String base = indexName.substring(0, indexName.length() - 4);
final String packName = base + ".pack"; //$NON-NLS-1$
if (!names.contains(packName)) {
final String base = indexName.substring(0, indexName.length() - 3);
int extensions = 0;
for (PackExt ext : PackExt.values()) {
if (names.contains(base + ext.getExtension()))
extensions |= ext.getBit();
}
if ((extensions & PACK.getBit()) == 0) {
// Sometimes C Git's HTTP fetch transport leaves a
// .idx file behind and does not download the .pack.
// We have to skip over such useless indexes.
@ -730,6 +752,7 @@ private PackList scanPacksImpl(final PackList old) {
continue;
}
final String packName = base + PACK.getExtension();
final PackFile oldPack = forReuse.remove(packName);
if (oldPack != null) {
list.add(oldPack);
@ -737,7 +760,7 @@ private PackList scanPacksImpl(final PackList old) {
}
final File packFile = new File(packDirectory, packName);
list.add(new PackFile(packFile));
list.add(new PackFile(packFile, extensions));
foundNew = true;
}

View File

@ -97,6 +97,8 @@ public int compare(final PackFile a, final PackFile b) {
private final File packFile;
private final int extensions;
private File keepFile;
private volatile String packName;
@ -138,10 +140,13 @@ public int compare(final PackFile a, final PackFile b) {
*
* @param packFile
* path of the <code>.pack</code> file holding the data.
* @param extensions
* additional pack file extensions with the same base as the pack
*/
public PackFile(final File packFile) {
public PackFile(final File packFile, int extensions) {
this.packFile = packFile;
this.packLastModified = (int) (packFile.lastModified() >> 10);
this.extensions = extensions;
// Multiply by 31 here so we can more directly combine with another
// value in WindowCache.hash(), without doing the multiply there.
@ -1085,4 +1090,8 @@ private File extFile(PackExt ext) {
String b = (dot < 0) ? p : p.substring(0, dot);
return new File(packFile.getParentFile(), b + '.' + ext.getExtension());
}
private boolean hasExt(PackExt ext) {
return (extensions & ext.getBit()) != 0;
}
}

View File

@ -45,21 +45,52 @@
/** A pack file extension. */
public class PackExt {
private static volatile PackExt[] VALUES = new PackExt[] {};
/** A pack file extension. */
public static final PackExt PACK = new PackExt("pack"); //$NON-NLS-1$
public static final PackExt PACK = newPackExt("pack"); //$NON-NLS-1$
/** A pack index file extension. */
public static final PackExt INDEX = new PackExt("idx"); //$NON-NLS-1$
public static final PackExt INDEX = newPackExt("idx"); //$NON-NLS-1$
/** @return all of the PackExt values. */
public static PackExt[] values() {
return VALUES;
}
/**
* Returns a PackExt for the file extension and registers it in the values
* array.
*
* @param ext
* the file extension.
* @return the PackExt for the ext
*/
public synchronized static PackExt newPackExt(String ext) {
PackExt[] dst = new PackExt[VALUES.length + 1];
for (int i = 0; i < VALUES.length; i++) {
PackExt packExt = VALUES[i];
if (packExt.getExtension().equals(ext))
return packExt;
dst[i] = packExt;
}
if (VALUES.length >= 32)
throw new IllegalStateException(
"maximum number of pack extensions exceeded"); //$NON-NLS-1$
PackExt value = new PackExt(ext, VALUES.length);
dst[VALUES.length] = value;
VALUES = dst;
return value;
}
private final String ext;
/**
* @param ext
* the file extension.
*/
public PackExt(String ext) {
private final int pos;
private PackExt(String ext, int pos) {
this.ext = ext;
this.pos = pos;
}
/** @return the file extension. */
@ -67,21 +98,19 @@ public String getExtension() {
return ext;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof PackExt) {
return ((PackExt) obj).getExtension().equals(getExtension());
}
return false;
/** @return the position of the extension in the values array. */
public int getPosition() {
return pos;
}
@Override
public int hashCode() {
return getExtension().hashCode();
/** @return the bit mask of the extension e.g {@code 1 << getPosition()}. */
public int getBit() {
return 1 << getPosition();
}
@Override
public String toString() {
return String.format("PackExt[%s]", getExtension()); //$NON-NLS-1$
return String.format("PackExt[%s, bit=0x%s]", getExtension(), //$NON-NLS-1$
Integer.toHexString(getBit()));
}
}