changeset 4200:b5d1eaade333

Merge a bunch of matcher and locate fixes.
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
date Sat, 10 Mar 2007 23:21:33 -0300
parents ba51a8225a60 (current diff) ec932167c3a7 (diff)
children 7e95381a9f1e
files mercurial/cmdutil.py mercurial/commands.py mercurial/dirstate.py mercurial/localrepo.py mercurial/patch.py mercurial/util.py
diffstat 14 files changed, 369 insertions(+), 143 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/cmdutil.py	Sat Mar 10 17:45:32 2007 -0800
+++ b/mercurial/cmdutil.py	Sat Mar 10 23:21:33 2007 -0300
@@ -125,21 +125,16 @@
                               pathname),
                 mode)
 
-def matchpats(repo, pats=[], opts={}, head='', globbed=False):
+def matchpats(repo, pats=[], opts={}, globbed=False, default=None):
     cwd = repo.getcwd()
-    if not pats and cwd:
-        opts['include'] = [os.path.join(cwd, i)
-                           for i in opts.get('include', [])]
-        opts['exclude'] = [os.path.join(cwd, x)
-                           for x in opts.get('exclude', [])]
-        cwd = ''
-    return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
-                           opts.get('exclude'), head, globbed=globbed)
+    return util.cmdmatcher(repo.root, cwd, pats or [], opts.get('include'),
+                           opts.get('exclude'), globbed=globbed,
+                           default=default)
 
-def walk(repo, pats=[], opts={}, node=None, head='', badmatch=None,
-         globbed=False):
-    files, matchfn, anypats = matchpats(repo, pats, opts, head,
-                                        globbed=globbed)
+def walk(repo, pats=[], opts={}, node=None, badmatch=None, globbed=False,
+         default=None):
+    files, matchfn, anypats = matchpats(repo, pats, opts, globbed=globbed,
+                                        default=default)
     exact = dict.fromkeys(files)
     for src, fn in repo.walk(node=node, files=files, match=matchfn,
                              badmatch=badmatch):
--- a/mercurial/commands.py	Sat Mar 10 17:45:32 2007 -0800
+++ b/mercurial/commands.py	Sat Mar 10 23:21:33 2007 -0300
@@ -1599,9 +1599,8 @@
     Print all files under Mercurial control whose names match the
     given patterns.
 
-    This command searches the current directory and its
-    subdirectories.  To search an entire repository, move to the root
-    of the repository.
+    This command searches the entire repository by default.  To search
+    just the current directory and its subdirectories, use "--include .".
 
     If no patterns are given to match, this command prints all file
     names.
@@ -1618,14 +1617,18 @@
     else:
         node = None
 
+    ret = 1
     for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
-                                             head='(?:.*/|)'):
+                                             default='relglob'):
         if not node and repo.dirstate.state(abs) == '?':
             continue
         if opts['fullpath']:
             ui.write(os.path.join(repo.root, abs), end)
         else:
             ui.write(((pats and rel) or abs), end)
