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

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

Issue 10816041: Add a tool to check license compatibility with Android (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed nit Created 8 years, 4 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 | « android_webview/tools/third_party_files_whitelist.txt ('k') | chrome/version.h.in » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
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
4 # found in the LICENSE file.
5
6 """Checks third-party licenses for the purposes of the Android WebView build.
7
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
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.
12
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,
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.
17 """
18
19 import optparse
20 import os
21 import re
22 import subprocess
23 import sys
24 import textwrap
25
26
27 REPOSITORY_ROOT = os.path.abspath(os.path.join(
28 os.path.dirname(__file__), '..', '..'))
29
30 sys.path.append(os.path.join(REPOSITORY_ROOT, 'tools'))
31 import licenses
32
33
34 def _CheckLicenseHeaders(directory_list, whitelisted_files):
35 """Checks that all files which are not in a listed third-party directory,
36 and which do not use the standard Chromium license, are whitelisted.
37 Args:
38 directory_list: The list of directories.
39 whitelisted_files: The whitelist of files.
40 Returns:
41 True if all files with non-standard license headers are whitelisted and the
42 whitelist contains no stale entries, otherwise false.
43 """
44
45 # Matches one of ...
46 # - '[Cc]opyright', but not when followed by
47 # ' 20[0-9][0-9] The Chromium Authors.', with optional (c) and date range
48 # - '([Cc]) (19|20)[0-9][0-9]', but not when preceeded by the word copyright,
49 # as this is handled above
50 regex = '[Cc]opyright(?!( \(c\))? 20[0-9][0-9](-20[0-9][0-9])? ' \
51 'The Chromium Authors\. All rights reserved\.)' \
52 '|' \
53 '(?<!(pyright |opyright))\([Cc]\) (19|20)[0-9][0-9]'
54
55 args = ['grep',
56 '-rPlI',
57 '--exclude-dir', 'third_party',
58 '--exclude-dir', 'out',
59 '--exclude-dir', '.git',
60 regex,
61 '.']
62 p = subprocess.Popen(args=args, cwd=REPOSITORY_ROOT, stdout=subprocess.PIPE)
63 files = p.communicate()[0].splitlines()
64
65 directory_list = directory_list[:]
66 # Ignore these tools.
67 directory_list.append('android_webview/tools/')
68 # This is a build intermediate directory.
69 directory_list.append('chrome/app/theme/google_chrome/')
70 # This is a test output directory.
71 directory_list.append('data/page_cycler/')
72 # 'Copyright' appears in strings.
73 directory_list.append('chrome/app/resources/')
74
75 # Exclude files under listed directories and some known offenders.
76 offending_files = []
77 for x in files:
78 x = os.path.normpath(x)
79 is_in_listed_directory = False
80 for y in directory_list:
81 if x.startswith(y):
82 is_in_listed_directory = True
83 break
84 if not is_in_listed_directory:
85 offending_files.append(x)
86
87 all_files_valid = True
88 unknown = set(offending_files) - set(whitelisted_files)
89 if unknown:
90 print 'The following files contain a third-party license but are not in ' \
91 'a listed third-party directory and are not whitelisted. You must ' \
92 'add the following files to the whitelist.\n%s' % \
93 '\n'.join(sorted(unknown))
94 all_files_valid = False
95
96 stale = set(whitelisted_files) - set(offending_files)
97 if stale:
98 print 'The following files are whitelisted unnecessarily. You must ' \
99 ' remove the following files from the whitelist.\n%s' % \
100 '\n'.join(sorted(stale))
101 all_files_valid = False
102
103 return all_files_valid
104
105
106 def _ReadFile(path):
107 """Reads a file from disk.
108 Args:
109 path: The path of the file to read, relative to the root of the repository.
110 Returns:
111 The contents of the file as a string.
112 """
113
114 return open(os.path.join(REPOSITORY_ROOT, path), 'rb').read()
115
116
117 def _FindThirdPartyDirs():
118 """Gets the list of third-party directories.
119 Returns:
120 The list of third-party directories.
121 """
122
123 prune_paths = [
124 # Placeholder directory, no third-party code.
125 os.path.join('third_party', 'adobe'),
126 # Apache 2.0 license. See
127 # https://code.google.com/p/chromium/issues/detail?id=140478.
128 os.path.join('third_party', 'bidichecker'),
129 ]
130 return licenses.FindThirdPartyDirs(prune_paths)
131
132
133 def _Scan():
134 """Checks that license meta-data is present for all third-party code.
135 Returns:
136 Whether the check succeeded.
137 """
138
139 third_party_dirs = _FindThirdPartyDirs()
140
141 # First, check designated third-party directories using src/tools/licenses.py.
142 all_licenses_valid = True
143 for path in sorted(third_party_dirs):
144 try:
145 licenses.ParseDir(path)
146 except licenses.LicenseError, e:
147 print 'Got LicenseError "%s" while scanning %s' % (e, path)
148 all_licenses_valid = False
149
150 # Second, check for non-standard license text.
151 files_data = _ReadFile(os.path.join('android_webview', 'tools',
152 'third_party_files_whitelist.txt'))
153 whitelisted_files = []
154 for line in files_data.splitlines():
155 match = re.match(r'([^#\s]+)', line)
156 if match:
157 whitelisted_files.append(match.group(1))
158 return _CheckLicenseHeaders(third_party_dirs, whitelisted_files) \
159 and all_licenses_valid
160
161
162 def _GenerateNoticeFile(print_warnings):
163 """Generates the contents of an Android NOTICE file for the third-party code.
164 Args:
165 print_warnings: Whether to print warnings.
166 Returns:
167 The contents of the NOTICE file.
168 """
169
170 third_party_dirs = _FindThirdPartyDirs()
171
172 # Don't forget Chromium's LICENSE file
173 content = [_ReadFile('LICENSE')]
174
175 # We provide attribution for all third-party directories.
176 # TODO(steveblock): Limit this to only code used by the WebView binary.
177 for directory in third_party_dirs:
178 license_file = licenses.ParseDir(directory)['License File']
179 if license_file != licenses.NOT_SHIPPED:
180 content.append(_ReadFile(license_file))
181
182 return '\n'.join(content)
183
184
185 def main():
186 class FormatterWithNewLines(optparse.IndentedHelpFormatter):
187 def format_description(self, description):
188 paras = description.split('\n')
189 formatted_paras = [textwrap.fill(para, self.width) for para in paras]
190 return '\n'.join(formatted_paras) + '\n'
191
192 parser = optparse.OptionParser(formatter=FormatterWithNewLines(),
193 usage='%prog [options]')
194 parser.description = (__doc__ +
195 '\nCommands:\n' \
196 ' scan Check licenses.\n' \
197 ' notice Generate Android NOTICE file on stdout')
198 (options, args) = parser.parse_args()
199 if len(args) != 1:
200 parser.print_help()
201 return 1
202
203 if os.getcwd() != REPOSITORY_ROOT:
204 print "This tool can only be run from the repository root."
205 return 1
206
207 if args[0] == 'scan':
208 if _Scan():
209 print 'OK!'
210 return 0
211 else:
212 return 1
213 elif args[0] == 'notice':
214 print _GenerateNoticeFile(print_warnings=False)
215 return 0
216
217 parser.print_help()
218 return 1
219
220 if __name__ == '__main__':
221 sys.exit(main())
OLDNEW
« no previous file with comments | « android_webview/tools/third_party_files_whitelist.txt ('k') | chrome/version.h.in » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698