45 |
45 |
46 os.unlink(b) |
46 os.unlink(b) |
47 os.unlink(c) |
47 os.unlink(c) |
48 return r |
48 return r |
49 |
49 |
50 def update(repo, node, branchmerge=False, force=False, choose=None, |
50 def update(repo, node, branchmerge=False, force=False, partial=None, |
51 moddirstate=True, forcemerge=False, wlock=None, show_stats=True, |
51 forcemerge=False, wlock=None, show_stats=True, remind=True): |
52 remind=True): |
|
53 pl = repo.dirstate.parents() |
52 pl = repo.dirstate.parents() |
54 if not force and pl[1] != nullid: |
53 if not force and pl[1] != nullid: |
55 raise util.Abort(_("outstanding uncommitted merges")) |
54 raise util.Abort(_("outstanding uncommitted merges")) |
56 |
55 |
57 err = False |
56 err = False |
91 " dir and differs from remote") % f) |
90 " dir and differs from remote") % f) |
92 |
91 |
93 # resolve the manifest to determine which files |
92 # resolve the manifest to determine which files |
94 # we care about merging |
93 # we care about merging |
95 repo.ui.note(_("resolving manifests\n")) |
94 repo.ui.note(_("resolving manifests\n")) |
96 repo.ui.debug(_(" force %s branchmerge %s moddirstate %s linear %s\n") % |
95 repo.ui.debug(_(" force %s branchmerge %s partial %s linear %s\n") % |
97 (force, branchmerge, moddirstate, linear_path)) |
96 (force, branchmerge, partial and True or False, linear_path)) |
98 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % |
97 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % |
99 (short(man), short(m1n), short(m2n))) |
98 (short(man), short(m1n), short(m2n))) |
100 |
99 |
101 merge = {} |
100 merge = {} |
102 get = {} |
101 get = {} |
109 |
108 |
110 for f in added + modified + unknown: |
109 for f in added + modified + unknown: |
111 mw[f] = "" |
110 mw[f] = "" |
112 mfw[f] = util.is_exec(repo.wjoin(f), mfw.get(f, False)) |
111 mfw[f] = util.is_exec(repo.wjoin(f), mfw.get(f, False)) |
113 |
112 |
114 if moddirstate and not wlock: |
113 if not partial and not wlock: wlock = repo.wlock() |
115 wlock = repo.wlock() |
|
116 |
114 |
117 for f in deleted + removed: |
115 for f in deleted + removed: |
118 if f in mw: |
116 if f in mw: |
119 del mw[f] |
117 del mw[f] |
120 |
118 |
121 # If we're jumping between revisions (as opposed to merging), |
119 # If we're jumping between revisions (as opposed to merging), |
122 # and if neither the working directory nor the target rev has |
120 # and if neither the working directory nor the target rev has |
123 # the file, then we need to remove it from the dirstate, to |
121 # the file, then we need to remove it from the dirstate, to |
124 # prevent the dirstate from listing the file when it is no |
122 # prevent the dirstate from listing the file when it is no |
125 # longer in the manifest. |
123 # longer in the manifest. |
126 if moddirstate and linear_path and f not in m2: |
124 if not partial and linear_path and f not in m2: |
127 repo.dirstate.forget((f,)) |
125 repo.dirstate.forget((f,)) |
128 |
126 |
129 # Compare manifests |
127 # Compare manifests |
130 for f, n in mw.iteritems(): |
128 for f, n in mw.iteritems(): |
131 if choose and not choose(f): |
129 if partial and not partial(f): |
132 continue |
130 continue |
133 if f in m2: |
131 if f in m2: |
134 s = 0 |
132 s = 0 |
135 |
133 |
136 # is the wfile new since m1, and match m2? |
134 # is the wfile new since m1, and match m2? |
202 repo.ui.debug(_("local modified %s, keeping\n") % f) |
200 repo.ui.debug(_("local modified %s, keeping\n") % f) |
203 else: |
201 else: |
204 repo.ui.debug(_("working dir created %s, keeping\n") % f) |
202 repo.ui.debug(_("working dir created %s, keeping\n") % f) |
205 |
203 |
206 for f, n in m2.iteritems(): |
204 for f, n in m2.iteritems(): |
207 if choose and not choose(f): |
205 if partial and not partial(f): |
208 continue |
206 continue |
209 if f[0] == "/": |
207 if f[0] == "/": |
210 continue |
208 continue |
211 if f in ma and n != ma[f]: |
209 if f in ma and n != ma[f]: |
212 r = _("k") |
210 r = _("k") |
267 continue |
265 continue |
268 repo.ui.note(_("getting %s\n") % f) |
266 repo.ui.note(_("getting %s\n") % f) |
269 t = repo.file(f).read(get[f]) |
267 t = repo.file(f).read(get[f]) |
270 repo.wwrite(f, t) |
268 repo.wwrite(f, t) |
271 util.set_exec(repo.wjoin(f), mf2[f]) |
269 util.set_exec(repo.wjoin(f), mf2[f]) |
272 if moddirstate: |
270 if not partial: |
273 if branchmerge: |
271 if branchmerge: |
274 repo.dirstate.update([f], 'n', st_mtime=-1) |
272 repo.dirstate.update([f], 'n', st_mtime=-1) |
275 else: |
273 else: |
276 repo.dirstate.update([f], 'n') |
274 repo.dirstate.update([f], 'n') |
277 |
275 |
285 ret = merge3(repo, f, my, other, xp1, xp2) |
283 ret = merge3(repo, f, my, other, xp1, xp2) |
286 if ret: |
284 if ret: |
287 err = True |
285 err = True |
288 failedmerge.append(f) |
286 failedmerge.append(f) |
289 util.set_exec(repo.wjoin(f), flag) |
287 util.set_exec(repo.wjoin(f), flag) |
290 if moddirstate: |
288 if not partial: |
291 if branchmerge: |
289 if branchmerge: |
292 # We've done a branch merge, mark this file as merged |
290 # We've done a branch merge, mark this file as merged |
293 # so that we properly record the merger later |
291 # so that we properly record the merger later |
294 repo.dirstate.update([f], 'm') |
292 repo.dirstate.update([f], 'm') |
295 else: |
293 else: |
309 util.unlink(repo.wjoin(f)) |
307 util.unlink(repo.wjoin(f)) |
310 except OSError, inst: |
308 except OSError, inst: |
311 if inst.errno != errno.ENOENT: |
309 if inst.errno != errno.ENOENT: |
312 repo.ui.warn(_("update failed to remove %s: %s!\n") % |
310 repo.ui.warn(_("update failed to remove %s: %s!\n") % |
313 (f, inst.strerror)) |
311 (f, inst.strerror)) |
314 if moddirstate: |
312 if not partial: |
315 if branchmerge: |
313 if branchmerge: |
316 repo.dirstate.update(remove, 'r') |
314 repo.dirstate.update(remove, 'r') |
317 else: |
315 else: |
318 repo.dirstate.forget(remove) |
316 repo.dirstate.forget(remove) |
319 |
317 |
320 if moddirstate: |
318 if not partial: |
321 repo.dirstate.setparents(p1, p2) |
319 repo.dirstate.setparents(p1, p2) |
322 |
320 |
323 if show_stats: |
321 if show_stats: |
324 stats = ((len(get), _("updated")), |
322 stats = ((len(get), _("updated")), |
325 (len(merge) - len(failedmerge), _("merged")), |
323 (len(merge) - len(failedmerge), _("merged")), |
326 (len(remove), _("removed")), |
324 (len(remove), _("removed")), |
327 (len(failedmerge), _("unresolved"))) |
325 (len(failedmerge), _("unresolved"))) |
328 note = ", ".join([_("%d files %s") % s for s in stats]) |
326 note = ", ".join([_("%d files %s") % s for s in stats]) |
329 repo.ui.status("%s\n" % note) |
327 repo.ui.status("%s\n" % note) |
330 if moddirstate: |
328 if not partial: |
331 if branchmerge: |
329 if branchmerge: |
332 if failedmerge: |
330 if failedmerge: |
333 repo.ui.status(_("There are unresolved merges," |
331 repo.ui.status(_("There are unresolved merges," |
334 " you can redo the full merge using:\n" |
332 " you can redo the full merge using:\n" |
335 " hg update -C %s\n" |
333 " hg update -C %s\n" |