Mercurial > hg
changeset 14389:909ac6b9636b
patch: stop modifying gitpatch objects
gitpatch objects emitted by iterhunks() were referencing file paths unmodified
from the input patch. _applydif() made them usable by modifying the gitpatch
objects in-place with specified path strip level. The same modified objects
were then reused by iterhunks() generator. _applydiff() now copies and update
the paths which completely decouples both routines.
As a side effect, the "git" event now receives only metadata about
copies/renames to perform the necessary copies ahead of time. Other actions are
handled in the "file" event.
author | Patrick Mezard <pmezard@gmail.com> |
---|---|
date | Thu, 19 May 2011 22:44:01 +0200 |
parents | 37c997d21752 |
children | ce77c275bec3 |
files | mercurial/patch.py |
diffstat | 1 files changed, 17 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/patch.py Thu May 19 22:44:01 2011 +0200 +++ b/mercurial/patch.py Thu May 19 22:44:01 2011 +0200 @@ -1157,7 +1157,8 @@ # scan whole input for git metadata gitpatches = [('b/' + gp.path, gp) for gp in scangitpatch(lr, x)] - yield 'git', [g[1] for g in gitpatches] + yield 'git', [g[1] for g in gitpatches + if g[1].op in ('COPY', 'RENAME')] gitpatches.reverse() afile = 'a/' + m.group(1) bfile = 'b/' + m.group(2) @@ -1220,6 +1221,10 @@ eolmode=eolmode) def _applydiff(ui, fp, patcher, backend, changed, strip=1, eolmode='strict'): + + def pstrip(p): + return pathstrip(p, strip - 1)[1] + rejects = 0 err = 0 current_file = None @@ -1239,18 +1244,19 @@ current_file = None afile, bfile, first_hunk, gp = values if gp: - changed[gp.path] = gp + path = pstrip(gp.path) + changed[path] = gp if gp.op == 'DELETE': - backend.unlink(gp.path) + backend.unlink(path) continue if gp.op == 'RENAME': - backend.unlink(gp.oldpath) + backend.unlink(pstrip(gp.oldpath)) if gp.mode and not first_hunk: if gp.op == 'ADD': # Added files without content have no hunk and must be created - backend.writelines(gp.path, [], gp.mode) + backend.writelines(path, [], gp.mode) else: - backend.setmode(gp.path, gp.mode[0], gp.mode[1]) + backend.setmode(path, gp.mode[0], gp.mode[1]) if not first_hunk: continue try: @@ -1266,11 +1272,7 @@ continue elif state == 'git': for gp in values: - gp.path = pathstrip(gp.path, strip - 1)[1] - if gp.oldpath: - gp.oldpath = pathstrip(gp.oldpath, strip - 1)[1] - if gp.op in ('COPY', 'RENAME'): - backend.copy(gp.oldpath, gp.path) + backend.copy(pstrip(gp.oldpath), pstrip(gp.path)) else: raise util.Abort(_('unsupported parser state: %s') % state) @@ -1387,25 +1389,18 @@ try: changed = set() for state, values in iterhunks(fp): - if state == 'hunk': - continue - elif state == 'file': + if state == 'file': afile, bfile, first_hunk, gp = values if gp: - changed.add(gp.path) + changed.add(pathstrip(gp.path, strip - 1)[1]) if gp.op == 'RENAME': - changed.add(gp.oldpath) + changed.add(pathstrip(gp.oldpath, strip - 1)[1]) if not first_hunk: continue current_file, missing = selectfile(backend, afile, bfile, first_hunk, strip) changed.add(current_file) - elif state == 'git': - for gp in values: - gp.path = pathstrip(gp.path, strip - 1)[1] - if gp.oldpath: - gp.oldpath = pathstrip(gp.oldpath, strip - 1)[1] - else: + elif state not in ('hunk', 'git'): raise util.Abort(_('unsupported parser state: %s') % state) return changed finally: