190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#!/usr/bin/env python 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)# Copyright (c) 2013 The Chromium Authors. All rights reserved. 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)# found in the LICENSE file. 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import optparse 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import os 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import re 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import sys 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)from build_paths import SDK_SRC_DIR 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)# Add SDK make tools scripts to the python path. 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)sys.path.append(os.path.join(SDK_SRC_DIR, 'tools')) 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import getos 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)VALID_PLATFORMS = ['linux', 'mac', 'win'] 197dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochPLATFORM_PREFIX_RE = re.compile(r'^\[([^\]]*)\](.*)$') 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class ParseException(Exception): 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) def __init__(self, filename, line, message): 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Exception.__init__(self) 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) self.filename = filename 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) self.line = line 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) self.message = message 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) def __str__(self): 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return '%s:%d: %s' % (self.filename, self.line, self.message) 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochdef SplitPattern(pattern): 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch match = PLATFORM_PREFIX_RE.match(pattern) 347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if not match: 357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return pattern, [] 367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch # platform-specific line 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch platforms = match.group(1).split(',') 397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch # If this platform is included, strip the [...] part. 417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch pattern = match.group(2) 427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return pattern, platforms 437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class VerifyException(Exception): 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pass 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class Rules(object): 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch def __init__(self, filename, platform=None, contents=None): 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) self.glob_prefixes = [] 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) self.exact_filenames = set() 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) self.filename = filename 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch self.platform = platform or getos.GetPlatform() 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch self.exe_ext = '.exe' if self.platform == 'win' else '' 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if self.platform not in VALID_PLATFORMS: 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch raise ParseException(self.filename, 1, 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 'Unknown platform %s' % self.platform) 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if not contents: 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) with open(filename) as f: 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) contents = f.read() 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for line_no, rule in enumerate(contents.split('\n')): 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) rule = rule.strip() 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if rule: 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) self.ParsePattern(line_no + 1, rule) 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) def ParsePattern(self, line_no, pattern): 707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch pattern, platforms = SplitPattern(pattern) 717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if platforms: 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unknown_platforms = set(platforms) - set(VALID_PLATFORMS) 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if unknown_platforms: 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msg = 'Unknown platform(s) %s.' % ( 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ', '.join('"%s"' % platform for platform in unknown_platforms)) 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) raise ParseException(self.filename, line_no, msg) 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if self.platform not in platforms: 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pattern = pattern.replace('${PLATFORM}', self.platform) 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pattern = pattern.replace('${EXE_EXT}', self.exe_ext) 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if '*' in pattern: 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # glob pattern 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # We only support * at the end. 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if pattern.find('*') != len(pattern) - 1: 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msg = '* is only allowed at the end of the line.' 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) raise ParseException(self.filename, line_no, msg) 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # Remove the * 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pattern = pattern[:-1] 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) self.glob_prefixes.append(pattern) 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) else: 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) self.exact_filenames.add(pattern) 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) def VerifyDirectoryList(self, directory_list): 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) exact_filenames_used = set() 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glob_prefixes_used = set() 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) expected_globs = set() 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) expected_filenames = set() 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unexpected_filenames = set() 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for filename in directory_list: 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if os.path.sep != '/': 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) filename = filename.replace(os.path.sep, '/') 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if filename in self.exact_filenames: 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) exact_filenames_used.add(filename) 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # glob pattern 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) found_prefix = False 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for prefix in self.glob_prefixes: 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if filename.startswith(prefix): 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glob_prefixes_used.add(prefix) 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) found_prefix = True 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if not found_prefix: 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unexpected_filenames.add(filename) 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if len(exact_filenames_used) != len(self.exact_filenames): 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # We looped through the directory list, so if the lengths are unequal, it 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # must be that we expected something that isn't there. 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) expected_filenames = self.exact_filenames - exact_filenames_used 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if len(glob_prefixes_used) != self.glob_prefixes: 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) expected_globs = set(self.glob_prefixes) - glob_prefixes_used 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if expected_filenames or unexpected_filenames or expected_globs: 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msg = '' 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if unexpected_filenames: 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msg += '>>> Unexpected filenames: <<<\n%s\n' % ( 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) '\n'.join(sorted(unexpected_filenames))) 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if expected_filenames: 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msg += '>>> Expected filenames: <<<\n%s\n' % ( 13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) '\n'.join(sorted(expected_filenames))) 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if expected_globs: 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msg += '>>> Expected 1+ files in these directories: <<< \n%s\n' % ( 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) '\n'.join(sorted(expected_globs))) 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) raise VerifyException(msg) 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)def GetDirectoryList(directory_path): 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) result = [] 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for root, _, files in os.walk(directory_path): 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) rel_root = os.path.relpath(root, directory_path) 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if rel_root == '.': 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) rel_root = '' 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for base_name in files: 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) result.append(os.path.join(rel_root, base_name)) 15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return result 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochdef Verify(rule_path, directory_path, platform=None): 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rules = Rules(rule_path, platform=platform) 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) directory_list = GetDirectoryList(directory_path) 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) rules.VerifyDirectoryList(directory_list) 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochdef SortFile(rule_path): 1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch with open(rule_path) as infile: 1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch lines = infile.readlines() 1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def compare(line1, line2): 1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch line1 = SplitPattern(line1)[0].lower() 1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch line2 = SplitPattern(line2)[0].lower() 1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return cmp(line1, line2) 1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch lines.sort(compare) 1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch with open(rule_path, 'w') as output: 1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for line in lines: 1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch output.write(line) 1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)def main(args): 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) parser = optparse.OptionParser(usage='%prog <rule file> <directory>') 17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) parser.add_option('-p', '--platform', 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) help='Test with this platform, instead of the system\'s platform') 1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch parser.add_option('-s', '--sort', action='store_true', 1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch help='Sort the file list in place, rather than verifying the contents.') 18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) options, args = parser.parse_args(args) 1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if options.sort: 1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if not args: 1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch parser.error('Expected rule file.') 1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SortFile(args[0]) 1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return 0 1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if len(args) != 2: 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) parser.error('Expected rule file and directory.') 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) rule_path, directory_path = args 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if options.platform: 19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if options.platform not in VALID_PLATFORMS: 19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) parser.error('Unknown platform: %s' % options.platform) 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) platform = options.platform 19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) else: 19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) platform = getos.GetPlatform() 19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) try: 201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return Verify(rule_path, directory_path, platform) 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) except ParseException, e: 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) print >> sys.stderr, 'Error parsing rules:\n', e 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 1 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) except VerifyException, e: 20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) print >> sys.stderr, 'Error verifying file list:\n', e 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 1 20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0 20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)if __name__ == '__main__': 21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sys.exit(main(sys.argv[1:])) 213