@@ -47,17 +47,123 @@ func (dw *deltaSelector) ObjectsToPack(hashes []plumbing.Hash) ([]*ObjectToPack,
4747func (dw * deltaSelector ) objectsToPack (hashes []plumbing.Hash ) ([]* ObjectToPack , error ) {
4848 var objectsToPack []* ObjectToPack
4949 for _ , h := range hashes {
50- o , err := dw .storer . EncodedObject ( plumbing . AnyObject , h )
50+ o , err := dw .encodedDeltaObject ( h )
5151 if err != nil {
5252 return nil , err
5353 }
5454
55- objectsToPack = append (objectsToPack , newObjectToPack (o ))
55+ otp := newObjectToPack (o )
56+ if _ , ok := o .(plumbing.DeltaObject ); ok {
57+ otp .Original = nil
58+ }
59+
60+ objectsToPack = append (objectsToPack , otp )
61+ }
62+
63+ if err := dw .fixAndBreakChains (objectsToPack ); err != nil {
64+ return nil , err
5665 }
5766
5867 return objectsToPack , nil
5968}
6069
70+ func (dw * deltaSelector ) encodedDeltaObject (h plumbing.Hash ) (plumbing.EncodedObject , error ) {
71+ edos , ok := dw .storer .(storer.DeltaObjectStorer )
72+ if ! ok {
73+ return dw .encodedObject (h )
74+ }
75+
76+ return edos .DeltaObject (plumbing .AnyObject , h )
77+ }
78+
79+ func (dw * deltaSelector ) encodedObject (h plumbing.Hash ) (plumbing.EncodedObject , error ) {
80+ return dw .storer .EncodedObject (plumbing .AnyObject , h )
81+ }
82+
83+ func (dw * deltaSelector ) fixAndBreakChains (objectsToPack []* ObjectToPack ) error {
84+ m := make (map [plumbing.Hash ]* ObjectToPack , len (objectsToPack ))
85+ for _ , otp := range objectsToPack {
86+ m [otp .Hash ()] = otp
87+ }
88+
89+ for _ , otp := range objectsToPack {
90+ if err := dw .fixAndBreakChainsOne (m , otp ); err != nil {
91+ return err
92+ }
93+ }
94+
95+ return nil
96+ }
97+
98+ func (dw * deltaSelector ) fixAndBreakChainsOne (objectsToPack map [plumbing.Hash ]* ObjectToPack , otp * ObjectToPack ) error {
99+ if ! otp .Object .Type ().IsDelta () {
100+ return nil
101+ }
102+
103+ // Initial ObjectToPack instances might have a delta assigned to Object
104+ // but no actual base initially. Once Base is assigned to a delta, it means
105+ // we already fixed it.
106+ if otp .Base != nil {
107+ return nil
108+ }
109+
110+ do , ok := otp .Object .(plumbing.DeltaObject )
111+ if ! ok {
112+ // if this is not a DeltaObject, then we cannot retrieve its base,
113+ // so we have to break the delta chain here.
114+ return dw .undeltify (otp )
115+ }
116+
117+ base , ok := objectsToPack [do .BaseHash ()]
118+ if ! ok {
119+ // The base of the delta is not in our list of objects to pack, so
120+ // we break the chain.
121+ return dw .undeltify (otp )
122+ }
123+
124+ if base .Size () <= otp .Size () {
125+ // Bases should be bigger
126+ return dw .undeltify (otp )
127+ }
128+
129+ if err := dw .fixAndBreakChainsOne (objectsToPack , base ); err != nil {
130+ return err
131+ }
132+
133+ otp .SetDelta (base , otp .Object )
134+ return nil
135+ }
136+
137+ func (dw * deltaSelector ) restoreOriginal (otp * ObjectToPack ) error {
138+ if otp .Original != nil {
139+ return nil
140+ }
141+
142+ if ! otp .Object .Type ().IsDelta () {
143+ return nil
144+ }
145+
146+ obj , err := dw .encodedObject (otp .Hash ())
147+ if err != nil {
148+ return err
149+ }
150+
151+ otp .Original = obj
152+ return nil
153+ }
154+
155+ // undeltify undeltifies an *ObjectToPack by retrieving the original object from
156+ // the storer and resetting it.
157+ func (dw * deltaSelector ) undeltify (otp * ObjectToPack ) error {
158+ if err := dw .restoreOriginal (otp ); err != nil {
159+ return err
160+ }
161+
162+ otp .Object = otp .Original
163+ otp .Depth = 0
164+ return nil
165+ }
166+
61167func (dw * deltaSelector ) sort (objectsToPack []* ObjectToPack ) {
62168 sort .Sort (byTypeAndSize (objectsToPack ))
63169}
@@ -66,15 +172,24 @@ func (dw *deltaSelector) walk(objectsToPack []*ObjectToPack) error {
66172 for i := 0 ; i < len (objectsToPack ); i ++ {
67173 target := objectsToPack [i ]
68174
69- // We only want to create deltas from specific types
70- if ! applyDelta [target .Original .Type ()] {
175+ // If we already have a delta, we don't try to find a new one for this
176+ // object. This happens when a delta is set to be reused from an existing
177+ // packfile.
178+ if target .IsDelta () {
179+ continue
180+ }
181+
182+ // We only want to create deltas from specific types.
183+ if ! applyDelta [target .Type ()] {
71184 continue
72185 }
73186
74187 for j := i - 1 ; j >= 0 ; j -- {
75188 base := objectsToPack [j ]
76189 // Objects must use only the same type as their delta base.
77- if base .Original .Type () != target .Original .Type () {
190+ // Since objectsToPack is sorted by type and size, once we find
191+ // a different type, we know we won't find more of them.
192+ if base .Type () != target .Type () {
78193 break
79194 }
80195
@@ -89,7 +204,7 @@ func (dw *deltaSelector) walk(objectsToPack []*ObjectToPack) error {
89204
90205func (dw * deltaSelector ) tryToDeltify (base , target * ObjectToPack ) error {
91206 // If the sizes are radically different, this is a bad pairing.
92- if target .Original . Size () < base . Original .Size ()>> 4 {
207+ if target .Size () < base .Size ()>> 4 {
93208 return nil
94209 }
95210
@@ -106,10 +221,20 @@ func (dw *deltaSelector) tryToDeltify(base, target *ObjectToPack) error {
106221 }
107222
108223 // If we have to insert a lot to make this work, find another.
109- if base .Original . Size ()- target . Object .Size () > msz {
224+ if base .Size ()- target .Size () > msz {
110225 return nil
111226 }
112227
228+ // Original object might not be present if we're reusing a delta, so we
229+ // ensure it is restored.
230+ if err := dw .restoreOriginal (target ); err != nil {
231+ return err
232+ }
233+
234+ if err := dw .restoreOriginal (base ); err != nil {
235+ return err
236+ }
237+
113238 // Now we can generate the delta using originals
114239 delta , err := GetDelta (base .Original , target .Original )
115240 if err != nil {
@@ -162,13 +287,13 @@ func (a byTypeAndSize) Len() int { return len(a) }
162287func (a byTypeAndSize ) Swap (i , j int ) { a [i ], a [j ] = a [j ], a [i ] }
163288
164289func (a byTypeAndSize ) Less (i , j int ) bool {
165- if a [i ].Object . Type () < a [j ]. Object .Type () {
290+ if a [i ].Type () < a [j ].Type () {
166291 return false
167292 }
168293
169- if a [i ].Object . Type () > a [j ]. Object .Type () {
294+ if a [i ].Type () > a [j ].Type () {
170295 return true
171296 }
172297
173- return a [i ].Object . Size () > a [j ]. Object .Size ()
298+ return a [i ].Size () > a [j ].Size ()
174299}
0 commit comments