+        ret = 0
+
+    return ret
 
 def log(ui, repo, *pats, **opts):
     """show revision history of entire repository or files
--- a/mercurial/dirstate.py	Sat Mar 10 17:45:32 2007 -0800
+++ b/mercurial/dirstate.py	Sat Mar 10 23:21:33 2007 -0300
@@ -386,7 +386,10 @@
                 return False
             return match(file_)
 
-        if ignored: imatch = match
+        ignore = self.ignore
+        if ignored:
+            imatch = match
+            ignore = util.never
 
         # self.root may end with a path separator when self.root == '/'
         common_prefix_len = len(self.root)
@@ -421,8 +424,7 @@
                     # don't trip over symlinks
                     st = os.lstat(p)
                     if stat.S_ISDIR(st.st_mode):
-                        ds = util.pconvert(os.path.join(nd, f +'/'))
-                        if imatch(ds):
+                        if not ignore(p):
                             work.append(p)
                             if directories:
                                 yield 'd', np, st
--- a/mercurial/localrepo.py	Sat Mar 10 17:45:32 2007 -0800
+++ b/mercurial/localrepo.py	Sat Mar 10 23:21:33 2007 -0300
@@ -873,7 +873,13 @@
 
         if node:
             fdict = dict.fromkeys(files)
-            for fn in self.manifest.read(self.changelog.read(node)[0]):
+            # for dirstate.walk, files=['.'] means "walk the whole tree".
+            # follow that here, too
+            fdict.pop('.', None)
+            mdict = self.manifest.read(self.changelog.read(node)[0])
+            mfiles = mdict.keys()
+            mfiles.sort()
+            for fn in mfiles:
                 for ffn in fdict:
                     # match if the file is the exact name or a directory
                     if ffn == fn or fn.startswith("%s/" % ffn):
@@ -881,7 +887,9 @@
                         break
                 if match(fn):
                     yield 'm', fn
-            for fn in fdict:
+            ffiles = fdict.keys()
+            ffiles.sort()
+            for fn in ffiles:
                 if badmatch and badmatch(fn):
                     if match(fn):
                         yield 'b', fn
--- a/mercurial/patch.py	Sat Mar 10 17:45:32 2007 -0800
+++ b/mercurial/patch.py	Sat Mar 10 23:21:33 2007 -0300
@@ -464,17 +464,6 @@
     if not changes:
         changes = repo.status(node1, node2, files, match=match)[:5]
     modified, added, removed, deleted, unknown = changes
-    if files:
-        def filterfiles(filters):
-            l = [x for x in filters if x in files]
-
-            for t in files:
-                if not t.endswith("/"):
-                    t += "/"
-                l += [x for x in filters if x.startswith(t)]
-            return l
-
-        modified, added, removed = map(filterfiles, (modified, added, removed))
 
     if not modified and not added and not removed:
         return
--- a/mercurial/util.py	Sat Mar 10 17:45:32 2007 -0800
+++ b/mercurial/util.py	Sat Mar 10 23:21:33 2007 -0300
@@ -389,16 +389,17 @@
 
         raise Abort('%s not under root' % myname)
 
-def matcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='', src=None):
-    return _matcher(canonroot, cwd, names, inc, exc, head, 'glob', src)
+def matcher(canonroot, cwd='', names=[], inc=[], exc=[], src=None):
+    return _matcher(canonroot, cwd, names, inc, exc, 'glob', src)
 
-def cmdmatcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='',
-               src=None, globbed=False):
-    if not globbed:
+def cmdmatcher(canonroot, cwd='', names=[], inc=[], exc=[], src=None,
+               globbed=False, default=None):
+    default = default or 'relpath'
+    if default == 'relpath' and not globbed:
         names = expand_glob(names)
-    return _matcher(canonroot, cwd, names, inc, exc, head, 'relpath', src)
+    return _matcher(canonroot, cwd, names, inc, exc, default, src)
 
-def _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat, src):
+def _matcher(canonroot, cwd, names, inc, exc, dflt_pat, src):
     """build a function to match a set of file patterns
 
     arguments:
@@ -407,26 +408,30 @@
     names - patterns to find
     inc - patterns to include
     exc - patterns to exclude
-    head - a regex to prepend to patterns to control whether a match is rooted
+    dflt_pat - if a pattern in names has no explicit type, assume this one
+    src - where these patterns came from (e.g. .hgignore)
 
     a pattern is one of:
-    'glob:<rooted glob>'
-    're:<rooted regexp>'
-    'path:<rooted path>'
-    'relglob:<relative glob>'
-    'relpath:<relative path>'
-    'relre:<relative regexp>'
-    '<rooted path or regexp>'
+    'glob:<glob>' - a glob relative to cwd
+    're:<regexp>' - a regular expression
+    'path:<path>' - a path relative to canonroot
+    'relglob:<glob>' - an unrooted glob (*.c matches C files in all dirs)
+    'relpath:<path>' - a path relative to cwd
+    'relre:<regexp>' - a regexp that doesn't have to match the start of a name
+    '<something>' - one of the cases above, selected by the dflt_pat argument
 
     returns:
     a 3-tuple containing
-    - list of explicit non-pattern names passed in
+    - list of roots (places where one should start a recursive walk of the fs);
+      this often matches the explicit non-pattern names passed in, but also
+      includes the initial part of glob: patterns that has no glob characters
     - a bool match(filename) function
     - a bool indicating if any patterns were passed in
