Mercurial > public > mercurial-scm > hg
comparison mercurial/merge.py @ 3111:5cc62d99b785
merge: move apply and dirstate code into separate functions
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sun, 17 Sep 2006 17:39:19 -0500 |
parents | 40e777bda455 |
children | f96c8e219865 |
comparison
equal
deleted
inserted
replaced
3110:40e777bda455 | 3111:5cc62d99b785 |
---|---|
197 else: | 197 else: |
198 ui.debug(_("local deleted %s\n") % f) | 198 ui.debug(_("local deleted %s\n") % f) |
199 | 199 |
200 return action | 200 return action |
201 | 201 |
202 def update(repo, node, branchmerge=False, force=False, partial=None, | 202 def applyupdates(repo, action, xp1, xp2): |
203 wlock=None, show_stats=True, remind=True): | |
204 | |
205 overwrite = force and not branchmerge | |
206 forcemerge = force and branchmerge | |
207 | |
208 if not wlock: | |
209 wlock = repo.wlock() | |
210 | |
211 ### check phase | |
212 | |
213 pl = repo.dirstate.parents() | |
214 if not overwrite and pl[1] != nullid: | |
215 raise util.Abort(_("outstanding uncommitted merges")) | |
216 | |
217 p1, p2 = pl[0], node | |
218 pa = repo.changelog.ancestor(p1, p2) | |
219 | |
220 # are we going backwards? | |
221 backwards = (pa == p2) | |
222 | |
223 # is there a linear path from p1 to p2? | |
224 if pa == p1 or pa == p2: | |
225 if branchmerge: | |
226 raise util.Abort(_("there is nothing to merge, just use " | |
227 "'hg update' or look at 'hg heads'")) | |
228 elif not (overwrite or branchmerge): | |
229 raise util.Abort(_("update spans branches, use 'hg merge' " | |
230 "or 'hg update -C' to lose changes")) | |
231 | |
232 status = repo.status() | |
233 modified, added, removed, deleted, unknown = status[:5] | |
234 if branchmerge and not forcemerge: | |
235 if modified or added or removed: | |
236 raise util.Abort(_("outstanding uncommitted changes")) | |
237 | |
238 m1 = repo.changectx(p1).manifest().copy() | |
239 m2 = repo.changectx(p2).manifest().copy() | |
240 ma = repo.changectx(pa).manifest() | |
241 | |
242 # resolve the manifest to determine which files | |
243 # we care about merging | |
244 repo.ui.note(_("resolving manifests\n")) | |
245 repo.ui.debug(_(" overwrite %s branchmerge %s partial %s\n") % | |
246 (overwrite, branchmerge, bool(partial))) | |
247 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % | |
248 (short(p1), short(p2), short(pa))) | |
249 | |
250 action = [] | |
251 m1 = workingmanifest(repo, m1, status) | |
252 | |
253 if not force: | |
254 checkunknown(repo, m2, status) | |
255 if not branchmerge: | |
256 action += forgetremoved(m2, status) | |
257 action += manifestmerge(repo.ui, m1, m2, ma, overwrite, backwards, partial) | |
258 del m1, m2, ma | |
259 | |
260 ### apply phase | |
261 | |
262 if not branchmerge: | |
263 # we don't need to do any magic, just jump to the new rev | |
264 p1, p2 = p2, nullid | |
265 | |
266 xp1, xp2 = hex(p1), hex(p2) | |
267 if p2 == nullid: xp2 = '' | |
268 | |
269 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2) | |
270 | |
271 # update files | |
272 updated, merged, removed, unresolved = 0, 0, 0, 0 | 203 updated, merged, removed, unresolved = 0, 0, 0, 0 |
273 action.sort() | 204 action.sort() |
274 for a in action: | 205 for a in action: |
275 f, m = a[:2] | 206 f, m = a[:2] |
276 if f[0] == "/": | 207 if f[0] == "/": |
301 updated += 1 | 232 updated += 1 |
302 elif m == "e": # exec | 233 elif m == "e": # exec |
303 flag = a[2:] | 234 flag = a[2:] |
304 util.set_exec(repo.wjoin(f), flag) | 235 util.set_exec(repo.wjoin(f), flag) |
305 | 236 |
237 return updated, merged, removed, unresolved | |
238 | |
239 def recordupdates(repo, action, branchmerge): | |
240 for a in action: | |
241 f, m = a[:2] | |
242 if m == "r": # remove | |
243 if branchmerge: | |
244 repo.dirstate.update([f], 'r') | |
245 else: | |
246 repo.dirstate.forget([f]) | |
247 elif m == "f": # forget | |
248 repo.dirstate.forget([f]) | |
249 elif m == "g": # get | |
250 if branchmerge: | |
251 repo.dirstate.update([f], 'n', st_mtime=-1) | |
252 else: | |
253 repo.dirstate.update([f], 'n') | |
254 elif m == "m": # merge | |
255 flag, my, other = a[2:] | |
256 if branchmerge: | |
257 # We've done a branch merge, mark this file as merged | |
258 # so that we properly record the merger later | |
259 repo.dirstate.update([f], 'm') | |
260 else: | |
261 # We've update-merged a locally modified file, so | |
262 # we set the dirstate to emulate a normal checkout | |
263 # of that file some time in the past. Thus our | |
264 # merge will appear as a normal local file | |
265 # modification. | |
266 fl = repo.file(f) | |
267 f_len = fl.size(fl.rev(other)) | |
268 repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1) | |
269 | |
270 def update(repo, node, branchmerge=False, force=False, partial=None, | |
271 wlock=None, show_stats=True, remind=True): | |
272 | |
273 overwrite = force and not branchmerge | |
274 forcemerge = force and branchmerge | |
275 | |
276 if not wlock: | |
277 wlock = repo.wlock() | |
278 | |
279 ### check phase | |
280 | |
281 pl = repo.dirstate.parents() | |
282 if not overwrite and pl[1] != nullid: | |
283 raise util.Abort(_("outstanding uncommitted merges")) | |
284 | |
285 p1, p2 = pl[0], node | |
286 pa = repo.changelog.ancestor(p1, p2) | |
287 | |
288 # are we going backwards? | |
289 backwards = (pa == p2) | |
290 | |
291 # is there a linear path from p1 to p2? | |
292 if pa == p1 or pa == p2: | |
293 if branchmerge: | |
294 raise util.Abort(_("there is nothing to merge, just use " | |
295 "'hg update' or look at 'hg heads'")) | |
296 elif not (overwrite or branchmerge): | |
297 raise util.Abort(_("update spans branches, use 'hg merge' " | |
298 "or 'hg update -C' to lose changes")) | |
299 | |
300 status = repo.status() | |
301 modified, added, removed, deleted, unknown = status[:5] | |
302 if branchmerge and not forcemerge: | |
303 if modified or added or removed: | |
304 raise util.Abort(_("outstanding uncommitted changes")) | |
305 | |
306 m1 = repo.changectx(p1).manifest().copy() | |
307 m2 = repo.changectx(p2).manifest().copy() | |
308 ma = repo.changectx(pa).manifest() | |
309 | |
310 # resolve the manifest to determine which files | |
311 # we care about merging | |
312 repo.ui.note(_("resolving manifests\n")) | |
313 repo.ui.debug(_(" overwrite %s branchmerge %s partial %s\n") % | |
314 (overwrite, branchmerge, bool(partial))) | |
315 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % | |
316 (short(p1), short(p2), short(pa))) | |
317 | |
318 action = [] | |
319 m1 = workingmanifest(repo, m1, status) | |
320 | |
321 if not force: | |
322 checkunknown(repo, m2, status) | |
323 if not branchmerge: | |
324 action += forgetremoved(m2, status) | |
325 action += manifestmerge(repo.ui, m1, m2, ma, overwrite, backwards, partial) | |
326 del m1, m2, ma | |
327 | |
328 ### apply phase | |
329 | |
330 if not branchmerge: | |
331 # we don't need to do any magic, just jump to the new rev | |
332 p1, p2 = p2, nullid | |
333 | |
334 xp1, xp2 = hex(p1), hex(p2) | |
335 if p2 == nullid: xp2 = '' | |
336 | |
337 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2) | |
338 | |
339 updated, merged, removed, unresolved = applyupdates(repo, action, xp1, xp2) | |
340 | |
306 # update dirstate | 341 # update dirstate |
307 if not partial: | 342 if not partial: |
308 repo.dirstate.setparents(p1, p2) | 343 repo.dirstate.setparents(p1, p2) |
309 for a in action: | 344 recordupdates(repo, action, branchmerge) |
310 f, m = a[:2] | |
311 if m == "r": # remove | |
312 if branchmerge: | |
313 repo.dirstate.update([f], 'r') | |
314 else: | |
315 repo.dirstate.forget([f]) | |
316 elif m == "f": # forget | |
317 repo.dirstate.forget([f]) | |
318 elif m == "g": # get | |
319 if branchmerge: | |
320 repo.dirstate.update([f], 'n', st_mtime=-1) | |
321 else: | |
322 repo.dirstate.update([f], 'n') | |
323 elif m == "m": # merge | |
324 flag, my, other = a[2:] | |
325 if branchmerge: | |
326 # We've done a branch merge, mark this file as merged | |
327 # so that we properly record the merger later | |
328 repo.dirstate.update([f], 'm') | |
329 else: | |
330 # We've update-merged a locally modified file, so | |
331 # we set the dirstate to emulate a normal checkout | |
332 # of that file some time in the past. Thus our | |
333 # merge will appear as a normal local file | |
334 # modification. | |
335 fl = repo.file(f) | |
336 f_len = fl.size(fl.rev(other)) | |
337 repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1) | |
338 | 345 |
339 if show_stats: | 346 if show_stats: |
340 stats = ((updated, _("updated")), | 347 stats = ((updated, _("updated")), |
341 (merged - unresolved, _("merged")), | 348 (merged - unresolved, _("merged")), |
342 (removed, _("removed")), | 349 (removed, _("removed")), |