Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(506)

Side by Side Diff: android_webview/tools/webview_licenses.py

Issue 12209034: [Android WebView] Make 3rd party licenses checker to turn bot red (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Return error code if cmdline args are invalid Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | build/android/buildbot/buildbot_functions.sh » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 if metadata.get('License Android Compatible', 'no') == 'yes': 67 if metadata.get('License Android Compatible', 'no') == 'yes':
68 continue 68 continue
69 license = re.split(' [Ll]icenses?$', metadata['License'])[0] 69 license = re.split(' [Ll]icenses?$', metadata['License'])[0]
70 tokens = [x.strip() for x in re.split(' and |,', license) if len(x) > 0] 70 tokens = [x.strip() for x in re.split(' and |,', license) if len(x) > 0]
71 for token in tokens: 71 for token in tokens:
72 if not re.match(regex, token, re.IGNORECASE): 72 if not re.match(regex, token, re.IGNORECASE):
73 result.append(directory) 73 result.append(directory)
74 break 74 break
75 return result 75 return result
76 76
77 SCAN_OK = 0
78 SCAN_WARNINGS = 1 << 0
79 SCAN_ERRORS = 1 << 1
mkosiba (inactive) 2013/02/06 15:40:49 It seems these are exclusive, not flags, so how ab
mnaganov (inactive) 2013/02/06 16:42:17 Fixed, thanks!
77 80
78 def _CheckLicenseHeaders(excluded_dirs_list, whitelisted_files): 81 def _CheckLicenseHeaders(excluded_dirs_list, whitelisted_files):
79 """Checks that all files which are not in a listed third-party directory, 82 """Checks that all files which are not in a listed third-party directory,
80 and which do not use the standard Chromium license, are whitelisted. 83 and which do not use the standard Chromium license, are whitelisted.
81 Args: 84 Args:
82 excluded_dirs_list: The list of directories to exclude from scanning. 85 excluded_dirs_list: The list of directories to exclude from scanning.
83 whitelisted_files: The whitelist of files. 86 whitelisted_files: The whitelist of files.
84 Returns: 87 Returns:
85 True if all files with non-standard license headers are whitelisted and the 88 SCAN_OK if all files with non-standard license headers are whitelisted and
mkosiba (inactive) 2013/02/06 15:40:49 if you go with the suggestion above you could say
mnaganov (inactive) 2013/02/06 16:42:17 The interpretation of results are method-dependent
mkosiba (inactive) 2013/02/06 16:54:51 ah, ok then.
86 whitelist contains no stale entries, otherwise false. 89 the whitelist contains no stale entries;
90 SCAN_WARNINGS if there are stale entries;
91 SCAN_ERRORS if new non-whitelisted entries found.
87 """ 92 """
88 93
89 excluded_dirs_list = [d for d in excluded_dirs_list if not 'third_party' in d] 94 excluded_dirs_list = [d for d in excluded_dirs_list if not 'third_party' in d]
90 # Using a commond pattern for third-partyies makes the ignore regexp shorter 95 # Using a commond pattern for third-partyies makes the ignore regexp shorter
91 excluded_dirs_list.append('third_party') 96 excluded_dirs_list.append('third_party')
92 # VCS dirs 97 # VCS dirs
93 excluded_dirs_list.append('.git') 98 excluded_dirs_list.append('.git')
94 excluded_dirs_list.append('.svn') 99 excluded_dirs_list.append('.svn')
95 # Build output 100 # Build output
96 excluded_dirs_list.append('out/Debug') 101 excluded_dirs_list.append('out/Debug')
(...skipping 25 matching lines...) Expand all
122 for l in lines: 127 for l in lines:
123 entries = l.split('\t') 128 entries = l.split('\t')
124 if entries[1] == "GENERATED FILE": 129 if entries[1] == "GENERATED FILE":
125 continue 130 continue
126 copyrights = entries[1].split(' / ') 131 copyrights = entries[1].split(' / ')
127 for c in copyrights: 132 for c in copyrights:
128 if c and not allowed_copyrights_re.match(c): 133 if c and not allowed_copyrights_re.match(c):
129 offending_files.append(os.path.normpath(entries[0])) 134 offending_files.append(os.path.normpath(entries[0]))
130 break 135 break
131 136
132 all_files_valid = True
133 unknown = set(offending_files) - set(whitelisted_files) 137 unknown = set(offending_files) - set(whitelisted_files)
134 if unknown: 138 if unknown:
135 print 'The following files contain a third-party license but are not in ' \ 139 print 'The following files contain a third-party license but are not in ' \
136 'a listed third-party directory and are not whitelisted. You must ' \ 140 'a listed third-party directory and are not whitelisted. You must ' \
137 'add the following files to the whitelist.\n%s' % \ 141 'add the following files to the whitelist.\n%s' % \
138 '\n'.join(sorted(unknown)) 142 '\n'.join(sorted(unknown))
139 all_files_valid = False
140 143
141 stale = set(whitelisted_files) - set(offending_files) 144 stale = set(whitelisted_files) - set(offending_files)
142 if stale: 145 if stale:
143 print 'The following files are whitelisted unnecessarily. You must ' \ 146 print 'The following files are whitelisted unnecessarily. You must ' \
144 ' remove the following files from the whitelist.\n%s' % \ 147 ' remove the following files from the whitelist.\n%s' % \
145 '\n'.join(sorted(stale)) 148 '\n'.join(sorted(stale))
146 all_files_valid = False
147 149
148 return all_files_valid 150 return SCAN_ERRORS if unknown else (SCAN_WARNINGS if stale else SCAN_OK)
mkosiba (inactive) 2013/02/06 15:40:49 I think it would be slightly clearer to make this
mnaganov (inactive) 2013/02/06 16:42:17 Done.
149 151
150 152
151 def _ReadFile(path): 153 def _ReadFile(path):
152 """Reads a file from disk. 154 """Reads a file from disk.
153 Args: 155 Args:
154 path: The path of the file to read, relative to the root of the repository. 156 path: The path of the file to read, relative to the root of the repository.
155 Returns: 157 Returns:
156 The contents of the file as a string. 158 The contents of the file as a string.
157 """ 159 """
158 160
(...skipping 20 matching lines...) Expand all
179 # The llvm-build doesn't exist for non-clang builder 181 # The llvm-build doesn't exist for non-clang builder
180 os.path.join('third_party', 'llvm-build'), 182 os.path.join('third_party', 'llvm-build'),
181 # Binaries doesn't apply to android 183 # Binaries doesn't apply to android
182 os.path.join('third_party', 'widevine'), 184 os.path.join('third_party', 'widevine'),
183 ] 185 ]
184 third_party_dirs = licenses.FindThirdPartyDirs(prune_paths, REPOSITORY_ROOT) 186 third_party_dirs = licenses.FindThirdPartyDirs(prune_paths, REPOSITORY_ROOT)
185 return licenses.FilterDirsWithFiles(third_party_dirs, REPOSITORY_ROOT) 187 return licenses.FilterDirsWithFiles(third_party_dirs, REPOSITORY_ROOT)
186 188
187 189
188 def _Scan(): 190 def _Scan():
189 """Checks that license meta-data is present for all third-party code. 191 """Checks that license meta-data is present for all third-party code and
192 that all non third-party code doesn't contain external copyrighted code.
190 Returns: 193 Returns:
191 Whether the check succeeded. 194 SCAN_OK if everything is in order;
195 SCAN_WARNINGS if there are non-fatal problems (e.g. stale whitelist entries)
196 SCAN_ERRORS otherwise.
192 """ 197 """
193 198
194 third_party_dirs = _FindThirdPartyDirs() 199 third_party_dirs = _FindThirdPartyDirs()
195 200
196 # First, check designated third-party directories using src/tools/licenses.py. 201 # First, check designated third-party directories using src/tools/licenses.py.
197 all_licenses_valid = True 202 all_licenses_valid = True
198 for path in sorted(third_party_dirs): 203 for path in sorted(third_party_dirs):
199 try: 204 try:
200 licenses.ParseDir(path, REPOSITORY_ROOT) 205 licenses.ParseDir(path, REPOSITORY_ROOT)
201 except licenses.LicenseError, e: 206 except licenses.LicenseError, e:
202 if not (path in known_issues.KNOWN_ISSUES): 207 if not (path in known_issues.KNOWN_ISSUES):
203 print 'Got LicenseError "%s" while scanning %s' % (e, path) 208 print 'Got LicenseError "%s" while scanning %s' % (e, path)
204 all_licenses_valid = False 209 all_licenses_valid = False
205 210
206 # Second, check for non-standard license text. 211 # Second, check for non-standard license text.
207 files_data = _ReadFile(os.path.join('android_webview', 'tools', 212 files_data = _ReadFile(os.path.join('android_webview', 'tools',
208 'third_party_files_whitelist.txt')) 213 'third_party_files_whitelist.txt'))
209 whitelisted_files = [] 214 whitelisted_files = []
210 for line in files_data.splitlines(): 215 for line in files_data.splitlines():
211 match = re.match(r'([^#\s]+)', line) 216 match = re.match(r'([^#\s]+)', line)
212 if match: 217 if match:
213 whitelisted_files.append(match.group(1)) 218 whitelisted_files.append(match.group(1))
214 return _CheckLicenseHeaders(third_party_dirs, whitelisted_files) \ 219 licenses_check = _CheckLicenseHeaders(third_party_dirs, whitelisted_files)
215 and all_licenses_valid 220
221 return licenses_check if all_licenses_valid else SCAN_ERRORS
216 222
217 223
218 def GenerateNoticeFile(): 224 def GenerateNoticeFile():
219 """Generates the contents of an Android NOTICE file for the third-party code. 225 """Generates the contents of an Android NOTICE file for the third-party code.
220 This is used by the snapshot tool. 226 This is used by the snapshot tool.
221 Returns: 227 Returns:
222 The contents of the NOTICE file. 228 The contents of the NOTICE file.
223 """ 229 """
224 230
225 third_party_dirs = _FindThirdPartyDirs() 231 third_party_dirs = _FindThirdPartyDirs()
(...skipping 22 matching lines...) Expand all
248 254
249 parser = optparse.OptionParser(formatter=FormatterWithNewLines(), 255 parser = optparse.OptionParser(formatter=FormatterWithNewLines(),
250 usage='%prog [options]') 256 usage='%prog [options]')
251 parser.description = (__doc__ + 257 parser.description = (__doc__ +
252 '\nCommands:\n' \ 258 '\nCommands:\n' \
253 ' scan Check licenses.\n' \ 259 ' scan Check licenses.\n' \
254 ' notice Generate Android NOTICE file on stdout') 260 ' notice Generate Android NOTICE file on stdout')
255 (options, args) = parser.parse_args() 261 (options, args) = parser.parse_args()
256 if len(args) != 1: 262 if len(args) != 1:
257 parser.print_help() 263 parser.print_help()
258 return 1 264 return SCAN_ERRORS
259 265
260 if args[0] == 'scan': 266 if args[0] == 'scan':
261 if _Scan(): 267 scan_result = _Scan()
268 if scan_result == SCAN_OK:
262 print 'OK!' 269 print 'OK!'
263 return 0 270 return scan_result
264 else:
265 return 1
266 elif args[0] == 'notice': 271 elif args[0] == 'notice':
267 print GenerateNoticeFile() 272 print GenerateNoticeFile()
268 return 0 273 return SCAN_OK
269 274
270 parser.print_help() 275 parser.print_help()
271 return 1 276 return SCAN_ERRORS
272 277
273 if __name__ == '__main__': 278 if __name__ == '__main__':
274 sys.exit(main()) 279 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | build/android/buildbot/buildbot_functions.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698