+    """
 
-    todo:
-    make head regex a rooted bool
-    """
+    # a common case: no patterns at all
+    if not names and not inc and not exc:
+        return [], always, False
 
     def contains_glob(name):
         for c in name:
@@ -435,19 +440,21 @@
 
     def regex(kind, name, tail):
         '''convert a pattern into a regular expression'''
+        if not name:
+            return ''
         if kind == 're':
             return name
         elif kind == 'path':
             return '^' + re.escape(name) + '(?:/|$)'
         elif kind == 'relglob':
-            return head + globre(name, '(?:|.*/)', tail)
+            return globre(name, '(?:|.*/)', '(?:/|$)')
         elif kind == 'relpath':
-            return head + re.escape(name) + tail
+            return re.escape(name) + '(?:/|$)'
         elif kind == 'relre':
             if name.startswith('^'):
                 return name
             return '.*' + name
-        return head + globre(name, '', tail)
+        return globre(name, '', tail)
 
     def matchfn(pats, tail):
         """build a matching function from a set of patterns"""
@@ -473,46 +480,53 @@
     def globprefix(pat):
         '''return the non-glob prefix of a path, e.g. foo/* -> foo'''
         root = []
-        for p in pat.split(os.sep):
+        for p in pat.split('/'):
             if contains_glob(p): break
             root.append(p)
-        return '/'.join(root)
+        return '/'.join(root) or '.'
 
-    pats = []
-    files = []
-    roots = []
-    for kind, name in [patkind(p, dflt_pat) for p in names]:
-        if kind in ('glob', 'relpath'):
-            name = canonpath(canonroot, cwd, name)
-            if name == '':
-                kind, name = 'glob', '**'
-        if kind in ('glob', 'path', 're'):
-            pats.append((kind, name))
-        if kind == 'glob':
-            root = globprefix(name)
-            if root: roots.append(root)
-        elif kind == 'relpath':
-            files.append((kind, name))
-            roots.append(name)
+    def normalizepats(names, default):
+        pats = []
+        files = []
+        roots = []
+        anypats = False
+        for kind, name in [patkind(p, default) for p in names]:
+            if kind in ('glob', 'relpath'):
+                name = canonpath(canonroot, cwd, name)
+            elif kind in ('relglob', 'path'):
+                name = normpath(name)
+            if kind in ('glob', 're', 'relglob', 'relre'):
+                pats.append((kind, name))
+                anypats = True
+            if kind == 'glob':
+                root = globprefix(name)
+                roots.append(root)
+            elif kind in ('relpath', 'path'):
+                files.append((kind, name))
+                roots.append(name)
+            elif kind == 'relglob':
+                roots.append('.')
+        return roots, pats + files, anypats
+
+    roots, pats, anypats = normalizepats(names, dflt_pat)
 
     patmatch = matchfn(pats, '$') or always
-    filematch = matchfn(files, '(?:/|$)') or always
     incmatch = always
     if inc:
-        inckinds = [patkind(canonpath(canonroot, cwd, i)) for i in inc]
+        dummy, inckinds, dummy = normalizepats(inc, 'glob')
         incmatch = matchfn(inckinds, '(?:/|$)')
     excmatch = lambda fn: False
     if exc:
-        exckinds = [patkind(canonpath(canonroot, cwd, x)) for x in exc]
+        dummy, exckinds, dummy = normalizepats(exc, 'glob')
         excmatch = matchfn(exckinds, '(?:/|$)')
 
