From b872b71112ed4034bbd9c33a0babd6353b582429 Mon Sep 17 00:00:00 2001 From: Antonio Jesus Navarro Perez Date: Tue, 7 Feb 2017 16:02:46 +0100 Subject: Fix missing objects if they where deltified using ref-delta - Deleted invalid logic that returned nil if an ref-delta was not found into the decoder index. This logic was missing objects if it was deltified using ref-deltas. - Now, to avoid that problem, index is mandatory to decode correctly a packfile of a specific type. Decoder.SetOffsets method now is called into the EncodedObjectIterator to avoid this problem. --- plumbing/format/packfile/decoder.go | 7 ---- plumbing/format/packfile/decoder_test.go | 65 ++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 7 deletions(-) (limited to 'plumbing') diff --git a/plumbing/format/packfile/decoder.go b/plumbing/format/packfile/decoder.go index 9f2174b..475d24d 100644 --- a/plumbing/format/packfile/decoder.go +++ b/plumbing/format/packfile/decoder.go @@ -225,13 +225,6 @@ func (d *Decoder) decodeIfSpecificType(h *ObjectHeader) (plumbing.EncodedObject, realType, err = d.ofsDeltaType(h.OffsetReference) case plumbing.REFDeltaObject: realType, err = d.refDeltaType(h.Reference) - - // If a reference delta is not found, it means that it isn't of - // the type we are looking for, because we don't have any reference - // and it is not present into the object storer - if err == plumbing.ErrObjectNotFound { - return nil, nil - } default: realType = h.Type } diff --git a/plumbing/format/packfile/decoder_test.go b/plumbing/format/packfile/decoder_test.go index 6bb49aa..bc40b30 100644 --- a/plumbing/format/packfile/decoder_test.go +++ b/plumbing/format/packfile/decoder_test.go @@ -47,6 +47,65 @@ func (s *ReaderSuite) TestDecode(c *C) { }) } +func (s *ReaderSuite) TestDecodeByTypeRefDelta(c *C) { + f := fixtures.Basic().ByTag("ref-delta").One() + + storage := memory.NewStorage() + scanner := packfile.NewScanner(f.Packfile()) + d, err := packfile.NewDecoderForType(scanner, storage, plumbing.CommitObject) + c.Assert(err, IsNil) + + // Specific offset elements needed to decode correctly the ref-delta + offsets := map[plumbing.Hash]int64{ + plumbing.NewHash("a8d315b2b1c615d43042c3a62402b8a54288cf5c"): 84880, + plumbing.NewHash("fb72698cab7617ac416264415f13224dfd7a165e"): 85141, + plumbing.NewHash("eba74343e2f15d62adedfd8c883ee0262b5c8021"): 85300, + } + + d.SetOffsets(offsets) + + defer d.Close() + + _, count, err := scanner.Header() + c.Assert(err, IsNil) + + var i uint32 + for i = 0; i < count; i++ { + obj, err := d.DecodeObject() + c.Assert(err, IsNil) + + if obj != nil { + c.Assert(obj.Type(), Equals, plumbing.CommitObject) + } + } +} + +func (s *ReaderSuite) TestDecodeByTypeRefDeltaError(c *C) { + fixtures.Basic().ByTag("ref-delta").Test(c, func(f *fixtures.Fixture) { + storage := memory.NewStorage() + scanner := packfile.NewScanner(f.Packfile()) + d, err := packfile.NewDecoderForType(scanner, storage, plumbing.CommitObject) + c.Assert(err, IsNil) + + defer d.Close() + + _, count, err := scanner.Header() + c.Assert(err, IsNil) + + isError := false + var i uint32 + for i = 0; i < count; i++ { + _, err := d.DecodeObject() + if err != nil { + isError = true + break + } + } + c.Assert(isError, Equals, true) + }) + +} + func (s *ReaderSuite) TestDecodeByType(c *C) { ts := []plumbing.ObjectType{ plumbing.CommitObject, @@ -61,6 +120,12 @@ func (s *ReaderSuite) TestDecodeByType(c *C) { scanner := packfile.NewScanner(f.Packfile()) d, err := packfile.NewDecoderForType(scanner, storage, t) c.Assert(err, IsNil) + + // when the packfile is ref-delta based, the offsets are required + if f.Is("ref-delta") { + d.SetOffsets(getOffsetsFromIdx(f.Idx())) + } + defer d.Close() _, count, err := scanner.Header() -- cgit