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', 'angle'): { | 115 os.path.join('third_party', 'angle'): { |
116 "Name": "Almost Native Graphics Layer Engine", | 116 "Name": "Almost Native Graphics Layer Engine", |
117 "URL": "http://code.google.com/p/angleproject/", | 117 "URL": "http://code.google.com/p/angleproject/", |
118 }, | 118 }, |
| 119 os.path.join('third_party', 'cros_system_api'): { |
| 120 "Name": "Chromium OS system API", |
| 121 "URL": "http://www.chromium.org/chromium-os", |
| 122 "License": "BSD", |
| 123 # Absolute path here is resolved as relative to the source root. |
| 124 "License File": "/LICENSE.chromium_os", |
| 125 }, |
| 126 os.path.join('third_party', 'GTM'): { |
| 127 "Name": "Google Toolbox for Mac", |
| 128 "URL": "http://code.google.com/p/google-toolbox-for-mac/", |
| 129 "License": "Apache 2.0", |
| 130 "License File": "COPYING", |
| 131 }, |
119 os.path.join('third_party', 'lss'): { | 132 os.path.join('third_party', 'lss'): { |
120 "Name": "linux-syscall-support", | 133 "Name": "linux-syscall-support", |
121 "URL": "http://code.google.com/p/lss/", | 134 "URL": "http://code.google.com/p/lss/", |
122 }, | 135 }, |
123 os.path.join('third_party', 'ots'): { | 136 os.path.join('third_party', 'ots'): { |
124 "Name": "OTS (OpenType Sanitizer)", | 137 "Name": "OTS (OpenType Sanitizer)", |
125 "URL": "http://code.google.com/p/ots/", | 138 "URL": "http://code.google.com/p/ots/", |
126 }, | 139 }, |
| 140 os.path.join('third_party', 'pdfsqueeze'): { |
| 141 "Name": "pdfsqueeze", |
| 142 "URL": "http://code.google.com/p/pdfsqueeze/", |
| 143 "License": "Apache 2.0", |
| 144 "License File": "COPYING", |
| 145 }, |
127 os.path.join('third_party', 'ppapi'): { | 146 os.path.join('third_party', 'ppapi'): { |
128 "Name": "ppapi", | 147 "Name": "ppapi", |
129 "URL": "http://code.google.com/p/ppapi/", | 148 "URL": "http://code.google.com/p/ppapi/", |
130 }, | 149 }, |
131 os.path.join('third_party', 'WebKit'): { | 150 os.path.join('third_party', 'scons-2.0.1'): { |
132 "Name": "WebKit", | 151 "Name": "scons-2.0.1", |
133 "URL": "http://webkit.org/", | 152 "URL": "http://www.scons.org", |
134 # Absolute path here is resolved as relative to the source root. | 153 "License": "MIT", |
135 "License File": "/webkit/LICENSE", | |
136 }, | 154 }, |
137 os.path.join('third_party', 'GTM'): { | 155 os.path.join('third_party', 'trace-viewer'): { |
138 "Name": "Google Toolbox for Mac", | 156 "Name": "trace-viewer", |
139 "URL": "http://code.google.com/p/google-toolbox-for-mac/", | 157 "URL": "http://code.google.com/p/trace-viewer", |
140 "License File": "COPYING", | 158 "License": "BSD", |
141 }, | |
142 os.path.join('third_party', 'pdfsqueeze'): { | |
143 "Name": "pdfsqueeze", | |
144 "URL": "http://code.google.com/p/pdfsqueeze/", | |
145 "License File": "COPYING", | |
146 }, | 159 }, |
147 os.path.join('third_party', 'v8-i18n'): { | 160 os.path.join('third_party', 'v8-i18n'): { |
148 "Name": "Internationalization Library for v8", | 161 "Name": "Internationalization Library for v8", |
149 "URL": "http://code.google.com/p/v8-i18n/", | 162 "URL": "http://code.google.com/p/v8-i18n/", |
150 }, | 163 }, |
| 164 os.path.join('third_party', 'WebKit'): { |
| 165 "Name": "WebKit", |
| 166 "URL": "http://webkit.org/", |
| 167 "License": "BSD and GPL v2", |
| 168 # Absolute path here is resolved as relative to the source root. |
| 169 "License File": "/webkit/LICENSE", |
| 170 }, |
| 171 os.path.join('third_party', 'webpagereplay'): { |
| 172 "Name": "webpagereplay", |
| 173 "URL": "http://code.google.com/p/web-page-replay", |
| 174 "License": "Apache 2.0", |
| 175 }, |
151 os.path.join('v8', 'strongtalk'): { | 176 os.path.join('v8', 'strongtalk'): { |
152 "Name": "Strongtalk", | 177 "Name": "Strongtalk", |
153 "URL": "http://www.strongtalk.org/", | 178 "URL": "http://www.strongtalk.org/", |
| 179 # Absolute path here is resolved as relative to the source root. |
154 "License File": "/v8/LICENSE.strongtalk", | 180 "License File": "/v8/LICENSE.strongtalk", |
155 }, | 181 }, |
156 } | 182 } |
157 | 183 |
158 class LicenseError(Exception): | 184 class LicenseError(Exception): |
159 """We raise this exception when a directory's licensing info isn't | 185 """We raise this exception when a directory's licensing info isn't |
160 fully filled out.""" | 186 fully filled out.""" |
161 pass | 187 pass |
162 | 188 |
163 def AbsolutePath(path, filename): | 189 def AbsolutePath(path, filename): |
(...skipping 23 matching lines...) Expand all Loading... |
187 # Relative path to a file containing some html we're required to place in | 213 # Relative path to a file containing some html we're required to place in |
188 # about:credits. | 214 # about:credits. |
189 optional_keys = ["Required Text"] | 215 optional_keys = ["Required Text"] |
190 | 216 |
191 if path in SPECIAL_CASES: | 217 if path in SPECIAL_CASES: |
192 metadata.update(SPECIAL_CASES[path]) | 218 metadata.update(SPECIAL_CASES[path]) |
193 else: | 219 else: |
194 # Try to find README.chromium. | 220 # Try to find README.chromium. |
195 readme_path = os.path.join(path, 'README.chromium') | 221 readme_path = os.path.join(path, 'README.chromium') |
196 if not os.path.exists(readme_path): | 222 if not os.path.exists(readme_path): |
197 raise LicenseError("missing README.chromium") | 223 raise LicenseError("missing README.chromium or licenses.py " |
| 224 "SPECIAL_CASES entry") |
198 | 225 |
199 for line in open(readme_path): | 226 for line in open(readme_path): |
200 line = line.strip() | 227 line = line.strip() |
201 if not line: | 228 if not line: |
202 break | 229 break |
203 for key in metadata.keys() + optional_keys: | 230 for key in metadata.keys() + optional_keys: |
204 field = key + ": " | 231 field = key + ": " |
205 if line.startswith(field): | 232 if line.startswith(field): |
206 metadata[key] = line[len(field):] | 233 metadata[key] = line[len(field):] |
207 | 234 |
(...skipping 21 matching lines...) Expand all Loading... |
229 if "Required Text" in metadata: | 256 if "Required Text" in metadata: |
230 required_path = AbsolutePath(path, metadata["Required Text"]) | 257 required_path = AbsolutePath(path, metadata["Required Text"]) |
231 if required_path is not None: | 258 if required_path is not None: |
232 metadata["Required Text"] = required_path | 259 metadata["Required Text"] = required_path |
233 else: | 260 else: |
234 raise LicenseError("Required text file listed but not found.") | 261 raise LicenseError("Required text file listed but not found.") |
235 | 262 |
236 return metadata | 263 return metadata |
237 | 264 |
238 | 265 |
| 266 def ContainsFiles(path): |
| 267 """Determines whether any files exist in a directory or in any of its |
| 268 subdirectories.""" |
| 269 for _, _, files in os.walk(path): |
| 270 if files: |
| 271 return True |
| 272 return False |
| 273 |
| 274 |
239 def FindThirdPartyDirs(): | 275 def FindThirdPartyDirs(): |
240 """Find all third_party directories underneath the current directory.""" | 276 """Find all third_party directories underneath the current directory.""" |
241 third_party_dirs = [] | 277 third_party_dirs = [] |
242 for path, dirs, files in os.walk('.'): | 278 for path, dirs, files in os.walk('.'): |
243 path = path[len('./'):] # Pretty up the path. | 279 path = path[len('./'):] # Pretty up the path. |
244 | 280 |
245 if path in PRUNE_PATHS: | 281 if path in PRUNE_PATHS: |
246 dirs[:] = [] | 282 dirs[:] = [] |
247 continue | 283 continue |
248 | 284 |
249 # Prune out directories we want to skip. | 285 # Prune out directories we want to skip. |
250 # (Note that we loop over PRUNE_DIRS so we're not iterating over a | 286 # (Note that we loop over PRUNE_DIRS so we're not iterating over a |
251 # list that we're simultaneously mutating.) | 287 # list that we're simultaneously mutating.) |
252 for skip in PRUNE_DIRS: | 288 for skip in PRUNE_DIRS: |
253 if skip in dirs: | 289 if skip in dirs: |
254 dirs.remove(skip) | 290 dirs.remove(skip) |
255 | 291 |
256 if os.path.basename(path) == 'third_party': | 292 if os.path.basename(path) == 'third_party': |
257 # Add all subdirectories that are not marked for skipping. | 293 # Add all subdirectories that are not marked for skipping. |
258 for dir in dirs: | 294 for dir in dirs: |
259 dirpath = os.path.join(path, dir) | 295 dirpath = os.path.join(path, dir) |
260 if dirpath not in PRUNE_PATHS: | 296 if dirpath not in PRUNE_PATHS: |
261 third_party_dirs.append(dirpath) | 297 third_party_dirs.append(dirpath) |
262 | 298 |
263 # Don't recurse into any subdirs from here. | 299 # Don't recurse into any subdirs from here. |
264 dirs[:] = [] | 300 dirs[:] = [] |
265 continue | 301 continue |
266 | 302 |
| 303 # Don't recurse into paths in ADDITIONAL_PATHS, like we do with regular |
| 304 # third_party/foo paths. |
| 305 if path in ADDITIONAL_PATHS: |
| 306 dirs[:] = [] |
| 307 |
267 for dir in ADDITIONAL_PATHS: | 308 for dir in ADDITIONAL_PATHS: |
268 third_party_dirs.append(dir) | 309 third_party_dirs.append(dir) |
269 | 310 |
270 return third_party_dirs | 311 # If a directory contains no files, assume it's a DEPS directory for a |
| 312 # project not used by our current configuration and skip it. |
| 313 return [x for x in third_party_dirs if ContainsFiles(x)] |
271 | 314 |
272 | 315 |
273 def ScanThirdPartyDirs(): | 316 def ScanThirdPartyDirs(): |
274 """Scan a list of directories and report on any problems we find.""" | 317 """Scan a list of directories and report on any problems we find.""" |
275 third_party_dirs = FindThirdPartyDirs() | 318 third_party_dirs = FindThirdPartyDirs() |
276 | 319 |
277 errors = [] | 320 errors = [] |
278 for path in sorted(third_party_dirs): | 321 for path in sorted(third_party_dirs): |
279 try: | 322 try: |
280 metadata = ParseDir(path) | 323 metadata = ParseDir(path) |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 elif command == 'credits': | 384 elif command == 'credits': |
342 if not GenerateCredits(): | 385 if not GenerateCredits(): |
343 return 1 | 386 return 1 |
344 else: | 387 else: |
345 print __doc__ | 388 print __doc__ |
346 return 1 | 389 return 1 |
347 | 390 |
348 | 391 |
349 if __name__ == '__main__': | 392 if __name__ == '__main__': |
350 sys.exit(main()) | 393 sys.exit(main()) |
OLD | NEW |