-    return (roots,
-            lambda fn: (incmatch(fn) and not excmatch(fn) and
-                        (fn.endswith('/') or
-                         (not pats and not files) or
-                         (pats and patmatch(fn)) or
-                         (files and filematch(fn)))),
-            (inc or exc or (pats and pats != [('glob', '**')])) and True)
+    if not names and inc and not exc:
+        # common case: hgignore patterns
+        match = incmatch
+    else:
+        match = lambda fn: incmatch(fn) and not excmatch(fn) and patmatch(fn)
+
+    return (roots, match, (inc or exc or anypats) and True)
 
 def system(cmd, environ={}, cwd=None, onerr=None, errprefix=None):
     '''enhanced shell command execution.
--- a/tests/test-backout.out	Sat Mar 10 17:45:32 2007 -0800
+++ b/tests/test-backout.out	Sat Mar 10 23:21:33 2007 -0300
@@ -28,7 +28,6 @@
 changeset 3:4cbb1e70196a backs out changeset 1:22bca4c721e5
 the backout changeset is a new head - do not forget to merge
 (use "backout --merge" if you want to auto-merge)
-b: No such file or directory
 adding a
 adding b
 adding c
--- a/tests/test-git-import.out	Sat Mar 10 17:45:32 2007 -0800
+++ b/tests/test-git-import.out	Sat Mar 10 23:21:33 2007 -0300
@@ -31,7 +31,6 @@
 a
 % rename and modify
 applying patch from stdin
-copy2: No such file or directory
 a
 a
 b
@@ -40,7 +39,6 @@
 % one file renamed multiple times
 applying patch from stdin
 9 rename2 rename3 rename3-2 / rename3 (rename2)rename3-2 (rename2)
-rename2: No such file or directory
 rename3
 rename3-2
 a
--- a/tests/test-issue352	Sat Mar 10 17:45:32 2007 -0800
+++ b/tests/test-issue352	Sat Mar 10 23:21:33 2007 -0300
@@ -6,16 +6,17 @@
 
 A=`echo -e -n 'he\rllo'`
 
-echo foo > "hell
-o"
 echo foo > "$A"
 hg add
 hg ci -A -m m
 rm "$A"
-ls
+
+echo foo > "hell
+o"
 hg add
-# BUG ? we don't walk on filenames with '\n' (regexp related) ?
-hg debugwalk
 hg ci -A -m m
 
+echo foo > "$A"
+hg debugwalk
+
 exit 0
--- a/tests/test-issue352.out	Sat Mar 10 17:45:32 2007 -0800
+++ b/tests/test-issue352.out	Sat Mar 10 23:21:33 2007 -0300
@@ -2,6 +2,13 @@
 abort: '\n' and '\r' disallowed in filenames
 adding he
llo
 abort: '\n' and '\r' disallowed in filenames
-hell
+adding hell
+o
+abort: '\n' and '\r' disallowed in filenames
+adding hell
 o
-nothing changed
+abort: '\n' and '\r' disallowed in filenames
+f  he
llo  he
llo
+f  hell
+o  hell
+o
--- a/tests/test-locate	Sat Mar 10 17:45:32 2007 -0800
+++ b/tests/test-locate	Sat Mar 10 23:21:33 2007 -0300
@@ -10,8 +10,8 @@
 echo 0 > t/x
 hg ci -A -m m -d "1000000 0"
 touch nottracked
-hg locate a
-hg locate NONEXISTENT
+hg locate a && echo locate succeeded || echo locate failed
+hg locate NONEXISTENT && echo locate succeeded || echo locate failed
 hg locate
 hg rm a
 hg ci -m m -d "1000000 0"
--- a/tests/test-locate.out	Sat Mar 10 17:45:32 2007 -0800
+++ b/tests/test-locate.out	Sat Mar 10 23:21:33 2007 -0300
@@ -3,22 +3,20 @@
 adding t.h
 adding t/x
 a
-NONEXISTENT: No such file or directory
+locate succeeded
+locate failed
 a
 b
 t.h
 t/x
-a: No such file or directory
-NONEXISTENT: No such file or directory
 b
 t.h
 t/x
 a
-NONEXISTENT: No such file in rev ce18e5bc5cd3
 a
-t/x
 b
 t.h
+t/x
 % -I/-X with relative path should work
 b
 t.h
--- a/tests/test-walk	Sat Mar 10 17:45:32 2007 -0800
+++ b/tests/test-walk	Sat Mar 10 23:21:33 2007 -0300
@@ -1,5 +1,19 @@
 #!/bin/sh
 
+debugwalk()
+{
+    echo "hg debugwalk $@"
+    hg debugwalk "$@"
+    echo
+}
+
+chdir()
+{
+    echo "cd $@"
+    cd "$@"
+    echo
+}
+
 mkdir t
 cd t
 hg init
@@ -18,44 +32,61 @@
 echo glob:glob > glob:glob
 hg addremove
 hg commit -m "commit #0" -d "1000000 0"
-hg debugwalk
-cd mammals
-hg debugwalk .
-hg debugwalk Procyonidae
-cd Procyonidae
-hg debugwalk .
-hg debugwalk ..
-cd ..
-hg debugwalk ../beans
-hg debugwalk .
-hg debugwalk .hg
-hg debugwalk ../.hg
-cd ..
-hg debugwalk -Ibeans
-hg debugwalk 'glob:mammals/../beans/b*'
-hg debugwalk '-X*/Procyonidae' mammals
-hg debugwalk path:mammals
-hg debugwalk ..
-hg debugwalk beans/../..
-hg debugwalk .hg
-hg debugwalk beans/../.hg
-hg debugwalk beans/../.hg/data
-hg debugwalk beans/.hg
+debugwalk
+debugwalk -I.
+chdir mammals
+debugwalk
+debugwalk -X ../beans
+debugwalk -I '*k'
+debugwalk -I 'glob:*k'
+debugwalk -I 'relglob:*k'
+debugwalk -I 'relglob:*k' .
+debugwalk -I 're:.*k$'
+debugwalk -I 'relre:.*k$'
+debugwalk -I 'path:beans'
+debugwalk -I 'relpath:../beans'
+debugwalk .
+debugwalk -I.
+debugwalk Procyonidae
+chdir Procyonidae
+debugwalk .
+debugwalk ..
+chdir ..
+debugwalk ../beans
+debugwalk .
+debugwalk .hg
+debugwalk ../.hg
+chdir ..
+debugwalk -Ibeans
+debugwalk 'glob:mammals/../beans/b*'
+debugwalk '-X*/Procyonidae' mammals
+debugwalk path:mammals
+debugwalk ..
+debugwalk beans/../..
+debugwalk .hg
+debugwalk beans/../.hg
+debugwalk beans/../.hg/data
+debugwalk beans/.hg
 # Don't know how to test absolute paths without always getting a false
 # error.
-#hg debugwalk `pwd`/beans
-#hg debugwalk `pwd`/..
-hg debugwalk glob:\*
-hg debugwalk 're:.*[kb]$'
-hg debugwalk path:beans/black
-hg debugwalk beans 'glob:beans/*'
-hg debugwalk 'glob:j*'
-hg debugwalk NOEXIST
+#debugwalk `pwd`/beans
+#debugwalk `pwd`/..
+debugwalk glob:\*
+debugwalk 're:.*[kb]$'
+debugwalk path:beans/black
+debugwalk path:beans//black
+debugwalk relglob:Procyonidae
+debugwalk relglob:Procyonidae/ fennel
+debugwalk beans 'glob:beans/*'
+debugwalk 'glob:mamm**'
+debugwalk 'glob:mamm**' fennel
+debugwalk 'glob:j*'
+debugwalk NOEXIST
 mkfifo fifo
-hg debugwalk fifo
+debugwalk fifo
 rm fenugreek
-hg debugwalk fenugreek
+debugwalk fenugreek
 hg rm fenugreek
-hg debugwalk fenugreek
+debugwalk fenugreek
 touch new
-hg debugwalk new
+debugwalk new
--- a/tests/test-walk.out	Sat Mar 10 17:45:32 2007 -0800
+++ b/tests/test-walk.out	Sat Mar 10 23:21:33 2007 -0300
@@ -12,6 +12,23 @@
 adding mammals/Procyonidae/coatimundi
 adding mammals/Procyonidae/raccoon
 adding mammals/skunk
+hg debugwalk 
+f  beans/black                     beans/black
+f  beans/borlotti                  beans/borlotti
+f  beans/kidney                    beans/kidney
+f  beans/navy                      beans/navy
+f  beans/pinto                     beans/pinto
+f  beans/turtle                    beans/turtle
+f  fennel                          fennel
+f  fenugreek                       fenugreek
+f  fiddlehead                      fiddlehead
+f  glob:glob                       glob:glob
+f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
+f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
+f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
+f  mammals/skunk                   mammals/skunk
+
+hg debugwalk -I.
 f  beans/black                     beans/black
 f  beans/borlotti                  beans/borlotti
 f  beans/kidney                    beans/kidney
@@ -26,72 +43,236 @@
 f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
 f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
 f  mammals/skunk                   mammals/skunk
+
+cd mammals
+
+hg debugwalk 
+f  beans/black                     ../beans/black
+f  beans/borlotti                  ../beans/borlotti
+f  beans/kidney                    ../beans/kidney
+f  beans/navy                      ../beans/navy
+f  beans/pinto                     ../beans/pinto
+f  beans/turtle                    ../beans/turtle
+f  fennel                          ../fennel
+f  fenugreek                       ../fenugreek
+f  fiddlehead                      ../fiddlehead
+f  glob:glob                       ../glob:glob
 f  mammals/Procyonidae/cacomistle  Procyonidae/cacomistle
 f  mammals/Procyonidae/coatimundi  Procyonidae/coatimundi
 f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
 f  mammals/skunk                   skunk
+
+hg debugwalk -X ../beans
+f  fennel                          ../fennel
+f  fenugreek                       ../fenugreek
+f  fiddlehead                      ../fiddlehead
+f  glob:glob                       ../glob:glob
 f  mammals/Procyonidae/cacomistle  Procyonidae/cacomistle
 f  mammals/Procyonidae/coatimundi  Procyonidae/coatimundi
 f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
-f  mammals/Procyonidae/cacomistle  cacomistle
-f  mammals/Procyonidae/coatimundi  coatimundi
-f  mammals/Procyonidae/raccoon     raccoon
-f  mammals/Procyonidae/cacomistle  cacomistle
-f  mammals/Procyonidae/coatimundi  coatimundi
-f  mammals/Procyonidae/raccoon     raccoon
-f  mammals/skunk                   ../skunk
+f  mammals/skunk                   skunk
+
+hg debugwalk -I *k
+f  mammals/skunk  skunk
+
+hg debugwalk -I glob:*k
+f  mammals/skunk  skunk
+
+hg debugwalk -I relglob:*k
+f  beans/black    ../beans/black
+f  fenugreek      ../fenugreek
+f  mammals/skunk  skunk
+
+hg debugwalk -I relglob:*k .
+f  mammals/skunk  skunk
+
+hg debugwalk -I re:.*k$
+f  beans/black    ../beans/black
+f  fenugreek      ../fenugreek
+f  mammals/skunk  skunk
+
+hg debugwalk -I relre:.*k$
+f  beans/black    ../beans/black
+f  fenugreek      ../fenugreek
+f  mammals/skunk  skunk
+
+hg debugwalk -I path:beans
 f  beans/black     ../beans/black
 f  beans/borlotti  ../beans/borlotti
 f  beans/kidney    ../beans/kidney
 f  beans/navy      ../beans/navy
 f  beans/pinto     ../beans/pinto
 f  beans/turtle    ../beans/turtle
+
+hg debugwalk -I relpath:../beans
+f  beans/black     ../beans/black
+f  beans/borlotti  ../beans/borlotti
+f  beans/kidney    ../beans/kidney
+f  beans/navy      ../beans/navy
+f  beans/pinto     ../beans/pinto
+f  beans/turtle    ../beans/turtle
+
+hg debugwalk .
+f  mammals/Procyonidae/cacomistle  Procyonidae/cacomistle
+f  mammals/Procyonidae/coatimundi  Procyonidae/coatimundi
+f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
+f  mammals/skunk                   skunk
+
+hg debugwalk -I.
 f  mammals/Procyonidae/cacomistle  Procyonidae/cacomistle
 f  mammals/Procyonidae/coatimundi  Procyonidae/coatimundi
 f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
 f  mammals/skunk                   skunk
+
+hg debugwalk Procyonidae
+f  mammals/Procyonidae/cacomistle  Procyonidae/cacomistle
+f  mammals/Procyonidae/coatimundi  Procyonidae/coatimundi
+f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
+
+cd Procyonidae
+
+hg debugwalk .
+f  mammals/Procyonidae/cacomistle  cacomistle
+f  mammals/Procyonidae/coatimundi  coatimundi
+f  mammals/Procyonidae/raccoon     raccoon
+
+hg debugwalk ..
+f  mammals/Procyonidae/cacomistle  cacomistle
+f  mammals/Procyonidae/coatimundi  coatimundi
+f  mammals/Procyonidae/raccoon     raccoon
+f  mammals/skunk                   ../skunk
+
+cd ..
+
+hg debugwalk ../beans
+f  beans/black     ../beans/black
+f  beans/borlotti  ../beans/borlotti
+f  beans/kidney    ../beans/kidney
+f  beans/navy      ../beans/navy
+f  beans/pinto     ../beans/pinto
+f  beans/turtle    ../beans/turtle
+
+hg debugwalk .
+f  mammals/Procyonidae/cacomistle  Procyonidae/cacomistle
+f  mammals/Procyonidae/coatimundi  Procyonidae/coatimundi
+f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
+f  mammals/skunk                   skunk
+
+hg debugwalk .hg
 .hg: No such file or directory
+
+hg debugwalk ../.hg
 abort: path contains illegal component: .hg
 
+
+cd ..
+
+hg debugwalk -Ibeans
 f  beans/black     beans/black
 f  beans/borlotti  beans/borlotti
 f  beans/kidney    beans/kidney
 f  beans/navy      beans/navy
 f  beans/pinto     beans/pinto
 f  beans/turtle    beans/turtle
+
+hg debugwalk glob:mammals/../beans/b*
 f  beans/black     beans/black
 f  beans/borlotti  beans/borlotti
+
+hg debugwalk -X*/Procyonidae mammals
 f  mammals/skunk  mammals/skunk
+
+hg debugwalk path:mammals
 f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
 f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
 f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
 f  mammals/skunk                   mammals/skunk
+
+hg debugwalk ..
 abort: .. not under root
+
+hg debugwalk beans/../..
 abort: beans/../.. not under root
+
+hg debugwalk .hg
 abort: path contains illegal component: .hg
 
+
+hg debugwalk beans/../.hg
 abort: path contains illegal component: .hg
 
+
+hg debugwalk beans/../.hg/data
 abort: path contains illegal component: .hg/data
 
+
+hg debugwalk beans/.hg
 beans/.hg: No such file or directory
+
+hg debugwalk glob:*
 f  fennel      fennel
 f  fenugreek   fenugreek
 f  fiddlehead  fiddlehead
 f  glob:glob   glob:glob
+
+hg debugwalk re:.*[kb]$
 f  beans/black    beans/black
 f  fenugreek      fenugreek
 f  glob:glob      glob:glob
 f  mammals/skunk  mammals/skunk
-f  beans/black  beans/black
+
+hg debugwalk path:beans/black
+f  beans/black  beans/black  exact
+
+hg debugwalk path:beans//black
+f  beans/black  beans/black  exact
+
+hg debugwalk relglob:Procyonidae
+f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
+f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
+f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
+
+hg debugwalk relglob:Procyonidae/ fennel
+f  fennel                          fennel                          exact
+f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
+f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
+f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
+
+hg debugwalk beans glob:beans/*
 f  beans/black     beans/black
 f  beans/borlotti  beans/borlotti
 f  beans/kidney    beans/kidney
 f  beans/navy      beans/navy
 f  beans/pinto     beans/pinto
 f  beans/turtle    beans/turtle
+
+hg debugwalk glob:mamm**
+f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
+f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
+f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
+f  mammals/skunk                   mammals/skunk
+
+hg debugwalk glob:mamm** fennel
+f  fennel                          fennel                          exact
+f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
+f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
+f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
+f  mammals/skunk                   mammals/skunk
+
+hg debugwalk glob:j*
+
+hg debugwalk NOEXIST
 NOEXIST: No such file or directory
+
+hg debugwalk fifo
 fifo: unsupported file type (type is fifo)
+
+hg debugwalk fenugreek
 m  fenugreek  fenugreek  exact
+
+hg debugwalk fenugreek
 m  fenugreek  fenugreek  exact
+
+hg debugwalk new
 f  new  new  exact
+