OLD | NEW |
1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
| 5 ANDROID_WHITELISTED_LICENSES = [ |
| 6 'A(pple )?PSL 2(\.0)?', |
| 7 'Apache( Version)? 2(\.0)?', |
| 8 '(New )?([23]-Clause )?BSD( [23]-Clause)?( with advertising clause)?', |
| 9 'L?GPL ?v?2(\.[01])?( or later)?', |
| 10 'MIT(/X11)?(-like)?', |
| 11 'MPL 1\.1 ?/ ?GPL 2(\.0)? ?/ ?LGPL 2\.1', |
| 12 'MPL 2(\.0)?', |
| 13 'Microsoft Limited Public License', |
| 14 'Microsoft Permissive License', |
| 15 'Public Domain', |
| 16 'Python', |
| 17 'SGI Free Software License B', |
| 18 'University of Illinois\/NCSA Open Source', |
| 19 'X11', |
| 20 ] |
| 21 |
| 22 def LicenseIsCompatibleWithAndroid(input_api, license): |
| 23 regex = '^(%s)$' % '|'.join(ANDROID_WHITELISTED_LICENSES) |
| 24 tokens = \ |
| 25 [x.strip() for x in input_api.re.split(' and |,', license) if len(x) > 0] |
| 26 has_compatible_license = False |
| 27 for token in tokens: |
| 28 if input_api.re.match(regex, token, input_api.re.IGNORECASE): |
| 29 has_compatible_license = True |
| 30 break |
| 31 return has_compatible_license |
| 32 |
5 def _CheckThirdPartyReadmesUpdated(input_api, output_api): | 33 def _CheckThirdPartyReadmesUpdated(input_api, output_api): |
6 """ | 34 """ |
7 Checks to make sure that README.chromium files are properly updated | 35 Checks to make sure that README.chromium files are properly updated |
8 when dependancies in third_party are modified. | 36 when dependancies in third_party are modified. |
9 """ | 37 """ |
10 readmes = [] | 38 readmes = [] |
11 files = [] | 39 files = [] |
12 errors = [] | 40 errors = [] |
13 for f in input_api.AffectedFiles(): | 41 for f in input_api.AffectedFiles(): |
14 local_path = f.LocalPath() | 42 local_path = f.LocalPath() |
(...skipping 14 matching lines...) Expand all Loading... |
29 name_pattern = input_api.re.compile( | 57 name_pattern = input_api.re.compile( |
30 r'^Name: [a-zA-Z0-9_\-\. \(\)]+\r?$', | 58 r'^Name: [a-zA-Z0-9_\-\. \(\)]+\r?$', |
31 input_api.re.IGNORECASE | input_api.re.MULTILINE) | 59 input_api.re.IGNORECASE | input_api.re.MULTILINE) |
32 shortname_pattern = input_api.re.compile( | 60 shortname_pattern = input_api.re.compile( |
33 r'^Short Name: [a-zA-Z0-9_\-\.]+\r?$', | 61 r'^Short Name: [a-zA-Z0-9_\-\.]+\r?$', |
34 input_api.re.IGNORECASE | input_api.re.MULTILINE) | 62 input_api.re.IGNORECASE | input_api.re.MULTILINE) |
35 version_pattern = input_api.re.compile( | 63 version_pattern = input_api.re.compile( |
36 r'^Version: [a-zA-Z0-9_\-\.:]+\r?$', | 64 r'^Version: [a-zA-Z0-9_\-\.:]+\r?$', |
37 input_api.re.IGNORECASE | input_api.re.MULTILINE) | 65 input_api.re.IGNORECASE | input_api.re.MULTILINE) |
38 release_pattern = input_api.re.compile( | 66 release_pattern = input_api.re.compile( |
39 r'^Security Critical: (yes)|(no)\r?$', | 67 r'^Security Critical: (yes|no)\r?$', |
40 input_api.re.IGNORECASE | input_api.re.MULTILINE) | 68 input_api.re.IGNORECASE | input_api.re.MULTILINE) |
41 license_pattern = input_api.re.compile( | 69 license_pattern = input_api.re.compile( |
42 r'^License: .+\r?$', | 70 r'^License: (.+)\r?$', |
| 71 input_api.re.IGNORECASE | input_api.re.MULTILINE) |
| 72 license_android_compatible_pattern = input_api.re.compile( |
| 73 r'^License Android Compatible: (yes|no)\r?$', |
43 input_api.re.IGNORECASE | input_api.re.MULTILINE) | 74 input_api.re.IGNORECASE | input_api.re.MULTILINE) |
44 | 75 |
45 for f in readmes: | 76 for f in readmes: |
46 if 'D' in f.Action(): | 77 if 'D' in f.Action(): |
47 _IgnoreIfDeleting(input_api, output_api, f, errors) | 78 _IgnoreIfDeleting(input_api, output_api, f, errors) |
48 continue | 79 continue |
49 | 80 |
50 contents = input_api.ReadFile(f) | 81 contents = input_api.ReadFile(f) |
51 if (not shortname_pattern.search(contents) | 82 if (not shortname_pattern.search(contents) |
52 and not name_pattern.search(contents)): | 83 and not name_pattern.search(contents)): |
53 errors.append(output_api.PresubmitError( | 84 errors.append(output_api.PresubmitError( |
54 'Third party README files should contain either a \'Short Name\' or\n' | 85 'Third party README files should contain either a \'Short Name\' or\n' |
55 'a \'Name\' which is the name under which the package is\n' | 86 'a \'Name\' which is the name under which the package is\n' |
56 'distributed. Check README.chromium.template for details.', | 87 'distributed. Check README.chromium.template for details.', |
57 [f])) | 88 [f])) |
58 if not version_pattern.search(contents): | 89 if not version_pattern.search(contents): |
59 errors.append(output_api.PresubmitError( | 90 errors.append(output_api.PresubmitError( |
60 'Third party README files should contain a \'Version\' field.\n' | 91 'Third party README files should contain a \'Version\' field.\n' |
61 'If the package is not versioned or the version is not known\n' | 92 'If the package is not versioned or the version is not known\n' |
62 'list the version as \'unknown\'.\n' | 93 'list the version as \'unknown\'.\n' |
63 'Check README.chromium.template for details.', | 94 'Check README.chromium.template for details.', |
64 [f])) | 95 [f])) |
65 if not release_pattern.search(contents): | 96 if not release_pattern.search(contents): |
66 errors.append(output_api.PresubmitError( | 97 errors.append(output_api.PresubmitError( |
67 'Third party README files should contain a \'Security Critical\'\n' | 98 'Third party README files should contain a \'Security Critical\'\n' |
68 'field. This field specifies whether the package is built with\n' | 99 'field. This field specifies whether the package is built with\n' |
69 'Chromium. Check README.chromium.template for details.', | 100 'Chromium. Check README.chromium.template for details.', |
70 [f])) | 101 [f])) |
71 if not license_pattern.search(contents): | 102 license_match = license_pattern.search(contents) |
| 103 if not license_match: |
72 errors.append(output_api.PresubmitError( | 104 errors.append(output_api.PresubmitError( |
73 'Third party README files should contain a \'License\' field.\n' | 105 'Third party README files should contain a \'License\' field.\n' |
74 'This field specifies the license used by the package. Check\n' | 106 'This field specifies the license used by the package. Check\n' |
75 'README.chromium.template for details.', | 107 'README.chromium.template for details.', |
76 [f])) | 108 [f])) |
| 109 elif not LicenseIsCompatibleWithAndroid(input_api, license_match.group(1)) \ |
| 110 and not license_android_compatible_pattern.search(contents): |
| 111 errors.append(output_api.PresubmitPromptWarning( |
| 112 'Cannot determine whether specified license is compatible with\n' + |
| 113 'the Android licensing requirements. Please check that the license\n' + |
| 114 'name is spelled according to third_party/PRESUBMIT.py. Please see\n' + |
| 115 'README.chromium.template for details.', |
| 116 [f])) |
77 return errors | 117 return errors |
78 | 118 |
79 | 119 |
80 def _IgnoreIfDeleting(input_api, output_api, affected_file, errors): | 120 def _IgnoreIfDeleting(input_api, output_api, affected_file, errors): |
81 third_party_dir = input_api.os_path.dirname(affected_file.LocalPath()) | 121 third_party_dir = input_api.os_path.dirname(affected_file.LocalPath()) |
82 for f in input_api.AffectedFiles(): | 122 for f in input_api.AffectedFiles(): |
83 if f.LocalPath().startswith(third_party_dir): | 123 if f.LocalPath().startswith(third_party_dir): |
84 if 'D' not in f.Action(): | 124 if 'D' not in f.Action(): |
85 errors.append(output_api.PresubmitError( | 125 errors.append(output_api.PresubmitError( |
86 'Third party README should only be removed when the whole\n' | 126 'Third party README should only be removed when the whole\n' |
87 'directory is being removed.\n', [f, affected_file])) | 127 'directory is being removed.\n', [f, affected_file])) |
88 | 128 |
89 | 129 |
90 def CheckChangeOnUpload(input_api, output_api): | 130 def CheckChangeOnUpload(input_api, output_api): |
91 results = [] | 131 results = [] |
92 results.extend(_CheckThirdPartyReadmesUpdated(input_api, output_api)) | 132 results.extend(_CheckThirdPartyReadmesUpdated(input_api, output_api)) |
93 return results | 133 return results |
OLD | NEW |