Roll android_tools to the latest.
[chromium-blink-merge.git] / native_client_sdk / src / build_tools / verify_filelist.py
blob02e3491f514dc476d2972fe3a81aef079cacdc7e
1 #!/usr/bin/env python
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 import optparse
7 import os
8 import re
9 import sys
11 import build_version
12 from build_paths import SDK_SRC_DIR, SCRIPT_DIR, OUT_DIR
14 # Add SDK make tools scripts to the python path.
15 sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
17 import getos
19 VALID_PLATFORMS = ['linux', 'mac', 'win']
20 PLATFORM_PREFIX_RE = re.compile(r'^\[([^\]]*)\](.*)$')
22 class ParseException(Exception):
23 def __init__(self, filename, line, message):
24 Exception.__init__(self)
25 self.filename = filename
26 self.line = line
27 self.message = message
29 def __str__(self):
30 return '%s:%d: %s' % (self.filename, self.line, self.message)
33 def SplitPattern(pattern):
34 match = PLATFORM_PREFIX_RE.match(pattern)
35 if not match:
36 return pattern, []
38 # platform-specific line
39 platforms = match.group(1).split(',')
41 # If this platform is included, strip the [...] part.
42 pattern = match.group(2)
43 return pattern, platforms
46 class VerifyException(Exception):
47 pass
49 class Rules(object):
50 def __init__(self, filename, platform=None, contents=None):
51 self.glob_prefixes = []
52 self.exact_filenames = set()
53 self.filename = filename
54 self.platform = platform or getos.GetPlatform()
55 self.exe_ext = '.exe' if self.platform == 'win' else ''
57 if self.platform not in VALID_PLATFORMS:
58 raise ParseException(self.filename, 1,
59 'Unknown platform %s' % self.platform)
61 if not contents:
62 with open(filename) as f:
63 contents = f.read()
65 for line_no, rule in enumerate(contents.split('\n')):
66 rule = rule.strip()
67 if rule:
68 self.ParsePattern(line_no + 1, rule)
70 def ParsePattern(self, line_no, pattern):
71 pattern, platforms = SplitPattern(pattern)
72 if platforms:
73 unknown_platforms = set(platforms) - set(VALID_PLATFORMS)
74 if unknown_platforms:
75 msg = 'Unknown platform(s) %s.' % (
76 ', '.join('"%s"' % platform for platform in unknown_platforms))
77 raise ParseException(self.filename, line_no, msg)
78 if self.platform not in platforms:
79 return
81 pattern = pattern.replace('${PLATFORM}', self.platform)
82 pattern = pattern.replace('${EXE_EXT}', self.exe_ext)
84 if '*' in pattern:
85 # glob pattern
86 # We only support * at the end.
87 if pattern.find('*') != len(pattern) - 1:
88 msg = '* is only allowed at the end of the line.'
89 raise ParseException(self.filename, line_no, msg)
91 # Remove the *
92 pattern = pattern[:-1]
93 self.glob_prefixes.append(pattern)
94 # Sort by longest prefix first; otherwise the rules:
96 # foo/*
97 # foo/bar/*
99 # Won't work properly. A file "foo/bar/baz" will match the first rule,
100 # not the second.
101 self.glob_prefixes.sort(cmp=lambda x, y: cmp(len(y), len(x)))
102 else:
103 self.exact_filenames.add(pattern)
105 def VerifyDirectoryList(self, directory_list):
106 exact_filenames_used = set()
107 glob_prefixes_used = set()
108 expected_globs = set()
109 expected_filenames = set()
110 unexpected_filenames = set()
112 for filename in directory_list:
113 if os.path.sep != '/':
114 filename = filename.replace(os.path.sep, '/')
115 if filename in self.exact_filenames:
116 exact_filenames_used.add(filename)
117 continue
119 # glob pattern
120 found_prefix = False
121 for prefix in self.glob_prefixes:
122 if filename.startswith(prefix):
123 glob_prefixes_used.add(prefix)
124 found_prefix = True
125 break
127 if not found_prefix:
128 unexpected_filenames.add(filename)
130 if len(exact_filenames_used) != len(self.exact_filenames):
131 # We looped through the directory list, so if the lengths are unequal, it
132 # must be that we expected something that isn't there.
133 expected_filenames = self.exact_filenames - exact_filenames_used
135 if len(glob_prefixes_used) != self.glob_prefixes:
136 expected_globs = set(self.glob_prefixes) - glob_prefixes_used
138 if expected_filenames or unexpected_filenames or expected_globs:
139 msg = ''
140 if unexpected_filenames:
141 msg += '>>> Unexpected filenames: <<<\n%s\n' % (
142 '\n'.join(sorted(unexpected_filenames)))
143 if expected_filenames:
144 msg += '>>> Expected filenames: <<<\n%s\n' % (
145 '\n'.join(sorted(expected_filenames)))
146 if expected_globs:
147 msg += '>>> Expected 1+ files in these directories: <<< \n%s\n' % (
148 '\n'.join(sorted(expected_globs)))
149 raise VerifyException(msg)
152 def GetDirectoryList(directory_path):
153 result = []
154 for root, _, files in os.walk(directory_path):
155 rel_root = os.path.relpath(root, directory_path)
156 if rel_root == '.':
157 rel_root = ''
158 for base_name in files:
159 result.append(os.path.join(rel_root, base_name))
160 return result
163 def Verify(rule_path, directory_path, platform=None):
164 rules = Rules(rule_path, platform=platform)
165 directory_list = GetDirectoryList(directory_path)
166 rules.VerifyDirectoryList(directory_list)
169 def SortFile(rule_path):
170 with open(rule_path) as infile:
171 lines = infile.readlines()
173 def compare(line1, line2):
174 line1 = SplitPattern(line1)[0].lower()
175 line2 = SplitPattern(line2)[0].lower()
176 return cmp(line1, line2)
178 lines.sort(compare)
179 with open(rule_path, 'w') as output:
180 for line in lines:
181 output.write(line)
184 def main(args):
185 parser = optparse.OptionParser(usage='%prog <rule file> <directory>')
186 parser.add_option('-p', '--platform',
187 help='Test with this platform, instead of the system\'s platform')
188 parser.add_option('-s', '--sort', action='store_true',
189 help='Sort the file list in place, rather than verifying the contents.')
190 options, args = parser.parse_args(args)
192 if not args:
193 args = [os.path.join(SCRIPT_DIR, 'sdk_files.list')]
195 if options.sort:
196 if not args:
197 parser.error('Expected rule file.')
198 SortFile(args[0])
199 return 0
201 if len(args) < 2:
202 version = build_version.ChromeMajorVersion()
203 args.append(os.path.join(OUT_DIR, 'pepper_%s' % version))
205 rule_path, directory_path = args
206 if options.platform:
207 if options.platform not in VALID_PLATFORMS:
208 parser.error('Unknown platform: %s' % options.platform)
209 platform = options.platform
210 else:
211 platform = getos.GetPlatform()
213 try:
214 return Verify(rule_path, directory_path, platform)
215 except ParseException, e:
216 print >> sys.stderr, 'Error parsing rules:\n', e
217 return 1
218 except VerifyException, e:
219 print >> sys.stderr, 'Error verifying file list:\n', e
220 return 1
221 return 0
224 if __name__ == '__main__':
225 sys.exit(main(sys.argv[1:]))