Chromium Code Reviews| 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 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 if filename.startswith('/'): | 166 if filename.startswith('/'): |
| 167 # Absolute-looking paths are relative to the source root | 167 # Absolute-looking paths are relative to the source root |
| 168 # (which is the directory we're run from). | 168 # (which is the directory we're run from). |
| 169 absolute_path = os.path.join(os.getcwd(), filename[1:]) | 169 absolute_path = os.path.join(os.getcwd(), filename[1:]) |
| 170 else: | 170 else: |
| 171 absolute_path = os.path.join(path, filename) | 171 absolute_path = os.path.join(path, filename) |
| 172 if os.path.exists(absolute_path): | 172 if os.path.exists(absolute_path): |
| 173 return absolute_path | 173 return absolute_path |
| 174 return None | 174 return None |
| 175 | 175 |
| 176 def ParseDir(path): | 176 def ParseDir(path, raise_on_error): |
| 177 """Examine a third_party/foo component and extract its metadata.""" | 177 """Examine a third_party/foo component and extract its metadata. |
| 178 Args: | |
| 179 path the path to the component to examine | |
| 180 raise_on_error whether to raise an exception if an error occurs | |
| 181 Returns: | |
| 182 metadata for the component | |
| 183 """ | |
| 178 | 184 |
| 179 # Parse metadata fields out of README.chromium. | 185 # Parse metadata fields out of README.chromium. |
| 180 # We examine "LICENSE" for the license file by default. | 186 # We examine "LICENSE" for the license file by default. |
| 181 metadata = { | 187 metadata = { |
| 182 "License File": "LICENSE", # Relative path to license text. | 188 "License File": "LICENSE", # Relative path to license text. |
| 183 "Name": None, # Short name (for header on about:credits). | 189 "Name": None, # Short name (for header on about:credits). |
| 184 "URL": None, # Project home page. | 190 "URL": None, # Project home page. |
| 185 } | 191 } |
| 186 | 192 |
| 187 # Relative path to a file containing some html we're required to place in | 193 # Relative path to a file containing some html we're required to place in |
| 188 # about:credits. | 194 # about:credits. |
| 189 optional_keys = ["Required Text"] | 195 optional_keys = ["Required Text"] |
| 190 | 196 |
| 191 if path in SPECIAL_CASES: | 197 if path in SPECIAL_CASES: |
| 192 metadata.update(SPECIAL_CASES[path]) | 198 metadata.update(SPECIAL_CASES[path]) |
| 193 else: | 199 else: |
| 194 # Try to find README.chromium. | 200 # Try to find README.chromium. |
| 195 readme_path = os.path.join(path, 'README.chromium') | 201 readme_path = os.path.join(path, 'README.chromium') |
| 196 if not os.path.exists(readme_path): | 202 if not os.path.exists(readme_path): |
| 197 raise LicenseError("missing README.chromium") | 203 if raise_on_error: |
| 198 | 204 raise LicenseError("missing README.chromium") |
| 199 for line in open(readme_path): | 205 else: |
| 200 line = line.strip() | 206 for line in open(readme_path): |
| 201 if not line: | 207 line = line.strip() |
| 202 break | 208 if not line: |
| 203 for key in metadata.keys() + optional_keys: | 209 break |
| 204 field = key + ": " | 210 for key in metadata.keys() + optional_keys: |
| 205 if line.startswith(field): | 211 field = key + ": " |
| 206 metadata[key] = line[len(field):] | 212 if line.startswith(field): |
| 213 metadata[key] = line[len(field):] | |
| 207 | 214 |
| 208 # Check that all expected metadata is present. | 215 # Check that all expected metadata is present. |
| 209 for key, value in metadata.iteritems(): | 216 if raise_on_error: |
| 210 if not value: | 217 for key, value in metadata.iteritems(): |
| 211 raise LicenseError("couldn't find '" + key + "' line " | 218 if not value: |
| 212 "in README.chromium or licences.py " | 219 raise LicenseError("couldn't find '" + key + "' line " |
| 213 "SPECIAL_CASES") | 220 "in README.chromium or licences.py " |
| 221 "SPECIAL_CASES") | |
| 214 | 222 |
| 215 # Check that the license file exists. | 223 # Check that the license file exists. |
| 216 for filename in (metadata["License File"], "COPYING"): | 224 for filename in (metadata["License File"], "COPYING"): |
| 217 license_path = AbsolutePath(path, filename) | 225 license_path = AbsolutePath(path, filename) |
| 218 if license_path is not None: | 226 if license_path is not None: |
| 219 metadata["License File"] = license_path | 227 metadata["License File"] = license_path |
| 220 break | 228 break |
| 221 | 229 |
| 222 if not license_path: | 230 if raise_on_error and not license_path: |
| 223 raise LicenseError("License file not found. " | 231 raise LicenseError("License file not found. " |
| 224 "Either add a file named LICENSE, " | 232 "Either add a file named LICENSE, " |
| 225 "import upstream's COPYING if available, " | 233 "import upstream's COPYING if available, " |
| 226 "or add a 'License File:' line to README.chromium " | 234 "or add a 'License File:' line to README.chromium " |
| 227 "with the appropriate path.") | 235 "with the appropriate path.") |
| 228 | 236 |
| 229 if "Required Text" in metadata: | 237 if "Required Text" in metadata: |
| 230 required_path = AbsolutePath(path, metadata["Required Text"]) | 238 required_path = AbsolutePath(path, metadata["Required Text"]) |
| 231 if required_path is not None: | 239 if required_path is not None: |
| 232 metadata["Required Text"] = required_path | 240 metadata["Required Text"] = required_path |
| 233 else: | 241 elif raise_on_error: |
| 234 raise LicenseError("Required text file listed but not found.") | 242 raise LicenseError("Required text file listed but not found.") |
| 235 | 243 |
| 236 return metadata | 244 return metadata |
| 237 | 245 |
| 238 | 246 |
| 239 def FindThirdPartyDirs(): | 247 def FindThirdPartyDirs(): |
| 240 """Find all third_party directories underneath the current directory.""" | 248 """Find all third_party directories underneath the current directory.""" |
| 241 third_party_dirs = [] | 249 third_party_dirs = [] |
| 242 for path, dirs, files in os.walk('.'): | 250 for path, dirs, files in os.walk('.'): |
| 243 path = path[len('./'):] # Pretty up the path. | 251 path = path[len('./'):] # Pretty up the path. |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 270 return third_party_dirs | 278 return third_party_dirs |
| 271 | 279 |
| 272 | 280 |
| 273 def ScanThirdPartyDirs(): | 281 def ScanThirdPartyDirs(): |
| 274 """Scan a list of directories and report on any problems we find.""" | 282 """Scan a list of directories and report on any problems we find.""" |
| 275 third_party_dirs = FindThirdPartyDirs() | 283 third_party_dirs = FindThirdPartyDirs() |
| 276 | 284 |
| 277 errors = [] | 285 errors = [] |
| 278 for path in sorted(third_party_dirs): | 286 for path in sorted(third_party_dirs): |
| 279 try: | 287 try: |
| 280 metadata = ParseDir(path) | 288 metadata = ParseDir(path, True) |
|
Evan Martin
2012/07/24 19:41:28
Consider something like:
ParseDir(path, raise_on
Steve Block
2012/07/24 21:20:58
Regarding a try block, this approach doesn't work
| |
| 281 except LicenseError, e: | 289 except LicenseError, e: |
| 282 errors.append((path, e.args[0])) | 290 errors.append((path, e.args[0])) |
| 283 continue | 291 continue |
| 284 | 292 |
| 285 for path, error in sorted(errors): | 293 for path, error in sorted(errors): |
| 286 print path + ": " + error | 294 print path + ": " + error |
| 287 | 295 |
| 288 return len(errors) == 0 | 296 return len(errors) == 0 |
| 289 | 297 |
| 290 | 298 |
| 291 def GenerateCredits(): | 299 def GenerateCredits(): |
| 292 """Generate about:credits, dumping the result to stdout.""" | 300 """Generate about:credits, dumping the result to stdout.""" |
| 293 | 301 |
| 294 def EvaluateTemplate(template, env, escape=True): | 302 def EvaluateTemplate(template, env, escape=True): |
| 295 """Expand a template with variables like {{foo}} using a | 303 """Expand a template with variables like {{foo}} using a |
| 296 dictionary of expansions.""" | 304 dictionary of expansions.""" |
| 297 for key, val in env.items(): | 305 for key, val in env.items(): |
| 298 if escape and not key.endswith("_unescaped"): | 306 if escape and not key.endswith("_unescaped"): |
| 299 val = cgi.escape(val) | 307 val = cgi.escape(val) |
| 300 template = template.replace('{{%s}}' % key, val) | 308 template = template.replace('{{%s}}' % key, val) |
| 301 return template | 309 return template |
| 302 | 310 |
| 303 third_party_dirs = FindThirdPartyDirs() | 311 third_party_dirs = FindThirdPartyDirs() |
| 304 | 312 |
| 305 entry_template = open('chrome/browser/resources/about_credits_entry.tmpl', | 313 entry_template = open('chrome/browser/resources/about_credits_entry.tmpl', |
| 306 'rb').read() | 314 'rb').read() |
| 307 entries = [] | 315 entries = [] |
| 308 for path in sorted(third_party_dirs): | 316 for path in sorted(third_party_dirs): |
| 309 try: | 317 try: |
| 310 metadata = ParseDir(path) | 318 metadata = ParseDir(path, True) |
| 311 except LicenseError: | 319 except LicenseError: |
| 312 print >>sys.stderr, ("WARNING: licensing info for " + path + | 320 print >>sys.stderr, ("WARNING: licensing info for " + path + |
| 313 " is incomplete, skipping.") | 321 " is incomplete, skipping.") |
| 314 continue | 322 continue |
| 315 env = { | 323 env = { |
| 316 'name': metadata['Name'], | 324 'name': metadata['Name'], |
| 317 'url': metadata['URL'], | 325 'url': metadata['URL'], |
| 318 'license': open(metadata['License File'], 'rb').read(), | 326 'license': open(metadata['License File'], 'rb').read(), |
| 319 'license_unescaped': '', | 327 'license_unescaped': '', |
| 320 } | 328 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 341 elif command == 'credits': | 349 elif command == 'credits': |
| 342 if not GenerateCredits(): | 350 if not GenerateCredits(): |
| 343 return 1 | 351 return 1 |
| 344 else: | 352 else: |
| 345 print __doc__ | 353 print __doc__ |
| 346 return 1 | 354 return 1 |
| 347 | 355 |
| 348 | 356 |
| 349 if __name__ == '__main__': | 357 if __name__ == '__main__': |
| 350 sys.exit(main()) | 358 sys.exit(main()) |
| OLD | NEW |