| OLD | NEW |
| 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 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 - For file extensions that must be executable, add it to EXECUTABLE_EXTENSIONS. | 12 - For file extensions that must be executable, add it to EXECUTABLE_EXTENSIONS. |
| 13 - For file extensions that must not be executable, add it to | 13 - For file extensions that must not be executable, add it to |
| 14 NOT_EXECUTABLE_EXTENSIONS. | 14 NOT_EXECUTABLE_EXTENSIONS. |
| 15 - To ignore all the files inside a directory, add it to IGNORED_PATHS. | 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 | 16 - For file base name with ambiguous state and that should not be checked for |
| 17 shebang, add it to IGNORED_FILENAMES. | 17 shebang, add it to IGNORED_FILENAMES. |
| 18 | 18 |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 Ignores the error code or stderr. | 223 Ignores the error code or stderr. |
| 224 """ | 224 """ |
| 225 logging.debug('%s; cwd=%s' % (' '.join(cmd), cwd)) | 225 logging.debug('%s; cwd=%s' % (' '.join(cmd), cwd)) |
| 226 env = os.environ.copy() | 226 env = os.environ.copy() |
| 227 env['LANGUAGE'] = 'en_US.UTF-8' | 227 env['LANGUAGE'] = 'en_US.UTF-8' |
| 228 p = subprocess.Popen( | 228 p = subprocess.Popen( |
| 229 cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, env=env) | 229 cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, env=env) |
| 230 return p.communicate()[0] | 230 return p.communicate()[0] |
| 231 | 231 |
| 232 | 232 |
| 233 def get_svn_info(dir_path): | |
| 234 """Returns svn meta-data for a svn checkout.""" | |
| 235 if not os.path.isdir(dir_path): | |
| 236 return {} | |
| 237 out = capture(['svn', 'info', '.', '--non-interactive'], dir_path) | |
| 238 return dict(l.split(': ', 1) for l in out.splitlines() if l) | |
| 239 | |
| 240 | |
| 241 def get_svn_url(dir_path): | |
| 242 return get_svn_info(dir_path).get('URL') | |
| 243 | |
| 244 | |
| 245 def get_svn_root(dir_path): | |
| 246 """Returns the svn checkout root or None.""" | |
| 247 svn_url = get_svn_url(dir_path) | |
| 248 if not svn_url: | |
| 249 return None | |
| 250 logging.info('svn url: %s' % svn_url) | |
| 251 while True: | |
| 252 parent = os.path.dirname(dir_path) | |
| 253 if parent == dir_path: | |
| 254 return None | |
| 255 svn_url = svn_url.rsplit('/', 1)[0] | |
| 256 if svn_url != get_svn_url(parent): | |
| 257 return dir_path | |
| 258 dir_path = parent | |
| 259 | |
| 260 | |
| 261 def get_git_root(dir_path): | 233 def get_git_root(dir_path): |
| 262 """Returns the git checkout root or None.""" | 234 """Returns the git checkout root or None.""" |
| 263 root = capture(['git', 'rev-parse', '--show-toplevel'], dir_path).strip() | 235 root = capture(['git', 'rev-parse', '--show-toplevel'], dir_path).strip() |
| 264 if root: | 236 if root: |
| 265 return root | 237 return root |
| 266 | 238 |
| 267 | 239 |
| 268 def is_ignored(rel_path): | 240 def is_ignored(rel_path): |
| 269 """Returns True if rel_path is in our whitelist of files to ignore.""" | 241 """Returns True if rel_path is in our whitelist of files to ignore.""" |
| 270 rel_path = rel_path.lower() | 242 rel_path = rel_path.lower() |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 return errors | 367 return errors |
| 396 | 368 |
| 397 def list_dir(self, start_dir): | 369 def list_dir(self, start_dir): |
| 398 """Lists all the files and directory inside start_dir.""" | 370 """Lists all the files and directory inside start_dir.""" |
| 399 return sorted( | 371 return sorted( |
| 400 x for x in os.listdir(os.path.join(self.root_dir, start_dir)) | 372 x for x in os.listdir(os.path.join(self.root_dir, start_dir)) |
| 401 if not x.startswith('.') | 373 if not x.startswith('.') |
| 402 ) | 374 ) |
| 403 | 375 |
| 404 | 376 |
| 405 class ApiSvnQuick(ApiBase): | |
| 406 """Returns all files in svn-versioned directories, independent of the fact if | |
| 407 they are versionned. | |
| 408 | |
| 409 Uses svn info in each directory to determine which directories should be | |
| 410 crawled. | |
| 411 """ | |
| 412 def __init__(self, *args): | |
| 413 super(ApiSvnQuick, self).__init__(*args) | |
| 414 self.url = get_svn_url(self.root_dir) | |
| 415 | |
| 416 def check_dir(self, rel_path): | |
| 417 url = self.url + '/' + rel_path | |
| 418 if get_svn_url(os.path.join(self.root_dir, rel_path)) != url: | |
| 419 return [] | |
| 420 return super(ApiSvnQuick, self).check_dir(rel_path) | |
| 421 | |
| 422 | |
| 423 class ApiAllFilesAtOnceBase(ApiBase): | 377 class ApiAllFilesAtOnceBase(ApiBase): |
| 424 _files = None | 378 _files = None |
| 425 | 379 |
| 426 def list_dir(self, start_dir): | 380 def list_dir(self, start_dir): |
| 427 """Lists all the files and directory inside start_dir.""" | 381 """Lists all the files and directory inside start_dir.""" |
| 428 if self._files is None: | 382 if self._files is None: |
| 429 self._files = sorted(self._get_all_files()) | 383 self._files = sorted(self._get_all_files()) |
| 430 if not self.bare_output: | 384 if not self.bare_output: |
| 431 print 'Found %s files' % len(self._files) | 385 print 'Found %s files' % len(self._files) |
| 432 start_dir = start_dir[len(self.root_dir) + 1:] | 386 start_dir = start_dir[len(self.root_dir) + 1:] |
| 433 return [ | 387 return [ |
| 434 x[len(start_dir):] for x in self._files if x.startswith(start_dir) | 388 x[len(start_dir):] for x in self._files if x.startswith(start_dir) |
| 435 ] | 389 ] |
| 436 | 390 |
| 437 def _get_all_files(self): | 391 def _get_all_files(self): |
| 438 """Lists all the files and directory inside self._root_dir.""" | 392 """Lists all the files and directory inside self._root_dir.""" |
| 439 raise NotImplementedError() | 393 raise NotImplementedError() |
| 440 | 394 |
| 441 | 395 |
| 442 class ApiSvn(ApiAllFilesAtOnceBase): | |
| 443 """Returns all the subversion controlled files. | |
| 444 | |
| 445 Warning: svn ls is abnormally slow. | |
| 446 """ | |
| 447 def _get_all_files(self): | |
| 448 cmd = ['svn', 'ls', '--non-interactive', '--recursive'] | |
| 449 return ( | |
| 450 x for x in capture(cmd, self.root_dir).splitlines() | |
| 451 if not x.endswith(os.path.sep)) | |
| 452 | |
| 453 | |
| 454 class ApiGit(ApiAllFilesAtOnceBase): | 396 class ApiGit(ApiAllFilesAtOnceBase): |
| 455 def _get_all_files(self): | 397 def _get_all_files(self): |
| 456 return capture(['git', 'ls-files'], cwd=self.root_dir).splitlines() | 398 return capture(['git', 'ls-files'], cwd=self.root_dir).splitlines() |
| 457 | 399 |
| 458 | 400 |
| 459 def get_scm(dir_path, bare): | 401 def get_scm(dir_path, bare): |
| 460 """Returns a properly configured ApiBase instance.""" | 402 """Returns a properly configured ApiBase instance.""" |
| 461 cwd = os.getcwd() | 403 cwd = os.getcwd() |
| 462 root = get_svn_root(dir_path or cwd) | |
| 463 if root: | |
| 464 if not bare: | |
| 465 print('Found subversion checkout at %s' % root) | |
| 466 return ApiSvnQuick(dir_path or root, bare) | |
| 467 root = get_git_root(dir_path or cwd) | 404 root = get_git_root(dir_path or cwd) |
| 468 if root: | 405 if root: |
| 469 if not bare: | 406 if not bare: |
| 470 print('Found git repository at %s' % root) | 407 print('Found git repository at %s' % root) |
| 471 return ApiGit(dir_path or root, bare) | 408 return ApiGit(dir_path or root, bare) |
| 472 | 409 |
| 473 # Returns a non-scm aware checker. | 410 # Returns a non-scm aware checker. |
| 474 if not bare: | 411 if not bare: |
| 475 print('Failed to determine the SCM for %s' % dir_path) | 412 print('Failed to determine the SCM for %s' % dir_path) |
| 476 return ApiBase(dir_path or cwd, bare) | 413 return ApiBase(dir_path or cwd, bare) |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 print '\nFAILED\n' | 475 print '\nFAILED\n' |
| 539 print '\n'.join('%s: %s' % (e['full_path'], e['error']) for e in errors) | 476 print '\n'.join('%s: %s' % (e['full_path'], e['error']) for e in errors) |
| 540 return 1 | 477 return 1 |
| 541 if not options.bare: | 478 if not options.bare: |
| 542 print '\nSUCCESS\n' | 479 print '\nSUCCESS\n' |
| 543 return 0 | 480 return 0 |
| 544 | 481 |
| 545 | 482 |
| 546 if '__main__' == __name__: | 483 if '__main__' == __name__: |
| 547 sys.exit(main()) | 484 sys.exit(main()) |
| OLD | NEW |