Index: tools/checkperms/checkperms.py |
diff --git a/tools/checkperms/checkperms.py b/tools/checkperms/checkperms.py |
index 9395c00d2765334ff24ecc8bbc3d534e458cddb3..ffb08043c160a392b5b303a5f6c09e6f2cd21287 100755 |
--- a/tools/checkperms/checkperms.py |
+++ b/tools/checkperms/checkperms.py |
@@ -25,6 +25,7 @@ backslashes. All directories should be relative to the source root and all |
file paths should be only lowercase. |
""" |
+import json |
import logging |
import optparse |
import os |
@@ -298,9 +299,9 @@ def has_shebang_or_is_elf(full_path): |
return (data[:3] == '#!/', data == '\x7fELF') |
-def check_file(root_path, rel_path, bare_output): |
+def check_file(root_path, rel_path): |
"""Checks the permissions of the file whose path is root_path + rel_path and |
- returns an error if it is inconsistent. |
+ returns an error if it is inconsistent. Returns None on success. |
It is assumed that the file is not ignored by is_ignored(). |
@@ -310,6 +311,12 @@ def check_file(root_path, rel_path, bare_output): |
shebang or ELF header and compares this with the executable bit on the file. |
""" |
full_path = os.path.join(root_path, rel_path) |
+ def result_dict(error): |
+ return { |
+ 'error': error, |
+ 'full_path': full_path, |
+ 'rel_path': rel_path, |
+ } |
try: |
bit = has_executable_bit(full_path) |
except OSError: |
@@ -320,40 +327,26 @@ def check_file(root_path, rel_path, bare_output): |
if must_be_executable(rel_path): |
if not bit: |
- if bare_output: |
- return full_path |
- return '%s: Must have executable bit set' % full_path |
+ return result_dict('Must have executable bit set') |
return |
if must_not_be_executable(rel_path): |
if bit: |
- if bare_output: |
- return full_path |
- return '%s: Must not have executable bit set' % full_path |
+ return result_dict('Must not have executable bit set') |
return |
# For the others, it depends on the file header. |
(shebang, elf) = has_shebang_or_is_elf(full_path) |
if bit != (shebang or elf): |
- if bare_output: |
- return full_path |
if bit: |
- return '%s: Has executable bit but not shebang or ELF header' % full_path |
+ return result_dict('Has executable bit but not shebang or ELF header') |
if shebang: |
- return '%s: Has shebang but not executable bit' % full_path |
- return '%s: Has ELF header but not executable bit' % full_path |
+ return result_dict('Has shebang but not executable bit') |
+ return result_dict('Has ELF header but not executable bit') |
-def check_files(root, files, bare_output): |
- errors = [] |
- for rel_path in files: |
- if is_ignored(rel_path): |
- continue |
- |
- error = check_file(root, rel_path, bare_output) |
- if error: |
- errors.append(error) |
- |
- return errors |
+def check_files(root, files): |
+ gen = (check_file(root, f) for f in files if not is_ignored(f)) |
+ return filter(None, gen) |
class ApiBase(object): |
@@ -371,7 +364,7 @@ class ApiBase(object): |
not must_not_be_executable(rel_path)): |
self.count_read_header += 1 |
- return check_file(self.root_dir, rel_path, self.bare_output) |
+ return check_file(self.root_dir, rel_path) |
def check_dir(self, rel_path): |
return self.check(rel_path) |
@@ -502,6 +495,7 @@ Examples: |
'--file', action='append', dest='files', |
help='Specifics a list of files to check the permissions of. Only these ' |
'files will be checked') |
+ parser.add_option('--json', help='Path to JSON output file') |
options, args = parser.parse_args() |
levels = [logging.ERROR, logging.INFO, logging.DEBUG] |
@@ -514,26 +508,29 @@ Examples: |
options.root = os.path.abspath(options.root) |
if options.files: |
- errors = check_files(options.root, options.files, options.bare) |
- print '\n'.join(errors) |
- return bool(errors) |
+ # --file implies --bare (for PRESUBMIT.py). |
+ options.bare = True |
- api = get_scm(options.root, options.bare) |
- if args: |
- start_dir = args[0] |
+ errors = check_files(options.root, options.files) |
else: |
- start_dir = api.root_dir |
+ api = get_scm(options.root, options.bare) |
+ start_dir = args[0] if args else api.root_dir |
+ errors = api.check(start_dir) |
- errors = api.check(start_dir) |
+ if not options.bare: |
+ print('Processed %s files, %d files where tested for shebang/ELF ' |
+ 'header' % (api.count, api.count_read_header)) |
- if not options.bare: |
- print 'Processed %s files, %d files where tested for shebang/ELF header' % ( |
- api.count, api.count_read_header) |
+ if options.json: |
+ with open(options.json, 'w') as f: |
+ json.dump(errors, f) |
if errors: |
- if not options.bare: |
+ if options.bare: |
+ print '\n'.join(e['full_path'] for e in errors) |
+ else: |
print '\nFAILED\n' |
- print '\n'.join(errors) |
+ print '\n'.join('%s: %s' % (e['full_path'], e['error']) for e in errors) |
return 1 |
if not options.bare: |
print '\nSUCCESS\n' |