Add locate command.
authorBryan O'Sullivan <bos@serpentine.com>
Tue, 05 Jul 2005 18:19:01 -0800
changeset 627 b6c42714d900
parent 626 47207ec19c51
child 628 8d7f6e68828a
Add locate command. # HG changeset patch # User Bryan O'Sullivan <bos@serpentine.com> # Node ID ebf5eba347a17a5c09000b3342caf350cd060a1b # Parent d2994b5298fb20f87dc1d4747635b280db3c0526 Add locate command. Used for finding files with names that match specific patterns, such as "*.c". This patch also introduces localrepository.getcwd, which returns the current directory relative to the repository root.
doc/hg.1.txt
mercurial/commands.py
mercurial/hg.py
--- a/doc/hg.1.txt	Tue Jul 05 18:15:38 2005 -0800
+++ b/doc/hg.1.txt	Tue Jul 05 18:19:01 2005 -0800
@@ -183,6 +183,34 @@
 init::
     Initialize a new repository in the current directory.
 
+locate [options] [patterns]::
+    Print all files under Mercurial control whose names or paths match
+    the given patterns.
+
+    Patterns are shell-style globs.  To restrict searches to specific
+    directories, use the "-i <pat>" option.  To eliminate particular
+    directories from searching, use the "-x <pat>" option.
+
+    This command searches the current directory and its
+    subdirectories.  To search an entire repository, move to the root
+    of the repository.
+
+    If no patterns are given to match, this command prints all file
+    names.
+
+    If you want to feed the output of this command into the "xargs"
+    command, use the "-0" option to both this command and "xargs".
+    This will avoid the problem of "xargs" treating single filenames
+    that contain white space as multiple file names.
+
+    options:
+
+    -0, --print0         end filenames with NUL, for use with xargs
+    -f, --fullpath       print complete paths from the filesystem root
+    -i, --include <pat>  include directories matching the given globs
+    -r, --rev <rev>      search the repository as it stood at rev
+    -x, --exclude <pat>  exclude directories matching the given globs
+
 log [-r revision ...] [-p] [file]::
     Print the revision history of the specified file or the entire project.
 
--- a/mercurial/commands.py	Tue Jul 05 18:15:38 2005 -0800
+++ b/mercurial/commands.py	Tue Jul 05 18:19:01 2005 -0800
@@ -8,7 +8,7 @@
 from demandload import *
 demandload(globals(), "os re sys signal")
 demandload(globals(), "fancyopts ui hg util")
-demandload(globals(), "hgweb mdiff random signal time traceback")
+demandload(globals(), "fnmatch hgweb mdiff random signal time traceback")
 demandload(globals(), "errno socket version struct")
 
 class UnknownCommand(Exception): pass
@@ -631,6 +631,46 @@
         sys.exit(1)
     repo = hg.repository(ui, ".", create=1)
 
+def locate(ui, repo, *pats, **opts):
+    """locate files matching specific patterns"""
+    if [p for p in pats if os.sep in p]:
+        ui.warn("error: patterns may not contain '%s'\n" % os.sep)
+        ui.warn("use '-i <dir>' instead\n")
+        sys.exit(1)
+    def compile(pats, head = '^', tail = os.sep, on_empty = True):
+        if not pats:
+            class c:
+                def match(self, x): return on_empty
+            return c()
+        regexp = r'%s(?:%s)%s' % (
+            head,
+            '|'.join([fnmatch.translate(os.path.normpath(os.path.normcase(p)))[:-1]
+                      for p in pats]),
+            tail)
+        print regexp
+        return re.compile(regexp)
+    exclude = compile(opts['exclude'], on_empty = False)
+    include = compile(opts['include'])
+    pat = compile([os.path.normcase(p) for p in pats], head = '', tail = '$')
+    end = '\n'
+    if opts['print0']: end = '\0'
+    if opts['rev']: node = repo.manifest.lookup(opts['rev'])
+    else: node = repo.manifest.tip()
+    manifest = repo.manifest.read(node)
+    cwd = repo.getcwd()
+    cwd_plus = cwd and (cwd + os.sep)
+    found = []
+    for f in manifest:
+        f = os.path.normcase(f)
+        if exclude.match(f) or not(include.match(f) and
+                                   f.startswith(cwd_plus) and
+                                   pat.match(os.path.basename(f))): continue
+        if opts['fullpath']: f = os.path.join(repo.root, f)
+        elif cwd: f = f[len(cwd_plus):]
+        found.append(f)
+    found.sort()
+    for f in found: ui.write(f, end)
+
 def log(ui, repo, f=None, **opts):
     """show the revision history of the repository or a single file"""
     if f:
@@ -1037,6 +1077,13 @@
                       ('b', 'base', "", 'base path')],
                      "hg import [options] <patches>"),
     "^init": (init, [], 'hg init'),
+    "locate": (locate,
+               [('0', 'print0', None, 'end records with NUL'),
+                ('f', 'fullpath', None, 'print complete paths'),
+                ('i', 'include', [], 'include path in search'),
+                ('r', 'rev', '', 'revision'),
+                ('x', 'exclude', [], 'exclude path from search')],
+               'hg locate [options] [files]'),
     "^log|history": (log,
                     [('r', 'rev', [], 'revision'),
                      ('p', 'patch', None, 'show patch')],
--- a/mercurial/hg.py	Tue Jul 05 18:15:38 2005 -0800
+++ b/mercurial/hg.py	Tue Jul 05 18:19:01 2005 -0800
@@ -508,6 +508,11 @@
         if f[0] == '/': f = f[1:]
         return filelog(self.opener, f)
 
+    def getcwd(self):
+        cwd = os.getcwd()
+        if cwd == self.root: return ''
+        return cwd[len(self.root) + 1:]
+
     def wfile(self, f, mode='r'):
         return self.wopener(f, mode)