@@ -38,15 +38,14 @@ type Observer interface {
38
38
// Parser decodes a packfile and calls any observer associated to it. Is used
39
39
// to generate indexes.
40
40
type Parser struct {
41
- storage storer.EncodedObjectStorer
42
- scanner * Scanner
43
- count uint32
44
- oi []* objectInfo
45
- oiByHash map [plumbing.Hash ]* objectInfo
46
- oiByOffset map [int64 ]* objectInfo
47
- hashOffset map [plumbing.Hash ]int64
48
- pendingRefDeltas map [plumbing.Hash ][]* objectInfo
49
- checksum plumbing.Hash
41
+ storage storer.EncodedObjectStorer
42
+ scanner * Scanner
43
+ count uint32
44
+ oi []* objectInfo
45
+ oiByHash map [plumbing.Hash ]* objectInfo
46
+ oiByOffset map [int64 ]* objectInfo
47
+ hashOffset map [plumbing.Hash ]int64
48
+ checksum plumbing.Hash
50
49
51
50
cache * cache.BufferLRU
52
51
// delta content by offset, only used if source is not seekable
@@ -78,13 +77,12 @@ func NewParserWithStorage(
78
77
}
79
78
80
79
return & Parser {
81
- storage : storage ,
82
- scanner : scanner ,
83
- ob : ob ,
84
- count : 0 ,
85
- cache : cache .NewBufferLRUDefault (),
86
- pendingRefDeltas : make (map [plumbing.Hash ][]* objectInfo ),
87
- deltas : deltas ,
80
+ storage : storage ,
81
+ scanner : scanner ,
82
+ ob : ob ,
83
+ count : 0 ,
84
+ cache : cache .NewBufferLRUDefault (),
85
+ deltas : deltas ,
88
86
}, nil
89
87
}
90
88
@@ -150,10 +148,6 @@ func (p *Parser) Parse() (plumbing.Hash, error) {
150
148
return plumbing .ZeroHash , err
151
149
}
152
150
153
- if len (p .pendingRefDeltas ) > 0 {
154
- return plumbing .ZeroHash , ErrReferenceDeltaNotFound
155
- }
156
-
157
151
if err := p .onFooter (p .checksum ); err != nil {
158
152
return plumbing .ZeroHash , err
159
153
}
@@ -205,18 +199,21 @@ func (p *Parser) indexObjects() error {
205
199
parent .Children = append (parent .Children , ota )
206
200
case plumbing .REFDeltaObject :
207
201
delta = true
208
-
209
202
parent , ok := p .oiByHash [oh .Reference ]
210
- if ok {
211
- ota = newDeltaObject (oh .Offset , oh .Length , t , parent )
212
- parent .Children = append (parent .Children , ota )
213
- } else {
214
- ota = newBaseObject (oh .Offset , oh .Length , t )
215
- p .pendingRefDeltas [oh .Reference ] = append (
216
- p .pendingRefDeltas [oh .Reference ],
217
- ota ,
218
- )
203
+ if ! ok {
204
+ // can't find referenced object in this pack file
205
+ // this must be a "thin" pack.
206
+ parent = & objectInfo { //Placeholder parent
207
+ SHA1 : oh .Reference ,
208
+ ExternalRef : true , // mark as an external reference that must be resolved
209
+ Type : plumbing .AnyObject ,
210
+ DiskType : plumbing .AnyObject ,
211
+ }
212
+ p .oiByHash [oh .Reference ] = parent
219
213
}
214
+ ota = newDeltaObject (oh .Offset , oh .Length , t , parent )
215
+ parent .Children = append (parent .Children , ota )
216
+
220
217
default :
221
218
ota = newBaseObject (oh .Offset , oh .Length , t )
222
219
}
@@ -297,16 +294,20 @@ func (p *Parser) resolveDeltas() error {
297
294
return nil
298
295
}
299
296
300
- func (p * Parser ) get (o * objectInfo ) ([]byte , error ) {
301
- b , ok := p .cache .Get (o .Offset )
297
+ func (p * Parser ) get (o * objectInfo ) (b []byte , err error ) {
298
+ var ok bool
299
+ if ! o .ExternalRef { // skip cache check for placeholder parents
300
+ b , ok = p .cache .Get (o .Offset )
301
+ }
302
+
302
303
// If it's not on the cache and is not a delta we can try to find it in the
303
- // storage, if there's one.
304
+ // storage, if there's one. External refs must enter here.
304
305
if ! ok && p .storage != nil && ! o .Type .IsDelta () {
305
- var err error
306
306
e , err := p .storage .EncodedObject (plumbing .AnyObject , o .SHA1 )
307
307
if err != nil {
308
308
return nil , err
309
309
}
310
+ o .Type = e .Type ()
310
311
311
312
r , err := e .Reader ()
312
313
if err != nil {
@@ -323,6 +324,11 @@ func (p *Parser) get(o *objectInfo) ([]byte, error) {
323
324
return b , nil
324
325
}
325
326
327
+ if o .ExternalRef {
328
+ // we were not able to resolve a ref in a thin pack
329
+ return nil , ErrReferenceDeltaNotFound
330
+ }
331
+
326
332
var data []byte
327
333
if o .DiskType .IsDelta () {
328
334
base , err := p .get (o .Parent )
@@ -335,7 +341,6 @@ func (p *Parser) get(o *objectInfo) ([]byte, error) {
335
341
return nil , err
336
342
}
337
343
} else {
338
- var err error
339
344
data , err = p .readData (o )
340
345
if err != nil {
341
346
return nil , err
@@ -367,14 +372,6 @@ func (p *Parser) resolveObject(
367
372
return nil , err
368
373
}
369
374
370
- if pending , ok := p .pendingRefDeltas [o .SHA1 ]; ok {
371
- for _ , po := range pending {
372
- po .Parent = o
373
- o .Children = append (o .Children , po )
374
- }
375
- delete (p .pendingRefDeltas , o .SHA1 )
376
- }
377
-
378
375
if p .storage != nil {
379
376
obj := new (plumbing.MemoryObject )
380
377
obj .SetSize (o .Size ())
@@ -447,10 +444,11 @@ func getSHA1(t plumbing.ObjectType, data []byte) (plumbing.Hash, error) {
447
444
}
448
445
449
446
type objectInfo struct {
450
- Offset int64
451
- Length int64
452
- Type plumbing.ObjectType
453
- DiskType plumbing.ObjectType
447
+ Offset int64
448
+ Length int64
449
+ Type plumbing.ObjectType
450
+ DiskType plumbing.ObjectType
451
+ ExternalRef bool // indicates this is an external reference in a thin pack file
454
452
455
453
Crc32 uint32
456
454
0 commit comments