@@ -160,6 +160,79 @@ func (s *ObjectStorage) HasEncodedObject(h plumbing.Hash) (err error) {
160
160
return nil
161
161
}
162
162
163
+ func (s * ObjectStorage ) encodedObjectSizeFromUnpacked (h plumbing.Hash ) (
164
+ size int64 , err error ) {
165
+ f , err := s .dir .Object (h )
166
+ if err != nil {
167
+ if os .IsNotExist (err ) {
168
+ return 0 , plumbing .ErrObjectNotFound
169
+ }
170
+
171
+ return 0 , err
172
+ }
173
+
174
+ r , err := objfile .NewReader (f )
175
+ if err != nil {
176
+ return 0 , err
177
+ }
178
+ defer ioutil .CheckClose (r , & err )
179
+
180
+ _ , size , err = r .Header ()
181
+ return size , err
182
+ }
183
+
184
+ func (s * ObjectStorage ) encodedObjectSizeFromPackfile (h plumbing.Hash ) (
185
+ size int64 , err error ) {
186
+ if err := s .requireIndex (); err != nil {
187
+ return 0 , err
188
+ }
189
+
190
+ pack , _ , offset := s .findObjectInPackfile (h )
191
+ if offset == - 1 {
192
+ return 0 , plumbing .ErrObjectNotFound
193
+ }
194
+
195
+ f , err := s .dir .ObjectPack (pack )
196
+ if err != nil {
197
+ return 0 , err
198
+ }
199
+ defer ioutil .CheckClose (f , & err )
200
+
201
+ idx := s .index [pack ]
202
+ hash , err := idx .FindHash (offset )
203
+ if err == nil {
204
+ obj , ok := s .deltaBaseCache .Get (hash )
205
+ if ok {
206
+ return obj .Size (), nil
207
+ }
208
+ } else if err != nil && err != plumbing .ErrObjectNotFound {
209
+ return 0 , err
210
+ }
211
+
212
+ var p * packfile.Packfile
213
+ if s .deltaBaseCache != nil {
214
+ p = packfile .NewPackfileWithCache (idx , s .dir .Fs (), f , s .deltaBaseCache )
215
+ } else {
216
+ p = packfile .NewPackfile (idx , s .dir .Fs (), f )
217
+ }
218
+
219
+ return p .GetSizeByOffset (offset )
220
+ }
221
+
222
+ // EncodedObjectSize returns the plaintext size of the given object,
223
+ // without actually reading the full object data from storage.
224
+ func (s * ObjectStorage ) EncodedObjectSize (h plumbing.Hash ) (
225
+ size int64 , err error ) {
226
+ size , err = s .encodedObjectSizeFromUnpacked (h )
227
+ if err != nil && err != plumbing .ErrObjectNotFound {
228
+ return 0 , err
229
+ } else if err == nil {
230
+ return size , nil
231
+ }
232
+
233
+ return s .encodedObjectSizeFromPackfile (h )
234
+ }
235
+
163
236
// EncodedObject returns the object with the given hash, by searching for it in
164
237
// the packfile and the git object directories.
165
238
func (s * ObjectStorage ) EncodedObject (t plumbing.ObjectType , h plumbing.Hash ) (plumbing.EncodedObject , error ) {
0 commit comments