| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/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 """Checks third-party licenses for the purposes of the Android WebView build. | 6 """Checks third-party licenses for the purposes of the Android WebView build. |
| 7 | 7 |
| 8 The Android tree includes a snapshot of Chromium in order to power the system | 8 The Android tree includes a snapshot of Chromium in order to power the system |
| 9 WebView. This tool checks that all code uses open-source licenses compatible | 9 WebView. This tool checks that all code uses open-source licenses compatible |
| 10 with Android, and that we meet the requirements of those licenses. It can also | 10 with Android, and that we meet the requirements of those licenses. It can also |
| 11 be used to generate an Android NOTICE file for the third-party code. | 11 be used to generate an Android NOTICE file for the third-party code. |
| 12 | 12 |
| 13 It makes use of src/tools/licenses.py and the README.chromium files on which | 13 It makes use of src/tools/licenses.py and the README.chromium files on which |
| 14 it depends. It also makes use of a data file, third_party_files_whitelist.txt, | 14 it depends. It also makes use of a data file, third_party_files_whitelist.txt, |
| 15 which whitelists indicidual files which contain third-party code but which | 15 which whitelists indicidual files which contain third-party code but which |
| 16 aren't in a third-party directory with a README.chromium file. | 16 aren't in a third-party directory with a README.chromium file. |
| 17 """ | 17 """ |
| 18 | 18 |
| 19 import glob | 19 import glob |
| 20 import imp |
| 20 import optparse | 21 import optparse |
| 21 import os | 22 import os |
| 22 import re | 23 import re |
| 23 import subprocess | 24 import subprocess |
| 24 import sys | 25 import sys |
| 25 import textwrap | 26 import textwrap |
| 26 | 27 |
| 27 | 28 |
| 28 REPOSITORY_ROOT = os.path.abspath(os.path.join( | 29 REPOSITORY_ROOT = os.path.abspath(os.path.join( |
| 29 os.path.dirname(__file__), '..', '..')) | 30 os.path.dirname(__file__), '..', '..')) |
| 30 | 31 |
| 32 # Import third_party/PRESUBMIT.py via imp to avoid importing a random |
| 33 # PRESUBMIT.py from $PATH, also make sure we don't generate a .pyc file. |
| 34 sys.dont_write_bytecode = True |
| 35 third_party = \ |
| 36 imp.load_source('PRESUBMIT', \ |
| 37 os.path.join(REPOSITORY_ROOT, 'third_party', 'PRESUBMIT.py')) |
| 38 |
| 31 sys.path.append(os.path.join(REPOSITORY_ROOT, 'tools')) | 39 sys.path.append(os.path.join(REPOSITORY_ROOT, 'tools')) |
| 32 import licenses | 40 import licenses |
| 33 | 41 |
| 34 import known_issues | 42 import known_issues |
| 35 | 43 |
| 44 class InputApi(object): |
| 45 def __init__(self): |
| 46 self.re = re |
| 47 |
| 36 def GetIncompatibleDirectories(): | 48 def GetIncompatibleDirectories(): |
| 37 """Gets a list of third-party directories which use licenses incompatible | 49 """Gets a list of third-party directories which use licenses incompatible |
| 38 with Android. This is used by the snapshot tool. | 50 with Android. This is used by the snapshot tool. |
| 39 Returns: | 51 Returns: |
| 40 A list of directories. | 52 A list of directories. |
| 41 """ | 53 """ |
| 42 | 54 |
| 43 whitelist = [ | |
| 44 'A(pple )?PSL 2(\.0)?', | |
| 45 'Apache( Version)? 2(\.0)?', | |
| 46 '(New )?([23]-Clause )?BSD( [23]-Clause)?( with advertising clause)?', | |
| 47 'L?GPL ?v?2(\.[01])?( or later)?', | |
| 48 'MIT(/X11)?(-like)?', | |
| 49 'MPL 1\.1 ?/ ?GPL 2(\.0)? ?/ ?LGPL 2\.1', | |
| 50 'MPL 2(\.0)?', | |
| 51 'Microsoft Limited Public License', | |
| 52 'Microsoft Permissive License', | |
| 53 'Public Domain', | |
| 54 'Python', | |
| 55 'SGI Free Software License B', | |
| 56 'University of Illinois\/NCSA Open Source', | |
| 57 'X11', | |
| 58 ] | |
| 59 regex = '^(%s)$' % '|'.join(whitelist) | |
| 60 result = [] | 55 result = [] |
| 61 for directory in _FindThirdPartyDirs(): | 56 for directory in _FindThirdPartyDirs(): |
| 62 if directory in known_issues.KNOWN_ISSUES: | 57 if directory in known_issues.KNOWN_ISSUES: |
| 63 result.append(directory) | 58 result.append(directory) |
| 64 continue | 59 continue |
| 65 try: | 60 try: |
| 66 metadata = licenses.ParseDir(directory, REPOSITORY_ROOT, | 61 metadata = licenses.ParseDir(directory, REPOSITORY_ROOT, |
| 67 require_license_file=False) | 62 require_license_file=False) |
| 68 except licenses.LicenseError as e: | 63 except licenses.LicenseError as e: |
| 69 print 'Got LicenseError while scanning ' + directory | 64 print 'Got LicenseError while scanning ' + directory |
| 70 raise | 65 raise |
| 71 if metadata.get('License Android Compatible', 'no').upper() == 'YES': | 66 if metadata.get('License Android Compatible', 'no').upper() == 'YES': |
| 72 continue | 67 continue |
| 73 license = re.split(' [Ll]icenses?$', metadata['License'])[0] | 68 license = re.split(' [Ll]icenses?$', metadata['License'])[0] |
| 74 tokens = [x.strip() for x in re.split(' and |,', license) if len(x) > 0] | 69 if not third_party.LicenseIsCompatibleWithAndroid(InputApi(), license): |
| 75 for token in tokens: | 70 result.append(directory) |
| 76 if not re.match(regex, token, re.IGNORECASE): | |
| 77 result.append(directory) | |
| 78 break | |
| 79 return result | 71 return result |
| 80 | 72 |
| 81 def GetUnknownIncompatibleDirectories(): | 73 def GetUnknownIncompatibleDirectories(): |
| 82 """Gets a list of third-party directories which use licenses incompatible | 74 """Gets a list of third-party directories which use licenses incompatible |
| 83 with Android which are not present in the known_issues.py file. | 75 with Android which are not present in the known_issues.py file. |
| 84 This is used by the AOSP bot. | 76 This is used by the AOSP bot. |
| 85 Returns: | 77 Returns: |
| 86 A list of directories. | 78 A list of directories. |
| 87 """ | 79 """ |
| 88 incompatible_directories = frozenset(GetIncompatibleDirectories()) | 80 incompatible_directories = frozenset(GetIncompatibleDirectories()) |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 print ("Incompatibly licensed directories found:\n" + | 322 print ("Incompatibly licensed directories found:\n" + |
| 331 "\n".join(sorted(incompatible_directories))) | 323 "\n".join(sorted(incompatible_directories))) |
| 332 return ScanResult.Errors | 324 return ScanResult.Errors |
| 333 return ScanResult.Ok | 325 return ScanResult.Ok |
| 334 | 326 |
| 335 parser.print_help() | 327 parser.print_help() |
| 336 return ScanResult.Errors | 328 return ScanResult.Errors |
| 337 | 329 |
| 338 if __name__ == '__main__': | 330 if __name__ == '__main__': |
| 339 sys.exit(main()) | 331 sys.exit(main()) |
| OLD | NEW |