summaryrefslogtreecommitdiffstats
path: root/build/pymake/pymake/globrelative.py
blob: 37ca28e0683a25370e1006cfd12cdbea6fe5f822 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
"""
Filename globbing like the python glob module with minor differences:

* glob relative to an arbitrary directory
* include . and ..
* check that link targets exist, not just links
"""

import os, re, fnmatch
import util

_globcheck = re.compile('[[*?]')

def hasglob(p):
    return _globcheck.search(p) is not None

def glob(fsdir, path):
    """
    Yield paths matching the path glob. Sorts as a bonus. Excludes '.' and '..'
    """

    dir, leaf = os.path.split(path)
    if dir == '':
        return globpattern(fsdir, leaf)

    if hasglob(dir):
        dirsfound = glob(fsdir, dir)
    else:
        dirsfound = [dir]

    r = []

    for dir in dirsfound:
        fspath = util.normaljoin(fsdir, dir)
        if not os.path.isdir(fspath):
            continue

        r.extend((util.normaljoin(dir, found) for found in globpattern(fspath, leaf)))

    return r

def globpattern(dir, pattern):
    """
    Return leaf names in the specified directory which match the pattern.
    """

    if not hasglob(pattern):
        if pattern == '':
            if os.path.isdir(dir):
                return ['']
            return []

        if os.path.exists(util.normaljoin(dir, pattern)):
            return [pattern]
        return []

    leaves = os.listdir(dir) + ['.', '..']

    # "hidden" filenames are a bit special
    if not pattern.startswith('.'):
        leaves = [leaf for leaf in leaves
                  if not leaf.startswith('.')]

    leaves = fnmatch.filter(leaves, pattern)
    leaves = filter(lambda l: os.path.exists(util.normaljoin(dir, l)), leaves)

    leaves.sort()
    return leaves