@@ -160,6 +160,81 @@ func (s *ObjectStorage) HasEncodedObject(h plumbing.Hash) (err error) {
160160 return nil
161161}
162162
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+ }
209+
210+ if err != nil && err != plumbing .ErrObjectNotFound {
211+ return 0 , err
212+ }
213+
214+ var p * packfile.Packfile
215+ if s .deltaBaseCache != nil {
216+ p = packfile .NewPackfileWithCache (idx , s .dir .Fs (), f , s .deltaBaseCache )
217+ } else {
218+ p = packfile .NewPackfile (idx , s .dir .Fs (), f )
219+ }
220+
221+ return p .GetSizeByOffset (offset )
222+ }
223+
224+ // EncodedObjectSize returns the plaintext size of the given object,
225+ // without actually reading the full object data from storage.
226+ func (s * ObjectStorage ) EncodedObjectSize (h plumbing.Hash ) (
227+ size int64 , err error ) {
228+ size , err = s .encodedObjectSizeFromUnpacked (h )
229+ if err != nil && err != plumbing .ErrObjectNotFound {
230+ return 0 , err
231+ } else if err == nil {
232+ return size , nil
233+ }
234+
235+ return s .encodedObjectSizeFromPackfile (h )
236+ }
237+
163238// EncodedObject returns the object with the given hash, by searching for it in
164239// the packfile and the git object directories.
165240func (s * ObjectStorage ) EncodedObject (t plumbing.ObjectType , h plumbing.Hash ) (plumbing.EncodedObject , error ) {
0 commit comments