[PATCH] Modified patch.applydiff() to work with repo filters such as win32text

Colin Caughie c.caughie at indigovision.com
Wed May 20 15:25:19 CDT 2009


# HG changeset patch
# User Colin Caughie <c.caughie at indigovision.com>
# Date 1242849926 -3600
# Node ID 232095d5aba2c5ae2da83c0d5f4582df217c9d55
# Parent  90f86a5330bbbcd075c792cd14fb6bb47b8ccd2c
Modified patch.applydiff() to work with repo filters such as win32text.

This change allows a repository to be passed to mercurial.patch.patch(); if
it is, this repo is used to read and write files during the patching process,
applying any active filters.
It also modifies the import command and the mq, record and transplant
extensions to pass the repo when applying patches. This gets these commands
working with win32text enabled, which they didn't before.
In order to implement this, the wreadlines and wwritelines methods were added
to localrepo.py. These are like wread and wwrite only they use a list of lines
for the file data instead of a single string.

diff -r 90f86a5330bb -r 232095d5aba2 hgext/keyword.py
--- a/hgext/keyword.py  Mon May 18 17:36:24 2009 -0500
+++ b/hgext/keyword.py  Wed May 20 21:05:26 2009 +0100
@@ -485,10 +485,11 @@
                 release(lock, wlock)

     # monkeypatches
