@@ -127,10 +127,61 @@ func (o *MergeTreeOptions) format(result *odb.MergeResult) {
127
127
128
128
type mergeTreeResult struct {
129
129
* odb.MergeResult
130
- Base plumbing.Hash
130
+ b0 plumbing.Hash
131
131
}
132
132
133
- func (r * Repository ) parseMergeBase (ctx context.Context , into , from , base * object.Commit , allowUnrelatedHistories bool ) (plumbing.Hash , * object.Tree , error ) {
133
+ func (r * Repository ) resolveAncestorTree0 (ctx context.Context , into , from * object.Commit , mergeDriver odb.MergeDriver , allowUnrelatedHistories , textconv bool ) (* object.Tree , error ) {
134
+ bases , err := into .MergeBase (ctx , from )
135
+ if err != nil {
136
+ die_error ("merge-base '%s-%s': %v" , from .Hash , into .Hash , err )
137
+ return nil , err
138
+ }
139
+ var o * object.Tree
140
+ switch len (bases ) {
141
+ case 0 :
142
+ if ! allowUnrelatedHistories {
143
+ r .DbgPrint ("merge: merge from %s to %s refusing to merge unrelated histories" , from .Hash , into .Hash )
144
+ fmt .Fprintf (os .Stderr , "merge: %s\n " , W ("refusing to merge unrelated histories" ))
145
+ return nil , ErrUnrelatedHistories
146
+ }
147
+ return r .odb .EmptyTree (), nil
148
+ case 1 :
149
+ if o , err = bases [0 ].Root (ctx ); err != nil {
150
+ die_error ("resolve bases tree: %v" , err )
151
+ return nil , err
152
+ }
153
+ default :
154
+ if o , err = r .resolveAncestorTree0 (ctx , bases [0 ], bases [1 ], mergeDriver , allowUnrelatedHistories , textconv ); err != nil {
155
+ return nil , err
156
+ }
157
+ }
158
+ a , err := into .Root (ctx )
159
+ if err != nil {
160
+ return nil , err
161
+ }
162
+ b , err := from .Root (ctx )
163
+ if err != nil {
164
+ return nil , err
165
+ }
166
+ result , err := r .odb .MergeTree (ctx , o , a , b , & odb.MergeOptions {
167
+ Branch1 : "Temporary merge branch 1" ,
168
+ Branch2 : "Temporary merge branch 2" ,
169
+ DetectRenames : true ,
170
+ Textconv : textconv ,
171
+ MergeDriver : mergeDriver ,
172
+ TextGetter : r .readMissingText ,
173
+ })
174
+ if err != nil {
175
+ return nil , err
176
+ }
177
+ if len (result .Conflicts ) != 0 {
178
+ return nil , result
179
+ }
180
+ r .DbgPrint ("make new merge-tree: %s" , result .NewTree )
181
+ return r .odb .Tree (ctx , result .NewTree )
182
+ }
183
+
184
+ func (r * Repository ) resolveAncestorTree (ctx context.Context , into , from , base * object.Commit , mergeDriver odb.MergeDriver , allowUnrelatedHistories , textconv bool ) (plumbing.Hash , * object.Tree , error ) {
134
185
if base != nil {
135
186
o , err := base .Root (ctx )
136
187
if err != nil {
@@ -152,20 +203,29 @@ func (r *Repository) parseMergeBase(ctx context.Context, into, from, base *objec
152
203
}
153
204
return plumbing .ZeroHash , r .odb .EmptyTree (), nil
154
205
}
155
- o , err := bases [0 ].Root (ctx )
206
+ if len (bases ) == 1 {
207
+ o , err := bases [0 ].Root (ctx )
208
+ if err != nil {
209
+ die_error ("resolve bases tree: %v" , err )
210
+ return plumbing .ZeroHash , nil , err
211
+ }
212
+ return bases [0 ].Hash , o , nil
213
+ }
214
+ o , err := r .resolveAncestorTree0 (ctx , bases [0 ], bases [1 ], mergeDriver , allowUnrelatedHistories , textconv )
156
215
if err != nil {
157
- die_error ("resolve bases tree: %v" , err )
158
216
return plumbing .ZeroHash , nil , err
159
217
}
218
+
160
219
return bases [0 ].Hash , o , nil
161
220
}
162
221
163
222
func (r * Repository ) mergeTree (ctx context.Context , into , from , base * object.Commit , branch1 , branch2 string , allowUnrelatedHistories , textconv bool ) (* mergeTreeResult , error ) {
164
- baseID , o , err := r .parseMergeBase (ctx , into , from , base , allowUnrelatedHistories )
223
+ mergeDriver := r .resolveMergeDriver ()
224
+ base0 , o , err := r .resolveAncestorTree (ctx , into , from , base , mergeDriver , allowUnrelatedHistories , textconv )
165
225
if err != nil {
166
226
return nil , err
167
227
}
168
- r .DbgPrint ("merge from %s to %s base: %s" , from .Hash , into .Hash , baseID )
228
+ r .DbgPrint ("merge from %s to %s base: %s" , from .Hash , into .Hash , base0 )
169
229
a , err := from .Root (ctx )
170
230
if err != nil {
171
231
die_error ("read tree '%s:' %v" , from .Hash , err )
@@ -177,21 +237,21 @@ func (r *Repository) mergeTree(ctx context.Context, into, from, base *object.Com
177
237
return nil , err
178
238
}
179
239
if a .Equal (b ) {
180
- return & mergeTreeResult {MergeResult : & odb.MergeResult {NewTree : a .Hash }, Base : baseID }, nil
240
+ return & mergeTreeResult {MergeResult : & odb.MergeResult {NewTree : a .Hash }, b0 : base0 }, nil
181
241
}
182
242
result , err := r .odb .MergeTree (ctx , o , a , b , & odb.MergeOptions {
183
243
Branch1 : branch1 ,
184
244
Branch2 : branch2 ,
185
245
DetectRenames : true ,
186
246
Textconv : textconv ,
187
- MergeDriver : r . resolveMergeDriver () ,
247
+ MergeDriver : mergeDriver ,
188
248
TextGetter : r .readMissingText ,
189
249
})
190
250
if err != nil {
191
251
die_error ("merge-tree: %v" , err )
192
252
return nil , err
193
253
}
194
- return & mergeTreeResult {MergeResult : result , Base : baseID }, nil
254
+ return & mergeTreeResult {MergeResult : result , b0 : base0 }, nil
195
255
}
196
256
197
257
func (r * Repository ) MergeTree (ctx context.Context , opts * MergeTreeOptions ) error {
@@ -214,6 +274,10 @@ func (r *Repository) MergeTree(ctx context.Context, opts *MergeTreeOptions) erro
214
274
}
215
275
result , err := r .mergeTree (ctx , c1 , c2 , base , opts .Branch1 , opts .Branch2 , opts .AllowUnrelatedHistories , opts .Textconv )
216
276
if err != nil {
277
+ if mr , ok := err .(* odb.MergeResult ); ok {
278
+ opts .format (mr )
279
+ return ErrHasConflicts
280
+ }
217
281
return err
218
282
}
219
283
opts .format (result .MergeResult )
0 commit comments