Home | History | Annotate | Download | only in sdk_tools
      1 #!/usr/bin/env python
      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
      4 # found in the LICENSE file.
      5 
      6 """Shim script for the SDK updater, to allow automatic updating.
      7 
      8 The purpose of this script is to be a shim which automatically updates
      9 sdk_tools (the bundle containing the updater scripts) whenever this script is
     10 run.
     11 
     12 When the sdk_tools bundle has been updated to the most recent version, this
     13 script forwards its arguments to sdk_updater_main.py.
     14 """
     15 
     16 import os
     17 import subprocess
     18 from sdk_update_common import RenameDir, RemoveDir, Error
     19 import sys
     20 import tempfile
     21 
     22 
     23 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
     24 SDK_UPDATE_MAIN = os.path.join(SCRIPT_DIR, 'sdk_update_main.py')
     25 SDK_ROOT_DIR = os.path.dirname(SCRIPT_DIR)
     26 NACLSDK_SHELL_SCRIPT = os.path.join(SDK_ROOT_DIR, 'naclsdk')
     27 if sys.platform.startswith('win'):
     28   NACLSDK_SHELL_SCRIPT += '.bat'
     29 SDK_TOOLS_DIR = os.path.join(SDK_ROOT_DIR, 'sdk_tools')
     30 SDK_TOOLS_UPDATE_DIR = os.path.join(SDK_ROOT_DIR, 'sdk_tools_update')
     31 
     32 
     33 def MakeSdkUpdateMainCmd(args):
     34   """Returns a list of command line arguments to run sdk_update_main.
     35 
     36   Args:
     37     args: A list of arguments to pass to sdk_update_main.py
     38   Returns:
     39     A new list that can be passed to subprocess.call, subprocess.Popen, etc.
     40   """
     41   return [sys.executable, SDK_UPDATE_MAIN] + args
     42 
     43 
     44 def UpdateSDKTools(args):
     45   """Run sdk_update_main to update sdk_tools bundle. Return True if it is
     46   updated.
     47 
     48   Args:
     49     args: The arguments to pass to sdk_update_main.py. We need to keep this to
     50         ensure sdk_update_main is called correctly; some parameters specify
     51         URLS or directories to use.
     52   Returns:
     53     True if the sdk_tools bundle was updated.
     54   """
     55   cmd = MakeSdkUpdateMainCmd(args + ['--update-sdk-tools'])
     56   process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
     57   stdout, _ = process.communicate()
     58   if process.returncode == 0:
     59     return stdout.find('Updating bundle sdk_tools to version') != -1
     60   else:
     61     # Updating sdk_tools could fail for any number of reasons. Regardless, it
     62     # should be safe to try to run the user's command.
     63     return False
     64 
     65 
     66 def RenameSdkToolsDirectory():
     67   """Rename sdk_tools_update to sdk_tools."""
     68   # If there is no update directory, bail.
     69   if not os.path.isdir(SDK_TOOLS_UPDATE_DIR):
     70     return False
     71 
     72   try:
     73     tempdir = tempfile.mkdtemp()
     74     temp_sdktools = os.path.join(tempdir, 'sdk_tools')
     75     try:
     76       RenameDir(SDK_TOOLS_DIR, temp_sdktools)
     77     except Error:
     78       # The user is probably on Windows, and the directory is locked.
     79       sys.stderr.write('Cannot rename directory "%s". Make sure no programs are'
     80           ' viewing or accessing this directory and try again.\n' % (
     81           SDK_TOOLS_DIR,))
     82       sys.exit(1)
     83 
     84     try:
     85       RenameDir(SDK_TOOLS_UPDATE_DIR, SDK_TOOLS_DIR)
     86     except Error:
     87       # Failed for some reason, move the old dir back.
     88       try:
     89         RenameDir(temp_sdktools, SDK_TOOLS_DIR)
     90       except Error:
     91         # Not much to do here. sdk_tools won't exist, but sdk_tools_update
     92         # should. Hopefully running the batch script again will move
     93         # sdk_tools_update -> sdk_tools and it will work this time...
     94         sys.stderr.write('Unable to restore directory "%s" while auto-updating.'
     95             'Make sure no programs are viewing or accessing this directory and'
     96             'try again.\n' % (SDK_TOOLS_DIR,))
     97         sys.exit(1)
     98   finally:
     99     RemoveDir(tempdir)
    100 
    101   return True
    102 
    103 
    104 def CheckRuntimeRequirements():
    105   if sys.platform.startswith('linux'):
    106     if not os.path.exists('/lib/ld-linux.so.2'):
    107       sys.stderr.write("""32-bit runtime environment was not found on this
    108 system.  Specifically the 32-bit dynamic loader which is needed by the NaCl
    109 compilers was not found ('/lib/ld-linux.so.2').  On modern debian/ubuntu
    110 systems this is included in the 'libc6:i386' package.\n""")
    111       sys.exit(1)
    112 
    113 
    114 def main():
    115   args = sys.argv[1:]
    116   CheckRuntimeRequirements()
    117   if UpdateSDKTools(args) and RenameSdkToolsDirectory():
    118     # Call the shell script, just in case this script was updated in the next
    119     # version of sdk_tools
    120     return subprocess.call([NACLSDK_SHELL_SCRIPT] + args)
    121   else:
    122     return subprocess.call(MakeSdkUpdateMainCmd(args))
    123 
    124 
    125 if __name__ == '__main__':
    126   try:
    127     sys.exit(main())
    128   except KeyboardInterrupt:
    129     sys.exit(1)
    130