Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/patch.py @ 6275:fda369b5779c
diff: use copy smarts from copies.py
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sat, 15 Mar 2008 10:02:31 -0500 |
parents | f89fd07fc51d |
children | 9db24a36d182 |
comparison
equal
deleted
inserted
replaced
6274:f3f383efbeae | 6275:fda369b5779c |
---|---|
6 # This software may be used and distributed according to the terms | 6 # This software may be used and distributed according to the terms |
7 # of the GNU General Public License, incorporated herein by reference. | 7 # of the GNU General Public License, incorporated herein by reference. |
8 | 8 |
9 from i18n import _ | 9 from i18n import _ |
10 from node import hex, nullid, short | 10 from node import hex, nullid, short |
11 import base85, cmdutil, mdiff, util, context, revlog, diffhelpers | 11 import base85, cmdutil, mdiff, util, context, revlog, diffhelpers, copies |
12 import cStringIO, email.Parser, os, popen2, re, sha, errno | 12 import cStringIO, email.Parser, os, popen2, re, sha, errno |
13 import sys, tempfile, zlib | 13 import sys, tempfile, zlib |
14 | 14 |
15 class PatchError(Exception): | 15 class PatchError(Exception): |
16 pass | 16 pass |
1200 if execf2 is None: | 1200 if execf2 is None: |
1201 mc = ctx2.parents()[0].manifest().copy() | 1201 mc = ctx2.parents()[0].manifest().copy() |
1202 execf2 = mc.execf | 1202 execf2 = mc.execf |
1203 linkf2 = mc.linkf | 1203 linkf2 = mc.linkf |
1204 | 1204 |
1205 # returns False if there was no rename between ctx1 and ctx2 | |
1206 # returns None if the file was created between ctx1 and ctx2 | |
1207 # returns the (file, node) present in ctx1 that was renamed to f in ctx2 | |
1208 # This will only really work if c1 is the Nth 1st parent of c2. | |
1209 def renamed(c1, c2, man, f): | |
1210 startrev = c1.rev() | |
1211 c = c2 | |
1212 crev = c.rev() | |
1213 if crev is None: | |
1214 crev = repo.changelog.count() | |
1215 orig = f | |
1216 files = (f,) | |
1217 while crev > startrev: | |
1218 if f in files: | |
1219 try: | |
1220 src = getfilectx(f, c).renamed() | |
1221 except revlog.LookupError: | |
1222 return None | |
1223 if src: | |
1224 f = src[0] | |
1225 crev = c.parents()[0].rev() | |
1226 # try to reuse | |
1227 c = getctx(crev) | |
1228 files = c.files() | |
1229 if f not in man: | |
1230 return None | |
1231 if f == orig: | |
1232 return False | |
1233 return f | |
1234 | |
1235 if repo.ui.quiet: | 1205 if repo.ui.quiet: |
1236 r = None | 1206 r = None |
1237 else: | 1207 else: |
1238 hexfunc = repo.ui.debugflag and hex or short | 1208 hexfunc = repo.ui.debugflag and hex or short |
1239 r = [hexfunc(node) for node in [node1, node2] if node] | 1209 r = [hexfunc(node) for node in [node1, node2] if node] |
1240 | 1210 |
1241 if opts.git: | 1211 if opts.git: |
1242 copied = {} | 1212 copy, diverge = copies.copies(repo, ctx1, ctx2, repo.changectx(nullid)) |
1243 c1, c2 = ctx1, ctx2 | 1213 for k, v in copy.items(): |
1244 files = added | 1214 copy[v] = k |
1245 man = man1 | |
1246 if node2 and ctx1.rev() >= ctx2.rev(): | |
1247 # renamed() starts at c2 and walks back in history until c1. | |
1248 # Since ctx1.rev() >= ctx2.rev(), invert ctx2 and ctx1 to | |
1249 # detect (inverted) copies. | |
1250 c1, c2 = ctx2, ctx1 | |
1251 files = removed | |
1252 man = ctx2.manifest() | |
1253 for f in files: | |
1254 src = renamed(c1, c2, man, f) | |
1255 if src: | |
1256 copied[f] = src | |
1257 if ctx1 == c2: | |
1258 # invert the copied dict | |
1259 copied = dict([(v, k) for (k, v) in copied.iteritems()]) | |
1260 # If we've renamed file foo to bar (copied['bar'] = 'foo'), | |
1261 # avoid showing a diff for foo if we're going to show | |
1262 # the rename to bar. | |
1263 srcs = [x[1] for x in copied.iteritems() if x[0] in added] | |
1264 | 1215 |
1265 all = modified + added + removed | 1216 all = modified + added + removed |
1266 all.sort() | 1217 all.sort() |
1267 gone = {} | 1218 gone = {} |
1268 | 1219 |
1284 header.append('old mode %s\n' % omode) | 1235 header.append('old mode %s\n' % omode) |
1285 header.append('new mode %s\n' % nmode) | 1236 header.append('new mode %s\n' % nmode) |
1286 | 1237 |
1287 if f in added: | 1238 if f in added: |
1288 mode = gitmode(execf2(f), linkf2(f)) | 1239 mode = gitmode(execf2(f), linkf2(f)) |
1289 if f in copied: | 1240 if f in copy: |
1290 a = copied[f] | 1241 a = copy[f] |
1291 omode = gitmode(man1.execf(a), man1.linkf(a)) | 1242 omode = gitmode(man1.execf(a), man1.linkf(a)) |
1292 addmodehdr(header, omode, mode) | 1243 addmodehdr(header, omode, mode) |
1293 if a in removed and a not in gone: | 1244 if a in removed and a not in gone: |
1294 op = 'rename' | 1245 op = 'rename' |
1295 gone[a] = 1 | 1246 gone[a] = 1 |
1301 else: | 1252 else: |
1302 header.append('new file mode %s\n' % mode) | 1253 header.append('new file mode %s\n' % mode) |
1303 if util.binary(tn): | 1254 if util.binary(tn): |
1304 dodiff = 'binary' | 1255 dodiff = 'binary' |
1305 elif f in removed: | 1256 elif f in removed: |
1306 if f in srcs: | 1257 # have we already reported a copy above? |
1258 if f in copy and copy[f] in added and copy[copy[f]] == f: | |
1307 dodiff = False | 1259 dodiff = False |
1308 else: | 1260 else: |
1309 mode = gitmode(man1.execf(f), man1.linkf(f)) | 1261 mode = gitmode(man1.execf(f), man1.linkf(f)) |
1310 header.append('deleted file mode %s\n' % mode) | 1262 header.append('deleted file mode %s\n' % mode) |
1311 else: | 1263 else: |