Chromium Code Reviews| 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 that all files contain proper licensing information.""" | 6 """Makes sure that all files contain proper licensing information.""" |
| 7 | 7 |
| 8 | 8 |
| 9 import json | |
| 9 import optparse | 10 import optparse |
| 10 import os.path | 11 import os.path |
| 11 import subprocess | 12 import subprocess |
| 12 import sys | 13 import sys |
| 13 | 14 |
| 14 | 15 |
| 15 def PrintUsage(): | 16 def PrintUsage(): |
| 16 print """Usage: python checklicenses.py [--root <root>] [tocheck] | 17 print """Usage: python checklicenses.py [--root <root>] [tocheck] |
| 17 --root Specifies the repository root. This defaults to "../.." relative | 18 --root Specifies the repository root. This defaults to "../.." relative |
| 18 to the script file. This will be correct given the normal location | 19 to the script file. This will be correct given the normal location |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 415 print stdout | 416 print stdout |
| 416 print '--------- end licensecheck stdout ---------' | 417 print '--------- end licensecheck stdout ---------' |
| 417 if licensecheck.returncode != 0 or stderr: | 418 if licensecheck.returncode != 0 or stderr: |
| 418 print '----------- licensecheck stderr -----------' | 419 print '----------- licensecheck stderr -----------' |
| 419 print stderr | 420 print stderr |
| 420 print '--------- end licensecheck stderr ---------' | 421 print '--------- end licensecheck stderr ---------' |
| 421 print "\nFAILED\n" | 422 print "\nFAILED\n" |
| 422 return 1 | 423 return 1 |
| 423 | 424 |
| 424 used_suppressions = set() | 425 used_suppressions = set() |
| 426 errors = [] | |
| 425 | 427 |
| 426 success = True | |
| 427 for line in stdout.splitlines(): | 428 for line in stdout.splitlines(): |
| 428 filename, license = line.split(':', 1) | 429 filename, license = line.split(':', 1) |
| 429 filename = os.path.relpath(filename.strip(), options.base_directory) | 430 filename = os.path.relpath(filename.strip(), options.base_directory) |
| 430 | 431 |
| 431 # All files in the build output directory are generated one way or another. | 432 # All files in the build output directory are generated one way or another. |
| 432 # There's no need to check them. | 433 # There's no need to check them. |
| 433 if filename.startswith('out/'): | 434 if filename.startswith('out/'): |
| 434 continue | 435 continue |
| 435 | 436 |
| 436 # For now we're just interested in the license. | 437 # For now we're just interested in the license. |
| 437 license = license.replace('*No copyright*', '').strip() | 438 license = license.replace('*No copyright*', '').strip() |
| 438 | 439 |
| 439 # Skip generated files. | 440 # Skip generated files. |
| 440 if 'GENERATED FILE' in license: | 441 if 'GENERATED FILE' in license: |
| 441 continue | 442 continue |
| 442 | 443 |
| 443 if license in WHITELISTED_LICENSES: | 444 if license in WHITELISTED_LICENSES: |
| 444 continue | 445 continue |
| 445 | 446 |
| 446 if not options.ignore_suppressions: | 447 if not options.ignore_suppressions: |
| 447 matched_prefixes = [ | 448 matched_prefixes = [ |
| 448 prefix for prefix in PATH_SPECIFIC_WHITELISTED_LICENSES | 449 prefix for prefix in PATH_SPECIFIC_WHITELISTED_LICENSES |
| 449 if filename.startswith(prefix) and | 450 if filename.startswith(prefix) and |
| 450 license in PATH_SPECIFIC_WHITELISTED_LICENSES[prefix]] | 451 license in PATH_SPECIFIC_WHITELISTED_LICENSES[prefix]] |
| 451 if matched_prefixes: | 452 if matched_prefixes: |
| 452 used_suppressions.update(set(matched_prefixes)) | 453 used_suppressions.update(set(matched_prefixes)) |
| 453 continue | 454 continue |
| 454 | 455 |
| 455 print "'%s' has non-whitelisted license '%s'" % (filename, license) | 456 errors.append({'filename': filename, 'license': license}) |
| 456 success = False | |
| 457 | 457 |
| 458 if success: | 458 if options.json: |
| 459 print "\nSUCCESS\n" | 459 with open(options.json, 'w') as f: |
|
M-A Ruel
2014/06/05 15:01:47
'wb'
Paweł Hajdan Jr.
2014/06/05 15:38:14
For now using 'w' for consistency with other json
| |
| 460 json.dump(errors, f) | |
| 460 | 461 |
| 461 if not len(args): | 462 if errors: |
| 462 unused_suppressions = set( | 463 for error in errors: |
| 463 PATH_SPECIFIC_WHITELISTED_LICENSES.keys()).difference(used_suppressions) | 464 print "'%s' has non-whitelisted license '%s'" % ( |
| 464 if unused_suppressions: | 465 error['filename'], error['license']) |
| 465 print "\nNOTE: unused suppressions detected:\n" | |
| 466 print '\n'.join(unused_suppressions) | |
| 467 | |
| 468 return 0 | |
| 469 else: | |
| 470 print "\nFAILED\n" | 466 print "\nFAILED\n" |
| 471 print "Please read", | 467 print "Please read", |
| 472 print "http://www.chromium.org/developers/adding-3rd-party-libraries" | 468 print "http://www.chromium.org/developers/adding-3rd-party-libraries" |
| 473 print "for more info how to handle the failure." | 469 print "for more info how to handle the failure." |
| 474 print | 470 print |
| 475 print "Please respect OWNERS of checklicenses.py. Changes violating" | 471 print "Please respect OWNERS of checklicenses.py. Changes violating" |
| 476 print "this requirement may be reverted." | 472 print "this requirement may be reverted." |
| 477 | 473 |
| 478 # Do not print unused suppressions so that above message is clearly | 474 # Do not print unused suppressions so that above message is clearly |
| 479 # visible and gets proper attention. Too much unrelated output | 475 # visible and gets proper attention. Too much unrelated output |
| 480 # would be distracting and make the important points easier to miss. | 476 # would be distracting and make the important points easier to miss. |
| 481 | 477 |
| 482 return 1 | 478 return 1 |
| 483 | 479 |
| 480 print "\nSUCCESS\n" | |
| 481 | |
| 482 if not len(args): | |
| 483 unused_suppressions = set( | |
| 484 PATH_SPECIFIC_WHITELISTED_LICENSES.keys()).difference(used_suppressions) | |
|
M-A Ruel
2014/06/05 15:01:47
.keys() is unnecessary, it creates a list when a g
Paweł Hajdan Jr.
2014/06/05 15:38:14
Done.
| |
| 485 if unused_suppressions: | |
| 486 print "\nNOTE: unused suppressions detected:\n" | |
| 487 print '\n'.join(unused_suppressions) | |
| 488 | |
| 489 return 0 | |
| 490 | |
| 484 | 491 |
| 485 def main(): | 492 def main(): |
| 486 default_root = os.path.abspath( | 493 default_root = os.path.abspath( |
| 487 os.path.join(os.path.dirname(__file__), '..', '..')) | 494 os.path.join(os.path.dirname(__file__), '..', '..')) |
| 488 option_parser = optparse.OptionParser() | 495 option_parser = optparse.OptionParser() |
| 489 option_parser.add_option('--root', default=default_root, | 496 option_parser.add_option('--root', default=default_root, |
| 490 dest='base_directory', | 497 dest='base_directory', |
| 491 help='Specifies the repository root. This defaults ' | 498 help='Specifies the repository root. This defaults ' |
| 492 'to "../.." relative to the script file, which ' | 499 'to "../.." relative to the script file, which ' |
| 493 'will normally be the repository root.') | 500 'will normally be the repository root.') |
| 494 option_parser.add_option('-v', '--verbose', action='store_true', | 501 option_parser.add_option('-v', '--verbose', action='store_true', |
| 495 default=False, help='Print debug logging') | 502 default=False, help='Print debug logging') |
| 496 option_parser.add_option('--ignore-suppressions', | 503 option_parser.add_option('--ignore-suppressions', |
| 497 action='store_true', | 504 action='store_true', |
| 498 default=False, | 505 default=False, |
| 499 help='Ignore path-specific license whitelist.') | 506 help='Ignore path-specific license whitelist.') |
| 507 option_parser.add_option('--json', help='Path to JSON output file') | |
| 500 options, args = option_parser.parse_args() | 508 options, args = option_parser.parse_args() |
| 501 return check_licenses(options, args) | 509 return check_licenses(options, args) |
| 502 | 510 |
| 503 | 511 |
| 504 if '__main__' == __name__: | 512 if '__main__' == __name__: |
| 505 sys.exit(main()) | 513 sys.exit(main()) |
| OLD | NEW |