-    def kwpatchfile_init(orig, self, ui, fname, opener, missing=False):
+    def kwpatchfile_init(orig, self, ui, fname, opener, missing=False,
+                         repo=None):
         '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
         rejects or conflicts due to expanded keywords in working dir.'''
-        orig(self, ui, fname, opener, missing)
+        orig(self, ui, fname, opener, missing, repo)
         # shrink keywords read from working dir
         self.lines = kwt.shrinklines(self.fname, self.lines)

diff -r 90f86a5330bb -r 232095d5aba2 hgext/mq.py
--- a/hgext/mq.py       Mon May 18 17:36:24 2009 -0500
+++ b/hgext/mq.py       Wed May 20 21:05:26 2009 +0100
@@ -488,7 +488,7 @@
         files = {}
         try:
             fuzz = patch.patch(patchfile, self.ui, strip=1, cwd=repo.root,
-                               files=files)
+                               files=files, repo=repo)
         except Exception, inst:
             self.ui.note(str(inst) + '\n')
             if not self.ui.verbose:
diff -r 90f86a5330bb -r 232095d5aba2 hgext/record.py
--- a/hgext/record.py   Mon May 18 17:36:24 2009 -0500
+++ b/hgext/record.py   Wed May 20 21:05:26 2009 +0100
@@ -481,7 +481,8 @@
                     ui.debug(_('applying patch\n'))
                     ui.debug(fp.getvalue())
                     pfiles = {}
-                    patch.internalpatch(fp, ui, 1, repo.root, files=pfiles)
+                    patch.internalpatch(fp, ui, 1, repo.root, files=pfiles,
+                                        repo=repo)
                     patch.updatedir(ui, repo, pfiles)
                 except patch.PatchError, err:
                     s = str(err)
diff -r 90f86a5330bb -r 232095d5aba2 hgext/transplant.py
--- a/hgext/transplant.py       Mon May 18 17:36:24 2009 -0500
+++ b/hgext/transplant.py       Wed May 20 21:05:26 2009 +0100
@@ -218,7 +218,7 @@
                 files = {}
                 try:
                     patch.patch(patchfile, self.ui, cwd=repo.root,
-                                files=files)
+                                files=files, repo=repo)
                     if not files:
                         self.ui.warn(_('%s: empty changeset')
                                      % revlog.hex(node))
diff -r 90f86a5330bb -r 232095d5aba2 mercurial/commands.py
--- a/mercurial/commands.py     Mon May 18 17:36:24 2009 -0500
+++ b/mercurial/commands.py     Wed May 20 21:05:26 2009 +0100
@@ -1746,7 +1746,7 @@
                 files = {}
                 try:
                     patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
-                                files=files)
+                                files=files, repo=repo)
                 finally:
                     files = patch.updatedir(ui, repo, files, similarity=sim/100.)
                 if not opts.get('no_commit'):
diff -r 90f86a5330bb -r 232095d5aba2 mercurial/localrepo.py
--- a/mercurial/localrepo.py    Mon May 18 17:36:24 2009 -0500
+++ b/mercurial/localrepo.py    Wed May 20 21:05:26 2009 +0100
@@ -14,7 +14,7 @@
 import match as match_
 import merge as merge_
 from lock import release
-import weakref, stat, errno, os, time, inspect
+import weakref, stat, errno, os, time, inspect, cStringIO
 propertycache = util.propertycache

 class localrepository(repo.repository):
@@ -579,6 +579,18 @@
     def wwritedata(self, filename, data):
         return self._filter("decode", filename, data)

+    def wreadlines(self, filename):
+        data = self.wopener(filename, 'r').read()
+        data = self._filter("encode", filename, data)
+        sio = cStringIO.StringIO(data)
+        lines = sio.readlines()
+        sio.close()
+        return lines
+
+    def wwritelines(self, filename, lines):
+        data = self._filter("decode", filename, ''.join(lines))
+        self.wopener(filename, 'w').write(data)
+
     def transaction(self):
         tr = self._transref and self._transref() or None
         if tr and tr.running():
diff -r 90f86a5330bb -r 232095d5aba2 mercurial/patch.py
--- a/mercurial/patch.py        Mon May 18 17:36:24 2009 -0500
+++ b/mercurial/patch.py        Wed May 20 21:05:26 2009 +0100
@@ -233,10 +233,11 @@
 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')

 class patchfile:
-    def __init__(self, ui, fname, opener, missing=False):
+    def __init__(self, ui, fname, opener, missing=False, repo=None):
         self.fname = fname
         self.opener = opener
         self.ui = ui
+        self.repo = repo
         self.lines = []
         self.exists = False
         self.missing = missing
@@ -258,18 +259,24 @@
         self.hunks = 0

     def readlines(self, fname):
-        fp = self.opener(fname, 'r')
-        try:
-            return fp.readlines()
-        finally:
-            fp.close()
+        if self.repo:
+            return self.repo.wreadlines(fname)
+        else:
+            fp = self.opener(fname, 'r')
+            try:
+                return fp.readlines()
+            finally:
+                fp.close()

     def writelines(self, fname, lines):
-        fp = self.opener(fname, 'w')
-        try:
-            fp.writelines(lines)
-        finally:
-            fp.close()
+        if self.repo:
+            self.repo.wwritelines(fname, lines)
+        else:
+            fp = self.opener(fname, 'w')
+            try:
+                fp.writelines(lines)
+            finally:
+                fp.close()

     def unlink(self, fname):
         os.unlink(fname)
@@ -955,7 +962,7 @@
     if hunknum == 0 and dopatch and not gitworkdone:
         raise NoHunks

-def applydiff(ui, fp, changed, strip=1, sourcefile=None, reverse=False):
+def applydiff(ui, fp, changed, strip=1, sourcefile=None, reverse=False, repo=None):
     """reads a patch from fp and tries to apply it.  The dict 'changed' is
        filled in with all of the filenames changed by the patch.  Returns 0
        for a clean patch, -1 if any rejects were found and 1 if there was
@@ -988,11 +995,11 @@
             afile, bfile, first_hunk = values
             try:
                 if sourcefile:
-                    current_file = patchfile(ui, sourcefile, opener)
+                    current_file = patchfile(ui, sourcefile, opener, repo=repo)
                 else:
                     current_file, missing = selectfile(afile, bfile, first_hunk,
                                             strip, reverse)
-                    current_file = patchfile(ui, current_file, opener, missing)
+                    current_file = patchfile(ui, current_file, opener, missing, repo=repo)
             except PatchError, err:
                 ui.warn(str(err) + '\n')
                 current_file, current_hunk = None, None
@@ -1105,7 +1112,7 @@
                          util.explain_exit(code)[0])
     return fuzz

-def internalpatch(patchobj, ui, strip, cwd, files={}):
+def internalpatch(patchobj, ui, strip, cwd, files={}, repo=None):
     """use builtin patch to apply <patchobj> to the working directory.
     returns whether patch was applied with fuzz factor."""
     try:
@@ -1116,7 +1123,7 @@
         curdir = os.getcwd()
         os.chdir(cwd)
     try:
-        ret = applydiff(ui, fp, files, strip=strip)
+        ret = applydiff(ui, fp, files, strip=strip, repo=repo)
     finally:
         if cwd:
             os.chdir(curdir)
@@ -1124,7 +1131,7 @@
         raise PatchError
     return ret > 0

-def patch(patchname, ui, strip=1, cwd=None, files={}):
+def patch(patchname, ui, strip=1, cwd=None, files={}, repo=None):
     """apply <patchname> to the working directory.
     returns whether patch was applied with fuzz factor."""
     patcher = ui.config('ui', 'patch')
@@ -1135,7 +1142,7 @@
                                  files)
         else:
             try:
-                return internalpatch(patchname, ui, strip, cwd, files)
+                return internalpatch(patchname, ui, strip, cwd, files, repo)
             except NoHunks:
                 patcher = util.find_exe('gpatch') or util.find_exe('patch') or 'patch'
                 ui.debug(_('no valid hunks found; trying with %r instead\n') %
diff -r 90f86a5330bb -r 232095d5aba2 tests/test-win32text-import
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-win32text-import       Wed May 20 21:05:26 2009 +0100
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+hg init a
+mkdir a/d1
+mkdir a/d1/d2
+echo line 1 > a/a
+echo line 1 > a/d1/d2/a
+hg --cwd a ci -Ama
+
+echo line 2 >> a/a
+hg --cwd a ci -u someone -d '1 0' -m'second change'
+
+echo % import exported patch
+hg clone -r0 -U a b
+
+echo '[extensions]' >> b/.hg/hgrc
+echo 'win32text = ' >> b/.hg/hgrc
+echo '[decode]' >> b/.hg/hgrc
+echo '** = cleverdecode:' >> b/.hg/hgrc
+echo '[encode]' >> b/.hg/hgrc
+echo '** = cleverencode:' >> b/.hg/hgrc
+
+hg --cwd b update
+hg --cwd a export tip > tip.patch
+hg --cwd b import ../tip.patch
+echo % check diff is correct
+hg --cwd b tip -p
+
+rm -r a
+rm -r b
diff -r 90f86a5330bb -r 232095d5aba2 tests/test-win32text-import.out
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-win32text-import.out   Wed May 20 21:05:26 2009 +0100
@@ -0,0 +1,24 @@
+adding a
+adding d1/d2/a
+% import exported patch
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 2 changes to 2 files
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+applying ../tip.patch
+% check diff is correct
+changeset:   1:1d4bd90af0e4
+tag:         tip
+user:        someone
+date:        Thu Jan 01 00:00:01 1970 +0000
+summary:     second change
+
+diff -r 80971e65b431 -r 1d4bd90af0e4 a
+--- a/a        Thu Jan 01 00:00:00 1970 +0000
++++ b/a        Thu Jan 01 00:00:01 1970 +0000
+@@ -1,1 +1,2 @@
+ line 1
++line 2
+




Latest News at: http://www.indigovision.com/news2009.php



More information about the Mercurial-devel mailing list