[PATCH] convert: support glob patterns in filemap directives

Tessa Starkey testarkey at gmail.com
Wed Mar 24 20:52:15 CDT 2010


# HG changeset patch
# User Tessa Starkey <testarkey at gmail.com>
# Date 1269481039 14400
# Node ID f428cd7661d07c6dd379760ccb99f51dcd359abb
# Parent  d9aa5b368e36c10d2c29411772fef9fd339c2e9f
convert: support glob patterns in exclude and include filemap directives

This is implemented using the matcher from the mercurial core, in order to
make the it more consistant and avoid rewriting the matching code.

diff --git a/hgext/convert/__init__.py b/hgext/convert/__init__.py
--- a/hgext/convert/__init__.py
+++ b/hgext/convert/__init__.py
@@ -90,9 +90,10 @@
     directory, to be included in the destination repository, and the
     exclusion of all other files and directories not explicitly
     included. The 'exclude' directive causes files or directories to
-    be omitted. The 'rename' directive renames a file or directory. To
-    rename from a subdirectory into the root of the repository, use
-    '.' as the path to rename to.
+    be omitted. In the arguments to 'include' and 'exclude' directives,
+    glob patterns can be used, but not regular expressions. The 'rename'
+    directive renames a file or directory. To rename from a subdirectory
+    into the root of the repository, use '.' as the path to rename to.
 
     The splicemap is a file that allows insertion of synthetic
     history, letting you specify the parents of a revision. This is
diff --git a/hgext/convert/filemap.py b/hgext/convert/filemap.py
--- a/hgext/convert/filemap.py
+++ b/hgext/convert/filemap.py
@@ -1,3 +1,4 @@
+
 # Copyright 2007 Bryan O'Sullivan <bos at serpentine.com>
 # Copyright 2007 Alexis S. L. Carvalho <alexis at cecm.usp.br>
 #
@@ -6,7 +7,7 @@
 
 import shlex
 from mercurial.i18n import _
-from mercurial import util
+from mercurial import util, match
 from common import SKIPREV, converter_source
 
 def rpairs(name):
