| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import copy | 5 import copy |
| 6 import hashlib | 6 import hashlib |
| 7 import json | 7 import json |
| 8 import sys | 8 import sys |
| 9 | 9 |
| 10 MANIFEST_VERSION = 2 | 10 MANIFEST_VERSION = 2 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 """Generic error/exception for manifest_util module""" | 99 """Generic error/exception for manifest_util module""" |
| 100 pass | 100 pass |
| 101 | 101 |
| 102 | 102 |
| 103 class Archive(dict): | 103 class Archive(dict): |
| 104 """A placeholder for sdk archive information. We derive Archive from | 104 """A placeholder for sdk archive information. We derive Archive from |
| 105 dict so that it is easily serializable. """ | 105 dict so that it is easily serializable. """ |
| 106 | 106 |
| 107 def __init__(self, host_os_name): | 107 def __init__(self, host_os_name): |
| 108 """ Create a new archive for the given host-os name. """ | 108 """ Create a new archive for the given host-os name. """ |
| 109 super(Archive, self).__init__() |
| 109 self['host_os'] = host_os_name | 110 self['host_os'] = host_os_name |
| 110 | 111 |
| 111 def CopyFrom(self, src): | 112 def CopyFrom(self, src): |
| 112 """Update the content of the archive by copying values from the given | 113 """Update the content of the archive by copying values from the given |
| 113 dictionary. | 114 dictionary. |
| 114 | 115 |
| 115 Args: | 116 Args: |
| 116 src: The dictionary whose values must be copied to the archive.""" | 117 src: The dictionary whose values must be copied to the archive.""" |
| 117 for key, value in src.items(): | 118 for key, value in src.items(): |
| 118 self[key] = value | 119 self[key] = value |
| (...skipping 15 matching lines...) Expand all Loading... |
| 134 if not self.get('size', None): | 135 if not self.get('size', None): |
| 135 raise Error('Archive "%s" has no size' % host_os) | 136 raise Error('Archive "%s" has no size' % host_os) |
| 136 checksum = self.get('checksum', None) | 137 checksum = self.get('checksum', None) |
| 137 if not checksum: | 138 if not checksum: |
| 138 raise Error('Archive "%s" has no checksum' % host_os) | 139 raise Error('Archive "%s" has no checksum' % host_os) |
| 139 elif not isinstance(checksum, dict): | 140 elif not isinstance(checksum, dict): |
| 140 raise Error('Archive "%s" has a checksum, but it is not a dict' % host_os) | 141 raise Error('Archive "%s" has a checksum, but it is not a dict' % host_os) |
| 141 elif not len(checksum): | 142 elif not len(checksum): |
| 142 raise Error('Archive "%s" has an empty checksum dict' % host_os) | 143 raise Error('Archive "%s" has an empty checksum dict' % host_os) |
| 143 # Verify that all key names are valid. | 144 # Verify that all key names are valid. |
| 144 for key, val in self.iteritems(): | 145 for key in self: |
| 145 if key not in VALID_ARCHIVE_KEYS: | 146 if key not in VALID_ARCHIVE_KEYS: |
| 146 raise Error('Archive "%s" has invalid attribute "%s"' % (host_os, key)) | 147 raise Error('Archive "%s" has invalid attribute "%s"' % (host_os, key)) |
| 147 | 148 |
| 148 def __getattr__(self, name): | 149 def __getattr__(self, name): |
| 149 """Retrieve values from this dict using attributes. | 150 """Retrieve values from this dict using attributes. |
| 150 | 151 |
| 151 This allows for foo.bar instead of foo['bar']. | 152 This allows for foo.bar instead of foo['bar']. |
| 152 | 153 |
| 153 Args: | 154 Args: |
| 154 name: the name of the key, 'bar' in the example above. | 155 name: the name of the key, 'bar' in the example above. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 170 name: The name of the key, 'bar' in the example above. | 171 name: The name of the key, 'bar' in the example above. |
| 171 value: The value to associate with that key.""" | 172 value: The value to associate with that key.""" |
| 172 if name not in VALID_ARCHIVE_KEYS: | 173 if name not in VALID_ARCHIVE_KEYS: |
| 173 raise AttributeError(name) | 174 raise AttributeError(name) |
| 174 # special case, self.checksum returns the sha1, not the checksum dict. | 175 # special case, self.checksum returns the sha1, not the checksum dict. |
| 175 if name == 'checksum': | 176 if name == 'checksum': |
| 176 self.setdefault('checksum', {})['sha1'] = value | 177 self.setdefault('checksum', {})['sha1'] = value |
| 177 return | 178 return |
| 178 return self.__setitem__(name, value) | 179 return self.__setitem__(name, value) |
| 179 | 180 |
| 180 def GetChecksum(self, type='sha1'): | 181 def GetChecksum(self, hash_type='sha1'): |
| 181 """Returns a given cryptographic checksum of the archive""" | 182 """Returns a given cryptographic checksum of the archive""" |
| 182 return self['checksum'][type] | 183 return self['checksum'][hash_type] |
| 183 | 184 |
| 184 | 185 |
| 185 class Bundle(dict): | 186 class Bundle(dict): |
| 186 """A placeholder for sdk bundle information. We derive Bundle from | 187 """A placeholder for sdk bundle information. We derive Bundle from |
| 187 dict so that it is easily serializable.""" | 188 dict so that it is easily serializable.""" |
| 188 | 189 |
| 189 def __init__(self, obj): | 190 def __init__(self, obj): |
| 190 """ Create a new bundle with the given bundle name.""" | 191 """ Create a new bundle with the given bundle name.""" |
| 191 if isinstance(obj, str) or isinstance(obj, unicode): | 192 if isinstance(obj, str) or isinstance(obj, unicode): |
| 192 dict.__init__(self, [(ARCHIVES_KEY, []), (NAME_KEY, obj)]) | 193 dict.__init__(self, [(ARCHIVES_KEY, []), (NAME_KEY, obj)]) |
| (...skipping 27 matching lines...) Expand all Loading... |
| 220 | 221 |
| 221 def LoadDataFromString(self, json_string): | 222 def LoadDataFromString(self, json_string): |
| 222 """Load a JSON bundle string. Raises an exception if json_string | 223 """Load a JSON bundle string. Raises an exception if json_string |
| 223 is not well-formed JSON. | 224 is not well-formed JSON. |
| 224 | 225 |
| 225 Args: | 226 Args: |
| 226 json_string: a JSON-formatted string containing the bundle | 227 json_string: a JSON-formatted string containing the bundle |
| 227 """ | 228 """ |
| 228 self.CopyFrom(json.loads(json_string)) | 229 self.CopyFrom(json.loads(json_string)) |
| 229 | 230 |
| 230 def CopyFrom(self, dict): | 231 def CopyFrom(self, source): |
| 231 """Update the content of the bundle by copying values from the given | 232 """Update the content of the bundle by copying values from the given |
| 232 dictionary. | 233 dictionary. |
| 233 | 234 |
| 234 Args: | 235 Args: |
| 235 dict: The dictionary whose values must be copied to the bundle.""" | 236 source: The dictionary whose values must be copied to the bundle.""" |
| 236 for key, value in dict.items(): | 237 for key, value in source.items(): |
| 237 if key == ARCHIVES_KEY: | 238 if key == ARCHIVES_KEY: |
| 238 archives = [] | 239 archives = [] |
| 239 for a in value: | 240 for a in value: |
| 240 new_archive = Archive(a['host_os']) | 241 new_archive = Archive(a['host_os']) |
| 241 new_archive.CopyFrom(a) | 242 new_archive.CopyFrom(a) |
| 242 archives.append(new_archive) | 243 archives.append(new_archive) |
| 243 self[ARCHIVES_KEY] = archives | 244 self[ARCHIVES_KEY] = archives |
| 244 else: | 245 else: |
| 245 self[key] = value | 246 self[key] = value |
| 246 | 247 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 263 self[NAME_KEY]) | 264 self[NAME_KEY]) |
| 264 # Check specific values | 265 # Check specific values |
| 265 if self['stability'] not in STABILITY_LITERALS: | 266 if self['stability'] not in STABILITY_LITERALS: |
| 266 raise Error('Bundle "%s" has invalid stability field: "%s"' % | 267 raise Error('Bundle "%s" has invalid stability field: "%s"' % |
| 267 (self[NAME_KEY], self['stability'])) | 268 (self[NAME_KEY], self['stability'])) |
| 268 if self['recommended'] not in YES_NO_LITERALS: | 269 if self['recommended'] not in YES_NO_LITERALS: |
| 269 raise Error( | 270 raise Error( |
| 270 'Bundle "%s" has invalid recommended field: "%s"' % | 271 'Bundle "%s" has invalid recommended field: "%s"' % |
| 271 (self[NAME_KEY], self['recommended'])) | 272 (self[NAME_KEY], self['recommended'])) |
| 272 # Verify that all key names are valid. | 273 # Verify that all key names are valid. |
| 273 for key, val in self.iteritems(): | 274 for key in self: |
| 274 if key not in VALID_BUNDLES_KEYS: | 275 if key not in VALID_BUNDLES_KEYS: |
| 275 raise Error('Bundle "%s" has invalid attribute "%s"' % | 276 raise Error('Bundle "%s" has invalid attribute "%s"' % |
| 276 (self[NAME_KEY], key)) | 277 (self[NAME_KEY], key)) |
| 277 # Validate the archives | 278 # Validate the archives |
| 278 for archive in self[ARCHIVES_KEY]: | 279 for archive in self[ARCHIVES_KEY]: |
| 279 archive.Validate() | 280 archive.Validate() |
| 280 | 281 |
| 281 def GetArchive(self, host_os_name): | 282 def GetArchive(self, host_os_name): |
| 282 """Retrieve the archive for the given host os. | 283 """Retrieve the archive for the given host os. |
| 283 | 284 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 "bundles": [], | 387 "bundles": [], |
| 387 } | 388 } |
| 388 | 389 |
| 389 def Validate(self): | 390 def Validate(self): |
| 390 """Validate the Manifest file and raises an exception for problems""" | 391 """Validate the Manifest file and raises an exception for problems""" |
| 391 # Validate the manifest top level | 392 # Validate the manifest top level |
| 392 if self._manifest_data["manifest_version"] > MANIFEST_VERSION: | 393 if self._manifest_data["manifest_version"] > MANIFEST_VERSION: |
| 393 raise Error("Manifest version too high: %s" % | 394 raise Error("Manifest version too high: %s" % |
| 394 self._manifest_data["manifest_version"]) | 395 self._manifest_data["manifest_version"]) |
| 395 # Verify that all key names are valid. | 396 # Verify that all key names are valid. |
| 396 for key, val in self._manifest_data.iteritems(): | 397 for key in self._manifest_data: |
| 397 if key not in VALID_MANIFEST_KEYS: | 398 if key not in VALID_MANIFEST_KEYS: |
| 398 raise Error('Manifest has invalid attribute "%s"' % key) | 399 raise Error('Manifest has invalid attribute "%s"' % key) |
| 399 # Validate each bundle | 400 # Validate each bundle |
| 400 for bundle in self._manifest_data[BUNDLES_KEY]: | 401 for bundle in self._manifest_data[BUNDLES_KEY]: |
| 401 bundle.Validate() | 402 bundle.Validate() |
| 402 | 403 |
| 403 def GetBundle(self, name): | 404 def GetBundle(self, name): |
| 404 """Get a bundle from the array of bundles. | 405 """Get a bundle from the array of bundles. |
| 405 | 406 |
| 406 Args: | 407 Args: |
| 407 name: the name of the bundle to return. | 408 name: the name of the bundle to return. |
| 408 Return: | 409 Return: |
| 409 The first bundle with the given name, or None if it is not found.""" | 410 The first bundle with the given name, or None if it is not found.""" |
| 410 if not BUNDLES_KEY in self._manifest_data: | 411 if not BUNDLES_KEY in self._manifest_data: |
| 411 return None | 412 return None |
| 412 bundles = [bundle for bundle in self._manifest_data[BUNDLES_KEY] | 413 bundles = [bundle for bundle in self._manifest_data[BUNDLES_KEY] |
| 413 if bundle[NAME_KEY] == name] | 414 if bundle[NAME_KEY] == name] |
| 414 if len(bundles) > 1: | 415 if len(bundles) > 1: |
| 415 WarningPrint("More than one bundle with name '%s' exists." % name) | 416 sys.stderr.write("WARNING: More than one bundle with name" |
| 417 "'%s' exists.\n" % name) |
| 416 return bundles[0] if len(bundles) > 0 else None | 418 return bundles[0] if len(bundles) > 0 else None |
| 417 | 419 |
| 418 def GetBundles(self): | 420 def GetBundles(self): |
| 419 """Return all the bundles in the manifest.""" | 421 """Return all the bundles in the manifest.""" |
| 420 return self._manifest_data[BUNDLES_KEY] | 422 return self._manifest_data[BUNDLES_KEY] |
| 421 | 423 |
| 422 def SetBundle(self, new_bundle): | 424 def SetBundle(self, new_bundle): |
| 423 """Replace named bundle. Add if absent. | 425 """Replace named bundle. Add if absent. |
| 424 | 426 |
| 425 Args: | 427 Args: |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 new_bundle.CopyFrom(b) | 515 new_bundle.CopyFrom(b) |
| 514 bundles.append(new_bundle) | 516 bundles.append(new_bundle) |
| 515 self._manifest_data[key] = bundles | 517 self._manifest_data[key] = bundles |
| 516 else: | 518 else: |
| 517 self._manifest_data[key] = value | 519 self._manifest_data[key] = value |
| 518 self.Validate() | 520 self.Validate() |
| 519 | 521 |
| 520 def GetDataAsString(self): | 522 def GetDataAsString(self): |
| 521 """Returns the current JSON manifest object, pretty-printed""" | 523 """Returns the current JSON manifest object, pretty-printed""" |
| 522 return DictToJSON(self._manifest_data) | 524 return DictToJSON(self._manifest_data) |
| OLD | NEW |