[PATCH 1 of 1] convert: add option --contentsfilter scriptname
Jason Harris
jason.f.harris at gmail.com
Sun Apr 17 19:36:23 CDT 2011
# HG changeset patch
# User jfh <jason at jasonfharris.com>
# Date 1303084955 -7200
# Node ID 3637c5384a73e35bbbecc611004351a75d8d6b8f
# Parent c860adb9feb161c27722af9d3e913e82ecb75e1e
convert: add option --contentsfilter scriptname
The contentsfilter can potentially transform the contents of every file at every
revision as the conversion happens. If the --contentsfilter scriptname option is
specified, then scriptname should be the full path name of a script which takes
three arguments - (i) original file name, (ii) the original changeset hash, and
(iii) the original contents of the file. The script should transform the passed
in file contents into the desired final output form and write this to stdout.
The result code returned should be 0 if the contents were modified and 1 if the
contents did not need modification.
The contentsfilter option is useful for example to transform all of the new
lines to / from unix for every file at every revision in the repository, or do
some special replacement for every file in the repository. For a more
complicated example one might transform c sources files using uncrustify to
transform to a new coding standard.
diff --git a/hgext/convert/__init__.py b/hgext/convert/__init__.py
--- a/hgext/convert/__init__.py
+++ b/hgext/convert/__init__.py
@@ -102,6 +102,22 @@
it is converted. To rename from a subdirectory into the root of
the repository, use ``.`` as the path to rename to.
+ The contentsfilter can potentially transform the contents of every file at
+ every revision as the conversion happens. If the --contentsfilter scriptname
+ option is specified, then scriptname should be the full path name of a
+ script which takes three arguments - (i) original file name, (ii) the
+ original changeset hash, and (iii) the original contents of the file. The
+ script should transform the passed in file contents into the desired final
+ output form and write this to stdout. The result code returned should be 0
+ if the contents were modified and 1 if the contents did not need
+ modification.
+
+ The contentsfilter option is useful for example to transform all of the new
+ lines to / from unix for every file at every revision in the repository, or
+ do some special replacement for every file in the repository. For a more
+ complicated example one might transform c sources files using uncrustify to
+ transform to a new coding standard.
+
The splicemap is a file that allows insertion of synthetic
history, letting you specify the parents of a revision. This is
useful if you want to e.g. give a Subversion merge two parents, or
@@ -300,6 +316,9 @@
_('import up to target revision REV'), _('REV')),
('A', 'authormap', '',
_('remap usernames using this file'), _('FILE')),
+ ('', 'contentsfilter', '',
+ _('transform the contents of each file according to an external filter'),
+ _('FILE')),
('', 'filemap', '',
_('remap file names using contents of file'), _('FILE')),
('', 'splicemap', '',
diff --git a/hgext/convert/convcmd.py b/hgext/convert/convcmd.py
--- a/hgext/convert/convcmd.py
+++ b/hgext/convert/convcmd.py
@@ -120,6 +120,7 @@
self.splicemap = mapfile(ui, opts.get('splicemap'))
self.branchmap = mapfile(ui, opts.get('branchmap'))
+ self.contentsfilter = opts.get('contentsfilter')
def walktree(self, heads):
'''Return a mapping that identifies the uncommitted parents of every
@@ -326,6 +327,7 @@
except KeyError:
parents = [b[0] for b in pbranches]
source = progresssource(self.ui, self.source, len(files))
+ self.dest.contentsfilter = self.contentsfilter
newnode = self.dest.putcommit(files, copies, parents, commit,
source, self.map)
source.close()
diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py
--- a/hgext/convert/hg.py
+++ b/hgext/convert/hg.py
@@ -18,7 +18,7 @@
# source.
-import os, time, cStringIO
+import os, time, cStringIO, subprocess
from mercurial.i18n import _
from mercurial.node import bin, hex, nullid
from mercurial import hg, util, context, bookmarks, error
@@ -135,6 +135,18 @@
def getfilectx(repo, memctx, f):
v = files[f]
data, mode = source.getfile(f, v)
+ if isinstance(data, str) and hasattr(memctx, '_contentsfilter'):
+ filter = memctx._contentsfilter
+ if filter != '':
+ try:
+ hash = v[1] if len(v) >= 2 else ''
+ p = subprocess.Popen([filter, f, hash, data],
+ stdout=subprocess.PIPE, close_fds=True)
+ child_stdout = p.communicate()[0]
+ if p.returncode == 0:
+ data = child_stdout
+ except:
+ pass
if f == '.hgtags':
data = self._rewritetags(source, revmap, data)
return context.memfilectx(f, data, 'l' in mode, 'x' in mode,
@@ -168,6 +180,7 @@
p2 = parents.pop(0)
ctx = context.memctx(self.repo, (p1, p2), text, files.keys(),
getfilectx, commit.author, commit.date, extra)
+ ctx._contentsfilter = self.contentsfilter
self.repo.commitctx(ctx)
text = "(octopus merge fixup)\n"
p2 = hex(self.repo.changelog.tip())
More information about the Mercurial-devel
mailing list