1#
2# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 The SCons Foundation
3#
4# Permission is hereby granted, free of charge, to any person obtaining
5# a copy of this software and associated documentation files (the
6# "Software"), to deal in the Software without restriction, including
7# without limitation the rights to use, copy, modify, merge, publish,
8# distribute, sublicense, and/or sell copies of the Software, and to
9# permit persons to whom the Software is furnished to do so, subject to
10# the following conditions:
11#
12# The above copyright notice and this permission notice shall be included
13# in all copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23__revision__ = "src/engine/SCons/Scanner/Dir.py issue-2856:2676:d23b7a2f45e8 2012/08/05 15:38:28 garyo"
24
25import SCons.Node.FS
26import SCons.Scanner
27
28def only_dirs(nodes):
29    is_Dir = lambda n: isinstance(n.disambiguate(), SCons.Node.FS.Dir)
30    return list(filter(is_Dir, nodes))
31
32def DirScanner(**kw):
33    """Return a prototype Scanner instance for scanning
34    directories for on-disk files"""
35    kw['node_factory'] = SCons.Node.FS.Entry
36    kw['recursive'] = only_dirs
37    return SCons.Scanner.Base(scan_on_disk, "DirScanner", **kw)
38
39def DirEntryScanner(**kw):
40    """Return a prototype Scanner instance for "scanning"
41    directory Nodes for their in-memory entries"""
42    kw['node_factory'] = SCons.Node.FS.Entry
43    kw['recursive'] = None
44    return SCons.Scanner.Base(scan_in_memory, "DirEntryScanner", **kw)
45
46skip_entry = {}
47
48skip_entry_list = [
49   '.',
50   '..',
51   '.sconsign',
52   # Used by the native dblite.py module.
53   '.sconsign.dblite',
54   # Used by dbm and dumbdbm.
55   '.sconsign.dir',
56   # Used by dbm.
57   '.sconsign.pag',
58   # Used by dumbdbm.
59   '.sconsign.dat',
60   '.sconsign.bak',
61   # Used by some dbm emulations using Berkeley DB.
62   '.sconsign.db',
63]
64
65for skip in skip_entry_list:
66    skip_entry[skip] = 1
67    skip_entry[SCons.Node.FS._my_normcase(skip)] = 1
68
69do_not_scan = lambda k: k not in skip_entry
70
71def scan_on_disk(node, env, path=()):
72    """
73    Scans a directory for on-disk files and directories therein.
74
75    Looking up the entries will add these to the in-memory Node tree
76    representation of the file system, so all we have to do is just
77    that and then call the in-memory scanning function.
78    """
79    try:
80        flist = node.fs.listdir(node.abspath)
81    except (IOError, OSError):
82        return []
83    e = node.Entry
84    for f in  filter(do_not_scan, flist):
85        # Add ./ to the beginning of the file name so if it begins with a
86        # '#' we don't look it up relative to the top-level directory.
87        e('./' + f)
88    return scan_in_memory(node, env, path)
89
90def scan_in_memory(node, env, path=()):
91    """
92    "Scans" a Node.FS.Dir for its in-memory entries.
93    """
94    try:
95        entries = node.entries
96    except AttributeError:
97        # It's not a Node.FS.Dir (or doesn't look enough like one for
98        # our purposes), which can happen if a target list containing
99        # mixed Node types (Dirs and Files, for example) has a Dir as
100        # the first entry.
101        return []
102    entry_list = sorted(filter(do_not_scan, list(entries.keys())))
103    return [entries[n] for n in entry_list]
104
105# Local Variables:
106# tab-width:4
107# indent-tabs-mode:nil
108# End:
109# vim: set expandtab tabstop=4 shiftwidth=4:
110