12da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#!/usr/bin/env python 22da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 32da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Copyright 2008 The Closure Linter Authors. All Rights Reserved. 42da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 52da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Licensed under the Apache License, Version 2.0 (the "License"); 62da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# you may not use this file except in compliance with the License. 72da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# You may obtain a copy of the License at 82da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 92da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# http://www.apache.org/licenses/LICENSE-2.0 102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Unless required by applicable law or agreed to in writing, software 122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# distributed under the License is distributed on an "AS-IS" BASIS, 132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# See the License for the specific language governing permissions and 152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# limitations under the License. 162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis"""Determines the list of files to be checked from command line arguments.""" 182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis__author__ = ('robbyw@google.com (Robert Walker)', 202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'ajp@google.com (Andy Perelson)') 212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 222da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport glob 232da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport os 242da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport re 252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 262da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport gflags as flags 272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 292da489cd246702bee5938545b18a6f710ed214bcJamie GennisFLAGS = flags.FLAGS 302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 312da489cd246702bee5938545b18a6f710ed214bcJamie Gennisflags.DEFINE_multistring( 322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'recurse', 332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis None, 342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'Recurse in to the subdirectories of the given path', 352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis short_name='r') 362da489cd246702bee5938545b18a6f710ed214bcJamie Gennisflags.DEFINE_list( 372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'exclude_directories', 382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('_demos'), 392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'Exclude the specified directories (only applicable along with -r or ' 402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis '--presubmit)', 412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis short_name='e') 422da489cd246702bee5938545b18a6f710ed214bcJamie Gennisflags.DEFINE_list( 432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'exclude_files', 442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('deps.js'), 452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'Exclude the specified files', 462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis short_name='x') 472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 492da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef MatchesSuffixes(filename, suffixes): 502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Returns whether the given filename matches one of the given suffixes. 512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Args: 532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis filename: Filename to check. 542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis suffixes: Sequence of suffixes to check. 552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Returns: 572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Whether the given filename matches one of the given suffixes. 582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis suffix = filename[filename.rfind('.'):] 602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return suffix in suffixes 612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 632da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _GetUserSpecifiedFiles(argv, suffixes): 642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Returns files to be linted, specified directly on the command line. 652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Can handle the '*' wildcard in filenames, but no other wildcards. 672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Args: 692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis argv: Sequence of command line arguments. The second and following arguments 702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis are assumed to be files that should be linted. 712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis suffixes: Expected suffixes for the file type being checked. 722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Returns: 742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis A sequence of files to be linted. 752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis files = argv[1:] or [] 772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis all_files = [] 782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis lint_files = [] 792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Perform any necessary globs. 812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for f in files: 822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if f.find('*') != -1: 832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for result in glob.glob(f): 842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis all_files.append(result) 852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis else: 862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis all_files.append(f) 872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for f in all_files: 892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if MatchesSuffixes(f, suffixes): 902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis lint_files.append(f) 912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return lint_files 922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 942da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _GetRecursiveFiles(suffixes): 952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Returns files to be checked specified by the --recurse flag. 962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Args: 982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis suffixes: Expected suffixes for the file type being checked. 992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Returns: 1012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis A list of files to be checked. 1022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 1032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis lint_files = [] 1042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Perform any request recursion 1052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if FLAGS.recurse: 1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for start in FLAGS.recurse: 1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for root, subdirs, files in os.walk(start): 1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for f in files: 1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if MatchesSuffixes(f, suffixes): 1102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis lint_files.append(os.path.join(root, f)) 1112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return lint_files 1122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1142da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef GetAllSpecifiedFiles(argv, suffixes): 1152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Returns all files specified by the user on the commandline. 1162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Args: 1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis argv: Sequence of command line arguments. The second and following arguments 1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis are assumed to be files that should be linted. 1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis suffixes: Expected suffixes for the file type 1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Returns: 1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis A list of all files specified directly or indirectly (via flags) on the 1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis command line by the user. 1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis files = _GetUserSpecifiedFiles(argv, suffixes) 1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if FLAGS.recurse: 1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis files += _GetRecursiveFiles(suffixes) 1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return FilterFiles(files) 1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef FilterFiles(files): 1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Filters the list of files to be linted be removing any excluded files. 1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Filters out files excluded using --exclude_files and --exclude_directories. 1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Args: 1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis files: Sequence of files that needs filtering. 1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Returns: 1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Filtered list of files to be linted. 1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis num_files = len(files) 1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ignore_dirs_regexs = [] 1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for ignore in FLAGS.exclude_directories: 1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ignore_dirs_regexs.append(re.compile(r'(^|[\\/])%s[\\/]' % ignore)) 1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis result_files = [] 1522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for f in files: 1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis add_file = True 1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for exclude in FLAGS.exclude_files: 1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if f.endswith('/' + exclude) or f == exclude: 1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis add_file = False 1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break 1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for ignore in ignore_dirs_regexs: 1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if ignore.search(f): 1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Break out of ignore loop so we don't add to 1612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # filtered files. 1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis add_file = False 1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break 1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if add_file: 1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Convert everything to absolute paths so we can easily remove duplicates 1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # using a set. 1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis result_files.append(os.path.abspath(f)) 1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis skipped = num_files - len(result_files) 1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if skipped: 1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis print 'Skipping %d file(s).' % skipped 1722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return set(result_files) 1742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef GetFileList(argv, file_type, suffixes): 1772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Parse the flags and return the list of files to check. 1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Args: 1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis argv: Sequence of command line arguments. 1812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis suffixes: Sequence of acceptable suffixes for the file type. 1822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Returns: 1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis The list of files to check. 1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return sorted(GetAllSpecifiedFiles(argv, suffixes)) 1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef IsEmptyArgumentList(argv): 1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return not (len(argv[1:]) or FLAGS.recurse) 191