huangcm
2025-07-01 676035278781360996553c427a12bf358249ebf7
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python
import sys
import os
 
class FileContextsNode:
    path = None
    fileType = None
    context = None
    Type = None
    meta = None
    stemLen = None
    strLen = None
    Type = None
    def __init__(self, path, fileType, context, meta, stemLen, strLen):
        self.path = path
        self.fileType = fileType
        self.context = context
        self.meta = meta
        self.stemLen = stemLen
        self.strlen = strLen
        self.Type = context.split(":")[2]
 
metaChars = frozenset(['.', '^', '$', '?', '*', '+', '|', '[', '(', '{'])
escapedMetaChars = frozenset(['\.', '\^', '\$', '\?', '\*', '\+', '\|', '\[', '\(', '\{'])
 
def getStemLen(path):
    global metaChars
    stemLen = 0
    i = 0
    while i < len(path):
        if path[i] == "\\":
            i += 1
        elif path[i] in metaChars:
            break
        stemLen += 1
        i += 1
    return stemLen
 
 
def getIsMeta(path):
    global metaChars
    global escapedMetaChars
    metaCharsCount = 0
    escapedMetaCharsCount = 0
    for c in metaChars:
        if c in path:
            metaCharsCount += 1
    for c in escapedMetaChars:
        if c in path:
            escapedMetaCharsCount += 1
    return metaCharsCount > escapedMetaCharsCount
 
def CreateNode(line):
    global metaChars
    if (len(line) == 0) or (line[0] == '#'):
        return None
 
    split = line.split()
    path = split[0].strip()
    context = split[-1].strip()
    fileType = None
    if len(split) == 3:
        fileType = split[1].strip()
    meta = getIsMeta(path)
    stemLen = getStemLen(path)
    strLen = len(path.replace("\\", ""))
 
    return FileContextsNode(path, fileType, context, meta, stemLen, strLen)
 
def ReadFileContexts(files):
    fc = []
    for f in files:
        fd = open(f)
        for line in fd:
            node = CreateNode(line.strip())
            if node != None:
                fc.append(node)
    return fc
 
# Comparator function for list.sort() based off of fc_sort.c
# Compares two FileContextNodes a and b and returns 1 if a is more
# specific or -1 if b is more specific.
def compare(a, b):
    # The regex without metachars is more specific
    if a.meta and not b.meta:
        return -1
    if b.meta and not a.meta:
        return 1
 
    # The regex with longer stemlen (regex before any meta characters) is more specific.
    if a.stemLen < b.stemLen:
        return -1
    if b.stemLen < a.stemLen:
        return 1
 
    # The regex with longer string length is more specific
    if a.strLen < b.strLen:
        return -1
    if b.strLen < a.strLen:
        return 1
 
    # A regex with a fileType defined (e.g. file, dir) is more specific.
    if a.fileType is None and b.fileType is not None:
        return -1
    if b.fileType is None and a.fileType is not None:
        return 1
 
    # Regexes are equally specific.
    return 0
 
def FcSort(files):
    for f in files:
        if not os.path.exists(f):
            sys.exit("Error: File_contexts file " + f + " does not exist\n")
 
    Fc = ReadFileContexts(files)
    Fc.sort(cmp=compare)
 
    return Fc
 
if __name__ == '__main__':
    if len(sys.argv) < 2:
        sys.exit("Usage: fc_sort.py <file_contexts 1> <file_contexts 2> <file_contexts 3>")
 
    FcSorted = FcSort(sys.argv[1:])