[PATCH] convert: support glob patterns to exclude/include files

Tessa Starkey testarkey at gmail.com
Sun Mar 7 15:21:23 CST 2010


# HG changeset patch
# User Tessa Starkey <testarkey at gmail.com>
# Date 1267939187 18000
# Node ID b894d8a84bef5dd0702e41c9f7959a62f7cbd9f6
# Parent  efd3b71fc29315e79a29033fdd0d149b309eb398
convert: support glob patterns to include/exclude files

Implemented by replacing the existing filename-matching logic and using
matcher from the main match module instead. This was done to avoid
re-implementing glob matching.

diff --git a/hgext/convert/filemap.py b/hgext/convert/filemap.py
--- a/hgext/convert/filemap.py
+++ b/hgext/convert/filemap.py
@@ -6,7 +6,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 +21,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 = []
+        self.excludematch = []
         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 +47,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')
+                self.includematch.append(match.match(self.root, '', [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
+                self.excludematch.append(match.match(self.root, '',[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())
@@ -73,16 +76,23 @@
                 pass
         return '', name, ''
 
+    def matchlookup(self, name, matchers):
+        for pre, suf in rpairs(name):
+            for m in matchers:
+                if m(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 +125,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.py
 hg ci -d '0 0' -qAm '0: add foo baz dir/'
 
 echo bar > bar
@@ -128,3 +130,16 @@
 hg --cwd source cat copied
 echo 'copied2:'
 hg --cwd renames.repo cat copied2
+
+cat > globs.fmap <<EOF
+exclude dir/file2
+exclude b*
+rename dir dir2
+rename foo foo2
+exclude */f?.py
+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.py dir/subdir/file3 dir/subdir/file4 foo
 
 % final file versions in this repo:
 9463f52fe115e377cf2878d4fc548117211063f2 644   bar
 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644   baz
 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644   copied
+6617e5e33028b1dd4bc5a15ddfe1657fc0f9bb34 644   dir/fi.bin
 3e20847584beff41d7cd16136b7331ab3d754be0 644   dir/file
 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644   dir/file2
+18b2e207d8149c85a4f4e9baf4a9d8d8d8bbd22d 644   dir/file5.py
 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.py dir2/subdir/file3 foo2
 
 d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644   copied2
+6617e5e33028b1dd4bc5a15ddfe1657fc0f9bb34 644   dir2/fi.bin
 3e20847584beff41d7cd16136b7331ab3d754be0 644   dir2/file
+18b2e207d8149c85a4f4e9baf4a9d8d8d8bbd22d 644   dir2/file5.py
 5fe139720576e18e34bcc9f79174db8897c8afe9 644   dir2/subdir/file3
 9a7b52012991e4873687192c3e17e61ba3e837a3 644   foo2
 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
@@ -157,3 +161,29 @@
 foo
 copied2:
 foo
+@  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/fi.bin dir2/file dir2/file5.py dir2/subdir/file3 dir2/subdir/file4 foo2
+
+d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644   copied
+6617e5e33028b1dd4bc5a15ddfe1657fc0f9bb34 644   dir2/fi.bin
+3e20847584beff41d7cd16136b7331ab3d754be0 644   dir2/file
+18b2e207d8149c85a4f4e9baf4a9d8d8d8bbd22d 644   dir2/file5.py
+5fe139720576e18e34bcc9f79174db8897c8afe9 644   dir2/subdir/file3
+57a1c1511590f3de52874adfa04effe8a77d64af 644   dir2/subdir/file4
+9a7b52012991e4873687192c3e17e61ba3e837a3 644   foo2
+bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644   quux


More information about the Mercurial-devel mailing list