Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/merge.py @ 3249:f05c182430a0
merge: add rename following
Currently disabled by default, enable with
[merge]
followcopies = 1
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 04 Oct 2006 15:43:27 -0500 |
parents | 751840e739a1 |
children | c93ce7f10f85 |
comparison
equal
deleted
inserted
replaced
3248:751840e739a1 | 3249:f05c182430a0 |
---|---|
52 environ={'HG_FILE': fw, | 52 environ={'HG_FILE': fw, |
53 'HG_MY_NODE': p1, | 53 'HG_MY_NODE': p1, |
54 'HG_OTHER_NODE': p2}) | 54 'HG_OTHER_NODE': p2}) |
55 if r: | 55 if r: |
56 repo.ui.warn(_("merging %s failed!\n") % fw) | 56 repo.ui.warn(_("merging %s failed!\n") % fw) |
57 else: | |
58 if fd != fw: | |
59 repo.ui.debug(_("copying %s to %s\n") % (fw, fd)) | |
60 repo.wwrite(fd, repo.wread(fw)) | |
61 if move: | |
62 repo.ui.debug(_("removing %s\n") % fw) | |
63 os.unlink(a) | |
57 | 64 |
58 os.unlink(b) | 65 os.unlink(b) |
59 os.unlink(c) | 66 os.unlink(c) |
60 return r | 67 return r |
61 | 68 |
124 def findcopies(repo, m1, m2, limit): | 131 def findcopies(repo, m1, m2, limit): |
125 """ | 132 """ |
126 Find moves and copies between m1 and m2 back to limit linkrev | 133 Find moves and copies between m1 and m2 back to limit linkrev |
127 """ | 134 """ |
128 | 135 |
136 if not repo.ui.config("merge", "followcopies"): | |
137 return {} | |
138 | |
129 # avoid silly behavior for update from empty dir | 139 # avoid silly behavior for update from empty dir |
130 if not m1: | 140 if not m1: |
131 return {} | 141 return {} |
132 | 142 |
133 dcopies = repo.dirstate.copies() | 143 dcopies = repo.dirstate.copies() |
162 for mf in match[of]: | 172 for mf in match[of]: |
163 checkpair(c, mf, m1) | 173 checkpair(c, mf, m1) |
164 | 174 |
165 return copy | 175 return copy |
166 | 176 |
167 def manifestmerge(ui, m1, m2, ma, overwrite, backwards, partial): | 177 def manifestmerge(ui, m1, m2, ma, copy, overwrite, backwards, partial): |
168 """ | 178 """ |
169 Merge manifest m1 with m2 using ancestor ma and generate merge action list | 179 Merge manifest m1 with m2 using ancestor ma and generate merge action list |
170 """ | 180 """ |
171 | 181 |
172 def fmerge(f): | 182 def fmerge(f, f2=None, fa=None): |
173 """merge executable flags""" | 183 """merge executable flags""" |
174 a, b, c = ma.execf(f), m1.execf(f), m2.execf(f) | 184 if not f2: |
185 f2 = f | |
186 fa = f | |
187 a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2) | |
175 return ((a^b) | (a^c)) ^ a | 188 return ((a^b) | (a^c)) ^ a |
176 | 189 |
177 action = [] | 190 action = [] |
178 | 191 |
179 def act(msg, f, m, *args): | 192 def act(msg, f, m, *args): |
201 act("update permissions", f, "e", m2.execf(f)) | 214 act("update permissions", f, "e", m2.execf(f)) |
202 # contents same, check mode bits | 215 # contents same, check mode bits |
203 elif m1.execf(f) != m2.execf(f): | 216 elif m1.execf(f) != m2.execf(f): |
204 if overwrite or fmerge(f) != m1.execf(f): | 217 if overwrite or fmerge(f) != m1.execf(f): |
205 act("update permissions", f, "e", m2.execf(f)) | 218 act("update permissions", f, "e", m2.execf(f)) |
219 elif f in copy: | |
220 f2 = copy[f] | |
221 if f in ma: # case 3,20 A/B/A | |
222 act("remote moved", | |
223 f, "c", f2, f2, m1[f], m2[f2], fmerge(f, f2, f), True) | |
224 else: | |
225 if f2 in m1: # case 2 A,B/B/B | |
226 act("local copied", | |
227 f, "c", f2, f, m1[f], m2[f2], fmerge(f, f2, f2), False) | |
228 else: # case 4,21 A/B/B | |
229 act("local moved", | |
230 f, "c", f2, f, m1[f], m2[f2], fmerge(f, f2, f2), False) | |
206 elif f in ma: | 231 elif f in ma: |
207 if n != ma[f] and not overwrite: | 232 if n != ma[f] and not overwrite: |
208 if ui.prompt( | 233 if ui.prompt( |
209 (_(" local changed %s which remote deleted\n") % f) + | 234 (_(" local changed %s which remote deleted\n") % f) + |
210 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("d"): | 235 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("d"): |
219 for f, n in m2.iteritems(): | 244 for f, n in m2.iteritems(): |
220 if partial and not partial(f): | 245 if partial and not partial(f): |
221 continue | 246 continue |
222 if f in m1: | 247 if f in m1: |
223 continue | 248 continue |
224 if f in ma: | 249 if f in copy: |
250 f2 = copy[f] | |
251 if f2 in ma or f2 in m1: # already seen | |
252 continue | |
253 # rename case 1, A/A,B/A | |
254 act("remote copied", | |
255 f, "c", f2, f, m1[f2], m2[f], fmerge(f2, f, f2), False) | |
256 elif f in ma: | |
225 if overwrite or backwards: | 257 if overwrite or backwards: |
226 act("recreating", f, "g", m2.execf(f), n) | 258 act("recreating", f, "g", m2.execf(f), n) |
227 elif n != ma[f]: | 259 elif n != ma[f]: |
228 if ui.prompt( | 260 if ui.prompt( |
229 (_("remote changed %s which local deleted\n") % f) + | 261 (_("remote changed %s which local deleted\n") % f) + |
249 except OSError, inst: | 281 except OSError, inst: |
250 if inst.errno != errno.ENOENT: | 282 if inst.errno != errno.ENOENT: |
251 repo.ui.warn(_("update failed to remove %s: %s!\n") % | 283 repo.ui.warn(_("update failed to remove %s: %s!\n") % |
252 (f, inst.strerror)) | 284 (f, inst.strerror)) |
253 removed +=1 | 285 removed +=1 |
286 elif m == "c": # copy | |
287 f2, fd, my, other, flag, remove = a[2:] | |
288 if filemerge(repo, f, f2, fd, my, other, xp1, xp2, remove): | |
289 unresolved += 1 | |
290 util.set_exec(repo.wjoin(fd), flag) | |
291 merged += 1 | |
254 elif m == "m": # merge | 292 elif m == "m": # merge |
255 flag, my, other = a[2:] | 293 flag, my, other = a[2:] |
256 repo.ui.status(_("merging %s\n") % f) | 294 repo.ui.status(_("merging %s\n") % f) |
257 if filemerge(repo, f, f, f, my, other, xp1, xp2, False): | 295 if filemerge(repo, f, f, f, my, other, xp1, xp2, False): |
258 unresolved += 1 | 296 unresolved += 1 |
356 if not branchmerge: | 394 if not branchmerge: |
357 action += forgetremoved(m2, wc) | 395 action += forgetremoved(m2, wc) |
358 if not (backwards or overwrite): | 396 if not (backwards or overwrite): |
359 copy = findcopies(repo, m1, m2, pa.rev()) | 397 copy = findcopies(repo, m1, m2, pa.rev()) |
360 | 398 |
361 action += manifestmerge(repo.ui, m1, m2, ma, overwrite, backwards, partial) | 399 action += manifestmerge(repo.ui, m1, m2, ma, copy, |
400 overwrite, backwards, partial) | |
362 | 401 |
363 ### apply phase | 402 ### apply phase |
364 | 403 |
365 if not branchmerge: | 404 if not branchmerge: |
366 # we don't need to do any magic, just jump to the new rev | 405 # we don't need to do any magic, just jump to the new rev |