--- a/hgext/keyword.py Sat Jun 11 14:14:13 2011 +0200
+++ b/hgext/keyword.py Sat Jun 11 14:17:25 2011 +0200
@@ -595,12 +595,10 @@
wlock.release()
# monkeypatches
- def kwpatchfile_init(orig, self, ui, fname, backend, store, mode, create,
- remove, eolmode=None, copysource=None):
+ def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None):
'''Monkeypatch/wrap patch.patchfile.__init__ to avoid
rejects or conflicts due to expanded keywords in working dir.'''
- orig(self, ui, fname, backend, store, mode, create, remove,
- eolmode, copysource)
+ orig(self, ui, gp, backend, store, eolmode)
# shrink keywords read from working dir
self.lines = kwt.shrinklines(self.fname, self.lines)
--- a/mercurial/patch.py Sat Jun 11 14:14:13 2011 +0200
+++ b/mercurial/patch.py Sat Jun 11 14:17:25 2011 +0200
@@ -281,6 +281,14 @@
isexec = mode & 0100
self.mode = (islink, isexec)
+ def copy(self):
+ other = patchmeta(self.path)
+ other.oldpath = self.oldpath
+ other.mode = self.mode
+ other.op = self.op
+ other.binary = self.binary
+ return other
+
def __repr__(self):
return "<patchmeta %s %r>" % (self.op, self.path)
@@ -509,9 +517,8 @@
eolmodes = ['strict', 'crlf', 'lf', 'auto']
class patchfile(object):
- def __init__(self, ui, fname, backend, store, mode, create, remove,
- eolmode='strict', copysource=None):
- self.fname = fname
+ def __init__(self, ui, gp, backend, store, eolmode='strict'):
+ self.fname = gp.path
self.eolmode = eolmode
self.eol = None
self.backend = backend
@@ -519,17 +526,17 @@
self.lines = []
self.exists = False
self.missing = True
- self.mode = mode
- self.copysource = copysource
- self.create = create
- self.remove = remove
+ self.mode = gp.mode
+ self.copysource = gp.oldpath
+ self.create = gp.op in ('ADD', 'COPY', 'RENAME')
+ self.remove = gp.op == 'DELETE'
try:
- if copysource is None:
- data, mode = backend.getfile(fname)
+ if self.copysource is None:
+ data, mode = backend.getfile(self.fname)
self.exists = True
else:
- data, mode = store.getfile(copysource)
- self.exists = backend.exists(fname)
+ data, mode = store.getfile(self.copysource)
+ self.exists = backend.exists(self.fname)
self.missing = False
if data:
self.lines = data.splitlines(True)
@@ -549,7 +556,7 @@
nlines.append(l)
self.lines = nlines
except IOError:
- if create:
+ if self.create:
self.missing = False
if self.mode is None:
self.mode = (False, False)
@@ -1016,14 +1023,7 @@
count -= 1
return path[:i].lstrip(), path[i:].rstrip()
-def selectfile(backend, afile_orig, bfile_orig, hunk, strip, gp):
- if gp:
- # Git patches do not play games. Excluding copies from the
- # following heuristic avoids a lot of confusion
- fname = pathstrip(gp.path, strip - 1)[1]
- create = gp.op in ('ADD', 'COPY', 'RENAME')
- remove = gp.op == 'DELETE'
- return fname, create, remove
+def makepatchmeta(backend, afile_orig, bfile_orig, hunk, strip):
nulla = afile_orig == "/dev/null"
nullb = bfile_orig == "/dev/null"
create = nulla and hunk.starta == 0 and hunk.lena == 0
@@ -1065,7 +1065,12 @@
else:
raise PatchError(_("undefined source and destination files"))
- return fname, create, remove
+ gp = patchmeta(fname)
+ if create:
+ gp.op = 'ADD'
+ elif remove:
+ gp.op = 'DELETE'
+ return gp
def scangitpatch(lr, firstline):
"""
@@ -1134,7 +1139,7 @@
hunknum += 1
if emitfile:
emitfile = False
- yield 'file', (afile, bfile, h, gp)
+ yield 'file', (afile, bfile, h, gp and gp.copy() or None)
yield 'hunk', h
elif x.startswith('diff --git'):
m = gitre.match(x)
@@ -1144,14 +1149,14 @@
# scan whole input for git metadata
gitpatches = [('a/' + gp.path, 'b/' + gp.path, gp) for gp
in scangitpatch(lr, x)]
- yield 'git', [g[2] for g in gitpatches
+ yield 'git', [g[2].copy() for g in gitpatches
if g[2].op in ('COPY', 'RENAME')]
gitpatches.reverse()
afile = 'a/' + m.group(1)
bfile = 'b/' + m.group(2)
while afile != gitpatches[-1][0] and bfile != gitpatches[-1][1]:
gp = gitpatches.pop()[2]
- yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp)
+ yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp.copy())
gp = gitpatches[-1][2]
# copy/rename + modify should modify target, not source
if gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD') or gp.mode:
@@ -1191,7 +1196,7 @@
while gitpatches:
gp = gitpatches.pop()[2]
- yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp)
+ yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp.copy())
def applydiff(ui, fp, backend, store, strip=1, eolmode='strict'):
"""Reads a patch from fp and tries to apply it.
@@ -1228,41 +1233,38 @@
rejects += current_file.close()
current_file = None
afile, bfile, first_hunk, gp = values
- copysource = None
if gp:
path = pstrip(gp.path)
+ gp.path = pstrip(gp.path)
if gp.oldpath:
- copysource = pstrip(gp.oldpath)
- if gp.op == 'RENAME':
- backend.unlink(copysource)
- if not first_hunk:
- if gp.op == 'DELETE':
- backend.unlink(path)
- continue
- data, mode = None, None
- if gp.op in ('RENAME', 'COPY'):
- data, mode = store.getfile(copysource)
- if gp.mode:
- mode = gp.mode
- if gp.op == 'ADD':
- # Added files without content have no hunk and
- # must be created
- data = ''
- if data or mode:
- if (gp.op in ('ADD', 'RENAME', 'COPY')
- and backend.exists(path)):
- raise PatchError(_("cannot create %s: destination "
- "already exists") % path)
- backend.setfile(path, data, mode, copysource)
+ gp.oldpath = pstrip(gp.oldpath)
+ else:
+ gp = makepatchmeta(backend, afile, bfile, first_hunk, strip)
+ if gp.op == 'RENAME':
+ backend.unlink(gp.oldpath)
if not first_hunk:
+ if gp.op == 'DELETE':
+ backend.unlink(gp.path)
+ continue
+ data, mode = None, None
+ if gp.op in ('RENAME', 'COPY'):
+ data, mode = store.getfile(gp.oldpath)
+ if gp.mode:
+ mode = gp.mode
+ if gp.op == 'ADD':
+ # Added files without content have no hunk and
+ # must be created
+ data = ''
+ if data or mode:
+ if (gp.op in ('ADD', 'RENAME', 'COPY')
+ and backend.exists(gp.path)):
+ raise PatchError(_("cannot create %s: destination "
+ "already exists") % gp.path)
+ backend.setfile(gp.path, data, mode, gp.oldpath)
continue
try:
- mode = gp and gp.mode or None
- current_file, create, remove = selectfile(
- backend, afile, bfile, first_hunk, strip, gp)
- current_file = patcher(ui, current_file, backend, store, mode,
- create, remove, eolmode=eolmode,
- copysource=copysource)
+ current_file = patcher(ui, gp, backend, store,
+ eolmode=eolmode)
except PatchError, inst:
ui.warn(str(inst) + '\n')
current_file = None
@@ -1395,14 +1397,14 @@
if state == 'file':
afile, bfile, first_hunk, gp = values
if gp:
- changed.add(pathstrip(gp.path, strip - 1)[1])
- if gp.op == 'RENAME':
- changed.add(pathstrip(gp.oldpath, strip - 1)[1])
- if not first_hunk:
- continue
- current_file, create, remove = selectfile(
- backend, afile, bfile, first_hunk, strip, gp)
- changed.add(current_file)
+ gp.path = pathstrip(gp.path, strip - 1)[1]
+ if gp.oldpath:
+ gp.oldpath = pathstrip(gp.oldpath, strip - 1)[1]
+ else:
+ gp = makepatchmeta(backend, afile, bfile, first_hunk, strip)
+ changed.add(gp.path)
+ if gp.op == 'RENAME':
+ changed.add(gp.oldpath)
elif state not in ('hunk', 'git'):
raise util.Abort(_('unsupported parser state: %s') % state)
return changed