Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: tools/checkperms/checkperms.py

Issue 10088002: Remove over 100 lines from checkperms.py. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add shebang count Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Makes sure files have the right permissions. 6 """Makes sure files have the right permissions.
7 7
8 Some developers have broken SCM configurations that flip the svn:executable 8 Some developers have broken SCM configurations that flip the svn:executable
9 permission on for no good reason. Unix developers who run ls --color will then 9 permission on for no good reason. Unix developers who run ls --color will then
10 see .cc files in green and get confused. 10 see .cc files in green and get confused.
11 11
12 To ignore a particular file, add it to WHITELIST_FILES. 12 - For file extensions that must be executable, add it to EXECUTABLE_EXTENSIONS.
13 To ignore a particular extension, add it to WHITELIST_EXTENSIONS. 13 - For file extensions that must not be executable, add it to
14 To ignore whatever regexps your heart desires, add it WHITELIST_REGEX. 14 NOT_EXECUTABLE_EXTENSIONS.
15 - To ignore all the files inside a directory, add it to IGNORED_PATHS.
16 - For file base name with ambiguous state and that should not be checked for
17 shebang, add it to IGNORED_FILENAMES.
18
19 Any file not matching the above will be opened and looked if it has a shebang.
20 It this doesn't match the executable bit on the file, the file will be flagged.
15 21
16 Note that all directory separators must be slashes (Unix-style) and not 22 Note that all directory separators must be slashes (Unix-style) and not
17 backslashes. All directories should be relative to the source root and all 23 backslashes. All directories should be relative to the source root and all
18 file paths should be only lowercase. 24 file paths should be only lowercase.
19 """ 25 """
20 26
27 import logging
21 import optparse 28 import optparse
22 import os 29 import os
23 import pipes
24 import re
25 import stat 30 import stat
31 import subprocess
26 import sys 32 import sys
27 33
28 #### USER EDITABLE SECTION STARTS HERE #### 34 #### USER EDITABLE SECTION STARTS HERE ####
29 35
30 # Files with these extensions are allowed to have executable permissions. 36 # Files with these extensions must have executable bit set.
31 WHITELIST_EXTENSIONS = [ 37 EXECUTABLE_EXTENSIONS = (
32 'bash', 38 'bat',
33 'bat', 39 'dll',
34 'dll', 40 'dylib',
35 'dylib', 41 'exe',
36 'exe', 42 )
37 'pl',
38 'py',
39 'rb',
40 'sed',
41 'sh',
42 ]
43 43
44 # Files that end the following paths are whitelisted too. 44 # These files must have executable bit set.
45 WHITELIST_FILES = [ 45 EXECUTABLE_PATHS = (
46 '/build/gyp_chromium', 46 # TODO(maruel): Detect ELF files.
47 '/build/linux/dump_app_syms', 47 'chrome/test/data/webrtc/linux/peerconnection_server',
48 '/build/linux/pkg-config-wrapper', 48 'chrome/installer/mac/sign_app.sh.in',
49 '/build/mac/strip_from_xcode', 49 'chrome/installer/mac/sign_versioned_dir.sh.in',
50 '/build/mac/strip_save_dsym', 50 )
51 '/chrome/installer/mac/pkg-dmg', 51
52 '/chrome/test/data/webrtc/linux/peerconnection_server', 52 # These files must not have the executable bit set. This is mainly a performance
53 '/chrome/tools/build/linux/chrome-wrapper', 53 # optimization as these files are not checked for shebang. The list was
54 '/chrome/tools/build/mac/build_app_dmg', 54 # partially generated from:
55 '/chrome/tools/build/mac/clean_up_old_versions', 55 # git ls-files | grep "\\." | sed 's/.*\.//' | sort | uniq -c | sort -b -g
56 '/chrome/tools/build/mac/dump_product_syms', 56 NON_EXECUTABLE_EXTENSIONS = (
57 '/chrome/tools/build/mac/generate_localizer', 57 '1',
58 '/chrome/tools/build/mac/make_sign_sh', 58 '3ds',
59 '/chrome/tools/build/mac/verify_order', 59 'S',
60 '/o3d/build/gyp_o3d', 60 'am',
61 '/o3d/gypbuild', 61 'applescript',
62 '/o3d/installer/linux/debian.in/rules', 62 'asm',
63 '/third_party/icu/source/runconfigureicu', 63 'c',
64 '/third_party/gold/gold32', 64 'cc',
65 '/third_party/gold/gold64', 65 'cfg',
66 '/third_party/gold/ld', 66 'chromium',
67 '/third_party/gold/ld.bfd', 67 'cpp',
68 '/third_party/lcov/bin/gendesc', 68 'crx',
69 '/third_party/lcov/bin/genhtml', 69 'cs',
70 '/third_party/lcov/bin/geninfo', 70 'css',
71 '/third_party/lcov/bin/genpng', 71 'cur',
72 '/third_party/lcov/bin/lcov', 72 'def',
73 '/third_party/lcov/bin/mcov', 73 'der',
74 '/third_party/lcov-1.9/bin/gendesc', 74 'expected',
75 '/third_party/lcov-1.9/bin/genhtml', 75 'gif',
76 '/third_party/lcov-1.9/bin/geninfo', 76 'grd',
77 '/third_party/lcov-1.9/bin/genpng', 77 'gyp',
78 '/third_party/lcov-1.9/bin/lcov', 78 'gypi',
79 '/third_party/libxml/linux/xml2-config', 79 'h',
80 '/third_party/lzma_sdk/executable/7za.exe', 80 'hh',
81 '/third_party/swig/linux/swig', 81 'htm',
82 '/third_party/tcmalloc/chromium/src/pprof', 82 'html',
83 '/tools/deep_memory_profiler/dmprof', 83 'hyph',
84 '/tools/git/post-checkout', 84 'ico',
85 '/tools/git/post-merge', 85 'idl',
86 '/tools/ld_bfd/ld', 86 'java',
87 ] 87 'jpg',
88 'js',
89 'json',
90 'm',
91 'm4',
92 'mm',
93 'mms',
94 'mock-http-headers',
95 'nmf',
96 'onc',
97 'pat',
98 'patch',
99 'pdf',
100 'pem',
101 'plist',
102 'png',
103 'proto',
104 'rc',
105 'rfx',
106 'rgs',
107 'rules',
108 'spec',
109 'sql',
110 'srpc',
111 'svg',
112 'tcl',
113 'test',
114 'tga',
115 'txt',
116 'vcproj',
117 'vsprops',
118 'webm',
119 'word',
120 'xib',
121 'xml',
122 'xtb',
123 'zip',
124 )
88 125
89 # File names that are always whitelisted. (These are all autoconf spew.) 126 # File names that are always whitelisted. (These are all autoconf spew.)
90 WHITELIST_FILENAMES = set(( 127 IGNORED_FILENAMES = set((
Lei Zhang 2012/04/27 20:51:40 Probably does not need to be a set.
M-A Ruel 2012/04/28 16:12:45 Indeed, fixed.
91 'config.guess', 128 'config.guess',
92 'config.sub', 129 'config.sub',
93 'configure', 130 'configure',
94 'depcomp', 131 'depcomp',
95 'install-sh', 132 'install-sh',
96 'missing', 133 'missing',
97 'mkinstalldirs', 134 'mkinstalldirs',
135 'naclsdk',
98 'scons', 136 'scons',
99 'naclsdk',
100 )) 137 ))
101 138
102 # File paths that contain these regexps will be whitelisted as well. 139 # File paths starting with one of these will be ignored as well.
103 WHITELIST_REGEX = [ 140 IGNORED_PATHS = (
104 re.compile('/third_party/openssl/'), 141 # TODO(maruel): Detect ELF files.
105 re.compile('/third_party/sqlite/'), 142 'chrome/test/data/webrtc/linux/peerconnection_server',
106 re.compile('/third_party/xdg-utils/'), 143 'chrome/installer/mac/sign_app.sh.in',
107 re.compile('/third_party/yasm/source/patched-yasm/config'), 144 'chrome/installer/mac/sign_versioned_dir.sh.in',
108 re.compile('/third_party/ffmpeg/tools'), 145 'native_client_sdk/src/build_tools/sdk_tools/third_party/',
109 ] 146 'out/',
147 # TODO(maruel): Fix these.
148 'third_party/android_testrunner/',
149 'third_party/closure_linter/',
150 'third_party/devscripts/licensecheck.pl.vanilla',
151 'third_party/hyphen/',
152 'third_party/jemalloc/',
153 'third_party/lcov-1.9/contrib/galaxy/conglomerate_functions.pl',
154 'third_party/lcov-1.9/contrib/galaxy/gen_makefile.sh',
155 'third_party/lcov/contrib/galaxy/conglomerate_functions.pl',
156 'third_party/lcov/contrib/galaxy/gen_makefile.sh',
157 'third_party/libevent/autogen.sh',
158 'third_party/libevent/test/test.sh',
159 'third_party/libxml/linux/xml2-config',
160 'third_party/libxml/src/ltmain.sh',
161 'third_party/mesa/',
162 'third_party/protobuf/',
163 'third_party/python_gflags/gflags.py',
164 'third_party/sqlite/',
165 'third_party/talloc/script/mksyms.sh',
166 'third_party/tcmalloc/',
167 'third_party/tlslite/setup.py',
168 )
110 169
111 #### USER EDITABLE SECTION ENDS HERE #### 170 #### USER EDITABLE SECTION ENDS HERE ####
112 171
113 WHITELIST_EXTENSIONS_REGEX = re.compile(r'\.(%s)' % 172 assert set(EXECUTABLE_EXTENSIONS) & set(NON_EXECUTABLE_EXTENSIONS) == set()
114 '|'.join(WHITELIST_EXTENSIONS)) 173
115 174
116 WHITELIST_FILES_REGEX = re.compile(r'(%s)$' % '|'.join(WHITELIST_FILES)) 175 def capture(cmd, cwd):
117 176 """Returns the output of a command.
118 # Set to true for more output. This is set by the command line options. 177
119 VERBOSE = False 178 Ignores the error code or stderr.
120 179 """
121 # Using forward slashes as directory separators, ending in a forward slash. 180 logging.debug(' '.join(cmd))
122 # Set by the command line options. 181 env = os.environ.copy()
123 BASE_DIRECTORY = '' 182 env['LANGUAGE'] = 'en_US.UTF-8'
124 183 p = subprocess.Popen(
125 # The default if BASE_DIRECTORY is not set on the command line. 184 cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, env=env)
126 DEFAULT_BASE_DIRECTORY = '../../..' 185 return p.communicate()[0]
127 186
128 # The directories which contain the sources managed by git. 187
129 GIT_SOURCE_DIRECTORY = set() 188 def get_svn_info(dir_path):
130 189 """Returns svn meta-data for a svn checkout."""
131 # The SVN repository url. 190 if not os.path.isdir(dir_path):
132 SVN_REPO_URL = '' 191 return {}
133 192 out = capture(['svn', 'info', '.', '--non-interactive'], dir_path)
134 # Whether we are using SVN or GIT. 193 return dict(l.split(': ', 1) for l in out.splitlines() if l)
135 IS_SVN = True 194
136 195
137 # Executable permission mask 196 def get_svn_url(dir_path):
138 EXECUTABLE_PERMISSION = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH 197 return get_svn_info(dir_path).get('Repository Root')
139 198
140 199
141 def IsWhiteListed(file_path): 200 def get_svn_root(dir_path):
142 """Returns True if file_path is in our whitelist of files to ignore.""" 201 """Returns the svn checkout root or None."""
143 if WHITELIST_EXTENSIONS_REGEX.match(os.path.splitext(file_path)[1]): 202 svn_url = get_svn_url(dir_path)
144 return True 203 if not svn_url:
145 if WHITELIST_FILES_REGEX.search(file_path):
146 return True
147 if os.path.basename(file_path) in WHITELIST_FILENAMES:
148 return True
149 for regex in WHITELIST_REGEX:
150 if regex.search(file_path):
151 return True
152 return False
153
154
155 def CheckFile(file_path):
156 """Checks file_path's permissions.
157
158 Args:
159 file_path: The file path to check.
160
161 Returns:
162 Either a string describing the error if there was one, or None if the file
163 checked out OK.
164 """
165 if VERBOSE:
166 print 'Checking file: ' + file_path
167
168 file_path_lower = file_path.lower()
169 if IsWhiteListed(file_path_lower):
170 return None 204 return None
171 205 logging.info('svn url: %s' % svn_url)
172 # Not whitelisted, stat the file and check permissions. 206 while True:
173 try: 207 parent = os.path.dirname(dir_path)
174 st_mode = os.stat(file_path).st_mode 208 if parent == dir_path:
175 except IOError, e: 209 return None
176 return 'Failed to stat file: %s' % e 210 if svn_url != get_svn_url(parent):
177 except OSError, e: 211 return dir_path
178 return 'Failed to stat file: %s' % e 212 dir_path = parent
179 213
180 if EXECUTABLE_PERMISSION & st_mode: 214
181 # Look if the file starts with #!/ 215 def get_git_root(dir_path):
182 with open(file_path, 'rb') as f: 216 """Returns the git checkout root or None."""
183 if f.read(3) == '#!/': 217 root = capture(['git', 'rev-parse', '--show-toplevel'], dir_path).strip()
184 # That's fine. 218 if root:
185 return None 219 return root
186 # TODO(maruel): Check that non-executable file do not start with a shebang. 220
187 error = 'Contains executable permission' 221
188 if VERBOSE: 222 def is_ignored(rel_path):
189 return '%s: %06o' % (error, st_mode) 223 """Returns True if rel_path is in our whitelist of files to ignore."""
190 return error 224 rel_path = rel_path.lower()
191 return None 225 return (
192 226 os.path.basename(rel_path) in IGNORED_FILENAMES or
Lei Zhang 2012/04/27 20:51:40 nit: this fits on the line above.
M-A Ruel 2012/04/28 16:12:45 That's on purpose, +4 alignment makes refactoring
193 227 rel_path.startswith(IGNORED_PATHS))
194 def ShouldCheckDirectory(dir_path): 228
195 """Determine if we should check the content of dir_path.""" 229
196 if not IS_SVN: 230 def must_be_executable(rel_path):
197 return dir_path in GIT_SOURCE_DIRECTORY 231 """The file name represents a file type that must have the executable bit
198 repo_url = GetSvnRepositoryRoot(dir_path) 232 set.
199 if not repo_url: 233 """
200 return False 234 return (
201 return repo_url == SVN_REPO_URL 235 os.path.splitext(rel_path)[1][1:].lower() in EXECUTABLE_EXTENSIONS or
202 236 rel_path in EXECUTABLE_PATHS)
203 237
204 def CheckDirectory(dir_path): 238
205 """Check the files in dir_path; recursively check its subdirectories.""" 239 def must_not_be_executable(rel_path):
206 # Collect a list of all files and directories to check. 240 """The file name represents a file type that must not have the executable
207 files_to_check = [] 241 bit set.
208 dirs_to_check = [] 242 """
209 success = True 243 return os.path.splitext(rel_path)[1][1:].lower() in NON_EXECUTABLE_EXTENSIONS
210 contents = os.listdir(dir_path) 244
211 for cur in contents: 245
212 full_path = os.path.join(dir_path, cur) 246 def has_executable_bit(full_path):
213 if os.path.isdir(full_path) and ShouldCheckDirectory(full_path): 247 """Returns if any executable bit is set."""
214 dirs_to_check.append(full_path) 248 permission = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
215 elif os.path.isfile(full_path): 249 return bool(permission & os.stat(full_path).st_mode)
216 files_to_check.append(full_path) 250
217 251
218 # First check all files in this directory. 252 def has_shebang(full_path):
219 for cur_file in files_to_check: 253 """Returns if the file starts with #!/.
220 file_status = CheckFile(cur_file) 254
221 if file_status is not None: 255 file_path is the absolute path to the file.
222 print 'ERROR in %s\n%s' % (cur_file, file_status) 256 """
223 success = False 257 with open(full_path, 'rb') as f:
224 258 return f.read(3) == '#!/'
225 # Next recurse into the subdirectories. 259
226 for cur_dir in dirs_to_check: 260
227 if not CheckDirectory(cur_dir): 261 class ApiBase(object):
228 success = False 262 def __init__(self, root_dir, bare_output):
229 return success 263 self.root_dir = root_dir
230 264 self.bare_output = bare_output
231 265 self.count = 0
232 def GetGitSourceDirectory(root): 266 self.count_shebang = 0
233 """Returns a set of the directories to be checked. 267
234 268 def check_file(self, rel_path):
235 Args: 269 """Checks file_path's permissions and returns an error if it is
236 root: The repository root where a .git directory must exist. 270 inconsistent.
237 271
238 Returns: 272 It is assumed that the file is not ignored by is_ignored().
239 A set of directories which contain sources managed by git. 273
240 """ 274 If the file name is matched with must_be_executable() or
241 git_source_directory = set() 275 must_not_be_executable(), only its executable bit is checked.
242 popen_out = os.popen('cd %s && git ls-files --full-name .' % 276 Otherwise, the 3 first bytes of the file are read to verify if it has a
243 pipes.quote(root)) 277 shebang and compares this with the executable bit on the file.
244 for line in popen_out: 278 """
245 dir_path = os.path.join(root, os.path.dirname(line)) 279 logging.debug('check_file(%s)' % rel_path)
246 git_source_directory.add(dir_path) 280 self.count += 1
247 git_source_directory.add(root) 281
248 return git_source_directory 282 full_path = os.path.join(self.root_dir, rel_path)
249 283 try:
250 284 bit = has_executable_bit(full_path)
251 def GetSvnRepositoryRoot(dir_path): 285 except OSError:
252 """Returns the repository root for a directory. 286 # It's faster to catch exception than call os.path.islink(). Chromium
253 287 # tree happens to have invalid symlinks under
254 Args: 288 # third_party/openssl/openssl/test/.
255 dir_path: A directory where a .svn subdirectory should exist. 289 return None
256 290
257 Returns: 291 if must_be_executable(rel_path):
258 The svn repository that contains dir_path or None. 292 if not bit:
259 """ 293 if self.bare_output:
260 svn_dir = os.path.join(dir_path, '.svn') 294 return rel_path
261 if not os.path.isdir(svn_dir): 295 return '%s: Must have executable bit set' % rel_path
262 return None 296 return
263 popen_out = os.popen('cd %s && svn info' % pipes.quote(dir_path)) 297 if must_not_be_executable(rel_path):
264 for line in popen_out: 298 if bit:
265 if line.startswith('Repository Root: '): 299 if self.bare_output:
266 return line[len('Repository Root: '):].rstrip() 300 return rel_path
267 return None 301 return '%s: Must not have executable bit set' % rel_path
268 302 return
269 303
270 def main(argv): 304 # For the others, it depends on the shebang.
305 shebang = has_shebang(full_path)
306 self.count_shebang += 1
307 if bit != shebang:
308 if self.bare_output:
309 return rel_path
310 if bit:
311 return '%s: Has executable bit but not shebang' % rel_path
312 else:
313 return '%s: Has shebang but not executable bit' % rel_path
314
315 def check_dir(self, rel_path):
316 return self.check(rel_path)
317
318 def check(self, start_dir):
319 """Check the files in start_dir, recursively check its subdirectories."""
320 errors = []
321 items = self.list_dir(start_dir)
322 logging.info('check(%s) -> %d' % (start_dir, len(items)))
323 for item in items:
324 full_path = os.path.join(self.root_dir, start_dir, item)
325 rel_path = full_path[len(self.root_dir) + 1:]
326 if is_ignored(rel_path):
327 continue
328 if os.path.isdir(full_path):
329 # Depth first.
330 errors.extend(self.check_dir(rel_path))
331 else:
332 error = self.check_file(rel_path)
333 if error:
334 errors.append(error)
335 return errors
336
337 def list_dir(self, start_dir):
338 """Lists all the files and directory inside start_dir."""
339 return sorted(
340 x for x in os.listdir(os.path.join(self.root_dir, start_dir))
341 if not x.startswith('.')
342 )
343
344
345 class ApiSvnQuick(ApiBase):
346 """Returns all files in svn-versioned directories, independent of the fact if
347 they are versionned.
348
349 Uses svn info in each directory to determine which directories should be
350 crawled.
351 """
352 def __init__(self, *args):
353 super(ApiSvnQuick, self).__init__(*args)
354 self.url = get_svn_info(self.root_dir)['Repository Root']
355
356 def check_dir(self, rel_path):
357 if get_svn_url(os.path.join(self.root_dir, rel_path)) != self.url:
358 return []
359 return super(ApiSvnQuick, self).check_dir(rel_path)
360
361
362 class ApiAllFilesAtOnceBase(ApiBase):
363 _files = None
364
365 def list_dir(self, start_dir):
366 """Lists all the files and directory inside start_dir."""
367 if self._files is None:
368 self._files = sorted(self._get_all_files())
369 if not self.bare_output:
370 print 'Found %s files' % len(self._files)
371 start_dir = start_dir[len(self.root_dir) + 1:]
372 return [
373 x[len(start_dir):] for x in self._files if x.startswith(start_dir)
374 ]
375
376 def _get_all_files(self):
377 """Lists all the files and directory inside self._root_dir."""
378 raise NotImplementedError()
379
380
381 class ApiSvn(ApiAllFilesAtOnceBase):
382 """Returns all the subversion controlled files.
383
384 Warning: svn ls is abnormally slow.
385 """
386 def _get_all_files(self):
387 cmd = ['svn', 'ls', '--non-interactive', '--recursive']
388 return (
389 x for x in capture(cmd, self.root_dir).splitlines()
390 if not x.endswith(os.path.sep))
391
392
393 class ApiGit(ApiAllFilesAtOnceBase):
394 def _get_all_files(self):
395 return capture(['git', 'ls-files'], cwd=self.root_dir).splitlines()
396
397
398 def get_scm(dir_path, bare):
399 """Returns a properly configured ApiBase instance."""
400 dir_path = os.path.abspath(dir_path)
401 root = get_svn_root(dir_path)
402 if root:
403 if not bare:
404 print('Found subversion checkout at %s' % root)
405 return ApiSvnQuick(root, bare)
406 root = get_git_root(dir_path)
407 if root:
408 if not bare:
409 print('Found git repository at %s' % root)
410 return ApiGit(root, bare)
411
412 # Returns a non-scm aware checker.
413 if not bare:
414 print('Failed to determine the SCM for %s' % dir_path)
415 return ApiBase(dir_path, bare)
416
417
418 def main():
271 usage = """Usage: python %prog [--root <root>] [tocheck] 419 usage = """Usage: python %prog [--root <root>] [tocheck]
272 tocheck Specifies the directory, relative to root, to check. This defaults 420 tocheck Specifies the directory, relative to root, to check. This defaults
273 to "." so it checks everything. 421 to "." so it checks everything.
274 422
275 Examples: 423 Examples:
276 python checkperms.py 424 python %prog
277 python checkperms.py --root /path/to/source chrome""" 425 python %prog --root /path/to/source chrome"""
278 426
279 option_parser = optparse.OptionParser(usage=usage) 427 parser = optparse.OptionParser(usage=usage)
280 option_parser.add_option('--root', dest='base_directory', 428 parser.add_option(
281 default=DEFAULT_BASE_DIRECTORY, 429 '--root',
282 help='Specifies the repository root. This defaults ' 430 help='Specifies the repository root. This defaults '
283 'to %default relative to the script file, which ' 431 'to the checkout repository root')
284 'will normally be the repository root.') 432 parser.add_option(
285 option_parser.add_option('-v', '--verbose', action='store_true', 433 '-v', '--verbose', action='count', default=0, help='Print debug logging')
286 help='Print debug logging') 434 parser.add_option(
287 options, args = option_parser.parse_args() 435 '--bare',
288 436 action='store_true',
289 global VERBOSE 437 default=False,
290 if options.verbose: 438 help='Prints the bare filename triggering the checks')
291 VERBOSE = True 439 options, args = parser.parse_args()
292 440
293 # Optional base directory of the repository. 441 levels = [logging.ERROR, logging.INFO, logging.DEBUG]
294 global BASE_DIRECTORY 442 logging.basicConfig(level=levels[min(len(levels) - 1, options.verbose)])
295 if (not options.base_directory or 443
296 options.base_directory == DEFAULT_BASE_DIRECTORY): 444 if len(args) > 1:
297 BASE_DIRECTORY = os.path.abspath( 445 parser.error('Too many arguments used')
298 os.path.join(os.path.abspath(argv[0]), DEFAULT_BASE_DIRECTORY)) 446
447 # Guess again the SCM used.
448 api = get_scm(options.root or '.', options.bare)
449 if args:
450 start_dir = args[0]
299 else: 451 else:
300 BASE_DIRECTORY = os.path.abspath(argv[2]) 452 start_dir = api.root_dir
301 453
302 # Figure out which directory we have to check. 454 errors = api.check(start_dir)
303 if not args: 455
304 # No directory to check specified, use the repository root. 456 if not options.bare:
305 start_dir = BASE_DIRECTORY 457 print 'Processed %s files, %d files where tested for shebang' % (
306 elif len(args) == 1: 458 api.count, api.count_shebang)
307 # Directory specified. Start here. It's supposed to be relative to the 459
308 # base directory. 460 if errors:
309 start_dir = os.path.abspath(os.path.join(BASE_DIRECTORY, args[0])) 461 if not options.bare:
310 else: 462 print '\nFAILED\n'
311 # More than one argument, we don't handle this. 463 print '\n'.join(errors)
312 option_parser.print_help()
313 return 1 464 return 1
314 465 if not options.bare:
315 print 'Using base directory:', BASE_DIRECTORY 466 print '\nSUCCESS\n'
316 print 'Checking directory:', start_dir
317
318 BASE_DIRECTORY = BASE_DIRECTORY.replace('\\', '/')
319 start_dir = start_dir.replace('\\', '/')
320
321 success = True
322 if os.path.exists(os.path.join(BASE_DIRECTORY, '.svn')):
323 global SVN_REPO_URL
324 SVN_REPO_URL = GetSvnRepositoryRoot(BASE_DIRECTORY)
325 if not SVN_REPO_URL:
326 print 'Cannot determine the SVN repo URL'
327 success = False
328 elif os.path.exists(os.path.join(BASE_DIRECTORY, '.git')):
329 global IS_SVN
330 IS_SVN = False
331 global GIT_SOURCE_DIRECTORY
332 GIT_SOURCE_DIRECTORY = GetGitSourceDirectory(BASE_DIRECTORY)
333 if not GIT_SOURCE_DIRECTORY:
334 print 'Cannot determine the list of GIT directories'
335 success = False
336 else:
337 print 'Cannot determine the SCM used in %s' % BASE_DIRECTORY
338 success = False
339
340 if success:
341 success = CheckDirectory(start_dir)
342 if not success:
343 print '\nFAILED\n'
344 return 1
345 print '\nSUCCESS\n'
346 return 0 467 return 0
347 468
348 469
349 if '__main__' == __name__: 470 if '__main__' == __name__:
350 sys.exit(main(sys.argv)) 471 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698