From 4a317a1790ae0d7ca2febaf41ec326ae8a8839b7 Mon Sep 17 00:00:00 2001 From: Colby Ranger Date: Mon, 28 Jan 2013 11:49:01 -0800 Subject: [PATCH] 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 --- .../storage/file/T0004_PackReaderTest.java | 4 +- .../jgit/storage/file/ObjectDirectory.java | 35 ++++++++++-- .../eclipse/jgit/storage/file/PackFile.java | 11 +++- .../eclipse/jgit/storage/pack/PackExt.java | 57 ++++++++++++++----- 4 files changed, 85 insertions(+), 22 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0004_PackReaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0004_PackReaderTest.java index 67861f6779..d14cc212af 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0004_PackReaderTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0004_PackReaderTest.java @@ -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 class T0004_PackReaderTest extends SampleDataRepositoryTestCase { 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()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/ObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/ObjectDirectory.java index 22ef45df6b..7574f2aa88 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/ObjectDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/ObjectDirectory.java @@ -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; 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 @@ public class ObjectDirectory extends FileObjectDatabase { 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 @@ public class ObjectDirectory extends FileObjectDatabase { 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 @@ public class ObjectDirectory extends FileObjectDatabase { continue; } + final String packName = base + PACK.getExtension(); final PackFile oldPack = forReuse.remove(packName); if (oldPack != null) { list.add(oldPack); @@ -737,7 +760,7 @@ public class ObjectDirectory extends FileObjectDatabase { } final File packFile = new File(packDirectory, packName); - list.add(new PackFile(packFile)); + list.add(new PackFile(packFile, extensions)); foundNew = true; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackFile.java index 666df58bec..6c24a3fef1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackFile.java @@ -97,6 +97,8 @@ public class PackFile implements Iterable { private final File packFile; + private final int extensions; + private File keepFile; private volatile String packName; @@ -138,10 +140,13 @@ public class PackFile implements Iterable { * * @param packFile * path of the .pack 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 @@ public class PackFile implements Iterable { 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; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackExt.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackExt.java index cb33308c61..61a6609300 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackExt.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackExt.java @@ -45,21 +45,52 @@ package org.eclipse.jgit.storage.pack; /** 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$ - private final String ext; + /** @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 PackExt(String 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; + + 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 class PackExt { 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())); } } -- 2.39.5