@@ -21,17 +22,20 @@
     A name can be mapped to itself, a new name, or None (omit from new
     repository).'''
 
-    def __init__(self, ui, path=None):
+    def __init__(self, ui, root,  path=None):
         self.ui = ui
-        self.include = {}
-        self.exclude = {}
+        self.root = root
         self.rename = {}
+        self.includematch = None
+        self.excludematch = None
         if path:
             if self.parse(path):
                 raise util.Abort(_('errors in filemap'))
 
     def parse(self, path):
         errs = 0
+        include = []
+        exclude = []
         def check(name, mapping, listname):
             if name in mapping:
                 self.ui.warn(_('%s:%d: %r already in %s list\n') %
@@ -44,17 +48,17 @@
         while cmd:
             if cmd == 'include':
                 name = lex.get_token()
-                errs += check(name, self.exclude, 'exclude')
-                self.include[name] = name
+                errs += check(name, exclude, 'exclude')
+                include.append(name)
             elif cmd == 'exclude':
                 name = lex.get_token()
-                errs += check(name, self.include, 'include')
+                errs += check(name, include, 'include')
                 errs += check(name, self.rename, 'rename')
-                self.exclude[name] = name
+                exclude.append(name)
             elif cmd == 'rename':
                 src = lex.get_token()
                 dest = lex.get_token()
-                errs += check(src, self.exclude, 'exclude')
+                errs += check(src, exclude, 'exclude')
                 self.rename[src] = dest
             elif cmd == 'source':
                 errs += self.parse(lex.get_token())
@@ -63,6 +67,13 @@
                              (lex.infile, lex.lineno, cmd))
                 errs += 1
             cmd = lex.get_token()
+        #deal with svn urls for files
+        if self.root.startswith("file://"):
+            self.root = self.root[7:]
+        if include:
+            self.includematch = match.match(self.root, '', include)
+        if exclude:
+            self.excludematch = match.match(self.root, '', exclude)
         return errs
 
     def lookup(self, name, mapping):
@@ -73,16 +84,22 @@
                 pass
         return '', name, ''
 
+    def matchlookup(self, name, matcher):
+        for pre, suf in rpairs(name):
+             if matcher(pre):
+                 return pre, pre, suf
+        return '', name, ''
+
     def __call__(self, name):
-        if self.include:
-            inc = self.lookup(name, self.include)[0]
+        if self.includematch:
+            inc = self.matchlookup(name, self.includematch)[0]
         else:
             inc = name
-        if self.exclude:
-            exc = self.lookup(name, self.exclude)[0]
+        if self.excludematch:
+            exc = self.matchlookup(name, self.excludematch)[0]
         else:
             exc = ''
-        if (not self.include and exc) or (len(inc) <= len(exc)):
+        if (not self.includematch and exc) or (len(inc) <= len(exc)):
             return None
         newpre, pre, suf = self.lookup(name, self.rename)
         if newpre:
@@ -115,7 +132,7 @@
     def __init__(self, ui, baseconverter, filemap):
         super(filemap_source, self).__init__(ui)
         self.base = baseconverter
-        self.filemapper = filemapper(ui, filemap)
+        self.filemapper = filemapper(ui, self.base.path, filemap)
         self.commits = {}
         # if a revision rev has parent p in the original revision graph, then
         # rev will have parent self.parentmap[p] in the restricted graph.
diff --git a/tests/test-convert-filemap b/tests/test-convert-filemap
--- a/tests/test-convert-filemap
+++ b/tests/test-convert-filemap
@@ -21,6 +21,8 @@
 echo dir/file2 >> dir/file2
 echo dir/subdir/file3 >> dir/subdir/file3
 echo dir/subdir/file4 >> dir/subdir/file4
+echo dir/fi.bin >> dir/fi.bin
+echo dir/file5.bin >> dir/file5.bin
 hg ci -d '0 0' -qAm '0: add foo baz dir/'
 
 echo bar > bar
@@ -128,3 +130,17 @@
 hg --cwd source cat copied
 echo 'copied2:'
 hg --cwd renames.repo cat copied2
+
+echo % convert with glob exclude patterns in filemap
+cat > globs.fmap <<EOF
+exclude dir/file2
+exclude b*
+rename dir dir2
+rename foo foo2
+exclude */f?.bin
+EOF
+hg -q convert --filemap globs.fmap --datesort source globs.repo
+hg up -q -R globs.repo
+glog -R globs.repo
+hg -R globs.repo manifest --debug
+
diff --git a/tests/test-convert-filemap.out b/tests/test-convert-filemap.out
--- a/tests/test-convert-filemap.out
+++ b/tests/test-convert-filemap.out
@@ -16,14 +16,16 @@
 |/
 o  1 "1: add bar quux; copy foo to copied" files: bar copied quux
 |
-o  0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/subdir/file3 dir/subdir/file4 foo
+o  0 "0: add foo baz dir/" files: baz dir/fi.bin dir/file dir/file2 dir/file5.bin dir/subdir/file3 dir/subdir/file4 foo
 
 % final file versions in this repo:
 9463f52fe115e377cf2878d4fc548117211063f2 644   bar
 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644   baz
 6ca237634e1f6bee1b6db94292fb44f092a25842 644   copied
+6617e5e33028b1dd4bc5a15ddfe1657fc0f9bb34 644   dir/fi.bin
 3e20847584beff41d7cd16136b7331ab3d754be0 644   dir/file
 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644   dir/file2
+18b2e207d8149c85a4f4e9baf4a9d8d8d8bbd22d 644   dir/file5.bin
 5fe139720576e18e34bcc9f79174db8897c8afe9 644   dir/subdir/file3
 57a1c1511590f3de52874adfa04effe8a77d64af 644   dir/subdir/file4
 9a7b52012991e4873687192c3e17e61ba3e837a3 644   foo
@@ -146,10 +148,12 @@
 |
 o  1 "1: add bar quux; copy foo to copied" files: copied2
 |
-o  0 "0: add foo baz dir/" files: dir2/file dir2/subdir/file3 foo2
+o  0 "0: add foo baz dir/" files: dir2/fi.bin dir2/file dir2/file5.bin dir2/subdir/file3 foo2
 
 e5e3d520be9be45937d0b06b004fadcd6c221fa2 644   copied2
+6617e5e33028b1dd4bc5a15ddfe1657fc0f9bb34 644   dir2/fi.bin
 3e20847584beff41d7cd16136b7331ab3d754be0 644   dir2/file
+18b2e207d8149c85a4f4e9baf4a9d8d8d8bbd22d 644   dir2/file5.bin
 5fe139720576e18e34bcc9f79174db8897c8afe9 644   dir2/subdir/file3
 9a7b52012991e4873687192c3e17e61ba3e837a3 644   foo2
 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
@@ -157,3 +161,29 @@
 foo
 copied2:
 foo
+% convert with glob exclude patterns in filemap
+@  8 "8: change foo" files: foo2
+|
+o    7 "7: second merge; change bar" files:
+|\
+| o  6 "6: change foo baz" files: foo2
+| |
+o |  5 "5: change bar baz quux" files: quux
+|/
+o    4 "4: first merge; change bar baz" files:
+|\
+| o  3 "3: change bar quux" files: quux
+| |
+o |  2 "2: change foo" files: foo2
+|/
+o  1 "1: add bar quux; copy foo to copied" files: copied quux
+|
+o  0 "0: add foo baz dir/" files: dir2/file dir2/file5.bin dir2/subdir/file3 dir2/subdir/file4 foo2
+
+e5e3d520be9be45937d0b06b004fadcd6c221fa2 644   copied
+3e20847584beff41d7cd16136b7331ab3d754be0 644   dir2/file
+18b2e207d8149c85a4f4e9baf4a9d8d8d8bbd22d 644   dir2/file5.bin
+5fe139720576e18e34bcc9f79174db8897c8afe9 644   dir2/subdir/file3
+57a1c1511590f3de52874adfa04effe8a77d64af 644   dir2/subdir/file4
+9a7b52012991e4873687192c3e17e61ba3e837a3 644   foo2
+bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644   quux
diff --git a/tests/test-convert.out b/tests/test-convert.out
--- a/tests/test-convert.out
+++ b/tests/test-convert.out
@@ -69,9 +69,11 @@
     The 'include' directive causes a file, or all files under a directory, to
     be included in the destination repository, and the exclusion of all other
     files and directories not explicitly included. The 'exclude' directive
-    causes files or directories to be omitted. The 'rename' directive renames
-    a file or directory. To rename from a subdirectory into the root of the
-    repository, use '.' as the path to rename to.
+    causes files or directories to be omitted. In the arguments to 'include'
+    and 'exclude' directives, glob patterns can be used, but not regular
+    expressions. The 'rename' directive renames a file or directory. To rename
+    from a subdirectory into the root of the repository, use '.' as the path
+    to rename to.
 
     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


More information about the Mercurial-devel mailing list