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: