FcSort.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #!/usr/bin/env python
  2. import sys
  3. import os
  4. class FileContextsNode:
  5. path = None
  6. fileType = None
  7. context = None
  8. Type = None
  9. meta = None
  10. stemLen = None
  11. strLen = None
  12. Type = None
  13. def __init__(self, path, fileType, context, meta, stemLen, strLen):
  14. self.path = path
  15. self.fileType = fileType
  16. self.context = context
  17. self.meta = meta
  18. self.stemLen = stemLen
  19. self.strlen = strLen
  20. self.Type = context.split(":")[2]
  21. metaChars = frozenset(['.', '^', '$', '?', '*', '+', '|', '[', '(', '{'])
  22. escapedMetaChars = frozenset(['\.', '\^', '\$', '\?', '\*', '\+', '\|', '\[', '\(', '\{'])
  23. def getStemLen(path):
  24. global metaChars
  25. stemLen = 0
  26. i = 0
  27. while i < len(path):
  28. if path[i] == "\\":
  29. i += 1
  30. elif path[i] in metaChars:
  31. break
  32. stemLen += 1
  33. i += 1
  34. return stemLen
  35. def getIsMeta(path):
  36. global metaChars
  37. global escapedMetaChars
  38. metaCharsCount = 0
  39. escapedMetaCharsCount = 0
  40. for c in metaChars:
  41. if c in path:
  42. metaCharsCount += 1
  43. for c in escapedMetaChars:
  44. if c in path:
  45. escapedMetaCharsCount += 1
  46. return metaCharsCount > escapedMetaCharsCount
  47. def CreateNode(line):
  48. global metaChars
  49. if (len(line) == 0) or (line[0] == '#'):
  50. return None
  51. split = line.split()
  52. path = split[0].strip()
  53. context = split[-1].strip()
  54. fileType = None
  55. if len(split) == 3:
  56. fileType = split[1].strip()
  57. meta = getIsMeta(path)
  58. stemLen = getStemLen(path)
  59. strLen = len(path.replace("\\", ""))
  60. return FileContextsNode(path, fileType, context, meta, stemLen, strLen)
  61. def ReadFileContexts(files):
  62. fc = []
  63. for f in files:
  64. fd = open(f)
  65. for line in fd:
  66. node = CreateNode(line.strip())
  67. if node != None:
  68. fc.append(node)
  69. return fc
  70. # Comparator function for list.sort() based off of fc_sort.c
  71. # Compares two FileContextNodes a and b and returns 1 if a is more
  72. # specific or -1 if b is more specific.
  73. def compare(a, b):
  74. # The regex without metachars is more specific
  75. if a.meta and not b.meta:
  76. return -1
  77. if b.meta and not a.meta:
  78. return 1
  79. # The regex with longer stemlen (regex before any meta characters) is more specific.
  80. if a.stemLen < b.stemLen:
  81. return -1
  82. if b.stemLen < a.stemLen:
  83. return 1
  84. # The regex with longer string length is more specific
  85. if a.strLen < b.strLen:
  86. return -1
  87. if b.strLen < a.strLen:
  88. return 1
  89. # A regex with a fileType defined (e.g. file, dir) is more specific.
  90. if a.fileType is None and b.fileType is not None:
  91. return -1
  92. if b.fileType is None and a.fileType is not None:
  93. return 1
  94. # Regexes are equally specific.
  95. return 0
  96. def FcSort(files):
  97. for f in files:
  98. if not os.path.exists(f):
  99. sys.exit("Error: File_contexts file " + f + " does not exist\n")
  100. Fc = ReadFileContexts(files)
  101. Fc.sort(cmp=compare)
  102. return Fc
  103. if __name__ == '__main__':
  104. if len(sys.argv) < 2:
  105. sys.exit("Usage: fc_sort.py <file_contexts 1> <file_contexts 2> <file_contexts 3>")
  106. FcSorted = FcSort(sys.argv[1:])