*/
package org.eclipse.jgit.storage.file;
+import static org.eclipse.jgit.storage.pack.PackExt.BITMAP_INDEX;
+import static org.eclipse.jgit.storage.pack.PackExt.INDEX;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.TreeMap;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.revwalk.ObjectWalk;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.pack.PackExt;
import org.eclipse.jgit.storage.pack.PackWriter;
import org.eclipse.jgit.storage.pack.PackWriter.ObjectIdSet;
import org.eclipse.jgit.treewalk.TreeWalk;
if (!oldPack.shouldBeKept()) {
oldPack.close();
- FileUtils.delete(nameFor(oldName, ".pack"), deleteOptions); //$NON-NLS-1$
- FileUtils.delete(nameFor(oldName, ".idx"), deleteOptions); //$NON-NLS-1$
+ for (PackExt ext : PackExt.values()) {
+ File f = nameFor(oldName, "." + ext.getExtension()); //$NON-NLS-1$
+ FileUtils.delete(f, deleteOptions);
+ }
}
}
// close the complete object database. Thats my only chance to force
Set<? extends ObjectId> have, Set<ObjectId> tagTargets,
List<ObjectIdSet> excludeObjects) throws IOException {
File tmpPack = null;
- File tmpIdx = null;
+ Map<PackExt, File> tmpExts = new TreeMap<PackExt, File>(
+ new Comparator<PackExt>() {
+ public int compare(PackExt o1, PackExt o2) {
+ // INDEX entries must be returned last, so the pack
+ // scanner does pick up the new pack until all the
+ // PackExt entries have been written.
+ if (o1 == o2)
+ return 0;
+ if (o1 == PackExt.INDEX)
+ return 1;
+ if (o2 == PackExt.INDEX)
+ return -1;
+ return Integer.signum(o1.hashCode() - o2.hashCode());
+ }
+
+ });
PackWriter pw = new PackWriter(repo);
try {
// prepare the PackWriter
String id = pw.computeName().getName();
File packdir = new File(repo.getObjectsDirectory(), "pack"); //$NON-NLS-1$
tmpPack = File.createTempFile("gc_", ".pack_tmp", packdir); //$NON-NLS-1$ //$NON-NLS-2$
- tmpIdx = new File(packdir, tmpPack.getName().substring(0,
- tmpPack.getName().lastIndexOf('.'))
- + ".idx_tmp"); //$NON-NLS-1$
+ final String tmpBase = tmpPack.getName()
+ .substring(0, tmpPack.getName().lastIndexOf('.'));
+ File tmpIdx = new File(packdir, tmpBase + ".idx_tmp"); //$NON-NLS-1$
+ tmpExts.put(INDEX, tmpIdx);
if (!tmpIdx.createNewFile())
throw new IOException(MessageFormat.format(
idxChannel.close();
}
+ if (pw.prepareBitmapIndex(pm)) {
+ File tmpBitmapIdx = new File(packdir, tmpBase + ".bitmap_tmp"); //$NON-NLS-1$
+ tmpExts.put(BITMAP_INDEX, tmpBitmapIdx);
+
+ if (!tmpBitmapIdx.createNewFile())
+ throw new IOException(MessageFormat.format(
+ JGitText.get().cannotCreateIndexfile,
+ tmpBitmapIdx.getPath()));
+
+ idxChannel = new FileOutputStream(tmpBitmapIdx).getChannel();
+ idxStream = Channels.newOutputStream(idxChannel);
+ try {
+ pw.writeBitmapIndex(idxStream);
+ } finally {
+ idxChannel.force(true);
+ idxStream.close();
+ idxChannel.close();
+ }
+ }
+
// rename the temporary files to real files
File realPack = nameFor(id, ".pack"); //$NON-NLS-1$
tmpPack.setReadOnly();
- File realIdx = nameFor(id, ".idx"); //$NON-NLS-1$
- realIdx.setReadOnly();
boolean delete = true;
try {
if (!tmpPack.renameTo(realPack))
return null;
delete = false;
- if (!tmpIdx.renameTo(realIdx)) {
- File newIdx = new File(realIdx.getParentFile(),
- realIdx.getName() + ".new"); //$NON-NLS-1$
- if (!tmpIdx.renameTo(newIdx))
- newIdx = tmpIdx;
- throw new IOException(MessageFormat.format(
- JGitText.get().panicCantRenameIndexFile, newIdx,
- realIdx));
+ for (Map.Entry<PackExt, File> tmpEntry : tmpExts.entrySet()) {
+ File tmpExt = tmpEntry.getValue();
+ tmpExt.setReadOnly();
+
+ File realExt = nameFor(
+ id, "." + tmpEntry.getKey().getExtension()); //$NON-NLS-1$
+ if (!tmpExt.renameTo(realExt)) {
+ File newExt = new File(realExt.getParentFile(),
+ realExt.getName() + ".new"); //$NON-NLS-1$
+ if (!tmpExt.renameTo(newExt))
+ newExt = tmpExt;
+ throw new IOException(MessageFormat.format(
+ JGitText.get().panicCantRenameIndexFile, newExt,
+ realExt));
+ }
}
+
} finally {
- if (delete && tmpPack.exists())
- tmpPack.delete();
- if (delete && tmpIdx.exists())
- tmpIdx.delete();
+ if (delete) {
+ if (tmpPack.exists())
+ tmpPack.delete();
+ for (File tmpExt : tmpExts.values()) {
+ if (tmpExt.exists())
+ tmpExt.delete();
+ }
+ }
}
return repo.getObjectDatabase().openPack(realPack);
} finally {
pw.release();
if (tmpPack != null && tmpPack.exists())
tmpPack.delete();
- if (tmpIdx != null && tmpIdx.exists())
- tmpIdx.delete();
+ for (File tmpExt : tmpExts.values()) {
+ if (tmpExt.exists())
+ tmpExt.delete();
+ }
}
}
* Create a bitmap index file to match the pack file just written.
* <p>
* This method can only be invoked after
- * {@link #prepareBitmapIndex(ProgressMonitor, Set)} has been invoked and
+ * {@link #prepareBitmapIndex(ProgressMonitor)} has been invoked and
* completed successfully. Writing a corresponding bitmap index is an
* optional feature that not all pack users may require.
*
*
* @param pm
* progress monitor to report bitmap building work.
- * @param want
- * collection of objects to be marked as interesting (start
- * points of graph traversal).
* @return whether a bitmap index may be written.
* @throws IOException
* when some I/O problem occur during reading objects.
*/
- public boolean prepareBitmapIndex(
- ProgressMonitor pm, Set<? extends ObjectId> want)
- throws IOException {
+ public boolean prepareBitmapIndex(ProgressMonitor pm) throws IOException {
if (!canBuildBitmaps || getObjectCount() > Integer.MAX_VALUE
|| !cachedPacks.isEmpty())
return false;
pm = NullProgressMonitor.INSTANCE;
writeBitmaps = new PackBitmapIndexBuilder(sortByName());
- PackWriterBitmapPreparer bitmapPreparer =
- new PackWriterBitmapPreparer(reader, writeBitmaps, pm, want);
+ PackWriterBitmapPreparer bitmapPreparer = new PackWriterBitmapPreparer(
+ reader, writeBitmaps, pm, stats.interestingObjects);
int numCommits = objectsLists[Constants.OBJ_COMMIT].size();
Collection<PackWriterBitmapPreparer.BitmapCommit> selectedCommits =