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

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: rebase 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 = (
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', 137 )
100 )) 138
101 139 # File paths starting with one of these will be ignored as well.
102 # File paths that contain these regexps will be whitelisted as well. 140 IGNORED_PATHS = (
103 WHITELIST_REGEX = [ 141 # TODO(maruel): Detect ELF files.
104 re.compile('/third_party/openssl/'), 142 'chrome/test/data/webrtc/linux/peerconnection_server',
105 re.compile('/third_party/sqlite/'), 143 'chrome/installer/mac/sign_app.sh.in',
106 re.compile('/third_party/xdg-utils/'), 144 'chrome/installer/mac/sign_versioned_dir.sh.in',
107 re.compile('/third_party/yasm/source/patched-yasm/config'), 145 'native_client_sdk/src/build_tools/sdk_tools/third_party/',
108 re.compile('/third_party/ffmpeg/tools'), 146 'out/',
109 ] 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('%s; cwd=%s' % (' '.join(cmd), cwd))
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('URL')
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 svn_url = svn_url.rsplit('/', 1)[0]
177 except OSError, e: 211 if svn_url != get_svn_url(parent):
178 return 'Failed to stat file: %s' % e 212 return dir_path
179 213 dir_path = parent
180 if EXECUTABLE_PERMISSION & st_mode: 214
181 # Look if the file starts with #!/ 215
182 with open(file_path, 'rb') as f: 216 def get_git_root(dir_path):
183 if f.read(3) == '#!/': 217 """Returns the git checkout root or None."""
184 # That's fine. 218 root = capture(['git', 'rev-parse', '--show-toplevel'], dir_path).strip()
185 return None 219 if root:
186 # TODO(maruel): Check that non-executable file do not start with a shebang. 220 return root
187 error = 'Contains executable permission' 221
188 if VERBOSE: 222
189 return '%s: %06o' % (error, st_mode) 223 def is_ignored(rel_path):
190 return error 224 """Returns True if rel_path is in our whitelist of files to ignore."""
191 return None 225 rel_path = rel_path.lower()
192 226 return (
193 227 os.path.basename(rel_path) in IGNORED_FILENAMES or
194 def ShouldCheckDirectory(dir_path): 228 rel_path.startswith(IGNORED_PATHS))
195 """Determine if we should check the content of dir_path.""" 229
196 if not IS_SVN: 230
197 return dir_path in GIT_SOURCE_DIRECTORY 231 def must_be_executable(rel_path):
198 repo_url = GetSvnRepositoryRoot(dir_path) 232 """The file name represents a file type that must have the executable bit
199 if not repo_url: 233 set.
200 return False 234 """
201 return repo_url == SVN_REPO_URL 235 return (
202 236 os.path.splitext(rel_path)[1][1:].lower() in EXECUTABLE_EXTENSIONS or
203 237 rel_path in EXECUTABLE_PATHS)
204 def CheckDirectory(dir_path): 238
205 """Check the files in dir_path; recursively check its subdirectories.""" 239
206 # Collect a list of all files and directories to check. 240 def must_not_be_executable(rel_path):
207 files_to_check = [] 241 """The file name represents a file type that must not have the executable
208 dirs_to_check = [] 242 bit set.
209 success = True 243 """
210 contents = os.listdir(dir_path) 244 return os.path.splitext(rel_path)[1][1:].lower() in NON_EXECUTABLE_EXTENSIONS
211 for cur in contents: 245
212 full_path = os.path.join(dir_path, cur) 246
213 if os.path.isdir(full_path) and ShouldCheckDirectory(full_path): 247 def has_executable_bit(full_path):
214 dirs_to_check.append(full_path) 248 """Returns if any executable bit is set."""
215 elif os.path.isfile(full_path): 249 permission = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
216 files_to_check.append(full_path) 250 return bool(permission & os.stat(full_path).st_mode)
217 251
218 # First check all files in this directory. 252
219 for cur_file in files_to_check: 253 def has_shebang(full_path):
220 file_status = CheckFile(cur_file) 254 """Returns if the file starts with #!/.
221 if file_status is not None: 255
222 print 'ERROR in %s\n%s' % (cur_file, file_status) 256 file_path is the absolute path to the file.
223 success = False 257 """
224 258 with open(full_path, 'rb') as f:
225 # Next recurse into the subdirectories. 259 return f.read(3) == '#!/'
226 for cur_dir in dirs_to_check: 260
227 if not CheckDirectory(cur_dir): 261
228 success = False 262 class ApiBase(object):
229 return success 263 def __init__(self, root_dir, bare_output):
230 264 self.root_dir = root_dir
231 265 self.bare_output = bare_output
232 def GetGitSourceDirectory(root): 266 self.count = 0
233 """Returns a set of the directories to be checked. 267 self.count_shebang = 0
234 268
235 Args: 269 def check_file(self, rel_path):
236 root: The repository root where a .git directory must exist. 270 """Checks file_path's permissions and returns an error if it is
237 271 inconsistent.
238 Returns: 272
239 A set of directories which contain sources managed by git. 273 It is assumed that the file is not ignored by is_ignored().
240 """ 274
241 git_source_directory = set() 275 If the file name is matched with must_be_executable() or
242 popen_out = os.popen('cd %s && git ls-files --full-name .' % 276 must_not_be_executable(), only its executable bit is checked.
243 pipes.quote(root)) 277 Otherwise, the 3 first bytes of the file are read to verify if it has a
244 for line in popen_out: 278 shebang and compares this with the executable bit on the file.
245 dir_path = os.path.join(root, os.path.dirname(line)) 279 """
246 git_source_directory.add(dir_path) 280 logging.debug('check_file(%s)' % rel_path)
247 git_source_directory.add(root) 281 self.count += 1
248 return git_source_directory 282
249 283 full_path = os.path.join(self.root_dir, rel_path)
250 284 try:
251 def GetSvnRepositoryRoot(dir_path): 285 bit = has_executable_bit(full_path)
252 """Returns the repository root for a directory. 286 except OSError:
253 287 # It's faster to catch exception than call os.path.islink(). Chromium
254 Args: 288 # tree happens to have invalid symlinks under
255 dir_path: A directory where a .svn subdirectory should exist. 289 # third_party/openssl/openssl/test/.
256 290 return None
257 Returns: 291
258 The svn repository that contains dir_path or None. 292 if must_be_executable(rel_path):
259 """ 293 if not bit:
260 svn_dir = os.path.join(dir_path, '.svn') 294 if self.bare_output:
261 if not os.path.isdir(svn_dir): 295 return rel_path
262 return None 296 return '%s: Must have executable bit set' % rel_path
263 popen_out = os.popen('cd %s && svn info' % pipes.quote(dir_path)) 297 return
264 for line in popen_out: 298 if must_not_be_executable(rel_path):
265 if line.startswith('Repository Root: '): 299 if bit:
266 return line[len('Repository Root: '):].rstrip() 300 if self.bare_output:
267 return None 301 return rel_path
268 302 return '%s: Must not have executable bit set' % rel_path
269 303 return
270 def main(argv): 304
305 # For the others, it depends on the shebang.
306 shebang = has_shebang(full_path)
307 self.count_shebang += 1
308 if bit != shebang:
309 if self.bare_output:
310 return rel_path
311 if bit:
312 return '%s: Has executable bit but not shebang' % rel_path
313 else:
314 return '%s: Has shebang but not executable bit' % rel_path
315
316 def check_dir(self, rel_path):
317 return self.check(rel_path)
318
319 def check(self, start_dir):
320 """Check the files in start_dir, recursively check its subdirectories."""
321 errors = []
322 items = self.list_dir(start_dir)
323 logging.info('check(%s) -> %d' % (start_dir, len(items)))
324 for item in items:
325 full_path = os.path.join(self.root_dir, start_dir, item)
326 rel_path = full_path[len(self.root_dir) + 1:]
327 if is_ignored(rel_path):
328 continue
329 if os.path.isdir(full_path):
330 # Depth first.
331 errors.extend(self.check_dir(rel_path))
332 else:
333 error = self.check_file(rel_path)
334 if error:
335 errors.append(error)
336 return errors
337
338 def list_dir(self, start_dir):
339 """Lists all the files and directory inside start_dir."""
340 return sorted(
341 x for x in os.listdir(os.path.join(self.root_dir, start_dir))
342 if not x.startswith('.')
343 )
344
345
346 class ApiSvnQuick(ApiBase):
347 """Returns all files in svn-versioned directories, independent of the fact if
348 they are versionned.
349
350 Uses svn info in each directory to determine which directories should be
351 crawled.
352 """
353 def __init__(self, *args):
354 super(ApiSvnQuick, self).__init__(*args)
355 self.url = get_svn_url(self.root_dir)
356
357 def check_dir(self, rel_path):
358 url = self.url + '/' + rel_path
359 if get_svn_url(os.path.join(self.root_dir, rel_path)) != url:
360 return []
361 return super(ApiSvnQuick, self).check_dir(rel_path)
362
363
364 class ApiAllFilesAtOnceBase(ApiBase):
365 _files = None
366
367 def list_dir(self, start_dir):
368 """Lists all the files and directory inside start_dir."""
369 if self._files is None:
370 self._files = sorted(self._get_all_files())
371 if not self.bare_output:
372 print 'Found %s files' % len(self._files)
373 start_dir = start_dir[len(self.root_dir) + 1:]
374 return [
375 x[len(start_dir):] for x in self._files if x.startswith(start_dir)
376 ]
377
378 def _get_all_files(self):
379 """Lists all the files and directory inside self._root_dir."""
380 raise NotImplementedError()
381
382
383 class ApiSvn(ApiAllFilesAtOnceBase):
384 """Returns all the subversion controlled files.
385
386 Warning: svn ls is abnormally slow.
387 """
388 def _get_all_files(self):
389 cmd = ['svn', 'ls', '--non-interactive', '--recursive']
390 return (
391 x for x in capture(cmd, self.root_dir).splitlines()
392 if not x.endswith(os.path.sep))
393
394
395 class ApiGit(ApiAllFilesAtOnceBase):
396 def _get_all_files(self):
397 return capture(['git', 'ls-files'], cwd=self.root_dir).splitlines()
398
399
400 def get_scm(dir_path, bare):
401 """Returns a properly configured ApiBase instance."""
402 cwd = os.getcwd()
403 root = get_svn_root(dir_path or cwd)
404 if root:
405 if not bare:
406 print('Found subversion checkout at %s' % root)
407 return ApiSvnQuick(dir_path or root, bare)
408 root = get_git_root(dir_path or cwd)
409 if root:
410 if not bare:
411 print('Found git repository at %s' % root)
412 return ApiGit(dir_path or root, bare)
413
414 # Returns a non-scm aware checker.
415 if not bare:
416 print('Failed to determine the SCM for %s' % dir_path)
417 return ApiBase(dir_path or cwd, bare)
418
419
420 def main():
271 usage = """Usage: python %prog [--root <root>] [tocheck] 421 usage = """Usage: python %prog [--root <root>] [tocheck]
272 tocheck Specifies the directory, relative to root, to check. This defaults 422 tocheck Specifies the directory, relative to root, to check. This defaults
273 to "." so it checks everything. 423 to "." so it checks everything.
274 424
275 Examples: 425 Examples:
276 python checkperms.py 426 python %prog
277 python checkperms.py --root /path/to/source chrome""" 427 python %prog --root /path/to/source chrome"""
278 428
279 option_parser = optparse.OptionParser(usage=usage) 429 parser = optparse.OptionParser(usage=usage)
280 option_parser.add_option('--root', dest='base_directory', 430 parser.add_option(
281 default=DEFAULT_BASE_DIRECTORY, 431 '--root',
282 help='Specifies the repository root. This defaults ' 432 help='Specifies the repository root. This defaults '
283 'to %default relative to the script file, which ' 433 'to the checkout repository root')
284 'will normally be the repository root.') 434 parser.add_option(
285 option_parser.add_option('-v', '--verbose', action='store_true', 435 '-v', '--verbose', action='count', default=0, help='Print debug logging')
286 help='Print debug logging') 436 parser.add_option(
287 options, args = option_parser.parse_args() 437 '--bare',
288 438 action='store_true',
289 global VERBOSE 439 default=False,
290 if options.verbose: 440 help='Prints the bare filename triggering the checks')
291 VERBOSE = True 441 options, args = parser.parse_args()
292 442
293 # Optional base directory of the repository. 443 levels = [logging.ERROR, logging.INFO, logging.DEBUG]
294 global BASE_DIRECTORY 444 logging.basicConfig(level=levels[min(len(levels) - 1, options.verbose)])
295 if (not options.base_directory or 445
296 options.base_directory == DEFAULT_BASE_DIRECTORY): 446 if len(args) > 1:
297 BASE_DIRECTORY = os.path.abspath( 447 parser.error('Too many arguments used')
298 os.path.join(os.path.abspath(argv[0]), DEFAULT_BASE_DIRECTORY)) 448
449 if options.root:
450 options.root = os.path.abspath(options.root)
451
452 api = get_scm(options.root, options.bare)
453 if args:
454 start_dir = args[0]
299 else: 455 else:
300 BASE_DIRECTORY = os.path.abspath(argv[2]) 456 start_dir = api.root_dir
301 457
302 # Figure out which directory we have to check. 458 errors = api.check(start_dir)
303 if not args: 459
304 # No directory to check specified, use the repository root. 460 if not options.bare:
305 start_dir = BASE_DIRECTORY 461 print 'Processed %s files, %d files where tested for shebang' % (
306 elif len(args) == 1: 462 api.count, api.count_shebang)
307 # Directory specified. Start here. It's supposed to be relative to the 463
308 # base directory. 464 if errors:
309 start_dir = os.path.abspath(os.path.join(BASE_DIRECTORY, args[0])) 465 if not options.bare:
310 else: 466 print '\nFAILED\n'
311 # More than one argument, we don't handle this. 467 print '\n'.join(errors)
312 option_parser.print_help()
313 return 1 468 return 1
314 469 if not options.bare:
315 print 'Using base directory:', BASE_DIRECTORY 470 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 471 return 0
347 472
348 473
349 if '__main__' == __name__: 474 if '__main__' == __name__:
350 sys.exit(main(sys.argv)) 475 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