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

Side by Side Diff: native_client_sdk/src/build_tools/sdk_tools/sdk_update.py

Issue 8915012: Update NaCl SDK to push MouseLock fix. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 9 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 '''A simple tool to update the Native Client SDK to the latest version''' 6 '''A simple tool to update the Native Client SDK to the latest version'''
7 7
8 import cStringIO 8 import cStringIO
9 import cygtar
9 import errno 10 import errno
10 import exceptions 11 import exceptions
11 import hashlib 12 import hashlib
12 import json 13 import json
13 import optparse 14 import optparse
14 import os 15 import os
15 import shutil 16 import shutil
16 import subprocess 17 import subprocess
17 import sys 18 import sys
18 import tarfile
19 import tempfile 19 import tempfile
20 import time 20 import time
21 import urllib2 21 import urllib2
22 import urlparse 22 import urlparse
23 23
24 24
25 #------------------------------------------------------------------------------ 25 #------------------------------------------------------------------------------
26 # Constants 26 # Constants
27 27
28 # Bump the MINOR_REV every time you check this file in. 28 # Bump the MINOR_REV every time you check this file in.
29 MAJOR_REV = 1 29 MAJOR_REV = 2
30 MINOR_REV = 14 30 MINOR_REV = 16
31 31
32 GLOBAL_HELP = '''Usage: naclsdk [options] command [command_options] 32 GLOBAL_HELP = '''Usage: naclsdk [options] command [command_options]
33 33
34 naclsdk is a simple utility that updates the Native Client (NaCl) 34 naclsdk is a simple utility that updates the Native Client (NaCl)
35 Software Developer's Kit (SDK). Each component is kept as a 'bundle' that 35 Software Developer's Kit (SDK). Each component is kept as a 'bundle' that
36 this utility can download as as subdirectory into the SDK. 36 this utility can download as as subdirectory into the SDK.
37 37
38 Commands: 38 Commands:
39 help [command] - Get either general or command-specific help 39 help [command] - Get either general or command-specific help
40 list - Lists the available bundles 40 list - Lists the available bundles
41 update/install - Updates/installs bundles in the SDK 41 update/install - Updates/installs bundles in the SDK
42 42
43 Example Usage: 43 Example Usage:
44 naclsdk list 44 naclsdk list
45 naclsdk update --force pepper_17 45 naclsdk update --force pepper_17
46 naclsdk install recommended 46 naclsdk install recommended
47 naclsdk help update''' 47 naclsdk help update'''
48 48
49 MANIFEST_FILENAME='naclsdk_manifest.json' 49 MANIFEST_FILENAME='naclsdk_manifest2.json'
50 SDK_TOOLS='sdk_tools' # the name for this tools directory 50 SDK_TOOLS='sdk_tools' # the name for this tools directory
51 USER_DATA_DIR='sdk_cache' 51 USER_DATA_DIR='sdk_cache'
52 52
53 HTTP_CONTENT_LENGTH = 'Content-Length' # HTTP Header field for content length 53 HTTP_CONTENT_LENGTH = 'Content-Length' # HTTP Header field for content length
54 54
55 # The following SSL certificates are used to validate the SSL connection 55 # The following SSL certificates are used to validate the SSL connection
56 # to https://commondatastorage.googleapis.com 56 # to https://commondatastorage.googleapis.com
57 # TODO(mball): Validate at least one of these certificates. 57 # TODO(mball): Validate at least one of these certificates.
58 # http://stackoverflow.com/questions/1087227/validate-ssl-certificates-with-pyth on 58 # http://stackoverflow.com/questions/1087227/validate-ssl-certificates-with-pyth on
59 59
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 STABILITY_LITERALS = [ 132 STABILITY_LITERALS = [
133 'obsolete', 'post_stable', 'stable', 'beta', 'dev', 'canary'] 133 'obsolete', 'post_stable', 'stable', 'beta', 'dev', 'canary']
134 # Valid values for the archive.host_os field 134 # Valid values for the archive.host_os field
135 HOST_OS_LITERALS = frozenset(['mac', 'win', 'linux', 'all']) 135 HOST_OS_LITERALS = frozenset(['mac', 'win', 'linux', 'all'])
136 # Valid values for bundle-recommended field. 136 # Valid values for bundle-recommended field.
137 YES_NO_LITERALS = ['yes', 'no'] 137 YES_NO_LITERALS = ['yes', 'no']
138 # Valid keys for various sdk objects, used for validation. 138 # Valid keys for various sdk objects, used for validation.
139 VALID_ARCHIVE_KEYS = frozenset(['host_os', 'size', 'checksum', 'url']) 139 VALID_ARCHIVE_KEYS = frozenset(['host_os', 'size', 'checksum', 'url'])
140 VALID_BUNDLES_KEYS = frozenset([ 140 VALID_BUNDLES_KEYS = frozenset([
141 ARCHIVES_KEY, NAME_KEY, VERSION_KEY, REVISION_KEY, 141 ARCHIVES_KEY, NAME_KEY, VERSION_KEY, REVISION_KEY,
142 'description', 'desc_url', 'stability', 'recommended', 142 'description', 'desc_url', 'stability', 'recommended', 'repath',
143 ]) 143 ])
144 VALID_MANIFEST_KEYS = frozenset(['manifest_version', BUNDLES_KEY]) 144 VALID_MANIFEST_KEYS = frozenset(['manifest_version', BUNDLES_KEY])
145 145
146 146
147 #------------------------------------------------------------------------------ 147 #------------------------------------------------------------------------------
148 # General Utilities 148 # General Utilities
149 149
150 150
151 _debug_mode = False 151 _debug_mode = False
152 _quiet_mode = False 152 _quiet_mode = False
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 RemoveDir(outdir) 216 RemoveDir(outdir)
217 217
218 if os.path.splitext(installer)[1] == '.exe': 218 if os.path.splitext(installer)[1] == '.exe':
219 # If the installer has extension 'exe', assume it's a Windows NSIS-style 219 # If the installer has extension 'exe', assume it's a Windows NSIS-style
220 # installer that handles silent (/S) and relocated (/D) installs. 220 # installer that handles silent (/S) and relocated (/D) installs.
221 command = [installer, '/S', '/D=%s' % outdir] 221 command = [installer, '/S', '/D=%s' % outdir]
222 subprocess.check_call(command) 222 subprocess.check_call(command)
223 else: 223 else:
224 os.mkdir(outdir) 224 os.mkdir(outdir)
225 tar_file = None 225 tar_file = None
226 curpath = os.getcwd()
226 try: 227 try:
227 tar_file = tarfile.open(installer) 228 tar_file = cygtar.CygTar(installer, 'r', verbose=True)
228 tar_file.extractall(path=outdir) 229 if outdir: os.chdir(outdir)
230 tar_file.Extract()
229 finally: 231 finally:
230 if tar_file: 232 if tar_file:
231 tar_file.close() 233 tar_file.Close()
234 os.chdir(curpath)
232 235
233 236
234 def RemoveDir(outdir): 237 def RemoveDir(outdir):
235 '''Removes the given directory 238 '''Removes the given directory
236 239
237 On Unix systems, this just runs shutil.rmtree, but on Windows, this doesn't 240 On Unix systems, this just runs shutil.rmtree, but on Windows, this doesn't
238 work when the directory contains junctions (as does our SDK installer). 241 work when the directory contains junctions (as does our SDK installer).
239 Therefore, on Windows, it runs rmdir /S /Q as a shell command. This always 242 Therefore, on Windows, it runs rmdir /S /Q as a shell command. This always
240 does the right thing on Windows. If the directory already didn't exist, 243 does the right thing on Windows. If the directory already didn't exist,
241 RemoveDir will return successfully without taking any action. 244 RemoveDir will return successfully without taking any action.
242 245
243 Args: 246 Args:
244 outdir: The directory to delete 247 outdir: The directory to delete
245 248
246 Raises: 249 Raises:
247 CalledProcessError - if the delete operation fails on Windows 250 CalledProcessError - if the delete operation fails on Windows
248 OSError - if the delete operation fails on Linux 251 OSError - if the delete operation fails on Linux
249 ''' 252 '''
250 253
251 DebugPrint('Removing %s' % outdir) 254 DebugPrint('Removing %s' % outdir)
252 try: 255 try:
253 if sys.platform == 'win32': 256 shutil.rmtree(outdir)
254 subprocess.check_call(['rmdir /S /Q', outdir], shell=True)
255 else:
256 shutil.rmtree(outdir)
257 except: 257 except:
258 # If the directory is gone anyway, we probably failed because it was
259 # already gone. Treat that as success.
260 if not os.path.exists(outdir): 258 if not os.path.exists(outdir):
261 return 259 return
262 # Otherwise, re-raise. 260 # On Windows this could be an issue with junctions, so try again with rmdir
263 raise 261 if sys.platform == 'win32':
262 subprocess.check_call(['rmdir', '/S', '/Q', outdir], shell=True)
264 263
265 264
266 def RenameDir(srcdir, destdir): 265 def RenameDir(srcdir, destdir):
267 '''Renames srcdir to destdir. Removes destdir before doing the 266 '''Renames srcdir to destdir. Removes destdir before doing the
268 rename if it already exists.''' 267 rename if it already exists.'''
269 268
270 max_tries = 100 269 max_tries = 5
271
272 for num_tries in xrange(max_tries): 270 for num_tries in xrange(max_tries):
273 try: 271 try:
274 RemoveDir(destdir) 272 RemoveDir(destdir)
275 os.rename(srcdir, destdir) 273 os.rename(srcdir, destdir)
276 return 274 return
277 except OSError as err: 275 except OSError as err:
278 if err.errno != errno.EACCES: 276 if err.errno != errno.EACCES:
279 raise err 277 raise err
280 # If we are here, we didn't exit due to raised exception, so we are 278 # If we are here, we didn't exit due to raised exception, so we are
281 # handling a Windows flaky access error. Sleep one second and try 279 # handling a Windows flaky access error. Sleep one second and try
282 # again. 280 # again.
283 time.sleep(1) 281 time.sleep(num_tries + 1)
284 # end of while loop -- could not RenameDir 282 # end of while loop -- could not RenameDir
285 raise Error('Could not RenameDir %s => %s after %d tries.\n' % 283 raise Error('Could not RenameDir %s => %s after %d tries.\n' %
286 'Please check that no shells or applications ' 284 'Please check that no shells or applications '
287 'are accessing files in %s.' 285 'are accessing files in %s.'
288 % (srcdir, destdir, num_tries, destdir)) 286 % (srcdir, destdir, num_tries, destdir))
289 287
290 288
291 def ShowProgress(progress): 289 def ShowProgress(progress):
292 ''' A download-progress function used by class Archive. 290 ''' A download-progress function used by class Archive.
293 (See DownloadAndComputeHash).''' 291 (See DownloadAndComputeHash).'''
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 605
608 606
609 class SDKManifest(object): 607 class SDKManifest(object):
610 '''This class contains utilities for manipulation an SDK manifest string 608 '''This class contains utilities for manipulation an SDK manifest string
611 609
612 For ease of unit-testing, this class should not contain any file I/O. 610 For ease of unit-testing, this class should not contain any file I/O.
613 ''' 611 '''
614 612
615 def __init__(self): 613 def __init__(self):
616 '''Create a new SDKManifest object with default contents''' 614 '''Create a new SDKManifest object with default contents'''
617 self.MANIFEST_VERSION = 1 615 self.MANIFEST_VERSION = MAJOR_REV
618 self._manifest_data = { 616 self._manifest_data = {
619 "manifest_version": self.MANIFEST_VERSION, 617 "manifest_version": self.MANIFEST_VERSION,
620 "bundles": [], 618 "bundles": [],
621 } 619 }
622 620
623 def _ValidateManifest(self): 621 def _ValidateManifest(self):
624 '''Validate the Manifest file and raises an exception for problems''' 622 '''Validate the Manifest file and raises an exception for problems'''
625 # Validate the manifest top level 623 # Validate the manifest top level
626 if self._manifest_data["manifest_version"] > self.MANIFEST_VERSION: 624 if self._manifest_data["manifest_version"] > self.MANIFEST_VERSION:
627 raise Error("Manifest version too high: %s" % 625 raise Error("Manifest version too high: %s" %
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 if sha1 != archive['checksum']['sha1']: 912 if sha1 != archive['checksum']['sha1']:
915 raise Error("SHA1 checksum mismatch on '%s'. Expected %s but got %s" % 913 raise Error("SHA1 checksum mismatch on '%s'. Expected %s but got %s" %
916 (bundle_name, archive['checksum']['sha1'], sha1)) 914 (bundle_name, archive['checksum']['sha1'], sha1))
917 if size != archive['size']: 915 if size != archive['size']:
918 raise Error("Size mismatch on Archive. Expected %s but got %s bytes" % 916 raise Error("Size mismatch on Archive. Expected %s but got %s bytes" %
919 (archive['size'], size)) 917 (archive['size'], size))
920 InfoPrint('Updating bundle %s to version %s, revision %s' % ( 918 InfoPrint('Updating bundle %s to version %s, revision %s' % (
921 (bundle_name, bundle[VERSION_KEY], bundle[REVISION_KEY]))) 919 (bundle_name, bundle[VERSION_KEY], bundle[REVISION_KEY])))
922 ExtractInstaller(dest_filename, bundle_update_path) 920 ExtractInstaller(dest_filename, bundle_update_path)
923 if bundle_name != SDK_TOOLS: 921 if bundle_name != SDK_TOOLS:
924 RenameDir(bundle_update_path, bundle_path) 922 repath = bundle.get('repath', None)
923 if repath:
924 bundle_move_path = os.path.join(bundle_update_path, repath)
925 else:
926 bundle_move_path = bundle_update_path
927 RenameDir(bundle_move_path, bundle_path)
928 if os.path.exists(bundle_update_path):
929 RemoveDir(bundle_update_path)
925 os.remove(dest_filename) 930 os.remove(dest_filename)
926 local_manifest.MergeBundle(bundle) 931 local_manifest.MergeBundle(bundle)
927 local_manifest.WriteFile() 932 local_manifest.WriteFile()
928 # Test revision numbers, update the bundle accordingly. 933 # Test revision numbers, update the bundle accordingly.
929 # TODO(dspringer): The local file should be refreshed from disk each 934 # TODO(dspringer): The local file should be refreshed from disk each
930 # iteration thought this loop so that multiple sdk_updates can run at the 935 # iteration thought this loop so that multiple sdk_updates can run at the
931 # same time. 936 # same time.
932 if local_manifest.BundleNeedsUpdate(bundle): 937 if local_manifest.BundleNeedsUpdate(bundle):
933 if (not update_options.force and os.path.exists(bundle_path) and 938 if (not update_options.force and os.path.exists(bundle_path) and
934 bundle_name != SDK_TOOLS): 939 bundle_name != SDK_TOOLS):
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1049 1054
1050 return 0 # Success 1055 return 0 # Success
1051 1056
1052 1057
1053 if __name__ == '__main__': 1058 if __name__ == '__main__':
1054 try: 1059 try:
1055 sys.exit(main(sys.argv[1:])) 1060 sys.exit(main(sys.argv[1:]))
1056 except Error as error: 1061 except Error as error:
1057 print "Error: %s" % error 1062 print "Error: %s" % error
1058 sys.exit(1) 1063 sys.exit(1)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698