--- a/mercurial/patch.py Mon Dec 25 18:57:55 2006 +0100
+++ b/mercurial/patch.py Mon Dec 25 17:43:49 2006 +0100
@@ -7,7 +7,7 @@
from i18n import _
from node import *
-import base85, cmdutil, mdiff, util
+import base85, cmdutil, mdiff, util, context, revlog
import cStringIO, email.Parser, os, popen2, re, sha
import sys, tempfile, zlib
@@ -436,27 +436,25 @@
if not node1:
node1 = repo.dirstate.parents()[0]
- clcache = {}
- def getchangelog(n):
- if n not in clcache:
- clcache[n] = repo.changelog.read(n)
- return clcache[n]
- mcache = {}
- def getmanifest(n):
- if n not in mcache:
- mcache[n] = repo.manifest.read(n)
- return mcache[n]
- fcache = {}
- def getfile(f):
- if f not in fcache:
- fcache[f] = repo.file(f)
- return fcache[f]
+ ccache = {}
+ def getctx(r):
+ if r not in ccache:
+ ccache[r] = context.changectx(repo, r)
+ return ccache[r]
+
+ flcache = {}
+ def getfilectx(f, ctx):
+ flctx = ctx.filectx(f, filelog=flcache.get(f))
+ if f not in flcache:
+ flcache[f] = flctx._filelog
+ return flctx
# reading the data for node1 early allows it to play nicely
# with repo.status and the revlog cache.
- change = getchangelog(node1)
- mmap = getmanifest(change[0])
- date1 = util.datestr(change[2])
+ ctx1 = context.changectx(repo, node1)
+ # force manifest reading
+ man1 = ctx1.manifest()
+ date1 = util.datestr(ctx1.date())
if not changes:
changes = repo.status(node1, node2, files, match=match)[:5]
@@ -476,67 +474,38 @@
if not modified and not added and not removed:
return
- # returns False if there was no rename between n1 and n2
- # returns None if the file was created between n1 and n2
- # returns the (file, node) present in n1 that was renamed to f in n2
- def renamedbetween(f, n1, n2):
- r1, r2 = map(repo.changelog.rev, (n1, n2))
+ if node2:
+ ctx2 = context.changectx(repo, node2)
+ else:
+ ctx2 = context.workingctx(repo)
+ man2 = ctx2.manifest()
+
+ # returns False if there was no rename between ctx1 and ctx2
+ # returns None if the file was created between ctx1 and ctx2
+ # returns the (file, node) present in ctx1 that was renamed to f in ctx2
+ def renamed(f):
+ startrev = ctx1.rev()
+ c = ctx2
+ crev = c.rev()
+ if crev is None:
+ crev = repo.changelog.count()
orig = f
- src = None
- while r2 > r1:
- cl = getchangelog(n2)
- if f in cl[3]:
- m = getmanifest(cl[0])
+ while crev > startrev:
+ if f in c.files():
try:
- src = getfile(f).renamed(m[f])
- except KeyError:
+ src = getfilectx(f, c).renamed()
+ except revlog.LookupError:
return None
if src:
f = src[0]
- n2 = repo.changelog.parents(n2)[0]
- r2 = repo.changelog.rev(n2)
- cl = getchangelog(n1)
- m = getmanifest(cl[0])
- if f not in m:
+ crev = c.parents()[0].rev()
+ # try to reuse
+ c = getctx(crev)
+ if f not in man1:
return None
if f == orig:
return False
- return f, m[f]
-
- if node2:
- change = getchangelog(node2)
- mmap2 = getmanifest(change[0])
- _date2 = util.datestr(change[2])
- def date2(f):
- return _date2
- def read(f):
- return getfile(f).read(mmap2[f])
- def renamed(f):
- return renamedbetween(f, node1, node2)
- else:
- tz = util.makedate()[1]
- _date2 = util.datestr()
- def date2(f):
- try:
- return util.datestr((os.lstat(repo.wjoin(f)).st_mtime, tz))
- except OSError, err:
- if err.errno != errno.ENOENT: raise
- return _date2
- def read(f):
- return repo.wread(f)
- def renamed(f):
- src = repo.dirstate.copied(f)
- parent = repo.dirstate.parents()[0]
- if src:
- f = src
- of = renamedbetween(f, node1, parent)
- if of or of is None:
- return of
- elif src:
- cl = getchangelog(parent)[0]
- return (src, getmanifest(cl)[src])
- else:
- return None
+ return f
if repo.ui.quiet:
r = None
@@ -550,7 +519,7 @@
src = renamed(f)
if src:
copied[f] = src
- srcs = [x[1][0] for x in copied.items()]
+ srcs = [x[1] for x in copied.items()]
all = modified + added + removed
all.sort()
@@ -560,10 +529,10 @@
tn = None
dodiff = True
header = []
- if f in mmap:
- to = getfile(f).read(mmap[f])
+ if f in man1:
+ to = getfilectx(f, ctx1).data()
if f not in removed:
- tn = read(f)
+ tn = getfilectx(f, ctx2).data()
if opts.git:
def gitmode(x):
return x and '100755' or '100644'
@@ -574,13 +543,10 @@
a, b = f, f
if f in added:
- if node2:
- mode = gitmode(mmap2.execf(f))
- else:
- mode = gitmode(util.is_exec(repo.wjoin(f), None))
+ mode = gitmode(man2.execf(f))
if f in copied:
- a, arev = copied[f]
- omode = gitmode(mmap.execf(a))
+ a = copied[f]
+ omode = gitmode(man1.execf(a))
addmodehdr(header, omode, mode)
if a in removed and a not in gone:
op = 'rename'
@@ -589,7 +555,7 @@
op = 'copy'
header.append('%s from %s\n' % (op, a))
header.append('%s to %s\n' % (op, f))
- to = getfile(a).read(arev)
+ to = getfilectx(a, ctx1).data()
else:
header.append('new file mode %s\n' % mode)
if util.binary(tn):
@@ -598,14 +564,11 @@
if f in srcs:
dodiff = False
else:
- mode = gitmode(mmap.execf(f))
+ mode = gitmode(man1.execf(f))
header.append('deleted file mode %s\n' % mode)
else:
- omode = gitmode(mmap.execf(f))
- if node2:
- nmode = gitmode(mmap2.execf(f))
- else:
- nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f)))
+ omode = gitmode(man1.execf(f))
+ nmode = gitmode(man2.execf(f))
addmodehdr(header, omode, nmode)
if util.binary(to) or util.binary(tn):
dodiff = 'binary'
@@ -615,7 +578,10 @@
fp.write(''.join(header))
b85diff(fp, to, tn)
elif dodiff:
- text = mdiff.unidiff(to, date1, tn, date2(f), f, r, opts=opts)
+ text = mdiff.unidiff(to, date1,
+ # ctx2 date may be dynamic
+ tn, util.datestr(ctx2.date()),
+ f, r, opts=opts)
if text or len(header) > 1:
fp.write(''.join(header))
fp.write(text)