Browse Source

Fix PackWriterBitmapWalker handling non-existing uninteresting objects

When writing new packs it should be allowed to specify objects as "have"
(objects which should not be included in the pack) which do not exist in
the local repository.

This works with the traditional PackWriter, but when PackWriter was
working on a repository with bitmap indexes and used
PackWriterBitmapWalker then this feature was broken. Non-existing "have"
objects lead to MissingObjectExceptions. That broke push and Gerrit
replication. When the replication target had branches unknown to the
replication source then the source repository wanted to build pack files
where "have" included branch-tips which were unknown in the source 
repository.

Bug: 427107
Change-Id: I6b6598a1ec49af68aa77ea6f1f06e827982ea4ac
Also-by: Matthias Sohn <matthias.sohn@sap.com>
tags/v3.5.0.201409260305-r
Christian Halstrick 9 years ago
parent
commit
fa4f00b7ed

+ 29
- 0
org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java View File

import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
// shouldn't throw anything // shouldn't throw anything
} }


/**
* Try to pass non-existing object as uninteresting, with ignoring setting.
* Use a repo with bitmap indexes because then PackWriter will use
* PackWriterBitmapWalker which had problems with this situation.
*
* @throws IOException
* @throws ParseException
*/
@Test
public void testIgnoreNonExistingObjectsWithBitmaps() throws IOException,
ParseException {
final ObjectId nonExisting = ObjectId
.fromString("0000000000000000000000000000000000000001");
new GC(db).gc();
createVerifyOpenPack(EMPTY_SET_OBJECT,
Collections.singleton(nonExisting), false, true, true);
// shouldn't throw anything
}

/** /**
* Create pack basing on only interesting objects, then precisely verify * Create pack basing on only interesting objects, then precisely verify
* content. No delta reuse here. * content. No delta reuse here.
final Set<ObjectId> uninterestings, final boolean thin, final Set<ObjectId> uninterestings, final boolean thin,
final boolean ignoreMissingUninteresting) final boolean ignoreMissingUninteresting)
throws MissingObjectException, IOException { throws MissingObjectException, IOException {
createVerifyOpenPack(interestings, uninterestings, thin,
ignoreMissingUninteresting, false);
}

private void createVerifyOpenPack(final Set<ObjectId> interestings,
final Set<ObjectId> uninterestings, final boolean thin,
final boolean ignoreMissingUninteresting, boolean useBitmaps)
throws MissingObjectException, IOException {
NullProgressMonitor m = NullProgressMonitor.INSTANCE; NullProgressMonitor m = NullProgressMonitor.INSTANCE;
writer = new PackWriter(config, db.newObjectReader()); writer = new PackWriter(config, db.newObjectReader());
writer.setUseBitmaps(useBitmaps);
writer.setThin(thin); writer.setThin(thin);
writer.setIgnoreMissingUninteresting(ignoreMissingUninteresting); writer.setIgnoreMissingUninteresting(ignoreMissingUninteresting);
writer.preparePack(m, interestings, uninterestings); writer.preparePack(m, interestings, uninterestings);

+ 4
- 3
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java View File

Set<? extends ObjectId> have) Set<? extends ObjectId> have)
throws MissingObjectException, IncorrectObjectTypeException, throws MissingObjectException, IncorrectObjectTypeException,
IOException { IOException {
BitmapBuilder haveBitmap = bitmapWalker.findObjects(have, null);
BitmapBuilder haveBitmap = bitmapWalker.findObjects(have, null, true);
bitmapWalker.reset(); bitmapWalker.reset();
BitmapBuilder wantBitmap = bitmapWalker.findObjects(want, haveBitmap);
BitmapBuilder wantBitmap = bitmapWalker.findObjects(want, haveBitmap,
false);
BitmapBuilder needBitmap = wantBitmap.andNot(haveBitmap); BitmapBuilder needBitmap = wantBitmap.andNot(haveBitmap);


if (useCachedPacks && reuseSupport != null if (useCachedPacks && reuseSupport != null
walker = bitmapPreparer.newBitmapWalker(); walker = bitmapPreparer.newBitmapWalker();


BitmapBuilder bitmap = walker.findObjects( BitmapBuilder bitmap = walker.findObjects(
Collections.singleton(cmit), null);
Collections.singleton(cmit), null, false);


if (last != null && cmit.isReuseWalker() && !bitmap.contains(last)) if (last != null && cmit.isReuseWalker() && !bitmap.contains(last))
throw new IllegalStateException(MessageFormat.format( throw new IllegalStateException(MessageFormat.format(

+ 10
- 4
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java View File

this.pm = (pm == null) ? NullProgressMonitor.INSTANCE : pm; this.pm = (pm == null) ? NullProgressMonitor.INSTANCE : pm;
} }


BitmapBuilder findObjects(Set<? extends ObjectId> start, BitmapBuilder seen)
BitmapBuilder findObjects(Set<? extends ObjectId> start, BitmapBuilder seen, boolean ignoreMissingStart)
throws MissingObjectException, IncorrectObjectTypeException, throws MissingObjectException, IncorrectObjectTypeException,
IOException { IOException {
final BitmapBuilder bitmapResult = bitmapIndex.newBitmapBuilder(); final BitmapBuilder bitmapResult = bitmapIndex.newBitmapBuilder();


boolean marked = false; boolean marked = false;
for (ObjectId obj : start) { for (ObjectId obj : start) {
if (!bitmapResult.contains(obj)) {
walker.markStart(walker.parseAny(obj));
marked = true;
try {
if (!bitmapResult.contains(obj)) {
walker.markStart(walker.parseAny(obj));
marked = true;
}
} catch (MissingObjectException e) {
if (ignoreMissingStart)
continue;
throw e;
} }
} }



Loading…
Cancel
Save