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

Colin Caughie c.caughie at indigovision.com
Sat May 23 03:13:33 CDT 2009


# HG changeset patch
# User Colin Caughie <c.caughie at indigovision.com>
# Date 1243065454 -3600
# Node ID ad793d85a6ceae217b754ff11bb078b77b102dbf
# Parent  9f85da26050895c67a162d0d2097255402618017
Modify patch.applydiff() to work with filters such as win32text.

This change makes it possible for patch.applydiff() to use working dir
filters such as win32text when applying patches. A repo object is passed
to patch.applydiff() (via patch.patch()) in order for this to work.

I've also modified the import command and the mq, record and transplant
extensions to pass the repo when applying patches. This gets these commands
working even with win32text enabled.

diff -r 9f85da260508 -r ad793d85a6ce hgext/keyword.py
--- a/hgext/keyword.py  Sat May 23 00:24:00 2009 +0200
+++ b/hgext/keyword.py  Sat May 23 08:57:34 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 9f85da260508 -r ad793d85a6ce hgext/mq.py
--- a/hgext/mq.py       Sat May 23 00:24:00 2009 +0200
+++ b/hgext/mq.py       Sat May 23 08:57:34 2009 +0100
@@ -510,7 +510,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 9f85da260508 -r ad793d85a6ce hgext/record.py
--- a/hgext/record.py   Sat May 23 00:24:00 2009 +0200
+++ b/hgext/record.py   Sat May 23 08:57:34 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 9f85da260508 -r ad793d85a6ce hgext/transplant.py
--- a/hgext/transplant.py       Sat May 23 00:24:00 2009 +0200
+++ b/hgext/transplant.py       Sat May 23 08:57:34 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 9f85da260508 -r ad793d85a6ce mercurial/commands.py
--- a/mercurial/commands.py     Sat May 23 00:24:00 2009 +0200
+++ b/mercurial/commands.py     Sat May 23 08:57:34 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 9f85da260508 -r ad793d85a6ce mercurial/patch.py
--- a/mercurial/patch.py        Sat May 23 00:24:00 2009 +0200
+++ b/mercurial/patch.py        Sat May 23 08:57:34 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,30 @@
         self.hunks = 0

     def readlines(self, fname):
-        fp = self.opener(fname, 'r')
-        try:
-            return fp.readlines()
-        finally:
-            fp.close()
+        if self.repo:
+            wctx = self.repo[None]
+            sio = cStringIO.StringIO(wctx.filectx(fname).data())
+            lines = sio.readlines()
+            sio.close()
+            return lines
+        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:
+            wctx = self.repo[None]
+            flags = wctx.manifest().flags(fname)
+            self.repo.wwrite(fname, ''.join(lines), flags)
+        else:
+            fp = self.opener(fname, 'w')
+            try:
+                fp.writelines(lines)
+            finally:
+                fp.close()

     def unlink(self, fname):
         os.unlink(fname)
@@ -955,7 +968,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 +1001,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 +1118,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 +1129,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 +1137,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 +1148,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 9f85da260508 -r ad793d85a6ce tests/test-win32text-import
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-win32text-import       Sat May 23 08:57:34 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 9f85da260508 -r ad793d85a6ce tests/test-win32text-import.out
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-win32text-import.out   Sat May 23 08:57:34 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