@@ -160,6 +160,79 @@ 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+ } 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+
163236// EncodedObject returns the object with the given hash, by searching for it in
164237// the packfile and the git object directories.
165238func (s * ObjectStorage ) EncodedObject (t plumbing.ObjectType , h plumbing.Hash ) (plumbing.EncodedObject , error ) {
0 commit comments