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

Side by Side Diff: native_client_sdk/src/build_tools/manifest_util.py

Issue 10065030: [NaCl SDK] Change build script to test sdk_updater, also push manifest snippets per bot. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 8 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
OLDNEW
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 import hashlib
6 import json 7 import json
8 import sys
7 9
8 MANIFEST_VERSION = 2 10 MANIFEST_VERSION = 2
9 11
10 # Some commonly-used key names. 12 # Some commonly-used key names.
11 ARCHIVES_KEY = 'archives' 13 ARCHIVES_KEY = 'archives'
12 BUNDLES_KEY = 'bundles' 14 BUNDLES_KEY = 'bundles'
13 NAME_KEY = 'name' 15 NAME_KEY = 'name'
14 REVISION_KEY = 'revision' 16 REVISION_KEY = 'revision'
15 VERSION_KEY = 'version' 17 VERSION_KEY = 'version'
16 18
(...skipping 10 matching lines...) Expand all
27 # Valid values for bundle-recommended field. 29 # Valid values for bundle-recommended field.
28 YES_NO_LITERALS = ['yes', 'no'] 30 YES_NO_LITERALS = ['yes', 'no']
29 VALID_BUNDLES_KEYS = frozenset([ 31 VALID_BUNDLES_KEYS = frozenset([
30 ARCHIVES_KEY, NAME_KEY, VERSION_KEY, REVISION_KEY, 32 ARCHIVES_KEY, NAME_KEY, VERSION_KEY, REVISION_KEY,
31 'description', 'desc_url', 'stability', 'recommended', 'repath', 33 'description', 'desc_url', 'stability', 'recommended', 'repath',
32 ]) 34 ])
33 35
34 VALID_MANIFEST_KEYS = frozenset(['manifest_version', BUNDLES_KEY]) 36 VALID_MANIFEST_KEYS = frozenset(['manifest_version', BUNDLES_KEY])
35 37
36 38
39 def GetHostOS():
40 '''Returns the host_os value that corresponds to the current host OS'''
41 return {
42 'linux2': 'linux',
43 'darwin': 'mac',
44 'cygwin': 'win',
45 'win32': 'win'
46 }[sys.platform]
47
48
49 def DictToJSON(dict):
50 """Convert a dict to a JSON-formatted string."""
51 pretty_string = json.dumps(dict, sort_keys=False, indent=2)
52 # json.dumps sometimes returns trailing whitespace and does not put
53 # a newline at the end. This code fixes these problems.
54 pretty_lines = pretty_string.split('\n')
55 return '\n'.join([line.rstrip() for line in pretty_lines]) + '\n'
56
57
58 def DownloadAndComputeHash(from_stream, to_stream=None, progress_func=None):
59 ''' Download the archive data from from-stream and generate sha1 and
60 size info.
61
62 Args:
63 from_stream: An input stream that supports read.
64 to_stream: [optional] the data is written to to_stream if it is
65 provided.
66 progress_func: [optional] A function used to report download progress. If
67 provided, progress_func is called with progress=0 at the
68 beginning of the download, periodically with progress=1
69 during the download, and progress=100 at the end.
70
71 Return
72 A tuple (sha1, size) where sha1 is a sha1-hash for the archive data and
73 size is the size of the archive data in bytes.'''
74 # Use a no-op progress function if none is specified.
75 def progress_no_op(progress):
76 pass
77 if not progress_func:
78 progress_func = progress_no_op
79
80 sha1_hash = hashlib.sha1()
81 size = 0
82 progress_func(progress=0)
83 while(1):
84 data = from_stream.read(32768)
85 if not data:
86 break
87 sha1_hash.update(data)
88 size += len(data)
89 if to_stream:
90 to_stream.write(data)
91 progress_func(size)
92
93 progress_func(progress=100)
94 return sha1_hash.hexdigest(), size
95
96
37 class Error(Exception): 97 class Error(Exception):
38 """Generic error/exception for manifest_util module""" 98 """Generic error/exception for manifest_util module"""
39 pass 99 pass
40 100
41 101
42 class Archive(dict): 102 class Archive(dict):
43 """A placeholder for sdk archive information. We derive Archive from 103 """A placeholder for sdk archive information. We derive Archive from
44 dict so that it is easily serializable. """ 104 dict so that it is easily serializable. """
45 105
46 def __init__(self, host_os_name): 106 def __init__(self, host_os_name):
(...skipping 16 matching lines...) Expand all
63 Returns: True if self is a valid bundle. 123 Returns: True if self is a valid bundle.
64 """ 124 """
65 host_os = self.get('host_os', None) 125 host_os = self.get('host_os', None)
66 if host_os and host_os not in HOST_OS_LITERALS: 126 if host_os and host_os not in HOST_OS_LITERALS:
67 raise Error('Invalid host-os name in archive') 127 raise Error('Invalid host-os name in archive')
68 # Ensure host_os has a valid string. We'll use it for pretty printing. 128 # Ensure host_os has a valid string. We'll use it for pretty printing.
69 if not host_os: 129 if not host_os:
70 host_os = 'all (default)' 130 host_os = 'all (default)'
71 if not self.get('url', None): 131 if not self.get('url', None):
72 raise Error('Archive "%s" has no URL' % host_os) 132 raise Error('Archive "%s" has no URL' % host_os)
133 if not self.get('size', None):
134 raise Error('Archive "%s" has no size' % host_os)
135 checksum = self.get('checksum', None)
136 if not checksum:
137 raise Error('Archive "%s" has no checksum' % host_os)
138 elif not isinstance(checksum, dict):
139 raise Error('Archive "%s" has a checksum, but it is not a dict' % host_os)
140 elif not len(checksum):
141 raise Error('Archive "%s" has an empty checksum dict' % host_os)
73 # Verify that all key names are valid. 142 # Verify that all key names are valid.
74 for key, val in self.iteritems(): 143 for key, val in self.iteritems():
75 if key not in VALID_ARCHIVE_KEYS: 144 if key not in VALID_ARCHIVE_KEYS:
76 raise Error('Archive "%s" has invalid attribute "%s"' % (host_os, key)) 145 raise Error('Archive "%s" has invalid attribute "%s"' % (host_os, key))
77 146
78 @property 147 @property
79 def url(self): 148 def url(self):
80 """Returns the URL of this archive""" 149 """Returns the URL of this archive"""
81 return self['url'] 150 return self['url']
82 151
152 @url.setter
153 def url(self, url):
154 """Set the URL of this archive"""
155 self['url'] = url
156
83 @property 157 @property
84 def size(self): 158 def size(self):
85 """Returns the size of this archive, in bytes""" 159 """Returns the size of this archive, in bytes"""
86 return self['size'] 160 return self['size']
87 161
88 @property 162 @property
89 def host_os(self): 163 def host_os(self):
90 """Returns the host OS of this archive""" 164 """Returns the host OS of this archive"""
91 return self['host_os'] 165 return self['host_os']
92 166
(...skipping 24 matching lines...) Expand all
117 either of the files or dicts sets are removed from the latter, meaning that 191 either of the files or dicts sets are removed from the latter, meaning that
118 symlinks or links which overlap file or directory entries take precedence. 192 symlinks or links which overlap file or directory entries take precedence.
119 193
120 Args: 194 Args:
121 bundle: The other bundle. Must be a dict. 195 bundle: The other bundle. Must be a dict.
122 Returns: 196 Returns:
123 A dict which is the result of merging the two Bundles. 197 A dict which is the result of merging the two Bundles.
124 """ 198 """
125 return Bundle(self.items() + bundle.items()) 199 return Bundle(self.items() + bundle.items())
126 200
201 def ToJSON(self):
202 """Convert this bundle to a JSON-formatted string."""
203 return DictToJSON(self)
204
205 def FromJSON(self, json_string):
206 """Parse and load bundle data from a JSON-formatted string."""
207 self.CopyFrom(json.loads(json_string))
208
127 def CopyFrom(self, dict): 209 def CopyFrom(self, dict):
128 """Update the content of the bundle by copying values from the given 210 """Update the content of the bundle by copying values from the given
129 dictionary. 211 dictionary.
130 212
131 Args: 213 Args:
132 dict: The dictionary whose values must be copied to the bundle.""" 214 dict: The dictionary whose values must be copied to the bundle."""
133 for key, value in dict.items(): 215 for key, value in dict.items():
134 if key == ARCHIVES_KEY: 216 if key == ARCHIVES_KEY:
135 archives = [] 217 archives = []
136 for a in value: 218 for a in value:
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 262
181 Args: 263 Args:
182 host_os_name: name of host os whose archive must be retrieved. 264 host_os_name: name of host os whose archive must be retrieved.
183 Return: 265 Return:
184 An Archive instance or None if it doesn't exist.""" 266 An Archive instance or None if it doesn't exist."""
185 for archive in self[ARCHIVES_KEY]: 267 for archive in self[ARCHIVES_KEY]:
186 if archive.host_os == host_os_name: 268 if archive.host_os == host_os_name:
187 return archive 269 return archive
188 return None 270 return None
189 271
272 def GetHostOSArchive(self):
273 """Retrieve the archive for the current host os."""
274 return self.GetArchive(GetHostOS())
275
190 def GetArchives(self): 276 def GetArchives(self):
191 """Returns all the archives in this bundle""" 277 """Returns all the archives in this bundle"""
192 return self[ARCHIVES_KEY] 278 return self[ARCHIVES_KEY]
193 279
194 @property 280 @property
195 def name(self): 281 def name(self):
196 """Returns the name of this bundle""" 282 """Returns the name of this bundle"""
197 return self[NAME_KEY] 283 return self[NAME_KEY]
198 284
199 @property 285 @property
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 new_bundle = Bundle(b[NAME_KEY]) 425 new_bundle = Bundle(b[NAME_KEY])
340 new_bundle.CopyFrom(b) 426 new_bundle.CopyFrom(b)
341 bundles.append(new_bundle) 427 bundles.append(new_bundle)
342 self._manifest_data[key] = bundles 428 self._manifest_data[key] = bundles
343 else: 429 else:
344 self._manifest_data[key] = value 430 self._manifest_data[key] = value
345 self.Validate() 431 self.Validate()
346 432
347 def GetManifestString(self): 433 def GetManifestString(self):
348 """Returns the current JSON manifest object, pretty-printed""" 434 """Returns the current JSON manifest object, pretty-printed"""
349 pretty_string = json.dumps(self._manifest_data, sort_keys=False, indent=2) 435 return DictToJSON(self._manifest_data)
350 # json.dumps sometimes returns trailing whitespace and does not put
351 # a newline at the end. This code fixes these problems.
352 pretty_lines = pretty_string.split('\n')
353 return '\n'.join([line.rstrip() for line in pretty_lines]) + '\n'
OLDNEW
« no previous file with comments | « native_client_sdk/src/build_tools/buildbot_common.py ('k') | native_client_sdk/src/build_tools/sdk_tools/sdk_update.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698