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 """Utility for checking and processing licensing information in third_party | 6 """Utility for checking and processing licensing information in third_party |
7 directories. | 7 directories. |
8 | 8 |
9 Usage: licenses.py <command> | 9 Usage: licenses.py <command> |
10 | 10 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
86 # Harfbuzz-ng is not currently shipping in any product: | 86 # Harfbuzz-ng is not currently shipping in any product: |
87 os.path.join('third_party','harfbuzz-ng'), | 87 os.path.join('third_party','harfbuzz-ng'), |
88 ]) | 88 ]) |
89 | 89 |
90 # Directories we don't scan through. | 90 # Directories we don't scan through. |
91 PRUNE_DIRS = ('.svn', '.git', # VCS metadata | 91 PRUNE_DIRS = ('.svn', '.git', # VCS metadata |
92 'out', 'Debug', 'Release', # build files | 92 'out', 'Debug', 'Release', # build files |
93 'layout_tests') # lots of subdirs | 93 'layout_tests') # lots of subdirs |
94 | 94 |
95 ADDITIONAL_PATHS = ( | 95 ADDITIONAL_PATHS = ( |
96 os.path.join('googleurl'), | |
97 os.path.join('native_client_sdk'), | |
96 # The directory with the word list for Chinese and Japanese segmentation | 98 # The directory with the word list for Chinese and Japanese segmentation |
97 # with different license terms than ICU. | 99 # with different license terms than ICU. |
98 os.path.join('third_party','icu','source','data','brkitr'), | 100 os.path.join('third_party','icu','source','data','brkitr'), |
99 # Fake directory so we can include the strongtalk license. | 101 # Fake directory so we can include the strongtalk license. |
100 os.path.join('v8', 'strongtalk'), | 102 os.path.join('v8', 'strongtalk'), |
101 # Fake directory so we can include the google-url license. | |
102 'googleurl', | |
103 ) | 103 ) |
104 | 104 |
105 | 105 |
106 # Directories where we check out directly from upstream, and therefore | 106 # Directories where we check out directly from upstream, and therefore |
107 # can't provide a README.chromium. Please prefer a README.chromium | 107 # can't provide a README.chromium. Please prefer a README.chromium |
108 # wherever possible. | 108 # wherever possible. |
109 SPECIAL_CASES = { | 109 SPECIAL_CASES = { |
110 'googleurl': { | 110 'googleurl': { |
111 "Name": "google-url", | 111 "Name": "google-url", |
112 "URL": "http://code.google.com/p/google-url/", | 112 "URL": "http://code.google.com/p/google-url/", |
113 "License File": "LICENSE.txt", | 113 "License File": "LICENSE.txt", |
114 }, | 114 }, |
115 os.path.join('third_party', 'GTM'): { | |
116 "Name": "Google Toolbox for Mac", | |
117 "URL": "http://code.google.com/p/google-toolbox-for-mac/", | |
118 "License": "Apache 2.0", | |
119 "License File": "COPYING", | |
120 }, | |
121 os.path.join('third_party', 'WebKit'): { | |
122 "Name": "WebKit", | |
123 "URL": "http://webkit.org/", | |
124 "License": "BSD and GPL v2", | |
125 # Absolute path here is resolved as relative to the source root. | |
126 "License File": "/webkit/LICENSE", | |
Nico
2012/07/26 19:45:04
nit: It looks like someone tried to keep these ord
Steve Block
2012/07/26 22:11:00
Hmm, they were still out of order, even if conside
| |
127 }, | |
115 os.path.join('third_party', 'angle'): { | 128 os.path.join('third_party', 'angle'): { |
116 "Name": "Almost Native Graphics Layer Engine", | 129 "Name": "Almost Native Graphics Layer Engine", |
117 "URL": "http://code.google.com/p/angleproject/", | 130 "URL": "http://code.google.com/p/angleproject/", |
118 }, | 131 }, |
132 os.path.join('third_party', 'cros_system_api'): { | |
133 "Name": "Chromium OS system API", | |
134 "URL": "http://code.google.com/apis/protocolbuffers", | |
Nico
2012/07/26 19:45:04
This looks wrong.
Steve Block
2012/07/26 22:11:00
This is from the README, but I guess it's specific
| |
135 "License": "BSD", | |
136 # Absolute path here is resolved as relative to the source root. | |
137 "License File": "/LICENSE.chromium_os", | |
138 }, | |
119 os.path.join('third_party', 'lss'): { | 139 os.path.join('third_party', 'lss'): { |
120 "Name": "linux-syscall-support", | 140 "Name": "linux-syscall-support", |
121 "URL": "http://code.google.com/p/lss/", | 141 "URL": "http://code.google.com/p/lss/", |
122 }, | 142 }, |
123 os.path.join('third_party', 'mozrunner'): { | 143 os.path.join('third_party', 'mozrunner'): { |
124 "Name": "mozrunner", | 144 "Name": "mozrunner", |
125 "URL": "http://pypi.python.org/packages/source/m/mozrunner", | 145 "URL": "http://pypi.python.org/packages/source/m/mozrunner", |
126 "License": "MPL 1.1/GPL 2.0/LGPL 2.1", | 146 "License": "MPL 1.1/GPL 2.0/LGPL 2.1", |
127 }, | 147 }, |
128 os.path.join('third_party', 'ots'): { | 148 os.path.join('third_party', 'ots'): { |
129 "Name": "OTS (OpenType Sanitizer)", | 149 "Name": "OTS (OpenType Sanitizer)", |
130 "URL": "http://code.google.com/p/ots/", | 150 "URL": "http://code.google.com/p/ots/", |
131 }, | 151 }, |
152 os.path.join('third_party', 'pdfsqueeze'): { | |
153 "Name": "pdfsqueeze", | |
154 "URL": "http://code.google.com/p/pdfsqueeze/", | |
155 "License": "Apache 2.0", | |
156 "License File": "COPYING", | |
157 }, | |
132 os.path.join('third_party', 'ppapi'): { | 158 os.path.join('third_party', 'ppapi'): { |
133 "Name": "ppapi", | 159 "Name": "ppapi", |
134 "URL": "http://code.google.com/p/ppapi/", | 160 "URL": "http://code.google.com/p/ppapi/", |
135 }, | 161 }, |
136 os.path.join('third_party', 'pylib_simplejson'): { | 162 os.path.join('third_party', 'pylib_simplejson'): { |
137 "Name": "simplejson", | 163 "Name": "simplejson", |
138 "URL": "http://pypi.python.org/packages/source/s/simplejson", | 164 "URL": "http://pypi.python.org/packages/source/s/simplejson", |
139 "License": "MIT", | 165 "License": "MIT", |
140 }, | 166 }, |
141 os.path.join('third_party', 'WebKit'): { | 167 os.path.join('third_party', 'scons-2.0.1'): { |
142 "Name": "WebKit", | 168 "Name": "scons-2.0.1", |
143 "URL": "http://webkit.org/", | 169 "URL": " http://www.scons.org", |
144 # Absolute path here is resolved as relative to the source root. | 170 "License": "MIT", |
145 "License File": "/webkit/LICENSE", | |
146 }, | 171 }, |
147 os.path.join('third_party', 'GTM'): { | 172 os.path.join('third_party', 'trace-viewer'): { |
148 "Name": "Google Toolbox for Mac", | 173 "Name": "trace-viewer", |
149 "URL": "http://code.google.com/p/google-toolbox-for-mac/", | 174 "URL": "http://code.google.com/p/trace-viewer", |
150 "License File": "COPYING", | 175 "License": "BSD", |
151 }, | |
152 os.path.join('third_party', 'pdfsqueeze'): { | |
153 "Name": "pdfsqueeze", | |
154 "URL": "http://code.google.com/p/pdfsqueeze/", | |
155 "License File": "COPYING", | |
156 }, | 176 }, |
157 os.path.join('third_party', 'v8-i18n'): { | 177 os.path.join('third_party', 'v8-i18n'): { |
158 "Name": "Internationalization Library for v8", | 178 "Name": "Internationalization Library for v8", |
159 "URL": "http://code.google.com/p/v8-i18n/", | 179 "URL": "http://code.google.com/p/v8-i18n/", |
160 }, | 180 }, |
181 os.path.join('third_party', 'webpagereplay'): { | |
182 "Name": "webpagereplay", | |
183 "URL": "http://code.google.com/p/web-page-replay", | |
184 "License": "Apache 2.0", | |
185 }, | |
161 os.path.join('v8', 'strongtalk'): { | 186 os.path.join('v8', 'strongtalk'): { |
162 "Name": "Strongtalk", | 187 "Name": "Strongtalk", |
163 "URL": "http://www.strongtalk.org/", | 188 "URL": "http://www.strongtalk.org/", |
189 # Absolute path here is resolved as relative to the source root. | |
164 "License File": "/v8/LICENSE.strongtalk", | 190 "License File": "/v8/LICENSE.strongtalk", |
165 }, | 191 }, |
166 } | 192 } |
167 | 193 |
168 class LicenseError(Exception): | 194 class LicenseError(Exception): |
169 """We raise this exception when a directory's licensing info isn't | 195 """We raise this exception when a directory's licensing info isn't |
170 fully filled out.""" | 196 fully filled out.""" |
171 pass | 197 pass |
172 | 198 |
173 def AbsolutePath(path, filename): | 199 def AbsolutePath(path, filename): |
(...skipping 23 matching lines...) Expand all Loading... | |
197 # Relative path to a file containing some html we're required to place in | 223 # Relative path to a file containing some html we're required to place in |
198 # about:credits. | 224 # about:credits. |
199 optional_keys = ["Required Text"] | 225 optional_keys = ["Required Text"] |
200 | 226 |
201 if path in SPECIAL_CASES: | 227 if path in SPECIAL_CASES: |
202 metadata.update(SPECIAL_CASES[path]) | 228 metadata.update(SPECIAL_CASES[path]) |
203 else: | 229 else: |
204 # Try to find README.chromium. | 230 # Try to find README.chromium. |
205 readme_path = os.path.join(path, 'README.chromium') | 231 readme_path = os.path.join(path, 'README.chromium') |
206 if not os.path.exists(readme_path): | 232 if not os.path.exists(readme_path): |
207 raise LicenseError("missing README.chromium") | 233 raise LicenseError("missing README.chromium or licenses.py " |
234 "SPECIAL_CASES entry") | |
208 | 235 |
209 for line in open(readme_path): | 236 for line in open(readme_path): |
210 line = line.strip() | 237 line = line.strip() |
211 if not line: | 238 if not line: |
212 break | 239 break |
213 for key in metadata.keys() + optional_keys: | 240 for key in metadata.keys() + optional_keys: |
214 field = key + ": " | 241 field = key + ": " |
215 if line.startswith(field): | 242 if line.startswith(field): |
216 metadata[key] = line[len(field):] | 243 metadata[key] = line[len(field):] |
217 | 244 |
(...skipping 21 matching lines...) Expand all Loading... | |
239 if "Required Text" in metadata: | 266 if "Required Text" in metadata: |
240 required_path = AbsolutePath(path, metadata["Required Text"]) | 267 required_path = AbsolutePath(path, metadata["Required Text"]) |
241 if required_path is not None: | 268 if required_path is not None: |
242 metadata["Required Text"] = required_path | 269 metadata["Required Text"] = required_path |
243 else: | 270 else: |
244 raise LicenseError("Required text file listed but not found.") | 271 raise LicenseError("Required text file listed but not found.") |
245 | 272 |
246 return metadata | 273 return metadata |
247 | 274 |
248 | 275 |
276 def ContainsFiles(path): | |
277 """Determines whether a directory contains any files.""" | |
Nico
2012/07/26 19:45:04
"any files in any subdirectory"
Steve Block
2012/07/26 22:11:00
Done.
| |
278 for _, _, files in os.walk(path): | |
279 if files: | |
280 return True | |
281 return False | |
282 | |
283 | |
249 def FindThirdPartyDirs(): | 284 def FindThirdPartyDirs(): |
250 """Find all third_party directories underneath the current directory.""" | 285 """Find all third_party directories underneath the current directory.""" |
251 third_party_dirs = [] | 286 third_party_dirs = [] |
252 for path, dirs, files in os.walk('.'): | 287 for path, dirs, files in os.walk('.'): |
253 path = path[len('./'):] # Pretty up the path. | 288 path = path[len('./'):] # Pretty up the path. |
254 | 289 |
255 if path in PRUNE_PATHS: | 290 if path in PRUNE_PATHS: |
256 dirs[:] = [] | 291 dirs[:] = [] |
257 continue | 292 continue |
258 | 293 |
259 # Prune out directories we want to skip. | 294 # Prune out directories we want to skip. |
260 # (Note that we loop over PRUNE_DIRS so we're not iterating over a | 295 # (Note that we loop over PRUNE_DIRS so we're not iterating over a |
261 # list that we're simultaneously mutating.) | 296 # list that we're simultaneously mutating.) |
262 for skip in PRUNE_DIRS: | 297 for skip in PRUNE_DIRS: |
263 if skip in dirs: | 298 if skip in dirs: |
264 dirs.remove(skip) | 299 dirs.remove(skip) |
265 | 300 |
266 if os.path.basename(path) == 'third_party': | 301 if os.path.basename(path) == 'third_party': |
267 # Add all subdirectories that are not marked for skipping. | 302 # Add all subdirectories that are not marked for skipping. |
268 for dir in dirs: | 303 for dir in dirs: |
269 dirpath = os.path.join(path, dir) | 304 dirpath = os.path.join(path, dir) |
270 if dirpath not in PRUNE_PATHS: | 305 if dirpath not in PRUNE_PATHS: |
271 third_party_dirs.append(dirpath) | 306 third_party_dirs.append(dirpath) |
272 | 307 |
273 # Don't recurse into any subdirs from here. | 308 # Don't recurse into any subdirs from here. |
274 dirs[:] = [] | 309 dirs[:] = [] |
275 continue | 310 continue |
276 | 311 |
312 # Don't recurse into paths in ADDITIONAL_PATHS, like we do with regular | |
313 # third_party/foo paths. | |
314 if path in ADDITIONAL_PATHS: | |
315 dirs[:] = [] | |
316 | |
277 for dir in ADDITIONAL_PATHS: | 317 for dir in ADDITIONAL_PATHS: |
278 third_party_dirs.append(dir) | 318 third_party_dirs.append(dir) |
279 | 319 |
280 return third_party_dirs | 320 # If a directory contains no files, assume it's a DEPS directory for a |
321 # project not used by our current configuration and skip it. | |
322 return [x for x in third_party_dirs if ContainsFiles(x)] | |
281 | 323 |
282 | 324 |
283 def ScanThirdPartyDirs(): | 325 def ScanThirdPartyDirs(): |
284 """Scan a list of directories and report on any problems we find.""" | 326 """Scan a list of directories and report on any problems we find.""" |
285 third_party_dirs = FindThirdPartyDirs() | 327 third_party_dirs = FindThirdPartyDirs() |
286 | 328 |
287 errors = [] | 329 errors = [] |
288 for path in sorted(third_party_dirs): | 330 for path in sorted(third_party_dirs): |
289 try: | 331 try: |
290 metadata = ParseDir(path) | 332 metadata = ParseDir(path) |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
351 elif command == 'credits': | 393 elif command == 'credits': |
352 if not GenerateCredits(): | 394 if not GenerateCredits(): |
353 return 1 | 395 return 1 |
354 else: | 396 else: |
355 print __doc__ | 397 print __doc__ |
356 return 1 | 398 return 1 |
357 | 399 |
358 | 400 |
359 if __name__ == '__main__': | 401 if __name__ == '__main__': |
360 sys.exit(main()) | 402 sys.exit(main()) |
OLD | NEW |