108 repo.ui.debug(_(" overwrite %s branchmerge %s partial %s linear %s\n") % |
108 repo.ui.debug(_(" overwrite %s branchmerge %s partial %s linear %s\n") % |
109 (overwrite, branchmerge, bool(partial), linear_path)) |
109 (overwrite, branchmerge, bool(partial), linear_path)) |
110 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % |
110 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % |
111 (short(man), short(m1n), short(m2n))) |
111 (short(man), short(m1n), short(m2n))) |
112 |
112 |
113 merge = {} |
113 action = {} |
114 get = {} |
|
115 remove = [] |
114 remove = [] |
116 forget = [] |
115 forget = [] |
117 |
116 |
118 # update m1 from working dir |
117 # update m1 from working dir |
119 umap = dict.fromkeys(unknown) |
118 umap = dict.fromkeys(unknown) |
148 if n != m2[f]: |
147 if n != m2[f]: |
149 a = ma.get(f, nullid) |
148 a = ma.get(f, nullid) |
150 # are both different from the ancestor? |
149 # are both different from the ancestor? |
151 if not overwrite and n != a and m2[f] != a: |
150 if not overwrite and n != a and m2[f] != a: |
152 repo.ui.debug(_(" %s versions differ, resolve\n") % f) |
151 repo.ui.debug(_(" %s versions differ, resolve\n") % f) |
153 merge[f] = (fmerge(f, m1, m2, ma), n[:20], m2[f]) |
152 action[f] = (fmerge(f, m1, m2, ma), n[:20], m2[f]) |
154 queued = 1 |
153 queued = 1 |
155 # are we clobbering? |
154 # are we clobbering? |
156 # is remote's version newer? |
155 # is remote's version newer? |
157 # or are we going back in time and clean? |
156 # or are we going back in time and clean? |
158 elif overwrite or m2[f] != a or (backwards and not n[20:]): |
157 elif overwrite or m2[f] != a or (backwards and not n[20:]): |
159 repo.ui.debug(_(" remote %s is newer, get\n") % f) |
158 repo.ui.debug(_(" remote %s is newer, get\n") % f) |
160 get[f] = (m2.execf(f), m2[f]) |
159 action[f] = (m2.execf(f), m2[f], None) |
161 queued = 1 |
160 queued = 1 |
162 elif f in umap or f in added: |
161 elif f in umap or f in added: |
163 # this unknown file is the same as the checkout |
162 # this unknown file is the same as the checkout |
164 # we need to reset the dirstate if the file was added |
163 # we need to reset the dirstate if the file was added |
165 get[f] = (m2.execf(f), m2[f]) |
164 action[f] = (m2.execf(f), m2[f], None) |
166 |
165 |
167 # do we still need to look at mode bits? |
166 # do we still need to look at mode bits? |
168 if not queued and m1.execf(f) != m2.execf(f): |
167 if not queued and m1.execf(f) != m2.execf(f): |
169 if overwrite: |
168 if overwrite: |
170 repo.ui.debug(_(" updating permissions for %s\n") % f) |
169 repo.ui.debug(_(" updating permissions for %s\n") % f) |
209 if not overwrite: |
208 if not overwrite: |
210 r = repo.ui.prompt( |
209 r = repo.ui.prompt( |
211 (_("remote changed %s which local deleted\n") % f) + |
210 (_("remote changed %s which local deleted\n") % f) + |
212 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) |
211 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) |
213 if r == _("k"): |
212 if r == _("k"): |
214 get[f] = (m2.execf(f), n) |
213 action[f] = (m2.execf(f), n, None) |
215 elif f not in ma: |
214 elif f not in ma: |
216 repo.ui.debug(_("remote created %s\n") % f) |
215 repo.ui.debug(_("remote created %s\n") % f) |
217 get[f] = (m2.execf(f), n) |
216 action[f] = (m2.execf(f), n, None) |
218 else: |
217 else: |
219 if overwrite or backwards: |
218 if overwrite or backwards: |
220 repo.ui.debug(_("local deleted %s, recreating\n") % f) |
219 repo.ui.debug(_("local deleted %s, recreating\n") % f) |
221 get[f] = (m2.execf(f), n) |
220 action[f] = (m2.execf(f), n, None) |
222 else: |
221 else: |
223 repo.ui.debug(_("local deleted %s\n") % f) |
222 repo.ui.debug(_("local deleted %s\n") % f) |
224 |
223 |
225 del m1, m2, ma |
224 del m1, m2, ma |
226 |
225 |
235 if p2 == nullid: xxp2 = '' |
234 if p2 == nullid: xxp2 = '' |
236 else: xxp2 = xp2 |
235 else: xxp2 = xp2 |
237 |
236 |
238 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xxp2) |
237 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xxp2) |
239 |
238 |
240 # get the files we don't need to change |
239 # update files |
241 files = get.keys() |
240 unresolved = [] |
|
241 updated = 0 |
|
242 merged = 0 |
|
243 files = action.keys() |
242 files.sort() |
244 files.sort() |
243 for f in files: |
245 for f in files: |
244 flag, node = get[f] |
246 flag, my, other = action[f] |
245 if f[0] == "/": |
247 if f[0] == "/": |
246 continue |
248 continue |
247 repo.ui.note(_("getting %s\n") % f) |
249 if other: |
248 t = repo.file(f).read(node) |
250 repo.ui.status(_("merging %s\n") % f) |
249 repo.wwrite(f, t) |
251 if merge3(repo, f, my, other, xp1, xp2): |
250 util.set_exec(repo.wjoin(f), flag) |
252 unresolved.append(f) |
251 |
253 merged += 1 |
252 # merge the tricky bits |
254 else: |
253 unresolved = [] |
255 repo.ui.note(_("getting %s\n") % f) |
254 files = merge.keys() |
256 t = repo.file(f).read(my) |
255 files.sort() |
257 repo.wwrite(f, t) |
256 for f in files: |
258 updated += 1 |
257 repo.ui.status(_("merging %s\n") % f) |
|
258 flag, my, other = merge[f] |
|
259 ret = merge3(repo, f, my, other, xp1, xp2) |
|
260 if ret: |
|
261 unresolved.append(f) |
|
262 util.set_exec(repo.wjoin(f), flag) |
259 util.set_exec(repo.wjoin(f), flag) |
263 |
260 |
264 remove.sort() |
261 remove.sort() |
265 for f in remove: |
262 for f in remove: |
266 repo.ui.note(_("removing %s\n") % f) |
263 repo.ui.note(_("removing %s\n") % f) |
279 if branchmerge: |
276 if branchmerge: |
280 repo.dirstate.update(remove, 'r') |
277 repo.dirstate.update(remove, 'r') |
281 else: |
278 else: |
282 repo.dirstate.forget(remove) |
279 repo.dirstate.forget(remove) |
283 |
280 |
284 files = get.keys() |
281 files = action.keys() |
285 files.sort() |
282 files.sort() |
286 for f in files: |
283 for f in files: |
287 if branchmerge: |
284 flag, my, other = action[f] |
288 repo.dirstate.update([f], 'n', st_mtime=-1) |
285 if not other: |
|
286 if branchmerge: |
|
287 repo.dirstate.update([f], 'n', st_mtime=-1) |
|
288 else: |
|
289 repo.dirstate.update([f], 'n') |
289 else: |
290 else: |
290 repo.dirstate.update([f], 'n') |
291 if branchmerge: |
291 |
292 # We've done a branch merge, mark this file as merged |
292 files = merge.keys() |
293 # so that we properly record the merger later |
293 files.sort() |
294 repo.dirstate.update([f], 'm') |
294 for f in files: |
295 else: |
295 if branchmerge: |
296 # We've update-merged a locally modified file, so |
296 # We've done a branch merge, mark this file as merged |
297 # we set the dirstate to emulate a normal checkout |
297 # so that we properly record the merger later |
298 # of that file some time in the past. Thus our |
298 repo.dirstate.update([f], 'm') |
299 # merge will appear as a normal local file |
299 else: |
300 # modification. |
300 # We've update-merged a locally modified file, so |
301 fl = repo.file(f) |
301 # we set the dirstate to emulate a normal checkout |
302 f_len = fl.size(fl.rev(other)) |
302 # of that file some time in the past. Thus our |
303 repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1) |
303 # merge will appear as a normal local file |
|
304 # modification. |
|
305 fl = repo.file(f) |
|
306 f_len = fl.size(fl.rev(other)) |
|
307 repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1) |
|
308 |
304 |
309 if show_stats: |
305 if show_stats: |
310 stats = ((len(get), _("updated")), |
306 stats = ((updated, _("updated")), |
311 (len(merge) - len(unresolved), _("merged")), |
307 (merged - len(unresolved), _("merged")), |
312 (len(remove), _("removed")), |
308 (len(remove), _("removed")), |
313 (len(unresolved), _("unresolved"))) |
309 (len(unresolved), _("unresolved"))) |
314 note = ", ".join([_("%d files %s") % s for s in stats]) |
310 note = ", ".join([_("%d files %s") % s for s in stats]) |
315 repo.ui.status("%s\n" % note) |
311 repo.ui.status("%s\n" % note) |
316 if not partial: |
312 if not partial: |