Browse Source

Do not write edge objects to the pack stream

Consider two objects A->B where A uses B as a delta base, and these
are in the same source pack file ordered as "A B".

If cached packs is enabled and B is also in the cached pack that
will be appended onto the end of the thin pack, and both A, B are
supposed to be in the thin pack, PackWriter must consider the fact
that A's base B is an edge object that claims to be part of the
new pack, but is actually "external" and cannot be written first.

If the object reuse system considered B candidates fist this bug
does not arise, as B will be marked as edge due to it existing in
the cached pack. When the A candidates are later examined, A sees a
valid delta base is available as an edge, and will not later try to
"write base first" during the writing phase.

However, when the reuse system considers A candidates first they
see that B will be in the outgoing pack, as it is still part of
the thin pack, and arrange for A to be written first. Later when A
switches from being in-pack to being an edge object (as it is part
of the cached pack) the pointer in B does not get its type changed
from ObjectToPack to ObjectId, so B thinks A is non-edge.

We work around this case by also checking that the delta base B
is non-edge before writing the object to the pack. Later when A
writes its object header, delta base B's ObjectToPack will have
an offset == 0, which makes isWritten() = false, and the OBJ_REF
delta format will be used for A's header. This will be resolved by
the client to the copy of B that appears in the later cached pack.

Change-Id: Ifab6bfdf3c0aa93649468f49bcf91d67f90362ca
stable-1.2
Shawn O. Pearce 13 years ago
parent
commit
60e51251db
  1. 6
      org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java

6
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java

@ -1396,10 +1396,10 @@ public class PackWriter {
otp.setCRC(out.getCRC32()); otp.setCRC(out.getCRC32());
} }
private void writeBase(PackOutputStream out, ObjectToPack baseInPack) private void writeBase(PackOutputStream out, ObjectToPack base)
throws IOException { throws IOException {
if (baseInPack != null && !baseInPack.isWritten()) if (base != null && !base.isWritten() && !base.isEdge())
writeObjectImpl(out, baseInPack); writeObjectImpl(out, base);
} }
private void writeWholeObjectDeflate(PackOutputStream out, private void writeWholeObjectDeflate(PackOutputStream out,

Loading…
Cancel
Save